diff --git a/.github/install_examples.sh b/.github/install_examples.sh index d5ad1b55..557428b1 100755 --- a/.github/install_examples.sh +++ b/.github/install_examples.sh @@ -31,6 +31,7 @@ mvn clean test -DskipTests -Dmaven.compiler.source=$SRC_VERSION -Dmaven.compiler # Compile real projects if [ $JAVA_MAJOR_VERSION -eq "8" ]; then mvn clean test -DskipTests -Dmaven.compiler.source=1.8 -Dmaven.compiler.target=1.8 -B -f examples/math_70/ + mvn clean test -DskipTests -Dmaven.compiler.source=1.5 -Dmaven.compiler.target=1.5 -B -f examples/cl2/ fi # Copy compiled classes to non-maven mirror projects diff --git a/examples/cl2/DEVELOPERS-GUIDE.html b/examples/cl2/DEVELOPERS-GUIDE.html new file mode 100644 index 00000000..8ebee093 --- /dev/null +++ b/examples/cl2/DEVELOPERS-GUIDE.html @@ -0,0 +1,105 @@ + +
+The Lang package contains a set of Java classes that extend +the basic JDK classes. This developers guide seeks to set +out rules for the naming of classes and methods within the package. The purpose +of this, as with all naming standards, is to improve the coherency and +consistency of the whole API.
+ +The philosophy of the naming standards is to follow those of the JDK +if possible.
+ + + + +The main package for Lang is org.apache.commons.lang
. Subpackages should
+be created for each group of related items.
Each package should have a package.html
file for javadoc. This should
+describe the use of the package and its scope.
Utility classes provide additional functionality around a class or interface. +Examples include StringUtils and SerializationUtils.
+ +Each class shall follow the naming pattern XxxUtils where Xxx relates to the
+class or interface that the utility services. Variations on a theme (Integer
+as opposed to Number
) should be dealt with in one Utils class where possible.
+Each Utils class shall:
A utility class can act as a factory for specific implementations of a class or +interface. In such cases the implementations should be non-public, static, inner classes +of the utility class. However, if warranted due to maintenance or other reasons, these +decorator classes may be moved to top-level classes in a subpackage. The +naming of such a subpackage should be discussed and agreed upon on the +developers mailing list.
+ + + + +The Sun javadoc guidelines are the starting point for Lang. These points are +an extension to make it easier for users reading the generated +docs and developers with javadoc-popup capabilities from within their IDE.
+ +References to other objects, interfaces or methods use the @link-tag the +first time it is referenced in a class or interface. On the following +references always enclose it inside <code></code>.
+ +References to null
, this
, long
,
+int
, short
, char
, byte
,
+double
, float
and boolean
should be enclosed
+in <code></code>.
Use a short description of what the class/interface/method is used for, +enclose with <p></p>.
+ +A longer description about what the class/interface/method is used for +and if it is needed how it is done. If it is nessesary include +description of the parameters, what they are used for and how. Enclose +with <p></p> where it is needed, try to divide into smaller parts (not +to small!) to enhance readability of the generated Javadoc.
+ +If an example is needed enclose it with <pre></pre>. +It should be supported with an explanation within a normal paragraph.
+ + + + + diff --git a/examples/cl2/LICENSE.txt b/examples/cl2/LICENSE.txt new file mode 100644 index 00000000..cee19439 --- /dev/null +++ b/examples/cl2/LICENSE.txt @@ -0,0 +1,53 @@ +/* ==================================================================== + * 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 acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements 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 + *The standard Java libraries fail to provide enough methods for +manipulation of its main components. The Lang Package provides +these extra methods. There are other classes which might justifiably +be included in java.lang someday, this package also provides for them.
+ + +This proposal is to create a package of Java utility classes for the +classes that are in java.lang's hierarchy, or are considered to be so +standard as to justify existence in java.lang. The Lang Package +also applies to primitives and arrays.
+ + +Lang relies only on standard JDK 1.2 (or later) APIs for +production deployment. It utilizes the JUnit unit testing framework for +developing and executing unit tests, but this is of interest only to +developers of the component. Lang will be a dependency for +several existing components in the open source world.
+ +No external configuration files are utilized.
+ + +The initial classes came from the Commons.Util subproject.
+ +The proposed package name for the new component is
+org.apache.commons.lang
.
lang
in the
+ jakarta-commons
CVS repository.The initial committers on the Lang component shall be as follows: +
The Lang Component contains a set of Java classes that provide +a basic set of common utility code on top of the standard Java classes. +The following principal classes are included:
+The Lang component is dependent upon the following external +components for development and use:
+Current Release: +Version 1.0 +
+ +Planned Next Release: +A 2.0 will be released after a undefined period of development. +
+ + + ++
Want to help? Here's some "to do" items the team has identified as possibly being in scope for Lang. Note that all are still under discussion, so please mail the list before actioning.
+The following individuals are the primary developers and maintainers of this +component. Developers who plan to use Lang in their own +projects are encouraged to collaborate on the future development of this +component to ensure that it continues to meet a variety of needs.
+ArrayUtils
contains utility methods for working with
+ * arrays.
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() { + } + + // Basic methods handling multi-dimensional arrays + //----------------------------------------------------------------------- + + /** + *Outputs an array as a String, treating null
as an empty array.
Multi-dimensional arrays are handled correctly, including + * multi-dimensional primitive arrays.
+ * + *The format is that of Java source code, for example {a,b}.
+ * + * @param array the array to get a toString for, may benull
+ * @return a String representation of the array, '{}' if null
passed in
+ */
+ public static String toString(Object array) {
+ return toString(array, "{}");
+ }
+
+ /**
+ * Outputs an array as a String handling null
s.
Multi-dimensional arrays are handled correctly, including + * multi-dimensional primitive arrays.
+ * + *The format is that of Java source code, for example {a,b}.
+ * + * @param array the array to get a toString for, may benull
+ * @param stringIfNull the String to return if the array is null
+ * @return a String representation of the array
+ */
+ public static String toString(Object array, String stringIfNull) {
+ if (array == null) {
+ return stringIfNull;
+ }
+ return new ToStringBuilder(array, ToStringStyle.SIMPLE_STYLE).append(array).toString();
+ }
+
+ /**
+ * 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
+ */
+ 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
+ * @return true
if the arrays are equal
+ */
+ public static boolean isEquals(Object array1, Object array2) {
+ return new EqualsBuilder().append(array1, array2).isEquals();
+ }
+
+ //-----------------------------------------------------------------------
+
+ /**
+ * Converts the given array into a {@link java.util.Map}. Each element of the array + * must be either a {@link java.util.Map.Entry} or an Array, containing at least two + * elements, where the first element is used as key and the second as + * value.
+ * + *This method can be used to initialize:
+ *+ * // Create a Map mapping colors. + * Map colorMap = MapUtils.toMap(new String[][] {{ + * {"RED", "#FF0000"}, + * {"GREEN", "#00FF00"}, + * {"BLUE", "#0000FF"}}); + *+ * + * @param array an array whose elements are either a {@link java.util.Map.Entry} or + * an Array containing at least two elements + * @return a
Map
that was created from the array
+ * @throws IllegalArgumentException if the array is null
+ * @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(Object[] array) {
+ if (array == null) {
+ throw new IllegalArgumentException("The array must not be null");
+ }
+ Map map = new HashMap((int) (array.length * 1.5));
+ for (int i = 0; i < array.length; i++) {
+ Object object = array[i];
+ if (object instanceof Map.Entry) {
+ Map.Entry entry = (Map.Entry) object;
+ map.put(entry.getKey(), entry.getValue());
+ } else if (object instanceof Object[]) {
+ Object[] entry = (Object[]) object;
+ if (entry.length < 2) {
+ 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 + ", '"
+ + object
+ + "', is neither of type Map.Entry nor an Array");
+ }
+ }
+ return map;
+ }
+
+ //-----------------------------------------------------------------------
+
+ /**
+ * Shallow clones an array returning a typecast result and handling
+ * null
.
The objecs in the array are not cloned, thus there is no special + * handling for multi-dimensional arrays.
+ * + * @param array the array to shallow clone, may benull
+ * @return the cloned array, or null
if null
+ * passed in
+ */
+ public static Object[] clone(Object[] array) {
+ if (array == null) {
+ return null;
+ }
+ return (Object[]) array.clone();
+ }
+
+ /**
+ * Clones an array returning a typecast result and handling
+ * null
.
Any multi-dimensional aspects of the arrays are ignored.
+ * + * @param array the array to clone, may benull
+ * @return the cloned array, or null
if null
+ * passed in
+ */
+ public static long[] clone(long[] array) {
+ if (array == null) {
+ return null;
+ }
+ return (long[]) array.clone();
+ }
+
+ /**
+ * Clones an array returning a typecast result and handling
+ * null
.
Any multi-dimensional aspects of the arrays are ignored.
+ * + * @param array the array to clone, may benull
+ * @return the cloned array, or null
if null
+ * passed in
+ */
+ public static int[] clone(int[] array) {
+ if (array == null) {
+ return null;
+ }
+ return (int[]) array.clone();
+ }
+
+ /**
+ * Clones an array returning a typecast result and handling
+ * null
.
Any multi-dimensional aspects of the arrays are ignored.
+ * + * @param array the array to clone, may benull
+ * @return the cloned array, or null
if null
+ * passed in
+ */
+ public static short[] clone(short[] array) {
+ if (array == null) {
+ return null;
+ }
+ return (short[]) array.clone();
+ }
+
+ /**
+ * Clones an array returning a typecast result and handling
+ * null
.
Any multi-dimensional aspects of the arrays are ignored.
+ * + * @param array the array to clone, may benull
+ * @return the cloned array, or null
if null
+ * passed in
+ */
+ public static char[] clone(char[] array) {
+ if (array == null) {
+ return null;
+ }
+ return (char[]) array.clone();
+ }
+
+ /**
+ * Clones an array returning a typecast result and handling
+ * null
.
Any multi-dimensional aspects of the arrays are ignored.
+ * + * @param array the array to clone, may benull
+ * @return the cloned array, or null
if null
+ * passed in
+ */
+ public static byte[] clone(byte[] array) {
+ if (array == null) {
+ return null;
+ }
+ return (byte[]) array.clone();
+ }
+
+ /**
+ * Clones an array returning a typecast result and handling
+ * null
.
Any multi-dimensional aspects of the arrays are ignored.
+ * + * @param array the array to clone, may benull
+ * @return the cloned array, or null
if null
+ * passed in
+ */
+ public static double[] clone(double[] array) {
+ if (array == null) {
+ return null;
+ }
+ return (double[]) array.clone();
+ }
+
+ /**
+ * Clones an array returning a typecast result and handling
+ * null
.
Any multi-dimensional aspects of the arrays are ignored.
+ * + * @param array the array to clone, may benull
+ * @return the cloned array, or null
if null
+ * passed in
+ */
+ public static float[] clone(float[] array) {
+ if (array == null) {
+ return null;
+ }
+ return (float[]) array.clone();
+ }
+
+ /**
+ * Clones an array returning a typecast result and handling
+ * null
.
Any multi-dimensional aspects of the arrays are ignored.
+ * + * @param array the array to clone, may benull
+ * @return the cloned array, or null
if null
+ * passed in
+ */
+ public static boolean[] clone(boolean[] array) {
+ if (array == null) {
+ return null;
+ }
+ return (boolean[]) array.clone();
+ }
+
+ //-----------------------------------------------------------------------
+
+ /**
+ * 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(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)) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * 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(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)) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * 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(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)) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * 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(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)) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * 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(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)) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * 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(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)) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * 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(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)) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * 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(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)) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * 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(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)) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Checks whether two arrays are the same type taking into account + * multi-dimensional arrays.
+ * + *Primitive arrays may be compared using this method too.
+ * + * @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(Object array1, Object array2) {
+ if (array1 == null || array2 == null) {
+ throw new IllegalArgumentException("The array must not be null");
+ }
+ return array1.getClass().getName().equals(array2.getClass().getName());
+ }
+
+ //-----------------------------------------------------------------------
+
+ /**
+ * Reverses the order of the given array.
+ * + * There is no special handling for multi-dimensional arrays. + *
+ * The method does nothing if null
is passed in.
+ *
+ * @param array the array to reverse, may be null
+ */
+ public static void reverse(Object[] array) {
+ if (array == null) {
+ return;
+ }
+ int i = 0;
+ int j = array.length - 1;
+ Object tmp;
+ while (j > i) {
+ tmp = array[j];
+ array[j] = array[i];
+ array[i] = tmp;
+ j--;
+ i++;
+ }
+ }
+
+ /**
+ * Reverses the order of the given array.
+ *
+ * The method does nothing if null
is passed in.
+ *
+ * @param array the array to reverse, may be null
+ */
+ public static void reverse(long[] array) {
+ if (array == null) {
+ return;
+ }
+ int i = 0;
+ int j = array.length - 1;
+ long tmp;
+ while (j > i) {
+ tmp = array[j];
+ array[j] = array[i];
+ array[i] = tmp;
+ j--;
+ i++;
+ }
+ }
+
+ /**
+ * Reverses the order of the given array.
+ *
+ * The method does nothing if null
is passed in.
+ *
+ * @param array the array to reverse, may be null
+ */
+ public static void reverse(int[] array) {
+ if (array == null) {
+ return;
+ }
+ int i = 0;
+ int j = array.length - 1;
+ int tmp;
+ while (j > i) {
+ tmp = array[j];
+ array[j] = array[i];
+ array[i] = tmp;
+ j--;
+ i++;
+ }
+ }
+
+ /**
+ * Reverses the order of the given array.
+ *
+ * There is no special handling for multi-dimensional arrays.
+ *
+ * @param array the array to reverse, may be null
+ */
+ public static void reverse(short[] array) {
+ if (array == null) {
+ return;
+ }
+ int i = 0;
+ int j = array.length - 1;
+ short tmp;
+ while (j > i) {
+ tmp = array[j];
+ array[j] = array[i];
+ array[i] = tmp;
+ j--;
+ i++;
+ }
+ }
+
+ /**
+ * Reverses the order of the given array.
+ *
+ * The method does nothing if null
is passed in.
+ *
+ * @param array the array to reverse, may be null
+ */
+ public static void reverse(char[] array) {
+ if (array == null) {
+ return;
+ }
+ int i = 0;
+ int j = array.length - 1;
+ char tmp;
+ while (j > i) {
+ tmp = array[j];
+ array[j] = array[i];
+ array[i] = tmp;
+ j--;
+ i++;
+ }
+ }
+
+ /**
+ * Reverses the order of the given array.
+ *
+ * The method does nothing if null
is passed in.
+ *
+ * @param array the array to reverse, may be null
+ */
+ public static void reverse(byte[] array) {
+ if (array == null) {
+ return;
+ }
+ int i = 0;
+ int j = array.length - 1;
+ byte tmp;
+ while (j > i) {
+ tmp = array[j];
+ array[j] = array[i];
+ array[i] = tmp;
+ j--;
+ i++;
+ }
+ }
+
+ /**
+ * Reverses the order of the given array.
+ *
+ * The method does nothing if null
is passed in.
+ *
+ * @param array the array to reverse, may be null
+ */
+ public static void reverse(double[] array) {
+ if (array == null) {
+ return;
+ }
+ int i = 0;
+ int j = array.length - 1;
+ double tmp;
+ while (j > i) {
+ tmp = array[j];
+ array[j] = array[i];
+ array[i] = tmp;
+ j--;
+ i++;
+ }
+ }
+
+ /**
+ * Reverses the order of the given array.
+ *
+ * The method does nothing if null
is passed in.
+ *
+ * @param array the array to reverse, may be null
+ */
+ public static void reverse(float[] array) {
+ if (array == null) {
+ return;
+ }
+ int i = 0;
+ int j = array.length - 1;
+ float tmp;
+ while (j > i) {
+ tmp = array[j];
+ array[j] = array[i];
+ array[i] = tmp;
+ j--;
+ i++;
+ }
+ }
+
+ /**
+ * Reverses the order of the given array.
+ *
+ * The method does nothing if null
is passed in.
+ *
+ * @param array the array to reverse, may be null
+ */
+ public static void reverse(boolean[] array) {
+ if (array == null) {
+ return;
+ }
+ int i = 0;
+ int j = array.length - 1;
+ boolean tmp;
+ while (j > i) {
+ tmp = array[j];
+ array[j] = array[i];
+ array[i] = tmp;
+ j--;
+ i++;
+ }
+ }
+
+ //-----------------------------------------------------------------------
+
+ /**
+ * Find the index of the given object in the array.
+ *
+ * The method returns -1 if a null
array is passed in.
+ *
+ * @param array the array to search through for the object, may be null
+ * @param objectToFind the object to find, may be null
+ * @return the index of the object within the array, or -1 if not found
+ */
+ 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.
+ *
+ * The method returns -1 if a null
array is passed in.
+ *
+ * A negative startIndex is treated as zero. A startIndex larger than the array
+ * length will return -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
+ * given index, or -1 if not found
+ */
+ public static int indexOf(Object[] array, Object objectToFind, int startIndex) {
+ if (array == null) {
+ return -1;
+ }
+ if (startIndex < 0) {
+ startIndex = 0;
+ }
+ if (objectToFind == null) {
+ for (int i = startIndex; i < array.length; i++) {
+ if (array[i] == null) {
+ return i;
+ }
+ }
+ } else {
+ for (int i = startIndex; i < array.length; i++) {
+ if (objectToFind.equals(array[i])) {
+ return i;
+ }
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * Find the last index of the given object within the array.
+ *
+ * The method returns -1 if a null
array is passed in.
+ *
+ * @param array the array to travers backwords looking for the object, may be null
+ * @param objectToFind the object to find, may be null
+ * @return the last index of the object to find, or -1 if not found
+ */
+ public static int lastIndexOf(Object[] array, Object objectToFind) {
+ if (array == null) {
+ return -1;
+ }
+ return lastIndexOf(array, objectToFind, array.length - 1);
+ }
+
+ /**
+ * Find the last index of the given object in the array starting at the given index.
+ *
+ * The method returns -1 if a null
array is passed in.
+ *
+ * A negative startIndex will return -1. A startIndex larger than the array
+ * length will search from the end of the array.
+ *
+ * @param array the array to traverse for looking for the object, may be 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 starting at the given index,
+ * or -1 if not found
+ */
+ public static int lastIndexOf(Object[] array, Object objectToFind, int startIndex) {
+ if (array == null) {
+ return -1;
+ }
+ if (startIndex < 0) {
+ return -1;
+ } else if (startIndex >= array.length) {
+ startIndex = array.length - 1;
+ }
+ if (objectToFind == null) {
+ for (int i = startIndex; i >= 0; i--) {
+ if (array[i] == null) {
+ return i;
+ }
+ }
+ } else {
+ for (int i = startIndex; i >= 0; i--) {
+ if (objectToFind.equals(array[i])) {
+ return i;
+ }
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * Checks if the object is in the given array.
+ *
+ * The method returns false
if a null
array is passed in.
+ *
+ * @param array the array to search through
+ * @param objectToFind the object to find
+ * @return true
if the array contains the object
+ */
+ public static boolean contains(Object[] array, Object objectToFind) {
+ return (indexOf(array, objectToFind) != -1);
+ }
+
+}
diff --git a/examples/cl2/src/java/org/apache/commons/lang/BooleanUtils.java b/examples/cl2/src/java/org/apache/commons/lang/BooleanUtils.java
new file mode 100644
index 00000000..a8073693
--- /dev/null
+++ b/examples/cl2/src/java/org/apache/commons/lang/BooleanUtils.java
@@ -0,0 +1,569 @@
+/* ====================================================================
+ * 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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
+ *
BooleanUtils
contains utility methods for working for
+ * boolean and Boolean objects.
BooleanUtils
instances should NOT be constructed in standard programming.
+ * Instead, the class should be used as BooleanUtils.toBooleanObject(true);
.
This constructor is public to permit tools that require a JavaBean instance + * to operate.
+ */ + public BooleanUtils() { + } + + // Boolean utilities + //-------------------------------------------------------------------------- + + /** + *Negates the specified boolean.
+ * + *If null
is passed in, null
will be returned.
null
if null
passed in
+ */
+ public static Boolean negate(Boolean bool) {
+ if (bool == null) {
+ return null;
+ }
+ return (bool.booleanValue() ? Boolean.FALSE : Boolean.TRUE);
+ }
+
+ // boolean Boolean methods
+ //--------------------------------------------------------------------------
+
+ /**
+ * 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.
+ * + * @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); + } + + /** + *Converts a Boolean to a boolean handling null by returning false.
+ * + * @param bool the boolean to convert + * @return true or false + */ + public static boolean toBoolean(Boolean bool) { + if (bool == null) { + return false; + } + return (bool.booleanValue() ? true : false); + } + + /** + *Converts a Boolean to a boolean handling null.
+ * + * @param bool the boolean to convert + * @param valueIfNull the boolean value to return if null + * @return true or false + */ + public static boolean toBooleanDefaultIfNull(Boolean bool, boolean valueIfNull) { + if (bool == null) { + return valueIfNull; + } + return (bool.booleanValue() ? true : false); + } + + // Integer to Boolean methods + //-------------------------------------------------------------------------- + + /** + *Convert an int to a boolean using the convention that zero is false.
+ * + * @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); + } + + /** + *Convert an int to a Boolean using the convention that zero is false.
+ * + * @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); + } + + /** + *Convert an Integer to a Boolean using the convention that zero is false.
+ * + *null will be converted to null.
+ * + * @param value the Integer to convert + * @return Boolean.TRUE if non-zero, Boolean.FALSE if zero, null if null + */ + public static Boolean toBooleanObject(Integer value) { + if (value == null) { + return null; + } + return (value.intValue() == 0 ? Boolean.FALSE : Boolean.TRUE); + } + + /** + *Convert an int to a boolean specifying the conversion values.
+ * + * @param value the Integer to convert + * @param trueValue the value to match for true + * @param falseValue the value to match for false + * @return true or false + * @throws IllegalArgumentException if no match + */ + public static boolean toBoolean(int value, int trueValue, int falseValue) { + if (value == trueValue) { + return true; + } else if (value == falseValue) { + return false; + } + // no match + throw new IllegalArgumentException("The Integer did not match either specified value"); + } + + /** + *Convert an Integer to a boolean specifying the conversion values.
+ * + * @param value the Integer to convert + * @param trueValue the value to match for true, may be null + * @param falseValue the value to match for false, may be null + * @return true or false + * @throws IllegalArgumentException if no match + */ + public static boolean toBoolean(Integer value, Integer trueValue, Integer falseValue) { + if (value == null) { + if (trueValue == null) { + return true; + } else if (falseValue == null) { + return false; + } + } else if (value.equals(trueValue)) { + return true; + } else if (value.equals(falseValue)) { + return false; + } + // no match + throw new IllegalArgumentException("The Integer did not match either specified value"); + } + + /** + *Convert an int to a Boolean specifying the conversion values.
+ * + * @param value the Integer to convert + * @param trueValue the value to match for true + * @param falseValue the value to match for false + * @param nullValue the value to to match for null + * @return Boolean.TRUE, Boolean.FALSE, or null + * @throws IllegalArgumentException if no match + */ + public static Boolean toBooleanObject(int value, int trueValue, int falseValue, int nullValue) { + if (value == trueValue) { + return Boolean.TRUE; + } else if (value == falseValue) { + return Boolean.FALSE; + } else if (value == nullValue) { + return null; + } + // no match + throw new IllegalArgumentException("The Integer did not match any specified value"); + } + + /** + *Convert an Integer to a Boolean specifying the conversion values.
+ * + * @param value the Integer to convert + * @param trueValue the value to match for true, may be null + * @param falseValue the value to match for false, may be null + * @param nullValue the value to to match for null, may be null + * @return Boolean.TRUE, Boolean.FALSE, or null + * @throws IllegalArgumentException if no match + */ + public static Boolean toBooleanObject(Integer value, Integer trueValue, Integer falseValue, Integer nullValue) { + if (value == null) { + if (trueValue == null) { + return Boolean.TRUE; + } else if (falseValue == null) { + return Boolean.FALSE; + } else if (nullValue == null) { + return null; + } + } else if (value.equals(trueValue)) { + return Boolean.TRUE; + } else if (value.equals(falseValue)) { + return Boolean.FALSE; + } else if (value.equals(nullValue)) { + return null; + } + // no match + throw new IllegalArgumentException("The Integer did not match any specified value"); + } + + // Boolean to Integer methods + //-------------------------------------------------------------------------- + + /** + *Convert a boolean to an int using the convention that zero is false.
+ * + * @param bool the boolean to convert + * @return one if true, zero if false + */ + public static int toInteger(boolean bool) { + return (bool ? 1 : 0); + } + + /** + *Convert a boolean to an Integer using the convention that zero is false.
+ * + * @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); + } + + /** + *Convert a Boolean to a Integer using the convention that zero is false.
+ * + *null will be converted to null.
+ * + * @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); + } + + /** + *Convert a boolean to an int specifying the conversion values.
+ * + * @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); + } + + /** + *Convert a Boolean to an int specifying the conversion values.
+ * + * @param bool the Boolean to convert + * @param trueValue the value to return if true + * @param falseValue the value to return if false + * @param nullValue the value to return if null + * @return the appropriate value + */ + public static int toInteger(Boolean bool, int trueValue, int falseValue, int nullValue) { + if (bool == null) { + return nullValue; + } + return (bool.booleanValue() ? trueValue : falseValue); + } + + /** + *Convert a boolean to an Integer specifying the conversion values.
+ * + * @param bool the to convert + * @param trueValue the value to return if true, may be null + * @param falseValue the value to return if false, may be null + * @return the appropriate value + */ + public static Integer toIntegerObject(boolean bool, Integer trueValue, Integer falseValue) { + return (bool ? trueValue : falseValue); + } + + /** + *Convert a Boolean to an Integer specifying the conversion values.
+ * + * @param bool the Boolean to convert + * @param trueValue the value to return if true, may be null + * @param falseValue the value to return if false, may be null + * @param nullValue the value to return if null, may be null + * @return the appropriate value + */ + public static Integer toIntegerObject(Boolean bool, Integer trueValue, Integer falseValue, Integer nullValue) { + if (bool == null) { + return nullValue; + } + return (bool.booleanValue() ? trueValue : falseValue); + } + + // String to Boolean methods + //-------------------------------------------------------------------------- + + /** + *Converts a String to a Boolean.
+ * + *'true', 'on' or 'yes' (case insensitive) will return true. + * 'false', 'off' or 'no' (case insensitive) will return false. + * Otherwise, null is returned.
+ * + * @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)) { + 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 + return null; + } + + /** + *Converts a String to a Boolean throwing an exception if no match.
+ * + * @param str the String to check + * @param trueString the String to match for true (case sensitive), may be null + * @param falseString the String to match for false (case sensitive), may be null + * @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 + */ + public static Boolean toBooleanObject(String str, String trueString, String falseString, String nullString) { + if (str == null) { + if (trueString == null) { + return Boolean.TRUE; + } else if (falseString == null) { + return Boolean.FALSE; + } else if (nullString == null) { + return null; + } + } else if (str.equals(trueString)) { + return Boolean.TRUE; + } else if (str.equals(falseString)) { + return Boolean.FALSE; + } else if (str.equals(nullString)) { + return null; + } + // no match + throw new IllegalArgumentException("The String did not match any specified value"); + } + + // String to boolean methods + //-------------------------------------------------------------------------- + + /** + *Converts a String to a boolean.
+ * + *'true', 'on' or 'yes' (case insensitive) will return true. + * Otherwise, false is returned.
+ * + * @param str the String to check + * @return the boolean value of the string, false if no match + */ + 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; + } + + /** + *Converts a String to a Boolean throwing an exception if no match found.
+ * + *null is returned if there is no match.
+ * + * @param str the String to check + * @param trueString the String to match for true (case sensitive), may be null + * @param falseString the String to match for false (case sensitive), may be null + * @return the boolean value of the string + * @throws IllegalArgumentException if the String doesn't match + */ + public static boolean toBoolean(String str, String trueString, String falseString) { + if (str == null) { + if (trueString == null) { + return true; + } else if (falseString == null) { + return false; + } + } else if (str.equals(trueString)) { + return true; + } else if (str.equals(falseString)) { + return false; + } + // no match + throw new IllegalArgumentException("The String did not match either specified value"); + } + + // Boolean to String methods + //-------------------------------------------------------------------------- + + /** + *Converts a Boolean to a String returning 'true', 'false', or null
.
null
+ */
+ public static String toStringTrueFalse(Boolean bool) {
+ return toString(bool, "true", "false", null);
+ }
+
+ /**
+ * Converts a Boolean to a String returning 'on', 'off', or null
.
null
+ */
+ public static String toStringOnOff(Boolean bool) {
+ return toString(bool, "on", "off", null);
+ }
+
+ /**
+ * Converts a Boolean to a String returning 'yes', 'no', or null
.
null
+ */
+ public static String toStringYesNo(Boolean bool) {
+ return toString(bool, "yes", "no", null);
+ }
+
+ /**
+ * Converts a Boolean to a String returning one of the input Strings.
+ * + * @param bool the Boolean to check + * @param trueString the String to return if true, may be null + * @param falseString the String to return if false, may be null + * @param nullString the String to return if null, may be null + * @return one of the three input Strings + */ + public static String toString(Boolean bool, String trueString, String falseString, String nullString) { + if (bool == null) { + return nullString; + } + return (bool.booleanValue() ? trueString : falseString); + } + + // boolean to String methods + //-------------------------------------------------------------------------- + + /** + *Converts a boolean to a String returning 'true' or 'false'.
+ * + * @param bool the Boolean to check + * @return 'true', 'false', ornull
+ */
+ public static String toStringTrueFalse(boolean bool) {
+ return toString(bool, "true", "false");
+ }
+
+ /**
+ * Converts a boolean to a String returning 'on' or 'off'.
+ * + * @param bool the Boolean to check + * @return 'on', 'off', ornull
+ */
+ public static String toStringOnOff(boolean bool) {
+ return toString(bool, "on", "off");
+ }
+
+ /**
+ * Converts a boolean to a String returning 'yes' or 'no'.
+ * + * @param bool the Boolean to check + * @return 'yes', 'no', ornull
+ */
+ public static String toStringYesNo(boolean bool) {
+ return toString(bool, "yes", "no");
+ }
+
+ /**
+ * Converts a boolean to a String returning one of the input Strings.
+ * + * @param bool the Boolean to check + * @param trueString the String to return if true, may be null + * @param falseString the String to return if false, may be null + * @return one of the two input Strings + */ + public static String toString(boolean bool, String trueString, String falseString) { + return (bool ? trueString : falseString); + } + +} diff --git a/examples/cl2/src/java/org/apache/commons/lang/CharRange.java b/examples/cl2/src/java/org/apache/commons/lang/CharRange.java new file mode 100644 index 00000000..6f9355ed --- /dev/null +++ b/examples/cl2/src/java/org/apache/commons/lang/CharRange.java @@ -0,0 +1,209 @@ +/* ==================================================================== + * 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 acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements 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 + *A range of characters. Able to understand the idea of a contiguous + * sublist of an alphabet, a negated concept, and a set of characters.
+ * + *Used by CharSet
to handle sets of characters.
Construct a CharRange
over a single character.
Construct a CharRange
over a set of characters.
Construct a CharRange
over a set of characters.
Get the start character for this character range.
+ * + * @return start char (inclusive) + */ + public char getStart() { + return this.start; + } + + /** + *Get the end character for this character range.
+ * + * @return end char (inclusive) + */ + public char getEnd() { + return this.close; + } + + /** + *Set the start character for this character range.
+ * + * @param ch start char (inclusive) + */ + public void setStart(char ch) { + this.start = ch; + } + + /** + *Set the end character for this character range.
+ * + * @param ch start char (inclusive) + */ + public void setEnd(char ch) { + this.close = ch; + } + + /** + *Is this CharRange
over many characters.
true
is many characters
+ */
+ public boolean isRange() {
+ return this.close != UNSET;
+ }
+
+ /**
+ * Is the passed in character ch
inside
+ * this range.
true
is in range
+ */
+ public boolean inRange(char ch) {
+ if( isRange() ) {
+ return ((ch >= start) && (ch <= close));
+ } else {
+ return start == ch;
+ }
+ }
+
+ /**
+ * Checks if this CharRange
is negated.
true
is negated
+ */
+ public boolean isNegated() {
+ return negated;
+ }
+
+ /**
+ * Sets this character range to be negated or not.
+ * + *This implies that this CharRange
is over
+ * all characters except the ones in this range.
true
to negate the range
+ */
+ public void setNegated(boolean negated) {
+ this.negated = negated;
+ }
+
+ /**
+ * Output a string representation of the character range.
+ * + * @return string representation + */ + public String toString() { + String str = ""; + if( isNegated() ) { + str += "^"; + } + str += start; + if( isRange() ) { + str += "-"; + str += close; + } + return str; + } + +} diff --git a/examples/cl2/src/java/org/apache/commons/lang/CharSet.java b/examples/cl2/src/java/org/apache/commons/lang/CharSet.java new file mode 100644 index 00000000..e2779c24 --- /dev/null +++ b/examples/cl2/src/java/org/apache/commons/lang/CharSet.java @@ -0,0 +1,162 @@ +/* ==================================================================== + * 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 acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements 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 + *A set of characters. You can iterate over the characters in the + * set.
+ * + * @author Henri Yandell + * @author Stephen Colebourne + * @since 1.0 + * @version $Id: CharSet.java,v 1.8 2003/03/23 17:59:09 scolebourne Exp $ + */ +public class CharSet { + + private List set = new LinkedList(); + + /** + *Restricted constructor.
+ * + *Use the factory method + * {@link CharSetUtils#evaluateSet(java.lang.String[])}.
+ * + * @throws NullPointerException if any of set[i] isnull
+ * or if set is null
+ */
+ protected CharSet(String[] set) {
+ int sz = set.length;
+ for (int i = 0; i < sz; i++) {
+ add(set[i]);
+ }
+ }
+
+ /**
+ * Does the CharSet
contain the specified
+ * character ch
.
true
if it does contain the character
+ * ch
+ */
+ public boolean contains(char ch) {
+ Iterator iterator = set.iterator();
+ boolean bool = false;
+ while (iterator.hasNext()) {
+ CharRange range = (CharRange) iterator.next();
+ if (range.isNegated()) {
+ if (!range.inRange(ch)) {
+ bool = true;
+ }
+ } else {
+ if (range.inRange(ch)) {
+ bool = true;
+ }
+ }
+ }
+ return bool;
+ }
+
+ /**
+ * Add a set definition string to the CharSet
.
str
is null
+ */
+ protected void add(String str) {
+ int sz = str.length();
+ CharRange range = null;
+
+ if("-".equals(str)) {
+ range = new CharRange('-');
+ set.add(range);
+ return;
+ }
+
+ boolean end = false;
+ boolean negated = false;
+ for(int i=0; iNumerous routines to manipulate a CharSet
.
CharSetUtils instances should NOT be constructed in standard programming.
+ * Instead, the class should be used as CharSetUtils.evaluateSet(null);
.
This constructor is public to permit tools that require a JavaBean instance + * to operate.
+ */ + public CharSetUtils() { + } + + /** + *Creates a CharSetUtils
object which allows a certain amount of
+ * set logic to be performed.
The syntax is:
+ *Squeezes any repititions of a character that is mentioned in the + * supplied set.
+ * + *An example is:
+ *Squeezes any repititions of a character that is mentioned in the + * supplied set.
+ * + *An example is:
+ *str
is
+ * null
+ */
+ public static String squeeze(String str, String[] set) {
+ CharSet chars = evaluateSet(set);
+ StringBuffer buffer = new StringBuffer(str.length());
+ char[] chrs = str.toCharArray();
+ int sz = chrs.length;
+ char lastChar = ' ';
+ char ch = ' ';
+ for (int i = 0; i < sz; i++) {
+ ch = chrs[i];
+ if (chars.contains(ch)) {
+ if ((ch == lastChar) && (i != 0)) {
+ continue;
+ }
+ }
+ buffer.append(ch);
+ lastChar = ch;
+ }
+ return buffer.toString();
+ }
+
+ /**
+ * Takes an argument in set-syntax, see evaluateSet, + * and returns the number of characters present in the specified string.
+ * + *An example would be:
+ *Takes an argument in set-syntax, see evaluateSet, + * and returns the number of characters present in the specified string.
+ * + * An example would be: + *An example would be:
+ *Takes an argument in set-syntax, see evaluateSet, + * and keeps any of characters present in the specified string.
+ * + *An example would be:
+ *str
is
+ * null
+ */
+ public static String keep(String str, String[] set) {
+ return modify(str, set, true);
+ }
+
+ /**
+ * Takes an argument in set-syntax, see evaluateSet, + * and deletes any of characters present in the specified string.
+ * + *An example would be:
+ *Takes an argument in set-syntax, see evaluateSet, + * and deletes any of characters present in the specified string.
+ * + *An example would be:
+ *str
is
+ * null
+ */
+ public static String delete(String str, String[] set) {
+ return modify(str, set, false);
+ }
+
+ // Implementation of delete and keep
+ private static String modify(String str, String[] set, boolean expect) {
+ CharSet chars = evaluateSet(set);
+ StringBuffer buffer = new StringBuffer(str.length());
+ char[] chrs = str.toCharArray();
+ int sz = chrs.length;
+ for(int i=0; iAn example is:
+ *If the length of characters to search for is greater than the + * length of characters to replace, then the last character is + * used.
+ * + * @param target String to replace characters in + * @param repl String to find that will be replaced + * @param with String to put into the target String + * @throws NullPointerException iftarget
, with
+ * or repl
is null
+ */
+ public static String translate(String target, String repl, String with) {
+ StringBuffer buffer = new StringBuffer(target.length());
+ char[] chrs = target.toCharArray();
+ char[] withChrs = with.toCharArray();
+ int sz = chrs.length;
+ int withMax = with.length() - 1;
+ for(int i=0; iProvides utility methods for working for classes without using reflection.
+ * + * @author Stephen Colebourne + * @author Gary Gregory + * @since 2.0 + * @version $Id: ClassUtils.java,v 1.12 2003/05/29 21:02:53 ggregory Exp $ + */ +public class ClassUtils { + + /** + * The package separator character:.
+ */
+ public static final char PACKAGE_SEPARATOR_CHAR = '.';
+
+ /**
+ * The package separator String: .
+ */
+ public static final String PACKAGE_SEPARATOR = String.valueOf(PACKAGE_SEPARATOR_CHAR);
+
+ /**
+ * The inner class separator character: $
+ */
+ public static final char INNER_CLASS_SEPARATOR_CHAR = '$';
+
+ /**
+ * The inner class separator String: $
+ */
+ public static final String INNER_CLASS_SEPARATOR = String.valueOf(INNER_CLASS_SEPARATOR_CHAR);
+
+ /**
+ * ClassUtils instances should NOT be constructed in standard programming.
+ * Instead, the class should be used as
+ * ClassUtils.getShortClassName(cls)
.
This constructor is public to permit tools that require a JavaBean + * instance to operate.
+ */ + public ClassUtils() { + } + + // ------------------------------------------------------------------------- + + /** + *Gets the class name minus the package name for an Object
.
Gets the class name minus the package name from a Class
.
null
+ * @return the class name without the package name
+ * @throws IllegalArgumentException if the class is null
+ */
+ public static String getShortClassName(Class cls) {
+ if (cls == null) {
+ throw new IllegalArgumentException("The class must not be null");
+ }
+ 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 + * @return the class name of the class without the package name + * @throws IllegalArgumentException if the className is empty + */ + public static String getShortClassName(String className) { + if (StringUtils.isEmpty(className)) { + throw new IllegalArgumentException("The class name must not be 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; + } + } + return new String(chars, lastDot, chars.length - lastDot); + } + + // ------------------------------------------------------------------------- + + /** + *Gets the package name of an Object
.
Gets the package name of a Class
.
null
+ * @return the package name
+ * @throws IllegalArgumentException if the class is null
+ */
+ public static String getPackageName(Class cls) {
+ if (cls == null) {
+ throw new IllegalArgumentException("The class must not be null");
+ }
+ 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 + * @return the package name + * @throws IllegalArgumentException if the className is empty + */ + public static String getPackageName(String className) { + if (StringUtils.isEmpty(className)) { + throw new IllegalArgumentException("The class name must not be empty"); + } + int i = className.lastIndexOf(PACKAGE_SEPARATOR_CHAR); + if (i == -1) { + return ""; + } + return className.substring(0, i); + } + + // ------------------------------------------------------------------------- + + /** + *Gets a List
of superclasses for the given class.
null
+ * @return the List
of superclasses in order going up from this one
+ * @throws IllegalArgumentException if the class is null
+ */
+ public static List getAllSuperclasses(Class cls) {
+ if (cls == null) {
+ throw new IllegalArgumentException("The class must not be null");
+ }
+ List classes = new ArrayList();
+ Class superclass = cls.getSuperclass();
+ while (superclass != null) {
+ classes.add(superclass);
+ superclass = superclass.getSuperclass();
+ }
+ 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, + * so the order is maintained.
+ * + * @param cls the class to look up, must not benull
+ * @return the List
of interfaces in order
+ * @throws IllegalArgumentException if the class is null
+ */
+ public static List getAllInterfaces(Class cls) {
+ if (cls == null) {
+ throw new IllegalArgumentException("The class must not be null");
+ }
+ List list = new ArrayList();
+ 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]);
+ }
+ 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 theList
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 theList
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 theList
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;
+// }
+
+ // -------------------------------------------------------------------------
+
+ /**
+ * Given a List
of class names, this method converts them into classes.
+ *
+ * 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
.
List
of Class objects corresponding to the class names
+ * @throws IllegalArgumentException if the classNames is null
+ * @throws ClassCastException if classNames contains a non String entry
+ */
+ public static List convertClassNamesToClasses(List classNames) {
+ if (classNames == null) {
+ throw new IllegalArgumentException("The class names must not be null");
+ }
+ List classes = new ArrayList(classNames.size());
+ for (Iterator it = classNames.iterator(); it.hasNext();) {
+ String className = (String) it.next();
+ try {
+ classes.add(Class.forName(className));
+ } catch (Exception ex) {
+ classes.add(null);
+ }
+ }
+ 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
.
List
of Class objects corresponding to the class names
+ * @throws IllegalArgumentException if the classNames is null
+ * @throws ClassCastException if classNames contains a non Class or null entry
+ */
+ public static List convertClassesToClassNames(List classes) {
+ if (classes == null) {
+ throw new IllegalArgumentException("The classes list must not be null");
+ }
+ List classNames = new ArrayList(classes.size());
+ for (Iterator it = classes.iterator(); it.hasNext();) {
+ Class cls = (Class) it.next();
+ if (cls == null) {
+ classNames.add(null);
+ } else {
+ classNames.add(cls.getName());
+ }
+ }
+ return classNames;
+ }
+
+ // -------------------------------------------------------------------------
+
+ /**
+ * 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 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.
null
+ * @param toClassArray the array of Classes to try to assign into, may be null
+ * @return true
if assignment possible
+ */
+ public static boolean isAssignable(Class[] classArray, Class[] toClassArray) {
+ if (ArrayUtils.isSameLength(classArray, toClassArray) == false) {
+ return false;
+ }
+ if (classArray == null) {
+ classArray = ArrayUtils.EMPTY_CLASS_ARRAY;
+ }
+ if (toClassArray == null) {
+ toClassArray = ArrayUtils.EMPTY_CLASS_ARRAY;
+ }
+ for (int i = 0; i < classArray.length; i++) {
+ if (isAssignable(classArray[i], toClassArray[i]) == false) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * 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.
null
+ * @param toClass the Class to try to assign into, must not be null
+ * @return true
if assignment possible
+ * @throws IllegalArgumentException if the toClass is null
+ */
+ public static boolean isAssignable(Class cls, Class toClass) {
+ if (toClass == null) {
+ throw new IllegalArgumentException("The class must not be null");
+ }
+ // have to check for null, as isAssignableFrom doesn't
+ if (cls == null) {
+ return !(toClass.isPrimitive());
+ }
+ if (cls.equals(toClass)) {
+ return true;
+ }
+ if (cls.isPrimitive()) {
+ if (toClass.isPrimitive() == false) {
+ return false;
+ }
+ if (Integer.TYPE.equals(cls)) {
+ return Long.TYPE.equals(toClass)
+ || Float.TYPE.equals(toClass)
+ || Double.TYPE.equals(toClass);
+ }
+ if (Long.TYPE.equals(cls)) {
+ return Float.TYPE.equals(toClass)
+ || Double.TYPE.equals(toClass);
+ }
+ if (Boolean.TYPE.equals(cls)) {
+ return false;
+ }
+ if (Double.TYPE.equals(cls)) {
+ return false;
+ }
+ if (Float.TYPE.equals(cls)) {
+ return Double.TYPE.equals(toClass);
+ }
+ if (Character.TYPE.equals(cls)) {
+ 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)
+ || 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)
+ || Double.TYPE.equals(toClass);
+ }
+ // should never get here
+ return false;
+ }
+ return toClass.isAssignableFrom(cls);
+ }
+
+ /**
+ * Is the specified class an inner class or static nested class.
+ * + * @param cls the class to check + * @returntrue
if the class is an inner or static nested class
+ * @throws IllegalArgumentException if the class is null
+ */
+ public static boolean isInnerClass(Class cls) {
+ if (cls == null) {
+ throw new IllegalArgumentException("The class must not be null");
+ }
+ return (cls.getName().indexOf(INNER_CLASS_SEPARATOR_CHAR) >= 0);
+ }
+
+}
diff --git a/examples/cl2/src/java/org/apache/commons/lang/Entities.java b/examples/cl2/src/java/org/apache/commons/lang/Entities.java
new file mode 100644
index 00000000..ad965f61
--- /dev/null
+++ b/examples/cl2/src/java/org/apache/commons/lang/Entities.java
@@ -0,0 +1,635 @@
+/* ====================================================================
+ * 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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
+ * 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 + * + * @author Alexander Day Chaffee + * @author Gary Gregory + * @since 2.0 + * @version $Id: Entities.java,v 1.8 2003/05/24 15:28:38 alex Exp $ + */ +class Entities { + + static private String[][] basic = { + {"quot", "34"}, // " - double-quote + {"amp", "38"}, // & - ampersand + {"lt", "60"}, // < - less-than + {"gt", "62"}, // > - greater-than + }; + + static String[][] apos = { + {"apos", "39"}, // XML apostrophe + }; + + static String[][] iso8859_1 = { + {"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 + {"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 + {"Agrave", "192"}, // À - uppercase A, grave accent + {"Aacute", "193"}, // Á - uppercase A, acute accent + {"Acirc", "194"}, // Â - uppercase A, circumflex accent + {"Atilde", "195"}, // Ã - uppercase A, tilde + {"Auml", "196"}, // Ä - uppercase A, umlaut + {"Aring", "197"}, // Å - uppercase A, ring + {"AElig", "198"}, // Æ - uppercase AE + {"Ccedil", "199"}, // Ç - uppercase C, cedilla + {"Egrave", "200"}, // È - uppercase E, grave accent + {"Eacute", "201"}, // É - uppercase E, acute accent + {"Ecirc", "202"}, // Ê - uppercase E, circumflex accent + {"Euml", "203"}, // Ë - uppercase E, umlaut + {"Igrave", "204"}, // Ì - uppercase I, grave accent + {"Iacute", "205"}, // Í - uppercase I, acute accent + {"Icirc", "206"}, // Î - uppercase I, circumflex accent + {"Iuml", "207"}, // Ï - uppercase I, umlaut + {"ETH", "208"}, // Ð - uppercase Eth, Icelandic + {"Ntilde", "209"}, // Ñ - uppercase N, tilde + {"Ograve", "210"}, // Ò - uppercase O, grave accent + {"Oacute", "211"}, // Ó - uppercase O, acute accent + {"Ocirc", "212"}, // Ô - uppercase O, circumflex accent + {"Otilde", "213"}, // Õ - uppercase O, tilde + {"Ouml", "214"}, // Ö - uppercase O, umlaut + {"times", "215"}, //multiplication sign + {"Oslash", "216"}, // Ø - uppercase O, slash + {"Ugrave", "217"}, // Ù - uppercase U, grave accent + {"Uacute", "218"}, // Ú - uppercase U, acute accent + {"Ucirc", "219"}, // Û - uppercase U, circumflex accent + {"Uuml", "220"}, // Ü - uppercase U, umlaut + {"Yacute", "221"}, // Ý - uppercase Y, acute accent + {"THORN", "222"}, // Þ - uppercase THORN, Icelandic + {"szlig", "223"}, // ß - lowercase sharps, German + {"agrave", "224"}, // à - lowercase a, grave accent + {"aacute", "225"}, // á - lowercase a, acute accent + {"acirc", "226"}, // â - lowercase a, circumflex accent + {"atilde", "227"}, // ã - lowercase a, tilde + {"auml", "228"}, // ä - lowercase a, umlaut + {"aring", "229"}, // å - lowercase a, ring + {"aelig", "230"}, // æ - lowercase ae + {"ccedil", "231"}, // ç - lowercase c, cedilla + {"egrave", "232"}, // è - lowercase e, grave accent + {"eacute", "233"}, // é - lowercase e, acute accent + {"ecirc", "234"}, // ê - lowercase e, circumflex accent + {"euml", "235"}, // ë - lowercase e, umlaut + {"igrave", "236"}, // ì - lowercase i, grave accent + {"iacute", "237"}, // í - lowercase i, acute accent + {"icirc", "238"}, // î - lowercase i, circumflex accent + {"iuml", "239"}, // ï - lowercase i, umlaut + {"eth", "240"}, // ð - lowercase eth, Icelandic + {"ntilde", "241"}, // ñ - lowercase n, tilde + {"ograve", "242"}, // ò - lowercase o, grave accent + {"oacute", "243"}, // ó - lowercase o, acute accent + {"ocirc", "244"}, // ô - lowercase o, circumflex accent + {"otilde", "245"}, // õ - lowercase o, tilde + {"ouml", "246"}, // ö - lowercase o, umlaut + {"divide", "247"}, // division sign + {"oslash", "248"}, // ø - lowercase o, slash + {"ugrave", "249"}, // ù - lowercase u, grave accent + {"uacute", "250"}, // ú - lowercase u, acute accent + {"ucirc", "251"}, // û - lowercase u, circumflex accent + {"uuml", "252"}, // ü - lowercase u, umlaut + {"yacute", "253"}, // ý - lowercase y, acute accent + {"thorn", "254"}, // þ - lowercase thorn, Icelandic + {"yuml", "255"}, // ÿ - lowercase y, umlaut + }; + + // http://www.w3.org/TR/REC-html40/sgml/entities.html + static String[][] html40 = { +// + {"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 --> + +// + {"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 --> + }; + + public static final Entities XML; + public static final Entities HTML32; + public static final Entities HTML40; + + static { + XML = new Entities(); + XML.addEntities(basic); + XML.addEntities(apos); + } + + static { + HTML32 = new Entities(); + HTML32.addEntities(basic); + HTML32.addEntities(iso8859_1); + } + + static { + HTML40 = new Entities(); + fillWithHtml40Entities(HTML40); + } + + static void fillWithHtml40Entities(Entities entities) { + entities.addEntities(basic); + entities.addEntities(iso8859_1); + entities.addEntities(html40); + } + + static interface IntMap { + void add(String name, int value); + + String name(int value); + + int value(String name); + } + + static abstract class MapIntMap implements IntMap { + protected Map mapNameToValue; + protected Map mapValueToName; + + public void add(String name, int value) { + mapNameToValue.put(name, new Integer(value)); + mapValueToName.put(new Integer(value), name); + } + + public String name(int value) { + return (String) mapValueToName.get(new Integer(value)); + } + + public int value(String name) { + Object value = mapNameToValue.get(name); + if (value == null) + return -1; + return ((Integer) value).intValue(); + } + } + + static class HashIntMap extends MapIntMap { + public HashIntMap() { + mapNameToValue = new HashMap(); + mapValueToName = new HashMap(); + } + } + + static class TreeIntMap extends MapIntMap { + public TreeIntMap() { + mapNameToValue = new TreeMap(); + mapValueToName = new TreeMap(); + } + } + + static class ArrayIntMap implements IntMap { + protected int growBy = 100; + protected int size = 0; + protected String[] names; + protected int[] values; + + public ArrayIntMap() { + names = new String[growBy]; + values = new int[growBy]; + } + + public ArrayIntMap(int growBy) { + this.growBy = growBy; + names = new String[growBy]; + values = new int[growBy]; + } + + public void add(String name, int value) { + ensureCapacity(size + 1); + names[size] = name; + values[size] = value; + size++; + } + + protected void ensureCapacity(int capacity) { + if (capacity > names.length) { + int newSize = Math.max(capacity, size + growBy); + String[] newNames = new String[newSize]; + System.arraycopy(names, 0, newNames, 0, size); + names = newNames; + int[] newValues = new int[newSize]; + System.arraycopy(values, 0, newValues, 0, size); + values = newValues; + } + } + + public String name(int value) { + for (int i = 0; i < size; ++i) { + if (values[i] == value) { + return names[i]; + } + } + return null; + } + + public int value(String name) { + for (int i = 0; i < size; ++i) { + if (names[i].equals(name)) { + return values[i]; + } + } + return -1; + } + } + + static class BinaryIntMap extends ArrayIntMap { + + public BinaryIntMap() { + } + + public BinaryIntMap(int growBy) { + super(growBy); + } + + // based on code in java.util.Arrays + private int binarySearch(int key) { + int low = 0; + int high = size - 1; + + while (low <= high) { + int mid = (low + high) >> 1; + int midVal = values[mid]; + + if (midVal < key) + low = mid + 1; + else if (midVal > key) + high = mid - 1; + else + return mid; // key found + } + return -(low + 1); // key not found. + } + + 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 + 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++; + } + + public String name(int value) { + int index = binarySearch(value); + if (index < 0) return null; + return names[index]; + } + } + + IntMap map = new BinaryIntMap(); + + public void addEntities(String[][] entityArray) { + for (int i = 0; i < entityArray.length; ++i) { + addEntity(entityArray[i][0], Integer.parseInt(entityArray[i][1])); + } + } + + public void addEntity(String name, int value) { + map.add(name, value); + } + + public String entityName(int value) { + return map.name(value); + } + + + public int entityValue(String name) { + return map.value(name); + } + + /** + * Escapes the characters in aString
.
+ * 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) {
+ 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);
+ if (entityName == null) {
+ if (((int) ch) > 0x7F) {
+ int intValue = ((int) ch);
+ buf.append("");
+ buf.append(intValue);
+ buf.append(';');
+ } else {
+ buf.append(ch);
+ }
+ } else {
+ buf.append('&');
+ buf.append(entityName);
+ buf.append(';');
+ }
+ }
+ 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.
+ * @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);
+ 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);
+ }
+ if (entityValue == -1) {
+ buf.append('&');
+ buf.append(entityName);
+ buf.append(';');
+ } else {
+ buf.append((char) (entityValue));
+ }
+ i = semi;
+ } else {
+ buf.append(ch);
+ }
+ }
+ return buf.toString();
+ }
+
+}
diff --git a/examples/cl2/src/java/org/apache/commons/lang/IllegalClassException.java b/examples/cl2/src/java/org/apache/commons/lang/IllegalClassException.java
new file mode 100644
index 00000000..72ea7b03
--- /dev/null
+++ b/examples/cl2/src/java/org/apache/commons/lang/IllegalClassException.java
@@ -0,0 +1,99 @@
+/* ====================================================================
+ * 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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
if the class is null
.
+ *
+ * @param cls a Class
+ * @return the name of cls
, or null
if if cls
is null
.
+ */
+ private static final String safeGetClassName(Class cls) {
+ return cls == null ? null : cls.getName();
+ }
+
+}
diff --git a/examples/cl2/src/java/org/apache/commons/lang/IncompleteArgumentException.java b/examples/cl2/src/java/org/apache/commons/lang/IncompleteArgumentException.java
new file mode 100644
index 00000000..2f7740ce
--- /dev/null
+++ b/examples/cl2/src/java/org/apache/commons/lang/IncompleteArgumentException.java
@@ -0,0 +1,99 @@
+/* ====================================================================
+ * 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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
+ * Class
that has not implemented the method
+ */
+ public NotImplementedException(Class clazz) {
+ super(
+ "Method is not implemented in class "
+ + ((clazz == null) ? null : clazz.getName()));
+ }
+
+ /**
+ * Constructs the exception with the specified message.
+ *
+ * @param msg the exception message.
+ */
+ public NotImplementedException(String msg) {
+ super(msg);
+ }
+
+}
diff --git a/examples/cl2/src/java/org/apache/commons/lang/NullArgumentException.java b/examples/cl2/src/java/org/apache/commons/lang/NullArgumentException.java
new file mode 100644
index 00000000..fe242e5e
--- /dev/null
+++ b/examples/cl2/src/java/org/apache/commons/lang/NullArgumentException.java
@@ -0,0 +1,74 @@
+/* ====================================================================
+ * 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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
+ * 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.
Constructs a new NumberRange
using the specified
+ * number as both the minimum and maximum in this range.
null
+ */
+ public NumberRange(Number num) {
+ if (num == null) {
+ throw new NullPointerException("The number must not be null");
+ }
+
+ this.min = num;
+ this.max = num;
+ }
+
+ /**
+ * Constructs a new NumberRange
with the specified
+ * minimum and maximum numbers.
If the maximum is less than the minimum, the range will be constructed + * from the minimum value to the minimum value, not what you would expect!.
+ * + * @param min the minimum number in this range + * @param max the maximum number in this range + * @throws NullPointerException if either the minimum or maximum number is + *null
+ */
+ public NumberRange(Number min, Number max) {
+ if (min == null) {
+ throw new NullPointerException("The minimum value must not be null");
+ } else if (max == null) {
+ throw new NullPointerException("The maximum value must not be null");
+ }
+
+ if (max.doubleValue() < min.doubleValue()) {
+ this.min = this.max = min;
+ } else {
+ this.min = min;
+ this.max = max;
+ }
+ }
+
+ /**
+ * Returns the minimum number in this range.
+ * + * @return the minimum number in this range + */ + public Number getMinimum() { + return min; + } + + /** + *Returns the maximum number in this range.
+ * + * @return the maximum number in this range + */ + public Number getMaximum() { + return max; + } + + /** + *Tests whether the specified number
occurs within
+ * this range using double
comparison.
true
if the specified number occurs within this
+ * range; otherwise, false
+ */
+ public boolean includesNumber(Number number) {
+ if (number == null) {
+ return false;
+ } else {
+ return !(min.doubleValue() > number.doubleValue()) &&
+ !(max.doubleValue() < number.doubleValue());
+ }
+ }
+
+ /**
+ * Tests whether the specified range occurs entirely within this
+ * range using double
comparison.
true
if the specified range occurs entirely within
+ * this range; otherwise, false
+ */
+ public boolean includesRange(NumberRange range) {
+ if (range == null) {
+ return false;
+ } else {
+ return includesNumber(range.min) && includesNumber(range.max);
+ }
+ }
+
+ /**
+ * Tests whether the specified range overlaps with this range
+ * using double
comparison.
true
if the specified range overlaps with this
+ * range; otherwise, false
+ */
+ public boolean overlaps(NumberRange range) {
+ if (range == null) {
+ return false;
+ } else {
+ return range.includesNumber(min) || range.includesNumber(max) ||
+ includesRange(range);
+ }
+ }
+
+ /**
+ * Indicates whether some other Object
is "equal" to
+ * this one.
true
if this object is the same as the obj
+ * argument; false
otherwise
+ */
+ public boolean equals(Object obj) {
+ if (obj == this) {
+ return true;
+ } else if (!(obj instanceof NumberRange)) {
+ return false;
+ } else {
+ NumberRange range = (NumberRange)obj;
+ return min.equals(range.min) && max.equals(range.max);
+ }
+ }
+
+ /**
+ * Returns a hash code value for this object.
+ * + * @return a hash code value for this object + */ + public int hashCode() { + int result = 17; + result = 37 * result + min.hashCode(); + result = 37 * result + max.hashCode(); + return result; + } + + /** + *Returns the string representation of this range.
+ * + *This string is the string representation of the minimum and + * maximum numbers in the range, separated by a hyphen. If a number + * is negative, then it is enclosed in parentheses.
+ * + * @return the string representation of this range + */ + public String toString() { + StringBuffer sb = new StringBuffer(); + + if (min.doubleValue() < 0) { + sb.append('(') + .append(min) + .append(')'); + } else { + sb.append(min); + } + + sb.append('-'); + + if (max.doubleValue() < 0) { + sb.append('(') + .append(max) + .append(')'); + } else { + sb.append(max); + } + + return sb.toString(); + } + +} diff --git a/examples/cl2/src/java/org/apache/commons/lang/NumberUtils.java b/examples/cl2/src/java/org/apache/commons/lang/NumberUtils.java new file mode 100644 index 00000000..047d0826 --- /dev/null +++ b/examples/cl2/src/java/org/apache/commons/lang/NumberUtils.java @@ -0,0 +1,775 @@ +/* ==================================================================== + * 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 acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements 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 + *Provides extra functionality for Java Number classes.
+ * + * @author Henri Yandell + * @author Rand McNeely + * @author Stephen Colebourne + * @author Steve Downey + * @author Eric Pugh + * @author Phil Steitz + * @since 1.0 + * @version $Id: NumberUtils.java,v 1.10 2003/06/08 14:14:01 scolebourne Exp $ + */ +public final class NumberUtils { + + /** Reusable Long constant for zero. */ + public static final Long LONG_ZERO = new Long(0L); + /** Reusable Long constant for one. */ + public static final Long LONG_ONE = new Long(1L); + /** Reusable Long constant for minus one. */ + public static final Long LONG_MINUS_ONE = new Long(-1L); + /** Reusable Integer constant for zero. */ + public static final Integer INTEGER_ZERO = new Integer(0); + /** Reusable Integer constant for one. */ + public static final Integer INTEGER_ONE = new Integer(1); + /** Reusable Integer constant for minus one. */ + public static final Integer INTEGER_MINUS_ONE = new Integer(-1); + /** Reusable Short constant for zero. */ + public static final Short SHORT_ZERO = new Short((short) 0); + /** Reusable Short constant for one. */ + public static final Short SHORT_ONE = new Short((short) 1); + /** Reusable Short constant for minus one. */ + public static final Short SHORT_MINUS_ONE = new Short((short) -1); + /** Reusable Byte constant for zero. */ + public static final Byte BYTE_ZERO = new Byte((byte) 0); + /** Reusable Byte constant for one. */ + public static final Byte BYTE_ONE = new Byte((byte) 1); + /** Reusable Byte constant for minus one. */ + public static final Byte BYTE_MINUS_ONE = new Byte((byte) -1); + /** Reusable Double constant for zero. */ + public static final Double DOUBLE_ZERO = new Double(0.0d); + /** Reusable Double constant for one. */ + public static final Double DOUBLE_ONE = new Double(1.0d); + /** Reusable Double constant for minus one. */ + public static final Double DOUBLE_MINUS_ONE = new Double(-1.0d); + /** Reusable Float constant for zero. */ + public static final Float FLOAT_ZERO = new Float(0.0f); + /** Reusable Float constant for one. */ + public static final Float FLOAT_ONE = new Float(1.0f); + /** Reusable Float constant for minus one. */ + public static final Float FLOAT_MINUS_ONE = new Float(-1.0f); + + /** + *NumberUtils
instances should NOT be constructed in standard programming.
+ * Instead, the class should be used as NumberUtils.stringToInt("6");
.
This constructor is public to permit tools that require a JavaBean instance + * to operate.
+ */ + public NumberUtils() { + } + + //-------------------------------------------------------------------- + + /** + *Convert a String
to an int
, returning
+ * zero
if the conversion fails.
zero
if
+ * conversion fails
+ */
+ public static int stringToInt(String str) {
+ return stringToInt(str, 0);
+ }
+
+ /**
+ * Convert a String
to an int
, returning a
+ * default value if the conversion fails.
Turns a string value into a java.lang.Number.
+ * + *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
+ * until one is found that can hold the value.
If a type specifier is not found, it will check for a decimal point
+ * and then try successively larger types from Integer
to
+ * BigInteger
and from Float
to
+ * BigDecimal
.
If the string starts with 0x
or -0x
, it
+ * will be interpreted as a hexadecimal integer. Values with leading
+ * 0
's will not be interpreted as octal.
Utility method for {@link #createNumber(java.lang.String)}.
+ * + *Returns true
if s is null
.
null
+ */
+ private static boolean isAllZeros(String s) {
+ if (s == null) {
+ return true;
+ }
+ for (int i = s.length() - 1; i >= 0; i--) {
+ if (s.charAt(i) != '0') {
+ return false;
+ }
+ }
+ return s.length() > 0;
+ }
+
+ //--------------------------------------------------------------------
+
+ /**
+ * Convert a String
to a Float
.
String
to convert
+ * @return converted Float
+ * @throws NumberFormatException if the value cannot be converted
+ */
+ public static Float createFloat(String val) {
+ return Float.valueOf(val);
+ }
+
+ /**
+ * Convert a String
to a Double
.
String
to convert
+ * @return converted Double
+ * @throws NumberFormatException if the value cannot be converted
+ */
+ public static Double createDouble(String val) {
+ return Double.valueOf(val);
+ }
+
+ /**
+ * Convert a String
to a Integer
, handling
+ * hex and octal notations.
String
to convert
+ * @return converted Integer
+ * @throws NumberFormatException if the value cannot be converted
+ */
+ public static Integer createInteger(String val) {
+ // decode() handles 0xAABD and 0777 (hex and octal) as well.
+ return Integer.decode(val);
+ }
+
+ /**
+ * Convert a String
to a Long
.
String
to convert
+ * @return converted Long
+ * @throws NumberFormatException if the value cannot be converted
+ */
+ public static Long createLong(String val) {
+ return Long.valueOf(val);
+ }
+
+ /**
+ * Convert a String
to a BigInteger
.
String
to convert
+ * @return converted BigInteger
+ * @throws NumberFormatException if the value cannot be converted
+ */
+ public static BigInteger createBigInteger(String val) {
+ BigInteger bi = new BigInteger(val);
+ return bi;
+ }
+
+ /**
+ * Convert a String
to a BigDecimal
.
String
to convert
+ * @return converted BigDecimal
+ * @throws NumberFormatException if the value cannot be converted
+ */
+ public static BigDecimal createBigDecimal(String val) {
+ BigDecimal bd = new BigDecimal(val);
+ return bd;
+ }
+
+ //--------------------------------------------------------------------
+
+ /**
+ * Gets the minimum of three long
values.
Gets the minimum of three int
values.
Gets the maximum of three long
values.
Gets the maximum of three int
values.
Compares two doubles
for order.
This method is more comprehensive than the standard Java greater + * than, less than and equals operators.
+ *-1
if the first value is less than the second.
+ * +1
if the first value is greater than the second.
+ * 0
if the values are equal.
+ * + * The ordering is as follows, largest to smallest: + *
Comparing NaN
with NaN
will
+ * return 0
.
double
+ * @param rhs the second double
+ * @return -1
if lhs is less, +1
if greater,
+ * 0
if equal to rhs
+ */
+ public static int compare(double lhs, double rhs) {
+ if (lhs < rhs) {
+ return -1;
+ }
+ if (lhs > rhs) {
+ return +1;
+ }
+ // Need to compare bits to handle 0.0 == -0.0 being true
+ // compare should put -0.0 < +0.0
+ // Two NaNs are also == for compare purposes
+ // where NaN == NaN is false
+ long lhsBits = Double.doubleToLongBits(lhs);
+ long rhsBits = Double.doubleToLongBits(rhs);
+ if (lhsBits == rhsBits) {
+ return 0;
+ }
+ // Something exotic! A comparison to NaN or 0.0 vs -0.0
+ // Fortunately NaN's long is > than everything else
+ // Also negzeros bits < poszero
+ // NAN: 9221120237041090560
+ // MAX: 9218868437227405311
+ // NEGZERO: -9223372036854775808
+ if (lhsBits < rhsBits) {
+ return -1;
+ } else {
+ return +1;
+ }
+ }
+
+ /**
+ * Compares two floats for order.
+ * + *This method is more comprhensive than the standard Java greater than, + * less than and equals operators.
+ *-1
if the first value is less than the second.
+ * +1
if the first value is greater than the second.
+ * 0
if the values are equal.
+ * The ordering is as follows, largest to smallest: + *
Comparing NaN
with NaN
will return
+ * 0
.
float
+ * @param rhs the second float
+ * @return -1
if lhs is less, +1
if greater,
+ * 0
if equal to rhs
+ */
+ public static int compare(float lhs, float rhs) {
+ if (lhs < rhs) {
+ return -1;
+ }
+ if (lhs > rhs) {
+ return +1;
+ }
+ //Need to compare bits to handle 0.0 == -0.0 being true
+ // compare should put -0.0 < +0.0
+ // Two NaNs are also == for compare purposes
+ // where NaN == NaN is false
+ int lhsBits = Float.floatToIntBits(lhs);
+ int rhsBits = Float.floatToIntBits(rhs);
+ if (lhsBits == rhsBits) {
+ return 0;
+ }
+ //Something exotic! A comparison to NaN or 0.0 vs -0.0
+ //Fortunately NaN's int is > than everything else
+ //Also negzeros bits < poszero
+ //NAN: 2143289344
+ //MAX: 2139095039
+ //NEGZERO: -2147483648
+ if (lhsBits < rhsBits) {
+ return -1;
+ } else {
+ return +1;
+ }
+ }
+
+ //--------------------------------------------------------------------
+
+ /**
+ * Checks whether the String
contains only
+ * digit characters.
Null
and empty String will return
+ * false
.
String
to check
+ * @return true
if str contains only unicode numeric
+ */
+ public static boolean isDigits(String str) {
+ if ((str == null) || (str.length() == 0)) {
+ return false;
+ }
+ for (int i = 0; i < str.length(); i++) {
+ if (!Character.isDigit(str.charAt(i))) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Checks whether the String a valid Java number.
+ * + *Valid numbers include hexadecimal marked with the 0x
+ * qualifier, scientific notation and numbers marked with a type
+ * qualifier (e.g. 123L).
Null
and empty String will return
+ * false
.
String
to check
+ * @return true
if the string is a correctly formatted number
+ */
+ public static boolean isNumber(String str) {
+ if ((str == null) || (str.length() == 0)) {
+ return false;
+ }
+ char[] chars = str.toCharArray();
+ int sz = chars.length;
+ boolean hasExp = false;
+ boolean hasDecPoint = false;
+ boolean allowSigns = false;
+ boolean foundDigit = false;
+ // deal with any possible sign up front
+ int start = (chars[0] == '-') ? 1 : 0;
+ if (sz > start + 1) {
+ if (chars[start] == '0' && chars[start + 1] == 'x') {
+ int i = start + 2;
+ if (i == sz) {
+ return false; // str == "0x"
+ }
+ // checking hex (it can't be anything else)
+ for (; i < chars.length; i++) {
+ if ((chars[i] < '0' || chars[i] > '9')
+ && (chars[i] < 'a' || chars[i] > 'f')
+ && (chars[i] < 'A' || chars[i] > 'F')) {
+ return false;
+ }
+ }
+ return true;
+ }
+ }
+ sz--; // don't want to loop to the last char, check it afterwords
+ // for type qualifiers
+ int i = start;
+ // loop to the next to last char or to the last char if we need another digit to
+ // make a valid number (e.g. chars[0..5] = "1234E")
+ while (i < sz || (i < sz + 1 && allowSigns && !foundDigit)) {
+ if (chars[i] >= '0' && chars[i] <= '9') {
+ foundDigit = true;
+ allowSigns = false;
+
+ } else if (chars[i] == '.') {
+ if (hasDecPoint || hasExp) {
+ // two decimal points or dec in exponent
+ return false;
+ }
+ hasDecPoint = true;
+ } else if (chars[i] == 'e' || chars[i] == 'E') {
+ // we've already taken care of hex.
+ if (hasExp) {
+ // two E's
+ return false;
+ }
+ if (!foundDigit) {
+ return false;
+ }
+ hasExp = true;
+ allowSigns = true;
+ } else if (chars[i] == '+' || chars[i] == '-') {
+ if (!allowSigns) {
+ return false;
+ }
+ allowSigns = false;
+ foundDigit = false; // we need a digit after the E
+ } else {
+ return false;
+ }
+ i++;
+ }
+ if (i < chars.length) {
+ if (chars[i] >= '0' && chars[i] <= '9') {
+ // no type qualifier, OK
+ return true;
+ }
+ if (chars[i] == 'e' || chars[i] == 'E') {
+ // can't have an E at the last byte
+ return false;
+ }
+ if (!allowSigns
+ && (chars[i] == 'd'
+ || chars[i] == 'D'
+ || chars[i] == 'f'
+ || chars[i] == 'F')) {
+ return foundDigit;
+ }
+ if (chars[i] == 'l'
+ || chars[i] == 'L') {
+ // not allowing L with an exponoent
+ return foundDigit && !hasExp;
+ }
+ // last character is illegal
+ return false;
+ }
+ // allowSigns is true iff the val ends in 'E'
+ // found digit it to make sure weird stuff like '.' and '1E-' doesn't pass
+ return !allowSigns && foundDigit;
+ }
+}
diff --git a/examples/cl2/src/java/org/apache/commons/lang/ObjectUtils.java b/examples/cl2/src/java/org/apache/commons/lang/ObjectUtils.java
new file mode 100644
index 00000000..e5bb5ded
--- /dev/null
+++ b/examples/cl2/src/java/org/apache/commons/lang/ObjectUtils.java
@@ -0,0 +1,184 @@
+/* ====================================================================
+ * 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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
+ * Common Object
manipulation routines.
Singleton used as a null
placeholder where
+ * null
has another meaning.
For example, in a HashMap
the
+ * {@link java.util.HashMap#get(java.lang.Object)} method returns
+ * null
if the Map
contains
+ * null
or if there is no matching key. The
+ * Null
placeholder can be used to distinguish between
+ * these two cases.
Another example is Hashtable
, where null
+ * cannot be stored.
This instance is Serializable.
+ */ + public static final Null NULL = new Null(); + + /** + *ObjectUtils
instances should NOT be constructed in
+ * standard programming. Instead, the class should be used as
+ * ObjectUtils.defaultIfNull("a","b");
.
This constructor is public to permit tools that require a JavaBean instance + * to operate.
+ */ + public ObjectUtils() { + } + + //-------------------------------------------------------------------- + + /** + *Returns a default value if the object passed is
+ * null
.
Object
to test
+ * @param defaultValue the default value to return
+ * @return object
if it is not null
, defaultValue otherwise
+ */
+ public static Object defaultIfNull(Object object, Object defaultValue) {
+ return (object != null ? object : defaultValue);
+ }
+
+ /**
+ * Compares two objects for equality, where either one or both
+ * objects may be null
.
true
if the values of both objects are the same
+ */
+ public static boolean equals(Object object1, Object object2) {
+ if (object1 == object2) {
+ return true;
+ }
+ if ((object1 == null) || (object2 == null)) {
+ return false;
+ }
+ return object1.equals(object2);
+ }
+
+ /**
+ * Gets the toString that would be produced by Object
+ * if a class did not override toString itself. Null
+ * will return null
.
null
+ * @return the default toString text, or null
if
+ * null
passed in
+ */
+ public static String identityToString(Object object) {
+ if (object == null) {
+ return null;
+ }
+ return new StringBuffer()
+ .append(object.getClass().getName())
+ .append('@')
+ .append(Integer.toHexString(System.identityHashCode(object)))
+ .toString();
+ }
+
+ /**
+ * Class used as a null placeholder where null has another meaning.
+ * + *For example, in a HashMap
the
+ * {@link java.util.HashMap#get(java.lang.Object)} method returns
+ * null
if the Map
contains
+ * null
or if there is no matching key. The
+ * Null
placeholder can be used to distinguish between
+ * these two cases.
Another example is Hashtable
, where null
+ * cannot be stored.
Ensure singleton.
+ * + * @return the singleton value + */ + private Object readResolve() { + return ObjectUtils.NULL; + } + } + +} diff --git a/examples/cl2/src/java/org/apache/commons/lang/RandomStringUtils.java b/examples/cl2/src/java/org/apache/commons/lang/RandomStringUtils.java new file mode 100644 index 00000000..63b8c11e --- /dev/null +++ b/examples/cl2/src/java/org/apache/commons/lang/RandomStringUtils.java @@ -0,0 +1,319 @@ +/* ==================================================================== + * 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 acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements 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 + *Common random String
manipulation routines.
Originally from the GenerationJava Core library.
+ * + * @author Henri Yandell + * @author Steven Caswell + * @author Stephen Colebourne + * @author Gary Gregory + * @author Phil Steitz + * @since 1.0 + * @version $Id: RandomStringUtils.java,v 1.13 2003/06/09 21:36:02 scolebourne Exp $ + */ +public class RandomStringUtils { + + /** + *Random object used by random method. This has to be not local + * to the random method so as to not return the same value in the + * same millisecond.
+ */ + private static final Random RANDOM = new Random(); + + /** + *RandomStringUtils
instances should NOT be constructed in
+ * standard programming. Instead, the class should be used as
+ * RandomStringUtils.random(5);
.
This constructor is public to permit tools that require a JavaBean instance + * to operate.
+ */ + public RandomStringUtils() { + } + + /** + *Creates a random string whose length is the number of characters + * specified.
+ * + *Characters will be chosen from the set of all characters.
+ * + * @param count length of random string to create + * @return the random string + */ + public static String random(int count) { + return random(count, false, false); + } + + /** + *Creates a random string whose length is the number of characters + * specified.
+ * + *Characters will be chosen from the set of characters whose
+ * ASCII value is between 32
and 126
(inclusive).
Creates a random string whose length is the number of characters + * specified.
+ * + *Characters will be chosen from the set of alphabetic + * characters.
+ * + * @param count length of random string to create + * @return the random string + */ + public static String randomAlphabetic(int count) { + return random(count, true, false); + } + + /** + *Creates a random string whose length is the number of characters + * specified.
+ * + *Characters will be chosen from the set of alpha-numeric + * characters.
+ * + * @param count length of random string to create + * @return the random string + */ + public static String randomAlphanumeric(int count) { + return random(count, true, true); + } + + /** + *Creates a random string whose length is the number of characters + * specified.
+ * + *Characters will be chosen from the set of numeric + * characters.
+ * + * @param count length of random string to create + * @return the random string + */ + public static String randomNumeric(int count) { + return random(count, false, true); + } + + /** + *Creates a random string whose length is the number of characters + * specified.
+ * + *Characters will be chosen from the set of alpha-numeric + * characters as indicated by the arguments.
+ * + * @param count length of random string to create + * @param letters iftrue
, generated string will include
+ * alphabetic characters
+ * @param numbers if true
, generatd string will include
+ * numeric characters
+ * @return the random string
+ */
+ public static String random(int count, boolean letters, boolean numbers) {
+ return random(count, 0, 0, letters, numbers);
+ }
+
+ /**
+ * Creates a random string whose length is the number of characters + * specified.
+ * + *Characters will be chosen from the set of alpha-numeric + * characters as indicated by the arguments.
+ * + * @param count length of random string to create + * @param start position in set of chars to start at + * @param end position in set of chars to end before + * @param letters iftrue
, generated string will include
+ * alphabetic characters
+ * @param numbers if true
, generated string will include
+ * numeric characters
+ * @return the random string
+ */
+ public static String random(int count, int start, int end, boolean letters, boolean numbers) {
+ return random(count, start, end, letters, numbers, null);
+ }
+
+ /**
+ * Creates a random string based on a variety of options, using + * default source of randomness.
+ * + * This method has exactly the same semantics as {@link + * #random(int,int,int,boolean,boolean,char[],Random)}, but + * instead of using an externally supplied source of randomness, it uses + * the internal static {@link Random} instance ({@link #RANDOM}). + * + * @param count length of random string to create + * @param start position in set of chars to start at + * @param end position in set of chars to end before + * @param letters only allow letters? + * @param numbers only allow numbers? + * @param set set of chars to choose randoms from. Ifnull
,
+ * then it will use the set of all chars.
+ * @return the random string
+ * @throws ArrayIndexOutOfBoundsException if there are not
+ * (end - start) + 1
characters in the set array.
+ */
+ public static String random(int count, int start, int end, boolean letters, boolean numbers, char[] set) {
+ return random(count,start,end,letters,numbers,set,RANDOM);
+ }
+
+ /**
+ * Creates a random string based on a variety of options, using + * supplied source of randomness.
+ * + *If start and end are both 0
, start and end are set
+ * to ' '
and 'z'
, the ASCII printable
+ * characters, will be used, unless letters and numbers are both
+ * false
, in which case, start and end are set to
+ * 0
and Integer.MAX_VALUE
.
+ *
+ *
If set is not null
, characters between start and
+ * end are chosen.
As a source of randomness is used supplied {@link Random}
+ * instance. This makes method behave predictively, and allows
+ * usage of RandomStringUtils
in situations that need
+ * repetitive behaviour.
null
,
+ * then it will use the set of all chars.
+ * @param random source of randomness.
+ * @return the random string
+ * @throws ArrayIndexOutOfBoundsException if there are not
+ * (end - start) + 1
characters in the set array.
+ * @throws IllegalArgumentException if count
< 0.
+ */
+ public static String random(int count, int start, int end, boolean letters, boolean numbers, char[] set, Random random) {
+ if( count == 0 ) {
+ return "";
+ } else if( count < 0 ) {
+ throw new IllegalArgumentException("Requested random string length " + count + " is less than 0.");
+ }
+ if( (start == 0) && (end == 0) ) {
+ end = (int)'z' + 1;
+ start = (int)' ';
+ if(!letters && !numbers) {
+ start = 0;
+ end = Integer.MAX_VALUE;
+ }
+ }
+
+ StringBuffer buffer = new StringBuffer();
+ int gap = end - start;
+
+ while(count-- != 0) {
+ char ch;
+ if(set == null) {
+ ch = (char)(random.nextInt(gap) + start);
+ } else {
+ ch = set[random.nextInt(gap) + start];
+ }
+ if( (letters && numbers && Character.isLetterOrDigit(ch)) ||
+ (letters && Character.isLetter(ch)) ||
+ (numbers && Character.isDigit(ch)) ||
+ (!letters && !numbers)
+ )
+ {
+ buffer.append( ch );
+ } else {
+ count++;
+ }
+ }
+ return buffer.toString();
+ }
+
+ /**
+ * Creates a random string whose length is the number of characters + * specified.
+ * + *Characters will be chosen from the set of characters + * specified.
+ * + * @param count length of random string to create + * @param set String containing the set of characters to use + * @return the random string + */ + public static String random(int count, String set) { + return random(count, set.toCharArray()); + } + + /** + *Creates a random string whose length is the number of characters + * specified.
+ * + *Characters will be chosen from the set of characters specified.
+ * + * @param count length of random string to create + * @param set character array containing the set of characters to use + * @return the random string + */ + public static String random(int count, char[] set) { + return random(count, 0, set.length, false, false, set); + } +} diff --git a/examples/cl2/src/java/org/apache/commons/lang/SerializationException.java b/examples/cl2/src/java/org/apache/commons/lang/SerializationException.java new file mode 100644 index 00000000..86578181 --- /dev/null +++ b/examples/cl2/src/java/org/apache/commons/lang/SerializationException.java @@ -0,0 +1,110 @@ +/* ==================================================================== + * 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 acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements 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 + *Exception thrown when the Serialization process fails.
+ * + *The original error is wrapped within this one.
+ * + * @author Stephen Colebourne + * @since 1.0 + * @version $Id: SerializationException.java,v 1.5 2003/03/23 18:02:29 scolebourne Exp $ + */ +public class SerializationException extends NestableRuntimeException { + + /** + *Constructs a new SerializationException
without specified
+ * detail message.
Constructs a new SerializationException
with specified
+ * detail message.
Constructs a new SerializationException
with specified
+ * nested Throwable
.
Exception
or Error
+ * that caused this exception to be thrown.
+ */
+ public SerializationException(Throwable cause) {
+ super(cause);
+ }
+
+ /**
+ * Constructs a new SerializationException
with specified
+ * detail message and nested Throwable
.
Exception
or Error
+ * that caused this exception to be thrown.
+ */
+ public SerializationException(String msg, Throwable cause) {
+ super(msg, cause);
+ }
+
+}
diff --git a/examples/cl2/src/java/org/apache/commons/lang/SerializationUtils.java b/examples/cl2/src/java/org/apache/commons/lang/SerializationUtils.java
new file mode 100644
index 00000000..8a226eed
--- /dev/null
+++ b/examples/cl2/src/java/org/apache/commons/lang/SerializationUtils.java
@@ -0,0 +1,208 @@
+/* ====================================================================
+ * 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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
+ * SerializationUtils
provides methods that assist with the
+ * serialization process, or perform additional functionality based on serialization.
SerializationUtils instances should NOT be constructed in standard programming.
+ * Instead, the class should be used as SerializationUtils.clone(object)
.
This constructor is public to permit tools that require a JavaBean instance + * to operate.
+ */ + public SerializationUtils() { + super(); + } + + /** + *Deep clone an Object
using serialization.
This is many times slower than writing clone methods by hand
+ * on all objects in your object graph. However, for complex object
+ * graphs, or for those that don't support deep cloning this can
+ * be a simple alternative implementation. Of course all the objects
+ * must be Serializable
.
Serializable
object to clone
+ * @return the cloned object
+ * @throws SerializationException (runtime) if the serialization fails
+ */
+ public static Object clone(Serializable object) {
+ return deserialize(serialize(object));
+ }
+
+ /**
+ * Serializes an Object
to the specified stream.
The stream will be closed once the object is written. + * This avoids the need for a finally clause, and maybe also exception + * handling, in the application code.
+ * + *The stream passed in is not buffered internally within this method. + * This is the responsibility of your application if desired.
+ * + * @param obj the object to serialize to bytes + * @param outputStream the stream to write to + * @throws SerializationException (runtime) if the serialization fails + */ + public static void serialize(Serializable obj, OutputStream outputStream) { + ObjectOutputStream out = null; + try { + // stream closed in the finally + out = new ObjectOutputStream(outputStream); + out.writeObject(obj); + + } catch (IOException ex) { + throw new SerializationException(ex); + } finally { + try { + if (out != null) { + out.close(); + } + } catch (IOException ex) { + // ignore; + } + } + } + + /** + *Serializes an Object
to a byte array for
+ * storage/serialization.
Deserializes an Object
from the specified stream.
The stream will be closed once the object is written. This + * avoids the need for a finally clause, and maybe also exception + * handling, in the application code.
+ * + *The stream passed in is not buffered internally within this method. + * This is the responsibility of your application if desired.
+ * + * @param inputStream the serialized object input stream + * @return the deserialized object + * @throws SerializationException (runtime) if the serialization fails + */ + public static Object deserialize(InputStream inputStream) { + ObjectInputStream in = null; + try { + // stream closed in the finally + in = new ObjectInputStream(inputStream); + return in.readObject(); + + } catch (ClassNotFoundException ex) { + throw new SerializationException(ex); + } catch (IOException ex) { + throw new SerializationException(ex); + } finally { + try { + if (in != null) { + in.close(); + } + } catch (IOException ex) { + // ignore + } + } + } + + /** + *Deserializes a single Object
from an array of bytes.
Escapes and unescapes String
s for Java, Java Script, HTML, and XML.
+ *
+ *
Originally from + * Turbine and the + * GenerationJavaCore library and from + * Purple Technology + *
+ * + * @author Henri Yandell + * @author Alexander Day Chaffee + * @author Antony Riley + * @author Helge Tesgaard + * @author Sean Brown + * @author Gary Gregory + * @since 2.0 + * @version $Id: StringEscapeUtils.java,v 1.12 2003/05/24 04:35:06 alex Exp $ + */ +public class StringEscapeUtils { + + /** + * The entity set to use when escaping and unescaping HTML. + */ + protected static Entities DEFAULT_ENTITIES = Entities.HTML40; + + /** + *StringEscapeUtils
instances should NOT be constructed in
+ * standard programming.
Instead, the class should be used as:
+ *StringEscapeUtils.escapeJava("foo");+ * + *
This constructor is public to permit tools that require a JavaBean + * instance to operate.
+ */ + public StringEscapeUtils() { + } + + // Java and JavaScript + //-------------------------------------------------------------------------- + /** + *Escapes the characters in a String
using Java String rules.
Deals correctly with quotes and control-chars (tab, backslash, cr, ff, etc.)
+ * + *So a tab becomes the characters '\\'
and
+ * 't'
.
The only difference between Java strings and JavaScript strings + * is that in JavaScript, a single quote must be escaped.
+ * + *Example: + *
+ * input string: He didn't say, "Stop!" + * output string: He didn't say, \"Stop!\" + *+ * + * + * @param str String to escape values in + * @return String with escaped values + * @throws NullPointerException if str is
null
+ */
+ public static String escapeJava(String str) {
+ return escapeJavaStyleString(str, false);
+ }
+
+ /**
+ * Escapes the characters in a String
using Java String rules to a Writer
.
null
+ * @throws IOException if error occurs on undelying Writer
+ */
+ public static void escapeJava(Writer out, String str) throws IOException {
+ escapeJavaStyleString(out, str, false);
+ }
+
+ /**
+ * Escapes the characters in a String
using JavaScript String rules.
Escapes any values it finds into their JavaScript String form. + * Deals correctly with quotes and control-chars (tab, backslash, cr, ff, etc.)
+ * + *So a tab becomes the characters '\\'
and
+ * 't'
.
The only difference between Java strings and JavaScript strings + * is that in JavaScript, a single quote must be escaped.
+ * + *Example: + *
+ * input string: He didn't say, "Stop!" + * output string: He didn\'t say, \"Stop!\" + *+ * + * + * @param str String to escape values in + * @return String with escaped values + * @throws NullPointerException if str is
null
+ */
+ public static String escapeJavaScript(String str) {
+ return escapeJavaStyleString(str, true);
+ }
+
+ /**
+ * Escapes the characters in a String
using JavaScript String rules to a Writer
.
null
+ * @throws IOException if error occurs on undelying Writer
+ **/
+ public static void escapeJavaScript(Writer out, String str) throws IOException {
+ escapeJavaStyleString(out, str, true);
+ }
+
+ private static String escapeJavaStyleString(String str, boolean escapeSingleQuotes) {
+ try {
+ StringPrintWriter writer = new StringPrintWriter(str.length() * 2);
+ escapeJavaStyleString(writer, str, escapeSingleQuotes);
+ return writer.getString();
+ } catch (IOException ioe) {
+ // this should never ever happen while writing to a StringWriter
+ ioe.printStackTrace();
+ return null;
+ }
+ }
+
+ private static void escapeJavaStyleString(Writer out, String str, boolean escapeSingleQuote) throws IOException {
+ int sz;
+ sz = str.length();
+ for (int i = 0; i < sz; i++) {
+ char ch = str.charAt(i);
+
+ // handle unicode
+ if (ch > 0xfff) {
+ out.write("\\u" + hex(ch));
+ } else if (ch > 0xff) {
+ out.write("\\u0" + hex(ch));
+ } else if (ch > 0x7f) {
+ out.write("\\u00" + hex(ch));
+ } else if (ch < 32) {
+ switch (ch) {
+ case '\b':
+ out.write('\\');
+ out.write('b');
+ break;
+ case '\n':
+ out.write('\\');
+ out.write('n');
+ break;
+ case '\t':
+ out.write('\\');
+ out.write('t');
+ break;
+ case '\f':
+ out.write('\\');
+ out.write('f');
+ break;
+ case '\r':
+ out.write('\\');
+ out.write('r');
+ break;
+ default :
+ if (ch > 0xf) {
+ out.write("\\u00" + hex(ch));
+ } else {
+ out.write("\\u000" + hex(ch));
+ }
+ break;
+ }
+ } else {
+ switch (ch) {
+ case '\'':
+ if (escapeSingleQuote) out.write('\\');
+ out.write('\'');
+ break;
+ case '"':
+ out.write('\\');
+ out.write('"');
+ break;
+ case '\\':
+ out.write('\\');
+ out.write('\\');
+ break;
+ default :
+ out.write(ch);
+ break;
+ }
+ }
+ }
+ }
+
+ /**
+ * Returns an upper case hexadecimal String
for the given character.
+ *
+ * @param ch The character to convert.
+ * @return An upper case hexadecimal String
+ */
+ private static String hex(char ch) {
+ return Integer.toHexString(ch).toUpperCase();
+ }
+
+ /**
+ * Unescapes any Java literals found in the String
.
+ * For example, it will turn a sequence of '\' and 'n' into a newline character,
+ * unless the '\' is preceded by another '\'.
+ *
+ * @param str The String
to unescape.
+ * @return A new unescaped String
.
+ */
+ public static String unescapeJava(String str) {
+ try {
+ StringPrintWriter writer = new StringPrintWriter(str.length());
+ unescapeJava(writer, str);
+ return writer.getString();
+ } catch (IOException ioe) {
+ // this should never ever happen while writing to a StringWriter
+ ioe.printStackTrace();
+ return null;
+ }
+ }
+
+ /**
+ * Unescapes any Java literals found in the String
to a Writer
.
+ * For example, it will turn a sequence of '\' and 'n' into a newline character,
+ * unless the '\' is preceded by another '\'.
+ *
+ * @param out The Writer
used to output unescaped characters.
+ * @param str The String
to unescape.
+ */
+ public static void unescapeJava(Writer out, String str) throws IOException {
+ int sz = str.length();
+ StringBuffer unicode = new StringBuffer(4);
+ boolean hadSlash = false;
+ boolean inUnicode = false;
+ for (int i = 0; i < sz; i++) {
+ char ch = str.charAt(i);
+ if (inUnicode) {
+ // if in unicode, then we're reading unicode
+ // values in somehow
+ unicode.append(ch);
+ if (unicode.length() == 4) {
+ // unicode now contains the four hex digits
+ // which represents our unicode chacater
+ try {
+ int value = Integer.parseInt(unicode.toString(), 16);
+ out.write((char) value);
+ unicode.setLength(0);
+ inUnicode = false;
+ hadSlash = false;
+ } catch (NumberFormatException nfe) {
+ throw new NestableRuntimeException("Unable to parse unicode value: " + unicode, nfe);
+ }
+ }
+ continue;
+ }
+ if (hadSlash) {
+ // handle an escaped value
+ hadSlash = false;
+ switch (ch) {
+ case '\\':
+ out.write('\\');
+ break;
+ case '\'':
+ out.write('\'');
+ break;
+ case '\"':
+ out.write('"');
+ break;
+ case 'r':
+ out.write('\r');
+ break;
+ case 'f':
+ out.write('\f');
+ break;
+ case 't':
+ out.write('\t');
+ break;
+ case 'n':
+ out.write('\n');
+ break;
+ case 'b':
+ out.write('\b');
+ break;
+ case 'u':
+ {
+ // uh-oh, we're in unicode country....
+ inUnicode = true;
+ break;
+ }
+ default :
+ out.write(ch);
+ break;
+ }
+ continue;
+ } else if (ch == '\\') {
+ hadSlash = true;
+ continue;
+ }
+ out.write(ch);
+ }
+ if (hadSlash) {
+ // then we're in the weird case of a \ at the end of the
+ // string, let's output it anyway.
+ out.write('\\');
+ }
+ }
+
+ /**
+ * @see #unescapeJava(String)
+ */
+ public static String unescapeJavaScript(String str) {
+ return unescapeJava(str);
+ }
+
+ /**
+ * @see #unescapeJava(Writer,String)
+ */
+ public static void unescapeJavaScript(Writer out, String str) throws IOException {
+ unescapeJava(out, str);
+ }
+
+ // HTML and XML
+ //--------------------------------------------------------------------------
+
+ /**
+ * Escapes the characters in a String
using HTML entities.
+ * For example: "bread" & "butter" => "bread" & "butter". + *
+ *Supports all known HTML 4.0 entities, including funky accents. + *
+ * + * @param str TheString
to escape
+ * @return A new escaped String
.
+ *
+ * @see Entities
+ * @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 String escapeHtml(String str) {
+ return escapeEntities(str, Entities.HTML40);
+ }
+
+ /**
+ * 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çla;ais>"
+ * will become "
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 str TheString
to unescape
+ * @return A new unescaped String
.
+ * @see #escapeHtml(String)
+ **/
+ public static String unescapeHtml(String str) {
+ return unescapeEntities(str, Entities.HTML40);
+ }
+
+ /**
+ * 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). + * Does not support DTDs or external entities. + *
+ * @param str TheString
to escape
+ * @return A new escaped String
.
+ * @see #unescapeXml(java.lang.String)
+ **/
+ public static String escapeXml(String str) {
+ return escapeEntities(str, Entities.XML);
+ }
+
+ /**
+ * 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). + * Does not support DTDs or external entities. + *
+ * + * @param str TheString
to unescape
+ * @return A new unescaped String
.
+ * @see #escapeXml(String)
+ **/
+ public static String unescapeXml(String str) {
+ return unescapeEntities(str, Entities.XML);
+ }
+
+ private static String escapeEntities(String str, Entities entities) {
+ return entities.escape(str);
+ }
+
+ private static String unescapeEntities(String str, Entities entities) {
+ return entities.unescape(str);
+ }
+
+}
+
diff --git a/examples/cl2/src/java/org/apache/commons/lang/StringPrintWriter.java b/examples/cl2/src/java/org/apache/commons/lang/StringPrintWriter.java
new file mode 100644
index 00000000..352cf0de
--- /dev/null
+++ b/examples/cl2/src/java/org/apache/commons/lang/StringPrintWriter.java
@@ -0,0 +1,88 @@
+/* ====================================================================
+ * 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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
+ * + * StringPrintWriter out = new StringPrintWriter(); + * printTo(out); + * System.out.println( out.getString() ); + *+ * @author Alex Chaffee + * @author Scott Stanchfield + **/ +public class StringPrintWriter extends PrintWriter { + public StringPrintWriter() { + super(new StringWriter()); + } + + public StringPrintWriter(int initialSize) { + super(new StringWriter(initialSize)); + } + + /** + * Since toString() returns information *about* this object, we + * want a separate method to extract just the contents of the + * internal buffer as a String. + * @return the contents of the internal string buffer + */ + public String getString() { + flush(); + return ((StringWriter) out).toString(); + } +} + diff --git a/examples/cl2/src/java/org/apache/commons/lang/StringUtils.java b/examples/cl2/src/java/org/apache/commons/lang/StringUtils.java new file mode 100644 index 00000000..1eaad2b4 --- /dev/null +++ b/examples/cl2/src/java/org/apache/commons/lang/StringUtils.java @@ -0,0 +1,2301 @@ +/* ==================================================================== + * 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 acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements 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 + *
Common String
manipulation routines.
Originally from + * Turbine and the + * GenerationJavaCore library.
+ * + * @author Jon S. Stevens + * @author Daniel 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 + * @since 1.0 + * @version $Id: StringUtils.java,v 1.47 2003/06/21 22:24:55 bayard Exp $ + */ +public class StringUtils { + + /** + *The maximum size to which the padding constant(s) can expand.
+ */ + private static int PAD_LIMIT = 8192; + + /** + *A String
containing all blank characters.
Used for efficient blank padding. The length of the string expands as needed.
+ */ + private static String blanks = new String(" "); + + /** + *An array of String
s used for padding.
Used for efficient blank padding. The length of each string expands as needed.
+ */ + private final static String[] padding = new String[Character.MAX_VALUE]; + // String.concat about twice as fast as StringBuffer.append + + /** + *StringUtils
instances should NOT be constructed in
+ * standard programming. Instead, the class should be used as
+ *
StringUtils.trim(" foo ");
.
This constructor is public to permit tools that require a JavaBean + * instance to operate.
+ */ + public StringUtils() { + } + + // Empty + //-------------------------------------------------------------------------- + + /** + *Removes control characters, including whitespace, from both
+ * ends of this String, handling null
by returning
+ * an empty String.
+ * StringUtils.clean("abc") = "abc" + * StringUtils.clean(" abc ") = "abc" + * StringUtils.clean(" ") = "" + * StringUtils.clean("") = "" + * StringUtils.clean(null) = "" + *+ * + * @see java.lang.String#trim() + * @param str the String to check + * @return the trimmed text (never
null
)
+ * @deprecated Use the clearer named {@link #trimToEmpty(String)}.
+ * Method will be removed in Commons Lang 3.0.
+ */
+ public static String clean(String str) {
+ return (str == null ? "" : str.trim());
+ }
+
+ /**
+ * Removes control characters, including whitespace, from both
+ * ends of this String, handling null
by returning
+ * null
.
The string is trimmed using {@link String#trim()}.
+ * + *+ * StringUtils.trim("abc") = "abc" + * StringUtils.trim(" abc ") = "abc" + * StringUtils.trim(" ") = "" + * StringUtils.trim("") = "" + * StringUtils.trim(null) = null + *+ * + * @see java.lang.String#trim() + * @param str the String to be trimmed + * @return the trimmed text (or
null
)
+ */
+ public static String trim(String str) {
+ return (str == null ? null : str.trim());
+ }
+
+ /**
+ * Removes control characters, including whitespace, 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()}.
+ * + *+ * StringUtils.trimToNull("abc") = "abc" + * StringUtils.trimToNull(" abc ") = "abc" + * StringUtils.trimToNull(" ") = null + * StringUtils.trimToNull("") = null + * StringUtils.trimToNull(null) = null + *+ * + * @see java.lang.String#trim() + * @param str the String to be trimmed. + * @return the trimmed string, or null if it's empty or null + */ + public static String trimToNull(String str) { + String ts = trim(str); + return (ts == null || ts.length() == 0 ? null : ts); + } + + /** + *
Removes control characters, including whitespace, 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()}.
+ * + *+ * StringUtils.trimToEmpty("abc") = "abc" + * StringUtils.trimToEmpty(" abc ") = "abc" + * StringUtils.trimToEmpty(" ") = "" + * StringUtils.trimToEmpty("") = "" + * StringUtils.trimToEmpty(null) = "" + *+ * + * @see java.lang.String#trim() + * @param str the String to be trimmed + * @return the trimmed string, or an empty string if it's empty or null + */ + public static String trimToEmpty(String str) { + return (str == null ? "" : str.trim()); + } + + /** + *
Deletes all 'space' characters from a String.
+ * + *Spaces are defined as {' ', '\t', '\r', '\n', '\b'}
+ * in line with the deprecated {@link Character#isSpace(char)}.
Deletes all whitespaces from a String.
+ * + *Whitespace is defined by + * {@link Character#isWhitespace(char)}.
+ * + * @param str String target to delete whitespace from + * @return the String without whitespaces + * @throws NullPointerException + */ + public static String deleteWhitespace(String str) { + StringBuffer buffer = new StringBuffer(); + int sz = str.length(); + for (int i=0; inull
and is
+ * not empty (length > 0
).
+ *
+ * @param str the String to check
+ * @return true if the String is non-null, and not length zero
+ */
+ public static boolean isNotEmpty(String str) {
+ return (str != null && str.length() > 0);
+ }
+
+ /**
+ * Checks if a (trimmed) String is null
or empty.
true
if the String is null
, or
+ * length zero once trimmed
+ */
+ public static boolean isEmpty(String str) {
+ return (str == null || str.trim().length() == 0);
+ }
+
+ // Equals and IndexOf
+ //--------------------------------------------------------------------------
+
+ /**
+ * Compares two Strings, returning true
if they are equal.
null
s are handled without exceptions. Two null
+ * references are considered to be equal. The comparison is case sensitive.
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));
+ }
+
+ /**
+ * Compares two Strings, returning true
if they are equal ignoring
+ * the case.
Nulls
are handled without exceptions. Two null
+ * references are considered equal. Comparison is case insensitive.
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));
+ }
+
+ /**
+ * Find the first index of any of a set of potential substrings.
+ * + *null
String will return -1
.
null
+ */
+ public static int indexOfAny(String str, String[] searchStrs) {
+ if ((str == null) || (searchStrs == null)) {
+ return -1;
+ }
+ int sz = searchStrs.length;
+
+ // String's can't have a MAX_VALUEth index.
+ int ret = Integer.MAX_VALUE;
+
+ int tmp = 0;
+ for (int i = 0; i < sz; i++) {
+ tmp = str.indexOf(searchStrs[i]);
+ if (tmp == -1) {
+ continue;
+ }
+
+ if (tmp < ret) {
+ ret = tmp;
+ }
+ }
+
+ return (ret == Integer.MAX_VALUE) ? -1 : ret;
+ }
+
+ /**
+ * Find the latest index of any of a set of potential substrings.
+ * + *null
string will return -1
.
null
+ */
+ public static int lastIndexOfAny(String str, String[] searchStrs) {
+ if ((str == null) || (searchStrs == null)) {
+ return -1;
+ }
+ int sz = searchStrs.length;
+ int ret = -1;
+ int tmp = 0;
+ for (int i = 0; i < sz; i++) {
+ tmp = str.lastIndexOf(searchStrs[i]);
+ if (tmp > ret) {
+ ret = tmp;
+ }
+ }
+ return ret;
+ }
+
+ // Substring
+ //--------------------------------------------------------------------------
+
+ /**
+ * Gets a substring from the specified string avoiding exceptions.
+ * + *A negative start position can be used to start n
+ * characters from the end of the String.
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.
Gets the leftmost n
characters of a String.
If n
characters are not available, or the
+ * String is null
, the String will be returned without
+ * an exception.
Gets the rightmost n
characters of a String.
If n
characters are not available, or the String
+ * is null
, the String will be returned without an
+ * exception.
Gets n
characters from the middle of a String.
If n
characters are not available, the remainder
+ * of the String will be returned without an exception. If the
+ * String is null
, null
will be returned.
Splits the provided text into a array, using whitespace as the + * separator.
+ * + *The separator is not included in the returned String array.
+ * + * @param str the String to parse + * @return an array of parsed Strings + */ + public static String[] split(String str) { + return split(str, null, -1); + } + + /** + * @see #split(String, String, int) + */ + public static String[] split(String text, String separator) { + return split(text, separator, -1); + } + + /** + *Splits the provided text into a array, based on a given separator.
+ * + *The separator is not included in the returned String array. The
+ * maximum number of splits to perfom can be controlled. A null
+ * separator will cause parsing to be on whitespace.
This is useful for quickly splitting a String directly into
+ * an array of tokens, instead of an enumeration of tokens (as
+ * StringTokenizer
does).
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
+ */
+ public static String[] split(String str, String separator, int max) {
+ StringTokenizer tok = null;
+ if (separator == null) {
+ // Null separator means we're using StringTokenizer's default
+ // delimiter, which comprises all whitespace characters.
+ tok = new StringTokenizer(str);
+ } else {
+ tok = new StringTokenizer(str, separator);
+ }
+
+ int listSize = tok.countTokens();
+ if (max > 0 && listSize > max) {
+ listSize = max;
+ }
+
+ String[] list = new String[listSize];
+ int i = 0;
+ int lastTokenBegin = 0;
+ int lastTokenEnd = 0;
+ while (tok.hasMoreTokens()) {
+ if (max > 0 && i == listSize - 1) {
+ // In the situation where we hit the max yet have
+ // tokens left over in our input, the last list
+ // element gets all remaining text.
+ String endToken = tok.nextToken();
+ lastTokenBegin = str.indexOf(endToken, lastTokenEnd);
+ list[i] = str.substring(lastTokenBegin);
+ break;
+ } else {
+ list[i] = tok.nextToken();
+ lastTokenBegin = str.indexOf(list[i], lastTokenEnd);
+ lastTokenEnd = lastTokenBegin + list[i].length();
+ }
+ i++;
+ }
+ return list;
+ }
+
+ // Joining
+ //--------------------------------------------------------------------------
+ /**
+ * Concatenates elements of an array into a single String.
+ * + *The difference from join is that concatenate has no delimiter.
+ * + * @param array the array of values to concatenate. + * @return the concatenated string. + */ + 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 delimiter is added before or after the list. A
+ * null
separator is the same as a blank String.
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 + * + * @param array the array of values to join together + * @param separator the separator character to use + * @return the joined String + */ + public static String join(Object[] array, char separator) { + int arraySize = array.length; + int bufSize = (arraySize == 0 ? 0 : (array[0].toString().length() + 1) * arraySize); + StringBuffer buf = new StringBuffer(bufSize); + + for (int i = 0; i < arraySize; i++) { + if (i > 0) { + buf.append(separator); + } + buf.append(array[i]); + } + return buf.toString(); + } + + /** + *
Joins the elements of the provided Iterator
into
+ * a single String containing the provided elements.
No delimiter is added before or after the list. A
+ * null
separator is the same as a blank String.
Iterator
of values to join together
+ * @param separator the separator character to use
+ * @return the joined String
+ */
+ public static String join(Iterator iterator, String separator) {
+ StringBuffer buf = new StringBuffer(256); // Java default is 16, probably too small
+ while (iterator.hasNext()) {
+ buf.append(iterator.next());
+ if ((separator != null) && iterator.hasNext()) {
+ buf.append(separator);
+ }
+ }
+ return buf.toString();
+ }
+
+ /**
+ * Joins the elements of the provided Iterator
into
+ * a single String containing the provided elements.
No delimiter is added before or after the list. A
+ *
+ * @param iterator the Iterator
of values to join together
+ * @param separator the separator character to use
+ * @return the joined String
+ */
+ public static String join(Iterator iterator, char separator) {
+ StringBuffer buf = new StringBuffer(256); // Java default is 16, probably too small
+ while (iterator.hasNext()) {
+ buf.append(iterator.next());
+ if (iterator.hasNext()) {
+ buf.append(separator);
+ }
+ }
+ return buf.toString();
+ }
+
+
+
+ // Replacing
+ //--------------------------------------------------------------------------
+
+ /**
+ *
Replace a String with another String inside a larger String, once.
+ * + *A null
reference passed to this method is a no-op.
Replace all occurances of a String within another String.
+ * + *A null
reference passed to this method is a no-op.
Replace a String with another String inside a larger String,
+ * for the first max
values of the search String.
A null
reference passed to this method is a no-op.
-1
if no maximum
+ * @return the text with any replacements processed
+ */
+ public static String replace(String text, String repl, String with, int max) {
+ if (text == null || repl == null || with == null || repl.length() == 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();
+
+ if (--max == 0) {
+ break;
+ }
+ }
+ buf.append(text.substring(start));
+ return buf.toString();
+ }
+
+ /**
+ * Overlay a part of a String with another String.
+ * + * @param text String to do overlaying in + * @param overlay String to overlay + * @param start int to start overlaying at + * @param end int to stop overlaying before + * @return String with overlayed text + * @throws NullPointerException if text or overlay isnull
+ */
+ public static String overlayString(String text, String overlay, int start, int end) {
+ return new StringBuffer(start + overlay.length() + text.length() - end + 1)
+ .append(text.substring(0, start))
+ .append(overlay)
+ .append(text.substring(end))
+ .toString();
+ }
+
+ // Centering
+ //--------------------------------------------------------------------------
+
+ /**
+ * Center a String in a larger String of size n
.
+ * + *
Uses spaces as the value to buffer the String with.
+ * Equivalent to center(str, size, " ")
.
null
+ */
+ public static String center(String str, int size) {
+ return center(str, size, " ");
+ }
+
+ /**
+ * Center a String in a larger String of size n
.
Uses a supplied String as the value to buffer the String with.
+ * + * @param str String to center + * @param size int size of new String + * @param delim String to buffer the new String with + * @return String containing centered String + * @throws NullPointerException if str or delim isnull
+ * @throws ArithmeticException if delim is the empty String
+ */
+ public static String center(String str, int size, String delim) {
+ int sz = str.length();
+ int p = size - sz;
+ if (p < 1) {
+ return str;
+ }
+ str = leftPad(str, sz + p / 2, delim);
+ str = rightPad(str, size, delim);
+ return str;
+ }
+
+ // Chomping
+ //--------------------------------------------------------------------------
+
+ /**
+ * Remove one newline from end of a String if it's there, + * otherwise leave it alone. A newline is "\n", "\r", or "\r\n". + *
+ * Note that this behavior has changed from 1.0. It
+ * now more closely matches Perl chomp. For the previous behavior,
+ * use slice(String).
+ *
+ * @param str String to chomp a newline from
+ * @return String without newline
+ * @throws NullPointerException if str is null
+ */
+ public static String chomp(String str) {
+ if (str.length() == 0) {
+ return str;
+ }
+
+ if (str.length() == 1) {
+ if ("\r".equals(str) || "\n".equals(str)) {
+ return "";
+ }
+ else {
+ return str;
+ }
+ }
+
+ int lastIdx = str.length() - 1;
+ char last = str.charAt(lastIdx);
+
+ if (last == '\n') {
+ if (str.charAt(lastIdx - 1) == '\r') {
+ lastIdx--;
+ }
+ } else if (last == '\r') {
+
+ } else {
+ lastIdx++;
+ }
+ return str.substring(0, lastIdx);
+ }
+
+ /**
+ *
Remove one string (the separator) from the end of another + * string if it's there, otherwise leave it alone. + *
+ *
+ * Note that this behavior has changed from 1.0. It
+ * now more closely matches Perl chomp. For the previous behavior,
+ * use {@link #slice(String,String)}.
+ *
+ * @param str string to chomp from
+ * @param separator separator string
+ * @return String without trailing separator
+ * @throws NullPointerException if str is null
+ */
+ public static String chomp(String str, String separator) {
+ if (str.length() == 0) {
+ return str;
+ }
+ if (str.endsWith(separator)) {
+ return str.substring(0, str.length() - separator.length());
+ }
+ return str;
+ }
+
+ /**
+ *
Remove a newline if and only if it is at the end + * of the supplied String.
+ * + * @param str String to chomp from + * @return String without chomped ending + * @throws NullPointerException if str isnull
+ * @deprecated Use {@link #chomp(String)} instead.
+ * Method will be removed in Commons Lang 3.0.
+ */
+ 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 String to chomp from + * @param sep String to chomp + * @return String without chomped ending + * @throws NullPointerException if str or sep isnull
+ * @deprecated Use {@link #chomp(String,String)} instead.
+ * Method will be removed in Commons Lang 3.0.
+ */
+ public static String chompLast(String str, String sep) {
+ if (str.length() == 0) {
+ return str;
+ }
+ String sub = str.substring(str.length() - sep.length());
+ if (sep.equals(sub)) {
+ return str.substring(0, str.length() - sep.length());
+ } else {
+ return str;
+ }
+ }
+
+ /**
+ * Remove everything and return the last value of a supplied String, and + * everything after it from a String. + * [That makes no sense. Just use sliceRemainder() :-)]
+ * + * @param str String to chomp from + * @param sep String to chomp + * @return String chomped + * @throws NullPointerException if str or sep isnull
+ * @deprecated Use {@link #sliceRemainder(String,String)} instead.
+ * Method will be removed in Commons Lang 3.0.
+ */
+ public static String getChomp(String str, String sep) {
+ int idx = str.lastIndexOf(sep);
+ if (idx == str.length() - sep.length()) {
+ return sep;
+ } else if (idx != -1) {
+ return str.substring(idx);
+ } else {
+ return "";
+ }
+ }
+
+ /**
+ * Remove the first value of a supplied String, and everything before it + * from a String.
+ * + * @param str String to chomp from + * @param sep String to chomp + * @return String without chomped beginning + * @throws NullPointerException if str or sep isnull
+ * @deprecated Use {@link #sliceFirstRemainder(String,String)} instead.
+ * Method will be removed in Commons Lang 3.0.
+ */
+ public static String prechomp(String str, String sep) {
+ int idx = str.indexOf(sep);
+ if (idx != -1) {
+ return str.substring(idx + sep.length());
+ } else {
+ return str;
+ }
+ }
+
+ /**
+ * Remove and return everything before the first value of a + * supplied String from another String.
+ * + * @param str String to chomp from + * @param sep String to chomp + * @return String prechomped + * @throws NullPointerException if str or sep isnull
+ * @deprecated Use {@link #sliceFirst(String,String)} instead.
+ * Method will be removed in Commons Lang 3.0.
+ */
+ public static String getPrechomp(String str, String sep) {
+ int idx = str.indexOf(sep);
+ if (idx != -1) {
+ return str.substring(0, idx + sep.length());
+ } else {
+ return "";
+ }
+ }
+
+ // Chopping
+ //--------------------------------------------------------------------------
+
+ /**
+ * Remove the last character from a String.
+ * + *If the String ends in \r\n
, then remove both
+ * of them.
null
+ */
+ public static String chop(String str) {
+ if ("".equals(str)) {
+ return "";
+ }
+ if (str.length() == 1) {
+ return "";
+ }
+ int lastIdx = str.length() - 1;
+ String ret = str.substring(0, lastIdx);
+ char last = str.charAt(lastIdx);
+ if (last == '\n') {
+ if (ret.charAt(lastIdx - 1) == '\r') {
+ return ret.substring(0, lastIdx - 1);
+ }
+ }
+ return ret;
+ }
+
+ /**
+ * Remove \n
from end of a String if it's there.
+ * If a \r
precedes it, then remove that too.
null
+ * @deprecated Use {@link #chomp(String)} instead.
+ * Method will be removed in Commons Lang 3.0.
+ */
+ public static String chopNewline(String str) {
+ int lastIdx = str.length() - 1;
+ if (lastIdx == 0) {
+ return "";
+ }
+ char last = str.charAt(lastIdx);
+ if (last == '\n') {
+ if (str.charAt(lastIdx - 1) == '\r') {
+ lastIdx--;
+ }
+ } else {
+ lastIdx++;
+ }
+ return str.substring(0, lastIdx);
+ }
+
+
+ // Slicing
+ //--------------------------------------------------------------------------
+
+ /**
+ * Remove the last newline, and everything after it from a String.
+ * (This method was formerly named chomp or chopNewline.) + * + * @param str String to slice the newline from + * @return String without sliced newline + * @throws NullPointerException if str isnull
+ */
+ public static String slice(String str) {
+ return slice(str, "\n");
+ }
+
+ /**
+ * Find the last occurence of a separator String; + * remove it and everything after it.
+ * (This method was formerly named chomp.) + * + * @param str String to slice from + * @param sep String to slice + * @return String without sliced ending + * @throws NullPointerException if str or sep isnull
+ */
+ public static String slice(String str, String sep) {
+ int idx = str.lastIndexOf(sep);
+ if (idx != -1) {
+ return str.substring(0, idx);
+ } else {
+ return str;
+ }
+ }
+
+ /**
+ * Find the last occurence of a separator String, and return + * everything after it.
+ * (This method was formerly named getchomp. Also, now it does not + * include the separator in the return value.) + * + * @param str String to slice from + * @param sep String to slice + * @return String sliced + * @throws NullPointerException if str or sep isnull
+ */
+ public static String sliceRemainder(String str, String sep) {
+ int idx = str.lastIndexOf(sep);
+ if (idx == str.length() - sep.length()) {
+ return "";
+ } else if (idx != -1) {
+ return str.substring(idx + sep.length());
+ } else {
+ return "";
+ }
+ }
+
+ /**
+ * Find the first occurence of a separator String, and return + * everything after it.
+ * (This method was formerly named prechomp. Also, previously + * it included the separator in the return value; now it does not.) + * + * @param str String to slice from + * @param sep String to slice + * @return String without sliced beginning + * @throws NullPointerException if str or sep isnull
+ */
+ public static String sliceFirstRemainder(String str, String sep) {
+ int idx = str.indexOf(sep);
+ if (idx != -1) {
+ return str.substring(idx + sep.length());
+ } else {
+ return str;
+ }
+ }
+
+ /**
+ * Find the first occurence of a separator string; + * return everything before it (but not including the separator).
+ * (This method was formerly named getPrechomp. Also, it used to + * include the separator, but now it does not.) + * + * @param str String to slice from + * @param sep String to slice + * @return String presliced + * @throws NullPointerException if str or sep isnull
+ */
+ public static String sliceFirst(String str, String sep) {
+ int idx = str.indexOf(sep);
+ if (idx != -1) {
+ return str.substring(0, idx);
+ } else {
+ return "";
+ }
+ }
+
+ // Conversion
+ //--------------------------------------------------------------------------
+
+ // spec 3.10.6
+ /**
+ * Escapes any values it finds into their String form.
+ * + *So a tab becomes the characters '\\'
and
+ * 't'
.
As of Lang 2.0, this calls {@link StringEscapeUtils#escapeJava(java.lang.String)} + * behind the scenes. For convenience, this method is not deprecated. + *
+ * @see StringEscapeUtils#escapeJava(java.lang.String) + * @param str String to escape values in + * @return String with escaped values + * @throws NullPointerException if str isnull
+ */
+ public static String escape(String str) {
+ return StringEscapeUtils.escapeJava(str);
+ }
+
+ /**
+ * Unescapes any Java literals found in the String. For example,
+ * it will turn a sequence of '\' and 'n' into a newline character,
+ * unless the '\' is preceded by another '\'.
+ * + * As of Lang 2.0, this calls {@link StringEscapeUtils#unescapeJava(java.lang.String)} + * behind the scenes. For convenience, this method is not deprecated. + *
+ * @see StringEscapeUtils#unescapeJava(java.lang.String) + */ + public static String unescape(String str) { + return StringEscapeUtils.unescapeJava(str); + } + + // Padding + //-------------------------------------------------------------------------- + + /** + *
Repeat a String n
times to form a
+ * new string.
repeat < 0
+ * @throws NullPointerException if str is null
+ */
+ public static String repeat(String str, int repeat) {
+ if (str.length() == 1 && repeat <= PAD_LIMIT) {
+ return padding(repeat, str.charAt(0));
+ }
+
+ StringBuffer buffer = new StringBuffer(repeat * str.length());
+ for (int i = 0; i < repeat; i++) {
+ buffer.append(str);
+ }
+ return buffer.toString();
+ }
+
+ /**
+ * Returns blank padding with a given length.
+ * + * @param repeat number of times to repeat a blank + * @return String with repeated character + * @throws IndexOutOfBoundsException if repeat < 0 + */ + private static String padding(int repeat) { + while (blanks.length() < repeat) { + blanks = blanks.concat(blanks); + } + return blanks.substring(0, repeat); + } + + /** + *Returns padding using the specified delimiter repeated to a given length. + *
+ * + * @param repeat number of times to repeat delim + * @param delim character to repeat + * @return String with repeated character + * @throws NullPointerException if delim isnull
+ * @throws IndexOutOfBoundsException if repeat < 0
+ */
+
+ private static String padding(int repeat, char delim) {
+ if (padding[delim] == null) {
+ padding[delim] = String.valueOf(delim);
+ }
+ while (padding[delim].length() < repeat) {
+ padding[delim] = padding[delim].concat(padding[delim]);
+ }
+ return padding[delim].substring(0, repeat);
+ }
+
+ /**
+ * Right pad a String with spaces.
+ * + *The String is padded to the size of n
.
null
+ */
+ public static String rightPad(String str, int size) {
+ int pads = size - str.length();
+ if (pads <= 0) {
+ return str; // returns original string when possible
+ }
+ if (pads > PAD_LIMIT) {
+ return rightPad(str, size, " ");
+ }
+ return str + padding(pads);
+ }
+
+ /**
+ * Right pad a String with a specified character.
+ * + *The String is padded to the size of n
.
null
+ */
+ public static String rightPad(String str, int size, char delim) {
+ int pads = size - str.length();
+ if (pads <= 0) {
+ return str; // returns original string when possible
+ }
+ if (pads > PAD_LIMIT) {
+ return rightPad(str, size, String.valueOf(delim));
+ }
+ return str + padding(pads, delim);
+ }
+
+ /**
+ * Right pad a String with a specified string.
+ *
+ * The String is padded to the size of n
.
+ *
+ * @param str String to pad out
+ * @param size size to pad to
+ * @param delim String to pad with
+ * @return right padded String or original String if no padding is necessary
+ * @throws NullPointerException if str or delim is null
+ * @throws ArithmeticException if delim is the empty String
+ */
+ public static String rightPad(String str, int size, String delim) {
+ if (delim.length() == 1 && size - str.length() <= PAD_LIMIT) {
+ return rightPad(str, size, delim.charAt(0));
+ }
+
+ size = (size - str.length()) / delim.length();
+ if (size > 0) {
+ str += repeat(delim, size);
+ }
+ return str;
+ }
+
+ /**
+ * Left pad a String with spaces.
+ *
+ * The String is padded to the size of n.
+ *
+ * @param str String to pad out
+ * @param size size to pad to
+ * @return left padded String or original String if no padding is necessary
+ * @throws NullPointerException if str or delim is null
+ */
+ public static String leftPad(String str, int size) {
+ int pads = size - str.length();
+ if (pads <= 0) {
+ return str; // returns original string when possible
+ }
+ if (pads > PAD_LIMIT) {
+ return leftPad(str, size, " ");
+ }
+ return padding(pads).concat(str);
+ }
+
+ /**
+ * Left pad a String with a specified character. Pad to a size of n.
+ *
+ * @param str String to pad out
+ * @param size size to pad to
+ * @param delim character to pad with
+ * @return left padded String or original String if no padding is necessary
+ * @throws NullPointerException if str or delim is null
+ */
+ public static String leftPad(String str, int size, char delim) {
+ int pads = size - str.length();
+ if (pads <= 0) {
+ return str; // returns original string when possible
+ }
+ if (pads > PAD_LIMIT) {
+ return leftPad(str, size, " ");
+ }
+ return padding(pads, delim).concat(str);
+ }
+
+ /**
+ * Left pad a String with a specified string. Pad to a size of n.
+ *
+ * @param str String to pad out
+ * @param size size to pad to
+ * @param delim String to pad with
+ * @return left padded String or original String if no padding is necessary
+ * @throws NullPointerException if str or delim is null
+ * @throws ArithmeticException if delim is the empty string
+ */
+ public static String leftPad(String str, int size, String delim) {
+ if (delim.length() == 1 && size - str.length() <= PAD_LIMIT)
+ return leftPad(str, size, delim.charAt(0));
+ size = (size - str.length()) / delim.length();
+ if (size > 0) {
+ str = repeat(delim, size) + str;
+ }
+ return str;
+ }
+
+ // Stripping
+ //--------------------------------------------------------------------------
+
+ /**
+ * Remove whitespace from the front and back of a String.
+ *
+ * @param str the String to remove whitespace from
+ * @return the stripped String
+ */
+ public static String strip(String str) {
+ return strip(str, null);
+ }
+ /**
+ * Remove a specified String from the front and back of a
+ * String.
+ *
+ * If whitespace is wanted to be removed, used the
+ * {@link #strip(java.lang.String)} method.
+ *
+ * @param str the String to remove a string from
+ * @param delim the String to remove at start and end
+ * @return the stripped String
+ */
+ public static String strip(String str, String delim) {
+ str = stripStart(str, delim);
+ return stripEnd(str, delim);
+ }
+
+ /**
+ * Strip whitespace from the front and back of every String
+ * in the array.
+ *
+ * @param strs the Strings to remove whitespace from
+ * @return the stripped Strings
+ */
+ public static String[] stripAll(String[] strs) {
+ return stripAll(strs, null);
+ }
+
+ /**
+ * Strip the specified delimiter from the front and back of
+ * every String in the array.
+ *
+ * @param strs the Strings to remove a String from
+ * @param delimiter the String to remove at start and end
+ * @return the stripped Strings
+ */
+ public static String[] stripAll(String[] strs, String delimiter) {
+ if ((strs == null) || (strs.length == 0)) {
+ return strs;
+ }
+ int sz = strs.length;
+ String[] newArr = new String[sz];
+ for (int i = 0; i < sz; i++) {
+ newArr[i] = strip(strs[i], delimiter);
+ }
+ return newArr;
+ }
+
+ /**
+ * Strip any of a supplied String from the end of a String.
+ *
+ * If the strip String is null
, whitespace is
+ * stripped.
+ *
+ * @param str the String to remove characters from
+ * @param strip the String to remove
+ * @return the stripped String
+ */
+ public static String stripEnd(String str, String strip) {
+ if (str == null) {
+ return null;
+ }
+ int end = str.length();
+
+ if (strip == null) {
+ while ((end != 0) && Character.isWhitespace(str.charAt(end - 1))) {
+ end--;
+ }
+ } else {
+ while ((end != 0) && (strip.indexOf(str.charAt(end - 1)) != -1)) {
+ end--;
+ }
+ }
+ return str.substring(0, end);
+ }
+
+ /**
+ * Strip any of a supplied String from the start of a String.
+ *
+ * If the strip String is null
, whitespace is
+ * stripped.
+ *
+ * @param str the String to remove characters from
+ * @param strip the String to remove
+ * @return the stripped String
+ */
+ public static String stripStart(String str, String strip) {
+ if (str == null) {
+ return null;
+ }
+
+ int start = 0;
+
+ int sz = str.length();
+
+ if (strip == null) {
+ while ((start != sz) && Character.isWhitespace(str.charAt(start))) {
+ start++;
+ }
+ } else {
+ while ((start != sz) && (strip.indexOf(str.charAt(start)) != -1)) {
+ start++;
+ }
+ }
+ return str.substring(start);
+ }
+
+ // Case conversion
+ //--------------------------------------------------------------------------
+
+ /**
+ * Convert a String to upper case, null
String
+ * returns null
.
+ *
+ * @param str the String to uppercase
+ * @return the upper cased String
+ */
+ public static String upperCase(String str) {
+ if (str == null) {
+ return null;
+ }
+ return str.toUpperCase();
+ }
+
+ /**
+ * Convert a String to lower case, null
String
+ * returns null
.
+ *
+ * @param str the string to lowercase
+ * @return the lower cased String
+ */
+ public static String lowerCase(String str) {
+ if (str == null) {
+ return null;
+ }
+ return str.toLowerCase();
+ }
+
+ /**
+ * Uncapitalise a String.
+ *
+ * That is, convert the first character into lower-case.
+ * null
is returned as null
.
+ *
+ * @param str the String to uncapitalise
+ * @return uncapitalised String
+ */
+ public static String uncapitalise(String str) {
+ if (str == null) {
+ return null;
+ }
+ else if (str.length() == 0) {
+ return "";
+ }
+ else {
+ return new StringBuffer(str.length())
+ .append(Character.toLowerCase(str.charAt(0)))
+ .append(str.substring(1))
+ .toString();
+ }
+ }
+
+ /**
+ * Capitalise a String.
+ *
+ * That is, convert the first character into title-case.
+ * null
is returned as null
.
+ *
+ * @param str the String to capitalise
+ * @return capitalised String
+ */
+ public static String capitalise(String str) {
+ if (str == null) {
+ return null;
+ }
+ else if (str.length() == 0) {
+ return "";
+ }
+ else {
+ return new StringBuffer(str.length())
+ .append(Character.toTitleCase(str.charAt(0)))
+ .append(str.substring(1))
+ .toString();
+ }
+ }
+
+ /**
+ * Swaps the case of String.
+ *
+ * Properly looks after making sure the start of words
+ * are Titlecase and not Uppercase.
+ *
+ * null
is returned as null
.
+ *
+ * @param str the String to swap the case of
+ * @return the modified String
+ */
+ public static String swapCase(String str) {
+ if (str == null) {
+ return null;
+ }
+ int sz = str.length();
+ StringBuffer buffer = new StringBuffer(sz);
+
+ boolean whitespace = false;
+ char ch = 0;
+ char tmp = 0;
+
+ for (int i = 0; i < sz; i++) {
+ ch = str.charAt(i);
+ if (Character.isUpperCase(ch)) {
+ tmp = Character.toLowerCase(ch);
+ } else if (Character.isTitleCase(ch)) {
+ tmp = Character.toLowerCase(ch);
+ } else if (Character.isLowerCase(ch)) {
+ if (whitespace) {
+ tmp = Character.toTitleCase(ch);
+ } else {
+ tmp = Character.toUpperCase(ch);
+ }
+ } else {
+ tmp = ch;
+ }
+ buffer.append(tmp);
+ whitespace = Character.isWhitespace(ch);
+ }
+ return buffer.toString();
+ }
+
+
+ /**
+ * Capitalise all the words in a String.
+ *
+ * Uses {@link Character#isWhitespace(char)} as a
+ * separator between words.
+ *
+ * null
will return null
.
+ *
+ * @param str the String to capitalise
+ * @return capitalised String
+ */
+ public static String capitaliseAllWords(String str) {
+ if (str == null) {
+ return null;
+ }
+ int sz = str.length();
+ StringBuffer buffer = new StringBuffer(sz);
+ boolean space = true;
+ for (int i = 0; i < sz; i++) {
+ char ch = str.charAt(i);
+ if (Character.isWhitespace(ch)) {
+ buffer.append(ch);
+ space = true;
+ } else if (space) {
+ buffer.append(Character.toTitleCase(ch));
+ space = false;
+ } else {
+ buffer.append(ch);
+ }
+ }
+ return buffer.toString();
+ }
+
+ /**
+ * Uncapitalise all the words in a string.
+ *
+ * Uses {@link Character#isWhitespace(char)} as a
+ * separator between words.
+ *
+ * null
will return null
.
+ *
+ * @param str the string to uncapitalise
+ * @return uncapitalised string
+ */
+ public static String uncapitaliseAllWords(String str) {
+ if (str == null) {
+ return null;
+ }
+ int sz = str.length();
+ StringBuffer buffer = new StringBuffer(sz);
+ boolean space = true;
+ for (int i = 0; i < sz; i++) {
+ char ch = str.charAt(i);
+ if (Character.isWhitespace(ch)) {
+ buffer.append(ch);
+ space = true;
+ } else if (space) {
+ buffer.append(Character.toLowerCase(ch));
+ space = false;
+ } else {
+ buffer.append(ch);
+ }
+ }
+ return buffer.toString();
+ }
+
+ // Nested extraction
+ //--------------------------------------------------------------------------
+
+ /**
+ * Get the String that is nested in between two instances of the
+ * same String.
+ *
+ * If str
is null
, will
+ * return null
.
+ *
+ * @param str the String containing nested-string
+ * @param tag the String before and after nested-string
+ * @return the String that was nested, or null
+ * @throws NullPointerException if tag is null
+ */
+ public static String getNestedString(String str, String tag) {
+ return getNestedString(str, tag, tag);
+ }
+
+ /**
+ * Get the String that is nested in between two Strings.
+ *
+ * @param str the String containing nested-string
+ * @param open the String before nested-string
+ * @param close the String after nested-string
+ * @return the String that was nested, or null
+ * @throws NullPointerException if open or close is null
+ */
+ public static String getNestedString(String str, String open, String close) {
+ if (str == null) {
+ return null;
+ }
+ int start = str.indexOf(open);
+ if (start != -1) {
+ int end = str.indexOf(close, start + open.length());
+ if (end != -1) {
+ return str.substring(start + open.length(), end);
+ }
+ }
+ return null;
+ }
+
+ /**
+ * How many times is the substring in the larger String.
+ *
+ * null
returns 0
.
+ *
+ * @param str the String to check
+ * @param sub the substring to count
+ * @return the number of occurances, 0 if the String is null
+ * @throws NullPointerException if sub is null
+ */
+ public static int countMatches(String str, String sub) {
+ if (sub.equals("")) {
+ return 0;
+ }
+ if (str == null) {
+ return 0;
+ }
+ int count = 0;
+ int idx = 0;
+ while ((idx = str.indexOf(sub, idx)) != -1) {
+ count++;
+ idx += sub.length();
+ }
+ return count;
+ }
+
+ // Character Tests
+ //--------------------------------------------------------------------------
+
+ /**
+ * Checks if the String contains only unicode letters.
+ *
+ * null
will return false
.
+ * An empty String will return true
.
+ *
+ * @param str the String to check
+ * @return true
if only contains letters, and is non-null
+ */
+ public static boolean isAlpha(String str) {
+ if (str == null) {
+ return false;
+ }
+ int sz = str.length();
+ for (int i = 0; i < sz; i++) {
+ if (Character.isLetter(str.charAt(i)) == false) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Checks if the String contains only whitespace.
+ *
+ * null
will return false
. An
+ * empty String will return true
.
+ *
+ * @param str the String to check
+ * @return true
if only contains whitespace, and is non-null
+ */
+ public static boolean isWhitespace(String str) {
+ if (str == null) {
+ return false;
+ }
+ int sz = str.length();
+ for (int i = 0; i < sz; i++) {
+ if ((Character.isWhitespace(str.charAt(i)) == false) ) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Checks if the String contains only unicode letters and
+ * space (' '
).
+ *
+ * null
will return false
. An
+ * empty String will return true
.
+ *
+ * @param str the String to check
+ * @return true
if only contains letters and space,
+ * and is non-null
+ */
+ public static boolean isAlphaSpace(String str) {
+ if (str == null) {
+ return false;
+ }
+ int sz = str.length();
+ for (int i = 0; i < sz; i++) {
+ if ((Character.isLetter(str.charAt(i)) == false) &&
+ (str.charAt(i) != ' ')) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Checks if the String contains only unicode letters or digits.
+ *
+ * null
will return false
. An empty
+ * String will return true
.
+ *
+ * @param str the String to check
+ * @return true
if only contains letters or digits,
+ * and is non-null
+ */
+ public static boolean isAlphanumeric(String str) {
+ if (str == null) {
+ return false;
+ }
+ int sz = str.length();
+ for (int i = 0; i < sz; i++) {
+ if (Character.isLetterOrDigit(str.charAt(i)) == false) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Checks if the String contains only unicode letters, digits
+ * or space (' '
).
+ *
+ * null
will return false
. An empty
+ * String will return true
.
+ *
+ * @param str the String to check
+ * @return true
if only contains letters, digits or space,
+ * and is non-null
+ */
+ public static boolean isAlphanumericSpace(String str) {
+ if (str == null) {
+ return false;
+ }
+ int sz = str.length();
+ for (int i = 0; i < sz; i++) {
+ if ((Character.isLetterOrDigit(str.charAt(i)) == false) &&
+ (str.charAt(i) != ' ')) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Checks if the String contains only unicode digits.
+ *
+ * null
will return false
.
+ * An empty String will return true
.
+ *
+ * @param str the String to check
+ * @return true
if only contains digits, and is non-null
+ */
+ public static boolean isNumeric(String str) {
+ if (str == null) {
+ return false;
+ }
+ int sz = str.length();
+ for (int i = 0; i < sz; i++) {
+ if (Character.isDigit(str.charAt(i)) == false) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Checks if the String contains only unicode digits or space
+ * (' '
).
+ *
+ * null
will return false
. An empty
+ * String will return true
.
+ *
+ * @param str the String to check
+ * @return true
if only contains digits or space,
+ * and is non-null
+ */
+ public static boolean isNumericSpace(String str) {
+ if (str == null) {
+ return false;
+ }
+ int sz = str.length();
+ for (int i = 0; i < sz; i++) {
+ if ((Character.isDigit(str.charAt(i)) == false) &&
+ (str.charAt(i) != ' ')) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Checks if the String contains only certain chars.
+ *
+ * @param str the String to check
+ * @param validChars a string of valid chars
+ * @return true if it only contains valid chars and is non-null
+ */
+ public static boolean containsOnly(String str, String validChars) {
+ if (str == null || validChars == null) {
+ return false;
+ }
+ return containsOnly(str, validChars.toCharArray());
+ }
+
+ /**
+ * Checks if the String contains only certain chars.
+ *
+ * @param str the String to check
+ * @param validChars an array of valid chars
+ * @return true if it only contains valid chars and is non-null
+ */
+ /* rewritten
+ public static boolean containsOnly(String str, char[] validChars) {
+ if (str == null || validChars == null) {
+ return false;
+ }
+ int strSize = str.length();
+ int validSize = validChars.length;
+ for (int i = 0; i < strSize; i++) {
+ char ch = str.charAt(i);
+ boolean contains = false;
+ for (int j = 0; j < validSize; j++) {
+ if (validChars[j] == ch) {
+ contains = true;
+ break;
+ }
+ }
+ if (contains == false) {
+ return false;
+ }
+ }
+ return true;
+ }
+ */
+
+ /**
+ * Checks that the String does not contain certain chars.
+ *
+ * @param str the String to check
+ * @param invalidChars a string of invalid chars
+ * @return true if it contains none of the invalid chars, or is null
+ */
+ public static boolean containsNone(String str, String invalidChars) {
+ if (str == null || invalidChars == null) {
+ return true;
+ }
+ return containsNone(str, invalidChars.toCharArray());
+ }
+
+ /**
+ * Checks that the String does not contain certain chars.
+ *
+ * @param str the String to check
+ * @param invalidChars an array of invalid chars
+ * @return true if it contains none of the invalid chars, or is null
+ */
+ public static boolean containsNone(String str, char[] invalidChars) {
+ if (str == null || invalidChars == null) {
+ return true;
+ }
+ int strSize = str.length();
+ int validSize = invalidChars.length;
+ for (int i = 0; i < strSize; i++) {
+ char ch = str.charAt(i);
+ for (int j = 0; j < validSize; j++) {
+ if (invalidChars[j] == ch) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Checks if the String contains only certain chars.
+ *
+ * @param str the String to check
+ * @param valid an array of valid chars
+ * @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) ) {
+ return false;
+ }
+ if(str.length() == 0) {
+ return true;
+ }
+ if(valid.length == 0) {
+ return false;
+ }
+ return indexOfAnyBut(str, valid) == -1;
+ }
+
+ /**
+ * Search a String to find the first index of any
+ * character not in the given set of characters.
+ *
+ * @param str the String to check
+ * @param searchChars the chars to search for
+ * @return the index of any of the chars
+ * @throws NullPointerException if either str or searchChars is null
+ */
+ public static int indexOfAnyBut(String str, char[] searchChars) {
+ if(searchChars == null) {
+ return -1;
+ }
+ return indexOfAnyBut(str, new String(searchChars));
+ }
+
+ /**
+ * Search a String to find the first index of any
+ * character not in the given set of characters.
+ *
+ * @param str the String to check
+ * @param searchChars a String containing the chars to search for
+ * @return the last index of any of the chars
+ * @throws NullPointerException if either str or searchChars is null
+ */
+ public static int indexOfAnyBut(String str, String searchChars) {
+ if (str == null || searchChars == null) {
+ return -1;
+ }
+
+ for (int i = 0; i < str.length(); i ++) {
+ if (searchChars.indexOf(str.charAt(i)) < 0) {
+ return i;
+ }
+ }
+
+ return -1;
+ }
+
+ // Defaults
+ //--------------------------------------------------------------------------
+
+ /**
+ * Returns either the passed in Object
as a String,
+ * or, if the Object
is null
, an empty
+ * String.
+ *
+ * @param obj the Object to check
+ * @return the passed in Object's toString, or blank if it was
+ * null
+ */
+ public static String defaultString(Object obj) {
+ return defaultString(obj, "");
+ }
+
+ /**
+ * Returns either the passed in Object
as a String,
+ * or, if the Object
is null
, a passed
+ * in default String.
+ *
+ * @param obj the Object to check
+ * @param defaultString the default String to return if str is
+ * null
+ * @return the passed in string, or the default if it was
+ * null
+ */
+ public static String defaultString(Object obj, String defaultString) {
+ return (obj == null) ? defaultString : obj.toString();
+ }
+
+ // Reversing
+ //--------------------------------------------------------------------------
+
+ /**
+ * Reverse a String.
+ *
+ * null
String returns null
.
+ *
+ * @param str the String to reverse
+ * @return the reversed String
+ */
+ public static String reverse(String str) {
+ if (str == null) {
+ return null;
+ }
+ return new StringBuffer(str).reverse().toString();
+ }
+
+ /**
+ * Reverses a String that is delimited by a specific character.
+ *
+ * The Strings between the delimiters are not reversed.
+ * Thus java.lang.String becomes String.lang.java (if the delimiter
+ * is '.'
).
+ *
+ * @param str the String to reverse
+ * @param delimiter the delimiter to use
+ * @return the reversed String
+ */
+ public static String reverseDelimitedString(String str, String delimiter) {
+ // could implement manually, but simple way is to reuse other,
+ // probably slower, methods.
+ String[] strs = split(str, delimiter);
+ ArrayUtils.reverse(strs);
+ return join(strs, delimiter);
+ }
+
+ // Abbreviating
+ //--------------------------------------------------------------------------
+
+ /**
+ * Turn "Now is the time for all good men" into "Now is the time for..."
+ *
+ * Specifically:
+ *
+ * If str is less than max characters long, return it.
+ * Else abbreviate it to (substring(str, 0, max-3) + "...").
+ * If maxWidth is less than 3, throw an IllegalArgumentException.
+ * In no case will it return a string of length greater than maxWidth.
+ *
+ * @param maxWidth maximum length of result string
+ */
+ public static String abbreviate(String s, int maxWidth) {
+ return abbreviate(s, 0, maxWidth);
+ }
+
+ /**
+ * Turn "Now is the time for all good men" into "...is the time for..."
+ *
+ * Works like abbreviate(String, int), but allows you to specify a "left edge"
+ * offset. Note that this left edge is not necessarily going to be the leftmost
+ * character in the result, or the first
+ * character following the ellipses, but it will appear somewhere in the result.
+ * In no case will it return a string of length greater than maxWidth.
+ *
+ * @param offset left edge of source string
+ * @param maxWidth maximum length of result string
+ */
+ public static String abbreviate(String s, int offset, int maxWidth) {
+ if (maxWidth < 4)
+ throw new IllegalArgumentException("Minimum abbreviation width is 4");
+ if (s.length() <= maxWidth)
+ return s;
+ if (offset > s.length())
+ offset = s.length();
+ if ((s.length() - offset) < (maxWidth-3))
+ offset = s.length() - (maxWidth-3);
+ if (offset <= 4)
+ return s.substring(0, maxWidth-3) + "...";
+ if (maxWidth < 7)
+ throw new IllegalArgumentException("Minimum abbreviation width with offset is 7");
+ if ((offset + (maxWidth-3)) < s.length())
+ return "..." + abbreviate(s.substring(offset), maxWidth-3);
+ return "..." + s.substring(s.length() - (maxWidth-3));
+ }
+
+ // Difference
+ //--------------------------------------------------------------------------
+
+ /**
+ * Compare two strings, and return the portion where they differ.
+ * (More precisely, return the remainder of the second string,
+ * starting from where it's different from the first.)
+ *
+ * For example, difference("i am a machine", "i am a robot") -> "robot"
+ *
+ * @return the portion of s2 where it differs from s1; returns the empty string ("") if they are equal
+ */
+ public static String difference(String s1, String s2) {
+ int at = differenceAt(s1, s2);
+ if (at == -1) {
+ return "";
+ }
+ return s2.substring(at);
+ }
+
+ /**
+ *
Compare two strings, and return the index at which the strings begin to differ.
+ *
+ * For example, differenceAt("i am a machine", "i am a robot") -> 7
+ *
+ * @return the index where s2 and s1 begin to differ; -1 if they are equal
+ */
+ public static int differenceAt(String s1, String s2) {
+ int i;
+ for (i=0; iFind 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.
+ *
+ * This implemmentation of the levenshtein distance algorithm
+ * is from http://www.merriampark.com/ld.htm
+ *
+ * @param s the first String
+ * @param t the second String
+ * @return result distance
+ * @throws NullPointerException if s or t is null
+ */
+ public static int getLevenshteinDistance(String s, String t) {
+ 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();
+ if (n == 0) {
+ return m;
+ }
+ if (m == 0) {
+ return n;
+ }
+ d = new int[n + 1][m + 1];
+
+ // Step 2
+ for (i = 0; i <= n; i++) {
+ d[i][0] = i;
+ }
+
+ for (j = 0; j <= m; j++) {
+ d[0][j] = j;
+ }
+
+ // Step 3
+ for (i = 1; i <= n; i++) {
+ s_i = s.charAt(i - 1);
+
+ // Step 4
+ for (j = 1; j <= m; j++) {
+ t_j = t.charAt(j - 1);
+
+ // Step 5
+ if (s_i == t_j) {
+ cost = 0;
+ } else {
+ cost = 1;
+ }
+
+ // Step 6
+ d[i][j] = NumberUtils.minimum(d[i - 1][j] + 1, d[i][j - 1] + 1, d[i - 1][j - 1] + cost);
+ }
+ }
+
+ // Step 7
+ return d[n][m];
+ }
+
+}
+
diff --git a/examples/cl2/src/java/org/apache/commons/lang/SystemUtils.java b/examples/cl2/src/java/org/apache/commons/lang/SystemUtils.java
new file mode 100644
index 00000000..4294da13
--- /dev/null
+++ b/examples/cl2/src/java/org/apache/commons/lang/SystemUtils.java
@@ -0,0 +1,815 @@
+/* ====================================================================
+ * 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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
+ * .
+ */
+package org.apache.commons.lang;
+
+/**
+ * Helpers for java.lang.System
.
+ *
+ * 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
.
+ *
+ * @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
+ * @since 1.0
+ * @version $Id: SystemUtils.java,v 1.16 2003/06/08 14:10:54 scolebourne Exp $
+ */
+public class SystemUtils {
+
+ //-----------------------------------------------------------------------
+ /**
+ * 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.
+ *
+ * @since Java version 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.
+ *
+ * @since Java version 1.1.
+ */
+ public static final String FILE_SEPARATOR = getSystemProperty("file.separator");
+
+ //-----------------------------------------------------------------------
+ /**
+ * 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
.
+ */
+ 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
.
+ */
+ 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 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
.
+ */
+ public static final boolean IS_JAVA_1_5 = getJavaVersionMatches("1.5");
+
+ /**
+ * Is true
if this is AIX.
+ *
+ * The field will return false if OS_NAME
is null
.
+ */
+ public static final boolean IS_OS_AIX = getOSMatches("AIX");
+
+ /**
+ * Is true
if this is HP-UX.
+ *
+ * The field will return false if OS_NAME
is null
.
+ */
+ public static final boolean IS_OS_HP_UX = getOSMatches("HP-UX");
+
+ /**
+ * Is true
if this is Irix.
+ *
+ * The field will return false if OS_NAME
is null
.
+ */
+ public static final boolean IS_OS_IRIX = getOSMatches("Irix");
+
+ /**
+ * Is true
if this is Linux.
+ *
+ * The field will return false if OS_NAME
is null
.
+ */
+ public static final boolean IS_OS_LINUX = getOSMatches("Linux") || getOSMatches("LINUX");
+ // Windows XP returns 'Windows 2000' just for fun...
+
+ /**
+ * Is true
if this is Mac.
+ *
+ * The field will return false if OS_NAME
is null
.
+ */
+ public static final boolean IS_OS_MAC = getOSMatches("Mac");
+
+ /**
+ * Is true
if this is Mac.
+ *
+ * The field will return false if OS_NAME
is null
.
+ */
+ public static final boolean IS_OS_MAC_OSX = getOSMatches("Mac OS X");
+
+ /**
+ * Is true
if this is Mac.
+ *
+ * The field will return false if OS_NAME
is null
.
+ */
+ public static final boolean IS_OS_OS2 = getOSMatches("OS/2");
+
+ /**
+ * Is true
if this is Solaris.
+ *
+ * The field will return false if OS_NAME
is null
.
+ */
+ public static final boolean IS_OS_SOLARIS = getOSMatches("Solaris");
+
+ /**
+ * Is true
if this is SunOS.
+ *
+ * The field will return false if OS_NAME
is null
.
+ */
+ public static final boolean IS_OS_SUN_OS = getOSMatches("SunOS");
+
+ //-----------------------------------------------------------------------
+ // OS names from http://www.vamphq.com/os.html
+ // Selected ones included - please advise commons-dev@jakarta.apache.org
+ // if you want another added or a mistake corrected
+
+ /**
+ * Is true
if this is Windows.
+ *
+ * The field will return false if OS_NAME
is null
.
+ */
+ public static final boolean IS_OS_WINDOWS = getOSMatches("Windows");
+
+ /**
+ * Is true
if this is Windows 2000.
+ *
+ * The field will return false if OS_NAME
is null
.
+ */
+ public static final boolean IS_OS_WINDOWS_2000 = getOSMatches("Windows", "5.0");
+
+ /**
+ * Is true
if this is Windows 95.
+ *
+ * The field will return false if OS_NAME
is null
.
+ */
+ 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
+
+ /**
+ * Is true
if this is Windows 98.
+ *
+ * The field will return false if OS_NAME
is null
.
+ */
+ 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
+
+ /**
+ * Is true
if this is Windows ME.
+ *
+ * The field will return false if OS_NAME
is null
.
+ */
+ 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
+
+ /**
+ * Is true
if this is Windows NT.
+ *
+ * The field will return false if OS_NAME
is null
.
+ */
+ public static final boolean IS_OS_WINDOWS_NT = getOSMatches("Windows NT");
+ // Windows 2000 returns 'Windows 2000' but may suffer from same JDK1.2 problem
+
+ /**
+ * Is true
if this is Windows XP.
+ *
+ * The field will return false if OS_NAME
is null
.
+ */
+ public static final boolean IS_OS_WINDOWS_XP = getOSMatches("Windows", "5.1");
+
+ /**
+ * 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.
+ *
+ * @since Java version 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.
+ *
+ * @since Java version 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.
+ *
+ * @since Java version 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.
+ *
+ * @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.
+ *
+ * @since Java 1.1
+ */
+ public static final String JAVA_HOME = getSystemProperty("java.home");
+
+ /**
+ * 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.
+ *
+ * @since Java 1.2
+ */
+ public static final String JAVA_IO_TMPDIR = getSystemProperty("java.io.tmpdir");
+
+ /**
+ * 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.
+ *
+ * @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.
+ *
+ * @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.
+ *
+ * @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.
+ *
+ * @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.
+ *
+ * @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.
+ *
+ * @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.
+ *
+ * @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.
+ *
+ * @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.
+ *
+ * @since Java 1.1
+ */
+ public static final String JAVA_VERSION = getSystemProperty("java.version");
+
+ //-----------------------------------------------------------------------
+ /**
+ * Gets the Java version as a float
.
+ * Example return values:
+ *
+ * 1.2f
for JDK 1.2
+ * 1.31f
for JDK 1.3.1
+ *
+ *
+ * The field will return zero if {@link #JAVA_VERSION} is null
.
+ */
+ public static final float JAVA_VERSION_FLOAT = getJavaVersionAsFloat();
+
+ /**
+ * Gets the Java version as an int
.
+ * Example return values:
+ *
+ * 120
for JDK 1.2
+ * 131
for JDK 1.3.1
+ *
+ *
+ * The field will return zero if {@link #JAVA_VERSION} is null
.
+ */
+ public static final int JAVA_VERSION_INT = getJavaVersionAsInt();
+
+ /**
+ * 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.
+ *
+ * @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.
+ *
+ * @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.
+ *
+ * @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.
+ *
+ * @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.
+ *
+ * @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.
+ *
+ * @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.
+ *
+ * @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.
+ *
+ * @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.
+ *
+ * @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.
+ *
+ * @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.
+ *
+ * @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.
+ *
+ * @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.
+ *
+ * @since Java 1.2
+ */
+ public static final String 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.
+ *
+ * @since Java 1.1
+ */
+ public static final String USER_DIR = getSystemProperty("user.dir");
+
+ /**
+ * 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.
+ *
+ * @since Java 1.1
+ */
+ public static final String USER_HOME = getSystemProperty("user.home");
+
+ /**
+ * 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.
+ *
+ * @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.
+ *
+ * @since Java 1.1
+ */
+ public static final String USER_NAME = getSystemProperty("user.name");
+
+ //-----------------------------------------------------------------------
+ /**
+ * Gets the Java version number as a float
.
+ *
+ * Example return values:
+ *
+ * 1.2f
for JDK 1.2
+ * 1.31f
for JDK 1.3.1
+ *
+ *
+ * @deprecated Use {@link #JAVA_VERSION_FLOAT} instead.
+ * Method will be removed in Commons Lang 3.0.
+ * @return the version, for example 1.31f for JDK 1.3.1
+ */
+ public static float getJavaVersion() {
+ return JAVA_VERSION_FLOAT;
+ }
+
+ /**
+ * Gets the Java version number as a float
.
+ *
+ * Example return values:
+ *
+ * 1.2f
for JDK 1.2
+ * 1.31f
for JDK 1.3.1
+ *
+ *
+ * Patch releases are not reported.
+ * Zero is returned if {@link #JAVA_VERSION} is null
.
+ *
+ * @return the version, for example 1.31f for JDK 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);
+ }
+
+ /**
+ * Gets the Java version number as an int
.
+ *
+ * Example return values:
+ *
+ * 120
for JDK 1.2
+ * 131
for JDK 1.3.1
+ *
+ *
+ * Patch releases are not reported.
+ * Zero is returned if {@link #JAVA_VERSION} is null
.
+ *
+ * @return the version, for example 131 for JDK 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);
+ }
+
+ /**
+ * Decides if the java version matches.
+ *
+ * @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);
+ }
+
+ /**
+ * Decides if the operating system matches.
+ *
+ * @param osNamePrefix the prefix for the os name
+ * @return true if matches, or false if not or can't determine
+ */
+ private static boolean getOSMatches(String osNamePrefix) {
+ if (OS_NAME == null) {
+ return false;
+ }
+ return OS_NAME.startsWith(osNamePrefix);
+ }
+
+ /**
+ * Decides if the operating system matches.
+ *
+ * @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);
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * 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."
+ );
+ return null;
+ }
+ }
+
+ /**
+ * 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
+ *
+ *
+ * @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);
+ }
+
+ /**
+ * 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
+ *
+ *
+ * @param requiredVersion the required version, for example 131
+ * @return true
if the actual version is equal or greater
+ * than the required version
+ */
+ public static boolean isJavaVersionAtLeast(int requiredVersion) {
+ return (JAVA_VERSION_INT >= requiredVersion);
+ }
+
+ /**
+ * 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() {
+ }
+
+}
diff --git a/examples/cl2/src/java/org/apache/commons/lang/UnhandledException.java b/examples/cl2/src/java/org/apache/commons/lang/UnhandledException.java
new file mode 100644
index 00000000..1a76482e
--- /dev/null
+++ b/examples/cl2/src/java/org/apache/commons/lang/UnhandledException.java
@@ -0,0 +1,87 @@
+/* ====================================================================
+ * 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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
+ * .
+ */
+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.
+ *
+ * @author Matthew Hawthorne
+ * @since 2.0
+ * @version $Id: UnhandledException.java,v 1.2 2003/05/16 16:14:17 scolebourne Exp $
+ */
+public class UnhandledException extends NestableRuntimeException {
+
+ /**
+ * Constructs the exception using a cause.
+ *
+ * @param cause the underlying 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);
+ }
+
+}
diff --git a/examples/cl2/src/java/org/apache/commons/lang/WordWrapUtils.java b/examples/cl2/src/java/org/apache/commons/lang/WordWrapUtils.java
new file mode 100644
index 00000000..f7c76961
--- /dev/null
+++ b/examples/cl2/src/java/org/apache/commons/lang/WordWrapUtils.java
@@ -0,0 +1,282 @@
+/* ====================================================================
+ * 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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
+ * .
+ */
+package org.apache.commons.lang;
+
+import java.util.NoSuchElementException;
+import java.util.StringTokenizer;
+
+/**
+ * WordWrapUtils
is a utility class to assist with word wrapping.
+ *
+ * @author Henri Yandell
+ * @author Stephen Colebourne
+ * @author Henning P. Schmiedehausen
+ * @author Gary Gregory
+ * @version $Id: WordWrapUtils.java,v 1.4 2003/06/08 23:27:26 scolebourne Exp $
+ */
+public class WordWrapUtils {
+
+ /**
+ * WordWrapUtils
instances should NOT be constructed in
+ * standard programming. Instead, the class should be used as
+ * WordWrapUtils.wordWrap("foo bar");
.
+ *
+ * This constructor is public to permit tools that require a JavaBean
+ * instance to operate.
+ */
+ public WordWrapUtils() {
+ }
+
+ // Wrapping
+ //--------------------------------------------------------------------------
+
+ /**
+ * Wraps a block of text to a specified line length.
+ *
+ * This method takes a block of text, which might have long lines in it
+ * and wraps the long lines based on the supplied wrapColumn parameter.
+ * It was initially implemented for use by VelocityEmail. If there are tabs
+ * in inString, you are going to get results that are a bit strange,
+ * since tabs are a single character but are displayed as 4 or 8
+ * spaces. Remove the tabs.
+ *
+ * @param str text which is in need of word-wrapping
+ * @param newline the characters that define a newline
+ * @param wrapColumn the column to wrap the words at
+ * @return the text with all the long lines word-wrapped
+ */
+ public static String wrapText(String str, String newline, int wrapColumn) {
+ StringTokenizer lineTokenizer = new StringTokenizer(str, newline, true);
+ StringBuffer stringBuffer = new StringBuffer();
+
+ while (lineTokenizer.hasMoreTokens()) {
+ try {
+ String nextLine = lineTokenizer.nextToken();
+
+ if (nextLine.length() > wrapColumn) {
+ // This line is long enough to be wrapped.
+ nextLine = wrapLine(nextLine, newline, wrapColumn);
+ }
+
+ stringBuffer.append(nextLine);
+
+ } catch (NoSuchElementException nsee) {
+ // thrown by nextToken(), but I don't know why it would
+ break;
+ }
+ }
+
+ return (stringBuffer.toString());
+ }
+
+ /**
+ * Wraps a single line of text.
+ * Called by wrapText() to do the real work of wrapping.
+ *
+ * @param line a line which is in need of word-wrapping
+ * @param newline the characters that define a newline
+ * @param wrapColumn the column to wrap the words at
+ * @return a line with newlines inserted
+ */
+ private static String wrapLine(String line, String newline, int wrapColumn) {
+ StringBuffer wrappedLine = new StringBuffer();
+
+ while (line.length() > wrapColumn) {
+ int spaceToWrapAt = line.lastIndexOf(' ', wrapColumn);
+
+ if (spaceToWrapAt >= 0) {
+ wrappedLine.append(line.substring(0, spaceToWrapAt));
+ wrappedLine.append(newline);
+ line = line.substring(spaceToWrapAt + 1);
+ }
+
+ // This must be a really long word or URL. Pass it
+ // through unchanged even though it's longer than the
+ // wrapColumn would allow. This behavior could be
+ // dependent on a parameter for those situations when
+ // someone wants long words broken at line length.
+ else {
+ spaceToWrapAt = line.indexOf(' ', wrapColumn);
+
+ if (spaceToWrapAt >= 0) {
+ wrappedLine.append(line.substring(0, spaceToWrapAt));
+ wrappedLine.append(newline);
+ line = line.substring(spaceToWrapAt + 1);
+ } else {
+ wrappedLine.append(line);
+ line = "";
+ }
+ }
+ }
+
+ // Whatever is left in line is short enough to just pass through
+ wrappedLine.append(line);
+
+ return (wrappedLine.toString());
+ }
+
+ // Word wrapping
+ //--------------------------------------------------------------------------
+
+ /**
+ * Create a word-wrapped version of a String. Wrap at 80 characters and
+ * use newlines as the delimiter. If a word is over 80 characters long
+ * use a - sign to split it.
+ */
+ public static String wordWrap(String str) {
+ return wordWrap(str, 80, "\n", "-");
+ }
+ /**
+ * Create a word-wrapped version of a String. Wrap at a specified width and
+ * use newlines as the delimiter. If a word is over the width in lenght
+ * use a - sign to split it.
+ */
+ public static String wordWrap(String str, int width) {
+ return wordWrap(str, width, "\n", "-");
+ }
+ /**
+ * Word-wrap a string.
+ *
+ * @param str String to word-wrap
+ * @param width int to wrap at
+ * @param delim String to use to separate lines
+ * @param split String to use to split a word greater than width long
+ *
+ * @return String that has been word wrapped
+ */
+ public static String wordWrap(String str, int width, String delim, String split) {
+ int sz = str.length();
+
+ /// shift width up one. mainly as it makes the logic easier
+ width++;
+
+ // our best guess as to an initial size
+ StringBuffer buffer = new StringBuffer(sz / width * delim.length() + sz);
+
+ // every line will include a delim on the end
+ width = width - delim.length();
+
+ int idx = -1;
+ String substr = null;
+
+ // beware: i is rolled-back inside the loop
+ for (int i = 0; i < sz; i += width) {
+
+ // on the last line
+ if (i > sz - width) {
+ buffer.append(str.substring(i));
+ break;
+ }
+
+ // the current line
+ substr = str.substring(i, i + width);
+
+ // is the delim already on the line
+ idx = substr.indexOf(delim);
+ if (idx != -1) {
+ buffer.append(substr.substring(0, idx));
+ buffer.append(delim);
+ i -= width - idx - delim.length();
+
+ // Erase a space after a delim. Is this too obscure?
+ if(substr.length() > idx + 1) {
+ if (substr.charAt(idx + 1) != '\n') {
+ if (Character.isWhitespace(substr.charAt(idx + 1))) {
+ i++;
+ }
+ }
+ }
+ continue;
+ }
+
+ idx = -1;
+
+ // figure out where the last space is
+ char[] chrs = substr.toCharArray();
+ for (int j = width; j > 0; j--) {
+ if (Character.isWhitespace(chrs[j - 1])) {
+ idx = j;
+ break;
+ }
+ }
+
+ // idx is the last whitespace on the line.
+ if (idx == -1) {
+ for (int j = width; j > 0; j--) {
+ if (chrs[j - 1] == '-') {
+ idx = j;
+ break;
+ }
+ }
+ if (idx == -1) {
+ buffer.append(substr);
+ buffer.append(delim);
+ } else {
+ if (idx != width) {
+ idx++;
+ }
+ buffer.append(substr.substring(0, idx));
+ buffer.append(delim);
+ i -= width - idx;
+ }
+ } else {
+ buffer.append(substr.substring(0, idx));
+ buffer.append(StringUtils.repeat(" ", width - idx));
+ buffer.append(delim);
+ i -= width - idx;
+ }
+ }
+ return buffer.toString();
+ }
+}
diff --git a/examples/cl2/src/java/org/apache/commons/lang/builder/CompareToBuilder.java b/examples/cl2/src/java/org/apache/commons/lang/builder/CompareToBuilder.java
new file mode 100644
index 00000000..e62b1472
--- /dev/null
+++ b/examples/cl2/src/java/org/apache/commons/lang/builder/CompareToBuilder.java
@@ -0,0 +1,901 @@
+/* ====================================================================
+ * 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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
+ * .
+ */
+package org.apache.commons.lang.builder;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.util.Comparator;
+
+import org.apache.commons.lang.NumberUtils;
+/**
+ *
CompareTo
generation routines.
+ *
+ * This class provides methods to build a good compareTo()
+ * method for any class. It is consistent with the equals
and
+ * hashcode
built with {@link EqualsBuilder} and
+ * {@link HashCodeBuilder}.
+ *
+ * Two object that compare equal using equals should normally compare
+ * equals using compareTo
.
+ *
+ * All relevant fields should be included in the calculation of the
+ * comparison. Derived fields may be ignored. The same fields, in the same
+ * order, should be used in both compareTo
and
+ * equals
.
+ *
+ * Typical use for the code is as follows:
+ *
+ * public int compareTo(Object o) {
+ * MyClass rhs = (MyClass) o;
+ * return new CompareToBuilder()
+ * .appendSuper(super.compareTo(o)
+ * .append(field1, rhs.field1)
+ * .append(field2, rhs.field2)
+ * .append(field3, rhs.field3)
+ * .toComparison();
+ * }
+ *
+ *
+ * Alternatively, there is a method that uses reflection to determine
+ * the fields to test. Because these fields are usually private, the method,
+ * reflectionCompare
, uses Field.setAccessible
to change
+ * the visibility of the fields. This will fail under a security manager,
+ * unless the appropriate permissions are set. It is also slower than testing
+ * explicitly.
+ *
+ * A typical invocation for this method would look like:
+ *
+ * public int compareTo(Object o) {
+ * return CompareToBuilder.reflectionCompare(this, obj);
+ * }
+ *
+ *
+ * @author Steve Downey
+ * @author Stephen Colebourne
+ * @author Gary Gregory
+ * @since 1.0
+ * @version $Id: CompareToBuilder.java,v 1.14 2003/04/18 09:12:16 ggregory Exp $
+ */
+public class CompareToBuilder {
+
+ /**
+ * If the fields tested are equals.
+ */
+ private int comparison;
+
+ /**
+ * Constructor for CompareToBuilder.
+ *
+ * Starts off assuming that the objects are equal. Multiple calls are
+ * then made to the various append methods, followed by a call to
+ * {@link #toComparison} to get the result.
+ */
+ public CompareToBuilder() {
+ super();
+ comparison = 0;
+ }
+
+ //-------------------------------------------------------------------------
+
+ /**
+ * This method uses reflection to determine the ordering between two
+ * Objects.
+ *
+ * It uses Field.setAccessible
to gain access to private
+ * fields. This means that it will throw a security exception if run under
+ * a security manger, 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
+ * @return a negative integer, zero, or a positive integer as this
+ * Object is less than, equal to, or greater than the specified Object.
+ * @throws NullPointerException if either (but not both) parameter is
+ * null
+ * @throws ClassCastException if the specified Object's type prevents it
+ * from being compared to this Object.
+ */
+ public static int reflectionCompare(Object lhs, Object rhs) {
+ return reflectionCompare(lhs, rhs, false, null);
+ }
+
+ /**
+ * This method uses reflection to determine if the two Objects are
+ * equal.
+ *
+ * It uses Field.setAccessible
to gain access to private
+ * fields. This means that it will throw a security exception if run under
+ * a security manger, if the permissions are not set up correctly. It is
+ * also not as efficient as testing explicitly.
+ *
+ * If the testTransients
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 lhs this
object
+ * @param rhs the other object
+ * @param testTransients whether to include transient fields
+ * @return a negative integer, zero, or a positive integer as this
+ * Object is less than, equal to, or greater than the specified Object.
+ * @throws NullPointerException if either (but not both) parameter is
+ * null
+ * @throws ClassCastException if the specified Object's type prevents it
+ * from being compared to this Object.
+ */
+ public static int reflectionCompare(Object lhs, Object rhs, boolean testTransients) {
+ return reflectionCompare(lhs, rhs, testTransients, null);
+ }
+
+ /**
+ * This method uses reflection to determine if the two Objects are
+ * equal.
+ *
+ * It uses Field.setAccessible
to gain access to private
+ * fields. This means that it will throw a security exception if run under
+ * a security manger, if the permissions are not set up correctly. It is
+ * also not as efficient as testing explicitly.
+ *
+ * If the testTransients
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
+ * @return a negative integer, zero, or a positive integer as this
+ * Object is less than, equal to, or greater than the specified Object.
+ * @throws NullPointerException if either (but not both) parameter is
+ * null
+ * @throws ClassCastException if the specified Object's type prevents it
+ * from being compared to this Object.
+ */
+ public static int reflectionCompare(Object lhs, Object rhs, boolean testTransients, Class reflectUpToClass) {
+ if (lhs == rhs) {
+ return 0;
+ }
+ if (lhs == null || rhs == null) {
+ throw new NullPointerException();
+ }
+ Class c1 = lhs.getClass();
+ if (!c1.isInstance(rhs)) {
+ throw new ClassCastException();
+ }
+ CompareToBuilder compareToBuilder = new CompareToBuilder();
+ reflectionAppend(lhs, rhs, c1, compareToBuilder, testTransients);
+ while (c1.getSuperclass() != null && c1 != reflectUpToClass) {
+ c1 = c1.getSuperclass();
+ reflectionAppend(lhs, rhs, c1, compareToBuilder, testTransients);
+ }
+ return compareToBuilder.toComparison();
+ }
+
+ /**
+ * Appends the fields and values defined by the given object of the
+ * given Class.
+ *
+ * @param lhs the left hand object
+ * @param rhs the right hand object
+ * @param clazz the class to append details of
+ * @param builder the builder to append to
+ * @param useTransients whether to test transient fields
+ */
+ private static void reflectionAppend(
+ Object lhs,
+ Object rhs,
+ Class clazz,
+ CompareToBuilder builder,
+ boolean useTransients) {
+ Field[] fields = clazz.getDeclaredFields();
+ Field.setAccessible(fields, true);
+ for (int i = 0; i < fields.length && builder.comparison == 0; i++) {
+ Field f = fields[i];
+ if ((f.getName().indexOf('$') == -1)
+ && (useTransients || !Modifier.isTransient(f.getModifiers()))
+ && (!Modifier.isStatic(f.getModifiers()))) {
+ try {
+ builder.append(f.get(lhs), f.get(rhs));
+ } 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");
+ }
+ }
+ }
+ }
+
+ //-------------------------------------------------------------------------
+
+ /**
+ * Adds the result of super.hashCode() to this builder.
+ *
+ * @param superHashCode the result of calling super.equals()
+ * @return CompareToBuilder - used to chain calls.
+ */
+ public CompareToBuilder appendSuper(int superHashCode) {
+ if (comparison != 0) {
+ return this;
+ }
+ comparison = superHashCode;
+ return this;
+ }
+
+ //-------------------------------------------------------------------------
+
+ /**
+ * Comparison of two Object references.
+ *
+ * - Check if Objects are same using
==
+ * - Check if either is null, a null object is less than a non-null
+ *
- Check the object contents
+ *
+ *
+ * The first parameter to be compared must either be an array or implement
+ * Comparable.
+ *
+ * @param lhs the Object from this
object
+ * @param rhs the Object from the other object
+ * @return CompareToBuilder - used to chain calls.
+ * @throws ClassCastException if the specified Object's type prevents it
+ * from being compared to this Object.
+ */
+ public CompareToBuilder append(Object lhs, Object rhs) {
+ return append(lhs, rhs, null);
+ }
+
+ /**
+ * Comparison of two Object references.
+ *
+ * - Check if Objects are same using
==
+ * - Check if either is null, a null object is less than a non-null
+ *
- Check the object contents
+ *
+ *
+ * If the first parameter to be compared is an array, the array methods will
+ * be used. Otherwise the comparator will be used. If the comparator is null,
+ * the lhs
will be cast to Comparable.
+ *
+ * @param lhs the Object from this
object
+ * @param rhs the Object from the other object
+ * @param comparator the comparator to use to compare the objects,
+ * null
means to treat the lhs
as Comparable
.
+ * @return CompareToBuilder - used to chain calls.
+ * @throws ClassCastException if the specified Object's type prevents it
+ * from being compared to this Object.
+ */
+ public CompareToBuilder append(Object lhs, Object rhs, Comparator comparator) {
+ if (comparison != 0) {
+ return this;
+ }
+ if (lhs == rhs) {
+ return this;
+ }
+ if (lhs == null) {
+ comparison = -1;
+ return this;
+ }
+ if (rhs == null) {
+ comparison = +1;
+ return this;
+ }
+ Class lhsClass = lhs.getClass();
+ if (lhsClass.isArray()) {
+ // 'Switch' on type of array, to dispatch to the correct handler
+ // This handles multi dimensional arrays
+ // this could throw a ClassCastException is rhs is not the correct array type
+ 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
+ // this could throw a ClassCastException is rhs is not an array
+ append((Object[]) lhs, (Object[]) rhs, comparator);
+ }
+ } else {
+ // the simple case, not an array, just test the element
+ if (comparator == null) {
+ comparison = ((Comparable) lhs).compareTo(rhs);
+ } else {
+ comparison = comparator.compare(lhs, rhs);
+ }
+ }
+ return this;
+ }
+
+ /**
+ * Test if two long
s are <, > or ==.
+ *
+ * @param lhs the long
from this
object
+ * @param rhs the long
from the other object
+ * @return CompareToBuilder - used to chain calls.
+ */
+ public CompareToBuilder append(long lhs, long rhs) {
+ if (comparison != 0) {
+ return this;
+ }
+ comparison = ((lhs < rhs) ? -1 : ((lhs > rhs) ? 1 : 0));
+ return this;
+ }
+
+ /**
+ * Test if two int
s are <, > or ==.
+ *
+ * @param lhs the int
from this
object
+ * @param rhs the int
from the other object
+ * @return CompareToBuilder - used to chain calls.
+ */
+ public CompareToBuilder append(int lhs, int rhs) {
+ if (comparison != 0) {
+ return this;
+ }
+ comparison = ((lhs < rhs) ? -1 : ((lhs > rhs) ? 1 : 0));
+ return this;
+ }
+
+ /**
+ * Test if two short
s are <, > or ==.
+ *
+ * @param lhs the short
from this
object
+ * @param rhs the short
from the other object
+ * @return CompareToBuilder - used to chain calls.
+ */
+ public CompareToBuilder append(short lhs, short rhs) {
+ if (comparison != 0) {
+ return this;
+ }
+ comparison = ((lhs < rhs) ? -1 : ((lhs > rhs) ? 1 : 0));
+ return this;
+ }
+
+ /**
+ * Test if two char
s are <, > or ==.
+ *
+ * @param lhs the char
from this
object
+ * @param rhs the char
from the other object
+ * @return CompareToBuilder - used to chain calls.
+ */
+ public CompareToBuilder append(char lhs, char rhs) {
+ if (comparison != 0) {
+ return this;
+ }
+ comparison = ((lhs < rhs) ? -1 : ((lhs > rhs) ? 1 : 0));
+ return this;
+ }
+
+ /**
+ * Test if two byte
s are <, > or ==.
+ *
+ * @param lhs the byte
from this
object
+ * @param rhs the byte
from the other object
+ * @return CompareToBuilder - used to chain calls.
+ */
+ public CompareToBuilder append(byte lhs, byte rhs) {
+ if (comparison != 0) {
+ return this;
+ }
+ comparison = ((lhs < rhs) ? -1 : ((lhs > rhs) ? 1 : 0));
+ return this;
+ }
+
+ /**
+ * Test if two double
s are <, > or ==.
+ *
+ * This handles NaNs, Infinties, and -0.0
.
+ *
+ * It is compatible with the hash code generated by
+ * HashCodeBuilder
.
+ *
+ * @param lhs the double
from this
object
+ * @param rhs the double
from the other object
+ * @return CompareToBuilder - used to chain calls.
+ */
+ public CompareToBuilder append(double lhs, double rhs) {
+ if (comparison != 0) {
+ return this;
+ }
+ comparison = NumberUtils.compare(lhs, rhs);
+ return this;
+ }
+
+ /**
+ * Test if two float
s are <, > or ==.
+ *
+ * This handles NaNs, Infinties, and -0.0
.
+ *
+ * It is compatible with the hash code generated by
+ * HashCodeBuilder
.
+ *
+ * @param lhs the float
from this
object
+ * @param rhs the float
from the other object
+ * @return CompareToBuilder - used to chain calls.
+ */
+ public CompareToBuilder append(float lhs, float rhs) {
+ if (comparison != 0) {
+ return this;
+ }
+ comparison = NumberUtils.compare(lhs, rhs);
+ return this;
+ }
+
+ /**
+ * Test if two booleans
s are <, > or ==.
+ *
+ * @param lhs the boolean
from this
object
+ * @param rhs the boolean
from the other object
+ * @return CompareToBuilder - used to chain calls.
+ */
+ public CompareToBuilder append(boolean lhs, boolean rhs) {
+ if (comparison != 0) {
+ return this;
+ }
+ if (lhs == rhs) {
+ return this;
+ }
+ if (lhs == false) {
+ comparison = -1;
+ } else {
+ comparison = +1;
+ }
+ return this;
+ }
+
+ /**
+ * Deep comparison of an Object
array.
+ *
+ * - Check if arrays are same using
==
+ * - Check if either is null, a null array is less than a non-null
+ *
- Check array length, a short length array is less than a long length array
+ *
- Check array contents element by element using {@link #append(long, long)}
+ *
+ *
+ * This method will also will be called for the top level of multi-dimensional,
+ * ragged, and multi-typed arrays.
+ *
+ * @param lhs array from this
object
+ * @param rhs array from the other object
+ * @return CompareToBuilder - used to chain calls.
+ * @throws ClassCastException if the specified Object's type prevents it
+ * from being compared to this Object.
+ */
+ public CompareToBuilder append(Object[] lhs, Object[] rhs) {
+ return append(lhs, rhs, null);
+ }
+
+ /**
+ * Deep comparison of an Object
array.
+ *
+ * - Check if arrays are same using
==
+ * - Check if either is null, a null array is less than a non-null
+ *
- Check array length, a shorter length array is less than a longer length array
+ *
- Check array contents element by element using {@link #append(Object, Object, Comparator)}
+ *
+ *
+ * This method will also will be called for the top level of multi-dimensional,
+ * ragged, and multi-typed arrays.
+ *
+ * @param lhs array from this
object
+ * @param rhs array from the other object
+ * @param comparator the comparator to use to compare the objects,
+ * null
means to treat the lhs
as Comparable
.
+ * @return CompareToBuilder - used to chain calls.
+ * @throws ClassCastException if the specified Object's type prevents it
+ * from being compared to this Object.
+ */
+ public CompareToBuilder append(Object[] lhs, Object[] rhs, Comparator comparator) {
+ if (comparison != 0) {
+ return this;
+ }
+ if (lhs == rhs) {
+ return this;
+ }
+ if (lhs == null) {
+ comparison = -1;
+ return this;
+ }
+ if (rhs == null) {
+ comparison = +1;
+ return this;
+ }
+ if (lhs.length != rhs.length) {
+ comparison = (lhs.length < rhs.length) ? -1 : +1;
+ return this;
+ }
+ for (int i = 0; i < lhs.length && comparison == 0; i++) {
+ append(lhs[i], rhs[i], comparator);
+ }
+ return this;
+ }
+
+ /**
+ * Deep comparison of a long
array.
+ *
+ * - Check if arrays are same using
==
+ * - Check if either is null, a null array is less than a non-null
+ *
- Check array length, a shorter length array is less than a longer length array
+ *
- Check array contents element by element using {@link #append(long, long)}
+ *
+ *
+ * @param lhs array from this
object
+ * @param rhs array from the other object
+ * @return CompareToBuilder - used to chain calls.
+ */
+ public CompareToBuilder append(long[] lhs, long[] rhs) {
+ if (comparison != 0) {
+ return this;
+ }
+ if (lhs == rhs) {
+ return this;
+ }
+ if (lhs == null) {
+ comparison = -1;
+ return this;
+ }
+ if (rhs == null) {
+ comparison = +1;
+ return this;
+ }
+ if (lhs.length != rhs.length) {
+ comparison = (lhs.length < rhs.length) ? -1 : +1;
+ return this;
+ }
+ for (int i = 0; i < lhs.length && comparison == 0; i++) {
+ append(lhs[i], rhs[i]);
+ }
+ return this;
+ }
+
+ /**
+ * Deep comparison of an int
array.
+ *
+ * - Check if arrays are same using
==
+ * - Check if either is null, a null array is less than a non-null
+ *
- Check array length, a shorter length array is less than a longer length array
+ *
- Check array contents element by element using {@link #append(int, int)}
+ *
+ *
+ * @param lhs array from this
object
+ * @param rhs array from the other object
+ * @return CompareToBuilder - used to chain calls.
+ */
+ public CompareToBuilder append(int[] lhs, int[] rhs) {
+ if (comparison != 0) {
+ return this;
+ }
+ if (lhs == rhs) {
+ return this;
+ }
+ if (lhs == null) {
+ comparison = -1;
+ return this;
+ }
+ if (rhs == null) {
+ comparison = +1;
+ return this;
+ }
+ if (lhs.length != rhs.length) {
+ comparison = (lhs.length < rhs.length) ? -1 : +1;
+ return this;
+ }
+ for (int i = 0; i < lhs.length && comparison == 0; i++) {
+ append(lhs[i], rhs[i]);
+ }
+ return this;
+ }
+
+ /**
+ * Deep comparison of a short
array.
+ *
+ * - Check if arrays are same using
==
+ * - Check if either is null, a null array is less than a non-null
+ *
- Check array length, a shorter length array is less than a longer length array
+ *
- Check array contents element by element using {@link #append(short, short)}
+ *
+ *
+ * @param lhs array from this
object
+ * @param rhs array from the other object
+ * @return CompareToBuilder - used to chain calls.
+ */
+ public CompareToBuilder append(short[] lhs, short[] rhs) {
+ if (comparison != 0) {
+ return this;
+ }
+ if (lhs == rhs) {
+ return this;
+ }
+ if (lhs == null) {
+ comparison = -1;
+ return this;
+ }
+ if (rhs == null) {
+ comparison = +1;
+ return this;
+ }
+ if (lhs.length != rhs.length) {
+ comparison = (lhs.length < rhs.length) ? -1 : +1;
+ return this;
+ }
+ for (int i = 0; i < lhs.length && comparison == 0; i++) {
+ append(lhs[i], rhs[i]);
+ }
+ return this;
+ }
+
+ /**
+ * Deep comparison of a char
array.
+ *
+ * - Check if arrays are same using
==
+ * - Check if either is null, a null array is less than a non-null
+ *
- Check array length, a shorter length array is less than a longer length array
+ *
- Check array contents element by element using {@link #append(char, char)}
+ *
+ *
+ * @param lhs array from this
object
+ * @param rhs array from the other object
+ * @return CompareToBuilder - used to chain calls.
+ */
+ public CompareToBuilder append(char[] lhs, char[] rhs) {
+ if (comparison != 0) {
+ return this;
+ }
+ if (lhs == rhs) {
+ return this;
+ }
+ if (lhs == null) {
+ comparison = -1;
+ return this;
+ }
+ if (rhs == null) {
+ comparison = +1;
+ return this;
+ }
+ if (lhs.length != rhs.length) {
+ comparison = (lhs.length < rhs.length) ? -1 : +1;
+ return this;
+ }
+ for (int i = 0; i < lhs.length && comparison == 0; i++) {
+ append(lhs[i], rhs[i]);
+ }
+ return this;
+ }
+
+ /**
+ * Deep comparison of a byte
array.
+ *
+ * - Check if arrays are same using
==
+ * - Check if either is null, a null array is less than a non-null
+ *
- Check array length, a shorter length array is less than a longer length array
+ *
- Check array contents element by element using {@link #append(byte, byte)}
+ *
+ *
+ * @param lhs array from this
object
+ * @param rhs array from the other object
+ * @return CompareToBuilder - used to chain calls.
+ */
+ public CompareToBuilder append(byte[] lhs, byte[] rhs) {
+ if (comparison != 0) {
+ return this;
+ }
+ if (lhs == rhs) {
+ return this;
+ }
+ if (lhs == null) {
+ comparison = -1;
+ return this;
+ }
+ if (rhs == null) {
+ comparison = +1;
+ return this;
+ }
+ if (lhs.length != rhs.length) {
+ comparison = (lhs.length < rhs.length) ? -1 : +1;
+ return this;
+ }
+ for (int i = 0; i < lhs.length && comparison == 0; i++) {
+ append(lhs[i], rhs[i]);
+ }
+ return this;
+ }
+
+ /**
+ * Deep comparison of a double
array.
+ *
+ * - Check if arrays are same using
==
+ * - Check if either is null, a null array is less than a non-null
+ *
- Check array length, a shorter length array is less than a longer length array
+ *
- Check array contents element by element using {@link #append(double, double)}
+ *
+ *
+ * @param lhs array from this
object
+ * @param rhs array from the other object
+ * @return CompareToBuilder - used to chain calls.
+ */
+ public CompareToBuilder append(double[] lhs, double[] rhs) {
+ if (comparison != 0) {
+ return this;
+ }
+ if (lhs == rhs) {
+ return this;
+ }
+ if (lhs == null) {
+ comparison = -1;
+ return this;
+ }
+ if (rhs == null) {
+ comparison = +1;
+ return this;
+ }
+ if (lhs.length != rhs.length) {
+ comparison = (lhs.length < rhs.length) ? -1 : +1;
+ return this;
+ }
+ for (int i = 0; i < lhs.length && comparison == 0; i++) {
+ append(lhs[i], rhs[i]);
+ }
+ return this;
+ }
+
+ /**
+ * Deep comparison of a float
array.
+ *
+ * - Check if arrays are same using
==
+ * - Check if either is null, a null array is less than a non-null
+ *
- Check array length, a shorter length array is less than a longer length array
+ *
- Check array contents element by element using {@link #append(float, float)}
+ *
+ *
+ * @param lhs array from this
object
+ * @param rhs array from the other object
+ * @return CompareToBuilder - used to chain calls.
+ */
+ public CompareToBuilder append(float[] lhs, float[] rhs) {
+ if (comparison != 0) {
+ return this;
+ }
+ if (lhs == rhs) {
+ return this;
+ }
+ if (lhs == null) {
+ comparison = -1;
+ return this;
+ }
+ if (rhs == null) {
+ comparison = +1;
+ return this;
+ }
+ if (lhs.length != rhs.length) {
+ comparison = (lhs.length < rhs.length) ? -1 : +1;
+ return this;
+ }
+ for (int i = 0; i < lhs.length && comparison == 0; i++) {
+ append(lhs[i], rhs[i]);
+ }
+ return this;
+ }
+
+ /**
+ * Deep comparison of a boolean/code> array.
+ *
+ * - Check if arrays are same using
==
+ * - Check if either is null, a null array is less than a non-null
+ *
- Check array length, a shorter length array is less than a longer length array
+ *
- Check array contents element by element using {@link #append(boolean, boolean)}
+ *
+ *
+ * @param lhs array from this
object
+ * @param rhs array from the other object
+ * @return CompareToBuilder - used to chain calls.
+ */
+ public CompareToBuilder append(boolean[] lhs, boolean[] rhs) {
+ if (comparison != 0) {
+ return this;
+ }
+ if (lhs == rhs) {
+ return this;
+ }
+ if (lhs == null) {
+ comparison = -1;
+ return this;
+ }
+ if (rhs == null) {
+ comparison = +1;
+ return this;
+ }
+ if (lhs.length != rhs.length) {
+ comparison = (lhs.length < rhs.length) ? -1 : +1;
+ return this;
+ }
+ for (int i = 0; i < lhs.length && comparison == 0; i++) {
+ append(lhs[i], rhs[i]);
+ }
+ return this;
+ }
+
+ /**
+ * Return a negative integer if the Object is less than, a positive
+ * integer if the Object is greater than, or 0
if the
+ * Object is equal.
+ *
+ * @return int - a negative integer, zero, or a positive integer as this
+ * Object is less than, equal to, or greater than the specified Object.
+ */
+ public int toComparison() {
+ return comparison;
+ }
+
+}
+
diff --git a/examples/cl2/src/java/org/apache/commons/lang/builder/EqualsBuilder.java b/examples/cl2/src/java/org/apache/commons/lang/builder/EqualsBuilder.java
new file mode 100644
index 00000000..657b1c82
--- /dev/null
+++ b/examples/cl2/src/java/org/apache/commons/lang/builder/EqualsBuilder.java
@@ -0,0 +1,772 @@
+/* ====================================================================
+ * 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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
+ * .
+ */
+package org.apache.commons.lang.builder;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+/**
+ *
Equals
generation routines.
+ *
+ * This class provides methods to build a good equals method for any
+ * class. It follows rules laid out in
+ * Effective Java
+ * , by Joshua Bloch. In particular the rule for comparing doubles
,
+ * floats
, and arrays can be tricky. Also, making sure that
+ * equals()
and hashCode()
are consistent can be
+ * difficult.
+ *
+ * Two Object that compare as equals must generate the same hash code.
+ * But two Objects with the same hash code do not have to be equal.
+ *
+ * All relevant fields should be included in the calculation of equals.
+ * Derived fields may be ignored. In particular, any field used in
+ * generating a hash code must be used in the equals method, and vice
+ * versa.
+ *
+ * Typical use for the code is as follows:
+ *
+ * public boolean equals(Object o) {
+ * if ( !(o instanceof MyClass) ) {
+ * return false;
+ * }
+ * MyClass rhs = (MyClass) o;
+ * return new EqualsBuilder()
+ * .appendSuper(super.equals(o))
+ * .append(field1, rhs.field1)
+ * .append(field2, rhs.field2)
+ * .append(field3, rhs.field3)
+ * .isEquals();
+ * }
+ *
+ *
+ * Alternatively, there is a method that uses reflection to determine
+ * the fields to test. Because these fields are usually private, the method,
+ * reflectionEquals
, uses Field.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 boolean equals(Object o) {
+ * return EqualsBuilder.reflectionEquals(this, o);
+ * }
+ *
+ *
+ * @author Steve Downey
+ * @author Stephen Colebourne
+ * @author Gary Gregory
+ * @since 1.0
+ * @version $Id: EqualsBuilder.java,v 1.13 2003/04/18 09:12:16 ggregory Exp $
+ */
+public class EqualsBuilder {
+ /**
+ * If the fields tested are equals.
+ */
+ private boolean isEquals;
+
+ /**
+ * Constructor for EqualsBuilder.
+ *
+ * Starts off assuming that equals is true
.
+ * @see java.lang.Object#Object()
+ */
+ public EqualsBuilder() {
+ super();
+ isEquals = true;
+ }
+
+ //-------------------------------------------------------------------------
+
+ /**
+ * This method uses reflection to determine if the two Object are equal.
+ *
+ * It uses Field.setAccessible
to gain access to private
+ * fields. This means that it will throw a security exception if run under
+ * a security manger, 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
+ * @return true
if the two Objects have tested equals.
+ */
+ public static boolean reflectionEquals(Object lhs, Object rhs) {
+ return reflectionEquals(lhs, rhs, false, null);
+ }
+
+ /**
+ * This method uses reflection to determine if the two Object are equal.
+ *
+ * It uses Field.setAccessible
to gain access to private
+ * fields. This means that it will throw a security exception if run under
+ * a security manger, 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 lhs this
object
+ * @param rhs the other object
+ * @param testTransients whether to include transient fields
+ * @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);
+ }
+
+ /**
+ * This method uses reflection to determine if the two Object are equal.
+ *
+ * It uses Field.setAccessible
to gain access to private
+ * fields. This means that it will throw a security exception if run under
+ * a security manger, 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
+ * @return true
if the two Objects have tested equals.
+ */
+ public static boolean reflectionEquals(Object lhs, Object rhs, boolean testTransients, Class reflectUpToClass) {
+ if (lhs == rhs) {
+ return true;
+ }
+ if (lhs == null || rhs == null) {
+ return false;
+ }
+ // Find the leaf class since there may be transients in the leaf
+ // class or in classes between the leaf and root.
+ // If we are not testing transients or a subclass has no ivars,
+ // then a subclass can test equals to a superclass.
+ Class lhsClass = lhs.getClass();
+ Class rhsClass = rhs.getClass();
+ Class testClass;
+ if (lhsClass.isInstance(rhs)) {
+ testClass = lhsClass;
+ if (!rhsClass.isInstance(lhs)) {
+ // rhsClass is a subclass of lhsClass
+ testClass = rhsClass;
+ }
+ } else if (rhsClass.isInstance(lhs)) {
+ testClass = rhsClass;
+ if (!lhsClass.isInstance(rhs)) {
+ // lhsClass is a subclass of rhsClass
+ testClass = lhsClass;
+ }
+ } else {
+ // The two classes are not related.
+ return false;
+ }
+ EqualsBuilder equalsBuilder = new EqualsBuilder();
+ try {
+ reflectionAppend(lhs, rhs, testClass, equalsBuilder, testTransients);
+ while (testClass.getSuperclass() != null && testClass != reflectUpToClass) {
+ testClass = testClass.getSuperclass();
+ reflectionAppend(lhs, rhs, testClass, equalsBuilder, testTransients);
+ }
+ } catch (IllegalArgumentException e) {
+ // In this case, we tried to test a subclass vs. a superclass and
+ // the subclass has ivars or the ivars are transient and
+ // we are testing transients.
+ // If a subclass has ivars that we are trying to test them, we get an
+ // exception and we know that the objects are not equal.
+ return false;
+ }
+ return equalsBuilder.isEquals();
+ }
+
+ /**
+ * Appends the fields and values defined by the given object of the
+ * given Class.
+ *
+ * @param lhs the left hand object
+ * @param rhs the right hand object
+ * @param clazz the class to append details of
+ * @param builder the builder to append to
+ * @param useTransients whether to test transient fields
+ */
+ private static void reflectionAppend(
+ Object lhs,
+ Object rhs,
+ Class clazz,
+ EqualsBuilder builder,
+ boolean useTransients) {
+ Field[] fields = clazz.getDeclaredFields();
+ Field.setAccessible(fields, true);
+ for (int i = 0; i < fields.length && builder.isEquals; i++) {
+ Field f = fields[i];
+ if ((f.getName().indexOf('$') == -1)
+ && (useTransients || !Modifier.isTransient(f.getModifiers()))
+ && (!Modifier.isStatic(f.getModifiers()))) {
+ try {
+ builder.append(f.get(lhs), f.get(rhs));
+ } 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");
+ }
+ }
+ }
+ }
+
+ //-------------------------------------------------------------------------
+
+ /**
+ * Adds the result of super.equals() to this builder.
+ *
+ * @param superEquals the result of calling super.equals()
+ * @return EqualsBuilder - used to chain calls.
+ */
+ public EqualsBuilder appendSuper(boolean superEquals) {
+ if (isEquals == false) {
+ return this;
+ }
+ isEquals = superEquals;
+ return this;
+ }
+
+ //-------------------------------------------------------------------------
+
+ /**
+ * Test if two Object
s are equal using their
+ * equals
method.
+ *
+ * @param lhs - Left Hand Side
+ * @param rhs - Right Hand Side
+ * @return EqualsBuilder - used to chain calls.
+ */
+ public EqualsBuilder append(Object lhs, Object rhs) {
+ if (isEquals == false) {
+ return this;
+ }
+ if (lhs == rhs) {
+ return this;
+ }
+ if (lhs == null || rhs == null) {
+ isEquals = false;
+ return this;
+ }
+ Class lhsClass = lhs.getClass();
+ if (!lhsClass.isArray()) {
+ //the simple case, not an array, just test the element
+ isEquals = lhs.equals(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);
+ }
+ }
+ return this;
+ }
+
+ /**
+ * Test if two long
s are equal using ==.
+ *
+ * @param lhs - Left Hand Side
+ * @param rhs - Right Hand Side
+ * @return EqualsBuilder - used to chain calls.
+ */
+ public EqualsBuilder append(long lhs, long rhs) {
+ if (isEquals == false) {
+ return this;
+ }
+ isEquals = (lhs == rhs);
+ return this;
+ }
+
+ /**
+ * Test if two int
s are equal using ==.
+ *
+ * @param lhs - Left Hand Side
+ * @param rhs - Right Hand Side
+ * @return EqualsBuilder - used to chain calls.
+ */
+ public EqualsBuilder append(int lhs, int rhs) {
+ if (isEquals == false) {
+ return this;
+ }
+ isEquals = (lhs == rhs);
+ return this;
+ }
+
+ /**
+ * Test if two short
s are equal using ==.
+ *
+ * @param lhs - Left Hand Side
+ * @param rhs - Right Hand Side
+ * @return EqualsBuilder - used to chain calls.
+ */
+ public EqualsBuilder append(short lhs, short rhs) {
+ if (isEquals == false) {
+ return this;
+ }
+ isEquals = (lhs == rhs);
+ return this;
+ }
+
+ /**
+ * Test if two char
s are equal using ==.
+ *
+ * @param lhs - Left Hand Side
+ * @param rhs - Right Hand Side
+ * @return EqualsBuilder - used to chain calls.
+ */
+ public EqualsBuilder append(char lhs, char rhs) {
+ if (isEquals == false) {
+ return this;
+ }
+ isEquals = (lhs == rhs);
+ return this;
+ }
+
+ /**
+ * Test if two byte
s are equal using ==.
+ *
+ * @param lhs - Left Hand Side
+ * @param rhs - Right Hand Side
+ * @return EqualsBuilder - used to chain calls.
+ */
+ public EqualsBuilder append(byte lhs, byte rhs) {
+ if (isEquals == false) {
+ return this;
+ }
+ isEquals = (lhs == rhs);
+ return this;
+ }
+
+ /**
+ * 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
.
+ *
+ * It is compatible with the hash code generated by
+ * HashCodeBuilder
.
+ *
+ * @param lhs - Left Hand Side
+ * @param rhs - Right Hand Side
+ * @return EqualsBuilder - used to chain calls.
+ */
+ public EqualsBuilder append(double lhs, double rhs) {
+ if (isEquals == false) {
+ return this;
+ }
+ return append(Double.doubleToLongBits(lhs), Double.doubleToLongBits(rhs));
+ }
+
+ /**
+ * 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
.
+ *
+ * It is compatible with the hash code generated by
+ * HashCodeBuilder
.
+ *
+ * @param lhs - Left Hand Side
+ * @param rhs - Right Hand Side
+ * @return EqualsBuilder - used to chain calls.
+ */
+ public EqualsBuilder append(float lhs, float rhs) {
+ if (isEquals == false) {
+ return this;
+ }
+ return append(Float.floatToIntBits(lhs), Float.floatToIntBits(rhs));
+ }
+
+ /**
+ * Test if two booleans
s are equal using ==.
+ *
+ * @param lhs - Left Hand Side
+ * @param rhs - Right Hand Side
+ * @return EqualsBuilder - used to chain calls.
+ */
+ public EqualsBuilder append(boolean lhs, boolean rhs) {
+ if (isEquals == false) {
+ return this;
+ }
+ isEquals = (lhs == rhs);
+ return this;
+ }
+
+ /**
+ * Performs a deep comparison of two Object arrays.
+ *
+ * This also will be called for the top level of
+ * multi-dimensional, ragged, and multi-typed arrays.
+ *
+ * @param lhs - Left Hand Side
+ * @param rhs - Right Hand Side
+ * @return EqualsBuilder - used to chain calls.
+ */
+ public EqualsBuilder append(Object[] lhs, Object[] rhs) {
+ if (isEquals == false) {
+ return this;
+ }
+ if (lhs == rhs) {
+ return this;
+ }
+ if (lhs == null || rhs == null) {
+ isEquals = false;
+ return this;
+ }
+ if (lhs.length != rhs.length) {
+ isEquals = 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;
+ }
+
+ /**
+ * Deep comparison of array of long
Length and all values
+ * are compared.
+ *
+ * The method {@link #append(long, long)} is used.
+ *
+ * @param lhs - Left Hand Side
+ * @param rhs - Right Hand Side
+ * @return EqualsBuilder - used to chain calls.
+ */
+ public EqualsBuilder append(long[] lhs, long[] rhs) {
+ if (isEquals == false) {
+ return this;
+ }
+ if (lhs == rhs) {
+ return this;
+ }
+ if (lhs == null || rhs == null) {
+ isEquals = false;
+ return this;
+ }
+ if (lhs.length != rhs.length) {
+ isEquals = false;
+ return this;
+ }
+ for (int i = 0; i < lhs.length && isEquals; ++i) {
+ append(lhs[i], rhs[i]);
+ }
+ return this;
+ }
+
+ /**
+ * Deep comparison of array of int
Length and all values
+ * are compared.
+ *
+ * The method {@link #append(int, int)} is used.
+ *
+ * @param lhs - Left Hand Side
+ * @param rhs - Right Hand Side
+ * @return EqualsBuilder - used to chain calls.
+ */
+ public EqualsBuilder append(int[] lhs, int[] rhs) {
+ if (isEquals == false) {
+ return this;
+ }
+ if (lhs == rhs) {
+ return this;
+ }
+ if (lhs == null || rhs == null) {
+ isEquals = false;
+ return this;
+ }
+ if (lhs.length != rhs.length) {
+ isEquals = false;
+ return this;
+ }
+ for (int i = 0; i < lhs.length && isEquals; ++i) {
+ append(lhs[i], rhs[i]);
+ }
+ return this;
+ }
+
+ /**
+ * Deep comparison of array of short
Length and all values
+ * are compared.
+ *
+ * The method {@link #append(short, short)} is used.
+ *
+ * @param lhs - Left Hand Side
+ * @param rhs - Right Hand Side
+ * @return EqualsBuilder - used to chain calls.
+ */
+ public EqualsBuilder append(short[] lhs, short[] rhs) {
+ if (isEquals == false) {
+ return this;
+ }
+ if (lhs == rhs) {
+ return this;
+ }
+ if (lhs == null || rhs == null) {
+ isEquals = false;
+ return this;
+ }
+ if (lhs.length != rhs.length) {
+ isEquals = false;
+ return this;
+ }
+ for (int i = 0; i < lhs.length && isEquals; ++i) {
+ append(lhs[i], rhs[i]);
+ }
+ return this;
+ }
+
+ /**
+ * Deep comparison of array of char
Length and all values
+ * are compared.
+ *
+ * The method {@link #append(char, char)} is used.
+ *
+ * @param lhs - Left Hand Side
+ * @param rhs - Right Hand Side
+ * @return EqualsBuilder - used to chain calls.
+ */
+ public EqualsBuilder append(char[] lhs, char[] rhs) {
+ if (isEquals == false) {
+ return this;
+ }
+ if (lhs == rhs) {
+ return this;
+ }
+ if (lhs == null || rhs == null) {
+ isEquals = false;
+ return this;
+ }
+ if (lhs.length != rhs.length) {
+ isEquals = false;
+ return this;
+ }
+ for (int i = 0; i < lhs.length && isEquals; ++i) {
+ append(lhs[i], rhs[i]);
+ }
+ return this;
+ }
+
+ /**
+ * Deep comparison of array of byte
Length and all values
+ * are compared.
+ *
+ * The method {@link #append(byte, byte)} is used.
+ *
+ * @param lhs - Left Hand Side
+ * @param rhs - Right Hand Side
+ * @return EqualsBuilder - used to chain calls.
+ */
+ public EqualsBuilder append(byte[] lhs, byte[] rhs) {
+ if (isEquals == false) {
+ return this;
+ }
+ if (lhs == rhs) {
+ return this;
+ }
+ if (lhs == null || rhs == null) {
+ isEquals = false;
+ return this;
+ }
+ if (lhs.length != rhs.length) {
+ isEquals = false;
+ return this;
+ }
+ for (int i = 0; i < lhs.length && isEquals; ++i) {
+ append(lhs[i], rhs[i]);
+ }
+ return this;
+ }
+
+ /**
+ * Deep comparison of array of double
Length and all values
+ * are compared.
+ *
+ * The method {@link #append(double, double)} is used.
+ *
+ * @param lhs - Left Hand Side
+ * @param rhs - Right Hand Side
+ * @return EqualsBuilder - used to chain calls.
+ */
+ public EqualsBuilder append(double[] lhs, double[] rhs) {
+ if (isEquals == false) {
+ return this;
+ }
+ if (lhs == rhs) {
+ return this;
+ }
+ if (lhs == null || rhs == null) {
+ isEquals = false;
+ return this;
+ }
+ if (lhs.length != rhs.length) {
+ isEquals = false;
+ return this;
+ }
+ for (int i = 0; i < lhs.length && isEquals; ++i) {
+ append(lhs[i], rhs[i]);
+ }
+ return this;
+ }
+
+ /**
+ * Deep comparison of array of float
Length and all values
+ * are compared.
+ *
+ * The method {@link #append(float, float)} is used.
+ *
+ * @param lhs - Left Hand Side
+ * @param rhs - Right Hand Side
+ * @return EqualsBuilder - used to chain calls.
+ */
+ public EqualsBuilder append(float[] lhs, float[] rhs) {
+ if (isEquals == false) {
+ return this;
+ }
+ if (lhs == rhs) {
+ return this;
+ }
+ if (lhs == null || rhs == null) {
+ isEquals = false;
+ return this;
+ }
+ if (lhs.length != rhs.length) {
+ isEquals = false;
+ return this;
+ }
+ for (int i = 0; i < lhs.length && isEquals; ++i) {
+ append(lhs[i], rhs[i]);
+ }
+ return this;
+ }
+
+ /**
+ * Deep comparison of array of boolean
Length and all values
+ * are compared.
+ *
+ * The method {@link #append(boolean, boolean)} is used.
+ *
+ * @param lhs - Left Hand Side
+ * @param rhs - Right Hand Side
+ * @return EqualsBuilder - used to chain calls.
+ */
+ public EqualsBuilder append(boolean[] lhs, boolean[] rhs) {
+ if (isEquals == false) {
+ return this;
+ }
+ if (lhs == rhs) {
+ return this;
+ }
+ if (lhs == null || rhs == null) {
+ isEquals = false;
+ return this;
+ }
+ if (lhs.length != rhs.length) {
+ isEquals = false;
+ return this;
+ }
+ for (int i = 0; i < lhs.length && isEquals; ++i) {
+ append(lhs[i], rhs[i]);
+ }
+ return this;
+ }
+
+ /**
+ * Return true
if the fields that have been checked
+ * are all equal.
+ *
+ * @return boolean
+ */
+ public boolean isEquals() {
+ return isEquals;
+ }
+
+}
diff --git a/examples/cl2/src/java/org/apache/commons/lang/builder/HashCodeBuilder.java b/examples/cl2/src/java/org/apache/commons/lang/builder/HashCodeBuilder.java
new file mode 100644
index 00000000..528935c9
--- /dev/null
+++ b/examples/cl2/src/java/org/apache/commons/lang/builder/HashCodeBuilder.java
@@ -0,0 +1,664 @@
+/* ====================================================================
+ * 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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
+ * .
+ */
+package org.apache.commons.lang.builder;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+/**
+ * HashCode
generation routines.
+ *
+ * This class enables a good hashcode to be built for any class. It
+ * follows the rules laid out in the book
+ * Effective Java
+ * , by Joshua Bloch. Writing a good hashCode
is actually quite
+ * difficult. This class aims to simplify the process.
+ *
+ * All relevant fields from the object should be included in the
+ * hashCode
. 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;
+ * ...
+ *
+ * public int hashCode() {
+ * // you pick a hard-coded, randomly chosen, non-zero, odd number
+ * // ideally different for each class
+ * return new HashCodeBuilder(17, 37).
+ * append(name).
+ * append(age).
+ * append(smoker).
+ * toHashCode();
+ * }
+ * }
+ *
+ *
+ * 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 Field.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 Gary Gregory
+ * @since 1.0
+ * @version $Id: HashCodeBuilder.java,v 1.12 2003/04/18 09:12:16 ggregory Exp $
+ */
+public class HashCodeBuilder {
+
+ /**
+ * Constant to use in building the hashCode
+ */
+ private final int iConstant;
+ /**
+ * Running total of the hashCode
+ */
+ private int iTotal = 0;
+
+ /**
+ * Constructor for HashCodeBuilder.
+ *
+ * This constructor uses two hard coded choices for the constants
+ * needed to build a hashCode
.
+ */
+ public HashCodeBuilder() {
+ super();
+ iConstant = 37;
+ iTotal = 17;
+ }
+
+ /**
+ * Constructor for HashCodeBuilder
.
+ *
+ * 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(int initialNonZeroOddNumber, int multiplierNonZeroOddNumber) {
+ super();
+ 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;
+ }
+
+ //-------------------------------------------------------------------------
+
+ /**
+ * 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 Field.setAccessible
to gain access to private
+ * fields. This means that it will throw a security exception if run under
+ * a security manger, 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
+ */
+ public static int reflectionHashCode(Object object) {
+ return reflectionHashCode(17, 37, object, false, 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 Field.setAccessible
to gain access to private
+ * fields. This means that it will throw a security exception if run under
+ * a security manger, 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);
+ }
+
+ /**
+ * This method uses reflection to build a valid hash code.
+ *
+ * It uses Field.setAccessible
to gain access to private
+ * fields. This means that it will throw a security exception if run under
+ * a security manger, 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 number is zero or even
+ */
+ public static int reflectionHashCode(
+ int initialNonZeroOddNumber, int multiplierNonZeroOddNumber, Object object) {
+ return reflectionHashCode(initialNonZeroOddNumber, multiplierNonZeroOddNumber, object, false, null);
+ }
+
+ /**
+ * This method uses reflection to build a valid hash code.
+ *
+ * It uses Field.setAccessible
to gain access to private
+ * fields. This means that it will throw a security exception if run under
+ * a security manger, 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 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 Field.setAccessible
to gain access to private
+ * fields. This means that it will throw a security exception if run under
+ * a security manger, 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
+ */
+ public static int reflectionHashCode(
+ int initialNonZeroOddNumber,
+ int multiplierNonZeroOddNumber,
+ Object object,
+ boolean testTransients,
+ Class reflectUpToClass) {
+
+ 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);
+ while (clazz.getSuperclass() != null && clazz != reflectUpToClass) {
+ clazz = clazz.getSuperclass();
+ reflectionAppend(object, clazz, builder, testTransients);
+ }
+ return builder.toHashCode();
+ }
+
+ /**
+ * 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
+ */
+ private static void reflectionAppend(Object object, Class clazz, HashCodeBuilder builder, boolean useTransients) {
+ Field[] fields = clazz.getDeclaredFields();
+ Field.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");
+ }
+ }
+ }
+ }
+
+ //-------------------------------------------------------------------------
+
+ /**
+ * Adds the result of super.hashCode() to this builder.
+ *
+ * @param superHashCode the result of calling super.hashCode()
+ * @return this HashCodeBuilder, used to chain calls.
+ */
+ public HashCodeBuilder appendSuper(int superHashCode) {
+ iTotal = iTotal * iConstant + superHashCode;
+ return this;
+ }
+
+ //-------------------------------------------------------------------------
+
+ /**
+ * Append a hashCode
for an Object
.
+ *
+ * @param object the Object to add to the hashCode
+ * @return this
+ */
+ public HashCodeBuilder append(Object object) {
+ if (object == null) {
+ iTotal = iTotal * iConstant;
+
+ } else {
+ if (object.getClass().isArray() == false) {
+ //the simple case, not an array, just the element
+ iTotal = iTotal * iConstant + object.hashCode();
+
+ } 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);
+ }
+ }
+ }
+ return this;
+ }
+
+ /**
+ * Append a hashCode
for a long
.
+ *
+ * @param value the long to add to the hashCode
+ * @return this
+ */
+ public HashCodeBuilder append(long value) {
+ iTotal = iTotal * iConstant + ((int) (value ^ (value >> 32)));
+ return this;
+ }
+
+ /**
+ * Append a hashCode
for an int
.
+ *
+ * @param value the int to add to the hashCode
+ * @return this
+ */
+ public HashCodeBuilder append(int value) {
+ iTotal = iTotal * iConstant + value;
+ return this;
+ }
+
+ /**
+ * Append a hashCode
for a short
.
+ *
+ * @param value the short to add to the hashCode
+ * @return this
+ */
+ public HashCodeBuilder append(short value) {
+ iTotal = iTotal * iConstant + (int) value;
+ return this;
+ }
+
+ /**
+ * Append a hashCode
for a char
.
+ *
+ * @param value the char to add to the hashCode
+ * @return this
+ */
+ public HashCodeBuilder append(char value) {
+ iTotal = iTotal * iConstant + (int) value;
+ return this;
+ }
+
+ /**
+ * 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 + (int) 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
+ * @return this
+ */
+ public HashCodeBuilder append(float value) {
+ iTotal = iTotal * iConstant + Float.floatToIntBits(value);
+ return this;
+ }
+
+ /**
+ * Append a hashCode
for a long
.
+ *
+ * @param value the long to add to the hashCode
+ * @return this
+ */
+ public HashCodeBuilder append(boolean value) {
+ iTotal = iTotal * iConstant + (value ? 0 : 1);
+ return this;
+ }
+
+ /**
+ * Append a hashCode
for an Object
array.
+ *
+ * @param array the array to add to the hashCode
+ * @return this
+ */
+ public HashCodeBuilder append(Object[] 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 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 {
+ for (int i = 0; i < array.length; i++) {
+ append(array[i]);
+ }
+ }
+ 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 {
+ for (int i = 0; i < array.length; i++) {
+ append(array[i]);
+ }
+ }
+ 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 {
+ for (int i = 0; i < array.length; i++) {
+ append(array[i]);
+ }
+ }
+ return this;
+ }
+
+ /**
+ * Append a hashCode
for a char
array.
+ *
+ * @param array the array to add to the hashCode
+ * @return this
+ */
+ public HashCodeBuilder append(char[] 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
array.
+ *
+ * @param array the array to add to the hashCode
+ * @return this
+ */
+ 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 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 {
+ for (int i = 0; i < array.length; i++) {
+ append(array[i]);
+ }
+ }
+ return this;
+ }
+
+ /**
+ * Append a hashCode
for a float
array.
+ *
+ * @param array the array to add to the hashCode
+ * @return this
+ */
+ public HashCodeBuilder append(float[] 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
array.
+ *
+ * @param array the array to add to the hashCode
+ * @return this
+ */
+ 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;
+ }
+
+ /**
+ * Return the computed hashCode
.
+ *
+ * @return hashCode
based on the fields appended
+ */
+ public int toHashCode() {
+ return iTotal;
+ }
+
+}
diff --git a/examples/cl2/src/java/org/apache/commons/lang/builder/ReflectionToStringBuilder.java b/examples/cl2/src/java/org/apache/commons/lang/builder/ReflectionToStringBuilder.java
new file mode 100644
index 00000000..814fb789
--- /dev/null
+++ b/examples/cl2/src/java/org/apache/commons/lang/builder/ReflectionToStringBuilder.java
@@ -0,0 +1,457 @@
+package org.apache.commons.lang.builder;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.apache.commons.lang.ClassUtils;
+
+/**
+ * Builds toString()
values using reflection.
+ *
+ * This class uses reflection to determine the fields to append.
+ * Because these fields are usually private, the class,
+ * uses Field.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:
+ *
+ * public String toString() {
+ * return ReflectionToStringBuilder.toString(this);
+ * }
+ *
+ *
+ * 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)}
+ *
+ *
+ *
+ * The exact format of the toString
is determined by
+ * the {@link ToStringStyle} passed into the constructor.
+ *
+ * @author Gary Gregory
+ * @author Stephen Colebourne
+ * @since 2.0
+ * @version $Id: ReflectionToStringBuilder.java,v 1.1 2003/06/03 03:51:56 ggregory Exp $
+ */
+public class ReflectionToStringBuilder extends ToStringBuilder {
+
+ /**
+ * A registry of objects used by reflectionToString
methods to detect cyclical object references
+ * and avoid infinite loops.
+ */
+ 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();
+ }
+ };
+
+ /**
+ * Returns the registry of objects being traversed by the
+ * reflectionToString
methods in the current thread.
+ * @return Set the registry of objects being traversed
+ */
+ static Set getRegistry() {
+ return (Set) 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) {
+ return getRegistry().contains(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) {
+ getRegistry().add(value);
+ }
+
+ /**
+ * This method uses reflection to build a suitable
+ * toString
using the default ToStringStyle
.
+ *
+ *
It uses Field.setAccessible
to gain access to private
+ * fields. This means that it will throw a security exception if run
+ * under a security manger, 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
+ */
+ public static String toString(Object object) {
+ return toString(object, null, false, null);
+ }
+
+ /**
+ * This method uses reflection to build a suitable
+ * toString
.
+ *
+ * It uses Field.setAccessible
to gain access to private
+ * fields. This means that it will throw a security exception if run
+ * under a security manger, 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
+ */
+ public static String toString(Object object, ToStringStyle style) {
+ return toString(object, style, false, null);
+ }
+
+ /**
+ * This method uses reflection to build a suitable
+ * toString
.
+ *
+ * It uses Field.setAccessible
to gain access to private
+ * fields. This means that it will throw a security exception if run
+ * under a security manger, 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
+ */
+ public static String toString(Object object, ToStringStyle style, boolean outputTransients) {
+ return toString(object, style, outputTransients, null);
+ }
+
+ /**
+ * This method uses reflection to build a suitable
+ * toString
.
+ *
+ * It uses Field.setAccessible
to gain access to private
+ * fields. This means that it will throw a security exception if run
+ * under a security manger, 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.
+ *
+ * @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
+ */
+ public static String toString(
+ Object object,
+ ToStringStyle style,
+ boolean outputTransients,
+ Class reflectUpToClass) {
+ return new ReflectionToStringBuilder(object, style, null, reflectUpToClass, outputTransients).toString();
+ }
+
+ /**
+ * Unregisters the given object.
+ * Used by the reflection methods to avoid infinite loops.
+ *
+ * @param value The object to unregister.
+ */
+ static void unregister(Object value) {
+ getRegistry().remove(value);
+ }
+
+ /**
+ * Whether or not to append transient fields.
+ */
+ private boolean appendTransients = false;
+
+ /**
+ * The last super class to stop appending fields for.
+ */
+ private Class upToClass = null;
+
+ /**
+ * Constructs a new instance.
+ *
+ * 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 specifying the 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
+ */
+ public ReflectionToStringBuilder(Object object, ToStringStyle style) {
+ super(object, style);
+ }
+
+ /**
+ * Constructors a new instance.
+ *
+ * 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
+ */
+ public ReflectionToStringBuilder(Object object, ToStringStyle style, StringBuffer buffer) {
+ super(object, style, buffer);
+ }
+
+ /**
+ * Constructs a new instance.
+ *
+ * @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
+ */
+ public ReflectionToStringBuilder(
+ Object object,
+ ToStringStyle style,
+ StringBuffer buffer,
+ Class reflectUpToClass,
+ boolean outputTransients) {
+ super(object, style, buffer);
+ this.setUpToClass(reflectUpToClass);
+ this.setAppendTransients(outputTransients);
+ }
+
+ /**
+ * 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.
+ *
+ * @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()));
+ }
+
+ /**
+ * Appends the fields and values defined by the given object of the
+ * given Class. If a cycle is detected as an objects 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());
+ return;
+ }
+ try {
+ this.registerObject();
+ if (clazz.isArray()) {
+ this.reflectionAppendArray(this.getObject());
+ return;
+ }
+ Field[] fields = clazz.getDeclaredFields();
+ Field.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());
+ }
+ }
+ }
+ } finally {
+ this.unregisterObject();
+ }
+ }
+
+ /**
+ * Gets the last super class to stop appending fields for.
+ *
+ * @return The last super class to stop appending fields for.
+ */
+ public Class getUpToClass() {
+ return this.upToClass;
+ }
+
+ /**
+ * Calls java.lang.reflect.Field.get(Object)
+ * @see java.lang.reflect.Field#get(Object)
+ * @throws IllegalArgumentException
+ * @throws IllegalAccessException
+ */
+ protected Object getValue(Field field) throws IllegalArgumentException, IllegalAccessException {
+ return field.get(this.getObject());
+ }
+
+ /**
+ * Returns 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
+ * @return this
+ */
+ public ToStringBuilder reflectionAppendArray(Object array) {
+ this.getStyle().reflectionAppendArrayDetail(this.getStringBuffer(), null, array);
+ return this;
+ }
+
+ /**
+ * Registers this builder's source object to avoid infinite loops processing circular object references.
+ */
+ void registerObject() {
+ register(this.getObject());
+ }
+
+ /**
+ * Sets 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.
+ *
+ * @param clazz The last super class to stop appending fields for.
+ */
+ public void setUpToClass(Class clazz) {
+ this.upToClass = clazz;
+ }
+
+ public String toString() {
+ if (this.getObject() == null) {
+ return this.getStyle().getNullText();
+ }
+ Class clazz = this.getObject().getClass();
+ this.appendFieldsIn(clazz);
+ while (clazz.getSuperclass() != null && clazz != this.getUpToClass()) {
+ clazz = clazz.getSuperclass();
+ this.appendFieldsIn(clazz);
+ }
+ return super.toString();
+ }
+
+ /**
+ * Unegisters this builder's source object to avoid infinite loops processing circular object references.
+ */
+ void unregisterObject() {
+ unregister(this.getObject());
+ }
+
+}
diff --git a/examples/cl2/src/java/org/apache/commons/lang/builder/StandardToStringStyle.java b/examples/cl2/src/java/org/apache/commons/lang/builder/StandardToStringStyle.java
new file mode 100644
index 00000000..db4332b6
--- /dev/null
+++ b/examples/cl2/src/java/org/apache/commons/lang/builder/StandardToStringStyle.java
@@ -0,0 +1,546 @@
+/* ====================================================================
+ * 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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
+ * .
+ */
+package org.apache.commons.lang.builder;
+
+/**
+ * StandardToStringStyle
works with {@link ToStringBuilder}
+ * to create a toString
.
+ *
+ * This class is intended to be used as a Singleton
. There
+ * is no need to instantiate a new style each time. Your code should
+ * instantiate the class once, customize the values as required, and then
+ * store the result in a public static final variable for the rest of the
+ * program to access.
+ *
+ * @author Stephen Colebourne
+ * @since 1.0
+ * @version $Id: StandardToStringStyle.java,v 1.8 2003/03/23 17:54:16 scolebourne Exp $
+ */
+public class StandardToStringStyle extends ToStringStyle {
+
+ /**
+ * Constructor.
+ */
+ public StandardToStringStyle() {
+ super();
+ }
+
+ //---------------------------------------------------------------------
+
+ /**
+ * Gets whether to use the class name.
+ *
+ * @return the current useClassName flag
+ */
+ public boolean isUseClassName() {
+ return super.isUseClassName();
+ }
+
+ /**
+ * Sets whether to use the class name.
+ *
+ * @param useClassName the new useClassName flag
+ */
+ public void setUseClassName(boolean useClassName) {
+ super.setUseClassName(useClassName);
+ }
+
+ //---------------------------------------------------------------------
+
+ /**
+ * Gets whether to output short or long class names.
+ *
+ * @return the current shortClassName flag
+ */
+ public boolean isShortClassName() {
+ return super.isShortClassName();
+ }
+
+ /**
+ * Sets whether to output short or long class names.
+ *
+ * @param shortClassName the new shortClassName flag
+ */
+ public void setShortClassName(boolean shortClassName) {
+ super.setShortClassName(shortClassName);
+ }
+
+ //---------------------------------------------------------------------
+
+ /**
+ * Gets whether to use the identity hash code.
+ * @return the current useIdentityHashCode flag
+ */
+ public boolean isUseIdentityHashCode() {
+ return super.isUseIdentityHashCode();
+ }
+
+ /**
+ * Sets whether to use the identity hash code.
+ *
+ * @param useIdentityHashCode the new useIdentityHashCode flag
+ */
+ public void setUseIdentityHashCode(boolean useIdentityHashCode) {
+ super.setUseIdentityHashCode(useIdentityHashCode);
+ }
+
+ //---------------------------------------------------------------------
+
+ /**
+ * Gets whether to use the field names passed in.
+ *
+ * @return the current useFieldNames flag
+ */
+ public boolean isUseFieldNames() {
+ return super.isUseFieldNames();
+ }
+
+ /**
+ * Sets whether to use the field names passed in.
+ *
+ * @param useFieldNames the new useFieldNames flag
+ */
+ public void setUseFieldNames(boolean useFieldNames) {
+ super.setUseFieldNames(useFieldNames);
+ }
+
+ //---------------------------------------------------------------------
+
+ /**
+ * Gets whether to use full detail when the caller doesn't
+ * specify.
+ *
+ * @return the current defaultFullDetail flag
+ */
+ public boolean isDefaultFullDetail() {
+ return super.isDefaultFullDetail();
+ }
+
+ /**
+ * Sets whether to use full detail when the caller doesn't
+ * specify.
+ *
+ * @param defaultFullDetail the new defaultFullDetail flag
+ */
+ public void setDefaultFullDetail(boolean defaultFullDetail) {
+ super.setDefaultFullDetail(defaultFullDetail);
+ }
+
+ //---------------------------------------------------------------------
+
+ /**
+ * Gets whether to output array content detail.
+ *
+ * @return the current array content detail setting
+ */
+ public boolean isArrayContentDetail() {
+ return super.isArrayContentDetail();
+ }
+
+ /**
+ * Sets whether to output array content detail.
+ *
+ * @param arrayContentDetail the new arrayContentDetail flag
+ */
+ public void setArrayContentDetail(boolean arrayContentDetail) {
+ super.setArrayContentDetail(arrayContentDetail);
+ }
+
+ //---------------------------------------------------------------------
+
+ /**
+ * Gets the array start text.
+ *
+ * @return the current array start text
+ */
+ public String getArrayStart() {
+ return super.getArrayStart();
+ }
+
+ /**
+ * Sets the array start text.
+ *
+ * Null
is accepted, but will be converted
+ * to a empry String.
+ *
+ * @param arrayStart the new array start text
+ */
+ public void setArrayStart(String arrayStart) {
+ super.setArrayStart(arrayStart);
+ }
+
+ //---------------------------------------------------------------------
+
+ /**
+ * Gets the array end text.
+ *
+ * @return the current array end text
+ */
+ public String getArrayEnd() {
+ return super.getArrayEnd();
+ }
+
+ /**
+ * Sets the array end text.
+ *
+ * Null
is accepted, but will be converted
+ * to a empty String.
+ *
+ * @param arrayEnd the new array end text
+ */
+ public void setArrayEnd(String arrayEnd) {
+ super.setArrayEnd(arrayEnd);
+ }
+
+ //---------------------------------------------------------------------
+
+ /**
+ * Gets the array separator text.
+ *
+ * @return the current array separator text
+ */
+ public String getArraySeparator() {
+ return super.getArraySeparator();
+ }
+
+ /**
+ * Sets the array separator text.
+ *
+ * Null
is accepted, but will be converted
+ * to a empty String.
+ *
+ * @param arraySeparator the new array separator text
+ */
+ public void setArraySeparator(String arraySeparator) {
+ super.setArraySeparator(arraySeparator);
+ }
+
+ //---------------------------------------------------------------------
+
+ /**
+ * Gets the content start text.
+ *
+ * @return the current content start text
+ */
+ public String getContentStart() {
+ return super.getContentStart();
+ }
+
+ /**
+ * Sets the content start text.
+ *
+ * Null
is accepted, but will be converted
+ * to a empty String.
+ *
+ * @param contentStart the new content start text
+ */
+ public void setContentStart(String contentStart) {
+ super.setContentStart(contentStart);
+ }
+
+ //---------------------------------------------------------------------
+
+ /**
+ * Gets the content end text.
+ *
+ * @return the current content end text
+ */
+ public String getContentEnd() {
+ return super.getContentEnd();
+ }
+
+ /**
+ * Sets the content end text.
+ *
+ * Null
is accepted, but will be converted
+ * to a empty String.
+ *
+ * @param contentEnd the new content end text
+ */
+ public void setContentEnd(String contentEnd) {
+ super.setContentEnd(contentEnd);
+ }
+
+ //---------------------------------------------------------------------
+
+ /**
+ * Gets the field name value separator text.
+ *
+ * @return the current field name value separator text
+ */
+ public String getFieldNameValueSeparator() {
+ return super.getFieldNameValueSeparator();
+ }
+
+ /**
+ * Sets the field name value separator text.
+ *
+ * Null
is accepted, but will be converted
+ * to a empty String.
+ *
+ * @param fieldNameValueSeparator the new field name value separator text
+ */
+ public void setFieldNameValueSeparator(String fieldNameValueSeparator) {
+ super.setFieldNameValueSeparator(fieldNameValueSeparator);
+ }
+
+ //---------------------------------------------------------------------
+
+ /**
+ * Gets the field separator text.
+ *
+ * @return the current field separator text
+ */
+ public String getFieldSeparator() {
+ return super.getFieldSeparator();
+ }
+
+ /**
+ * Sets the field separator text.
+ *
+ * Null
is accepted, but will be converted
+ * to a empty String.
+ *
+ * @param fieldSeparator the new field separator text
+ */
+ public void setFieldSeparator(String fieldSeparator) {
+ super.setFieldSeparator(fieldSeparator);
+ }
+
+ //---------------------------------------------------------------------
+
+ /**
+ * Gets whether the field separator should be added at the start
+ * of each buffer.
+ *
+ * @return the fieldSeparatorAtStart flag
+ */
+ public boolean isFieldSeparatorAtStart() {
+ return super.isFieldSeparatorAtStart();
+ }
+
+ /**
+ * Sets whether the field separator should be added at the start
+ * of each buffer.
+ *
+ * @param fieldSeparatorAtStart the fieldSeparatorAtStart flag
+ */
+ public void setFieldSeparatorAtStart(boolean fieldSeparatorAtStart) {
+ super.setFieldSeparatorAtStart(fieldSeparatorAtStart);
+ }
+
+ //---------------------------------------------------------------------
+
+ /**
+ * Gets whether the field separator should be added at the end
+ * of each buffer.
+ *
+ * @return fieldSeparatorAtEnd flag
+ */
+ public boolean isFieldSeparatorAtEnd() {
+ return super.isFieldSeparatorAtEnd();
+ }
+
+ /**
+ * Sets whether the field separator should be added at the end
+ * of each buffer.
+ *
+ * @param fieldSeparatorAtEnd the fieldSeparatorAtEnd flag
+ */
+ public void setFieldSeparatorAtEnd(boolean fieldSeparatorAtEnd) {
+ super.setFieldSeparatorAtEnd(fieldSeparatorAtEnd);
+ }
+
+ //---------------------------------------------------------------------
+
+ /**
+ * Gets the text to output when null
found.
+ *
+ * @return the current text to output when null
found
+ */
+ public String getNullText() {
+ return super.getNullText();
+ }
+
+ /**
+ * Sets the text to output when null
found.
+ *
+ * Null
is accepted, but will be converted
+ * to a empty String.
+ *
+ * @param nullText the new text to output when null found
+ */
+ public void setNullText(String nullText) {
+ super.setNullText(nullText);
+ }
+
+ //---------------------------------------------------------------------
+
+ /**
+ * Gets the text to output when a Collection
,
+ * Map
or Array
size is output.
+ *
+ * This is output before the size value.
+ *
+ * @return the current start of size text
+ */
+ public String getSizeStartText() {
+ return super.getSizeStartText();
+ }
+
+ /**
+ * Sets the text to output when a Collection
,
+ * Map
or Array
size is output.
+ *
+ * This is output before the size value.
+ *
+ * Null
is accepted, but will be converted to
+ * a empty String.
+ *
+ * @param sizeStartText the new start of size text
+ */
+ public void setSizeStartText(String sizeStartText) {
+ super.setSizeStartText(sizeStartText);
+ }
+
+ //---------------------------------------------------------------------
+
+ /**
+ * Gets the text to output when a Collection
,
+ * Map
or Array
size is output.
+ *
+ * This is output after the size value.
+ *
+ * @return the current end of size text
+ */
+ public String getSizeEndText() {
+ return super.getSizeEndText();
+ }
+
+ /**
+ * Sets the text to output when a Collection
,
+ * Map
or Array
size is output.
+ *
+ * This is output after the size value.
+ *
+ * Null
is accepted, but will be converted
+ * to a Empty String.
+ *
+ * @param sizeEndText the new end of size text
+ */
+ public void setSizeEndText(String sizeEndText) {
+ super.setSizeEndText(sizeEndText);
+ }
+
+ //---------------------------------------------------------------------
+
+ /**
+ * Gets the text to output when an Object
is
+ * output in summary mode.
+ *
+ * This is output before the size value.
+ *
+ * @return the current start of summary text
+ */
+ public String getSummaryObjectStartText() {
+ return super.getSummaryObjectStartText();
+ }
+
+ /**
+ * Sets the text to output when an Object
is
+ * output in summary mode.
+ *
+ * This is output before the size value.
+ *
+ * Null
is accepted, but will be converted to
+ * a empty String.
+ *
+ * @param summaryObjectStartText the new start of summary text
+ */
+ public void setSummaryObjectStartText(String summaryObjectStartText) {
+ super.setSummaryObjectStartText(summaryObjectStartText);
+ }
+
+ //---------------------------------------------------------------------
+
+ /**
+ * Gets the text to output when an Object
is
+ * output in summary mode.
+ *
+ * This is output after the size value.
+ *
+ * @return the current end of summary text
+ */
+ public String getSummaryObjectEndText() {
+ return super.getSummaryObjectEndText();
+ }
+
+ /**
+ * Sets the text to output when an Object
is
+ * output in summary mode.
+ *
+ * This is output after the size value.
+ *
+ * Null
is accepted, but will be converted to
+ * a empty String.
+ *
+ * @param summaryObjectEndText the new end of summary text
+ */
+ public void setSummaryObjectEndText(String summaryObjectEndText) {
+ super.setSummaryObjectEndText(summaryObjectEndText);
+ }
+
+ //---------------------------------------------------------------------
+
+}
diff --git a/examples/cl2/src/java/org/apache/commons/lang/builder/ToStringBuilder.java b/examples/cl2/src/java/org/apache/commons/lang/builder/ToStringBuilder.java
new file mode 100644
index 00000000..48601699
--- /dev/null
+++ b/examples/cl2/src/java/org/apache/commons/lang/builder/ToStringBuilder.java
@@ -0,0 +1,1069 @@
+/* ====================================================================
+ * 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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
+ * .
+ */
+package org.apache.commons.lang.builder;
+
+/**
+ * Builds toString()
values.
+ *
+ * This class enables a good and consistent toString()
to be built for any
+ * class or object. This class aims to simplify the process by:
+ *
+ * - allowing field names
+ *
- handling all types consistently
+ *
- handling nulls consistently
+ *
- outputting arrays and multi-dimensional arrays
+ *
- enabling the detail level to be controlled for Objects and Collections
+ *
- handling class hierarchies
+ *
+ *
+ * To use this class write code as follows:
+ *
+ * public class Person {
+ * String name;
+ * int age;
+ * boolean isSmoker;
+ *
+ * ...
+ *
+ * public String toString() {
+ * return new ToStringBuilder(this).
+ * append("name", name).
+ * append("age", age).
+ * append("smoker", smoker).
+ * toString();
+ * }
+ * }
+ *
+ * This will produce a toString of the format:
+ * Person@7f54[name=Stephen,age=29,smoker=false]
+ *
+ * To add the superclass toString
, use {@link #appendSuper}.
+ * To append the toString
from an object that is delegated
+ * to (or any other object), use {@link #appendToString}.
+ *
+ * Alternatively, there is a method that uses reflection to determine
+ * the fields to test. Because these fields are usually private, the method,
+ * reflectionToString
, uses Field.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 String toString() {
+ * return ToStringBuilder.reflectionToString(this);
+ * }
+ *
+ *
+ * You can also use the builder to debug 3rd party objects:
+ *
+ * System.out.println("An object: " + ToStringBuilder.reflectionToString(anObject));
+ *
+ *
+ * The exact format of the toString
is determined by
+ * the {@link ToStringStyle} passed into the constructor.
+ *
+ * @author Stephen Colebourne
+ * @author Gary Gregory
+ * @since 1.0
+ * @version $Id: ToStringBuilder.java,v 1.22 2003/06/03 03:51:56 ggregory Exp $
+ */
+public class ToStringBuilder {
+
+ /**
+ * The default style of output to use
+ */
+ private static 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
+ */
+ public static ToStringStyle getDefaultStyle() {
+ return defaultStyle;
+ }
+
+ /**
+ * Forwards to ReflectionToStringBuilder.
+ *
+ * @see ReflectionToStringBuilder#toString(Object)
+ */
+ public static String reflectionToString(Object object) {
+ return ReflectionToStringBuilder.toString(object);
+ }
+
+ /**
+ * Forwards to ReflectionToStringBuilder.
+ *
+ * @see ReflectionToStringBuilder#toString(Object,ToStringStyle)
+ */
+ public static String reflectionToString(Object object, ToStringStyle style) {
+ return ReflectionToStringBuilder.toString(object, style);
+ }
+
+ /**
+ * Forwards to ReflectionToStringBuilder.
+ *
+ * @see ReflectionToStringBuilder#toString(Object,ToStringStyle,boolean)
+ */
+ public static String reflectionToString(Object object, ToStringStyle style, boolean outputTransients) {
+ return ReflectionToStringBuilder.toString(object, style, outputTransients, null);
+ }
+
+ /**
+ * Forwards to ReflectionToStringBuilder.
+ *
+ * @see ReflectionToStringBuilder#toString(Object,ToStringStyle,boolean,Class)
+ */
+ public static String reflectionToString(
+ Object object,
+ ToStringStyle style,
+ boolean outputTransients,
+ Class reflectUpToClass) {
+ return ReflectionToStringBuilder.toString(object, style, outputTransients, 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.
+ */
+ private final StringBuffer buffer;
+
+ /**
+ * The object being output.
+ */
+ private final Object object;
+
+ /**
+ * The style of output to use.
+ */
+ private final ToStringStyle style;
+
+ /**
+ * Constructor for ToStringBuilder
.
+ *
+ * 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 ToStringBuilder(Object object) {
+ this(object, getDefaultStyle(), null);
+ }
+
+ /**
+ * Constructor for ToStringBuilder
specifying the
+ * 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
+ */
+ public ToStringBuilder(Object object, ToStringStyle style) {
+ this(object, style, null);
+ }
+
+ /**
+ * Constructor for ToStringBuilder
.
+ *
+ * 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
+ */
+ 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();
+ }
+ if (buffer == null) {
+ buffer = new StringBuffer(512);
+ }
+ this.buffer = buffer;
+ this.style = style;
+ this.object = object;
+
+ style.appendStart(buffer, object);
+ }
+
+ //----------------------------------------------------------------------------
+
+ /**
+ * Append to the toString
an boolean
+ * value.
+ *
+ * @param value the value to add to the toString
+ * @return this
+ */
+ public ToStringBuilder append(boolean value) {
+ style.append(buffer, null, value);
+ return this;
+ }
+
+ //----------------------------------------------------------------------------
+
+ /**
+ * Append to the toString
a boolean
+ * array.
+ *
+ * @param array the array to add to the toString
+ * @return this
+ */
+ public ToStringBuilder append(boolean[] array) {
+ style.append(buffer, null, array, null);
+ return this;
+ }
+
+ //----------------------------------------------------------------------------
+
+ /**
+ * Append to the toString
an byte
+ * value.
+ *
+ * @param value the value to add to the toString
+ * @return this
+ */
+ public ToStringBuilder append(byte value) {
+ style.append(buffer, null, value);
+ return this;
+ }
+
+ //----------------------------------------------------------------------------
+
+ /**
+ * Append to the toString
a byte
+ * array.
+ *
+ * @param array the array to add to the toString
+ * @return this
+ */
+ public ToStringBuilder append(byte[] array) {
+ style.append(buffer, null, array, null);
+ return this;
+ }
+
+ //----------------------------------------------------------------------------
+
+ /**
+ * Append to the toString
an char
+ * value.
+ *
+ * @param value the value to add to the toString
+ * @return this
+ */
+ public ToStringBuilder append(char value) {
+ style.append(buffer, null, value);
+ return this;
+ }
+
+ //----------------------------------------------------------------------------
+
+ /**
+ * Append to the toString
a char
+ * array.
+ *
+ * @param array the array to add to the toString
+ * @return this
+ */
+ public ToStringBuilder append(char[] array) {
+ style.append(buffer, null, array, null);
+ return this;
+ }
+
+ //----------------------------------------------------------------------------
+
+ /**
+ * Append to the toString
an double
+ * value.
+ *
+ * @param value the value to add to the toString
+ * @return this
+ */
+ public ToStringBuilder append(double value) {
+ style.append(buffer, null, value);
+ return this;
+ }
+
+ //----------------------------------------------------------------------------
+
+ /**
+ * Append to the toString
a double
+ * array.
+ *
+ * @param array the array to add to the toString
+ * @return this
+ */
+ public ToStringBuilder append(double[] array) {
+ style.append(buffer, null, array, null);
+ return this;
+ }
+
+ //----------------------------------------------------------------------------
+
+ /**
+ * Append to the toString
an float
+ * value.
+ *
+ * @param value the value to add to the toString
+ * @return this
+ */
+ public ToStringBuilder append(float value) {
+ style.append(buffer, null, value);
+ return this;
+ }
+
+ //----------------------------------------------------------------------------
+
+ /**
+ * Append to the toString
a float
+ * array.
+ *
+ * @param array the array to add to the toString
+ * @return this
+ */
+ public ToStringBuilder append(float[] array) {
+ style.append(buffer, null, array, null);
+ return this;
+ }
+
+ //----------------------------------------------------------------------------
+
+ /**
+ * Append to the toString
an int
+ * value.
+ *
+ * @param value the value to add to the toString
+ * @return this
+ */
+ public ToStringBuilder append(int value) {
+ style.append(buffer, null, value);
+ return this;
+ }
+
+ //----------------------------------------------------------------------------
+
+ /**
+ * Append to the toString
a int
+ * array.
+ *
+ * @param array the array to add to the toString
+ * @return this
+ */
+ public ToStringBuilder append(int[] array) {
+ style.append(buffer, null, array, null);
+ return this;
+ }
+
+ //----------------------------------------------------------------------------
+
+ /**
+ * Append to the toString
a long
+ * value.
+ *
+ * @param value the value to add to the toString
+ * @return this
+ */
+ public ToStringBuilder append(long value) {
+ style.append(buffer, null, value);
+ return this;
+ }
+
+ //----------------------------------------------------------------------------
+
+ /**
+ * Append to the toString
a long
+ * array.
+ *
+ * @param array the array to add to the toString
+ * @return this
+ */
+ public ToStringBuilder append(long[] array) {
+ style.append(buffer, null, array, null);
+ return this;
+ }
+
+ //----------------------------------------------------------------------------
+
+ /**
+ * Append to the toString
an Object
+ * value.
+ *
+ * @param object the value to add to the toString
+ * @return this
+ */
+ public ToStringBuilder append(Object object) {
+ style.append(buffer, null, object, null);
+ return this;
+ }
+
+ //----------------------------------------------------------------------------
+
+ /**
+ * Append to the toString
an Object
+ * array.
+ *
+ * @param array the array to add to the toString
+ * @return this
+ */
+ public ToStringBuilder append(Object[] array) {
+ style.append(buffer, null, array, null);
+ return this;
+ }
+
+ //----------------------------------------------------------------------------
+
+ /**
+ * Append to the toString
an short
+ * value.
+ *
+ * @param value the value to add to the toString
+ * @return this
+ */
+ public ToStringBuilder append(short value) {
+ style.append(buffer, null, value);
+ return this;
+ }
+
+ //----------------------------------------------------------------------------
+
+ /**
+ * Append to the toString
a short
+ * array.
+ *
+ * @param array the array to add to the toString
+ * @return this
+ */
+ public ToStringBuilder append(short[] array) {
+ style.append(buffer, null, array, null);
+ return this;
+ }
+
+ /**
+ * Append to the toString
an boolean
+ * value.
+ *
+ * @param fieldName the field name
+ * @param value the value to add to the toString
+ * @return this
+ */
+ public ToStringBuilder append(String fieldName, boolean value) {
+ style.append(buffer, fieldName, value);
+ return this;
+ }
+
+ /**
+ * Append a hashCode
for a boolean
+ * array.
+ *
+ * @param fieldName the field name
+ * @param array the array to add to the hashCode
+ * @return this
+ */
+ public ToStringBuilder append(String fieldName, boolean[] array) {
+ style.append(buffer, fieldName, array, null);
+ return this;
+ }
+
+ /**
+ * Append to the toString
a boolean
+ * array.
+ *
+ * A boolean parameter controls the level of detail to show.
+ * Setting true
will output the array in full. Setting
+ * false
will output a summary, typically the size of
+ * the array.
+ *
+ * @param fieldName the field name
+ * @param array the array to add to the toString
+ * @param fullDetail true
for detail, false
+ * for summary info
+ * @return this
+ */
+ public ToStringBuilder append(String fieldName, boolean[] array, boolean fullDetail) {
+ style.append(buffer, fieldName, array, new Boolean(fullDetail));
+ return this;
+ }
+
+ /**
+ * Append to the toString
an byte
+ * value.
+ *
+ * @param fieldName the field name
+ * @param value the value to add to the toString
+ * @return this
+ */
+ public ToStringBuilder append(String fieldName, byte value) {
+ style.append(buffer, fieldName, value);
+ return this;
+ }
+
+ /**
+ * Append a hashCode
for a byte
+ * array.
+ *
+ * @param fieldName the field name
+ * @param array the array to add to the hashCode
+ * @return this
+ */
+ public ToStringBuilder append(String fieldName, byte[] array) {
+ style.append(buffer, fieldName, array, null);
+ return this;
+ }
+
+ /**
+ * Append to the toString
a byte
+ * array.
+ *
+ * A boolean parameter controls the level of detail to show.
+ * Setting true
will output the array in full. Setting
+ * false
will output a summary, typically the size of
+ * the array.
+ *
+ * @param fieldName the field name
+ * @param array the array to add to the toString
+ * @param fullDetail true
for detail, false
+ * for summary info
+ * @return this
+ */
+ public ToStringBuilder append(String fieldName, byte[] array, boolean fullDetail) {
+ style.append(buffer, fieldName, array, new Boolean(fullDetail));
+ return this;
+ }
+
+ /**
+ *
Append to the toString
an char
+ * value.
+ *
+ * @param fieldName the field name
+ * @param value the value to add to the toString
+ * @return this
+ */
+ public ToStringBuilder append(String fieldName, char value) {
+ style.append(buffer, fieldName, value);
+ return this;
+ }
+
+ /**
+ * Append a hashCode
for a char
+ * array.
+ *
+ * @param fieldName the field name
+ * @param array the array to add to the hashCode
+ * @return this
+ */
+ public ToStringBuilder append(String fieldName, char[] array) {
+ style.append(buffer, fieldName, array, null);
+ return this;
+ }
+
+ /**
+ * Append to the toString
a char
+ * array.
+ *
+ * A boolean parameter controls the level of detail to show.
+ * Setting true
will output the array in full. Setting
+ * false
will output a summary, typically the size of
+ * the array.
+ *
+ * @param fieldName the field name
+ * @param array the array to add to the toString
+ * @param fullDetail true
for detail, false
+ * for summary info
+ * @return this
+ */
+ public ToStringBuilder append(String fieldName, char[] array, boolean fullDetail) {
+ style.append(buffer, fieldName, array, new Boolean(fullDetail));
+ return this;
+ }
+
+ /**
+ * Append to the toString
an double
+ * value.
+ *
+ * @param fieldName the field name
+ * @param value the value to add to the toString
+ * @return this
+ */
+ public ToStringBuilder append(String fieldName, double value) {
+ style.append(buffer, fieldName, value);
+ return this;
+ }
+
+ /**
+ * Append a hashCode
for a double
+ * array.
+ *
+ * @param fieldName the field name
+ * @param array the array to add to the hashCode
+ * @return this
+ */
+ public ToStringBuilder append(String fieldName, double[] array) {
+ style.append(buffer, fieldName, array, null);
+ return this;
+ }
+
+ /**
+ * Append to the toString
a double
+ * array.
+ *
+ * A boolean parameter controls the level of detail to show.
+ * Setting true
will output the array in full. Setting
+ * false
will output a summary, typically the size of
+ * the array.
+ *
+ * @param fieldName the field name
+ * @param array the array to add to the toString
+ * @param fullDetail true
for detail, false
+ * for summary info
+ * @return this
+ */
+ public ToStringBuilder append(String fieldName, double[] array, boolean fullDetail) {
+ style.append(buffer, fieldName, array, new Boolean(fullDetail));
+ return this;
+ }
+
+ /**
+ * Append to the toString
an float
+ * value.
+ *
+ * @param fieldName the field name
+ * @param value the value to add to the toString
+ * @return this
+ */
+ public ToStringBuilder append(String fieldName, float value) {
+ style.append(buffer, fieldName, value);
+ return this;
+ }
+
+ /**
+ * Append a hashCode
for a float
+ * array.
+ *
+ * @param fieldName the field name
+ * @param array the array to add to the hashCode
+ * @return this
+ */
+ public ToStringBuilder append(String fieldName, float[] array) {
+ style.append(buffer, fieldName, array, null);
+ return this;
+ }
+
+ /**
+ * Append to the toString
a float
+ * array.
+ *
+ * A boolean parameter controls the level of detail to show.
+ * Setting true
will output the array in full. Setting
+ * false
will output a summary, typically the size of
+ * the array.
+ *
+ * @param fieldName the field name
+ * @param array the array to add to the toString
+ * @param fullDetail true
for detail, false
+ * for summary info
+ * @return this
+ */
+ public ToStringBuilder append(String fieldName, float[] array, boolean fullDetail) {
+ style.append(buffer, fieldName, array, new Boolean(fullDetail));
+ return this;
+ }
+
+ /**
+ * Append to the toString
an int
+ * value.
+ *
+ * @param fieldName the field name
+ * @param value the value to add to the toString
+ * @return this
+ */
+ public ToStringBuilder append(String fieldName, int value) {
+ style.append(buffer, fieldName, value);
+ return this;
+ }
+
+ /**
+ * Append a hashCode
for an int
+ * array.
+ *
+ * @param fieldName the field name
+ * @param array the array to add to the hashCode
+ * @return this
+ */
+ public ToStringBuilder append(String fieldName, int[] array) {
+ style.append(buffer, fieldName, array, null);
+ return this;
+ }
+
+ /**
+ * Append to the toString
an int
+ * array.
+ *
+ * A boolean parameter controls the level of detail to show.
+ * Setting true
will output the array in full. Setting
+ * false
will output a summary, typically the size of
+ * the array.
+ *
+ * @param fieldName the field name
+ * @param array the array to add to the toString
+ * @param fullDetail true
for detail, false
+ * for summary info
+ * @return this
+ */
+ public ToStringBuilder append(String fieldName, int[] array, boolean fullDetail) {
+ style.append(buffer, fieldName, array, new Boolean(fullDetail));
+ return this;
+ }
+
+ /**
+ * Append to the toString
a long
+ * value.
+ *
+ * @param fieldName the field name
+ * @param value the value to add to the toString
+ * @return this
+ */
+ public ToStringBuilder append(String fieldName, long value) {
+ style.append(buffer, fieldName, value);
+ return this;
+ }
+
+ /**
+ * Append a hashCode
for a long
+ * array.
+ *
+ * @param fieldName the field name
+ * @param array the array to add to the hashCode
+ * @return this
+ */
+ public ToStringBuilder append(String fieldName, long[] array) {
+ style.append(buffer, fieldName, array, null);
+ return this;
+ }
+
+ /**
+ * Append to the toString
a long
+ * array.
+ *
+ * A boolean parameter controls the level of detail to show.
+ * Setting true
will output the array in full. Setting
+ * false
will output a summary, typically the size of
+ * the array.
+ *
+ * @param fieldName the field name
+ * @param array the array to add to the toString
+ * @param fullDetail true
for detail, false
+ * for summary info
+ * @return this
+ */
+ public ToStringBuilder append(String fieldName, long[] array, boolean fullDetail) {
+ style.append(buffer, fieldName, array, new Boolean(fullDetail));
+ return this;
+ }
+
+ /**
+ * Append to the toString
an Object
+ * value.
+ *
+ * @param fieldName the field name
+ * @param object the value to add to the toString
+ * @return this
+ */
+ public ToStringBuilder append(String fieldName, Object object) {
+ style.append(buffer, fieldName, object, null);
+ return this;
+ }
+
+ /**
+ * Append to the toString
an Object
+ * value.
+ *
+ * @param fieldName the field name
+ * @param object 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, new Boolean(fullDetail));
+ return this;
+ }
+
+ /**
+ * Append to the toString
an Object
+ * array.
+ *
+ * @param fieldName the field name
+ * @param array the array to add to the toString
+ * @return this
+ */
+ public ToStringBuilder append(String fieldName, Object[] array) {
+ style.append(buffer, fieldName, array, null);
+ return this;
+ }
+
+ /**
+ * Append to the toString
an Object
+ * array.
+ *
+ * A boolean parameter controls the level of detail to show.
+ * Setting true
will output the array in full. Setting
+ * false
will output a summary, typically the size of
+ * the array.
+ *
+ * @param fieldName the field name
+ * @param array the array to add to the toString
+ * @param fullDetail true
for detail, false
+ * for summary info
+ * @return this
+ */
+ public ToStringBuilder append(String fieldName, Object[] array, boolean fullDetail) {
+ style.append(buffer, fieldName, array, new Boolean(fullDetail));
+ return this;
+ }
+
+ /**
+ * Append to the toString
an short
+ * value.
+ *
+ * @param fieldName the field name
+ * @param value the value to add to the toString
+ * @return this
+ */
+ public ToStringBuilder append(String fieldName, short value) {
+ style.append(buffer, fieldName, value);
+ return this;
+ }
+
+ /**
+ * Append a hashCode
for a short
+ * array.
+ *
+ * @param fieldName the field name
+ * @param array the array to add to the hashCode
+ * @return this
+ */
+ public ToStringBuilder append(String fieldName, short[] array) {
+ style.append(buffer, fieldName, array, null);
+ return this;
+ }
+
+ /**
+ * Append to the toString
a short
+ * array.
+ *
+ * A boolean parameter controls the level of detail to show.
+ * Setting true
will output the array in full. Setting
+ * false
will output a summary, typically the size of
+ * the array.
+ *
+ * @param fieldName the field name
+ * @param array the array to add to the toString
+ * @param fullDetail true
for detail, false
+ * for summary info
+ * @return this
+ */
+ public ToStringBuilder append(String fieldName, short[] array, boolean fullDetail) {
+ style.append(buffer, fieldName, array, new Boolean(fullDetail));
+ return this;
+ }
+
+ /**
+ *
Appends with the same format as the default Object toString()
+ *
method. Appends the class name followed by
+ * {@link System#identityHashCode(java.lang.Object)}.
+ *
+ * @param object the Object
whose class name and id to output
+ */
+ public ToStringBuilder appendAsObjectToString(Object object) {
+ this.getStyle().appendAsObjectToString(this.getStringBuffer(), object);
+ return this;
+ }
+
+ //----------------------------------------------------------------------------
+
+ /**
+ * Append the toString
from the superclass.
+ *
+ * This method asumes that the superclass uses the same ToStringStyle
+ * as this one.
+ *
+ * If the superToString
is null, no change is made.
+ *
+ * @param superToString the result of super.toString()
+ * @return this
+ */
+ public ToStringBuilder appendSuper(String superToString) {
+ if (superToString != null) {
+ style.appendSuper(buffer, superToString);
+ }
+ return this;
+ }
+
+ /**
+ * Append the toString
from another object.
+ *
+ * This method is useful where a class delegates most of the implementation of
+ * it's properties to another class. You can then call toString() on the other
+ * class and pass the result into this method.
+ *
+ *
+ * private AnotherObject delegate;
+ * private String fieldInThisClass;
+ *
+ * public String toString() {
+ * return new ToStringBuilder(this).
+ * appendToString(delegate.toString()).
+ * append(fieldInThisClass).
+ * toString();
+ * }
+ *
+ * This method asumes that the other object uses the same ToStringStyle
+ * as this one.
+ *
+ * If the toString
is null, no change is made.
+ *
+ * @param toString the result of toString()
on another object
+ * @return this
+ */
+ public ToStringBuilder appendToString(String toString) {
+ if (toString != null) {
+ style.appendToString(buffer, toString);
+ }
+ return this;
+ }
+
+ /**
+ * Gets the StringBuffer
being populated.
+ *
+ * @return the StringBuffer
being populated
+ */
+ public StringBuffer getStringBuffer() {
+ return buffer;
+ }
+
+ //----------------------------------------------------------------------------
+
+ /**
+ * Gets the ToStringStyle
being used.
+ *
+ * @return the ToStringStyle
being used
+ */
+ public ToStringStyle getStyle() {
+ return style;
+ }
+
+ /**
+ * Returns the built toString
.
+ *
+ * This method appends the end of the buffer, and can only be called once.
+ * Use {@link #getStringBuffer} to get the current string state.
+ *
+ * @return the String toString
+ */
+ public String toString() {
+ style.appendEnd(buffer, object);
+ return buffer.toString();
+ }
+
+ /**
+ * Returns the object being output.
+ *
+ * @return The object being output.
+ */
+ public Object getObject() {
+ return object;
+ }
+
+}
diff --git a/examples/cl2/src/java/org/apache/commons/lang/builder/ToStringStyle.java b/examples/cl2/src/java/org/apache/commons/lang/builder/ToStringStyle.java
new file mode 100644
index 00000000..db558765
--- /dev/null
+++ b/examples/cl2/src/java/org/apache/commons/lang/builder/ToStringStyle.java
@@ -0,0 +1,2151 @@
+/* ====================================================================
+ * 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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
+ * .
+ */
+package org.apache.commons.lang.builder;
+
+import java.io.Serializable;
+import java.lang.reflect.Array;
+import java.util.Collection;
+import java.util.Map;
+
+import org.apache.commons.lang.SystemUtils;
+/**
+ * ToStringStyle
works with ToStringBuilder
+ * to create a toString
. The main public interface is always
+ * via ToStringBuilder
.
+ *
+ * These classes are intended to be used as Singletons
.
+ * There is no need to instantiate a new style each time. A program
+ * will generally use one of the predefined constants on this class.
+ * Alternatively, the {@link StandardToStringStyle} class can be used
+ * to set the individual settings. Thus most styles can be achieved
+ * without subclassing.
+ *
+ * If required, a subclass can override as many or as few of the
+ * methods as it requires. Each object type (from boolean
+ * to long
to Object
to int[]
) has
+ * its own methods to output it. Most have two versions, detail and summary.
+ *
+ *
For example, the detail version of the array based methods will
+ * output the whole array, whereas the summary method will just output
+ * the array length.
+ *
+ * @author Stephen Colebourne
+ * @author Gary Gregory
+ * @since 1.0
+ * @version $Id: ToStringStyle.java,v 1.14 2003/06/03 03:51:56 ggregory Exp $
+ */
+public abstract class ToStringStyle implements Serializable {
+
+ /**
+ * The default toString style.
+ */
+ public static final ToStringStyle DEFAULT_STYLE = new DefaultToStringStyle();
+ /**
+ * The multi line toString style.
+ */
+ public static final ToStringStyle MULTI_LINE_STYLE = new MultiLineToStringStyle();
+ /**
+ * The no field names toString style.
+ */
+ public static final ToStringStyle NO_FIELD_NAMES_STYLE = new NoFieldNameToStringStyle();
+ /**
+ * The simple toString style.
+ */
+ public static final ToStringStyle SIMPLE_STYLE = new SimpleToStringStyle();
+
+ /**
+ * 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
.
+ */
+ private boolean useIdentityHashCode = true;
+
+ /**
+ * 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 '>'
.
+ */
+ private String summaryObjectEndText = ">";
+
+ //----------------------------------------------------------------------------
+
+ /**
+ * Constructor.
+ */
+ protected ToStringStyle() {
+ super();
+ }
+
+ //----------------------------------------------------------------------------
+
+ /**
+ * Append the superclass toString.
+ *
+ * A null super.toString()
is ignored.
+ *
+ * @param buffer the StringBuffer
to populate
+ * @param superToString the super.toString()
+ */
+ public void appendSuper(StringBuffer buffer, String superToString) {
+ appendToString(buffer, superToString);
+ }
+
+ /**
+ * Append a toString.
+ *
+ * A null toString()
is ignored.
+ *
+ * @param buffer the StringBuffer
to populate
+ * @param toString the super.toString()
+ */
+ public void appendToString(StringBuffer buffer, String toString) {
+ if (toString != null) {
+ int pos1 = toString.indexOf(contentStart) + contentStart.length();
+ int pos2 = toString.lastIndexOf(contentEnd);
+ if (pos1 != pos2 && pos1 >= 0 && pos2 >= 0) {
+ String data = toString.substring(pos1, pos2);
+ if (fieldSeparatorAtStart) {
+ removeLastFieldSeparator(buffer);
+ }
+ buffer.append(data);
+ appendFieldSeparator(buffer);
+ }
+ }
+ }
+
+ /**
+ * Append the start of data indicator.
+ *
+ * @param buffer the StringBuffer
to populate
+ * @param object the Object
to build a
+ * toString
for, must not be null
+ */
+ public void appendStart(StringBuffer buffer, Object object) {
+ appendClassName(buffer, object);
+ appendIdentityHashCode(buffer, object);
+ appendContentStart(buffer);
+ if (fieldSeparatorAtStart) {
+ appendFieldSeparator(buffer);
+ }
+ }
+
+ /**
+ * Append the end of data indicator.
+ *
+ * @param buffer the StringBuffer
to populate
+ * @param object the Object
to build a
+ * toString
for, must not be null
+ */
+ public void appendEnd(StringBuffer buffer, Object object) {
+ if (fieldSeparatorAtEnd == false) {
+ removeLastFieldSeparator(buffer);
+ }
+ appendContentEnd(buffer);
+ }
+
+ /**
+ * Remove the last field separator from the buffer.
+ *
+ * @param buffer the StringBuffer
to populate
+ */
+ protected void removeLastFieldSeparator(StringBuffer buffer) {
+ int len = buffer.length();
+ int sepLen = fieldSeparator.length();
+ if (len > 0 && sepLen > 0 && len >= sepLen) {
+ boolean match = true;
+ for (int i = 0; i < sepLen; i++) {
+ if (buffer.charAt(len - 1 - i) != fieldSeparator.charAt(sepLen - 1 - i)) {
+ match = false;
+ break;
+ }
+ }
+ if (match) {
+ buffer.setLength(len - sepLen);
+ }
+ }
+ }
+
+ //----------------------------------------------------------------------------
+
+ /**
+ * Append to the toString
an Object
+ * value, printing the full toString
of the
+ * Object
passed in.
+ *
+ * @param buffer the StringBuffer
to populate
+ * @param fieldName the field name
+ * @param value the value to add to the toString
+ * @param fullDetail true
for detail, false
+ * for summary info, null
for style decides
+ */
+ public void append(StringBuffer buffer, String fieldName, Object value, Boolean fullDetail) {
+ appendFieldStart(buffer, fieldName);
+
+ if (value == null) {
+ appendNullText(buffer, fieldName);
+
+ } else {
+ appendInternal(buffer, fieldName, value, isFullDetail(fullDetail));
+ }
+
+ appendFieldEnd(buffer, fieldName);
+ }
+
+ /**
+ * Append to the toString
an Object
,
+ * correctly interpretting its type.
+ *
+ * This method performs the main lookup by Class type to correctly
+ * route arrays, Collections
, Maps
and
+ * Objects
to the appropriate method.
+ *
+ * Either detail or summary views can be specified.
+ *
+ * If a cycle is detected, an object will be appended with the Object.toString() format.
+ *
+ * @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
+ * @param detail output detail or not
+ */
+ protected void appendInternal(StringBuffer buffer, String fieldName, Object value, boolean detail) {
+ if (ReflectionToStringBuilder.isRegistered(value)
+ && !(value instanceof Number || value instanceof Boolean || value instanceof Character)) {
+ appendAsObjectToString(buffer, value);
+
+ } else if (value instanceof Collection) {
+ if (detail) {
+ appendDetail(buffer, fieldName, (Collection) value);
+ } else {
+ appendSummarySize(buffer, fieldName, ((Collection) value).size());
+ }
+
+ } else if (value instanceof Map) {
+ if (detail) {
+ appendDetail(buffer, fieldName, (Map) value);
+ } else {
+ appendSummarySize(buffer, fieldName, ((Map) value).size());
+ }
+
+ } else if (value instanceof long[]) {
+ if (detail) {
+ appendDetail(buffer, fieldName, (long[]) value);
+ } else {
+ appendSummary(buffer, fieldName, (long[]) value);
+ }
+
+ } else if (value instanceof int[]) {
+ if (detail) {
+ appendDetail(buffer, fieldName, (int[]) value);
+ } else {
+ appendSummary(buffer, fieldName, (int[]) value);
+ }
+
+ } else if (value instanceof short[]) {
+ if (detail) {
+ appendDetail(buffer, fieldName, (short[]) value);
+ } else {
+ appendSummary(buffer, fieldName, (short[]) value);
+ }
+
+ } else if (value instanceof byte[]) {
+ if (detail) {
+ appendDetail(buffer, fieldName, (byte[]) value);
+ } else {
+ appendSummary(buffer, fieldName, (byte[]) value);
+ }
+
+ } else if (value instanceof char[]) {
+ if (detail) {
+ appendDetail(buffer, fieldName, (char[]) value);
+ } else {
+ appendSummary(buffer, fieldName, (char[]) value);
+ }
+
+ } else if (value instanceof double[]) {
+ if (detail) {
+ appendDetail(buffer, fieldName, (double[]) value);
+ } else {
+ appendSummary(buffer, fieldName, (double[]) value);
+ }
+
+ } else if (value instanceof float[]) {
+ if (detail) {
+ appendDetail(buffer, fieldName, (float[]) value);
+ } else {
+ appendSummary(buffer, fieldName, (float[]) value);
+ }
+
+ } else if (value instanceof boolean[]) {
+ if (detail) {
+ appendDetail(buffer, fieldName, (boolean[]) value);
+ } else {
+ appendSummary(buffer, fieldName, (boolean[]) value);
+ }
+
+ } else if (value.getClass().isArray()) {
+ if (detail) {
+ appendDetail(buffer, fieldName, (Object[]) value);
+ } else {
+ appendSummary(buffer, fieldName, (Object[]) value);
+ }
+
+ } else {
+ if (detail) {
+ appendDetail(buffer, fieldName, (Object) value);
+ } else {
+ appendSummary(buffer, fieldName, (Object) value);
+ }
+ }
+ }
+
+ /**
+ * Append to the toString
an Object
+ * value, printing the full detail of the Object
.
+ *
+ * @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
+ */
+ protected void appendDetail(StringBuffer buffer, String fieldName, Object value) {
+ buffer.append(value);
+ }
+
+ /**
+ * Append to the toString
a Collection
.
+ *
+ * @param buffer the StringBuffer
to populate
+ * @param fieldName the field name, typically not used as already appended
+ * @param coll the Collection
to add to the
+ * toString
, not null
+ */
+ protected void appendDetail(StringBuffer buffer, String fieldName, Collection coll) {
+ buffer.append(coll);
+ }
+
+ /**
+ * Append to the toString
a Map.
+ *
+ * @param buffer the StringBuffer
to populate
+ * @param fieldName the field name, typically not used as already appended
+ * @param map the Map
to add to the toString
,
+ * not null
+ */
+ protected void appendDetail(StringBuffer buffer, String fieldName, Map map) {
+ buffer.append(map);
+ }
+
+ /**
+ * Append to the toString
an Object
+ * value, printing a summary of the Object.
+ *
+ * @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
+ */
+ protected void appendSummary(StringBuffer buffer, String fieldName, Object value) {
+ buffer.append(summaryObjectStartText);
+ buffer.append(getShortClassName(value.getClass()));
+ buffer.append(summaryObjectEndText);
+ }
+
+ //----------------------------------------------------------------------------
+
+ /**
+ * Append to the toString
a long
+ * value.
+ *
+ * @param buffer the StringBuffer
to populate
+ * @param fieldName the field name
+ * @param value the value to add to the toString
+ */
+ public void append(StringBuffer buffer, String fieldName, long value) {
+ appendFieldStart(buffer, fieldName);
+ appendDetail(buffer, fieldName, value);
+ appendFieldEnd(buffer, fieldName);
+ }
+
+ /**
+ * Append to the toString
a long
+ * 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
+ */
+ protected void appendDetail(StringBuffer buffer, String fieldName, long value) {
+ buffer.append(value);
+ }
+
+ //----------------------------------------------------------------------------
+
+ /**
+ * Append to the toString
an int
+ * value.
+ *
+ * @param buffer the StringBuffer
to populate
+ * @param fieldName the field name
+ * @param value the value to add to the toString
+ */
+ public void append(StringBuffer buffer, String fieldName, int value) {
+ appendFieldStart(buffer, fieldName);
+ appendDetail(buffer, fieldName, value);
+ appendFieldEnd(buffer, fieldName);
+ }
+
+ /**
+ * Append to the toString
an int
+ * 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
+ */
+ protected void appendDetail(StringBuffer buffer, String fieldName, int value) {
+ buffer.append(value);
+ }
+
+ //----------------------------------------------------------------------------
+
+ /**
+ * Append to the toString
a short
+ * value.
+ *
+ * @param buffer the StringBuffer
to populate
+ * @param fieldName the field name
+ * @param value the value to add to the toString
+ */
+ public void append(StringBuffer buffer, String fieldName, short value) {
+ appendFieldStart(buffer, fieldName);
+ appendDetail(buffer, fieldName, value);
+ appendFieldEnd(buffer, fieldName);
+ }
+
+ /**
+ * Append to the toString
a short
+ * 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
+ */
+ protected void appendDetail(StringBuffer buffer, String fieldName, short value) {
+ buffer.append(value);
+ }
+
+ //----------------------------------------------------------------------------
+
+ /**
+ * Append to the toString
a byte
+ * value.
+ *
+ * @param buffer the StringBuffer
to populate
+ * @param fieldName the field name
+ * @param value the value to add to the toString
+ */
+ public void append(StringBuffer buffer, String fieldName, byte value) {
+ appendFieldStart(buffer, fieldName);
+ appendDetail(buffer, fieldName, value);
+ appendFieldEnd(buffer, fieldName);
+ }
+
+ /**
+ * Append to the toString
a byte
+ * 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
+ */
+ protected void appendDetail(StringBuffer buffer, String fieldName, byte value) {
+ buffer.append(value);
+ }
+
+ //----------------------------------------------------------------------------
+
+ /**
+ * Append to the toString
a char
+ * value.
+ *
+ * @param buffer the StringBuffer
to populate
+ * @param fieldName the field name
+ * @param value the value to add to the toString
+ */
+ public void append(StringBuffer buffer, String fieldName, char value) {
+ appendFieldStart(buffer, fieldName);
+ appendDetail(buffer, fieldName, value);
+ appendFieldEnd(buffer, fieldName);
+ }
+
+ /**
+ * Append to the toString
a char
+ * 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
+ */
+ protected void appendDetail(StringBuffer buffer, String fieldName, char value) {
+ buffer.append(value);
+ }
+
+ //----------------------------------------------------------------------------
+
+ /**
+ * Append to the toString
a double
+ * value.
+ *
+ * @param buffer the StringBuffer
to populate
+ * @param fieldName the field name
+ * @param value the value to add to the toString
+ */
+ public void append(StringBuffer buffer, String fieldName, double value) {
+ appendFieldStart(buffer, fieldName);
+ appendDetail(buffer, fieldName, value);
+ appendFieldEnd(buffer, fieldName);
+ }
+
+ /**
+ * Append to the toString
a double
+ * 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
+ */
+ protected void appendDetail(StringBuffer buffer, String fieldName, double value) {
+ buffer.append(value);
+ }
+
+ //----------------------------------------------------------------------------
+
+ /**
+ * Append to the toString
a float
+ * value.
+ *
+ * @param buffer the StringBuffer
to populate
+ * @param fieldName the field name
+ * @param value the value to add to the toString
+ */
+ public void append(StringBuffer buffer, String fieldName, float value) {
+ appendFieldStart(buffer, fieldName);
+ appendDetail(buffer, fieldName, value);
+ appendFieldEnd(buffer, fieldName);
+ }
+
+ /**
+ * Append to the toString
a float
+ * 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
+ */
+ protected void appendDetail(StringBuffer buffer, String fieldName, float value) {
+ buffer.append(value);
+ }
+
+ //----------------------------------------------------------------------------
+
+ /**
+ * Append to the toString
a boolean
+ * value.
+ *
+ * @param buffer the StringBuffer
to populate
+ * @param fieldName the field name
+ * @param value the value to add to the toString
+ */
+ public void append(StringBuffer buffer, String fieldName, boolean value) {
+ appendFieldStart(buffer, fieldName);
+ appendDetail(buffer, fieldName, value);
+ appendFieldEnd(buffer, fieldName);
+ }
+
+ /**
+ * Append to the toString
a boolean
+ * 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
+ */
+ protected void appendDetail(StringBuffer buffer, String fieldName, boolean value) {
+ buffer.append(value);
+ }
+
+ /**
+ * Append to the toString
an Object
+ * array.
+ *
+ * @param buffer the StringBuffer
to populate
+ * @param fieldName the field name
+ * @param array the array to add to the toString
+ * @param fullDetail true
for detail, false
+ * for summary info, null
for style decides
+ */
+ public void append(StringBuffer buffer, String fieldName, Object[] array, Boolean fullDetail) {
+ appendFieldStart(buffer, fieldName);
+
+ if (array == null) {
+ appendNullText(buffer, fieldName);
+
+ } else if (isFullDetail(fullDetail)) {
+ appendDetail(buffer, fieldName, array);
+
+ } else {
+ appendSummary(buffer, fieldName, array);
+ }
+
+ appendFieldEnd(buffer, fieldName);
+ }
+
+ //----------------------------------------------------------------------------
+
+ /**
+ * Append to the toString
the detail of an
+ * Object
array.
+ *
+ * @param buffer the StringBuffer
to populate
+ * @param fieldName the field name, typically not used as already appended
+ * @param array the array to add to the toString
,
+ * not null
+ */
+ protected void appendDetail(StringBuffer buffer, String fieldName, Object[] array) {
+ buffer.append(arrayStart);
+ for (int i = 0; i < array.length; i++) {
+ Object item = array[i];
+ if (i > 0) {
+ buffer.append(arraySeparator);
+ }
+ if (item == null) {
+ appendNullText(buffer, fieldName);
+
+ } else {
+ appendInternal(buffer, fieldName, item, arrayContentDetail);
+ }
+ }
+ buffer.append(arrayEnd);
+ }
+
+ /**
+ * Append to the toString
the detail of an any array type.
+ *
+ * @param buffer the StringBuffer
to populate
+ * @param fieldName the field name, typically not used as already appended
+ * @param array the array to add to the toString
,
+ * not null
+ */
+ protected void reflectionAppendArrayDetail(StringBuffer buffer, String fieldName, Object array) {
+ buffer.append(arrayStart);
+ int length = Array.getLength(array);
+ for (int i = 0; i < length; i++) {
+ Object item = Array.get(array, i);
+ if (i > 0) {
+ buffer.append(arraySeparator);
+ }
+ if (item == null) {
+ appendNullText(buffer, fieldName);
+
+ } else {
+ appendInternal(buffer, fieldName, item, arrayContentDetail);
+ }
+ }
+ buffer.append(arrayEnd);
+ }
+
+ /**
+ * Append to the toString
a summary of an
+ * Object
array.
+ *
+ * @param buffer the StringBuffer
to populate
+ * @param fieldName the field name, typically not used as already appended
+ * @param array the array to add to the toString
,
+ * not null
+ */
+ protected void appendSummary(StringBuffer buffer, String fieldName, Object[] array) {
+ appendSummarySize(buffer, fieldName, array.length);
+ }
+
+ //----------------------------------------------------------------------------
+
+ /**
+ * Append to the toString
a long
+ * array.
+ *
+ * @param buffer the StringBuffer
to populate
+ * @param fieldName the field name
+ * @param array the array to add to the toString
+ * @param fullDetail true
for detail, false
+ * for summary info, null
for style decides
+ */
+ public void append(StringBuffer buffer, String fieldName, long[] array, Boolean fullDetail) {
+ appendFieldStart(buffer, fieldName);
+
+ if (array == null) {
+ appendNullText(buffer, fieldName);
+
+ } else if (isFullDetail(fullDetail)) {
+ appendDetail(buffer, fieldName, array);
+
+ } else {
+ appendSummary(buffer, fieldName, array);
+ }
+
+ appendFieldEnd(buffer, fieldName);
+ }
+
+ /**
+ * Append to the toString
the detail of a
+ * long
array.
+ *
+ * @param buffer the StringBuffer
to populate
+ * @param fieldName the field name, typically not used as already appended
+ * @param array the array to add to the toString
,
+ * not null
+ */
+ protected void appendDetail(StringBuffer buffer, String fieldName, long[] array) {
+ buffer.append(arrayStart);
+ for (int i = 0; i < array.length; i++) {
+ if (i > 0) {
+ buffer.append(arraySeparator);
+ }
+ appendDetail(buffer, fieldName, array[i]);
+ }
+ buffer.append(arrayEnd);
+ }
+
+ /**
+ * Append to the toString
a summary of a
+ * long
array.
+ *
+ * @param buffer the StringBuffer
to populate
+ * @param fieldName the field name, typically not used as already appended
+ * @param array the array to add to the toString
,
+ * not null
+ */
+ protected void appendSummary(StringBuffer buffer, String fieldName, long[] array) {
+ appendSummarySize(buffer, fieldName, array.length);
+ }
+
+ //----------------------------------------------------------------------------
+
+ /**
+ * Append to the toString
an int
+ * array.
+ *
+ * @param buffer the StringBuffer
to populate
+ * @param fieldName the field name
+ * @param array the array to add to the toString
+ * @param fullDetail true
for detail, false
+ * for summary info, null
for style decides
+ */
+ public void append(StringBuffer buffer, String fieldName, int[] array, Boolean fullDetail) {
+ appendFieldStart(buffer, fieldName);
+
+ if (array == null) {
+ appendNullText(buffer, fieldName);
+
+ } else if (isFullDetail(fullDetail)) {
+ appendDetail(buffer, fieldName, array);
+
+ } else {
+ appendSummary(buffer, fieldName, array);
+ }
+
+ appendFieldEnd(buffer, fieldName);
+ }
+
+ /**
+ * Append to the toString
the detail of an
+ * int
array.
+ *
+ * @param buffer the StringBuffer
to populate
+ * @param fieldName the field name, typically not used as already appended
+ * @param array the array to add to the toString
,
+ * not null
+ */
+ protected void appendDetail(StringBuffer buffer, String fieldName, int[] array) {
+ buffer.append(arrayStart);
+ for (int i = 0; i < array.length; i++) {
+ if (i > 0) {
+ buffer.append(arraySeparator);
+ }
+ appendDetail(buffer, fieldName, array[i]);
+ }
+ buffer.append(arrayEnd);
+ }
+
+ /**
+ * Append to the toString
a summary of an
+ * int
array.
+ *
+ * @param buffer the StringBuffer
to populate
+ * @param fieldName the field name, typically not used as already appended
+ * @param array the array to add to the toString
,
+ * not null
+ */
+ protected void appendSummary(StringBuffer buffer, String fieldName, int[] array) {
+ appendSummarySize(buffer, fieldName, array.length);
+ }
+
+ //----------------------------------------------------------------------------
+
+ /**
+ * Append to the toString
a short
+ * array.
+ *
+ * @param buffer the StringBuffer
to populate
+ * @param fieldName the field name
+ * @param array the array to add to the toString
+ * @param fullDetail true
for detail, false
+ * for summary info, null
for style decides
+ */
+ public void append(StringBuffer buffer, String fieldName, short[] array, Boolean fullDetail) {
+ appendFieldStart(buffer, fieldName);
+
+ if (array == null) {
+ appendNullText(buffer, fieldName);
+
+ } else if (isFullDetail(fullDetail)) {
+ appendDetail(buffer, fieldName, array);
+
+ } else {
+ appendSummary(buffer, fieldName, array);
+ }
+
+ appendFieldEnd(buffer, fieldName);
+ }
+
+ /**
+ * Append to the toString
the detail of a
+ * short
array.
+ *
+ * @param buffer the StringBuffer
to populate
+ * @param fieldName the field name, typically not used as already appended
+ * @param array the array to add to the toString
,
+ * not null
+ */
+ protected void appendDetail(StringBuffer buffer, String fieldName, short[] array) {
+ buffer.append(arrayStart);
+ for (int i = 0; i < array.length; i++) {
+ if (i > 0) {
+ buffer.append(arraySeparator);
+ }
+ appendDetail(buffer, fieldName, array[i]);
+ }
+ buffer.append(arrayEnd);
+ }
+
+ /**
+ * Append to the toString
a summary of a
+ * short
array.
+ *
+ * @param buffer the StringBuffer
to populate
+ * @param fieldName the field name, typically not used as already appended
+ * @param array the array to add to the toString
,
+ * not null
+ */
+ protected void appendSummary(StringBuffer buffer, String fieldName, short[] array) {
+ appendSummarySize(buffer, fieldName, array.length);
+ }
+
+ //----------------------------------------------------------------------------
+
+ /**
+ * Append to the toString
a byte
+ * array.
+ *
+ * @param buffer the StringBuffer
to populate
+ * @param fieldName the field name
+ * @param array the array to add to the toString
+ * @param fullDetail true
for detail, false
+ * for summary info, null
for style decides
+ */
+ public void append(StringBuffer buffer, String fieldName, byte[] array, Boolean fullDetail) {
+ appendFieldStart(buffer, fieldName);
+
+ if (array == null) {
+ appendNullText(buffer, fieldName);
+
+ } else if (isFullDetail(fullDetail)) {
+ appendDetail(buffer, fieldName, array);
+
+ } else {
+ appendSummary(buffer, fieldName, array);
+ }
+
+ appendFieldEnd(buffer, fieldName);
+ }
+
+ /**
+ * Append to the toString
the detail of a
+ * byte
array.
+ *
+ * @param buffer the StringBuffer
to populate
+ * @param fieldName the field name, typically not used as already appended
+ * @param array the array to add to the toString
,
+ * not null
+ */
+ protected void appendDetail(StringBuffer buffer, String fieldName, byte[] array) {
+ buffer.append(arrayStart);
+ for (int i = 0; i < array.length; i++) {
+ if (i > 0) {
+ buffer.append(arraySeparator);
+ }
+ appendDetail(buffer, fieldName, array[i]);
+ }
+ buffer.append(arrayEnd);
+ }
+
+ /**
+ * Append to the toString
a summary of a
+ * byte
array.
+ *
+ * @param buffer the StringBuffer
to populate
+ * @param fieldName the field name, typically not used as already appended
+ * @param array the array to add to the toString
,
+ * not null
+ */
+ protected void appendSummary(StringBuffer buffer, String fieldName, byte[] array) {
+ appendSummarySize(buffer, fieldName, array.length);
+ }
+
+ //----------------------------------------------------------------------------
+
+ /**
+ * Append to the toString
a char
+ * array.
+ *
+ * @param buffer the StringBuffer
to populate
+ * @param fieldName the field name
+ * @param array the array to add to the toString
+ * @param fullDetail true
for detail, false
+ * for summary info, null
for style decides
+ */
+ public void append(StringBuffer buffer, String fieldName, char[] array, Boolean fullDetail) {
+ appendFieldStart(buffer, fieldName);
+
+ if (array == null) {
+ appendNullText(buffer, fieldName);
+
+ } else if (isFullDetail(fullDetail)) {
+ appendDetail(buffer, fieldName, array);
+
+ } else {
+ appendSummary(buffer, fieldName, array);
+ }
+
+ appendFieldEnd(buffer, fieldName);
+ }
+
+ /**
+ * Append to the toString
the detail of a
+ * char
array.
+ *
+ * @param buffer the StringBuffer
to populate
+ * @param fieldName the field name, typically not used as already appended
+ * @param array the array to add to the toString
,
+ * not null
+ */
+ protected void appendDetail(StringBuffer buffer, String fieldName, char[] array) {
+ buffer.append(arrayStart);
+ for (int i = 0; i < array.length; i++) {
+ if (i > 0) {
+ buffer.append(arraySeparator);
+ }
+ appendDetail(buffer, fieldName, array[i]);
+ }
+ buffer.append(arrayEnd);
+ }
+
+ /**
+ * Append to the toString
a summary of a
+ * char
array.
+ *
+ * @param buffer the StringBuffer
to populate
+ * @param fieldName the field name, typically not used as already appended
+ * @param array the array to add to the toString
,
+ * not null
+ */
+ protected void appendSummary(StringBuffer buffer, String fieldName, char[] array) {
+ appendSummarySize(buffer, fieldName, array.length);
+ }
+
+ //----------------------------------------------------------------------------
+
+ /**
+ * Append to the toString
a double
+ * array.
+ *
+ * @param buffer the StringBuffer
to populate
+ * @param fieldName the field name
+ * @param array the array to add to the toString
+ * @param fullDetail true
for detail, false
+ * for summary info, null
for style decides
+ */
+ public void append(StringBuffer buffer, String fieldName, double[] array, Boolean fullDetail) {
+ appendFieldStart(buffer, fieldName);
+
+ if (array == null) {
+ appendNullText(buffer, fieldName);
+
+ } else if (isFullDetail(fullDetail)) {
+ appendDetail(buffer, fieldName, array);
+
+ } else {
+ appendSummary(buffer, fieldName, array);
+ }
+
+ appendFieldEnd(buffer, fieldName);
+ }
+
+ /**
+ * Append to the toString
the detail of a
+ * double
array.
+ *
+ * @param buffer the StringBuffer
to populate
+ * @param fieldName the field name, typically not used as already appended
+ * @param array the array to add to the toString
,
+ * not null
+ */
+ protected void appendDetail(StringBuffer buffer, String fieldName, double[] array) {
+ buffer.append(arrayStart);
+ for (int i = 0; i < array.length; i++) {
+ if (i > 0) {
+ buffer.append(arraySeparator);
+ }
+ appendDetail(buffer, fieldName, array[i]);
+ }
+ buffer.append(arrayEnd);
+ }
+
+ /**
+ * Append to the toString
a summary of a
+ * double
array.
+ *
+ * @param buffer the StringBuffer
to populate
+ * @param fieldName the field name, typically not used as already appended
+ * @param array the array to add to the toString
,
+ * not null
+ */
+ protected void appendSummary(StringBuffer buffer, String fieldName, double[] array) {
+ appendSummarySize(buffer, fieldName, array.length);
+ }
+
+ //----------------------------------------------------------------------------
+
+ /**
+ * Append to the toString
a float
+ * array.
+ *
+ * @param buffer the StringBuffer
to populate
+ * @param fieldName the field name
+ * @param array the array to add to the toString
+ * @param fullDetail true
for detail, false
+ * for summary info, null
for style decides
+ */
+ public void append(StringBuffer buffer, String fieldName, float[] array, Boolean fullDetail) {
+ appendFieldStart(buffer, fieldName);
+
+ if (array == null) {
+ appendNullText(buffer, fieldName);
+
+ } else if (isFullDetail(fullDetail)) {
+ appendDetail(buffer, fieldName, array);
+
+ } else {
+ appendSummary(buffer, fieldName, array);
+ }
+
+ appendFieldEnd(buffer, fieldName);
+ }
+
+ /**
+ * Append to the toString
the detail of a
+ * float
array.
+ *
+ * @param buffer the StringBuffer
to populate
+ * @param fieldName the field name, typically not used as already appended
+ * @param array the array to add to the toString
,
+ * not null
+ */
+ protected void appendDetail(StringBuffer buffer, String fieldName, float[] array) {
+ buffer.append(arrayStart);
+ for (int i = 0; i < array.length; i++) {
+ if (i > 0) {
+ buffer.append(arraySeparator);
+ }
+ appendDetail(buffer, fieldName, array[i]);
+ }
+ buffer.append(arrayEnd);
+ }
+
+ /**
+ * Append to the toString
a summary of a
+ * float
array.
+ *
+ * @param buffer the StringBuffer
to populate
+ * @param fieldName the field name, typically not used as already appended
+ * @param array the array to add to the toString
,
+ * not null
+ */
+ protected void appendSummary(StringBuffer buffer, String fieldName, float[] array) {
+ appendSummarySize(buffer, fieldName, array.length);
+ }
+
+ //----------------------------------------------------------------------------
+
+ /**
+ * Append to the toString
a boolean
+ * array.
+ *
+ * @param buffer the StringBuffer
to populate
+ * @param fieldName the field name
+ * @param array the array to add to the toString
+ * @param fullDetail true
for detail, false
+ * for summary info, null
for style decides
+ */
+ public void append(StringBuffer buffer, String fieldName, boolean[] array, Boolean fullDetail) {
+ appendFieldStart(buffer, fieldName);
+
+ if (array == null) {
+ appendNullText(buffer, fieldName);
+
+ } else if (isFullDetail(fullDetail)) {
+ appendDetail(buffer, fieldName, array);
+
+ } else {
+ appendSummary(buffer, fieldName, array);
+ }
+
+ appendFieldEnd(buffer, fieldName);
+ }
+
+ /**
+ * Append to the toString
the detail of a
+ * boolean
array.
+ *
+ * @param buffer the StringBuffer
to populate
+ * @param fieldName the field name, typically not used as already appended
+ * @param array the array to add to the toString
,
+ * not null
+ */
+ protected void appendDetail(StringBuffer buffer, String fieldName, boolean[] array) {
+ buffer.append(arrayStart);
+ for (int i = 0; i < array.length; i++) {
+ if (i > 0) {
+ buffer.append(arraySeparator);
+ }
+ appendDetail(buffer, fieldName, array[i]);
+ }
+ buffer.append(arrayEnd);
+ }
+
+ /**
+ * Append to the toString
a summary of a
+ * boolean
array.
+ *
+ * @param buffer the StringBuffer
to populate
+ * @param fieldName the field name, typically not used as already appended
+ * @param array the array to add to the toString
,
+ * not null
+ */
+ protected void appendSummary(StringBuffer buffer, String fieldName, boolean[] array) {
+ appendSummarySize(buffer, fieldName, array.length);
+ }
+
+ //----------------------------------------------------------------------------
+
+ /**
+ * Append 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 (useShortClassName) {
+ buffer.append(getShortClassName(object.getClass()));
+ } else {
+ buffer.append(object.getClass().getName());
+ }
+ }
+ }
+
+ /**
+ * 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) {
+ buffer.append('@');
+ buffer.append(Integer.toHexString(System.identityHashCode(object)));
+ }
+ }
+
+ /**
+ * Appends with the same format as the default Object toString()
+ *
method. Appends the class name followed by
+ * {@link System#identityHashCode(java.lang.Object)}.
+ *
+ * @param buffer the StringBuffer
to populate
+ * @param object the Object
whose class name and id to output
+ */
+ protected void appendAsObjectToString(StringBuffer buffer, Object object) {
+ this.appendClassName(buffer, object);
+ this.appendIdentityHashCode(buffer, object);
+ }
+
+ /**
+ * Append the content start to the buffer.
+ *
+ * @param buffer the StringBuffer
to populate
+ */
+ protected void appendContentStart(StringBuffer buffer) {
+ buffer.append(contentStart);
+ }
+
+ /**
+ * Append the content end to the buffer.
+ *
+ * @param buffer the StringBuffer
to populate
+ */
+ protected void appendContentEnd(StringBuffer buffer) {
+ buffer.append(contentEnd);
+ }
+
+ /**
+ * Append an indicator for null
to the buffer.
+ *
+ * The default indicator is '<null>'
.
+ *
+ * @param buffer the StringBuffer
to populate
+ * @param fieldName the field name, typically not used as already appended
+ */
+ protected void appendNullText(StringBuffer buffer, String fieldName) {
+ buffer.append(nullText);
+ }
+
+ /**
+ * Append the field separator to the buffer.
+ *
+ * @param buffer the StringBuffer
to populate
+ */
+ protected void appendFieldSeparator(StringBuffer buffer) {
+ buffer.append(fieldSeparator);
+ }
+
+ /**
+ * Append the field start to the buffer.
+ *
+ * @param buffer the StringBuffer
to populate
+ * @param fieldName the field name
+ */
+ protected void appendFieldStart(StringBuffer buffer, String fieldName) {
+ if (useFieldNames && fieldName != null) {
+ buffer.append(fieldName);
+ buffer.append(fieldNameValueSeparator);
+ }
+ }
+
+ /**
+ * Append the field end to the buffer.
+ *
+ * @param buffer the StringBuffer
to populate
+ * @param fieldName the field name, typically not used as already appended
+ */
+ protected void appendFieldEnd(StringBuffer buffer, String fieldName) {
+ appendFieldSeparator(buffer);
+ }
+
+ /**
+ * Append to the toString
a size summary.
+ *
+ * The size summary is used to summarize the contents of
+ * Collections
, Maps
and arrays.
+ *
+ * The output consists of a prefix, the passed in size
+ * and a suffix.
+ *
+ * The default format is '<size=n>'.
+ *
+ * @param buffer the StringBuffer
to populate
+ * @param fieldName the field name, typically not used as already appended
+ * @param size the size to append
+ */
+ protected void appendSummarySize(StringBuffer buffer, String fieldName, int size) {
+ buffer.append(sizeStartText);
+ buffer.append(size);
+ buffer.append(sizeEndText);
+ }
+
+ /**
+ * Is this field to be output in full detail.
+ *
+ * This method converts a detail request into a detail level.
+ * The calling code may request full detail (true
),
+ * but a subclass might ignore that and always return
+ * false
. The calling code may pass in
+ * 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
+ */
+ protected boolean isFullDetail(Boolean fullDetailRequest) {
+ if (fullDetailRequest == null) {
+ return defaultFullDetail;
+ }
+ return fullDetailRequest.booleanValue();
+ }
+
+ /**
+ * Gets the short class name for a class.
+ *
+ * The short class name is the classname excluding
+ * the package name.
+ *
+ * @param cls the Class
to get the short name of
+ * @return the short name
+ */
+ protected String getShortClassName(Class cls) {
+ String name = cls.getName();
+ int pos = name.lastIndexOf('.');
+ if (pos == -1) {
+ return name;
+ }
+ return name.substring(pos + 1);
+ }
+
+ // Setters and getters for the customizable parts of the style
+ // These methods are not expected to be overridden, except to make public
+ // (They are not public so that immutable subclasses can be written)
+ //---------------------------------------------------------------------
+
+ /**
+ * Gets whether to use the class name.
+ *
+ * @return the current useClassName flag
+ */
+ protected boolean isUseClassName() {
+ return useClassName;
+ }
+
+ /**
+ * Sets whether to use the class name.
+ *
+ * @param useClassName the new useClassName flag
+ */
+ protected void setUseClassName(boolean useClassName) {
+ this.useClassName = useClassName;
+ }
+
+ //---------------------------------------------------------------------
+
+ /**
+ * Gets whether to output short or long class names.
+ *
+ * @return the current shortClassName flag
+ */
+ protected boolean isShortClassName() {
+ return useShortClassName;
+ }
+
+ /**
+ * Sets whether to output short or long class names.
+ *
+ * @param shortClassName the new shortClassName flag
+ */
+ protected void setShortClassName(boolean shortClassName) {
+ this.useShortClassName = shortClassName;
+ }
+
+ //---------------------------------------------------------------------
+
+ /**
+ * Gets whether to use the identity hash code.
+ *
+ * @return the current useIdentityHashCode flag
+ */
+ protected boolean isUseIdentityHashCode() {
+ return useIdentityHashCode;
+ }
+
+ /**
+ * Sets whether to use the identity hash code.
+ *
+ * @param useIdentityHashCode the new useIdentityHashCode flag
+ */
+ protected void setUseIdentityHashCode(boolean useIdentityHashCode) {
+ this.useIdentityHashCode = useIdentityHashCode;
+ }
+
+ //---------------------------------------------------------------------
+
+ /**
+ * Gets whether to use the field names passed in.
+ *
+ * @return the current useFieldNames flag
+ */
+ protected boolean isUseFieldNames() {
+ return useFieldNames;
+ }
+
+ /**
+ * Sets whether to use the field names passed in.
+ *
+ * @param useFieldNames the new useFieldNames flag
+ */
+ protected void setUseFieldNames(boolean useFieldNames) {
+ this.useFieldNames = useFieldNames;
+ }
+
+ //---------------------------------------------------------------------
+
+ /**
+ * Gets whether to use full detail when the caller doesn't
+ * specify.
+ *
+ * @return the current defaultFullDetail flag
+ */
+ protected boolean isDefaultFullDetail() {
+ return defaultFullDetail;
+ }
+
+ /**
+ * Sets whether to use full detail when the caller doesn't
+ * specify.
+ *
+ * @param defaultFullDetail the new defaultFullDetail flag
+ */
+ protected void setDefaultFullDetail(boolean defaultFullDetail) {
+ this.defaultFullDetail = defaultFullDetail;
+ }
+
+ //---------------------------------------------------------------------
+
+ /**
+ * Gets whether to output array content detail.
+ *
+ * @return the current array content detail setting
+ */
+ protected boolean isArrayContentDetail() {
+ return arrayContentDetail;
+ }
+
+ /**
+ * Sets whether to output array content detail.
+ *
+ * @param arrayContentDetail the new arrayContentDetail flag
+ */
+ protected void setArrayContentDetail(boolean arrayContentDetail) {
+ this.arrayContentDetail = arrayContentDetail;
+ }
+
+ //---------------------------------------------------------------------
+
+ /**
+ * Gets the array start text.
+ *
+ * @return the current array start text
+ */
+ protected String getArrayStart() {
+ return arrayStart;
+ }
+
+ /**
+ * Sets the array start text.
+ *
+ * Null
is accepted, but will be converted to
+ * a emptry String.
+ *
+ * @param arrayStart the new array start text
+ */
+ protected void setArrayStart(String arrayStart) {
+ if (arrayStart == null) {
+ arrayStart = "";
+ }
+ this.arrayStart = arrayStart;
+ }
+
+ //---------------------------------------------------------------------
+
+ /**
+ * Gets the array end text.
+ *
+ * @return the current array end text
+ */
+ protected String getArrayEnd() {
+ return arrayEnd;
+ }
+
+ /**
+ * Sets the array end text.
+ *
+ * Null
is accepted, but will be converted to
+ * a empty String.
+ *
+ * @param arrayEnd the new array end text
+ */
+ protected void setArrayEnd(String arrayEnd) {
+ if (arrayStart == null) {
+ arrayStart = "";
+ }
+ this.arrayEnd = arrayEnd;
+ }
+
+ //---------------------------------------------------------------------
+
+ /**
+ * Gets the array separator text.
+ *
+ * @return the current array separator text
+ */
+ protected String getArraySeparator() {
+ return arraySeparator;
+ }
+
+ /**
+ * Sets the array separator text.
+ *
+ * Null
is accepted, but will be converted to
+ * a empty String.
+ *
+ * @param arraySeparator the new array separator text
+ */
+ protected void setArraySeparator(String arraySeparator) {
+ if (arraySeparator == null) {
+ arraySeparator = "";
+ }
+ this.arraySeparator = arraySeparator;
+ }
+
+ //---------------------------------------------------------------------
+
+ /**
+ * Gets the content start text.
+ *
+ * @return the current content start text
+ */
+ protected String getContentStart() {
+ return contentStart;
+ }
+
+ /**
+ * Sets the content start text.
+ *
+ * Null
is accepted, but will be converted to
+ * a empty String.
+ *
+ * @param contentStart the new content start text
+ */
+ protected void setContentStart(String contentStart) {
+ if (contentStart == null) {
+ contentStart = "";
+ }
+ this.contentStart = contentStart;
+ }
+
+ //---------------------------------------------------------------------
+
+ /**
+ * Gets the content end text.
+ *
+ * @return the current content end text
+ */
+ protected String getContentEnd() {
+ return contentEnd;
+ }
+
+ /**
+ * Sets the content end text.
+ *
+ * Null
is accepted, but will be converted to
+ * a empty String.
+ *
+ * @param contentEnd the new content end text
+ */
+ protected void setContentEnd(String contentEnd) {
+ if (contentEnd == null) {
+ contentEnd = "";
+ }
+ this.contentEnd = contentEnd;
+ }
+
+ //---------------------------------------------------------------------
+
+ /**
+ * Gets the field name value separator text.
+ *
+ * @return the current field name value separator text
+ */
+ protected String getFieldNameValueSeparator() {
+ return fieldNameValueSeparator;
+ }
+
+ /**
+ * Sets the field name value separator text.
+ *
+ * Null
is accepted, but will be converted to
+ * a empty String.
+ *
+ * @param fieldNameValueSeparator the new field name value separator text
+ */
+ protected void setFieldNameValueSeparator(String fieldNameValueSeparator) {
+ if (fieldNameValueSeparator == null) {
+ fieldNameValueSeparator = "";
+ }
+ this.fieldNameValueSeparator = fieldNameValueSeparator;
+ }
+
+ //---------------------------------------------------------------------
+
+ /**
+ * Gets the field separator text.
+ *
+ * @return the current field separator text
+ */
+ protected String getFieldSeparator() {
+ return fieldSeparator;
+ }
+
+ /**
+ * Sets the field separator text.
+ *
+ * Null
is accepted, but will be converted to
+ * a empty String.
+ *
+ * @param fieldSeparator the new field separator text
+ */
+ protected void setFieldSeparator(String fieldSeparator) {
+ if (fieldSeparator == null) {
+ fieldSeparator = "";
+ }
+ this.fieldSeparator = fieldSeparator;
+ }
+
+ //---------------------------------------------------------------------
+
+ /**
+ * Gets whether the field separator should be added at the start
+ * of each buffer.
+ *
+ * @return the fieldSeparatorAtStart flag
+ */
+ protected boolean isFieldSeparatorAtStart() {
+ return fieldSeparatorAtStart;
+ }
+
+ /**
+ * Sets whether the field separator should be added at the start
+ * of each buffer.
+ *
+ * @param fieldSeparatorAtStart the fieldSeparatorAtStart flag
+ */
+ protected void setFieldSeparatorAtStart(boolean fieldSeparatorAtStart) {
+ this.fieldSeparatorAtStart = fieldSeparatorAtStart;
+ }
+
+ //---------------------------------------------------------------------
+
+ /**
+ * Gets whether the field separator should be added at the end
+ * of each buffer.
+ *
+ * @return fieldSeparatorAtEnd flag
+ */
+ protected boolean isFieldSeparatorAtEnd() {
+ return fieldSeparatorAtEnd;
+ }
+
+ /**
+ * Sets whether the field separator should be added at the end
+ * of each buffer.
+ *
+ * @param fieldSeparatorAtEnd the fieldSeparatorAtEnd flag
+ */
+ protected void setFieldSeparatorAtEnd(boolean fieldSeparatorAtEnd) {
+ this.fieldSeparatorAtEnd = fieldSeparatorAtEnd;
+ }
+
+ //---------------------------------------------------------------------
+
+ /**
+ * Gets the text to output when null
found.
+ *
+ * @return the current text to output when null found
+ */
+ protected String getNullText() {
+ return nullText;
+ }
+
+ /**
+ * Sets the text to output when null
found.
+ *
+ * Null
is accepted, but will be converted to
+ * a empty String.
+ *
+ * @param nullText the new text to output when null found
+ */
+ protected void setNullText(String nullText) {
+ if (nullText == null) {
+ nullText = "";
+ }
+ this.nullText = nullText;
+ }
+
+ //---------------------------------------------------------------------
+
+ /**
+ * Gets the text to output when a Collection
,
+ * Map
or array size is output.
+ *
+ * This is output before the size value.
+ *
+ * @return the current start of size text
+ */
+ protected String getSizeStartText() {
+ return sizeStartText;
+ }
+
+ /**
+ * Sets the text to output when a Collection
,
+ * Map
or array size is output.
+ *
+ * This is output before the size value.
+ *
+ * Null
is accepted, but will be converted to
+ * a empty String.
+ *
+ * @param sizeStartText the new start of size text
+ */
+ protected void setSizeStartText(String sizeStartText) {
+ if (sizeStartText == null) {
+ sizeStartText = "";
+ }
+ this.sizeStartText = sizeStartText;
+ }
+
+ //---------------------------------------------------------------------
+
+ /**
+ * Gets the text to output when a Collection
,
+ * Map
or array size is output.
+ *
+ * This is output after the size value.
+ *
+ * @return the current end of size text
+ */
+ protected String getSizeEndText() {
+ return sizeEndText;
+ }
+
+ /**
+ * Sets the text to output when a Collection
,
+ * Map
or array size is output.
+ *
+ * This is output after the size value.
+ *
+ * Null
is accepted, but will be converted to
+ * a empty String.
+ *
+ * @param sizeEndText the new end of size text
+ */
+ protected void setSizeEndText(String sizeEndText) {
+ if (sizeEndText == null) {
+ sizeEndText = "";
+ }
+ this.sizeEndText = sizeEndText;
+ }
+
+ //---------------------------------------------------------------------
+
+ /**
+ * Gets the text to output when an Object
is
+ * output in summary mode.
+ *
+ * This is output before the size value.
+ *
+ * @return the current start of summary text
+ */
+ protected String getSummaryObjectStartText() {
+ return summaryObjectStartText;
+ }
+
+ /**
+ * Sets the text to output when an Object
is
+ * output in summary mode.
+ *
+ * This is output before the size value.
+ *
+ * Null
is accepted, but will be converted to
+ * a empty String.
+ *
+ * @param summaryObjectStartText the new start of summary text
+ */
+ protected void setSummaryObjectStartText(String summaryObjectStartText) {
+ if (summaryObjectStartText == null) {
+ summaryObjectStartText = "";
+ }
+ this.summaryObjectStartText = summaryObjectStartText;
+ }
+
+ //---------------------------------------------------------------------
+
+ /**
+ * Gets the text to output when an Object
is
+ * output in summary mode.
+ *
+ * This is output after the size value.
+ *
+ * @return the current end of summary text
+ */
+ protected String getSummaryObjectEndText() {
+ return summaryObjectEndText;
+ }
+
+ /**
+ * Sets the text to output when an Object
is
+ * output in summary mode.
+ *
+ * This is output after the size value.
+ *
+ * Null
is accepted, but will be converted to
+ * a empty String.
+ *
+ * @param summaryObjectEndText the new end of summary text
+ */
+ protected void setSummaryObjectEndText(String summaryObjectEndText) {
+ if (summaryObjectEndText == null) {
+ summaryObjectEndText = "";
+ }
+ this.summaryObjectEndText = summaryObjectEndText;
+ }
+
+ //----------------------------------------------------------------------------
+
+ /**
+ * Default ToStringStyle
.
+ *
+ * This is an inner class rather than using
+ * StandardToStringStyle
to ensure its immutability.
+ */
+ private static final class DefaultToStringStyle extends ToStringStyle {
+
+ /**
+ * Constructor.
+ *
+ * Use the static constant rather than instantiating.
+ */
+ private DefaultToStringStyle() {
+ super();
+ }
+
+ /**
+ * Ensure Singleton
after serialization.
+ *
+ * @return the singleton
+ */
+ private Object readResolve() {
+ return ToStringStyle.DEFAULT_STYLE;
+ }
+
+ }
+
+ //----------------------------------------------------------------------------
+
+ /**
+ * ToStringStyle
that does not print out
+ * the field names.
+ *
+ * This is an inner class rather than using
+ * StandardToStringStyle
to ensure its immutability.
+ */
+ private static final class NoFieldNameToStringStyle extends ToStringStyle {
+
+ /**
+ *
Constructor.
+ *
+ * Use the static constant rather than instantiating.
+ */
+ private NoFieldNameToStringStyle() {
+ super();
+ this.setUseFieldNames(false);
+ }
+
+ /**
+ * Ensure Singleton
after serialization.
+ *
+ * @return the singleton
+ */
+ private Object readResolve() {
+ return ToStringStyle.NO_FIELD_NAMES_STYLE;
+ }
+
+ }
+
+ //----------------------------------------------------------------------------
+
+ /**
+ * ToStringStyle
that does not print out the
+ * classname, identity hashcode, content start or field name.
+ *
+ * This is an inner class rather than using
+ * StandardToStringStyle
to ensure its immutability.
+ */
+ private static final class SimpleToStringStyle extends ToStringStyle {
+
+ /**
+ * Constructor.
+ *
+ * Use the static constant rather than instantiating.
+ */
+ private SimpleToStringStyle() {
+ super();
+ this.setUseClassName(false);
+ this.setUseIdentityHashCode(false);
+ this.setUseFieldNames(false);
+ this.setContentStart("");
+ this.setContentEnd("");
+ }
+
+ /**
+ * Ensure Singleton after serialization.
+ * @return the singleton
+ */
+ private Object readResolve() {
+ return ToStringStyle.SIMPLE_STYLE;
+ }
+
+ }
+
+ //----------------------------------------------------------------------------
+
+ /**
+ * ToStringStyle
that outputs on multiple lines.
+ *
+ * This is an inner class rather than using
+ * StandardToStringStyle
to ensure its immutability.
+ */
+ private static final class MultiLineToStringStyle extends ToStringStyle {
+
+ /**
+ * Constructor.
+ *
+ * Use the static constant rather than instantiating.
+ */
+ private MultiLineToStringStyle() {
+ super();
+ this.setContentStart("[");
+ this.setFieldSeparator(SystemUtils.LINE_SEPARATOR + " ");
+ this.setFieldSeparatorAtStart(true);
+ this.setContentEnd(SystemUtils.LINE_SEPARATOR + "]");
+ }
+
+ /**
+ * Ensure Singleton
after serialization.
+ *
+ * @return the singleton
+ */
+ private Object readResolve() {
+ return ToStringStyle.MULTI_LINE_STYLE;
+ }
+
+ }
+
+ //----------------------------------------------------------------------------
+
+ // 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("\">");
+// }
+//
+// }
+
+}
diff --git a/examples/cl2/src/java/org/apache/commons/lang/builder/package.html b/examples/cl2/src/java/org/apache/commons/lang/builder/package.html
new file mode 100644
index 00000000..7d68184b
--- /dev/null
+++ b/examples/cl2/src/java/org/apache/commons/lang/builder/package.html
@@ -0,0 +1,6 @@
+
+
+Assists in creating good and consistent equals()
, toString()
,
+hashCode()
, and compareTo()
methods.
+
+
diff --git a/examples/cl2/src/java/org/apache/commons/lang/enums/Enum.java b/examples/cl2/src/java/org/apache/commons/lang/enums/Enum.java
new file mode 100644
index 00000000..248714cf
--- /dev/null
+++ b/examples/cl2/src/java/org/apache/commons/lang/enums/Enum.java
@@ -0,0 +1,496 @@
+/* ====================================================================
+ * 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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
+ * .
+ */
+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;
+/**
+ * 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 the equals() method, not ==. The equals() method will
+ * try == first so in most cases the effect is the same.
+ *
+ *
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 enums 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 class ExtraColorEnum extends ColorEnum {
+ * // NOTE: Color enums 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 using anonymous inner classes
+ * [Effective Java, Bloch01]:
+ *
+ *
+ * public abstract class OperationEnum extends Enum {
+ * public static final OperationEnum PLUS = new OperationEnum("Plus") {
+ * public double eval(double a, double b) {
+ * return (a + b);
+ * }
+ * };
+ * public static final OperationEnum MINUS = new OperationEnum("Minus") {
+ * public double eval(double a, double b) {
+ * return (a - b);
+ * }
+ * };
+ *
+ * private OperationEnum(String color) {
+ * super(color);
+ * }
+ *
+ * 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);
+ * }
+ * }
+ *
+ *
+ * NOTE: This class originated in the Jakarta Avalon project.
+ *
+ *
+ * @author Stephen Colebourne
+ * @author Chris Webb
+ * @author Mike Bowler
+ * @since 1.0
+ * @version $Id: Enum.java,v 1.10 2003/02/06 20:13:07 scolebourne Exp $
+ */
+public abstract class Enum implements Comparable, Serializable {
+ // 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 final Map cEnumClasses = new HashMap();
+ /**
+ * The string representation of the Enum.
+ */
+ private final String iName;
+
+ /**
+ * Enable the iterator to retain the source code order
+ */
+ private static class Entry {
+ /** Map of Enum name to Enum */
+ final Map map = new HashMap();
+ /** List of Enums in source code order */
+ final List list = new ArrayList(25);
+
+ /**
+ * Restrictive constructor
+ */
+ private Entry() {
+ }
+ }
+
+ /**
+ * Constructor to add a new named item to the enumeration.
+ *
+ * @param name the name of the enums object
+ * @throws IllegalArgumentException if the name is null or a blank string
+ */
+ protected Enum(String name) {
+ super();
+ if (name == null || name.length() == 0) {
+ throw new IllegalArgumentException("The Enum name must not be empty or null");
+ }
+ iName = name;
+ Class enumClass = Enum.getEnumClass(getClass());
+ Entry entry = (Entry) cEnumClasses.get(enumClass);
+ if (entry == null) {
+ entry = createEntry(getClass());
+ cEnumClasses.put(enumClass, entry);
+ }
+ 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 enums types created.
+ * @return the resolved object
+ */
+ protected Object readResolve() {
+ Entry entry = (Entry) cEnumClasses.get(Enum.getEnumClass(getClass()));
+ if (entry == null) {
+ return null;
+ }
+ return (Enum) 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 enums object, or null if the enums does not exist
+ * @throws IllegalArgumentException if the enums 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 enums objects an empty Map is returned.
+ *
+ * @param enumClass the class of the Enum to get, must not be null
+ * @return the enums object Map
+ * @throws IllegalArgumentException if the enums class is null
+ * @throws IllegalArgumentException if the enums class is not a subclass of Enum
+ */
+ protected static Map getEnumMap(Class enumClass) {
+ Entry entry = getEntry(enumClass);
+ if (entry == null) {
+ return EMPTY_MAP;
+ }
+ return Collections.unmodifiableMap(entry.map);
+ }
+
+ /**
+ * 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 enums objects an empty List is returned.
+ *
+ * @param enumClass the class of the Enum to get, must not be null
+ * @return the enums object Map
+ * @throws IllegalArgumentException if the enums class is null
+ * @throws IllegalArgumentException if the enums 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 Collections.unmodifiableList(entry.list);
+ }
+
+ /**
+ * 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 enums 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 enums class is null
+ * @throws IllegalArgumentException if the enums 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 enums 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);
+ 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 enums 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;
+ }
+
+ /**
+ * Convert a class to the actual common enums class.
+ * This accounts for anonymous inner classes.
+ *
+ * @param cls the class to get the name for
+ * @return the class name
+ */
+ protected static Class getEnumClass(Class cls) {
+ String className = cls.getName();
+ int index = className.lastIndexOf('$');
+ if (index > -1) {
+ // is it an anonymous inner class?
+ String inner = className.substring(index + 1);
+ if (inner.length() > 0 &&
+ inner.charAt(0) >= '0' &&
+ inner.charAt(0) < '9') {
+ return cls.getSuperclass();
+ }
+ }
+ return cls;
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * 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;
+ }
+
+ /**
+ * 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.
+ *
+ * @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()) {
+ // shouldn't happen, but...
+ return iName.equals(((Enum) other).iName);
+ } else if (getEnumClass(other.getClass()).getName().equals(getEnumClass(this.getClass()).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
+ }
+ return false;
+ }
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Returns a suitable hashCode for the enumeration.
+ *
+ * @return a hashcode based on the name
+ */
+ public final int hashCode() {
+ return 7 + iName.hashCode();
+ }
+
+ /**
+ * Tests for order. The default ordering is alphabetic by name, but this
+ * can be overridden by subclasses.
+ *
+ * @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) {
+ return iName.compareTo(((Enum) other).iName);
+ }
+
+ /**
+ * Human readable description of this Enum item. For use when debugging.
+ *
+ * @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() {
+ String shortName = Enum.getEnumClass(getClass()).getName();
+ int pos = shortName.lastIndexOf('.');
+ if (pos != -1) {
+ shortName = shortName.substring(pos + 1);
+ }
+ shortName = shortName.replace('$', '.');
+ return shortName + "[" + getName() + "]";
+ }
+}
diff --git a/examples/cl2/src/java/org/apache/commons/lang/enums/EnumUtils.java b/examples/cl2/src/java/org/apache/commons/lang/enums/EnumUtils.java
new file mode 100644
index 00000000..84740377
--- /dev/null
+++ b/examples/cl2/src/java/org/apache/commons/lang/enums/EnumUtils.java
@@ -0,0 +1,145 @@
+/* ====================================================================
+ * 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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
+ * .
+ */
+package org.apache.commons.lang.enums;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Utility class for accessing and manipulating Enums.
+ *
+ * @see Enum
+ * @see ValuedEnum
+ * @author Stephen Colebourne
+ * @since 1.0
+ * @version $Id: EnumUtils.java,v 1.6 2003/03/06 22:50:21 scolebourne Exp $
+ */
+public class EnumUtils {
+
+ /**
+ * Restricted constructor
+ */
+ private EnumUtils() {
+ }
+
+ /**
+ * 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 enums object
+ * @throws IllegalArgumentException if the enums 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 enums object, or null if the enums does not exist
+ * @throws IllegalArgumentException if the enums 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 enums objects an empty Map is returned.
+ * The Map is unmodifiable.
+ *
+ * @param enumClass the class of the Enum to get
+ * @return the enums object Map
+ * @throws IllegalArgumentException if the enums class is null
+ * @throws IllegalArgumentException if the enums 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 enums objects an empty List is returned.
+ * The List is unmodifiable.
+ *
+ * @param enumClass the class of the Enum to get
+ * @return the enums object Map
+ * @throws IllegalArgumentException if the enums class is null
+ * @throws IllegalArgumentException if the enums 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 enums 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 enums class is null
+ * @throws IllegalArgumentException if the enums class is not a subclass of Enum
+ */
+ public static Iterator iterator(Class enumClass) {
+ return Enum.getEnumList(enumClass).iterator();
+ }
+
+}
diff --git a/examples/cl2/src/java/org/apache/commons/lang/enums/ValuedEnum.java b/examples/cl2/src/java/org/apache/commons/lang/enums/ValuedEnum.java
new file mode 100644
index 00000000..88fa7086
--- /dev/null
+++ b/examples/cl2/src/java/org/apache/commons/lang/enums/ValuedEnum.java
@@ -0,0 +1,215 @@
+/* ====================================================================
+ * 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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
+ * .
+ */
+package org.apache.commons.lang.enums;
+
+import java.util.Iterator;
+import java.util.List;
+/**
+ * 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);
+ * }
+ * }
+ *
+ *
+ * The above class could then be used as follows:
+ *
+ * public void doSomething(JavaVersion ver) {
+ * switch (ver.getValue()) {
+ * case JAVA1_0_VALUE:
+ * // ...
+ * break;
+ * case JAVA1_1_VALUE:
+ * // ...
+ * break;
+ * //...
+ * }
+ * }
+ *
+ *
+ * As shown, each enums has a name and a value. These can be accessed using
+ * getName
and getValue
.
+ *
+ * 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.
+ *
+ * NOTE: This class originated in the Jakarta Avalon project.
+ *
+ *
+ * @author Stephen Colebourne
+ * @since 1.0
+ * @version $Id: ValuedEnum.java,v 1.5 2003/02/04 18:30:07 scolebourne Exp $
+ */
+public abstract class ValuedEnum extends Enum {
+ /**
+ * The value contained in enums.
+ */
+ private final int iValue;
+
+ /**
+ * Constructor for enums item.
+ *
+ * @param name the name of enums item.
+ * @param value the value of enums 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 Enums, thus if there
+ * are many Enums this will be slow.
+ *
+ * @param enumClass the class of the Enum to get
+ * @param value the value of the Enum to get
+ * @return the enums object, or null if the enums does not exist
+ * @throws IllegalArgumentException if the enums 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 enumx = (ValuedEnum) it.next();
+ if (enumx.getValue() == value) {
+ return enumx;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Get value of enums item.
+ *
+ * @return the enums 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.
+ *
+ * @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) {
+ return iValue - ((ValuedEnum) other).iValue;
+ }
+
+ /**
+ * Human readable description of this Enum item. For use when debugging.
+ *
+ * @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() {
+ String shortName = Enum.getEnumClass(getClass()).getName();
+ int pos = shortName.lastIndexOf('.');
+ if (pos != -1) {
+ shortName = shortName.substring(pos + 1);
+ }
+ shortName = shortName.replace('$', '.');
+ return shortName + "[" + getName() + "=" + getValue() + "]";
+ }
+}
diff --git a/examples/cl2/src/java/org/apache/commons/lang/enums/package.html b/examples/cl2/src/java/org/apache/commons/lang/enums/package.html
new file mode 100644
index 00000000..214f8d54
--- /dev/null
+++ b/examples/cl2/src/java/org/apache/commons/lang/enums/package.html
@@ -0,0 +1,34 @@
+
+
+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);
+ }
+}
+
+
+
diff --git a/examples/cl2/src/java/org/apache/commons/lang/exception/ExceptionUtils.java b/examples/cl2/src/java/org/apache/commons/lang/exception/ExceptionUtils.java
new file mode 100644
index 00000000..becc198a
--- /dev/null
+++ b/examples/cl2/src/java/org/apache/commons/lang/exception/ExceptionUtils.java
@@ -0,0 +1,593 @@
+/* ====================================================================
+ * 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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
+ * .
+ */
+package org.apache.commons.lang.exception;
+
+import java.io.PrintStream;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+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.SystemUtils;
+
+/**
+ * Provides utilities for manipulating and examining
+ * Throwable
objects.
+ *
+ * @author Daniel Rall
+ * @author Dmitri Plotnikov
+ * @author Stephen Colebourne
+ * @author Gary Gregory
+ * @since 1.0
+ * @version $Id: ExceptionUtils.java,v 1.24 2003/05/31 17:16:11 ggregory Exp $
+ */
+public class ExceptionUtils {
+
+ /**
+ * Used when printing stack frames to denote the start of a
+ * wrapped exception. Package private for accessibility by test
+ * suite.
+ */
+ static final String WRAPPED_MARKER = " [wrapped] ";
+
+ /**
+ * The names of methods commonly used to access a wrapped
+ * exception.
+ */
+ protected static String[] CAUSE_METHOD_NAMES = {
+ "getCause",
+ "getNextException",
+ "getTargetException",
+ "getException",
+ "getSourceException",
+ "getRootCause",
+ "getCausedByException",
+ "getNested"
+ };
+
+ /**
+ * Constructs a new ExceptionUtils
. Protected to
+ * discourage instantiation.
+ */
+ protected ExceptionUtils() {
+ }
+
+ /**
+ * Adds to the list of method names used in the search for Throwable
+ * objects.
+ *
+ * @param methodName the methodName to add to the list, null and empty strings are ignored
+ */
+ public static void addCauseMethodName(String methodName) {
+ if (methodName != null && methodName.length() > 0) {
+ List list = new ArrayList(Arrays.asList(CAUSE_METHOD_NAMES));
+ list.add(methodName);
+ CAUSE_METHOD_NAMES = (String[]) list.toArray(new String[list.size()]);
+ }
+ }
+
+ /**
+ * Introspects the specified 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
+ * {@link org.apache.commons.lang.exception.NestableException NestableException}.
+ * The method names can be added to using {@link #addCauseMethodName(String)}.
+ * The default list searched for are:
+ *
+ * getCause()
+ * getNextException()
+ * getTargetException()
+ * getException()
+ * getSourceException()
+ * getRootCause()
+ * getCausedByException()
+ * getNested()
+ *
+ *
+ * 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 exception to introspect for a cause.
+ * @return The cause of the Throwable
.
+ * @throws NullPointerException if the throwable is null
+ */
+ public static Throwable getCause(Throwable throwable) {
+ return getCause(throwable, CAUSE_METHOD_NAMES);
+ }
+
+ /**
+ * Introspects the specified Throwable
to obtain the cause
+ * using a supplied array of method names.
+ *
+ * @param throwable The exception to introspect for a cause.
+ * @return The cause of the Throwable
.
+ * @throws NullPointerException if the method names array is null or contains null
+ * @throws NullPointerException if the throwable is null
+ */
+ public static Throwable getCause(Throwable throwable, String[] methodNames) {
+ Throwable cause = getCauseUsingWellKnownTypes(throwable);
+ if (cause == null) {
+ for (int i = 0; i < methodNames.length; i++) {
+ cause = getCauseUsingMethodName(throwable, methodNames[i]);
+ if (cause != null) {
+ break;
+ }
+ }
+
+ if (cause == null) {
+ cause = getCauseUsingFieldName(throwable, "detail");
+ }
+ }
+ return cause;
+ }
+
+ /**
+ * Walks through the exception chain to the last element -- the
+ * "root" of the tree -- using {@link #getCause(Throwable)}, and
+ * returns that exception.
+ *
+ * @param throwable the throwable to get the root cause for
+ * @return The root cause of the Throwable
.
+ */
+ public static Throwable getRootCause(Throwable throwable) {
+ Throwable cause = getCause(throwable);
+ if (cause != null) {
+ throwable = cause;
+ while ((throwable = getCause(throwable)) != null) {
+ cause = throwable;
+ }
+ }
+ return cause;
+ }
+
+ /**
+ * Uses instanceof
checks to examine the exception,
+ * looking for well known types which could contain chained or
+ * wrapped exceptions.
+ *
+ * @param throwable the exception to examine
+ * @return The wrapped exception, or null
if not
+ * found.
+ */
+ private static Throwable getCauseUsingWellKnownTypes(Throwable throwable) {
+ if (throwable instanceof Nestable) {
+ return ((Nestable) throwable).getCause();
+ } else if (throwable instanceof SQLException) {
+ return ((SQLException) throwable).getNextException();
+ } else if (throwable instanceof InvocationTargetException) {
+ return ((InvocationTargetException) throwable).getTargetException();
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * 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.
+ */
+ private static Throwable getCauseUsingMethodName(Throwable throwable, String methodName) {
+ Method method = null;
+ try {
+ method = throwable.getClass().getMethod(methodName, null);
+ } catch (NoSuchMethodException ignored) {
+ } catch (SecurityException ignored) {
+ }
+
+ if (method != null && Throwable.class.isAssignableFrom(method.getReturnType())) {
+ try {
+ return (Throwable) method.invoke(throwable, ArrayUtils.EMPTY_OBJECT_ARRAY);
+ } catch (IllegalAccessException ignored) {
+ } catch (IllegalArgumentException ignored) {
+ } catch (InvocationTargetException 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.
+ */
+ private static Throwable getCauseUsingFieldName(Throwable throwable, String fieldName) {
+ Field field = null;
+ try {
+ field = throwable.getClass().getField(fieldName);
+ } catch (NoSuchFieldException ignored) {
+ } catch (SecurityException ignored) {
+ }
+
+ if (field != null && Throwable.class.isAssignableFrom(field.getType())) {
+ try {
+ return (Throwable) field.get(throwable);
+ } catch (IllegalAccessException ignored) {
+ } catch (IllegalArgumentException ignored) {
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Returns the number of Throwable
objects in the
+ * exception chain.
+ *
+ * @param throwable the exception to inspect
+ * @return The throwable count.
+ */
+ public static int getThrowableCount(Throwable throwable) {
+ // Count the number of throwables
+ int count = 0;
+ while (throwable != null) {
+ count++;
+ throwable = ExceptionUtils.getCause(throwable);
+ }
+ return count;
+ }
+
+ /**
+ * Returns the list of Throwable
objects in the
+ * exception chain.
+ *
+ * @param throwable the exception to inspect
+ * @return The list of Throwable
objects.
+ */
+ public static Throwable[] getThrowables(Throwable throwable) {
+ List list = new ArrayList();
+ while (throwable != null) {
+ list.add(throwable);
+ throwable = ExceptionUtils.getCause(throwable);
+ }
+ return (Throwable[]) list.toArray(new Throwable[list.size()]);
+ }
+
+ /**
+ * Delegates to {@link #indexOfThrowable(Throwable, Class, int)},
+ * starting the search at the beginning of the exception chain.
+ *
+ * @see #indexOfThrowable(Throwable, Class, int)
+ */
+ public static int indexOfThrowable(Throwable throwable, Class type) {
+ return indexOfThrowable(throwable, type, 0);
+ }
+
+ /**
+ * Returns the (zero based) index, of the first
+ * Throwable
that matches the specified type in the
+ * exception chain of Throwable
objects with an index
+ * greater than or equal to the specified index, or
+ * -1
if the type is not found.
+ *
+ * @param throwable the exception to inspect
+ * @param type Class
to look for
+ * @param fromIndex the (zero based) index of the starting
+ * position in the chain to be searched
+ * @return 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.
+ */
+ public static int indexOfThrowable(Throwable throwable, Class type, int fromIndex) {
+ if (fromIndex < 0) {
+ throw new IndexOutOfBoundsException("Throwable index out of range: " + fromIndex);
+ }
+ Throwable[] throwables = ExceptionUtils.getThrowables(throwable);
+ if (fromIndex >= throwables.length) {
+ throw new IndexOutOfBoundsException("Throwable index out of range: " + fromIndex);
+ }
+ for (int i = fromIndex; i < throwables.length; i++) {
+ if (throwables[i].getClass().equals(type)) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * Prints a compact stack trace for the root cause of a throwable.
+ * 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 method is equivalent to t.printStackTrace() for throwables
+ * that don't have nested causes.
+ */
+ public static void printRootCauseStackTrace(Throwable t, PrintStream stream) {
+ String trace[] = getRootCauseStackTrace(t);
+ for (int i = 0; i < trace.length; i++) {
+ stream.println(trace[i]);
+ }
+ stream.flush();
+ }
+
+ /**
+ * Equivalent to printRootCauseStackTrace(t, System.err);
+ *
+ * @see #printRootCauseStackTrace(Throwable,PrintWriter)
+ */
+ public static void printRootCauseStackTrace(Throwable t) {
+ printRootCauseStackTrace(t, System.err);
+ }
+
+ /**
+ * Same as {@link #printRootCauseStackTrace(Throwable,java.io.PrintStream)}, except it takes
+ * a PrintWriter as an argument.
+ */
+ public static void printRootCauseStackTrace(Throwable t, PrintWriter writer) {
+ String trace[] = getRootCauseStackTrace(t);
+ for (int i = 0; i < trace.length; i++) {
+ writer.println(trace[i]);
+ }
+ writer.flush();
+ }
+
+ /**
+ * Creates a compact stack trace for the root cause of the supplied
+ * Throwable
.
+ */
+ public static String[] getRootCauseStackTrace(Throwable t) {
+ Throwable throwables[] = getThrowables(t);
+ int count = throwables.length;
+ ArrayList frames = new ArrayList();
+ List nextTrace = getStackFrameList(throwables[count - 1]);
+ for (int i = count; --i >= 0;) {
+ List trace = nextTrace;
+ if (i != 0) {
+ nextTrace = getStackFrameList(throwables[i - 1]);
+ removeCommonFrames(trace, nextTrace);
+ }
+ if (i == count - 1) {
+ frames.add(throwables[i].toString());
+ } else {
+ frames.add(WRAPPED_MARKER + throwables[i].toString());
+ }
+ for (int j = 0; j < trace.size(); j++) {
+ frames.add(trace.get(j));
+ }
+ }
+ return (String[]) frames.toArray(new String[0]);
+ }
+
+ /**
+ * 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
+ */
+ public static void removeCommonFrames(List causeFrames, List wrapperFrames) {
+ int causeFrameIndex = causeFrames.size() - 1;
+ int wrapperFrameIndex = wrapperFrames.size() - 1;
+ while (causeFrameIndex >= 0 && wrapperFrameIndex >= 0) {
+ // Remove the frame from the cause trace if it is the same
+ // as in the wrapper trace
+ String causeFrame = (String) causeFrames.get(causeFrameIndex);
+ String wrapperFrame = (String) wrapperFrames.get(wrapperFrameIndex);
+ if (causeFrame.equals(wrapperFrame)) {
+ causeFrames.remove(causeFrameIndex);
+ }
+ causeFrameIndex--;
+ wrapperFrameIndex--;
+ }
+ }
+
+ /**
+ * A convenient way of extracting the stack trace from an
+ * exception.
+ *
+ * @param t The Throwable
.
+ * @return The stack trace as generated by the exception's
+ * printStackTrace(PrintWriter)
method.
+ */
+ public static String getStackTrace(Throwable t) {
+ StringWriter sw = new StringWriter();
+ PrintWriter pw = new PrintWriter(sw, true);
+ t.printStackTrace(pw);
+ return sw.getBuffer().toString();
+ }
+
+ /**
+ * A way to get the entire nested stack-trace of an throwable.
+ *
+ * @param t The Throwable
.
+ * @return The nested stack trace, with the root cause first.
+ */
+ public static String getFullStackTrace(Throwable t) {
+ StringWriter sw = new StringWriter();
+ PrintWriter pw = new PrintWriter(sw, true);
+ Throwable[] ts = getThrowables(t);
+ for(int i=0; iThrowable
is considered nested or not.
+ *
+ * @param t The Throwable
.
+ * @return boolean true/false
+ */
+ public static boolean isNestedThrowable(Throwable throwable) {
+ if(throwable == null) {
+ return false;
+ }
+
+ if (throwable instanceof Nestable) {
+ return true;
+ } else if (throwable instanceof SQLException) {
+ return true;
+ } else if (throwable instanceof InvocationTargetException) {
+ return true;
+ }
+
+ int sz = CAUSE_METHOD_NAMES.length;
+ for(int i=0; iThrowable
object, decomposing it into a list of
+ * stack frames.
+ *
+ * @param t The Throwable
.
+ * @return An array of strings describing each stack frame.
+ */
+ public static String[] getStackFrames(Throwable t) {
+ return getStackFrames(getStackTrace(t));
+ }
+
+ /**
+ * Functionality shared between the
+ * getStackFrames(Throwable)
methods of this and the
+ * {@link org.apache.commons.lang.exception.NestableDelegate}
+ * classes.
+ */
+ static String[] getStackFrames(String stackTrace) {
+ String linebreak = SystemUtils.LINE_SEPARATOR;
+ StringTokenizer frames = new StringTokenizer(stackTrace, linebreak);
+ List list = new LinkedList();
+ while (frames.hasMoreTokens()) {
+ list.add(frames.nextToken());
+ }
+ return (String[]) list.toArray(new String[] {
+ });
+ }
+
+ /**
+ * Produces a List of stack frames - the message is not included.
+ * This works in most cases - it will only fail if the exception message
+ * contains a line that starts with: " at".
+ *
+ * @param t is any throwable
+ * @return List of stack frames
+ */
+ static List getStackFrameList(Throwable t) {
+ String stackTrace = getStackTrace(t);
+ String linebreak = SystemUtils.LINE_SEPARATOR;
+ StringTokenizer frames = new StringTokenizer(stackTrace, linebreak);
+ List list = new LinkedList();
+ boolean traceStarted = false;
+ while (frames.hasMoreTokens()) {
+ String token = frames.nextToken();
+ // Determine if the line starts with at
+ int at = token.indexOf("at");
+ if (at != -1 && token.substring(0, at).trim().length() == 0) {
+ traceStarted = true;
+ list.add(token);
+ } else if (traceStarted) {
+ break;
+ }
+ }
+ return list;
+ }
+
+ private static Object getCauseMethod = null;
+ static {
+ try {
+ getCauseMethod = Throwable.class.getMethod("getCause", null);
+ } catch (Exception e) {
+ // ignore
+ }
+ }
+
+ /**
+ * Checks if the Throwable class has a getCause
method.
+ */
+ public static boolean isThrowableNested() {
+ return (getCauseMethod != null);
+ }
+}
diff --git a/examples/cl2/src/java/org/apache/commons/lang/exception/Nestable.java b/examples/cl2/src/java/org/apache/commons/lang/exception/Nestable.java
new file mode 100644
index 00000000..c07ccc84
--- /dev/null
+++ b/examples/cl2/src/java/org/apache/commons/lang/exception/Nestable.java
@@ -0,0 +1,199 @@
+/* ====================================================================
+ * 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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
+ * .
+ */
+package org.apache.commons.lang.exception;
+
+import java.io.PrintStream;
+import java.io.PrintWriter;
+
+/**
+ * An interface to be implemented by {@link java.lang.Throwable}
+ * extensions which would like to be able to nest root exceptions
+ * inside themselves.
+ *
+ * @author Daniel Rall
+ * @author Kasper Nielsen
+ * @author Steven Caswell
+ * @since 1.0
+ * @version $Id: Nestable.java,v 1.6 2003/03/23 17:47:51 scolebourne Exp $
+ */
+public interface Nestable {
+
+ /**
+ * Returns the reference to the exception or error that caused the
+ * exception implementing the Nestable
to be thrown.
+ */
+ public Throwable getCause();
+
+ /**
+ * Returns the error message of this and any nested
+ * Throwable
.
+ *
+ * @return the error message
+ */
+ public String getMessage();
+
+ /**
+ * 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
+ */
+ public String getMessage(int index);
+
+ /**
+ * 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
+ */
+ public String[] getMessages();
+
+ /**
+ * Returns the Throwable
in the chain of
+ * Throwable
s at the specified index, numbererd from 0.
+ *
+ * @param index the index, numbered from 0, of the Throwable
in
+ * the chain of Throwable
s
+ * @return the Throwable
+ * @throws IndexOutOfBoundsException if the index
argument is
+ * negative or not less than the count of Throwable
s in the
+ * chain
+ */
+ public Throwable getThrowable(int index);
+
+ /**
+ * Returns the number of nested Throwable
s represented by
+ * this Nestable
, including this Nestable
.
+ *
+ * @return the throwable count
+ */
+ public int getThrowableCount();
+
+ /**
+ * Returns this Nestable
and any nested Throwable
s
+ * in an array of Throwable
s, one element for each
+ * Throwable
.
+ *
+ * @return the Throwable
s
+ */
+ public Throwable[] getThrowables();
+
+ /**
+ * 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.
+ *
+ * @param type Class
to be found
+ * @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.
+ *
+ * @param type Class
to be found
+ * @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
+ * 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
+ */
+ public int indexOfThrowable(Class type, int fromIndex);
+
+ /**
+ * Prints the stack trace of this exception to the specified print
+ * writer. Includes inforamation from the exception--if
+ * any--which caused this exception.
+ *
+ * @param out PrintWriter
to use for output.
+ */
+ public void printStackTrace(PrintWriter out);
+
+ /**
+ * Prints the stack trace of this exception to the specified print
+ * stream. Includes inforamation from the exception--if
+ * any--which caused this exception.
+ *
+ * @param out PrintStream
to use for output.
+ */
+ public void printStackTrace(PrintStream out);
+
+ /**
+ * 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
+ * individual stack traces to a buffer. The implementation of
+ * this method should call
+ * super.printStackTrace(out);
in most cases.
+ *
+ * @param out The writer to use.
+ */
+ public void printPartialStackTrace(PrintWriter out);
+}
diff --git a/examples/cl2/src/java/org/apache/commons/lang/exception/NestableDelegate.java b/examples/cl2/src/java/org/apache/commons/lang/exception/NestableDelegate.java
new file mode 100644
index 00000000..0fe9d925
--- /dev/null
+++ b/examples/cl2/src/java/org/apache/commons/lang/exception/NestableDelegate.java
@@ -0,0 +1,379 @@
+/* ====================================================================
+ * 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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
+ * .
+ */
+package org.apache.commons.lang.exception;
+
+import java.io.PrintStream;
+import java.io.PrintWriter;
+import java.io.Serializable;
+import java.io.StringWriter;
+import java.util.*;
+
+/**
+ * NestableDelegate
is a shared implementation of the nestable
+ * exception functionality.
+ *
+ * The code is shared between
+ * {@link org.apache.commons.lang.exception.NestableError NestableError},
+ * {@link org.apache.commons.lang.exception.NestableException NestableException} and
+ * {@link org.apache.commons.lang.exception.NestableRuntimeException NestableRuntimeException}.
+ *
+ * @author Rafal Krzewski
+ * @author Daniel Rall
+ * @author Kasper Nielsen
+ * @author Steven Caswell
+ * @author Sean C. Sullivan
+ * @author Stephen Colebourne
+ * @since 1.0
+ * @version $Id: NestableDelegate.java,v 1.14 2003/06/10 06:16:54 scolebourne Exp $
+ */
+public class NestableDelegate implements Serializable {
+
+ /**
+ * Constructor error message.
+ */
+ private transient static final String MUST_BE_THROWABLE =
+ "The Nestable implementation passed to the NestableDelegate(Nestable) "
+ + "constructor must extend java.lang.Throwable";
+
+ /**
+ * Holds the reference to the exception or error that we're
+ * wrapping (which must be a {@link
+ * org.apache.commons.lang.exception.Nestable} implementation).
+ */
+ private Throwable nestable = null;
+
+ /**
+ * Whether to print the stack trace top-down.
+ */
+ public static boolean topDown = true;
+
+ /**
+ * Whether to trim the repeated stack trace.
+ */
+ public static boolean trimStackFrames = true;
+
+ /**
+ * Constructs a new NestableDelegate
instance to manage the
+ * specified Nestable
.
+ *
+ * @param nestable the Nestable implementation (must extend
+ * {@link java.lang.Throwable})
+ */
+ public NestableDelegate(Nestable nestable) {
+ if (nestable instanceof Throwable) {
+ this.nestable = (Throwable) nestable;
+ } else {
+ throw new IllegalArgumentException(MUST_BE_THROWABLE);
+ }
+ }
+
+ /**
+ * 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
+ */
+ public String getMessage(int index) {
+ Throwable t = this.getThrowable(index);
+ if (Nestable.class.isInstance(t)) {
+ return ((Nestable) t).getMessage(0);
+ } else {
+ 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
+ */
+ 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);
+ }
+
+ }
+ return (msg.length() > 0 ? msg.toString() : null);
+ }
+
+ /**
+ * 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
+ */
+ public String[] getMessages() {
+ Throwable[] throwables = this.getThrowables();
+ String[] msgs = new String[throwables.length];
+ for (int i = 0; i < throwables.length; i++) {
+ msgs[i] =
+ (Nestable.class.isInstance(throwables[i])
+ ? ((Nestable) throwables[i]).getMessage(0)
+ : throwables[i].getMessage());
+ }
+ return msgs;
+ }
+
+ /**
+ * Returns the Throwable
in the chain of
+ * Throwable
s at the specified index, numbererd from 0.
+ *
+ * @param index the index, numbered from 0, of the Throwable
in
+ * the chain of Throwable
s
+ * @return the Throwable
+ * @throws IndexOutOfBoundsException if the index
argument is
+ * negative or not less than the count of Throwable
s in the
+ * chain
+ */
+ public Throwable getThrowable(int index) {
+ if (index == 0) {
+ return this.nestable;
+ }
+ Throwable[] throwables = this.getThrowables();
+ return throwables[index];
+ }
+
+ /**
+ * Returns the number of Throwable
s contained in the
+ * Nestable
contained by this delegate.
+ *
+ * @return the throwable count
+ */
+ public int getThrowableCount() {
+ return ExceptionUtils.getThrowableCount(this.nestable);
+ }
+
+ /**
+ * Returns this delegate's Nestable
and any nested
+ * Throwable
s in an array of Throwable
s, one
+ * element for each Throwable
.
+ *
+ * @return the Throwable
s
+ */
+ public Throwable[] getThrowables() {
+ return ExceptionUtils.getThrowables(this.nestable);
+ }
+
+ /**
+ * 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.
+ *
+ * @param type Class
to be found
+ * @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
+ * 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
+ */
+ public int indexOfThrowable(Class type, int fromIndex) {
+ return ExceptionUtils.indexOfThrowable(this.nestable, type, fromIndex);
+ }
+
+ /**
+ * Prints the stack trace of this exception the the standar error
+ * stream.
+ */
+ public void printStackTrace() {
+ printStackTrace(System.err);
+ }
+
+ /**
+ * Prints the stack trace of this exception to the specified
+ * stream.
+ *
+ * @param out PrintStream
to use for output.
+ * @see #printStackTrace(PrintWriter)
+ */
+ public void printStackTrace(PrintStream out) {
+ synchronized (out) {
+ PrintWriter pw = new PrintWriter(out, false);
+ printStackTrace(pw);
+ // Flush the PrintWriter before it's GC'ed.
+ pw.flush();
+ }
+ }
+
+ /**
+ * Prints the stack trace of this exception to the specified
+ * writer. If the Throwable class has a getCause
+ * method (i.e. running on jre1.4 or higher), this method just
+ * uses Throwable's printStackTrace() method. Otherwise, generates
+ * the stack-trace, by taking into account the 'topDown' and
+ * 'trimStackFrames' parameters. The topDown and trimStackFrames
+ * are set to 'true' by default (produces jre1.4-like stack trace).
+ *
+ * @param out PrintWriter
to use for output.
+ */
+ public void printStackTrace(PrintWriter out) {
+ Throwable throwable = this.nestable;
+ // if running on jre1.4 or higher, use default printStackTrace
+ if (ExceptionUtils.isThrowableNested()) {
+ if (throwable instanceof Nestable) {
+ ((Nestable)throwable).printPartialStackTrace(out);
+ } else {
+ throwable.printStackTrace(out);
+ }
+ return;
+ }
+
+ // generating the nested stack trace
+ List stacks = new ArrayList();
+ while (throwable != null) {
+ String[] st = getStackFrames(throwable);
+ stacks.add(st);
+ throwable = ExceptionUtils.getCause(throwable);
+ }
+
+ // If NOT topDown, reverse the stack
+ String separatorLine = "Caused by: ";
+ if (!topDown) {
+ separatorLine = "Rethrown as: ";
+ Collections.reverse(stacks);
+ }
+
+ // Remove the repeated lines in the stack
+ 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())
+ out.print(separatorLine);
+ }
+ }
+ }
+
+ /**
+ * Captures the stack trace associated with the specified
+ * Throwable
object, decomposing it into a list of
+ * stack frames.
+ *
+ * @param t The Throwable
.
+ * @return An array of strings describing each stack frame.
+ */
+ protected String[] getStackFrames(Throwable t) {
+ StringWriter sw = new StringWriter();
+ PrintWriter pw = new PrintWriter(sw, true);
+
+ // Avoid infinite loop between decompose() and printStackTrace().
+ if (t instanceof Nestable) {
+ ((Nestable) t).printPartialStackTrace(pw);
+ } else {
+ t.printStackTrace(pw);
+ }
+ return ExceptionUtils.getStackFrames(sw.getBuffer().toString());
+ }
+
+ /**
+ * Trims the stack frames. The first set is left untouched. The rest
+ * of the frames are truncated from the bottom by comparing with
+ * one just on top.
+ *
+ * @param stacks The list containing String[] elements
+ */
+ protected void trimStackFrames(List stacks) {
+ for (int size=stacks.size(), i=size-1; i > 0; i--) {
+ String[] curr = (String[]) stacks.get(i);
+ String[] next = (String[]) stacks.get(i-1);
+
+ List currList = new ArrayList(Arrays.asList(curr));
+ List nextList = new ArrayList(Arrays.asList(next));
+ ExceptionUtils.removeCommonFrames(currList, nextList);
+
+ int trimmed = curr.length - currList.size();
+ if (trimmed > 0) {
+ currList.add("\t... "+trimmed+" more");
+ stacks.set(
+ i,
+ (String[])currList.toArray(new String[currList.size()])
+ );
+ }
+ }
+ }
+}
diff --git a/examples/cl2/src/java/org/apache/commons/lang/exception/NestableError.java b/examples/cl2/src/java/org/apache/commons/lang/exception/NestableError.java
new file mode 100644
index 00000000..21402109
--- /dev/null
+++ b/examples/cl2/src/java/org/apache/commons/lang/exception/NestableError.java
@@ -0,0 +1,190 @@
+/* ====================================================================
+ * 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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
+ * .
+ */
+package org.apache.commons.lang.exception;
+
+import java.io.PrintStream;
+import java.io.PrintWriter;
+
+/**
+ * The base class of all errors which can contain other exceptions.
+ *
+ * @author Daniel Rall
+ * @see org.apache.commons.lang.exception.NestableException
+ * @since 1.0
+ * @version $Id: NestableError.java,v 1.6 2003/05/14 02:59:13 bayard Exp $
+ */
+public class NestableError extends Error implements Nestable {
+
+ /**
+ * The helper instance which contains much of the code which we
+ * delegate to.
+ */
+ protected NestableDelegate delegate = new NestableDelegate(this);
+
+ /**
+ * Holds the reference to the exception or error that caused
+ * this exception to be thrown.
+ */
+ private Throwable cause = null;
+
+ /**
+ * Constructs a new NestableError
without specified
+ * detail message.
+ */
+ public NestableError() {
+ super();
+ }
+
+ /**
+ * Constructs a new NestableError
with specified
+ * detail message.
+ *
+ * @param msg The error message.
+ */
+ public NestableError(String msg) {
+ super(msg);
+ }
+
+ /**
+ * Constructs a new NestableError
with specified
+ * nested Throwable
.
+ *
+ * @param cause the exception or error that caused this exception to be
+ * thrown
+ */
+ public NestableError(Throwable cause) {
+ super();
+ this.cause = cause;
+ }
+
+ /**
+ * Constructs a new NestableError
with specified
+ * detail message and nested Throwable
.
+ *
+ * @param msg the error message
+ * @param cause the exception or error that caused this exception to be
+ * thrown
+ */
+ public NestableError(String msg, Throwable cause) {
+ super(msg);
+ this.cause = cause;
+ }
+
+ public Throwable getCause() {
+ return cause;
+ }
+
+ /**
+ * Returns the detail message string of this throwable. If it was
+ * created with a null message, returns the following:
+ * (cause==null ? null : cause.toString()).
+ */
+ public String getMessage() {
+ if (super.getMessage() != null) {
+ return super.getMessage();
+ } else if (cause != null) {
+ return cause.toString();
+ } else {
+ return null;
+ }
+ }
+
+ public String getMessage(int index) {
+ if (index == 0) {
+ return super.getMessage();
+ } else {
+ return delegate.getMessage(index);
+ }
+ }
+
+ public String[] getMessages() {
+ return delegate.getMessages();
+ }
+
+ public Throwable getThrowable(int index) {
+ return delegate.getThrowable(index);
+ }
+
+ public int getThrowableCount() {
+ return delegate.getThrowableCount();
+ }
+
+ public Throwable[] getThrowables() {
+ return delegate.getThrowables();
+ }
+
+ public int indexOfThrowable(Class type) {
+ return delegate.indexOfThrowable(type, 0);
+ }
+
+ public int indexOfThrowable(Class type, int fromIndex) {
+ return delegate.indexOfThrowable(type, fromIndex);
+ }
+
+ public void printStackTrace() {
+ delegate.printStackTrace();
+ }
+
+ public void printStackTrace(PrintStream out) {
+ delegate.printStackTrace(out);
+ }
+
+ public void printStackTrace(PrintWriter out) {
+ delegate.printStackTrace(out);
+ }
+
+ public final void printPartialStackTrace(PrintWriter out) {
+ super.printStackTrace(out);
+ }
+}
diff --git a/examples/cl2/src/java/org/apache/commons/lang/exception/NestableException.java b/examples/cl2/src/java/org/apache/commons/lang/exception/NestableException.java
new file mode 100644
index 00000000..14fd219b
--- /dev/null
+++ b/examples/cl2/src/java/org/apache/commons/lang/exception/NestableException.java
@@ -0,0 +1,251 @@
+/* ====================================================================
+ * 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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
+ * .
+ */
+package org.apache.commons.lang.exception;
+
+import java.io.PrintStream;
+import java.io.PrintWriter;
+
+/**
+ * The base class of all exceptions which can contain other exceptions.
+ *
+ * It is intended to ease the debugging by carrying on the information
+ * 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
+ * exception is finally printed out using any of the
+ * printStackTrace()
methods, the stacktrace will contain
+ * the information about all exceptions thrown and caught on
+ * the way.
+ *
Running the following program
+ *
+ * 1 import org.apache.commons.lang.exception.NestableException;
+ * 2
+ * 3 public class Test {
+ * 4 public static void main( String[] args ) {
+ * 5 try {
+ * 6 a();
+ * 7 } catch(Exception e) {
+ * 8 e.printStackTrace();
+ * 9 }
+ * 10 }
+ * 11
+ * 12 public static void a() throws Exception {
+ * 13 try {
+ * 14 b();
+ * 15 } catch(Exception e) {
+ * 16 throw new NestableException("foo", e);
+ * 17 }
+ * 18 }
+ * 19
+ * 20 public static void b() throws Exception {
+ * 21 try {
+ * 22 c();
+ * 23 } catch(Exception e) {
+ * 24 throw new NestableException("bar", e);
+ * 25 }
+ * 26 }
+ * 27
+ * 28 public static void c() throws Exception {
+ * 29 throw new Exception("baz");
+ * 30 }
+ * 31 }
+ *
+ * Yields the following stacktrace:
+ *
+ * org.apache.commons.lang.exception.NestableException: foo
+ * at Test.a(Test.java:16)
+ * at Test.main(Test.java:6)
+ * Caused by: org.apache.commons.lang.exception.NestableException: bar
+ * at Test.b(Test.java:24)
+ * at Test.a(Test.java:14)
+ * ... 1 more
+ * Caused by: java.lang.Exception: baz
+ * at Test.c(Test.java:29)
+ * at Test.b(Test.java:22)
+ * ... 2 more
+ *
+ *
+ * @author Rafal Krzewski
+ * @author Daniel Rall
+ * @author Kasper Nielsen
+ * @author Steven Caswell
+ * @since 1.0
+ * @version $Id: NestableException.java,v 1.8 2003/05/14 02:59:13 bayard Exp $
+ */
+public class NestableException extends Exception implements Nestable {
+
+ /**
+ * The helper instance which contains much of the code which we
+ * delegate to.
+ */
+ protected NestableDelegate delegate = new NestableDelegate(this);
+
+ /**
+ * Holds the reference to the exception or error that caused
+ * this exception to be thrown.
+ */
+ private Throwable cause = null;
+
+ /**
+ * Constructs a new NestableException
without specified
+ * detail message.
+ */
+ public NestableException() {
+ super();
+ }
+
+ /**
+ * Constructs a new NestableException
with specified
+ * detail message.
+ *
+ * @param msg The error message.
+ */
+ public NestableException(String msg) {
+ super(msg);
+ }
+
+ /**
+ * Constructs a new NestableException
with specified
+ * nested Throwable
.
+ *
+ * @param cause the exception or error that caused this exception to be
+ * thrown
+ */
+ public NestableException(Throwable cause) {
+ super();
+ this.cause = cause;
+ }
+
+ /**
+ * Constructs a new NestableException
with specified
+ * detail message and nested Throwable
.
+ *
+ * @param msg the error message
+ * @param cause the exception or error that caused this exception to be
+ * thrown
+ */
+ public NestableException(String msg, Throwable cause) {
+ super(msg);
+ this.cause = cause;
+ }
+
+ public Throwable getCause() {
+ return cause;
+ }
+
+ /**
+ * Returns the detail message string of this throwable. If it was
+ * created with a null message, returns the following:
+ * (cause==null ? null : cause.toString()).
+ */
+ public String getMessage() {
+ if (super.getMessage() != null) {
+ return super.getMessage();
+ } else if (cause != null) {
+ return cause.toString();
+ } else {
+ return null;
+ }
+ }
+
+ public String getMessage(int index) {
+ if (index == 0) {
+ return super.getMessage();
+ } else {
+ return delegate.getMessage(index);
+ }
+ }
+
+ public String[] getMessages() {
+ return delegate.getMessages();
+ }
+
+ public Throwable getThrowable(int index) {
+ return delegate.getThrowable(index);
+ }
+
+ public int getThrowableCount() {
+ return delegate.getThrowableCount();
+ }
+
+ public Throwable[] getThrowables() {
+ return delegate.getThrowables();
+ }
+
+ public int indexOfThrowable(Class type) {
+ return delegate.indexOfThrowable(type, 0);
+ }
+
+ public int indexOfThrowable(Class type, int fromIndex) {
+ return delegate.indexOfThrowable(type, fromIndex);
+ }
+
+ public void printStackTrace() {
+ delegate.printStackTrace();
+ }
+
+ public void printStackTrace(PrintStream out) {
+ delegate.printStackTrace(out);
+ }
+
+ public void printStackTrace(PrintWriter out) {
+ delegate.printStackTrace(out);
+ }
+
+ public final void printPartialStackTrace(PrintWriter out) {
+ super.printStackTrace(out);
+ }
+
+}
diff --git a/examples/cl2/src/java/org/apache/commons/lang/exception/NestableRuntimeException.java b/examples/cl2/src/java/org/apache/commons/lang/exception/NestableRuntimeException.java
new file mode 100644
index 00000000..84b4872b
--- /dev/null
+++ b/examples/cl2/src/java/org/apache/commons/lang/exception/NestableRuntimeException.java
@@ -0,0 +1,195 @@
+/* ====================================================================
+ * 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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
+ * .
+ */
+package org.apache.commons.lang.exception;
+
+import java.io.PrintStream;
+import java.io.PrintWriter;
+
+/**
+ * The base class of all runtime exceptions which can contain other
+ * exceptions.
+ *
+ * @see org.apache.commons.lang.exception.NestableException
+ * @author Rafal Krzewski
+ * @author Daniel Rall
+ * @author Kasper Nielsen
+ * @author Steven Caswell
+ * @since 1.0
+ * @version $Id: NestableRuntimeException.java,v 1.8 2003/05/14 02:59:13 bayard Exp $
+ */
+public class NestableRuntimeException extends RuntimeException implements Nestable {
+
+ /**
+ * The helper instance which contains much of the code which we
+ * delegate to.
+ */
+ protected NestableDelegate delegate = new NestableDelegate(this);
+
+ /**
+ * Holds the reference to the exception or error that caused
+ * this exception to be thrown.
+ */
+ private Throwable cause = null;
+
+ /**
+ * Constructs a new NestableRuntimeException
without specified
+ * detail message.
+ */
+ public NestableRuntimeException() {
+ super();
+ }
+
+ /**
+ * Constructs a new NestableRuntimeException
with specified
+ * detail message.
+ *
+ * @param msg the error message
+ */
+ public NestableRuntimeException(String msg) {
+ super(msg);
+ }
+
+ /**
+ * Constructs a new NestableRuntimeException
with specified
+ * nested Throwable
.
+ *
+ * @param cause the exception or error that caused this exception to be
+ * thrown
+ */
+ public NestableRuntimeException(Throwable cause) {
+ super();
+ this.cause = cause;
+ }
+
+ /**
+ * Constructs a new NestableRuntimeException
with specified
+ * detail message and nested Throwable
.
+ *
+ * @param msg the error message
+ * @param cause the exception or error that caused this exception to be
+ * thrown
+ */
+ public NestableRuntimeException(String msg, Throwable cause) {
+ super(msg);
+ this.cause = cause;
+ }
+
+ public Throwable getCause() {
+ return cause;
+ }
+
+ /**
+ * Returns the detail message string of this throwable. If it was
+ * created with a null message, returns the following:
+ * (cause==null ? null : cause.toString()).
+ */
+ public String getMessage() {
+ if (super.getMessage() != null) {
+ return super.getMessage();
+ } else if (cause != null) {
+ return cause.toString();
+ } else {
+ return null;
+ }
+ }
+
+ public String getMessage(int index) {
+ if (index == 0) {
+ return super.getMessage();
+ } else {
+ return delegate.getMessage(index);
+ }
+ }
+
+ public String[] getMessages() {
+ return delegate.getMessages();
+ }
+
+ public Throwable getThrowable(int index) {
+ return delegate.getThrowable(index);
+ }
+
+ public int getThrowableCount() {
+ return delegate.getThrowableCount();
+ }
+
+ public Throwable[] getThrowables() {
+ return delegate.getThrowables();
+ }
+
+ public int indexOfThrowable(Class type) {
+ return delegate.indexOfThrowable(type, 0);
+ }
+
+ public int indexOfThrowable(Class type, int fromIndex) {
+ return delegate.indexOfThrowable(type, fromIndex);
+ }
+
+ public void printStackTrace() {
+ delegate.printStackTrace();
+ }
+
+ public void printStackTrace(PrintStream out) {
+ delegate.printStackTrace(out);
+ }
+
+ public void printStackTrace(PrintWriter out) {
+ delegate.printStackTrace(out);
+ }
+
+ public final void printPartialStackTrace(PrintWriter out) {
+ super.printStackTrace(out);
+ }
+
+}
diff --git a/examples/cl2/src/java/org/apache/commons/lang/exception/package.html b/examples/cl2/src/java/org/apache/commons/lang/exception/package.html
new file mode 100644
index 00000000..2707883d
--- /dev/null
+++ b/examples/cl2/src/java/org/apache/commons/lang/exception/package.html
@@ -0,0 +1,10 @@
+
+
+Provides JDK 1.4 style Nested Exception functionality for those on prior Java
+versions.
+Includes a static utility to create version independent Nested
+Exception which can handle JDK 1.4 Exceptions as well as others.
+Lastly, {@link org.apache.commons.lang.exception.ExceptionUtils}
+also contains Throwable
manipulation and examination routines.
+
+
diff --git a/examples/cl2/src/java/org/apache/commons/lang/math/DoubleRange.java b/examples/cl2/src/java/org/apache/commons/lang/math/DoubleRange.java
new file mode 100644
index 00000000..be5b511e
--- /dev/null
+++ b/examples/cl2/src/java/org/apache/commons/lang/math/DoubleRange.java
@@ -0,0 +1,435 @@
+/* ====================================================================
+ * 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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
+ * .
+ */
+package org.apache.commons.lang.math;
+
+import java.io.Serializable;
+
+/**
+ * DoubleRange
represents an inclusive range of double
s.
+ *
+ * @author Stephen Colebourne
+ * @since 2.0
+ * @version $Id: DoubleRange.java,v 1.2 2003/03/23 17:51:15 scolebourne Exp $
+ */
+public final class DoubleRange extends Range implements Serializable {
+
+ private static final long serialVersionUID = 71849363892740L;
+
+ /* The minimum number in this range (inclusive). */
+ private final double min;
+ /* The maximum number in this range (inclusive). */
+ private final double max;
+
+ /** Cached output minObject (class is immutable) */
+ private transient Double minObject = null;
+ /** Cached output maxObject (class is immutable) */
+ private transient Double maxObject = null;
+ /** Cached output hashCode (class is immutable) */
+ private transient int hashCode = 0;
+ /** Cached output toString (class is immutable) */
+ private transient String toString = null;
+
+ /**
+ * Constructs a new DoubleRange
using the specified
+ * number as both the minimum and maximum in this range.
+ *
+ * @param number the number to use for this range
+ * @throws IllegalArgumentException if the number is NaN
+ */
+ public DoubleRange(double number) {
+ super();
+ if (Double.isNaN(number)) {
+ throw new IllegalArgumentException("The number must not be NaN");
+ }
+ this.min = number;
+ this.max = number;
+ }
+
+ /**
+ * Constructs a new DoubleRange
using the specified
+ * number as both the minimum and maximum in this range.
+ *
+ * @param number the number to use for this range, must not be null
+ * @throws IllegalArgumentException if the number is null
+ * @throws IllegalArgumentException if the number is NaN
+ */
+ public DoubleRange(Number number) {
+ super();
+ if (number == null) {
+ throw new IllegalArgumentException("The number must not be null");
+ }
+ this.min = number.doubleValue();
+ this.max = number.doubleValue();
+ if (Double.isNaN(min) || Double.isNaN(max)) {
+ throw new IllegalArgumentException("The number must not be NaN");
+ }
+ if (number instanceof Double) {
+ this.minObject = (Double) number;
+ this.maxObject = (Double) number;
+ }
+ }
+
+ /**
+ * Constructs a new DoubleRange
with the specified
+ * minimum and maximum numbers (both inclusive).
+ *
+ * The arguments may be passed in the order (min,max) or (max,min). The
+ * getMinimum and getMaximum methods will return the correct values.
+ *
+ * @param number1 first number that defines the edge of the range, inclusive
+ * @param number2 second number that defines the edge of the range, inclusive
+ * @throws IllegalArgumentException if either number is NaN
+ */
+ public DoubleRange(double number1, double number2) {
+ super();
+ if (Double.isNaN(number1) || Double.isNaN(number2)) {
+ throw new IllegalArgumentException("The numbers must not be NaN");
+ }
+ if (number2 < number1) {
+ this.min = number2;
+ this.max = number1;
+ } else {
+ this.min = number1;
+ this.max = number2;
+ }
+ }
+
+ /**
+ * Constructs a new DoubleRange
with the specified
+ * minimum and maximum numbers (both inclusive).
+ *
+ * The arguments may be passed in the order (min,max) or (max,min). The
+ * getMinimum and getMaximum methods will return the correct values.
+ *
+ * @param number1 first number that defines the edge of the range, inclusive
+ * @param number2 second number that defines the edge of the range, inclusive
+ * @throws IllegalArgumentException if either number is null
+ * @throws IllegalArgumentException if either number is NaN
+ */
+ public DoubleRange(Number number1, Number number2) {
+ super();
+ if (number1 == null || number2 == null) {
+ throw new IllegalArgumentException("The numbers must not be null");
+ }
+ double number1val = number1.doubleValue();
+ double number2val = number2.doubleValue();
+ if (Double.isNaN(number1val) || Double.isNaN(number2val)) {
+ throw new IllegalArgumentException("The numbers must not be NaN");
+ }
+ if (number2val < number1val) {
+ this.min = number2val;
+ this.max = number1val;
+ if (number2 instanceof Double) {
+ this.minObject = (Double) number2;
+ }
+ if (number1 instanceof Double) {
+ this.maxObject = (Double) number1;
+ }
+ } else {
+ this.min = number1val;
+ this.max = number2val;
+ if (number1 instanceof Double) {
+ this.minObject = (Double) number1;
+ }
+ if (number2 instanceof Double) {
+ this.maxObject = (Double) number2;
+ }
+ }
+ }
+
+ // Accessors
+ //--------------------------------------------------------------------
+
+ /**
+ * Returns the minimum number in this range.
+ *
+ * @return the minimum number in this range
+ */
+ public Number getMinimumNumber() {
+ if (minObject == null) {
+ minObject = new Double(min);
+ }
+ return minObject;
+ }
+
+ /**
+ * Gets the minimum number in this range as a long
.
+ *
+ * This conversion can lose information for large values or decimals.
+ *
+ * @return the minimum number in this range
+ */
+ public long getMinimumLong() {
+ return (long) min;
+ }
+
+ /**
+ * Gets the minimum number in this range as a int
.
+ *
+ * This conversion can lose information for large values or decimals.
+ *
+ * @return the minimum number in this range
+ */
+ public int getMinimumInteger() {
+ return (int) min;
+ }
+
+ /**
+ * Gets the minimum number in this range as a double
.
+ *
+ * @return the minimum number in this range
+ */
+ public double getMinimumDouble() {
+ return min;
+ }
+
+ /**
+ * Gets the minimum number in this range as a float
.
+ *
+ * This conversion can lose information for large values.
+ *
+ * @return the minimum number in this range
+ */
+ public float getMinimumFloat() {
+ return (float) min;
+ }
+
+ /**
+ * Returns the maximum number in this range.
+ *
+ * @return the maximum number in this range
+ */
+ public Number getMaximumNumber() {
+ if (maxObject == null) {
+ maxObject = new Double(max);
+ }
+ return maxObject;
+ }
+
+ /**
+ * Gets the maximum number in this range as a long
.
+ *
+ * This conversion can lose information for large values or decimals.
+ *
+ * @return the maximum number in this range
+ */
+ public long getMaximumLong() {
+ return (long) max;
+ }
+
+ /**
+ * Gets the maximum number in this range as a int
.
+ *
+ * This conversion can lose information for large values or decimals.
+ *
+ * @return the maximum number in this range
+ */
+ public int getMaximumInteger() {
+ return (int) max;
+ }
+
+ /**
+ * Gets the maximum number in this range as a double
.
+ *
+ * @return the maximum number in this range
+ */
+ public double getMaximumDouble() {
+ return max;
+ }
+
+ /**
+ * 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
+ */
+ public float getMaximumFloat() {
+ return (float) max;
+ }
+
+ // Tests
+ //--------------------------------------------------------------------
+
+ /**
+ * Tests whether the specified number
occurs within
+ * this range using double
comparison.
+ *
+ * null
is handled and returns false
.
+ *
+ * @param number the number to test, may be null
+ * @return true
if the specified number occurs within this range
+ */
+ public boolean includesNumber(Number number) {
+ if (number == null) {
+ return false;
+ }
+ return includesDouble(number.doubleValue());
+ }
+
+ /**
+ * Tests whether the specified double
occurs within
+ * this range using double
comparison.
+ *
+ * This implementation overrides the superclass for performance as it is
+ * the most common case.
+ *
+ * @param value the double to test
+ * @return true
if the specified number occurs within this
+ * range by double
comparison
+ */
+ public boolean includesDouble(double value) {
+ return (value >= min && value <= max);
+ }
+
+ // Range tests
+ //--------------------------------------------------------------------
+
+ /**
+ * Tests whether the specified range occurs entirely within this range
+ * using double
comparison.
+ *
+ * null
is handled and returns false
.
+ *
+ * @param range the range to test, may be null
+ * @return true
if the specified range occurs entirely within this range
+ * @throws IllegalArgumentException if the range is not of this type
+ */
+ public boolean includesRange(Range range) {
+ if (range == null) {
+ return false;
+ }
+ return includesDouble(range.getMinimumDouble()) &&
+ includesDouble(range.getMaximumDouble());
+ }
+
+ /**
+ * Tests whether the specified range overlaps with this range
+ * using double
comparison.
+ *
+ * null
is handled and returns false
.
+ *
+ * @param range the range to test, may be null
+ * @return true
if the specified range overlaps with this range
+ */
+ public boolean overlapsRange(Range range) {
+ if (range == null) {
+ return false;
+ }
+ return range.includesDouble(min) ||
+ range.includesDouble(max) ||
+ includesDouble(range.getMinimumDouble());
+ }
+
+ // Basics
+ //--------------------------------------------------------------------
+
+ /**
+ * Compares this range to another object to test if they are equal.
.
+ *
+ * To be equal, the class, minimum and maximum must be equal.
+ *
+ * @param obj the reference object with which to compare
+ * @return true
if this object is equal
+ */
+ public boolean equals(Object obj) {
+ if (obj == this) {
+ return true;
+ }
+ if (obj instanceof DoubleRange == false) {
+ return false;
+ }
+ DoubleRange range = (DoubleRange) obj;
+ return (Double.doubleToLongBits(min) == Double.doubleToLongBits(range.min) &&
+ Double.doubleToLongBits(max) == Double.doubleToLongBits(range.max));
+ }
+
+ /**
+ * Gets a hashCode for the range.
+ *
+ * @return a hash code value for this object
+ */
+ public int hashCode() {
+ if (hashCode == 0) {
+ hashCode = 17;
+ hashCode = 37 * hashCode + getClass().hashCode();
+ long lng = Double.doubleToLongBits(min);
+ hashCode = 37 * hashCode + ((int) (lng ^ (lng >> 32)));
+ lng = Double.doubleToLongBits(max);
+ hashCode = 37 * hashCode + ((int) (lng ^ (lng >> 32)));
+ }
+ return hashCode;
+ }
+
+ /**
+ * Gets the range as a String
.
+ *
+ * The format of the String is 'Range[min,max]'.
+ *
+ * @return the String
representation of this range
+ */
+ public String toString() {
+ if (toString == null) {
+ StringBuffer buf = new StringBuffer(32);
+ buf.append("Range[");
+ buf.append(min);
+ buf.append(',');
+ buf.append(max);
+ buf.append(']');
+ toString = buf.toString();
+ }
+ return toString;
+ }
+
+}
diff --git a/examples/cl2/src/java/org/apache/commons/lang/math/FloatRange.java b/examples/cl2/src/java/org/apache/commons/lang/math/FloatRange.java
new file mode 100644
index 00000000..7263b266
--- /dev/null
+++ b/examples/cl2/src/java/org/apache/commons/lang/math/FloatRange.java
@@ -0,0 +1,429 @@
+/* ====================================================================
+ * 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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
+ * .
+ */
+package org.apache.commons.lang.math;
+
+import java.io.Serializable;
+
+/**
+ * FloatRange
represents an inclusive range of float
s.
+ *
+ * @author Stephen Colebourne
+ * @since 2.0
+ * @version $Id: FloatRange.java,v 1.2 2003/03/23 17:51:15 scolebourne Exp $
+ */
+public final class FloatRange extends Range implements Serializable {
+
+ private static final long serialVersionUID = 71849363892750L;
+
+ /* The minimum number in this range (inclusive). */
+ private final float min;
+ /* The maximum number in this range (inclusive). */
+ private final float max;
+
+ /** Cached output minObject (class is immutable) */
+ private transient Float minObject = null;
+ /** Cached output maxObject (class is immutable) */
+ private transient Float maxObject = null;
+ /** Cached output hashCode (class is immutable) */
+ private transient int hashCode = 0;
+ /** Cached output toString (class is immutable) */
+ private transient String toString = null;
+
+ /**
+ * Constructs a new FloatRange
using the specified
+ * number as both the minimum and maximum in this range.
+ *
+ * @param number the number to use for this range
+ * @throws IllegalArgumentException if the number is NaN
+ */
+ public FloatRange(float number) {
+ super();
+ if (Float.isNaN(number)) {
+ throw new IllegalArgumentException("The number must not be NaN");
+ }
+ this.min = number;
+ this.max = number;
+ }
+
+ /**
+ * Constructs a new FloatRange
using the specified
+ * number as both the minimum and maximum in this range.
+ *
+ * @param number the number to use for this range, must not be null
+ * @throws IllegalArgumentException if the number is null
+ * @throws IllegalArgumentException if the number is NaN
+ */
+ public FloatRange(Number number) {
+ super();
+ if (number == null) {
+ throw new IllegalArgumentException("The number must not be null");
+ }
+ this.min = number.floatValue();
+ this.max = number.floatValue();
+ if (Float.isNaN(min) || Float.isNaN(max)) {
+ throw new IllegalArgumentException("The number must not be NaN");
+ }
+ if (number instanceof Float) {
+ this.minObject = (Float) number;
+ this.maxObject = (Float) number;
+ }
+ }
+
+ /**
+ * Constructs a new FloatRange
with the specified
+ * minimum and maximum numbers (both inclusive).
+ *
+ * The arguments may be passed in the order (min,max) or (max,min). The
+ * getMinimum and getMaximum methods will return the correct values.
+ *
+ * @param number1 first number that defines the edge of the range, inclusive
+ * @param number2 second number that defines the edge of the range, inclusive
+ * @throws IllegalArgumentException if either number is NaN
+ */
+ public FloatRange(float number1, float number2) {
+ super();
+ if (Float.isNaN(number1) || Float.isNaN(number2)) {
+ throw new IllegalArgumentException("The numbers must not be NaN");
+ }
+ if (number2 < number1) {
+ this.min = number2;
+ this.max = number1;
+ } else {
+ this.min = number1;
+ this.max = number2;
+ }
+ }
+
+ /**
+ * Constructs a new FloatRange
with the specified
+ * minimum and maximum numbers (both inclusive).
+ *
+ * The arguments may be passed in the order (min,max) or (max,min). The
+ * getMinimum and getMaximum methods will return the correct values.
+ *
+ * @param number1 first number that defines the edge of the range, inclusive
+ * @param number2 second number that defines the edge of the range, inclusive
+ * @throws IllegalArgumentException if either number is null
+ * @throws IllegalArgumentException if either number is NaN
+ */
+ public FloatRange(Number number1, Number number2) {
+ super();
+ if (number1 == null || number2 == null) {
+ throw new IllegalArgumentException("The numbers must not be null");
+ }
+ float number1val = number1.floatValue();
+ float number2val = number2.floatValue();
+ if (Float.isNaN(number1val) || Float.isNaN(number2val)) {
+ throw new IllegalArgumentException("The numbers must not be NaN");
+ }
+ if (number2val < number1val) {
+ this.min = number2val;
+ this.max = number1val;
+ if (number2 instanceof Float) {
+ this.minObject = (Float) number2;
+ }
+ if (number1 instanceof Float) {
+ this.maxObject = (Float) number1;
+ }
+ } else {
+ this.min = number1val;
+ this.max = number2val;
+ if (number1 instanceof Float) {
+ this.minObject = (Float) number1;
+ }
+ if (number2 instanceof Float) {
+ this.maxObject = (Float) number2;
+ }
+ }
+ }
+
+ // Accessors
+ //--------------------------------------------------------------------
+
+ /**
+ * Returns the minimum number in this range.
+ *
+ * @return the minimum number in this range
+ */
+ public Number getMinimumNumber() {
+ if (minObject == null) {
+ minObject = new Float(min);
+ }
+ return minObject;
+ }
+
+ /**
+ * Gets the minimum number in this range as a long
.
+ *
+ * This conversion can lose information for large values or decimals.
+ *
+ * @return the minimum number in this range
+ */
+ public long getMinimumLong() {
+ return (long) min;
+ }
+
+ /**
+ * Gets the minimum number in this range as a int
.
+ *
+ * This conversion can lose information for large values or decimals.
+ *
+ * @return the minimum number in this range
+ */
+ public int getMinimumInteger() {
+ return (int) min;
+ }
+
+ /**
+ * Gets the minimum number in this range as a double
.
+ *
+ * @return the minimum number in this range
+ */
+ public double getMinimumDouble() {
+ return min;
+ }
+
+ /**
+ * Gets the minimum number in this range as a float
.
+ *
+ * @return the minimum number in this range
+ */
+ public float getMinimumFloat() {
+ return min;
+ }
+
+ /**
+ * Returns the maximum number in this range.
+ *
+ * @return the maximum number in this range
+ */
+ public Number getMaximumNumber() {
+ if (maxObject == null) {
+ maxObject = new Float(max);
+ }
+ return maxObject;
+ }
+
+ /**
+ * Gets the maximum number in this range as a long
.
+ *
+ * This conversion can lose information for large values or decimals.
+ *
+ * @return the maximum number in this range
+ */
+ public long getMaximumLong() {
+ return (long) max;
+ }
+
+ /**
+ * Gets the maximum number in this range as a int
.
+ *
+ * This conversion can lose information for large values or decimals.
+ *
+ * @return the maximum number in this range
+ */
+ public int getMaximumInteger() {
+ return (int) max;
+ }
+
+ /**
+ * Gets the maximum number in this range as a double
.
+ *
+ * @return the maximum number in this range
+ */
+ public double getMaximumDouble() {
+ return max;
+ }
+
+ /**
+ * Gets the maximum number in this range as a float
.
+ *
+ * @return the maximum number in this range
+ */
+ public float getMaximumFloat() {
+ return max;
+ }
+
+ // Tests
+ //--------------------------------------------------------------------
+
+ /**
+ * Tests whether the specified number
occurs within
+ * this range using float
comparison.
+ *
+ * null
is handled and returns false
.
+ *
+ * @param number the number to test, may be null
+ * @return true
if the specified number occurs within this range
+ */
+ public boolean includesNumber(Number number) {
+ if (number == null) {
+ return false;
+ }
+ return includesFloat(number.floatValue());
+ }
+
+ /**
+ * Tests whether the specified float
occurs within
+ * this range using float
comparison.
+ *
+ * This implementation overrides the superclass for performance as it is
+ * the most common case.
+ *
+ * @param value the float to test
+ * @return true
if the specified number occurs within this
+ * range by float
comparison
+ */
+ public boolean includesFloat(float value) {
+ return (value >= min && value <= max);
+ }
+
+ // Range tests
+ //--------------------------------------------------------------------
+
+ /**
+ * Tests whether the specified range occurs entirely within this range
+ * using float
comparison.
+ *
+ * null
is handled and returns false
.
+ *
+ * @param range the range to test, may be null
+ * @return true
if the specified range occurs entirely within this range
+ * @throws IllegalArgumentException if the range is not of this type
+ */
+ public boolean includesRange(Range range) {
+ if (range == null) {
+ return false;
+ }
+ return includesFloat(range.getMinimumFloat()) &&
+ includesFloat(range.getMaximumFloat());
+ }
+
+ /**
+ * Tests whether the specified range overlaps with this range
+ * using float
comparison.
+ *
+ * null
is handled and returns false
.
+ *
+ * @param range the range to test, may be null
+ * @return true
if the specified range overlaps with this range
+ */
+ public boolean overlapsRange(Range range) {
+ if (range == null) {
+ return false;
+ }
+ return range.includesFloat(min) ||
+ range.includesFloat(max) ||
+ includesFloat(range.getMinimumFloat());
+ }
+
+ // Basics
+ //--------------------------------------------------------------------
+
+ /**
+ * Compares this range to another object to test if they are equal.
.
+ *
+ * To be equal, the class, minimum and maximum must be equal.
+ *
+ * @param obj the reference object with which to compare
+ * @return true
if this object is equal
+ */
+ public boolean equals(Object obj) {
+ if (obj == this) {
+ return true;
+ }
+ if (obj instanceof FloatRange == false) {
+ return false;
+ }
+ FloatRange range = (FloatRange) obj;
+ return (Float.floatToIntBits(min) == Float.floatToIntBits(range.min) &&
+ Float.floatToIntBits(max) == Float.floatToIntBits(range.max));
+ }
+
+ /**
+ * Gets a hashCode for the range.
+ *
+ * @return a hash code value for this object
+ */
+ public int hashCode() {
+ if (hashCode == 0) {
+ hashCode = 17;
+ hashCode = 37 * hashCode + getClass().hashCode();
+ hashCode = 37 * hashCode + Float.floatToIntBits(min);
+ hashCode = 37 * hashCode + Float.floatToIntBits(max);
+ }
+ return hashCode;
+ }
+
+ /**
+ * Gets the range as a String
.
+ *
+ * The format of the String is 'Range[min,max]'.
+ *
+ * @return the String
representation of this range
+ */
+ public String toString() {
+ if (toString == null) {
+ StringBuffer buf = new StringBuffer(32);
+ buf.append("Range[");
+ buf.append(min);
+ buf.append(',');
+ buf.append(max);
+ buf.append(']');
+ toString = buf.toString();
+ }
+ return toString;
+ }
+
+}
diff --git a/examples/cl2/src/java/org/apache/commons/lang/math/Fraction.java b/examples/cl2/src/java/org/apache/commons/lang/math/Fraction.java
new file mode 100644
index 00000000..a46b1eff
--- /dev/null
+++ b/examples/cl2/src/java/org/apache/commons/lang/math/Fraction.java
@@ -0,0 +1,735 @@
+/* ====================================================================
+ * 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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
+ * .
+ */
+package org.apache.commons.lang.math;
+
+import java.io.Serializable;
+
+/**
+ * Fraction
is a Number
implementation that
+ * stores fractions accurately.
+ *
+ * This class is immutable, and interoperable with most methods that accept
+ * a Number
.
+ *
+ * @author Travis Reeder
+ * @author Stephen Colebourne
+ * @since 2.0
+ * @version $Id: Fraction.java,v 1.3 2003/04/09 01:08:30 ggregory Exp $
+ */
+public final class Fraction extends Number implements Serializable, Comparable {
+
+ private static final long serialVersionUID = 65382027393090L;
+
+ public static final Fraction ZERO = new Fraction(0, 1);
+ public static final Fraction ONE = new Fraction(1, 1);
+
+ public static final Fraction ONE_HALF = new Fraction(1, 2);
+
+ public static final Fraction ONE_THIRD = new Fraction(1, 3);
+ public static final Fraction TWO_THIRDS = new Fraction(2, 3);
+
+ public static final Fraction ONE_QUARTER = new Fraction(1, 4);
+ public static final Fraction TWO_QUARTERS = new Fraction(2, 4);
+ public static final Fraction THREE_QUARTERS = new Fraction(3, 4);
+
+ public static final Fraction ONE_FIFTH = new Fraction(1, 5);
+ public static final Fraction TWO_FIFTHS = new Fraction(2, 5);
+ public static final Fraction THREE_FIFTHS = new Fraction(3, 5);
+ public static final Fraction FOUR_FIFTHS = new Fraction(4, 5);
+
+
+ /** The numerator number part of the fraction (the three in three sevenths) */
+ private final int numerator;
+ /** The denominator number part of the fraction (the seven in three sevenths) */
+ private final int denominator;
+
+ /** Cached output hashCode (class is immutable) */
+ private transient int hashCode = 0;
+ /** Cached output toString (class is immutable) */
+ private transient String toString = null;
+ /** Cached output toProperString (class is immutable) */
+ private transient String toProperString = null;
+
+ /**
+ * Constructs a Fraction
instance with the 2 parts
+ * of a fraction Y/Z.
+ *
+ * @param numerator the numerator, for example the three in 'three sevenths'
+ * @param denominator the denominator, for example the seven in 'three sevenths'
+ */
+ private Fraction(int numerator, int denominator) {
+ super();
+ this.numerator = numerator;
+ this.denominator = denominator;
+ }
+
+ /**
+ * Creates a Fraction
instance with the 2 parts
+ * of a fraction Y/Z.
+ *
+ * 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
+ * @throws ArithmeticException if the denomiator is zero
+ */
+ public static Fraction getFraction(int numerator, int denominator) {
+ if (denominator == 0) {
+ throw new ArithmeticException("The denominator must not be zero");
+ }
+ if (denominator < 0) {
+ numerator = -numerator;
+ denominator = -denominator;
+ }
+ return new Fraction(numerator, denominator);
+ }
+
+ /**
+ * Creates a Fraction
instance with the 3 parts
+ * of a fraction X Y/Z.
+ *
+ * The negative sign must be passed in on the whole number part.
+ *
+ * @param whole the whole number, for example the one in 'one and three sevenths'
+ * @param numerator the numerator, for example the three in 'one and three sevenths'
+ * @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 numerator is negative
+ */
+ public static Fraction getFraction(int whole, int numerator, int denominator) {
+ if (denominator == 0) {
+ throw new ArithmeticException("The denominator must not be zero");
+ }
+ if (denominator < 0) {
+ throw new ArithmeticException("The denominator must not be negative");
+ }
+ if (numerator < 0) {
+ throw new ArithmeticException("The numerator must not be negative");
+ }
+ if (whole < 0) {
+ numerator = whole * denominator - numerator;
+ } else {
+ numerator = whole * denominator + numerator;
+ }
+ return new Fraction(numerator, denominator);
+ }
+
+ /**
+ * Creates a Fraction
instance with the 2 parts
+ * of a fraction Y/Z.
+ *
+ * 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
+ */
+ public static Fraction getReducedFraction(int numerator, int denominator) {
+ if (denominator == 0) {
+ throw new ArithmeticException("The denominator must not be zero");
+ }
+ if (denominator < 0) {
+ numerator = -numerator;
+ denominator = -denominator;
+ }
+ int gcd = greatestCommonDenominator(Math.abs(numerator), denominator);
+ if (gcd == 0) {
+ return new Fraction(numerator, denominator);
+ }
+ return new Fraction(numerator / gcd, denominator / gcd);
+ }
+
+ /**
+ * Creates a Fraction
instance from a double
value.
+ *
+ * This method uses the continued fraction algorithm.
+ *
+ * @param value the double value to convert
+ * @return a new fraction instance that is close to the value
+ * @throws ArithmeticException if the value is infinite or NaN
+ * @throws ArithmeticException if the calculated denomiator is zero
+ */
+ public static Fraction getFraction(double value) {
+ if (Double.isInfinite(value) || Double.isNaN(value)) {
+ throw new ArithmeticException("The value must not be infinite or NaN");
+ }
+ int sign = (value < 0 ? -1 : 1);
+ value = Math.abs(value);
+ int wholeNumber = (int) value;
+ value -= wholeNumber;
+
+ // http://archives.math.utk.edu/articles/atuyl/confrac/
+ int numer0 = 0; // the pre-previous
+ int denom0 = 1; // the pre-previous
+ int numer1 = 1; // the previous
+ int denom1 = 0; // the previous
+ int numer2 = 0; // the current, setup in calculation
+ int denom2 = 0; // the current, setup in calculation
+ int a1 = (int) value;
+ int a2 = 0;
+ double x1 = 1;
+ double x2 = 0;
+ double y1 = value - a1;
+ double y2 = 0;
+ double delta1, delta2 = Double.MAX_VALUE;
+ double fraction;
+ int i = 1;
+// System.out.println("---");
+ do {
+ delta1 = delta2;
+ a2 = (int) (x1 / y1);
+ x2 = y1;
+ y2 = x1 - a2 * y1;
+ numer2 = a1 * numer1 + numer0;
+ denom2 = a1 * denom1 + denom0;
+ fraction = (double) numer2 / (double) denom2;
+ delta2 = Math.abs(value - fraction);
+// System.out.println(numer2 + " " + denom2 + " " + fraction + " " + delta2 + " " + y1);
+ a1 = a2;
+ x1 = x2;
+ y1 = y2;
+ numer0 = numer1;
+ denom0 = denom1;
+ numer1 = numer2;
+ denom1 = denom2;
+ i++;
+// System.out.println(">>" + delta1 +" "+ delta2+" "+(delta1 > delta2)+" "+i+" "+denom2);
+ } while ((delta1 > delta2) && (denom2 <= 10000) && (denom2 > 0) && (i < 25));
+ if (i == 25) {
+ throw new ArithmeticException("Unable to convert double to fraction");
+ }
+ return getReducedFraction((numer0 + wholeNumber * denom0) * sign, denom0);
+ }
+
+ /**
+ * Creates a Fraction from a String
.
+ *
+ * The formats accepted are:
+ *
+ * double
String containing a dot
+ * - 'X Y/Z'
+ *
- 'Y/Z'
+ *
and a .
+ *
+ * @param str the string to parse, must not be null
+ * @return the new Fraction
instance
+ * @throws IllegalArgumentException if the string is null
+ * @throws NumberFormatException if the number format is invalid
+ */
+ public static Fraction getFraction(String str) {
+ if (str == null) {
+ throw new IllegalArgumentException("The string must not be null");
+ }
+ // parse double format
+ int pos = str.indexOf('.');
+ if (pos >= 0) {
+ return getFraction(Double.parseDouble(str));
+ }
+
+ // parse X Y/Z format
+ pos = str.indexOf(' ');
+ if (pos > 0) {
+ int whole = Integer.parseInt(str.substring(0, pos));
+ str = str.substring(pos + 1);
+ pos = str.indexOf('/');
+ if (pos < 0) {
+ throw new NumberFormatException("The fraction could not be parsed as the format X Y/Z");
+ } else {
+ int denom = Integer.parseInt(str.substring(pos + 1));
+ return getFraction(
+ Integer.parseInt(str.substring(0, pos)) + whole * denom,
+ denom
+ );
+ }
+ }
+
+ // parse Y/Z format
+ pos = str.indexOf('/');
+ if (pos < 0) {
+ // simple whole number
+ return getFraction(Integer.parseInt(str), 1);
+ } else {
+ return getFraction(
+ Integer.parseInt(str.substring(0, pos)),
+ Integer.parseInt(str.substring(pos + 1))
+ );
+ }
+ }
+
+ // Accessors
+ //-------------------------------------------------------------------
+
+ /**
+ * Gets the numerator part of the fraction.
+ *
+ * This method may return a value greater than the denominator, an
+ * improper fraction, such as the seven in 7/8.
+ *
+ * @return the numerator fraction part
+ */
+ public int getNumerator() {
+ return numerator;
+ }
+
+ /**
+ * Gets the denominator part of the fraction.
+ *
+ * @return the denominator fraction part
+ */
+ public int getDenominator() {
+ return denominator;
+ }
+
+ /**
+ * Gets the proper numerator, always positive.
+ *
+ * An improper fraction 7/8 can be resolved into a proper one, 1 3/4.
+ * This method returns the 3 from the proper fraction.
+ *
+ * If the fraction is negative such as -7/8, it can be resolved into
+ * -1 3/4, so this method returns the positive proper numerator, 3.
+ *
+ * @return the numerator fraction part of a proper fraction, always positive
+ */
+ public int getProperNumerator() {
+ return Math.abs(numerator % denominator);
+ }
+
+ /**
+ * Gets the proper whole part of the fraction.
+ *
+ * An improper fraction 7/8 can be resolved into a proper one, 1 3/4.
+ * This method returns the 1 from the proper fraction.
+ *
+ * If the fraction is negative such as -7/8, it can be resolved into
+ * -1 3/4, so this method returns the positive whole part -1.
+ *
+ * @return the whole fraction part of a proper fraction, that includes the sign
+ */
+ public int getProperWhole() {
+ return numerator / denominator;
+ }
+
+ // Number methods
+ //-------------------------------------------------------------------
+
+ /**
+ * Gets the fraction as an int
. This returns the whole number
+ * part of the fraction.
+ *
+ * @return the whole number fraction part
+ */
+ public int intValue() {
+ return (int) numerator / denominator;
+ }
+
+ /**
+ * Gets the fraction as a long
. This returns the whole number
+ * part of the fraction.
+ *
+ * @return the whole number fraction part
+ */
+ public long longValue() {
+ return (long) numerator / denominator;
+ }
+
+ /**
+ * Gets the fraction as a float
. This calculates the fraction
+ * as the numerator divided by denominator.
+ *
+ * @return the fraction as a float
+ */
+ public float floatValue() {
+ return ((float) numerator) / ((float) denominator);
+ }
+
+ /**
+ * Gets the fraction as a double
. This calculates the fraction
+ * as the numerator divided by denominator.
+ *
+ * @return the fraction as a double
+ */
+ public double doubleValue() {
+ return ((double) numerator) / ((double) denominator);
+ }
+
+ // Calculations
+ //-------------------------------------------------------------------
+
+ /**
+ * Reduce the fraction to the smallest values for the numerator and
+ * denominator, returning the result..
+ *
+ * @return a new reduce fraction instance, or this if no simplification possible
+ */
+ public Fraction reduce() {
+ int gcd = greatestCommonDenominator(Math.abs(numerator), denominator);
+ if (gcd == 0) {
+ return this;
+ }
+ return Fraction.getFraction(numerator / gcd, denominator / gcd);
+ }
+
+ /**
+ * Gets a fraction that is the invert (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
+ */
+ public Fraction invert() {
+ if (numerator == 0) {
+ throw new ArithmeticException("Unable to invert a fraction with a zero numerator");
+ }
+ return getFraction(denominator, numerator);
+ }
+
+ /**
+ * Gets a fraction that is the negative (-fraction) of this one.
+ *
+ * The returned fraction is not reduced.
+ *
+ * @return a new fraction instance with the opposite signed numerator
+ */
+ public Fraction negate() {
+ return getFraction(-numerator, denominator);
+ }
+
+ /**
+ * Gets a fraction that is the positive equivalent of this one.
+ * More precisely:
(fraction >= 0 ? this : -fraction)
+ *
+ * The returned fraction is not reduced.
+ *
+ * @return this
if it is positive, or a new positive fraction
+ * instance with the opposite signed numerator
+ */
+ public Fraction abs() {
+ if (numerator >= 0) {
+ return this;
+ }
+ return getFraction(-numerator, denominator);
+ }
+
+ /**
+ * Gets a fraction that is raised to the passed in power.
+ *
+ * The returned fraction is not reduced.
+ *
+ * @param power the power to raise the fraction to
+ * @return this
if the power is one, ONE
if the power
+ * is zero or a new fraction instance raised to the appropriate power
+ */
+ public Fraction pow(int power) {
+ if (power == 1) {
+ return this;
+ } else if (power == 0) {
+ return ONE;
+ } else 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 denominator of two numbers.
+ *
+ * @param number1 a positive number
+ * @param number2 a positive number
+ * @return the greatest common denominator
+ */
+ private static int greatestCommonDenominator(int number1, int number2) {
+ int remainder = number1 % number2;
+ while (remainder != 0) {
+ number1 = number2;
+ number2 = remainder;
+ remainder = number1 % number2;
+ }
+ return number2;
+ }
+
+ // Arithmetic
+ //-------------------------------------------------------------------
+
+ /**
+ * Adds the value of this fraction to another, returning the result.
+ *
+ * The implementation spots common cases of zero numerators and equal
+ * denominators. Otherwise, it uses (a/b) + (c/d) = (a*d + b*c) / (b*d)
+ * and then reduces the result.
+ *
+ * @param the fraction to add, must not be null
+ * @return a Fraction
instance with the resulting values
+ * @throws IllegalArgumentException if the fraction is null
+ */
+ 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;
+ }
+ if (denominator == fraction.denominator) {
+ return getReducedFraction(numerator + fraction.numerator, denominator);
+ }
+ return getReducedFraction(
+ numerator * fraction.denominator + denominator * fraction.numerator,
+ denominator * fraction.denominator
+ );
+ }
+
+ /**
+ * Subtracts the value of another fraction from the value of this one,
+ * returning the result.
+ *
+ * The implementation spots common cases of zero numerators and equal
+ * denominators. Otherwise, it uses (a/b) - (c/d) = (a*d - b*c) / (b*d)
+ * and then reduces the result.
+ *
+ * @param the fraction to subtract, must not be null
+ * @return a Fraction
instance with the resulting values
+ * @throws IllegalArgumentException if the fraction is null
+ */
+ public Fraction subtract(Fraction fraction) {
+ if (fraction == null) {
+ throw new IllegalArgumentException("The fraction must not be null");
+ }
+ if (numerator == 0) {
+ return fraction.negate();
+ }
+ if (fraction.numerator == 0) {
+ return this;
+ }
+ if (denominator == fraction.denominator) {
+ return getReducedFraction(numerator - fraction.numerator, denominator);
+ }
+ return getReducedFraction(
+ numerator * fraction.denominator - denominator * fraction.numerator,
+ denominator * fraction.denominator
+ );
+ }
+
+ /**
+ * Multiplies the value of this fraction by another, returning the result.
+ *
+ * The implementation uses (a/b)*(c/d) = (a*c)/(b*d)
+ * and then reduces the result.
+ *
+ * @param the fraction to multipy by, must not be null
+ * @return a Fraction
instance with the resulting values
+ * @throws IllegalArgumentException if the fraction is null
+ */
+ public Fraction multiplyBy(Fraction fraction) {
+ if (fraction == null) {
+ throw new IllegalArgumentException("The fraction must not be null");
+ }
+ if (numerator == 0 || fraction.numerator == 0) {
+ return ZERO;
+ }
+ return getReducedFraction(
+ numerator * fraction.numerator,
+ denominator * fraction.denominator
+ );
+ }
+
+ /**
+ * Divide the value of this fraction by another, returning the result.
+ *
+ * The implementation uses (a/b)/(c/d) = a/b * d/c = (a*d)/(b*c)
+ * and then reduces the result.
+ *
+ * @param the fraction to divide by, must not be null
+ * @return a Fraction
instance with the resulting values
+ * @throws IllegalArgumentException if the fraction is null
+ * @throws ArithmeticException if the fraction to divide by is zero
+ */
+ public Fraction divideBy(Fraction fraction) {
+ if (fraction == null) {
+ throw new IllegalArgumentException("The fraction must not be null");
+ }
+ if (fraction.numerator == 0) {
+ throw new ArithmeticException("The fraction to divide by must not be zero");
+ }
+ if (numerator == 0) {
+ return ZERO;
+ }
+ return getReducedFraction(
+ numerator * fraction.denominator,
+ denominator * fraction.numerator
+ );
+ }
+
+ // Basics
+ //-------------------------------------------------------------------
+
+ /**
+ * Compares this fraction to another object to test if they are equal.
.
+ *
+ * To be equal, both values must be equal. Thus 2/4 is not equal to 1/2.
+ *
+ * @param obj the reference object with which to compare
+ * @return true
if this object is equal
+ */
+ public boolean equals(Object obj) {
+ if (obj == this) {
+ return true;
+ }
+ if (obj instanceof Fraction == false) {
+ return false;
+ }
+ Fraction other = (Fraction) obj;
+ return (numerator == other.numerator &&
+ denominator == other.denominator);
+ }
+
+ /**
+ * Gets a hashCode for the fraction.
+ *
+ * @return a hash code value for this object
+ */
+ public int hashCode() {
+ if (hashCode == 0) {
+ hashCode = 17;
+ hashCode = 37 * hashCode + numerator;
+ hashCode = 37 * hashCode + denominator;
+ }
+ return hashCode;
+ }
+
+ /**
+ * Compares this object to another based on size.
+ *
+ * @param object the object to compare to
+ * @return -ve if this is less, 0 if equal, +ve 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 (numerator == other.numerator && denominator == other.denominator) {
+ return 0;
+ }
+
+ // otherwise see which is less
+ long first = (long) numerator * (long) other.denominator;
+ long second = (long) other.numerator * (long) denominator;
+ if (first == second) {
+ return 0;
+ } else if (first < second) {
+ return -1;
+ } else {
+ return 1;
+ }
+ }
+
+ /**
+ * Gets the fraction as a String
.
+ *
+ * The format used is 'numerator/denominator' always.
+ *
+ * @return a String
form of the fraction
+ */
+ public String toString() {
+ if (toString == null) {
+ toString = new StringBuffer(32)
+ .append(numerator)
+ .append('/')
+ .append(denominator).toString();
+ }
+ return toString;
+ }
+
+ /**
+ *
Gets the fraction as a proper String
in the format X Y/Z.
+ *
+ * The format used in 'wholeNumber numerator/denominator'.
+ * If the whole number is zero it will be ommitted. If the numerator is zero,
+ * only the whole number is returned.
+ *
+ * @return a String
form of the fraction
+ */
+ public String toProperString() {
+ if (toProperString == null) {
+ if (numerator == 0) {
+ toProperString = "0";
+ } else if (numerator == denominator) {
+ toProperString = "1";
+ } else if (Math.abs(numerator) > denominator) {
+ int properNumerator = getProperNumerator();
+ if (properNumerator == 0) {
+ toProperString = Integer.toString(getProperWhole());
+ } else {
+ toProperString = new StringBuffer(32)
+ .append(getProperWhole()).append(' ')
+ .append(properNumerator).append('/')
+ .append(denominator).toString();
+ }
+ } else {
+ toProperString = new StringBuffer(32)
+ .append(numerator).append('/')
+ .append(denominator).toString();
+ }
+ }
+ return toProperString;
+ }
+
+}
diff --git a/examples/cl2/src/java/org/apache/commons/lang/math/IntRange.java b/examples/cl2/src/java/org/apache/commons/lang/math/IntRange.java
new file mode 100644
index 00000000..2711e759
--- /dev/null
+++ b/examples/cl2/src/java/org/apache/commons/lang/math/IntRange.java
@@ -0,0 +1,404 @@
+/* ====================================================================
+ * 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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
+ * .
+ */
+package org.apache.commons.lang.math;
+
+import java.io.Serializable;
+
+/**
+ * IntRange
represents an inclusive range of int
s.
+ *
+ * @author Stephen Colebourne
+ * @since 2.0
+ * @version $Id: IntRange.java,v 1.2 2003/03/23 17:51:15 scolebourne Exp $
+ */
+public final class IntRange extends Range implements Serializable {
+
+ private static final long serialVersionUID = 71849363892730L;
+
+ /* The minimum number in this range (inclusive). */
+ private final int min;
+ /* The maximum number in this range (inclusive). */
+ private final int max;
+
+ /** Cached output minObject (class is immutable) */
+ private transient Integer minObject = null;
+ /** Cached output maxObject (class is immutable) */
+ private transient Integer maxObject = null;
+ /** Cached output hashCode (class is immutable) */
+ private transient int hashCode = 0;
+ /** Cached output toString (class is immutable) */
+ private transient String toString = null;
+
+ /**
+ * Constructs a new IntRange
using the specified
+ * number as both the minimum and maximum in this range.
+ *
+ * @param number the number to use for this range
+ */
+ public IntRange(int number) {
+ super();
+ this.min = number;
+ this.max = number;
+ }
+
+ /**
+ * Constructs a new IntRange
using the specified
+ * number as both the minimum and maximum in this range.
+ *
+ * @param number the number to use for this range, must not be null
+ * @throws IllegalArgumentException if the number is null
+ */
+ public IntRange(Number number) {
+ super();
+ if (number == null) {
+ throw new IllegalArgumentException("The number must not be null");
+ }
+ this.min = number.intValue();
+ this.max = number.intValue();
+ if (number instanceof Integer) {
+ this.minObject = (Integer) number;
+ this.maxObject = (Integer) number;
+ }
+ }
+
+ /**
+ * Constructs a new IntRange
with the specified
+ * minimum and maximum numbers (both inclusive).
+ *
+ * The arguments may be passed in the order (min,max) or (max,min). The
+ * getMinimum and getMaximum methods will return the correct values.
+ *
+ * @param number1 first number that defines the edge of the range, inclusive
+ * @param number2 second number that defines the edge of the range, inclusive
+ */
+ public IntRange(int number1, int number2) {
+ super();
+ if (number2 < number1) {
+ this.min = number2;
+ this.max = number1;
+ } else {
+ this.min = number1;
+ this.max = number2;
+ }
+ }
+
+ /**
+ * Constructs a new IntRange
with the specified
+ * minimum and maximum numbers (both inclusive).
+ *
+ * The arguments may be passed in the order (min,max) or (max,min). The
+ * getMinimum and getMaximum methods will return the correct values.
+ *
+ * @param number1 first number that defines the edge of the range, inclusive
+ * @param number2 second number that defines the edge of the range, inclusive
+ * @throws IllegalArgumentException if either number is null
+ */
+ public IntRange(Number number1, Number number2) {
+ super();
+ if (number1 == null || number2 == null) {
+ throw new IllegalArgumentException("The numbers must not be null");
+ }
+ int number1val = number1.intValue();
+ int number2val = number2.intValue();
+ if (number2val < number1val) {
+ this.min = number2val;
+ this.max = number1val;
+ if (number2 instanceof Integer) {
+ this.minObject = (Integer) number2;
+ }
+ if (number1 instanceof Integer) {
+ this.maxObject = (Integer) number1;
+ }
+ } else {
+ this.min = number1val;
+ this.max = number2val;
+ if (number1 instanceof Integer) {
+ this.minObject = (Integer) number1;
+ }
+ if (number2 instanceof Integer) {
+ this.maxObject = (Integer) number2;
+ }
+ }
+ }
+
+ // Accessors
+ //--------------------------------------------------------------------
+
+ /**
+ * Returns the minimum number in this range.
+ *
+ * @return the minimum number in this range
+ */
+ public Number getMinimumNumber() {
+ if (minObject == null) {
+ minObject = new Integer(min);
+ }
+ return minObject;
+ }
+
+ /**
+ * Gets the minimum number in this range as a long
.
+ *
+ * @return the minimum number in this range
+ */
+ public long getMinimumLong() {
+ return min;
+ }
+
+ /**
+ * Gets the minimum number in this range as a int
.
+ *
+ * @return the minimum number in this range
+ */
+ public int getMinimumInteger() {
+ return min;
+ }
+
+ /**
+ * Gets the minimum number in this range as a double
.
+ *
+ * @return the minimum number in this range
+ */
+ public double getMinimumDouble() {
+ return min;
+ }
+
+ /**
+ * Gets the minimum number in this range as a float
.
+ *
+ * @return the minimum number in this range
+ */
+ public float getMinimumFloat() {
+ return min;
+ }
+
+ /**
+ * Returns the maximum number in this range.
+ *
+ * @return the maximum number in this range
+ */
+ public Number getMaximumNumber() {
+ if (maxObject == null) {
+ maxObject = new Integer(max);
+ }
+ return maxObject;
+ }
+
+ /**
+ * Gets the maximum number in this range as a long
.
+ *
+ * @return the maximum number in this range
+ */
+ public long getMaximumLong() {
+ return max;
+ }
+
+ /**
+ * Gets the maximum number in this range as a int
.
+ *
+ * @return the maximum number in this range
+ */
+ public int getMaximumInteger() {
+ return max;
+ }
+
+ /**
+ * Gets the maximum number in this range as a double
.
+ *
+ * @return the maximum number in this range
+ */
+ public double getMaximumDouble() {
+ return max;
+ }
+
+ /**
+ * Gets the maximum number in this range as a float
.
+ *
+ * @return the maximum number in this range
+ */
+ public float getMaximumFloat() {
+ return max;
+ }
+
+ // Tests
+ //--------------------------------------------------------------------
+
+ /**
+ * Tests whether the specified number
occurs within
+ * this range using int
comparison.
+ *
+ * null
is handled and returns false
.
+ *
+ * @param number the number to test, may be null
+ * @return true
if the specified number occurs within this range
+ */
+ public boolean includesNumber(Number number) {
+ if (number == null) {
+ return false;
+ }
+ return includesInteger(number.intValue());
+ }
+
+ /**
+ * Tests whether the specified int
occurs within
+ * this range using int
comparison.
+ *
+ * This implementation overrides the superclass for performance as it is
+ * the most common case.
+ *
+ * @param value the int to test
+ * @return true
if the specified number occurs within this
+ * range by int
comparison
+ */
+ public boolean includesInteger(int value) {
+ return (value >= min && value <= max);
+ }
+
+ // Range tests
+ //--------------------------------------------------------------------
+
+ /**
+ * Tests whether the specified range occurs entirely within this range
+ * using int
comparison.
+ *
+ * null
is handled and returns false
.
+ *
+ * @param range the range to test, may be null
+ * @return true
if the specified range occurs entirely within this range
+ * @throws IllegalArgumentException if the range is not of this type
+ */
+ public boolean includesRange(Range range) {
+ if (range == null) {
+ return false;
+ }
+ return includesInteger(range.getMinimumInteger()) &&
+ includesInteger(range.getMaximumInteger());
+ }
+
+ /**
+ * Tests whether the specified range overlaps with this range
+ * using int
comparison.
+ *
+ * null
is handled and returns false
.
+ *
+ * @param range the range to test, may be null
+ * @return true
if the specified range overlaps with this range
+ */
+ public boolean overlapsRange(Range range) {
+ if (range == null) {
+ return false;
+ }
+ return range.includesInteger(min) ||
+ range.includesInteger(max) ||
+ includesInteger(range.getMinimumInteger());
+ }
+
+ // Basics
+ //--------------------------------------------------------------------
+
+ /**
+ * Compares this range to another object to test if they are equal.
.
+ *
+ * To be equal, the class, minimum and maximum must be equal.
+ *
+ * @param obj the reference object with which to compare
+ * @return true
if this object is equal
+ */
+ public boolean equals(Object obj) {
+ if (obj == this) {
+ return true;
+ }
+ if (obj instanceof IntRange == false) {
+ return false;
+ }
+ IntRange range = (IntRange) obj;
+ return (min == range.min && max == range.max);
+ }
+
+ /**
+ * Gets a hashCode for the range.
+ *
+ * @return a hash code value for this object
+ */
+ public int hashCode() {
+ if (hashCode == 0) {
+ hashCode = 17;
+ hashCode = 37 * hashCode + getClass().hashCode();
+ hashCode = 37 * hashCode + min;
+ hashCode = 37 * hashCode + max;
+ }
+ return hashCode;
+ }
+
+ /**
+ * Gets the range as a String
.
+ *
+ * The format of the String is 'Range[min,max]'.
+ *
+ * @return the String
representation of this range
+ */
+ public String toString() {
+ if (toString == null) {
+ StringBuffer buf = new StringBuffer(32);
+ buf.append("Range[");
+ buf.append(min);
+ buf.append(',');
+ buf.append(max);
+ buf.append(']');
+ toString = buf.toString();
+ }
+ return toString;
+ }
+
+}
diff --git a/examples/cl2/src/java/org/apache/commons/lang/math/JVMRandom.java b/examples/cl2/src/java/org/apache/commons/lang/math/JVMRandom.java
new file mode 100644
index 00000000..3da7a79a
--- /dev/null
+++ b/examples/cl2/src/java/org/apache/commons/lang/math/JVMRandom.java
@@ -0,0 +1,180 @@
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2002 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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
+ * .
+ */
+package org.apache.commons.lang.math;
+
+import java.util.Random;
+
+/**
+ * JVMRandom
is a wrapper that supports all possible
+ * Random methods via the java.lang.Math.random() method and its system-wide
+ * Random object.
+ *
+ * @author Henri Yandell
+ * @since 2.0
+ * @version $Id: JVMRandom.java,v 1.6 2003/06/16 02:26:41 bayard Exp $
+ */
+public final class JVMRandom extends Random {
+
+ /** ensures that only the constructor can call reseed */
+ private boolean constructed = false;
+
+ public JVMRandom() {
+ this.constructed = true;
+ }
+
+ /** Unsupported in 2.0 */
+ public synchronized void setSeed(long seed) {
+ if (this.constructed) {
+ throw new UnsupportedOperationException();
+ }
+ }
+
+ /** Unsupported in 2.0 */
+ public synchronized double nextGaussian() {
+ throw new UnsupportedOperationException();
+ }
+
+ /** Unsupported in 2.0 */
+ public void nextBytes(byte[] byteArray) {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Returns the next pseudorandom, uniformly distributed int value
+ * from the Math.random() sequence.
+ *
+ * @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 the
+ * Math.random() sequence.
+ *
+ * @param n the specified exclusive max-value
+ * @throws IllegalArgumentException when n <= 0
+ *
+ * @return the random int
+ */
+ 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);
+ }
+ /**
+ * Returns the next pseudorandom, uniformly distributed long value
+ * from the Math.random() sequence.
+ *
+ * @return the random long
+ */
+ public long nextLong() {
+ // possible loss of precision?
+ return nextLong(Long.MAX_VALUE);
+ }
+
+
+ /**
+ * Returns a pseudorandom, uniformly distributed long value between 0
+ * (inclusive) and the specified value (exclusive), from the
+ * Math.random() sequence.
+ *
+ * @param n the specified exclusive max-value
+ * @throws IllegalArgumentException when n <= 0
+ *
+ * @return the random long
+ */
+ public static long nextLong(long n) {
+ if (n <= 0) {
+ throw new IllegalArgumentException(
+ "Upper bound for nextInt must be positive"
+ );
+ }
+ // TODO: check this cannot return 'n'
+ return (long)(Math.random() * n);
+ }
+
+ /**
+ * Returns the next pseudorandom, uniformly distributed boolean value
+ * from the Math.random() sequence.
+ *
+ * @return the random boolean
+ */
+ public boolean nextBoolean() {
+ return (Math.random() > 0.5);
+ }
+ /**
+ * Returns the next pseudorandom, uniformly distributed float value
+ * between 0.0 and 1.0 from the Math.random() sequence.
+ *
+ * @return the random float
+ */
+ public float nextFloat() {
+ return (float)Math.random();
+ }
+ /**
+ * Synonymous to the Math.random() call.
+ *
+ * @return the random double
+ */
+ public double nextDouble() {
+ return Math.random();
+ }
+
+}
diff --git a/examples/cl2/src/java/org/apache/commons/lang/math/LongRange.java b/examples/cl2/src/java/org/apache/commons/lang/math/LongRange.java
new file mode 100644
index 00000000..0d439aa5
--- /dev/null
+++ b/examples/cl2/src/java/org/apache/commons/lang/math/LongRange.java
@@ -0,0 +1,410 @@
+/* ====================================================================
+ * 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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
+ * .
+ */
+package org.apache.commons.lang.math;
+
+import java.io.Serializable;
+
+/**
+ *
LongRange
represents an inclusive range of long
s.
+ *
+ * @author Stephen Colebourne
+ * @since 2.0
+ * @version $Id: LongRange.java,v 1.2 2003/03/23 17:51:15 scolebourne Exp $
+ */
+public final class LongRange extends Range implements Serializable {
+
+ private static final long serialVersionUID = 71849363892720L;
+
+ /* The minimum number in this range (inclusive). */
+ private final long min;
+ /* The maximum number in this range (inclusive). */
+ private final long max;
+
+ /** Cached output minObject (class is immutable) */
+ private transient Long minObject = null;
+ /** Cached output maxObject (class is immutable) */
+ private transient Long maxObject = null;
+ /** Cached output hashCode (class is immutable) */
+ private transient int hashCode = 0;
+ /** Cached output toString (class is immutable) */
+ private transient String toString = null;
+
+ /**
+ * Constructs a new LongRange
using the specified
+ * number as both the minimum and maximum in this range.
+ *
+ * @param number the number to use for this range
+ */
+ public LongRange(long number) {
+ super();
+ this.min = number;
+ this.max = number;
+ }
+
+ /**
+ * Constructs a new LongRange
using the specified
+ * number as both the minimum and maximum in this range.
+ *
+ * @param number the number to use for this range, must not be null
+ * @throws IllegalArgumentException if the number is null
+ */
+ public LongRange(Number number) {
+ super();
+ if (number == null) {
+ throw new IllegalArgumentException("The number must not be null");
+ }
+ this.min = number.longValue();
+ this.max = number.longValue();
+ if (number instanceof Long) {
+ this.minObject = (Long) number;
+ this.maxObject = (Long) number;
+ }
+ }
+
+ /**
+ * Constructs a new LongRange
with the specified
+ * minimum and maximum numbers (both inclusive).
+ *
+ * The arguments may be passed in the order (min,max) or (max,min). The
+ * getMinimum and getMaximum methods will return the correct values.
+ *
+ * @param number1 first number that defines the edge of the range, inclusive
+ * @param number2 second number that defines the edge of the range, inclusive
+ */
+ public LongRange(long number1, long number2) {
+ super();
+ if (number2 < number1) {
+ this.min = number2;
+ this.max = number1;
+ } else {
+ this.min = number1;
+ this.max = number2;
+ }
+ }
+
+ /**
+ * Constructs a new LongRange
with the specified
+ * minimum and maximum numbers (both inclusive).
+ *
+ * The arguments may be passed in the order (min,max) or (max,min). The
+ * getMinimum and getMaximum methods will return the correct values.
+ *
+ * @param number1 first number that defines the edge of the range, inclusive
+ * @param number2 second number that defines the edge of the range, inclusive
+ * @throws IllegalArgumentException if either number is null
+ */
+ public LongRange(Number number1, Number number2) {
+ super();
+ if (number1 == null || number2 == null) {
+ throw new IllegalArgumentException("The numbers must not be null");
+ }
+ long number1val = number1.longValue();
+ long number2val = number2.longValue();
+ if (number2val < number1val) {
+ this.min = number2val;
+ this.max = number1val;
+ if (number2 instanceof Long) {
+ this.minObject = (Long) number2;
+ }
+ if (number1 instanceof Long) {
+ this.maxObject = (Long) number1;
+ }
+ } else {
+ this.min = number1val;
+ this.max = number2val;
+ if (number1 instanceof Long) {
+ this.minObject = (Long) number1;
+ }
+ if (number2 instanceof Long) {
+ this.maxObject = (Long) number2;
+ }
+ }
+ }
+
+ // Accessors
+ //--------------------------------------------------------------------
+
+ /**
+ * Returns the minimum number in this range.
+ *
+ * @return the minimum number in this range
+ */
+ public Number getMinimumNumber() {
+ if (minObject == null) {
+ minObject = new Long(min);
+ }
+ return minObject;
+ }
+
+ /**
+ * Gets the minimum number in this range as a long
.
+ *
+ * @return the minimum number in this range
+ */
+ public long getMinimumLong() {
+ return min;
+ }
+
+ /**
+ * Gets the minimum number in this range as a int
.
+ *
+ * This conversion can lose information for large values.
+ *
+ * @return the minimum number in this range
+ */
+ public int getMinimumInteger() {
+ return (int) min;
+ }
+
+ /**
+ * Gets the minimum number in this range as a double
.
+ *
+ * This conversion can lose information for large values.
+ *
+ * @return the minimum number in this range
+ */
+ public double getMinimumDouble() {
+ return min;
+ }
+
+ /**
+ * Gets the minimum number in this range as a float
.
+ *
+ * This conversion can lose information for large values.
+ *
+ * @return the minimum number in this range
+ */
+ public float getMinimumFloat() {
+ return min;
+ }
+
+ /**
+ * Returns the maximum number in this range.
+ *
+ * @return the maximum number in this range
+ */
+ public Number getMaximumNumber() {
+ if (maxObject == null) {
+ maxObject = new Long(max);
+ }
+ return maxObject;
+ }
+
+ /**
+ * Gets the maximum number in this range as a long
.
+ *
+ * @return the maximum number in this range
+ */
+ public long getMaximumLong() {
+ return max;
+ }
+
+ /**
+ * Gets the maximum number in this range as a int
.
+ *
+ * This conversion can lose information for large values.
+ */
+ public int getMaximumInteger() {
+ return (int) max;
+ }
+
+ /**
+ * Gets the maximum number in this range as a double
.
+ *
+ * This conversion can lose information for large values.
+ */
+ public double getMaximumDouble() {
+ return max;
+ }
+
+ /**
+ * Gets the maximum number in this range as a float
.
+ *
+ * This conversion can lose information for large values.
+ */
+ public float getMaximumFloat() {
+ return max;
+ }
+
+ // Tests
+ //--------------------------------------------------------------------
+
+ /**
+ * Tests whether the specified number
occurs within
+ * this range using long
comparison.
+ *
+ * null
is handled and returns false
.
+ *
+ * @param number the number to test, may be null
+ * @return true
if the specified number occurs within this range
+ */
+ public boolean includesNumber(Number number) {
+ if (number == null) {
+ return false;
+ }
+ return includesLong(number.longValue());
+ }
+
+ /**
+ * Tests whether the specified long
occurs within
+ * this range using long
comparison.
+ *
+ * This implementation overrides the superclass for performance as it is
+ * the most common case.
+ *
+ * @param value the long to test
+ * @return true
if the specified number occurs within this
+ * range by long
comparison
+ */
+ public boolean includesLong(long value) {
+ return (value >= min && value <= max);
+ }
+
+ // Range tests
+ //--------------------------------------------------------------------
+
+ /**
+ * Tests whether the specified range occurs entirely within this range
+ * using long
comparison.
+ *
+ * null
is handled and returns false
.
+ *
+ * @param range the range to test, may be null
+ * @return true
if the specified range occurs entirely within this range
+ * @throws IllegalArgumentException if the range is not of this type
+ */
+ public boolean includesRange(Range range) {
+ if (range == null) {
+ return false;
+ }
+ return includesLong(range.getMinimumLong()) &&
+ includesLong(range.getMaximumLong());
+ }
+
+ /**
+ * Tests whether the specified range overlaps with this range
+ * using long
comparison.
+ *
+ * null
is handled and returns false
.
+ *
+ * @param range the range to test, may be null
+ * @return true
if the specified range overlaps with this range
+ */
+ public boolean overlapsRange(Range range) {
+ if (range == null) {
+ return false;
+ }
+ return range.includesLong(min) ||
+ range.includesLong(max) ||
+ includesLong(range.getMinimumLong());
+ }
+
+ // Basics
+ //--------------------------------------------------------------------
+
+ /**
+ * Compares this range to another object to test if they are equal.
.
+ *
+ * To be equal, the class, minimum and maximum must be equal.
+ *
+ * @param obj the reference object with which to compare
+ * @return true
if this object is equal
+ */
+ public boolean equals(Object obj) {
+ if (obj == this) {
+ return true;
+ }
+ if (obj instanceof LongRange == false) {
+ return false;
+ }
+ LongRange range = (LongRange) obj;
+ return (min == range.min && max == range.max);
+ }
+
+ /**
+ * Gets a hashCode for the range.
+ *
+ * @return a hash code value for this object
+ */
+ public int hashCode() {
+ if (hashCode == 0) {
+ hashCode = 17;
+ hashCode = 37 * hashCode + getClass().hashCode();
+ hashCode = 37 * hashCode + ((int) (min ^ (min >> 32)));
+ hashCode = 37 * hashCode + ((int) (max ^ (max >> 32)));
+ }
+ return hashCode;
+ }
+
+ /**
+ * Gets the range as a String
.
+ *
+ * The format of the String is 'Range[min,max]'.
+ *
+ * @return the String
representation of this range
+ */
+ public String toString() {
+ if (toString == null) {
+ StringBuffer buf = new StringBuffer(32);
+ buf.append("Range[");
+ buf.append(min);
+ buf.append(',');
+ buf.append(max);
+ buf.append(']');
+ toString = buf.toString();
+ }
+ return toString;
+ }
+
+}
diff --git a/examples/cl2/src/java/org/apache/commons/lang/math/NumberRange.java b/examples/cl2/src/java/org/apache/commons/lang/math/NumberRange.java
new file mode 100644
index 00000000..894904cd
--- /dev/null
+++ b/examples/cl2/src/java/org/apache/commons/lang/math/NumberRange.java
@@ -0,0 +1,266 @@
+/* ====================================================================
+ * 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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
+ * .
+ */
+package org.apache.commons.lang.math;
+
+import java.io.Serializable;
+
+/**
+ * NumberRange
represents an inclusive range of
+ * {@link java.lang.Number Number} objects of the same type.
+ *
+ * @author Christopher Elkins
+ * @author Stephen Colebourne
+ * @since 2.0 (previously in org.apache.commons.lang)
+ * @version $Id: NumberRange.java,v 1.3 2003/04/09 01:04:47 ggregory Exp $
+ */
+public final class NumberRange extends Range implements Serializable {
+
+ private static final long serialVersionUID = 71849363892710L;
+
+ /* The minimum number in this range. */
+ private final Number min;
+ /* The maximum number in this range. */
+ private final Number max;
+
+ /** Cached output hashCode (class is immutable) */
+ private transient int hashCode = 0;
+ /** Cached output toString (class is immutable) */
+ private transient String toString = null;
+
+ /**
+ * Constructs a new NumberRange
using the specified
+ * number as both the minimum and maximum in this range.
+ *
+ * @param num the number to use for this range
+ * @throws IllegalArgumentException if the number is null
+ * @throws IllegalArgumentException if the number doesn't implement Comparable
+ * @throws IllegalArgumentException if the number is Double.NaN
or Float.NaN
+ */
+ public NumberRange(Number num) {
+ if (num == null) {
+ throw new IllegalArgumentException("The number must not be null");
+ }
+ if (num instanceof Comparable == false) {
+ throw new IllegalArgumentException("The number must implement Comparable");
+ }
+ if (num instanceof Double && ((Double) num).isNaN()) {
+ throw new IllegalArgumentException("The number must not be NaN");
+ }
+ if (num instanceof Float && ((Float) num).isNaN()) {
+ throw new IllegalArgumentException("The number must not be NaN");
+ }
+
+ this.min = num;
+ this.max = num;
+ }
+
+ /**
+ * Constructs a new NumberRange
with the specified
+ * minimum and maximum numbers (both inclusive).
+ *
+ * The arguments may be passed in the order (min,max) or (max,min). The
+ * {@link #getMinimumNumber()} and {@link #getMaximumNumber()} methods will return the
+ * correct value.
+ *
+ * This constructor is designed to be used with two Number
+ * objects of the same type. If two objects of different types are passed in,
+ * an exception is thrown.
+ *
+ * @param num1 first number that defines the edge of the range, inclusive
+ * @param num2 second number that defines the edge of the range, inclusive
+ * @throws IllegalArgumentException if either number is null
+ * @throws IllegalArgumentException if the numbers are of different types
+ * @throws IllegalArgumentException if the numbers don't implement Comparable
+ */
+ public NumberRange(Number num1, Number num2) {
+ if (num1 == null || num2 == null) {
+ throw new IllegalArgumentException("The numbers must not be null");
+ }
+ if (num1.getClass() != num2.getClass()) {
+ throw new IllegalArgumentException("The numbers must be of the same type");
+ }
+ if (num1 instanceof Comparable == false) {
+ throw new IllegalArgumentException("The numbers must implement Comparable");
+ }
+ if (num1 instanceof Double) {
+ if (((Double) num1).isNaN() || ((Double) num2).isNaN()) {
+ throw new IllegalArgumentException("The number must not be NaN");
+ }
+ } else if (num1 instanceof Float) {
+ if (((Float) num1).isNaN() || ((Float) num2).isNaN()) {
+ throw new IllegalArgumentException("The number must not be NaN");
+ }
+ }
+
+ int compare = ((Comparable) num1).compareTo(num2);
+ if (compare == 0) {
+ this.min = num1;
+ this.max = num1;
+ } else if (compare > 0) {
+ this.min = num2;
+ this.max = num1;
+ } else {
+ this.min = num1;
+ this.max = num2;
+ }
+ }
+
+ // Accessors
+ //--------------------------------------------------------------------
+
+ /**
+ * Returns the minimum number in this range.
+ *
+ * @return the minimum number in this range
+ */
+ public Number getMinimumNumber() {
+ return min;
+ }
+
+ /**
+ * Returns the maximum number in this range.
+ *
+ * @return the maximum number in this range
+ */
+ public Number getMaximumNumber() {
+ return max;
+ }
+
+ // Tests
+ //--------------------------------------------------------------------
+
+ /**
+ * Tests whether the specified number
occurs within
+ * this range.
+ *
+ * null
is handled and returns false
.
+ *
+ * @param number the number to test, may be null
+ * @return true
if the specified number occurs within this range
+ * @throws IllegalArgumentException if the number is of a different type to the range
+ */
+ public boolean includesNumber(Number number) {
+ if (number == null) {
+ return false;
+ }
+ if (number.getClass() != min.getClass()) {
+ throw new IllegalArgumentException("The number must be of the same type as the range numbers");
+ }
+ int compareMin = ((Comparable) min).compareTo(number);
+ int compareMax = ((Comparable) max).compareTo(number);
+ return (compareMin <= 0 && compareMax >= 0);
+ }
+
+ // Range tests
+ //--------------------------------------------------------------------
+ // use Range implementations
+
+ // Basics
+ //--------------------------------------------------------------------
+
+ /**
+ * Compares this range to another object to test if they are equal.
.
+ *
+ * To be equal, the class, minimum and maximum must be equal.
+ *
+ * @param obj the reference object with which to compare
+ * @return true
if this object is equal
+ */
+ public boolean equals(Object obj) {
+ if (obj == this) {
+ return true;
+ }
+ if (obj instanceof NumberRange == false) {
+ return false;
+ }
+ NumberRange range = (NumberRange) obj;
+ return min.equals(range.min) && max.equals(range.max);
+ }
+
+ /**
+ * Gets a hashCode for the range.
+ *
+ * @return a hash code value for this object
+ */
+ public int hashCode() {
+ if (hashCode == 0) {
+ hashCode = 17;
+ hashCode = 37 * hashCode + getClass().hashCode();
+ hashCode = 37 * hashCode + min.hashCode();
+ hashCode = 37 * hashCode + max.hashCode();
+ }
+ return hashCode;
+ }
+
+ /**
+ * Gets the range as a String
.
+ *
+ * The format of the String is 'Range[min,max]'.
+ *
+ * @return the String
representation of this range
+ */
+ public String toString() {
+ if (toString == null) {
+ StringBuffer buf = new StringBuffer(32);
+ buf.append("Range[");
+ buf.append(min);
+ buf.append(',');
+ buf.append(max);
+ buf.append(']');
+ toString = buf.toString();
+ }
+ return toString;
+ }
+
+}
diff --git a/examples/cl2/src/java/org/apache/commons/lang/math/RandomUtils.java b/examples/cl2/src/java/org/apache/commons/lang/math/RandomUtils.java
new file mode 100644
index 00000000..46f4bf2d
--- /dev/null
+++ b/examples/cl2/src/java/org/apache/commons/lang/math/RandomUtils.java
@@ -0,0 +1,152 @@
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2002 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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
+ * .
+ */
+package org.apache.commons.lang.math;
+
+import java.util.Random;
+
+/**
+ * RandomUtils
is a wrapper that supports all possible
+ * Random methods via the java.lang.Math.random() method and its system-wide
+ * Random object.
+ *
+ * @author Henri Yandell
+ * @since 2.0
+ * @version $Id: RandomUtils.java,v 1.2 2003/05/07 15:09:19 bayard Exp $
+ */
+public final class RandomUtils {
+
+ public static Random JVM_RANDOM = new JVMRandom();
+
+// should be possible for JVM_RANDOM?
+// public static void nextBytes(byte[]) {
+// public synchronized double nextGaussian();
+// }
+
+ /**
+ * Returns the next pseudorandom, uniformly distributed int value
+ * from the Math.random() sequence.
+ *
+ * @return the random int
+ */
+ public static int nextInt() {
+ return nextInt(JVM_RANDOM);
+ }
+ public static int nextInt(Random rnd) {
+ return rnd.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) {
+ // check this cannot return 'n'
+ return rnd.nextInt(n);
+ }
+ /**
+ * Returns the next pseudorandom, uniformly distributed long value
+ * from the Math.random() sequence.
+ *
+ * @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 boolean value
+ * from the Math.random() sequence.
+ *
+ * @return the random boolean
+ */
+ public static boolean nextBoolean() {
+ return nextBoolean(JVM_RANDOM);
+ }
+ public static boolean nextBoolean(Random rnd) {
+ return rnd.nextBoolean();
+ }
+ /**
+ * Returns the next pseudorandom, uniformly distributed float value
+ * between 0.0 and 1.0 from the Math.random() sequence.
+ *
+ * @return the random float
+ */
+ public static float nextFloat() {
+ return nextFloat(JVM_RANDOM);
+ }
+ public static float nextFloat(Random rnd) {
+ return rnd.nextFloat();
+ }
+ /**
+ * Synonymous to the Math.random() call.
+ *
+ * @return the random double
+ */
+ public static double nextDouble() {
+ return nextDouble(JVM_RANDOM);
+ }
+ public static double nextDouble(Random rnd) {
+ return rnd.nextDouble();
+ }
+
+}
diff --git a/examples/cl2/src/java/org/apache/commons/lang/math/Range.java b/examples/cl2/src/java/org/apache/commons/lang/math/Range.java
new file mode 100644
index 00000000..15175863
--- /dev/null
+++ b/examples/cl2/src/java/org/apache/commons/lang/math/Range.java
@@ -0,0 +1,470 @@
+/* ====================================================================
+ * 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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
+ * .
+ */
+package org.apache.commons.lang.math;
+
+import org.apache.commons.lang.NumberUtils;
+
+/**
+ *
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
+ * @since 2.0
+ * @version $Id: Range.java,v 1.2 2003/03/23 17:51:15 scolebourne Exp $
+ */
+public abstract class Range {
+
+ /**
+ * Constructs a new range.
+ */
+ public Range() {
+ super();
+ }
+
+ // Accessors
+ //--------------------------------------------------------------------
+
+ /**
+ * Gets the minimum number in this range.
+ *
+ * @return the minimum number in this range
+ */
+ public abstract Number getMinimumNumber();
+
+ /**
+ * Gets the minimum number in this range as a long
.
+ *
+ * This implementation uses the {@link #getMinimumNumber()} method.
+ * Subclasses may be able to optimise this.
+ *
+ * @return the minimum number in this range
+ */
+ public long getMinimumLong() {
+ return getMinimumNumber().longValue();
+ }
+
+ /**
+ * Gets the minimum number in this range as a int
.
+ *
+ * This implementation uses the {@link #getMinimumNumber()} method.
+ * Subclasses may be able to optimise this.
+ *
+ * @return the minimum number in this range
+ */
+ public int getMinimumInteger() {
+ return getMinimumNumber().intValue();
+ }
+
+ /**
+ * Gets the minimum number in this range as a double
.
+ *
+ * This implementation uses the {@link #getMinimumNumber()} method.
+ * Subclasses may be able to optimise this.
+ *
+ * @return the minimum number in this range
+ */
+ public double getMinimumDouble() {
+ return getMinimumNumber().doubleValue();
+ }
+
+ /**
+ * Gets the minimum number in this range as a float
.
+ *
+ * This implementation uses the {@link #getMinimumNumber()} method.
+ * Subclasses may be able to optimise this.
+ *
+ * @return the minimum number in this range
+ */
+ public float getMinimumFloat() {
+ return getMinimumNumber().floatValue();
+ }
+
+ /**
+ * Gets the maximum number in this range.
+ *
+ * @return the maximum number in this range
+ */
+ public abstract Number getMaximumNumber();
+
+ /**
+ * Gets the maximum number in this range as a long
.
+ *
+ * This implementation uses the {@link #getMaximumNumber()} method.
+ * Subclasses may be able to optimise this.
+ *
+ * @return the maximum number in this range
+ */
+ public long getMaximumLong() {
+ return getMaximumNumber().longValue();
+ }
+
+ /**
+ * Gets the maximum number in this range as a int
.
+ *
+ * This implementation uses the {@link #getMaximumNumber()} method.
+ * Subclasses may be able to optimise this.
+ *
+ * @return the maximum number in this range
+ */
+ public int getMaximumInteger() {
+ return getMaximumNumber().intValue();
+ }
+
+ /**
+ * Gets the maximum number in this range as a double
.
+ *
+ * This implementation uses the {@link #getMaximumNumber()} method.
+ * Subclasses may be able to optimise this.
+ *
+ * @return the maximum number in this range
+ */
+ public double getMaximumDouble() {
+ return getMaximumNumber().doubleValue();
+ }
+
+ /**
+ * Gets the maximum number in this range as a float
.
+ *
+ * This implementation uses the {@link #getMaximumNumber()} method.
+ * Subclasses may be able to optimise this.
+ *
+ * @return the maximum number in this range
+ */
+ public float getMaximumFloat() {
+ return getMaximumNumber().floatValue();
+ }
+
+ // Include tests
+ //--------------------------------------------------------------------
+
+ /**
+ * Tests whether the specified Number
occurs within
+ * this range.
+ *
+ * The exact comparison implementation varies by subclass. It is
+ * intended that an int
specific subclass will compare using
+ * int
comparison.
+ *
+ * null
is handled and returns false
.
+ *
+ * @param number the number to test, may be null
+ * @return true
if the specified number occurs within this range
+ * @throws IllegalArgumentException if the Number
cannot be compared
+ */
+ public abstract boolean includesNumber(Number number);
+
+ /**
+ * Tests whether the specified Number
occurs within
+ * this range using long
comparison..
+ *
+ * null
is handled and returns false
.
+ *
+ * This implementation forwards to the {@link #includesLong(long)} method.
+ *
+ * @param value the long to test, may be null
+ * @return true
if the specified number occurs within this
+ * range by long
comparison
+ */
+ public boolean includesLong(Number value) {
+ if (value == null) {
+ return false;
+ }
+ return includesLong(value.longValue());
+ }
+
+ /**
+ * Tests whether the specified long
occurs within
+ * this range using long
comparison.
+ *
+ * This implementation uses the {@link #getMinimumLong()} and
+ * {@link #getMaximumLong()} methods and should be good for most uses.
+ *
+ * @param value the long to test
+ * @return true
if the specified number occurs within this
+ * range by long
comparison
+ */
+ public boolean includesLong(long value) {
+ return (value >= getMinimumLong() && value <= getMaximumLong());
+ }
+
+ /**
+ * Tests whether the specified Number
occurs within
+ * this range using int
comparison..
+ *
+ * null
is handled and returns false
.
+ *
+ * This implementation forwards to the {@link #includesInteger(int)} method.
+ *
+ * @param value the integer to test, may be null
+ * @return true
if the specified number occurs within this
+ * range by int
comparison
+ */
+ public boolean includesInteger(Number value) {
+ if (value == null) {
+ return false;
+ }
+ return includesInteger(value.intValue());
+ }
+
+ /**
+ * Tests whether the specified int
occurs within
+ * this range using int
comparison.
+ *
+ * This implementation uses the {@link #getMinimumInteger()} and
+ * {@link #getMaximumInteger()} methods and should be good for most uses.
+ *
+ * @param value the int to test
+ * @return true
if the specified number occurs within this
+ * range by int
comparison
+ */
+ public boolean includesInteger(int value) {
+ return (value >= getMinimumInteger() && value <= getMaximumInteger());
+ }
+
+ /**
+ * Tests whether the specified Number
occurs within
+ * this range using double
comparison..
+ *
+ * null
is handled and returns false
.
+ *
+ * This implementation forwards to the {@link #includesDouble(double)} method.
+ *
+ * @param value the double to test, may be null
+ * @return true
if the specified number occurs within this
+ * range by double
comparison
+ */
+ public boolean includesDouble(Number value) {
+ if (value == null) {
+ return false;
+ }
+ return includesDouble(value.doubleValue());
+ }
+
+ /**
+ * Tests whether the specified double
occurs within
+ * this range using double
comparison.
+ *
+ * This implementation uses the {@link #getMinimumDouble()} and
+ * {@link #getMaximumDouble()} methods and should be good for most uses.
+ *
+ * @param value the double to test
+ * @return true
if the specified number occurs within this
+ * range by double
comparison
+ */
+ public boolean includesDouble(double value) {
+ int compareMin = NumberUtils.compare(getMinimumDouble(), value);
+ int compareMax = NumberUtils.compare(getMaximumDouble(), value);
+ return (compareMin <= 0 && compareMax >= 0);
+ }
+
+ /**
+ * Tests whether the specified Number
occurs within
+ * this range using float
comparison.
+ *
+ * null
is handled and returns false
.
+ *
+ * This implementation forwards to the {@link #includesFloat(float)} method.
+ *
+ * @param value the float to test, may be null
+ * @return true
if the specified number occurs within this
+ * range by float
comparison
+ */
+ public boolean includesFloat(Number value) {
+ if (value == null) {
+ return false;
+ }
+ return includesFloat(value.floatValue());
+ }
+
+ /**
+ * Tests whether the specified float
occurs within
+ * this range using float
comparison.
+ *
+ * This implementation uses the {@link #getMinimumFloat()} and
+ * {@link #getMaximumFloat()} methods and should be good for most uses.
+ *
+ * @param value the float to test
+ * @return true
if the specified number occurs within this
+ * range by float
comparison
+ */
+ public boolean includesFloat(float value) {
+ int compareMin = NumberUtils.compare(getMinimumFloat(), value);
+ int compareMax = NumberUtils.compare(getMaximumFloat(), value);
+ return (compareMin <= 0 && compareMax >= 0);
+ }
+
+ // Range tests
+ //--------------------------------------------------------------------
+
+ /**
+ * Tests whether the specified range occurs entirely within this range.
+ *
+ * The exact comparison implementation varies by subclass. It is
+ * intended that an int
specific subclass will compare using
+ * int
comparison.
+ *
+ * null
is handled and returns false
.
+ *
+ * This implementation uses the {@link #includesNumber(Number)} method.
+ * Subclasses may be able to optimise this.
+ *
+ * @param range the range to test, may be null
+ * @return true
if the specified range occurs entirely within
+ * this range; otherwise, false
+ * @throws IllegalArgumentException if the Range
cannot be compared
+ */
+ public boolean includesRange(Range range) {
+ if (range == null) {
+ return false;
+ }
+ return includesNumber(range.getMinimumNumber()) &&
+ includesNumber(range.getMaximumNumber());
+ }
+
+ /**
+ * Tests whether the specified range overlaps with this range.
+ *
+ * The exact comparison implementation varies by subclass. It is
+ * intended that an int
specific subclass will compare using
+ * int
comparison.
+ *
+ * null
is handled and returns false
.
+ *
+ * This implementation uses the {@link #includesNumber(Number)} and
+ * {@link #includesRange(Range)} methods.
+ * Subclasses may be able to optimise this.
+ *
+ * @param range the range to test, may be null
+ * @return true
if the specified range overlaps with this
+ * range; otherwise, false
+ * @throws IllegalArgumentException if the Range
cannot be compared
+ */
+ public boolean overlapsRange(Range range) {
+ if (range == null) {
+ return false;
+ }
+ return range.includesNumber(getMinimumNumber()) ||
+ range.includesNumber(getMaximumNumber()) ||
+ includesNumber(range.getMinimumNumber());
+ }
+
+ // Basics
+ //--------------------------------------------------------------------
+
+ /**
+ * Compares this range to another object to test if they are equal.
.
+ *
+ * To be equal, the class, minimum and maximum must be equal.
+ *
+ * This implementation uses the {@link #getMinimumNumber()} and
+ * {@link #getMaximumNumber()} methods.
+ * Subclasses may be able to optimise this.
+ *
+ * @param obj the reference object with which to compare
+ * @return true
if this object is equal
+ */
+ public boolean equals(Object obj) {
+ if (obj == this) {
+ return true;
+ } else if (obj == null || obj.getClass() != getClass()) {
+ return false;
+ } else {
+ Range range = (Range) obj;
+ return getMinimumNumber().equals(range.getMinimumNumber()) &&
+ getMaximumNumber().equals(range.getMaximumNumber());
+ }
+ }
+
+ /**
+ * Gets a hashCode for the range.
+ *
+ * This implementation uses the {@link #getMinimumNumber()} and
+ * {@link #getMaximumNumber()} methods.
+ * Subclasses may be able to optimise this.
+ *
+ * @return a hash code value for this object
+ */
+ public int hashCode() {
+ int result = 17;
+ result = 37 * result + getClass().hashCode();
+ result = 37 * result + getMinimumNumber().hashCode();
+ result = 37 * result + getMaximumNumber().hashCode();
+ return result;
+ }
+
+ /**
+ * Gets the range as a String
.
+ *
+ * The format of the String is 'Range[min,max]'.
+ *
+ * This implementation uses the {@link #getMinimumNumber()} and
+ * {@link #getMaximumNumber()} methods.
+ * Subclasses may be able to optimise this.
+ *
+ * @return the String
representation of this range
+ */
+ public String toString() {
+ StringBuffer buf = new StringBuffer(32);
+ buf.append("Range[");
+ buf.append(getMinimumNumber());
+ buf.append(',');
+ buf.append(getMaximumNumber());
+ buf.append(']');
+ return buf.toString();
+ }
+
+}
diff --git a/examples/cl2/src/java/org/apache/commons/lang/math/package.html b/examples/cl2/src/java/org/apache/commons/lang/math/package.html
new file mode 100644
index 00000000..1503ff9a
--- /dev/null
+++ b/examples/cl2/src/java/org/apache/commons/lang/math/package.html
@@ -0,0 +1,6 @@
+
+
+Extends java.math
for business mathematical classes. This package is intended for business
+mathematical classes, not scientific ones.
+
+
diff --git a/examples/cl2/src/java/org/apache/commons/lang/overview.html b/examples/cl2/src/java/org/apache/commons/lang/overview.html
new file mode 100644
index 00000000..3314daae
--- /dev/null
+++ b/examples/cl2/src/java/org/apache/commons/lang/overview.html
@@ -0,0 +1,7 @@
+
+
+
+This document is the API specification for the Apache Jakarta Commons Lang Library, version 2.0.
+
+
+
\ No newline at end of file
diff --git a/examples/cl2/src/java/org/apache/commons/lang/package.html b/examples/cl2/src/java/org/apache/commons/lang/package.html
new file mode 100644
index 00000000..61cf85dc
--- /dev/null
+++ b/examples/cl2/src/java/org/apache/commons/lang/package.html
@@ -0,0 +1,6 @@
+
+
+Provides highly reusable static utility methods, chiefly concerned
+with adding value to java.lang
and other standard core classes.
+
+
diff --git a/examples/cl2/src/java/org/apache/commons/lang/reflect/ConstructorUtils.java b/examples/cl2/src/java/org/apache/commons/lang/reflect/ConstructorUtils.java
new file mode 100644
index 00000000..4ceddf75
--- /dev/null
+++ b/examples/cl2/src/java/org/apache/commons/lang/reflect/ConstructorUtils.java
@@ -0,0 +1,428 @@
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2002 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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
+ * .
+ */
+package org.apache.commons.lang.reflect;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Modifier;
+
+import org.apache.commons.lang.ArrayUtils;
+/**
+ * ConstructorUtils
contains utility methods for working for
+ * constructors by reflection.
+ *
+ * The ability is provided to break the scoping restrictions coded by the
+ * programmer. This can allow classes to be created that shouldn't be, for
+ * example new instances of an enumerated type. Thus, this facility should
+ * be used with care.
+ *
+ * @author Stephen Colebourne
+ * @version $Id: ConstructorUtils.java,v 1.1 2002/10/24 23:12:54 scolebourne Exp $
+ */
+public class ConstructorUtils {
+
+ /** An empty constructor array */
+ public static final Constructor[] EMPTY_CONSTRUCTOR_ARRAY = new Constructor[0];
+
+ /**
+ * ConstructorUtils instances should NOT be constructed in standard programming.
+ * Instead, the class should be used as ConstructorUtils.newInstance(...)
.
+ * This constructor is public to permit tools that require a JavaBean instance
+ * to operate.
+ */
+ public ConstructorUtils() {
+ }
+
+ // -------------------------------------------------------------------------
+
+ /**
+ * Gets a public Constructor
object by matching the
+ * parameter types as per the Java Language Specification.
+ *
+ * @param cls Class object to find constructor for, must not be null
+ * @param types array of Class objects representing parameter types, may be null
+ * @return Constructor object
+ * @throws ReflectionException if an error occurs during reflection
+ * @throws IllegalArgumentException if the class is null
+ */
+ public static Constructor getConstructor(Class cls, Class[] types) {
+ return getConstructor(cls, types, false);
+ }
+
+ /**
+ * Gets a public Constructor
object by matching the
+ * parameter types as per the Java Language Specification.
+ *
+ * @param cls Class object to find constructor for, must not be null
+ * @param types array of Class objects representing parameter types, may be null
+ * @param breakScope whether to break scope restrictions using the
+ * setAccessible
method. False will only match public methods.
+ * @return Constructor object
+ * @throws ReflectionException if an error occurs during reflection
+ * @throws IllegalArgumentException if the class is null
+ */
+ public static Constructor getConstructor(Class cls, Class[] types, boolean breakScope) {
+ if (cls == null) {
+ throw new IllegalArgumentException("The class must not be null");
+ }
+ // try exact call first for speed
+ try {
+ getConstructorExact(cls, types, breakScope);
+
+ } catch (ReflectionException ex) {
+ if (types == null || types.length == 0) {
+ throw ex;
+ }
+ if (ex.getCause() instanceof NoSuchMethodException == false) {
+ throw ex;
+ }
+ }
+ // try to find best match
+ try {
+ Constructor[] cons = cls.getDeclaredConstructors();
+ for (int i = 0; i < cons.length; i++) {
+ if (cons[i].getParameterTypes().length == types.length) {
+ // TODO
+ }
+ }
+ return null;
+
+ } catch (ReflectionException ex) {
+ throw ex;
+ } catch (LinkageError ex) {
+ throw new ReflectionException(ReflectionUtils.getThrowableText(
+ ex, "getting constructor", cls.getName(), types, null), ex);
+ } catch (Exception ex) {
+ throw new ReflectionException(ReflectionUtils.getThrowableText(
+ ex, "getting constructor", cls.getName(), types, null), ex);
+ }
+ }
+
+ // -------------------------------------------------------------------------
+
+ /**
+ * Gets a public Constructor
object by exactly matching the
+ * parameter types.
+ *
+ * @param cls Class object to find constructor for, must not be null
+ * @param types array of Class objects representing parameter types, may be null
+ * @return Constructor object
+ * @throws ReflectionException if an error occurs during reflection
+ * @throws IllegalArgumentException if the class is null
+ */
+ public static Constructor getConstructorExact(Class cls, Class[] types) {
+ return getConstructorExact(cls, types, false);
+ }
+
+ /**
+ * Gets a Constructor
object by exactly matching the
+ * parameter types.
+ *
+ * @param cls Class object to find constructor for, must not be null
+ * @param types array of Class objects representing parameter types, may be null
+ * @param breakScope whether to break scope restrictions using the
+ * setAccessible
method. False will only match public methods.
+ * @return Constructor object
+ * @throws ReflectionException if an error occurs during reflection
+ * @throws IllegalArgumentException if the class is null
+ */
+ public static Constructor getConstructorExact(Class cls, Class[] types, boolean breakScope) {
+ if (cls == null) {
+ throw new IllegalArgumentException("The class must not be null");
+ }
+ try {
+ if (breakScope) {
+ Constructor con = cls.getDeclaredConstructor(types);
+ if (Modifier.isPublic(con.getModifiers()) == false) {
+ con.setAccessible(true);
+ }
+ return con;
+
+ } else {
+ return cls.getConstructor(types);
+ }
+
+ } catch (ReflectionException ex) {
+ throw ex;
+ } catch (LinkageError ex) {
+ throw new ReflectionException(ReflectionUtils.getThrowableText(
+ ex, "getting constructor", cls.getName(), types, null), ex);
+ } catch (Exception ex) {
+ throw new ReflectionException(ReflectionUtils.getThrowableText(
+ ex, "getting constructor", cls.getName(), types, null), ex);
+ }
+ }
+
+ // -------------------------------------------------------------------------
+
+ /**
+ * Creates a new instance using a Constructor
and parameters.
+ *
+ * @param con Class object to find constructor for, must not be null
+ * @param param the single parameter to pass to the constructor, may be null
+ * @return the newly created object
+ * @throws ReflectionException if an error occurs during reflection
+ * @throws IllegalArgumentException if the constructor is null
+ */
+ public static Object newInstance(Constructor con, Object param) {
+ return newInstance(con, new Object[] {param}, false);
+ }
+
+ /**
+ * Creates a new instance using a Constructor
and parameters.
+ *
+ * @param con Class object to find constructor for, must not be null
+ * @param params array of objects to pass as parameters, may be null
+ * @return the newly created object
+ * @throws ReflectionException if an error occurs during reflection
+ * @throws IllegalArgumentException if the constructor is null
+ */
+ public static Object newInstance(Constructor con, Object[] params) {
+ return newInstance(con, params, false);
+ }
+
+ /**
+ * Creates a new instance using a Constructor
and parameters.
+ *
+ * @param con Class object to find constructor for, must not be null
+ * @param params array of objects to pass as parameters, may be null
+ * @param breakScope whether to break scope restrictions using the
+ * setAccessible
method. False will only match public methods.
+ * @return the newly created object
+ * @throws ReflectionException if an error occurs during reflection
+ * @throws IllegalArgumentException if the constructor is null
+ */
+ public static Object newInstance(Constructor con, Object[] params, boolean breakScope) {
+ if (con == null) {
+ throw new IllegalArgumentException("The constructor must not be null");
+ }
+ try {
+ if (breakScope && Modifier.isPublic(con.getModifiers()) == false) {
+ con.setAccessible(true);
+ }
+ return con.newInstance(params);
+
+ } catch (ReflectionException ex) {
+ throw ex;
+ } catch (LinkageError ex) {
+ throw new ReflectionException(ReflectionUtils.getThrowableText(
+ ex, "invoking constructor", con.getDeclaringClass().getName(), con.getParameterTypes(), null), ex);
+ } catch (Exception ex) {
+ throw new ReflectionException(ReflectionUtils.getThrowableText(
+ ex, "invoking constructor", con.getDeclaringClass().getName(), con.getParameterTypes(), null), ex);
+ }
+ }
+
+ // -------------------------------------------------------------------------
+
+ /**
+ * Creates a new instance of the specified Class
by name.
+ *
+ * @param className String class name to instantiate, must not be empty
+ * @return the newly created object
+ * @throws ReflectionException if an error occurs during reflection
+ * @throws IllegalArgumentException if the class name is empty
+ */
+ public static Object newInstance(String className) {
+ return newInstance(className, false);
+ }
+
+ /**
+ * Creates a new instance of the specified Class
by name.
+ * If the constructor is not public, setAccessible(true)
+ * is used to make it accessible.
+ *
+ * @param className String class name to instantiate, must not be empty
+ * @param breakScope whether to break scope restrictions using the
+ * setAccessible
method. False will only match public methods.
+ * @return the newly created object
+ * @throws ReflectionException if an error occurs during reflection
+ * @throws IllegalArgumentException if the class name is empty
+ */
+ public static Object newInstance(String className, boolean breakScope) {
+ Class cls = ReflectionUtils.getClass(className);
+ return newInstance(cls, breakScope);
+ }
+
+ // -------------------------------------------------------------------------
+
+ /**
+ * Creates a new instance of the specified Class
.
+ *
+ * @param cls Class object to instantiate, must not be null
+ * @return the newly created object
+ * @throws ReflectionException if an error occurs during reflection
+ * @throws IllegalArgumentException if the class is null
+ */
+ public static Object newInstance(Class cls) {
+ return newInstance(cls, false);
+ }
+
+ /**
+ * Creates a new instance of the specified Class
.
+ * If the constructor is not public, setAccessible(true)
+ * is used to make it accessible.
+ *
+ * @param cls Class object to instantiate, must not be null
+ * @param breakScope whether to break scope restrictions using the
+ * setAccessible
method. False will only match public methods.
+ * @return the newly created object
+ * @throws ReflectionException if an error occurs during reflection
+ * @throws IllegalArgumentException if the class is null
+ */
+ public static Object newInstance(Class cls, boolean breakScope) {
+ if (breakScope) {
+ return newInstanceExact(cls, null, null, true);
+
+ } else {
+ if (cls == null) {
+ throw new IllegalArgumentException("The constructor must not be null");
+ }
+ try {
+ return cls.newInstance();
+
+ } catch (ReflectionException ex) {
+ throw ex;
+ } catch (LinkageError ex) {
+ throw new ReflectionException(ReflectionUtils.getThrowableText(
+ ex, "instantiating class", cls.getName(), null, null), ex);
+ } catch (Exception ex) {
+ throw new ReflectionException(ReflectionUtils.getThrowableText(
+ ex, "instantiating class", cls.getName(), null, null), ex);
+ }
+ }
+ }
+
+ // -------------------------------------------------------------------------
+
+ /**
+ * Creates a new instance of the specified Class
.
+ * The constructor is found by matching the
+ * parameter types as per the Java Language Specification.
+ *
+ * @param cls Class object to instantiate, must not be null
+ * @param types array of Class objects representing parameter types, may be null
+ * @param params array of objects to pass as parameters, may be null
+ * @return the newly created object
+ * @throws ReflectionException if an error occurs during reflection
+ * @throws IllegalArgumentException if the class is null
+ */
+ public static Object newInstance(Class cls, Class[] types, Object[] params) {
+ return newInstance(cls, types, params, false);
+ }
+
+ /**
+ * Creates a new instance of the specified Class
.
+ * The constructor is found by matching the
+ * parameter types as per the Java Language Specification.
+ *
+ * @param cls Class object to instantiate, must not be null
+ * @param types array of Class objects representing parameter types, may be null
+ * @param params array of objects to pass as parameters, may be null
+ * @param breakScope whether to break scope restrictions using the
+ * setAccessible
method. False will only match public methods.
+ * @return the newly created object
+ * @throws ReflectionException if an error occurs during reflection
+ * @throws IllegalArgumentException if the types and params lengths differ
+ * @throws IllegalArgumentException if the class is null
+ */
+ public static Object newInstance(Class cls, Class[] types, Object[] params, boolean breakScope) {
+ if (ArrayUtils.isSameLength(types, params) == false) {
+ throw new IllegalArgumentException("The types and params lengths must be the same");
+ }
+ Constructor con = getConstructor(cls, types, breakScope);
+ return newInstance(con, params, breakScope);
+ }
+
+ // -------------------------------------------------------------------------
+
+ /**
+ * Creates a new instance of the specified Class
.
+ * The constructor is found by matching the parameter types exactly.
+ *
+ * @param cls Class object to instantiate, must not be null
+ * @param types array of Class objects representing parameter types, may be null
+ * @param params array of objects to pass as parameters, may be null
+ * @return the newly created object
+ * @throws ReflectionException if an error occurs during reflection
+ * @throws IllegalArgumentException if the class is null
+ */
+ public static Object newInstanceExact(Class cls, Class[] types, Object[] params) {
+ return newInstanceExact(cls, types, params, false);
+ }
+
+ /**
+ * Creates a new instance of the specified Class
.
+ * The constructor is found by matching the parameter types exactly.
+ *
+ * @param cls Class object to instantiate, must not be null
+ * @param types array of Class objects representing parameter types, may be null
+ * @param params array of objects to pass as parameters, may be null
+ * @param breakScope whether to break scope restrictions using the
+ * setAccessible
method. False will only match public methods.
+ * @return the newly created object
+ * @throws ReflectionException if an error occurs during reflection
+ * @throws IllegalArgumentException if the types and params lengths differ
+ * @throws IllegalArgumentException if the class is null
+ */
+ public static Object newInstanceExact(Class cls, Class[] types, Object[] params, boolean breakScope) {
+ if (ArrayUtils.isSameLength(types, params) == false) {
+ throw new IllegalArgumentException("The types and params lengths must be the same");
+ }
+ Constructor con = getConstructorExact(cls, types, breakScope);
+ return newInstance(con, params, breakScope);
+ }
+
+ // -------------------------------------------------------------------------
+
+}
diff --git a/examples/cl2/src/java/org/apache/commons/lang/reflect/FieldUtils.java b/examples/cl2/src/java/org/apache/commons/lang/reflect/FieldUtils.java
new file mode 100644
index 00000000..b2c082e0
--- /dev/null
+++ b/examples/cl2/src/java/org/apache/commons/lang/reflect/FieldUtils.java
@@ -0,0 +1,492 @@
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2002 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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
+ * .
+ */
+package org.apache.commons.lang.reflect;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+/**
+ * FieldUtils
contains utility methods for working with
+ * fields by reflection.
+ *
+ * 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 Stephen Colebourne
+ * @version $Id: FieldUtils.java,v 1.1 2002/10/24 23:12:54 scolebourne Exp $
+ */
+public class FieldUtils {
+
+ /** An empty field array */
+ public static final Field[] EMPTY_FIELD_ARRAY = new Field[0];
+
+ /**
+ * FieldUtils instances should NOT be constructed in standard programming.
+ * Instead, the class should be used as FieldUtils.getField(cls, name)
.
+ * This constructor is public to permit tools that require a JavaBean instance
+ * to operate.
+ */
+ public FieldUtils() {
+ }
+
+ // -------------------------------------------------------------------------
+
+ /**
+ * Gets an accessible Field by name repecting 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
+ * @throws ReflectionException if an error occurs during reflection
+ */
+ public static Field getField(Class cls, String fieldName) {
+ return getField(cls, fieldName, false);
+ }
+
+ /**
+ * 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 breakScope 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 ReflectionException if an error occurs during reflection
+ */
+ public static Field getField(Class cls, String fieldName, boolean breakScope) {
+ 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
+ try {
+ // check up the superclass hierarchy
+ Class acls = cls;
+ Field match = null;
+ while (acls != null && acls != Object.class) {
+ // getDeclaredField checks for non-public scopes as well
+ // and it returns accurate results
+ try {
+ Field field = acls.getDeclaredField(fieldName);
+ if (Modifier.isPublic(field.getModifiers()) == false) {
+ field.setAccessible(breakScope);
+ return field;
+ }
+ if (breakScope == false) {
+ // only public acceptable if not breaking scope
+ throw new IllegalAccessException("The field '" + fieldName +
+ "' was found, but it's scope prevents direct access by reflection");
+ }
+ field.setAccessible(true);
+ match = field;
+ break;
+
+ } catch (NoSuchFieldException ex) {
+ // ignore
+ }
+ // next superclass
+ acls = acls.getSuperclass();
+ }
+ // 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.
+ // check up the superclass hierarchy
+ Class[] ints = cls.getInterfaces();
+ for (int i = 0; i < ints.length; i++) {
+ // getField is fine here, because everything is public, and thus it works
+ try {
+ Field field = ints[i].getField(fieldName);
+ return field;
+
+ } catch (NoSuchFieldException ex) {
+ // ignore
+ }
+ }
+ if (match != null) {
+ return match;
+ }
+ throw new NoSuchFieldException("The field '" + fieldName + "' could not be found");
+
+ } catch (ReflectionException ex) {
+ throw ex;
+ } catch (LinkageError ex) {
+ throw new ReflectionException(ReflectionUtils.getThrowableText(
+ ex, "getting field", cls.getName(), null, fieldName), ex);
+ } catch (Exception ex) {
+ throw new ReflectionException(ReflectionUtils.getThrowableText(
+ ex, "getting field", cls.getName(), null, fieldName), ex);
+ }
+ }
+
+ // -------------------------------------------------------------------------
+
+ /**
+ * 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
+ * @throws ReflectionException if an error occurs during reflection
+ */
+ public static Field getFieldExact(Class cls, String fieldName) {
+ return getFieldExact(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 breakScope 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 ReflectionException if an error occurs during reflection
+ */
+ public static Field getFieldExact(Class cls, String fieldName, boolean breakScope) {
+ 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 (Modifier.isPublic(field.getModifiers()) == false) {
+ if (breakScope) {
+ field.setAccessible(true);
+ } else {
+ throw new IllegalAccessException("The field '" + fieldName + "' was found, but it's scope prevents direct access by reflection");
+ }
+ }
+ return field;
+
+ } catch (ReflectionException ex) {
+ throw ex;
+ } catch (LinkageError ex) {
+ throw new ReflectionException(ReflectionUtils.getThrowableText(
+ ex, "getting field", cls.getName(), null, fieldName), ex);
+ } catch (Exception ex) {
+ throw new ReflectionException(ReflectionUtils.getThrowableText(
+ ex, "getting field", cls.getName(), null, fieldName), ex);
+ }
+ }
+
+ // -------------------------------------------------------------------------
+
+ /**
+ * Gets a static Field value from a Field object.
+ *
+ * @param field the field to use
+ * @return the field value
+ * @throws IllegalArgumentException if the field is null or not static
+ * @throws ReflectionException if an error occurs during reflection
+ */
+ public static Object getStaticFieldValue(Field field) {
+ if (field == null) {
+ throw new IllegalArgumentException("The field must not be null");
+ }
+ if (Modifier.isStatic(field.getModifiers()) == false) {
+ throw new IllegalArgumentException("The field '" + field.getName() + "' is not static");
+ }
+ return getFieldValue(field, (Object) null, false);
+ }
+
+ /**
+ * Gets a static Field value from a Field object.
+ *
+ * @param field the field to use
+ * @param breakScope whether to break scope restrictions using the
+ * setAccessible
method. False will only match public methods.
+ * @return the field value
+ * @throws IllegalArgumentException if the field is null or not static
+ * @throws ReflectionException if an error occurs during reflection
+ */
+ public static Object getStaticFieldValue(Field field, boolean breakScope) {
+ if (field == null) {
+ throw new IllegalArgumentException("The field must not be null");
+ }
+ if (Modifier.isStatic(field.getModifiers()) == false) {
+ throw new IllegalArgumentException("The field '" + field.getName() + "' is not static");
+ }
+ return getFieldValue(field, (Object) null, breakScope);
+ }
+
+ /**
+ * Gets a Field value from a Field object.
+ *
+ * @param field the field to use
+ * @param object the object to call on, may be null for static fields
+ * @return the field value
+ * @throws IllegalArgumentException if the field is null
+ * @throws ReflectionException if an error occurs during reflection
+ */
+ public static Object getFieldValue(Field field, Object object) {
+ return getFieldValue(field, object, false);
+ }
+
+ /**
+ * Gets a Field value from a Field object.
+ *
+ * @param field the field to use
+ * @param object the object to call on, may be null for static fields
+ * @param breakScope whether to break scope restrictions using the
+ * setAccessible
method. False will only match public methods.
+ * @return the field value
+ * @throws IllegalArgumentException if the field is null
+ * @throws ReflectionException if an error occurs during reflection
+ */
+ public static Object getFieldValue(Field field, Object object, boolean breakScope) {
+ if (field == null) {
+ throw new IllegalArgumentException("The field must not be null");
+ }
+ try {
+ if (breakScope && Modifier.isPublic(field.getModifiers()) == false) {
+ field.setAccessible(true);
+ }
+ return field.get(object);
+
+ } catch (ReflectionException ex) {
+ throw ex;
+ } catch (LinkageError ex) {
+ throw new ReflectionException(ReflectionUtils.getThrowableText(
+ ex, "getting field value", field.getDeclaringClass().getName(), null, field.getName()), ex);
+ } catch (Exception ex) {
+ throw new ReflectionException(ReflectionUtils.getThrowableText(
+ ex, "getting field value", field.getDeclaringClass().getName(), null, field.getName()), ex);
+ }
+ }
+
+ // -------------------------------------------------------------------------
+
+ /**
+ * Gets a static Field value by name. The field must be public.
+ * 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 ReflectionException if an error occurs during reflection
+ */
+ public static Object getStaticFieldValue(Class cls, String fieldName) {
+ return getStaticFieldValue(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 breakScope 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 ReflectionException if an error occurs during reflection
+ */
+ public static Object getStaticFieldValue(Class cls, String fieldName, boolean breakScope) {
+ try {
+ Field field = getField(cls, fieldName, breakScope);
+ if (Modifier.isStatic(field.getModifiers()) == false) {
+ throw new NoSuchMethodException("The field '" + fieldName + "' is not static");
+ }
+ return getStaticFieldValue(field, breakScope);
+
+ } catch (ReflectionException ex) {
+ throw ex;
+ } catch (LinkageError ex) {
+ throw new ReflectionException(ReflectionUtils.getThrowableText(
+ ex, "getting field value", cls.getName(), null, fieldName), ex);
+ } catch (Exception ex) {
+ throw new ReflectionException(ReflectionUtils.getThrowableText(
+ ex, "getting field value", cls.getName(), null, fieldName), ex);
+ }
+ }
+
+ // -------------------------------------------------------------------------
+
+ /**
+ * 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 ReflectionException if an error occurs during reflection
+ */
+ public static Object getStaticFieldValueExact(Class cls, String fieldName) {
+ return getStaticFieldValueExact(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 breakScope 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 ReflectionException if an error occurs during reflection
+ */
+ public static Object getStaticFieldValueExact(Class cls, String fieldName, boolean breakScope) {
+ try {
+ Field field = getFieldExact(cls, fieldName, breakScope);
+ if (Modifier.isStatic(field.getModifiers()) == false) {
+ throw new NoSuchMethodException("The field '" + fieldName + "' is not static");
+ }
+ return getStaticFieldValue(field, breakScope);
+
+ } catch (ReflectionException ex) {
+ throw ex;
+ } catch (LinkageError ex) {
+ throw new ReflectionException(ReflectionUtils.getThrowableText(
+ ex, "getting field value", cls.getName(), null, fieldName), ex);
+ } catch (Exception ex) {
+ throw new ReflectionException(ReflectionUtils.getThrowableText(
+ ex, "getting field value", cls.getName(), null, fieldName), ex);
+ }
+ }
+
+ // -------------------------------------------------------------------------
+
+ /**
+ * Gets a Field value by name. The field must be public.
+ * Superclasses will be considered.
+ *
+ * @param object 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 ReflectionException if an error occurs during reflection
+ */
+ public static Object getFieldValue(Object object, String fieldName) {
+ return getFieldValue(object, fieldName, false);
+ }
+
+ /**
+ * Gets a Field value by name.
+ * Only the specified class will be considered.
+ *
+ * @param object the object to reflect, must not be null
+ * @param fieldName the field name to obtain
+ * @param breakScope 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 ReflectionException if an error occurs during reflection
+ */
+ public static Object getFieldValue(Object object, String fieldName, boolean breakScope) {
+ Field field = getField(object.getClass(), fieldName, breakScope);
+ return getFieldValue(field, object, breakScope);
+ }
+
+ // -------------------------------------------------------------------------
+
+ /**
+ * Gets a Field value by name. The field must be public.
+ * Only the class of the specified object will be considered.
+ *
+ * @param object 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 ReflectionException if an error occurs during reflection
+ */
+ public static Object getFieldValueExact(Object object, String fieldName) {
+ return getFieldValueExact(object, fieldName, false);
+ }
+
+ /**
+ * Gets a Field value by name.
+ * Only the class of the specified object will be considered.
+ *
+ * @param object the object to reflect, must not be null
+ * @param fieldName the field name to obtain
+ * @param breakScope 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 ReflectionException if an error occurs during reflection
+ */
+ public static Object getFieldValueExact(Object object, String fieldName, boolean breakScope) {
+ Field field = getFieldExact(object.getClass(), fieldName, breakScope);
+ return getFieldValue(field, object, breakScope);
+ }
+
+}
diff --git a/examples/cl2/src/java/org/apache/commons/lang/reflect/MethodUtils.java b/examples/cl2/src/java/org/apache/commons/lang/reflect/MethodUtils.java
new file mode 100644
index 00000000..44ec7429
--- /dev/null
+++ b/examples/cl2/src/java/org/apache/commons/lang/reflect/MethodUtils.java
@@ -0,0 +1,560 @@
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2002 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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
+ * .
+ */
+package org.apache.commons.lang.reflect;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+
+import org.apache.commons.lang.ArrayUtils;
+/**
+ * MethodUtils
contains utility methods for working for
+ * methods by reflection.
+ *
+ * The ability is provided to break the scoping restrictions coded by the
+ * programmer. This can break an implementation if used incorrectly. This
+ * facility should be used with care.
+ *
+ * @author Stephen Colebourne
+ * @author Based on code from BeanUtils
by: 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 Gary Gregory
+ * @version $Id: MethodUtils.java,v 1.11 2003/01/25 13:01:38 scolebourne Exp $
+ */
+public class MethodUtils {
+
+ public static final boolean debug = false;
+
+ /** An empty method array */
+ public static final Method[] EMPTY_METHOD_ARRAY = new Method[0];
+
+ /**
+ * MethodUtils instances should NOT be constructed in standard programming.
+ * Instead, the class should be used as MethodUtils.getMethod(cls, name)
.
+ * This constructor is public to permit tools that require a JavaBean instance
+ * to operate.
+ */
+ public MethodUtils() {
+ }
+
+ // -------------------------------------------------------------------------
+
+ /**
+ * Gets a Method by name. The method must be public and take no parameters.
+ * Superclasses will be considered.
+ *
+ * @param cls the class to reflect, must not be null
+ * @param methodName the field name to obtain
+ * @return the Method object
+ * @throws IllegalArgumentException if the class or method name is null
+ * @throws ReflectionException if an error occurs during reflection
+ */
+ public static Method getMethod(Class cls, String methodName) {
+ return getMethod(cls, methodName, ArrayUtils.EMPTY_CLASS_ARRAY, false);
+ }
+
+ /**
+ * Gets a Method by name. The method must be public.
+ * Superclasses will be considered.
+ *
+ * @param cls the class to reflect, must not be null
+ * @param methodName the field name to obtain
+ * @return the Method object
+ * @throws IllegalArgumentException if the class or method name is null
+ * @throws ReflectionException if an error occurs during reflection
+ */
+ public static Method getMethod(Class cls, String methodName, Class paramType) {
+ Class[] paramTypes = {paramType};
+ return getMethod(cls, methodName, paramTypes);
+ }
+
+ /**
+ * Gets a Method by name. The method must be public.
+ * Superclasses will be considered.
+ *
+ * @param cls the class to reflect, must not be null
+ * @param methodName the field name to obtain
+ * @return the Method object
+ * @throws IllegalArgumentException if the class or method name is null
+ * @throws ReflectionException if an error occurs during reflection
+ */
+ public static Method getMethod(Class cls, String methodName, Class[] paramTypes) {
+ return getMethod(cls, methodName, paramTypes, false);
+ }
+
+ /**
+ * Gets a Method by name.
+ * Superclasses will be considered.
+ *
+ * @param cls the class to reflect, must not be null
+ * @param methodName the method name to obtain
+ * @param breakScope whether to break scope restrictions using the
+ * setAccessible
method. False will only match public fields.
+ * @return the Method object
+ * @throws IllegalArgumentException if the class or field name is null
+ * @throws ReflectionException if an error occurs during reflection
+ */
+ public static Method getMethod(Class cls, String methodName, Class[] paramTypes, boolean breakScope) {
+ if (cls == null) {
+ throw new IllegalArgumentException("The class must not be null");
+ }
+ if (methodName == null) {
+ throw new IllegalArgumentException("The method name must not be null");
+ }
+ try {
+ if (breakScope) {
+ try {
+ // most common case, always do this for speed
+ return cls.getMethod(methodName, paramTypes); // must be public
+ } catch (NoSuchMethodException ex) {
+ // ignore
+ }
+ Class acls = cls;
+ while (acls != null) {
+ Method[] methods = acls.getDeclaredMethods();
+ for (int i = 0; i < methods.length; i++) {
+ if (methods[i].getName().equals(methodName) &&
+ ReflectionUtils.isCompatible(paramTypes, methods[i].getParameterTypes())) {
+ if (Modifier.isPublic(methods[i].getModifiers())) {
+ methods[i].setAccessible(true);
+ }
+ return methods[i];
+ }
+ }
+ acls = acls.getSuperclass(); // TODO interfaces
+ }
+ throw new NoSuchMethodException("The method '" + methodName + "' could not be found");
+ } else {
+ // apply workarounds
+ Method method = null;
+ try {
+
+ method = cls.getMethod(methodName, paramTypes);
+
+ } catch(NoSuchMethodException e) {
+ // swallow
+ }
+
+ if (method == null) {
+ // use the same as beanutils for the moment
+ Method[] compatibles = getCompatibleMethods(cls, methodName, paramTypes);
+ if (compatibles.length > 0) {
+ method = compatibles[0];
+ }
+ }
+ return getMethod(method);
+ }
+
+ } catch (ReflectionException ex) {
+ throw ex;
+ } catch (LinkageError ex) {
+ throw new ReflectionException(ReflectionUtils.getThrowableText(
+ ex, "getting method", cls.getName(), null, methodName), ex);
+ } catch (Exception ex) {
+ throw new ReflectionException(ReflectionUtils.getThrowableText(
+ ex, "getting method", cls.getName(), null, methodName), ex);
+ }
+ }
+
+ /**
+ *
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
+ */
+ public static Method getMethod(Method method) {
+
+ Method accessibleMethod = getAccessibleMethod(method);
+ if (accessibleMethod == null) {
+ try {
+ //
+ // XXX Default access superclass workaround
+ //
+ // When a public class has a default access superclass
+ // with public methods, these methods are accessible.
+ // Calling them from compiled code works fine.
+ //
+ // Unfortunately, using reflection to invoke these methods
+ // seems to (wrongly) to prevent access even when the method
+ // modifer is public.
+ //
+ // The following workaround solves the problem but will only
+ // work from sufficiently privilages code.
+ //
+ // Better workarounds would be greatfully accepted.
+ //
+ if (ReflectionUtils.isPublicScope(method)) {
+ method.setAccessible(true);
+ accessibleMethod = method;
+ }
+
+ } catch (SecurityException se) {
+ // log but continue just in case the method.invoke works anyway
+ log(
+ "Cannot setAccessible on method. Therefore cannot use jvm access bug workaround.",
+ se);
+ }
+ }
+ return (accessibleMethod);
+
+ }
+
+ // -------------------------------------------------------------------------
+
+ /**
+ * Invoke a named method whose parameter type matches the object type.
+ *
+ * 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 #invokeMethod(Object object,String methodName,Object [] args)}.
+ *
+ *
+ * @param objectToInvoke invoke method on this object, must not be null
+ * @param methodName get method with this name, must not be null
+ * @param arg use this argument, must not be null
+ *
+ * @throws ReflectionException if an error occurs during reflection
+ * @throws IllegalArgumentException if any parameter is null
+ */
+ public static Object invokeMethod(
+ Object objectToInvoke,
+ String methodName,
+ Object arg)
+ throws
+ ReflectionException {
+
+ if (objectToInvoke == null) {
+ throw new IllegalArgumentException("The object to invoke must not be null");
+ }
+ if (methodName == null) {
+ throw new IllegalArgumentException("The method name must not be null");
+ }
+ if (arg == null) {
+ throw new IllegalArgumentException("The argument must not be null");
+ }
+ Object[] args = {arg};
+ return invokeMethod(objectToInvoke, methodName, args);
+ }
+
+ /**
+ * Invoke a named method whose parameter type matches the object type.
+ *
+ * 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 #invokeMethod(Object object,String methodName,Object [] args,Class[] parameterTypes)}.
+ *
+ *
+ * @param objectToInvoke invoke method on this object, must not be null
+ * @param methodName get method with this name, must not be null
+ * @param args use these arguments - treat null as empty array
+ *
+ * @throws ReflectionException if an error occurs during reflection
+ * @throws IllegalArgumentException if the objectToInvoke, methodName or any argument is null
+ */
+ public static Object invokeMethod(
+ Object objectToInvoke,
+ String methodName,
+ Object[] args)
+ throws
+ ReflectionException {
+
+ if (objectToInvoke == null) {
+ throw new IllegalArgumentException("The object to invoke must not be null");
+ }
+ if (methodName == null) {
+ throw new IllegalArgumentException("The method name must not be null");
+ }
+ if (args == null) {
+ return invokeMethod(objectToInvoke, methodName, null, null);
+ } else {
+ int arguments = args.length;
+ Class parameterTypes [] = new Class[arguments];
+ for (int i = 0; i < arguments; i++) {
+ if (args[i] == null) {
+ throw new IllegalArgumentException("The arguments must not be null. Index " + i + " was null.");
+ }
+ parameterTypes[i] = args[i].getClass();
+ }
+ return invokeMethod(objectToInvoke, methodName, args, parameterTypes);
+ }
+ }
+
+ /**
+ * Invoke a named method whose parameter type matches the object type.
+ *
+ * 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 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
+ *
+ * @throws ReflectionException if an error occurs during reflection
+ */
+ public static Object invokeMethod(
+ Object object,
+ String methodName,
+ Object[] args,
+ Class[] parameterTypes)
+ throws
+ ReflectionException {
+
+ if (parameterTypes == null) {
+ parameterTypes = ArrayUtils.EMPTY_CLASS_ARRAY;
+ }
+ if (args == null) {
+ args = ArrayUtils.EMPTY_OBJECT_ARRAY;
+ }
+
+ Method method = getMethod(
+ object.getClass(),
+ methodName,
+ parameterTypes);
+ if (method == null)
+ throw new ReflectionException("No such accessible method: " +
+ methodName + "() on object: " + object.getClass().getName());
+
+ try {
+
+ return method.invoke(object, args);
+
+ } catch (IllegalAccessException ex) {
+ throw new ReflectionException(
+ ReflectionUtils.getThrowableText(
+ ex, "invoking method", object.getClass().getName(), parameterTypes, methodName)
+ , ex);
+
+ } catch (InvocationTargetException ex) {
+ throw new ReflectionException(
+ ReflectionUtils.getThrowableText(
+ ex, "invoking method", object.getClass().getName(), parameterTypes, methodName)
+ , ex);
+
+ }
+ }
+
+
+
+ // -------------------------------------------------------- Private Methods
+
+ private static Method getAccessibleMethod(Method method) {
+
+ // Make sure we have a method to check
+ if (method == null) {
+ return (null);
+ }
+
+ // If the requested method is not public we cannot call it
+ if (!Modifier.isPublic(method.getModifiers())) {
+ log("Method is not public");
+ return (null);
+ }
+
+ // If the declaring class is public, we are done
+ Class clazz = method.getDeclaringClass();
+ if (Modifier.isPublic(clazz.getModifiers())) {
+ log("Class is public");
+ return (method);
+ }
+
+ if (debug) {
+ log("Method is in non-public class " + clazz);
+ }
+
+ // Check the implemented interfaces and subinterfaces
+ method =
+ getAccessibleMethodFromInterfaceNest(clazz,
+ method.getName(),
+ method.getParameterTypes());
+
+ return (method);
+
+ }
+
+
+ /**
+ * 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 clazz 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
+ */
+ private static Method getAccessibleMethodFromInterfaceNest
+ (Class clazz, String methodName, Class parameterTypes[]) {
+ if (debug) {
+ log("Finding accessible method " + methodName + " from interface nest");
+ }
+ Method method = null;
+
+ // Search up the superclass chain
+ for (; clazz != null; clazz = clazz.getSuperclass()) {
+
+ // Check the implemented interfaces of the parent class
+ Class interfaces[] = clazz.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) {
+ ;
+ }
+ if (method != null)
+ break;
+
+ // Recursively check our parent interfaces
+ method =
+ getAccessibleMethodFromInterfaceNest(interfaces[i],
+ methodName,
+ parameterTypes);
+ if (method != null)
+ break;
+
+ }
+
+ }
+
+ // If we found a method return it
+ if (method != null) {
+ if (debug) {
+ log("Found method in class " + method.getDeclaringClass());
+ }
+ return (method);
+ }
+ // We did not find anything
+ return (null);
+
+ }
+
+ private static Method[] getCompatibleMethods(
+ Class clazz,
+ String methodName,
+ Class[] parameterTypes) {
+ // trace logging
+ if (debug) {
+ log("Matching name=" + methodName + " on " + clazz);
+ }
+
+ // search through all methods
+ Method[] methods = clazz.getMethods();
+ ArrayList compatibles = new ArrayList(methods.length);
+ for (int i = 0, size = methods.length; i < size ; i++) {
+ if (debug) {
+ log("Checking: " + methods[i]);
+ }
+ if (methods[i].getName().equals(methodName)) {
+ // log some trace information
+ if (debug) {
+ log("Found matching name:" + methods[i]);
+ }
+
+ // compare parameters
+ Class[] methodsParams = methods[i].getParameterTypes();
+ if (ReflectionUtils.isCompatible(parameterTypes, methodsParams)) {
+ // get accessible version of method
+ Method method = getMethod(methods[i]);
+ if (method != null) {
+ compatibles.add(method);
+ } else {
+ log("Couldn't find accessible method for: " + methods[i]);
+ }
+ }
+ }
+ }
+
+ return (Method[]) compatibles.toArray(new Method[compatibles.size()]);
+ }
+
+ private static void log(Object o) {
+ if (debug) {
+ System.err.println(o);
+ }
+ }
+
+ private static void log(Object o, Throwable t) {
+ if (debug) {
+ System.err.println(o);
+ System.err.println(t);
+
+ }
+ }
+}
diff --git a/examples/cl2/src/java/org/apache/commons/lang/reflect/ReflectionException.java b/examples/cl2/src/java/org/apache/commons/lang/reflect/ReflectionException.java
new file mode 100644
index 00000000..38c42803
--- /dev/null
+++ b/examples/cl2/src/java/org/apache/commons/lang/reflect/ReflectionException.java
@@ -0,0 +1,107 @@
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2002 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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
+ * .
+ */
+package org.apache.commons.lang.reflect;
+
+import org.apache.commons.lang.exception.NestableRuntimeException;
+/**
+ * Exception thrown when the Reflection process fails. The original
+ * error is wrapped within this one.
+ *
+ * @author Stephen Colebourne
+ * @version $Id: ReflectionException.java,v 1.1 2002/10/24 23:12:54 scolebourne Exp $
+ */
+public class ReflectionException extends NestableRuntimeException {
+
+ /**
+ * Constructs a new ReflectionException
without specified
+ * detail message.
+ */
+ public ReflectionException() {
+ super();
+ }
+
+ /**
+ * Constructs a new ReflectionException
with specified
+ * detail message.
+ *
+ * @param msg The error message.
+ */
+ public ReflectionException(String msg) {
+ super(msg);
+ }
+
+ /**
+ * Constructs a new ReflectionException
with specified
+ * nested Throwable
.
+ *
+ * @param cause The exception or error that caused this exception
+ * to be thrown.
+ */
+ public ReflectionException(Throwable cause) {
+ super(cause);
+ }
+
+ /**
+ * Constructs a new ReflectionException
with specified
+ * detail message and nested Throwable
.
+ *
+ * @param msg The error message.
+ * @param cause The exception or error that caused this exception
+ * to be thrown.
+ */
+ public ReflectionException(String msg, Throwable cause) {
+ super(msg, cause);
+ }
+
+}
diff --git a/examples/cl2/src/java/org/apache/commons/lang/reflect/ReflectionUtils.java b/examples/cl2/src/java/org/apache/commons/lang/reflect/ReflectionUtils.java
new file mode 100644
index 00000000..47d31add
--- /dev/null
+++ b/examples/cl2/src/java/org/apache/commons/lang/reflect/ReflectionUtils.java
@@ -0,0 +1,412 @@
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2002 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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
+ * .
+ */
+package org.apache.commons.lang.reflect;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Member;
+import java.lang.reflect.Modifier;
+
+import org.apache.commons.lang.ArrayUtils;
+import org.apache.commons.lang.ClassUtils;
+import org.apache.commons.lang.StringUtils;
+/**
+ * ReflectionUtils
contains utility methods for working for
+ * reflection.
+ *
+ * @author Stephen Colebourne
+ * @version $Id: ReflectionUtils.java,v 1.6 2002/12/25 22:03:00 scolebourne Exp $
+ */
+public class ReflectionUtils {
+
+ /**
+ * ReflectionUtils instances should NOT be constructed in standard programming.
+ * Instead, the class should be used as ReflectionUtils.getShortClassName(obj)
.
+ * This constructor is public to permit tools that require a JavaBean instance
+ * to operate.
+ */
+ public ReflectionUtils() {
+ }
+
+ // -------------------------------------------------------------------------
+
+ /**
+ * Tests whether the specified field or method is
+ * static
.
+ *
+ * @param member the member to test, must not be null
+ * @return true if the member is static
+ */
+ public static boolean isStatic(Member member) {
+ if (member == null) {
+ throw new IllegalArgumentException("The member must not be null");
+ }
+ return Modifier.isStatic(member.getModifiers());
+ }
+
+ /**
+ * Tests whether the specified field or method is
+ * final
.
+ *
+ * @param member the member to test, must not be null
+ * @return true if the member is final
+ */
+ public static boolean isFinal(Member member) {
+ if (member == null) {
+ throw new IllegalArgumentException("The member must not be null");
+ }
+ return Modifier.isFinal(member.getModifiers());
+ }
+
+ /**
+ * Tests whether the specified field, method or constructor is
+ * public
.
+ *
+ * @param member the member to test, must not be null
+ * @return true if the member is public scoped
+ */
+ public static boolean isPublicScope(Member member) {
+ if (member == null) {
+ throw new IllegalArgumentException("The member must not be null");
+ }
+ return Modifier.isPublic(member.getModifiers());
+ }
+
+ /**
+ * Tests whether the specified field, method or constructor is
+ * protected
.
+ *
+ * @param member the member to test, must not be null
+ * @return true if the member is protected scoped
+ */
+ public static boolean isProtectedScope(Member member) {
+ if (member == null) {
+ throw new IllegalArgumentException("The member must not be null");
+ }
+ return Modifier.isProtected(member.getModifiers());
+ }
+
+ /**
+ * Tests whether the specified field, method or constructor is
+ * package (default) scoped.
+ *
+ * @param member the member to test, must not be null
+ * @return true if the member is package scoped
+ */
+ public static boolean isPackageScope(Member member) {
+ return !(isPublicScope(member) || isProtectedScope(member) || isPrivateScope(member));
+ }
+
+ /**
+ * Tests whether the specified field, method or constructor is
+ * private
.
+ *
+ * @param member the member to test, must not be null
+ * @return true if the member is private scoped
+ */
+ public static boolean isPrivateScope(Member member) {
+ if (member == null) {
+ throw new IllegalArgumentException("The member must not be null");
+ }
+ return Modifier.isPrivate(member.getModifiers());
+ }
+
+ // -------------------------------------------------------------------------
+
+ /**
+ * Gets a class object for the specified string.
+ *
+ * @param className fully qualified class name to find, must not be empty
+ * @return Class object for class
+ * @throws ReflectionException if an error occurs during reflection
+ * @throws IllegalArgumentException if the class name is empty
+ */
+ public static Class getClass(String className) throws ReflectionException {
+ if (StringUtils.isEmpty(className)) {
+ throw new IllegalArgumentException("The class name must not be null");
+ }
+ try {
+ return Class.forName(className);
+
+ } catch (LinkageError ex) {
+ throw new ReflectionException(getThrowableText(ex, "getting class", className, null, null), ex);
+ } catch (Exception ex) {
+ throw new ReflectionException(getThrowableText(ex, "getting class", className, null, null), ex);
+ }
+ }
+
+ // -------------------------------------------------------------------------
+
+ /**
+ * Checks if the requested Class array is compatible with the specified
+ * parameter array.
+ * Primitive classes are handled correctly .
+ *
+ * In other words, a boolean
Class will be converted to
+ * a Boolean
Class and so on.
+ *
+ * This method also handles widening for primitives as given in section 5.1.2 of the
+ * The Java Language Specification.
+ *
+ * @param requestedTypes the class array requested
+ * @param paramTypes the actual class array for the method
+ * @return true if the parameters are compatible
+ */
+ public static boolean isCompatible(Class[] requestedTypes, Class[] paramTypes) {
+ if (ArrayUtils.isSameLength(requestedTypes, paramTypes) == false) {
+ return false;
+ }
+ if (requestedTypes == null) {
+ requestedTypes = ArrayUtils.EMPTY_CLASS_ARRAY;
+ }
+ if (paramTypes == null) {
+ paramTypes = ArrayUtils.EMPTY_CLASS_ARRAY;
+ }
+ for (int i = 0; i < requestedTypes.length; i++) {
+ if (isCompatible(requestedTypes[i], paramTypes[i]) == false) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+
+ /**
+ *
Determine whether a type can be used as a parameter in a method invocation.
+ * This method handles primitive conversions correctly.
+ *
+ * This method also handles widening for primitives as given in section 5.1.2 of the
+ * The Java Language Specification.
+ *
+ * @param parameterType the type of parameter accepted by the method
+ * @param requestedType the type of parameter being requested
+ *
+ * @return true if the assignement is compatible.
+ */
+ public static boolean isCompatible(Class requestedType, Class parameterType) {
+ // try plain assignment
+ if (ClassUtils.isAssignable(requestedType, parameterType)) {
+ return true;
+ }
+
+ if (parameterType.isPrimitive()) {
+ // also, this method does *not* do widening - you must specify exactly
+ // is this the right behaviour?
+ if (boolean.class.equals(parameterType)) {
+ return Boolean.class.equals(requestedType);
+ }
+
+ if (byte.class.equals(parameterType)) {
+ return Byte.class.equals(requestedType);
+ }
+
+ if (short.class.equals(parameterType)) {
+ return (Short.class.equals(requestedType)
+ || Byte.class.equals(requestedType));
+ }
+
+ if (char.class.equals(parameterType)) {
+ return Character.class.equals(requestedType);
+ }
+
+ if (int.class.equals(parameterType)) {
+ return (Integer.class.equals(requestedType)
+ || Character.class.equals(requestedType)
+ || Short.class.equals(requestedType)
+ || Byte.class.equals(requestedType));
+ }
+ if (long.class.equals(parameterType)) {
+ return (Long.class.equals(requestedType)
+ || Integer.class.equals(requestedType)
+ || Character.class.equals(requestedType)
+ || Short.class.equals(requestedType)
+ || Byte.class.equals(requestedType));
+ }
+
+ if (float.class.equals(parameterType)) {
+ return (Float.class.equals(requestedType)
+ || Long.class.equals(requestedType)
+ || Integer.class.equals(requestedType)
+ || Character.class.equals(requestedType)
+ || Short.class.equals(requestedType)
+ || Byte.class.equals(requestedType));
+ }
+
+ if (double.class.equals(parameterType)) {
+ return (Double.class.equals(requestedType)
+ || Float.class.equals(requestedType)
+ || Long.class.equals(requestedType)
+ || Integer.class.equals(requestedType)
+ || Character.class.equals(requestedType)
+ || Short.class.equals(requestedType)
+ || Byte.class.equals(requestedType));
+ }
+ }
+
+ return false;
+ }
+
+
+ /**
+ * Converts a primitive class to its matching object class.
+ * Non-primitive classes are unaffected.
+ *
+ * In other words, a boolean
Class will be converted to
+ * a Boolean
Class and so on.
+ *
+ * @param cls the class to convert
+ * @return converted class
+ * @throws IllegalArgumentException if the class is null
+ */
+ public static Class convertPrimitiveClass(Class cls) {
+ if (cls == null) {
+ throw new IllegalArgumentException("The class must not be null");
+ }
+ if (cls.isPrimitive()) {
+ if (Integer.TYPE.equals(cls)) {
+ return Integer.class;
+ } else if (Long.TYPE.equals(cls)) {
+ return Long.class;
+ } else if (Boolean.TYPE.equals(cls)) {
+ return Boolean.class;
+ } else if (Double.TYPE.equals(cls)) {
+ return Double.class;
+ } else if (Float.TYPE.equals(cls)) {
+ return Float.class;
+ } else if (Character.TYPE.equals(cls)) {
+ return Character.class;
+ } else if (Short.TYPE.equals(cls)) {
+ return Short.class;
+ } else if (Byte.TYPE.equals(cls)) {
+ return Byte.class;
+ }
+ }
+ return cls;
+ }
+
+ // -------------------------------------------------------------------------
+
+ /**
+ * Produces nicely formatted informational error messages for reflection errors.
+ *
+ * @param th the throwable
+ * @param desc the short description of the action, such as 'getting field'
+ * @param className the class name being used
+ * @param types the parameter types
+ * @param memberName the name of the field or method
+ * @return a suitable error message
+ */
+ public static String getThrowableText(Throwable th, String desc, String className, Class[] types, String memberName) {
+ String message = null;
+ try {
+ throw th;
+
+ } catch (NoSuchMethodException ex) {
+ message = "the method does not exist";
+ } catch (NoSuchFieldException ex) {
+ message = "the field does not exist";
+ } catch (ClassNotFoundException ex) {
+ message = "the class could not be found in the classpath";
+ } catch (InvocationTargetException ex) {
+ message = "the method threw an exception";
+ } catch (InstantiationException ex) {
+ message = "the class is abstract/interface/array/primitive";
+ } catch (IllegalAccessException ex) {
+ message = "the method was not public/accessible";
+ } catch (IllegalArgumentException ex) {
+ message = "the parameters did not match those expected";
+ } catch (SecurityException ex) {
+ message = "the security manager prevents reflection";
+ } catch (ExceptionInInitializerError ex) {
+ message = "the class initialization for static variables threw an exception";
+ } catch (ClassCircularityError ex) {
+ message = "a circularity has been detected while initializing a class";
+ } catch (ClassFormatError ex) {
+ message = "the class file is malformed or otherwise cannot be interpreted as a class";
+ } catch (IncompatibleClassChangeError ex) {
+ message = "the method references another class that has changed incompatibly since compile time";
+ } catch (UnsatisfiedLinkError ex) {
+ message = "no implementation found for a native method";
+ } catch (VerifyError ex) {
+ message = "the class file contains an internal inconsistency or security problem";
+ } catch (NoClassDefFoundError ex) {
+ message = "the class references another class that was present at compile time but is no longer available";
+ } catch (LinkageError ex) {
+ message = "the class references another class that has changed incompatibly since compile time";
+ } catch (Throwable ex) {
+ message = null;
+ }
+ StringBuffer buf = new StringBuffer();
+ buf.append(ClassUtils.getShortClassName(th, ""));
+ buf.append(" while ");
+ buf.append(desc);
+ buf.append(" on Class '");
+ buf.append(className);
+ buf.append("'");
+ if (types != null) {
+ buf.append(" for types ");
+ buf.append(ArrayUtils.toString(types));
+ }
+ if (memberName != null) {
+ buf.append(" for method '");
+ buf.append(memberName);
+ buf.append("'");
+ }
+ if (message != null) {
+ buf.append(" - ");
+ buf.append(message);
+ }
+ return buf.toString();
+ }
+
+}
diff --git a/examples/cl2/src/java/org/apache/commons/lang/reflect/package.html b/examples/cl2/src/java/org/apache/commons/lang/reflect/package.html
new file mode 100644
index 00000000..82c82742
--- /dev/null
+++ b/examples/cl2/src/java/org/apache/commons/lang/reflect/package.html
@@ -0,0 +1,24 @@
+
+
+
+
+Assists in reflection with the aim to create a simple, clean and clear API which can be built upon on by more
+sophisticated introspection schemes as well as fixes for bugs found in various
+Java implementations.
+
+Accessibility Rules
+These determine which methods are in scope
+
+Java Language Specification Rules
+The Java Language Specification Rules are those that are given in the
+Java Language Specification as applied by the compiler.
+The aim of those methods who contract is given as the Java Language Specification
+is to behave in an identical manner to compiled code.
+In other words, any code that would compile should be found by reflection
+ and any code that would not should not
+Java 1.3 And Below
+This aim is actually easier said than done for some java versions.
+The reflection implementation is slow and buggy.
+If you are using one of these easier java versions, then you will probably find our code
+more reliable than the standard java implementation.
+
diff --git a/examples/cl2/src/java/org/apache/commons/lang/time/DateFormatUtils.java b/examples/cl2/src/java/org/apache/commons/lang/time/DateFormatUtils.java
new file mode 100644
index 00000000..4e74a147
--- /dev/null
+++ b/examples/cl2/src/java/org/apache/commons/lang/time/DateFormatUtils.java
@@ -0,0 +1,297 @@
+/* ====================================================================
+ * 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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
+ * .
+ */
+package org.apache.commons.lang.time;
+
+import java.util.Date;
+import java.util.Locale;
+import java.util.TimeZone;
+
+/**
+ * Date and time formatting utilites and constants.
+ *
+ * Formatting is performed using the
+ * {@link org.apache.commons.lang.time.FastDateFormat} class.
+ *
+ * @author Apache Ant - DateUtils
+ * @author Stephane Bailliez
+ * @author Stefan Bodewig
+ * @author Stephen Colebourne
+ * @since 2.0
+ * @version $Id: DateFormatUtils.java,v 1.2 2003/06/09 21:22:31 scolebourne Exp $
+ */
+public class DateFormatUtils {
+
+ /**
+ * ISO8601 formatter for date-time witout timezone.
+ * The format used is yyyy-MM-dd'T'HH:mm:ss.
+ */
+ public static final FastDateFormat ISO_DATETIME_FORMAT
+ = FastDateFormat.getInstance("yyyy-MM-dd'T'HH:mm:ss");
+
+ /**
+ * ISO8601 formatter for date-time with timezone.
+ * The format used is yyyy-MM-dd'T'HH:mm:ssZZ.
+ */
+ public static final FastDateFormat ISO_DATETIME_TIMEZONE_FORMAT
+ = FastDateFormat.getInstance("yyyy-MM-dd'T'HH:mm:ssZZ");
+
+ /**
+ * ISO8601 formatter for date without timezone.
+ * The format used is yyyy-MM-dd.
+ */
+ public static final FastDateFormat ISO_DATE_FORMAT
+ = FastDateFormat.getInstance("yyyy-MM-dd");
+
+ /**
+ * ISO8601-like formatter for date with timezone.
+ * The format used is yyyy-MM-ddZZ.
+ * This pattern does not comply with the formal ISO8601 specification
+ * as the standard does not allow a timezone without a time.
+ */
+ public static final FastDateFormat ISO_DATE_TIMEZONE_FORMAT
+ = FastDateFormat.getInstance("yyyy-MM-ddZZ");
+
+ /**
+ * ISO8601 formatter for time without timezone.
+ * The format used is 'T'HH:mm:ss.
+ */
+ public static final FastDateFormat ISO_TIME_FORMAT
+ = FastDateFormat.getInstance("'T'HH:mm:ss");
+
+ /**
+ * ISO8601 formatter for time with timezone.
+ * The format used is 'T'HH:mm:ssZZ.
+ */
+ public static final FastDateFormat ISO_TIME_TIMEZONE_FORMAT
+ = FastDateFormat.getInstance("'T'HH:mm:ssZZ");
+
+ /**
+ * ISO8601-like formatter for time without timezone.
+ * The format used is HH:mm:ss.
+ * This pattern does not comply with the formal ISO8601 specification
+ * as the standard requires the 'T' prefix for times.
+ */
+ public static final FastDateFormat ISO_TIME_NO_T_FORMAT
+ = FastDateFormat.getInstance("HH:mm:ss");
+
+ /**
+ * ISO8601-like formatter for time with timezone.
+ * The format used is HH:mm:ssZZ.
+ * This pattern does not comply with the formal ISO8601 specification
+ * as the standard requires the 'T' prefix for times.
+ */
+ public static final FastDateFormat ISO_TIME_NO_T_TIMEZONE_FORMAT
+ = FastDateFormat.getInstance("HH:mm:ssZZ");
+
+ /**
+ * SMTP (and probably other) date headers.
+ * The format used is EEE, dd MMM yyyy HH:mm:ss Z in US locale.
+ */
+ public static final FastDateFormat SMTP_DATETIME_FORMAT
+ = FastDateFormat.getInstance("EEE, dd MMM yyyy HH:mm:ss Z", Locale.US);
+
+ //-----------------------------------------------------------------------
+ /**
+ * DateFormatUtils instances should NOT be constructed in standard programming.
+ *
+ * This constructor is public to permit tools that require a JavaBean instance
+ * to operate.
+ */
+ public DateFormatUtils() {
+ }
+
+ /**
+ * Format a date/time into a specific pattern using the UTC timezone.
+ *
+ * @param millis the date to format expressed in milliseconds
+ * @param pattern the pattern to use to format the date
+ * @return the formatted date
+ */
+ public static String formatUTC(long millis, String pattern) {
+ return format(new Date(millis), pattern, DateUtils.UTC_TIMEZONE, null);
+ }
+
+ /**
+ * Format a date/time into a specific pattern using the UTC timezone.
+ *
+ * @param date the date to format
+ * @param pattern the pattern to use to format the date
+ * @return the formatted date
+ */
+ public static String formatUTC(Date date, String pattern) {
+ return format(date, pattern, DateUtils.UTC_TIMEZONE, null);
+ }
+
+ /**
+ * Format a date/time into a specific pattern using the UTC timezone.
+ *
+ * @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
+ * @return the formatted date
+ */
+ public static String formatUTC(long millis, String pattern, Locale locale) {
+ return format(new Date(millis), pattern, DateUtils.UTC_TIMEZONE, locale);
+ }
+
+ /**
+ * Format a date/time into a specific pattern using the UTC timezone.
+ *
+ * @param date the date to format
+ * @param pattern the pattern to use to format the date
+ * @param locale the locale to use, may be null
+ * @return the formatted date
+ */
+ public static String formatUTC(Date date, String pattern, Locale locale) {
+ return format(date, pattern, DateUtils.UTC_TIMEZONE, locale);
+ }
+
+ /**
+ * Format 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
+ * @return the formatted date
+ */
+ public static String format(long millis, String pattern) {
+ return format(new Date(millis), pattern, null, null);
+ }
+
+ /**
+ * Format a date/time into a specific pattern.
+ *
+ * @param date the date to format
+ * @param pattern the pattern to use to format the date
+ * @return the formatted date
+ */
+ public static String format(Date date, String pattern) {
+ return format(date, pattern, null, null);
+ }
+
+ /**
+ * Format a date/time into a specific pattern in a timezone.
+ *
+ * @param millis the time expressed in milliseconds
+ * @param pattern the pattern to use to format the date
+ * @param timeZone the timezone to use, may be null
+ * @return the formatted date
+ */
+ public static String format(long millis, String pattern, TimeZone timeZone) {
+ return format(new Date(millis), pattern, timeZone, null);
+ }
+
+ /**
+ * Format a date/time into a specific pattern in a timezone.
+ *
+ * @param date the date to format
+ * @param pattern the pattern to use to format the date
+ * @param timeZone the timezone to use, may be null
+ * @return the formatted date
+ */
+ public static String format(Date date, String pattern, TimeZone timeZone) {
+ return format(date, pattern, timeZone, null);
+ }
+
+ /**
+ * Format 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
+ * @return the formatted date
+ */
+ public static String format(long millis, String pattern, Locale locale) {
+ return format(new Date(millis), pattern, null, locale);
+ }
+
+ /**
+ * Format 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
+ * @param locale the locale to use, may be null
+ * @return the formatted date
+ */
+ public static String format(Date date, String pattern, Locale locale) {
+ return format(date, pattern, null, locale);
+ }
+
+ /**
+ * Format a date/time into a specific pattern in a timezone and locale.
+ *
+ * @param millis the date to format expressed in milliseconds
+ * @param pattern the pattern to use to format the date
+ * @param timeZone the timezone to use, may be null
+ * @param locale the locale to use, may be null
+ * @return the formatted date
+ */
+ public static String format(long millis, String pattern, TimeZone timeZone, Locale locale) {
+ return format(new Date(millis), pattern, timeZone, locale);
+ }
+
+ /**
+ * Format a date/time into a specific pattern in a timezone and locale.
+ *
+ * @param date the date to format
+ * @param pattern the pattern to use to format the date
+ * @param timeZone the timezone to use, may be null
+ * @param locale the locale to use, may be null
+ * @return the formatted date
+ */
+ public static String format(Date date, String pattern, TimeZone timeZone, Locale locale) {
+ FastDateFormat df = FastDateFormat.getInstance(pattern, timeZone, locale);
+ return df.format(date);
+ }
+
+}
diff --git a/examples/cl2/src/java/org/apache/commons/lang/time/DateUtils.java b/examples/cl2/src/java/org/apache/commons/lang/time/DateUtils.java
new file mode 100644
index 00000000..89230dec
--- /dev/null
+++ b/examples/cl2/src/java/org/apache/commons/lang/time/DateUtils.java
@@ -0,0 +1,543 @@
+/* ====================================================================
+ * 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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
+ * .
+ */
+package org.apache.commons.lang.time;
+
+import java.text.DateFormat;
+import java.text.DateFormatSymbols;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.GregorianCalendar;
+import java.util.Iterator;
+import java.util.Locale;
+import java.util.NoSuchElementException;
+import java.util.TimeZone;
+
+/**
+ * A suite of utilities surrounding the use of the Calendar and Date object.
+ *
+ * @author Serge Knystautas
+ * @author Stephen Colebourne
+ * @since 2.0
+ * @version $Id: DateUtils.java,v 1.3 2003/06/08 23:14:23 scolebourne Exp $
+ */
+public class DateUtils {
+
+ /**
+ * The UTC timezone (often referred to as GMT).
+ */
+ public static final TimeZone UTC_TIMEZONE = TimeZone.getTimeZone("GMT");
+ /**
+ * Number of milliseconds in a standard second.
+ */
+ public static final int MILLIS_IN_SECOND = 1000;
+ /**
+ * Number of milliseconds in a standard minute.
+ */
+ public static final int MILLIS_IN_MINUTE = 60 * 1000;
+ /**
+ * Number of milliseconds in a standard hour.
+ */
+ public static final int MILLIS_IN_HOUR = 60 * 60 * 1000;
+ /**
+ * Number of milliseconds in a standard day.
+ */
+ public static final int MILLIS_IN_DAY = 24 * 60 * 60 * 1000;
+
+ /**
+ * This is half a month, so this represents whether a date is in the top
+ * or bottom half of the month.
+ */
+ public final static int SEMI_MONTH = 1001;
+
+ private static final int[][] fields = {
+ {Calendar.MILLISECOND},
+ {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.MONTH, DateUtils.SEMI_MONTH},
+ {Calendar.YEAR},
+ {Calendar.ERA}};
+
+ private static DateFormat[] dateFormats = {
+ //3/31/92 10:00:07 PST
+ new SimpleDateFormat("M/dd/yy h:mm:ss z"),
+ //January 23, 1987 10:05pm
+ new SimpleDateFormat("MMM d, yyyy h:mm a"),
+ //22:00 GMT
+ new SimpleDateFormat("h:mm z")};
+
+ /**
+ * A week range, starting on Sunday.
+ */
+ public final static int RANGE_WEEK_SUNDAY = 1;
+
+ /**
+ * A week range, starting on Monday.
+ */
+ public final static int RANGE_WEEK_MONDAY = 2;
+
+ /**
+ * A week range, starting on the day focused.
+ */
+ public final static int RANGE_WEEK_RELATIVE = 3;
+
+ /**
+ * A week range, centered around the day focused.
+ */
+ public final static int RANGE_WEEK_CENTER = 4;
+
+ /**
+ * A month range, the week starting on Sunday.
+ */
+ public final static int RANGE_MONTH_SUNDAY = 5;
+
+ /**
+ * A month range, the week starting on Monday.
+ */
+ public final static int RANGE_MONTH_MONDAY = 6;
+
+ /**
+ * See the other round method. Works with a Date object.
+ */
+ public static Date round(Date val, int field) {
+ GregorianCalendar gval = new GregorianCalendar();
+ gval.setTime(val);
+ modify(gval, field, true);
+ return gval.getTime();
+ }
+
+ /**
+ * Round 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 this was passed with HOUR, it would return 28 Mar
+ * 2002 14:00:00.000. If this was passed with MONTH, it would return
+ * 1 April 2002 0:00:00.000.
+ */
+ public static Calendar round(Calendar val, int field) {
+ Calendar rounded = (Calendar) val.clone();
+ modify(rounded, field, true);
+ return rounded;
+ }
+
+ /**
+ * See the other round method. Works with an Object, trying to
+ * use it as either a Date or Calendar.
+ */
+ public static Date round(Object val, int field) {
+ if (val instanceof Date) {
+ return round((Date) val, field);
+ } else if (val instanceof Calendar) {
+ return round((Calendar) val, field).getTime();
+ } else {
+ throw new ClassCastException("Could not round " + val);
+ }
+ }
+
+ /**
+ * See the other trunc method. Works with a Date.
+ */
+ public static Date trunc(Date val, int field) {
+ GregorianCalendar gval = new GregorianCalendar();
+ gval.setTime(val);
+ modify(gval, field, false);
+ return gval.getTime();
+ }
+
+ /**
+ * Truncate 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.
+ */
+ public static Calendar trunc(Calendar val, int field) {
+ Calendar truncated = (Calendar) val.clone();
+ modify(truncated, field, false);
+ return truncated;
+ }
+
+ /**
+ * See the other trunc method. Works with an Object, trying to
+ * use it as either a Date or Calendar.
+ */
+ public static Date trunc(Object val, int field) {
+ if (val instanceof Date) {
+ return trunc((Date) val, field);
+ } else if (val instanceof Calendar) {
+ return trunc((Calendar) val, field).getTime();
+ } else {
+ throw new ClassCastException("Could not trunc " + val);
+ }
+ }
+
+ private static void modify(Calendar val, int field, boolean round) {
+ 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 (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
+ // we subtract 15 days and add 1 month
+ if (val.get(Calendar.DATE) == 1) {
+ val.add(Calendar.DATE, 15);
+ } else {
+ val.add(Calendar.DATE, -15);
+ val.add(Calendar.MONTH, 1);
+ }
+ } else {
+ //We need at add one to this field since the
+ // last number causes us to round up
+ val.add(fields[i][0], 1);
+ }
+ }
+ return;
+ }
+ }
+ //We have various fields that are not easy roundings
+ int offset = 0;
+ boolean offsetSet = false;
+ //These are special types of fields that require different rounding rules
+ switch (field) {
+ case DateUtils.SEMI_MONTH:
+ if (fields[i][0] == Calendar.DATE) {
+ //If we're going to drop the DATE field's value,
+ // we want to do this our own way.
+ //We need to subtrace 1 since the date has a minimum of 1
+ offset = val.get(Calendar.DATE) - 1;
+ //If we're above 15 days adjustment, that means we're in the
+ // bottom half of the month and should stay accordingly.
+ if (offset >= 15) {
+ offset -= 15;
+ }
+ //Record whether we're in the top or bottom half of that range
+ roundUp = offset > 7;
+ offsetSet = true;
+ }
+ break;
+ case Calendar.AM_PM:
+ if (fields[i][0] == Calendar.HOUR) {
+ //If we're going to drop the HOUR field's value,
+ // we want to do this our own way.
+ offset = val.get(Calendar.HOUR);
+ if (offset >= 12) {
+ offset -= 12;
+ }
+ roundUp = offset > 6;
+ offsetSet = true;
+ }
+ break;
+ }
+ if (!offsetSet) {
+ int min = val.getActualMinimum(fields[i][0]);
+ int max = val.getActualMaximum(fields[i][0]);
+ //Calculate the offset from the minimum allowed value
+ offset = val.get(fields[i][0]) - min;
+ //Set roundUp if this is more than half way between the minimum and maximum
+ roundUp = offset > ((max - min) / 2);
+ }
+ //We need to remove this field
+ val.add(fields[i][0], -offset);
+ }
+ throw new RuntimeException("We do not support that field.");
+
+ }
+
+ /**
+ * Parses strings the way that CVS supports it (very human readable).
+ */
+ public static Calendar parse(String original) {
+ return parse(original, Locale.getDefault());
+ }
+
+ /**
+ * Parses strings the way that CVS supports it (very human readable).
+ */
+ public static Calendar parse(String original, Locale locale) {
+ //Get the symbol names
+ DateFormatSymbols symbols = new DateFormatSymbols(locale);
+
+ //Prep the string to parse
+ String value = original.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 RuntimeException("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 RuntimeException("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;
+ }
+ } 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(original);
+ Calendar cal = Calendar.getInstance();
+ cal.setTime(datetime);
+ return cal;
+ } catch (ParseException pe) {
+ //we ignore this and just keep trying
+ }
+ }
+
+ throw new RuntimeException("Unable to parse '" + original + "'.");
+ }
+
+ /**
+ * This constructs an Iterator that will start and stop over a date
+ * range based on the focused date and the 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.
+ */
+ public static Iterator getCalendarIterator(Calendar focus, int rangeStyle) {
+ Calendar start = null;
+ Calendar end = null;
+ int startCutoff = Calendar.SUNDAY;
+ int endCutoff = Calendar.SATURDAY;
+ switch (rangeStyle) {
+ case RANGE_MONTH_SUNDAY:
+ case RANGE_MONTH_MONDAY:
+ //Set start to the first of the month
+ start = trunc(focus, Calendar.MONTH);
+ //Set end to the last of the month
+ end = (Calendar) start.clone();
+ end.add(Calendar.MONTH, 1);
+ end.add(Calendar.DATE, -1);
+ //Loop start back to the previous sunday or monday
+ if (rangeStyle == RANGE_MONTH_MONDAY) {
+ startCutoff = Calendar.MONDAY;
+ endCutoff = Calendar.SUNDAY;
+ }
+ break;
+ case RANGE_WEEK_SUNDAY:
+ case RANGE_WEEK_MONDAY:
+ case RANGE_WEEK_RELATIVE:
+ case RANGE_WEEK_CENTER:
+ //Set start and end to the current date
+ start = trunc(focus, Calendar.DATE);
+ end = trunc(focus, Calendar.DATE);
+ switch (rangeStyle) {
+ case RANGE_WEEK_SUNDAY:
+ //already set by default
+ break;
+ case RANGE_WEEK_MONDAY:
+ startCutoff = Calendar.MONDAY;
+ endCutoff = Calendar.SUNDAY;
+ break;
+ case RANGE_WEEK_RELATIVE:
+ startCutoff = focus.get(Calendar.DAY_OF_WEEK);
+ endCutoff = startCutoff - 1;
+ break;
+ case RANGE_WEEK_CENTER:
+ startCutoff = focus.get(Calendar.DAY_OF_WEEK) - 3;
+ endCutoff = focus.get(Calendar.DAY_OF_WEEK) + 3;
+ break;
+ }
+ break;
+ default:
+ throw new RuntimeException("The range style " + rangeStyle + " is not valid.");
+ }
+ if (startCutoff < Calendar.SUNDAY) {
+ startCutoff += 7;
+ }
+ if (startCutoff > Calendar.SATURDAY) {
+ startCutoff -= 7;
+ }
+ if (endCutoff < Calendar.SUNDAY) {
+ endCutoff += 7;
+ }
+ if (endCutoff > Calendar.SATURDAY) {
+ endCutoff -= 7;
+ }
+ while (start.get(Calendar.DAY_OF_WEEK) != startCutoff) {
+ start.add(Calendar.DATE, -1);
+ }
+ while (end.get(Calendar.DAY_OF_WEEK) != endCutoff) {
+ end.add(Calendar.DATE, 1);
+ }
+ final Calendar startFinal = start;
+ final Calendar endFinal = end;
+ Iterator it = new Iterator() {
+ Calendar spot = null;
+ {
+ spot = startFinal;
+ spot.add(Calendar.DATE, -1);
+ }
+
+ public boolean hasNext() {
+ return spot.before(endFinal);
+ }
+
+ public Object next() {
+ if (spot.equals(endFinal)) {
+ throw new NoSuchElementException();
+ }
+ spot.add(Calendar.DATE, 1);
+ return spot.clone();
+ }
+
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+ };
+ return it;
+ }
+
+ /**
+ * See the other getCalendarIterator. Works with a Date.
+ */
+ public static Iterator getCalendarIterator(Date focus, int rangeStyle) {
+ GregorianCalendar gval = new GregorianCalendar();
+ gval.setTime(focus);
+ return getCalendarIterator(gval, rangeStyle);
+ }
+
+ /**
+ * See the other getCalendarIterator. Works with an Object, trying
+ * to use it as a Date or Calendar.
+ */
+ public static Iterator getCalendarIterator(Object focus, int rangeStyle) {
+ if (focus instanceof Date) {
+ return getCalendarIterator((Date) focus, rangeStyle);
+ } else if (focus instanceof Calendar) {
+ return getCalendarIterator((Calendar) focus, rangeStyle);
+ } else {
+ throw new ClassCastException("Could not iterate based on " + focus);
+ }
+ }
+
+}
diff --git a/examples/cl2/src/java/org/apache/commons/lang/time/DurationFormatUtils.java b/examples/cl2/src/java/org/apache/commons/lang/time/DurationFormatUtils.java
new file mode 100644
index 00000000..aecaba94
--- /dev/null
+++ b/examples/cl2/src/java/org/apache/commons/lang/time/DurationFormatUtils.java
@@ -0,0 +1,167 @@
+/* ====================================================================
+ * 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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
+ * .
+ */
+package org.apache.commons.lang.time;
+
+/**
+ * Duration formatting utilites and constants.
+ *
+ * @author Apache Ant - DateUtils
+ * @author Stephane Bailliez
+ * @author Stefan Bodewig
+ * @author Stephen Colebourne
+ * @since 2.0
+ * @version $Id: DurationFormatUtils.java,v 1.2 2003/06/09 21:23:14 scolebourne Exp $
+ */
+class DurationFormatUtils {
+ // TODO: Make class public once methods can fully select which fields to output
+
+ /**
+ * 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() {
+ }
+
+ /**
+ * 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.
+ *
+ * - 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")
+ *
+ *
+ * @param millis the elapsed time to report in milliseconds
+ * @return the formatted text in minutes/seconds
+ */
+ 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"};
+
+ StringBuffer buf = new StringBuffer(64);
+ boolean valueOutput = false;
+
+ 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]);
+ }
+ } else {
+ if (supressLeadingZeroElements == false) {
+ buf.append('0').append(fieldsPlural[i]);
+ }
+ }
+ } else if (value == 1) {
+ // one
+ valueOutput = true;
+ buf.append('1').append(fieldsOne[i]);
+ } else {
+ // other
+ valueOutput = true;
+ buf.append(value).append(fieldsPlural[i]);
+ }
+ }
+
+ return buf.toString().trim();
+ }
+
+ /**
+ * Get the time gap as a string.
+ *
+ * The format used is ISO8601-like.
+ * hours:minutes:seconds.milliseconds.
+ *
+ * @param millis the duration to format
+ * @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;
+
+ 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');
+ }
+ buf.append(milliseconds);
+ return buf.toString();
+ }
+
+}
diff --git a/examples/cl2/src/java/org/apache/commons/lang/time/FastDateFormat.java b/examples/cl2/src/java/org/apache/commons/lang/time/FastDateFormat.java
new file mode 100644
index 00000000..ff63b891
--- /dev/null
+++ b/examples/cl2/src/java/org/apache/commons/lang/time/FastDateFormat.java
@@ -0,0 +1,1305 @@
+/* ====================================================================
+ * 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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
+ * .
+ */
+package org.apache.commons.lang.time;
+
+import java.text.DateFormat;
+import java.text.DateFormatSymbols;
+import java.text.FieldPosition;
+import java.text.Format;
+import java.text.ParsePosition;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.GregorianCalendar;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.TimeZone;
+
+/**
+ * FastDateFormat is a fast and thread-safe version of {@link java.text.SimpleDateFormat}.
+ *
+ * Only formatting is supported, but all patterns are compatible with
+ * SimpleDateFormat (except timezones - see below).
+ *
+ * Java 1.4 introduced a new pattern letter, 'Z', to represent time zones in
+ * RFC822 format (eg. +0800 or -1100). This pattern letter can be used here (on
+ * all JDK versions).
+ *
+ * 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 useful functionality.
+ *
+ * NOTE: Code originally taken from the open source TreeTrove project.
+ *
+ * @author Brian S O'Neill
+ * @author Sean Schofield
+ * @author Gary Gregory
+ * @author Stephen Colebourne
+ * @since 2.0
+ * @version $Id: FastDateFormat.java,v 1.6 2003/06/08 23:14:23 scolebourne Exp $
+ */
+public class FastDateFormat extends Format {
+ // A lot of the speed in this class comes from caching, but some comes
+ // from the special int to StringBuffer conversion.
+ //
+ // The following produces a padded 2 digit number:
+ // buffer.append((char)(value / 10 + '0'));
+ // buffer.append((char)(value % 10 + '0'));
+ //
+ // Note that the fastest append to StringBuffer is a single char (used here).
+ // Note that Integer.toString() is not called, the conversion is simply
+ // taking the value and adding (mathematically) the ASCII value for '0'.
+ // So, don't change this code! It works and is vary fast.
+
+ /** FULL locale dependent date or time style */
+ public static final int FULL = SimpleDateFormat.FULL;
+ /** LONG locale dependent date or time style */
+ public static final int LONG = SimpleDateFormat.LONG;
+ /** MEDIUM locale dependent date or time style */
+ public static final int MEDIUM = SimpleDateFormat.MEDIUM;
+ /** SHORT locale dependent date or time style */
+ public static final int SHORT = SimpleDateFormat.SHORT;
+
+ // package scoped as used by inner class
+ static final double LOG_10 = Math.log(10);
+
+ private static String cDefaultPattern;
+
+ private static Map cInstanceCache = new HashMap(7);
+ private static Map cDateInstanceCache = new HashMap(7);
+ private static Map cTimeInstanceCache = new HashMap(7);
+ private static Map cDateTimeInstanceCache = new HashMap(7);
+ private static Map cTimeZoneDisplayCache = new HashMap(7);
+
+ /** The pattern */
+ private final String mPattern;
+ /** The time zone */
+ private final TimeZone mTimeZone;
+ /** Whether the time zone overrides any on Calendars */
+ private final boolean mTimeZoneForced;
+ /** The locale */
+ private final Locale mLocale;
+ /** Whether the locale overrides the default */
+ private final boolean mLocaleForced;
+ /** The parsed rules */
+ private Rule[] mRules;
+ /** The estimated maximum length */
+ private int mMaxLengthEstimate;
+
+ //-----------------------------------------------------------------------
+ /**
+ * Gets a formatter instance using the default pattern in the default locale.
+ *
+ * @return a date/time formatter
+ */
+ public static FastDateFormat getInstance() {
+ return getInstance(getDefaultPattern(), null, null);
+ }
+
+ /**
+ * Gets a formatter instance using the specified pattern in the default locale.
+ *
+ * @param pattern {@link java.text.SimpleDateFormat} compatible pattern
+ * @return a pattern based date/time formatter
+ * @throws IllegalArgumentException if pattern is invalid
+ */
+ public static FastDateFormat getInstance(String pattern) {
+ return getInstance(pattern, null, null);
+ }
+
+ /**
+ * Gets a formatter instance using the specified pattern and time zone.
+ *
+ * @param pattern {@link java.text.SimpleDateFormat} compatible pattern
+ * @param timeZone optional time zone, overrides time zone of formatted date
+ * @return a pattern based date/time formatter
+ * @throws IllegalArgumentException if pattern is invalid
+ */
+ public static FastDateFormat getInstance(String pattern, TimeZone timeZone) {
+ return getInstance(pattern, timeZone, null);
+ }
+
+ /**
+ * Gets a formatter instance using the specified pattern and locale.
+ *
+ * @param pattern {@link java.text.SimpleDateFormat} compatible pattern
+ * @param locale optional locale, overrides system locale
+ * @return a pattern based date/time formatter
+ * @throws IllegalArgumentException if pattern is invalid
+ */
+ public static FastDateFormat getInstance(String pattern, Locale locale) {
+ return getInstance(pattern, null, locale);
+ }
+
+ /**
+ * Gets a formatter instance using the specified pattern, time zone and locale.
+ *
+ * @param pattern {@link java.text.SimpleDateFormat} compatible pattern
+ * @param timeZone optional time zone, overrides time zone of formatted date
+ * @param locale optional locale, overrides system locale
+ * @return a pattern based date/time formatter
+ * @throws IllegalArgumentException if pattern is invalid or null
+ */
+ public static synchronized FastDateFormat getInstance(String pattern, TimeZone timeZone, Locale locale) {
+ FastDateFormat emptyFormat = new FastDateFormat(pattern, timeZone, locale);
+ FastDateFormat format = (FastDateFormat) cInstanceCache.get(emptyFormat);
+ if (format == null) {
+ format = emptyFormat;
+ format.init(); // convert shell format into usable one
+ cInstanceCache.put(format, format); // this is OK!
+ }
+ return format;
+ }
+
+ /**
+ * Gets a date formatter instance using the specified style, time zone and locale.
+ *
+ * @param style date style: FULL, LONG, MEDIUM, or SHORT
+ * @param timeZone optional time zone, overrides time zone of formatted date
+ * @param locale optional locale, overrides system locale
+ * @return a localized standard date formatter
+ * @throws IllegalArgumentException if the Locale has no date pattern defined
+ */
+ public static synchronized FastDateFormat getDateInstance(int style, TimeZone timeZone, Locale locale) {
+ Object key = new Integer(style);
+ if (timeZone != null) {
+ key = new Pair(key, timeZone);
+ }
+ if (locale == null) {
+ 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();
+ format = getInstance(pattern, timeZone, locale);
+ cDateInstanceCache.put(key, format);
+
+ } catch (ClassCastException ex) {
+ throw new IllegalArgumentException("No date pattern for locale: " + locale);
+ }
+ }
+ return format;
+ }
+
+ /**
+ * Gets a time formatter instance using the specified style, time zone and locale.
+ *
+ * @param style time style: FULL, LONG, MEDIUM, or SHORT
+ * @param timeZone optional time zone, overrides time zone of formatted time
+ * @param locale optional locale, overrides system locale
+ * @return a localized standard time formatter
+ * @throws IllegalArgumentException if the Locale has no time pattern defined
+ */
+ public static synchronized FastDateFormat getTimeInstance(int style, TimeZone timeZone, Locale locale) {
+ Object key = new Integer(style);
+ if (timeZone != null) {
+ key = new Pair(key, timeZone);
+ }
+ if (locale != null) {
+ key = new Pair(key, locale);
+ }
+
+ FastDateFormat format = (FastDateFormat) cTimeInstanceCache.get(key);
+ if (format == null) {
+ if (locale == null) {
+ locale = Locale.getDefault();
+ }
+
+ try {
+ SimpleDateFormat formatter = (SimpleDateFormat) DateFormat.getTimeInstance(style, locale);
+ String pattern = formatter.toPattern();
+ format = getInstance(pattern, timeZone, locale);
+ cTimeInstanceCache.put(key, format);
+
+ } catch (ClassCastException ex) {
+ throw new IllegalArgumentException("No date pattern for locale: " + locale);
+ }
+ }
+ return format;
+ }
+
+ /**
+ * Gets a date/time formatter instance using the specified style, time zone and 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
+ * @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
+ */
+ 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);
+ }
+
+ FastDateFormat format = (FastDateFormat) cDateTimeInstanceCache.get(key);
+ if (format == null) {
+ if (locale == null) {
+ locale = Locale.getDefault();
+ }
+
+ try {
+ 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);
+ }
+ }
+ return format;
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Gets the time zone display name, using a cache for performance.
+ *
+ * @param tz the zone to query
+ * @param daylight true if daylight savings
+ * @param style the style to use TimeZone.LONG or TimeZone.SHORT
+ * @param locale the locale to use
+ * @return the textual name of the time zone
+ */
+ static synchronized String getTimeZoneDisplay(TimeZone tz, boolean daylight, int style, Locale locale) {
+ Object key = new TimeZoneDisplayKey(tz, daylight, style, locale);
+ String value = (String) cTimeZoneDisplayCache.get(key);
+ if (value == null) {
+ // This is a very slow call, so cache the results.
+ value = tz.getDisplayName(daylight, style, locale);
+ cTimeZoneDisplayCache.put(key, value);
+ }
+ return value;
+ }
+
+ /**
+ * Gets the default pattern.
+ *
+ * @return the default pattern
+ */
+ private static synchronized String getDefaultPattern() {
+ if (cDefaultPattern == null) {
+ cDefaultPattern = new SimpleDateFormat().toPattern();
+ }
+ return cDefaultPattern;
+ }
+
+ // Constructor
+ //-----------------------------------------------------------------------
+ /**
+ * Constructs a new FastDateFormat.
+ *
+ * @param pattern {@link java.text.SimpleDateFormat} compatible pattern
+ * @param timeZone time zone to use, null means use default for Date and
+ * value within for Calendar
+ * @param locale locale, null means use system default
+ * @throws IllegalArgumentException if pattern is invalid or null
+ */
+ protected FastDateFormat(String pattern, TimeZone timeZone, Locale locale) {
+ super();
+ if (pattern == null) {
+ throw new IllegalArgumentException("The pattern must not be null");
+ }
+ mPattern = pattern;
+
+ mTimeZoneForced = (timeZone != null);
+ if (timeZone == null) {
+ timeZone = TimeZone.getDefault();
+ }
+ mTimeZone = timeZone;
+
+ mLocaleForced = (locale != null);
+ if (locale == null) {
+ locale = Locale.getDefault();
+ }
+ mLocale = locale;
+ }
+
+ /**
+ * Initialise the instance for first use.
+ */
+ protected void init() {
+ List rulesList = parsePattern();
+ mRules = (Rule[]) rulesList.toArray(new Rule[rulesList.size()]);
+
+ int len = 0;
+ for (int i=mRules.length; --i >= 0; ) {
+ len += mRules[i].estimateLength();
+ }
+
+ mMaxLengthEstimate = len;
+ }
+
+ // Parse the pattern
+ //-----------------------------------------------------------------------
+ /**
+ * Returns a list of Rules given a pattern.
+ *
+ * @return a List of Rule objects
+ * @throws IllegalArgumentException if pattern is invalid
+ */
+ protected List parsePattern() {
+ DateFormatSymbols symbols = new DateFormatSymbols(mLocale);
+ List rules = new ArrayList();
+
+ String[] ERAs = symbols.getEras();
+ String[] months = symbols.getMonths();
+ String[] shortMonths = symbols.getShortMonths();
+ String[] weekdays = symbols.getWeekdays();
+ String[] shortWeekdays = symbols.getShortWeekdays();
+ String[] AmPmStrings = symbols.getAmPmStrings();
+
+ int length = mPattern.length();
+ int[] indexRef = new int[1];
+
+ for (int i = 0; i < length; i++) {
+ indexRef[0] = i;
+ String token = parseToken(mPattern, indexRef);
+ i = indexRef[0];
+
+ int tokenLen = token.length();
+ if (tokenLen == 0) {
+ break;
+ }
+
+ Rule rule;
+ char c = token.charAt(0);
+
+ switch (c) {
+ case 'G': // era designator (text)
+ rule = new TextField(Calendar.ERA, ERAs);
+ break;
+ case 'y': // year (number)
+ if (tokenLen >= 4) {
+ rule = UnpaddedNumberField.INSTANCE_YEAR;
+ } else {
+ rule = TwoDigitYearField.INSTANCE;
+ }
+ break;
+ case 'M': // month in year (text and number)
+ if (tokenLen >= 4) {
+ rule = new TextField(Calendar.MONTH, months);
+ } else if (tokenLen == 3) {
+ rule = new TextField(Calendar.MONTH, shortMonths);
+ } else if (tokenLen == 2) {
+ rule = TwoDigitMonthField.INSTANCE;
+ } else {
+ rule = UnpaddedMonthField.INSTANCE;
+ }
+ break;
+ case 'd': // day in month (number)
+ rule = selectNumberRule(Calendar.DAY_OF_MONTH, tokenLen);
+ break;
+ case 'h': // hour in am/pm (number, 1..12)
+ rule = new TwelveHourField(selectNumberRule(Calendar.HOUR, tokenLen));
+ break;
+ case 'H': // hour in day (number, 0..23)
+ rule = selectNumberRule(Calendar.HOUR_OF_DAY, tokenLen);
+ break;
+ case 'm': // minute in hour (number)
+ rule = selectNumberRule(Calendar.MINUTE, tokenLen);
+ break;
+ case 's': // second in minute (number)
+ rule = selectNumberRule(Calendar.SECOND, tokenLen);
+ break;
+ case 'S': // millisecond (number)
+ rule = selectNumberRule(Calendar.MILLISECOND, tokenLen);
+ break;
+ case 'E': // day in week (text)
+ rule = new TextField(Calendar.DAY_OF_WEEK, tokenLen < 4 ? shortWeekdays : weekdays);
+ break;
+ case 'D': // day in year (number)
+ rule = selectNumberRule(Calendar.DAY_OF_YEAR, tokenLen);
+ break;
+ case 'F': // day of week in month (number)
+ rule = selectNumberRule(Calendar.DAY_OF_WEEK_IN_MONTH, tokenLen);
+ break;
+ case 'w': // week in year (number)
+ rule = selectNumberRule(Calendar.WEEK_OF_YEAR, tokenLen);
+ break;
+ case 'W': // week in month (number)
+ rule = selectNumberRule(Calendar.WEEK_OF_MONTH, tokenLen);
+ break;
+ case 'a': // am/pm marker (text)
+ rule = new TextField(Calendar.AM_PM, AmPmStrings);
+ break;
+ case 'k': // hour in day (1..24)
+ rule = new TwentyFourHourField(selectNumberRule(Calendar.HOUR_OF_DAY, tokenLen));
+ break;
+ case 'K': // hour in am/pm (0..11)
+ rule = selectNumberRule(Calendar.HOUR, tokenLen);
+ break;
+ case 'z': // time zone (text)
+ if (tokenLen >= 4) {
+ rule = new TimeZoneNameRule(mTimeZone, mTimeZoneForced, mLocale, TimeZone.LONG);
+ } else {
+ rule = new TimeZoneNameRule(mTimeZone, mTimeZoneForced, mLocale, TimeZone.SHORT);
+ }
+ break;
+ case 'Z': // time zone (value)
+ if (tokenLen == 1) {
+ rule = TimeZoneNumberRule.INSTANCE_NO_COLON;
+ } else {
+ rule = TimeZoneNumberRule.INSTANCE_COLON;
+ }
+ break;
+ case '\'': // literal text
+ String sub = token.substring(1);
+ if (sub.length() == 1) {
+ rule = new CharacterLiteral(sub.charAt(0));
+ } else {
+ rule = new StringLiteral(new String(sub));
+ }
+ break;
+ default:
+ throw new IllegalArgumentException("Illegal pattern component: " + token);
+ }
+
+ rules.add(rule);
+ }
+
+ return rules;
+ }
+
+ /**
+ * Performs the parsing of tokens.
+ *
+ * @param pattern the pattern
+ * @param indexRef index references
+ * @return parsed token
+ */
+ protected String parseToken(String pattern, int[] indexRef) {
+ StringBuffer buf = new StringBuffer();
+
+ int i = indexRef[0];
+ int length = pattern.length();
+
+ char c = pattern.charAt(i);
+ if (c >= 'A' && c <= 'Z' || c >= 'a' && c <= 'z') {
+ // Scan a run of the same character, which indicates a time
+ // pattern.
+ buf.append(c);
+
+ while (i + 1 < length) {
+ char peek = pattern.charAt(i + 1);
+ if (peek == c) {
+ buf.append(c);
+ i++;
+ } else {
+ break;
+ }
+ }
+ } else {
+ // This will identify token as text.
+ buf.append('\'');
+
+ boolean inLiteral = false;
+
+ for (; i < length; i++) {
+ c = pattern.charAt(i);
+
+ if (c == '\'') {
+ if (i + 1 < length && pattern.charAt(i + 1) == '\'') {
+ // '' is treated as escaped '
+ i++;
+ buf.append(c);
+ } else {
+ inLiteral = !inLiteral;
+ }
+ } else if (!inLiteral &&
+ (c >= 'A' && c <= 'Z' || c >= 'a' && c <= 'z')) {
+ i--;
+ break;
+ } else {
+ buf.append(c);
+ }
+ }
+ }
+
+ indexRef[0] = i;
+ return buf.toString();
+ }
+
+ /**
+ * Gets an appropriate rule for the padding required.
+ *
+ * @param field the field to get a rule for
+ * @param padding the padding required
+ * @return a new rule with the correct padding
+ */
+ protected NumberRule selectNumberRule(int field, int padding) {
+ switch (padding) {
+ case 1:
+ return new UnpaddedNumberField(field);
+ case 2:
+ return new TwoDigitNumberField(field);
+ default:
+ return new PaddedNumberField(field, padding);
+ }
+ }
+
+ // Format methods
+ //-----------------------------------------------------------------------
+ /**
+ * Format either a Date or a Calendar object.
+ *
+ * @param obj the object to format
+ * @param toAppendTo the buffer to append to
+ * @param pos the position - ignored
+ * @return the buffer passed in
+ */
+ public StringBuffer format(Object obj, StringBuffer toAppendTo, FieldPosition pos) {
+ if (obj instanceof Date) {
+ return format((Date) obj, toAppendTo);
+ } else if (obj instanceof Calendar) {
+ return format((Calendar) obj, toAppendTo);
+ } else {
+ throw new IllegalArgumentException("Unknown class: " +
+ (obj == null ? "" : obj.getClass().getName()));
+ }
+ }
+
+ /**
+ * Formats a Date object.
+ *
+ * @param date the date to format
+ * @return the formatted string
+ */
+ public String format(Date date) {
+ Calendar c = new GregorianCalendar(mTimeZone);
+ c.setTime(date);
+ return applyRules(c, new StringBuffer(mMaxLengthEstimate)).toString();
+ }
+
+ /**
+ * Formats a Calendar object.
+ *
+ * @param calendar the calendar to format
+ * @return the formatted string
+ */
+ public String format(Calendar calendar) {
+ return format(calendar, new StringBuffer(mMaxLengthEstimate)).toString();
+ }
+
+ /**
+ * Formats a Date object into the supplied StringBuffer.
+ *
+ * @param date the date to format
+ * @param buf the buffer to format into
+ * @return the specified string buffer
+ */
+ public StringBuffer format(Date date, StringBuffer buf) {
+ Calendar c = new GregorianCalendar(mTimeZone);
+ c.setTime(date);
+ return applyRules(c, buf);
+ }
+
+ /**
+ * Formats a Calendar object into the supplied StringBuffer.
+ *
+ * @param calendar the calendar to format
+ * @param buf the buffer to format into
+ * @return the specified string buffer
+ */
+ public StringBuffer format(Calendar calendar, StringBuffer buf) {
+ if (mTimeZoneForced) {
+ calendar = (Calendar) calendar.clone();
+ calendar.setTimeZone(mTimeZone);
+ }
+ return applyRules(calendar, buf);
+ }
+
+ /**
+ * Performs the formatting by applying the rules to the specified calendar.
+ *
+ * @param calendar the calendar to format
+ * @param buf the buffer to format into
+ * @return the specified string buffer
+ */
+ protected StringBuffer applyRules(Calendar calendar, StringBuffer buf) {
+ Rule[] rules = mRules;
+ int len = mRules.length;
+ for (int i = 0; i < len; i++) {
+ rules[i].appendTo(buf, calendar);
+ }
+ return buf;
+ }
+
+ // Parsing
+ //-----------------------------------------------------------------------
+ /**
+ * Parsing not supported.
+ *
+ * @param source the string to parse
+ * @param pos the parsing position
+ * @return null as not supported
+ */
+ public Object parseObject(String source, ParsePosition pos) {
+ pos.setIndex(0);
+ pos.setErrorIndex(0);
+ return null;
+ }
+
+ // Accessors
+ //-----------------------------------------------------------------------
+ /**
+ * Gets the pattern used by this formatter.
+ *
+ * @return the pattern, {@link java.text.SimpleDateFormat} compatible
+ */
+ public String getPattern() {
+ return mPattern;
+ }
+
+ /**
+ * Gets the time zone used by this formatter.
+ *
+ * This zone is always used for Date formatting.
+ * If a Calendar is passed in to be formatted, the time zone on that may
+ * be used depending on {@link #getTimeZoneOverridesCalendar()}.
+ *
+ * @return the time zone
+ */
+ public TimeZone getTimeZone() {
+ return mTimeZone;
+ }
+
+ /**
+ * Returns true if the time zone of the calendar overrides the time zone
+ * of the formatter
+ *
+ * @return true if time zone of formatter overridden for calendars
+ */
+ public boolean getTimeZoneOverridesCalendar() {
+ return mTimeZoneForced;
+ }
+
+ /**
+ * Gets the locale used by this formatter.
+ *
+ * @return the locale
+ */
+ public Locale getLocale() {
+ return mLocale;
+ }
+
+ /**
+ * Gets an estimate for the maximum string length that the formatter will produce.
+ * The actual formatted length will almost always be less than or equal to this amount.
+ *
+ * @return the maximum formatted length
+ */
+ public int getMaxLengthEstimate() {
+ return mMaxLengthEstimate;
+ }
+
+ // Basics
+ //-----------------------------------------------------------------------
+ /**
+ * Compare two objects for equality.
+ *
+ * @param obj the object to compare to
+ * @return true if equal
+ */
+ public boolean equals(Object obj) {
+ if (obj instanceof FastDateFormat == false) {
+ return false;
+ }
+ FastDateFormat other = (FastDateFormat) obj;
+ if (
+ (mPattern == other.mPattern || mPattern.equals(other.mPattern)) &&
+ (mTimeZone == other.mTimeZone || mTimeZone.equals(other.mTimeZone)) &&
+ (mLocale == other.mLocale || mLocale.equals(other.mLocale)) &&
+ (mTimeZoneForced == other.mTimeZoneForced) &&
+ (mLocaleForced == other.mLocaleForced)
+ ) {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * A suitable hashcode.
+ *
+ * @return a hashcode compatable with equals
+ */
+ public int hashCode() {
+ int total = 0;
+ total += mPattern.hashCode();
+ total += mTimeZone.hashCode();
+ total += (mTimeZoneForced ? 1 : 0);
+ total += mLocale.hashCode();
+ total += (mLocaleForced ? 1 : 0);
+ return total;
+ }
+
+ /**
+ * Gets a debugging string version of this formatter.
+ *
+ * @return a debugging string
+ */
+ public String toString() {
+ return "FastDateFormat[" + mPattern + "]";
+ }
+
+ // Rules
+ //-----------------------------------------------------------------------
+ /**
+ * Inner class defining a rule.
+ */
+ private interface Rule {
+ int estimateLength();
+ void appendTo(StringBuffer buffer, Calendar calendar);
+ }
+
+ /**
+ * Inner class defining a numeric rule.
+ */
+ private interface NumberRule extends Rule {
+ void appendTo(StringBuffer buffer, int value);
+ }
+
+ /**
+ * Inner class to output a constant single character.
+ */
+ private static class CharacterLiteral implements Rule {
+ private final char mValue;
+
+ CharacterLiteral(char value) {
+ mValue = value;
+ }
+
+ public int estimateLength() {
+ return 1;
+ }
+
+ public void appendTo(StringBuffer buffer, Calendar calendar) {
+ buffer.append(mValue);
+ }
+ }
+
+ /**
+ * Inner class to output a constant string.
+ */
+ private static class StringLiteral implements Rule {
+ private final String mValue;
+
+ StringLiteral(String value) {
+ mValue = value;
+ }
+
+ public int estimateLength() {
+ return mValue.length();
+ }
+
+ public void appendTo(StringBuffer buffer, Calendar calendar) {
+ buffer.append(mValue);
+ }
+ }
+
+ /**
+ * Inner class to output one of a set of values.
+ */
+ private static class TextField implements Rule {
+ private final int mField;
+ private final String[] mValues;
+
+ TextField(int field, String[] values) {
+ mField = field;
+ mValues = values;
+ }
+
+ public int estimateLength() {
+ int max = 0;
+ for (int i=mValues.length; --i >= 0; ) {
+ int len = mValues[i].length();
+ if (len > max) {
+ max = len;
+ }
+ }
+ return max;
+ }
+
+ public void appendTo(StringBuffer buffer, Calendar calendar) {
+ buffer.append(mValues[calendar.get(mField)]);
+ }
+ }
+
+ /**
+ * 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;
+
+ UnpaddedNumberField(int field) {
+ mField = field;
+ }
+
+ public int estimateLength() {
+ return 4;
+ }
+
+ public void appendTo(StringBuffer buffer, Calendar calendar) {
+ appendTo(buffer, calendar.get(mField));
+ }
+
+ public final void appendTo(StringBuffer buffer, int value) {
+ if (value < 10) {
+ buffer.append((char)(value + '0'));
+ } else if (value < 100) {
+ buffer.append((char)(value / 10 + '0'));
+ buffer.append((char)(value % 10 + '0'));
+ } else {
+ buffer.append(Integer.toString(value));
+ }
+ }
+ }
+
+ /**
+ * Inner class to output an unpadded month.
+ */
+ private static class UnpaddedMonthField implements NumberRule {
+ static final UnpaddedMonthField INSTANCE = new UnpaddedMonthField();
+
+ UnpaddedMonthField() {
+ }
+
+ public int estimateLength() {
+ return 2;
+ }
+
+ public void appendTo(StringBuffer buffer, Calendar calendar) {
+ appendTo(buffer, calendar.get(Calendar.MONTH) + 1);
+ }
+
+ public final void appendTo(StringBuffer buffer, int value) {
+ if (value < 10) {
+ buffer.append((char)(value + '0'));
+ } else {
+ buffer.append((char)(value / 10 + '0'));
+ buffer.append((char)(value % 10 + '0'));
+ }
+ }
+ }
+
+ /**
+ * Inner class to output a padded number.
+ */
+ private static class PaddedNumberField implements NumberRule {
+ private final int mField;
+ private final int mSize;
+
+ PaddedNumberField(int field, int size) {
+ if (size < 3) {
+ // Should use UnpaddedNumberField or TwoDigitNumberField.
+ throw new IllegalArgumentException();
+ }
+ mField = field;
+ mSize = size;
+ }
+
+ public int estimateLength() {
+ return 4;
+ }
+
+ public void appendTo(StringBuffer buffer, Calendar calendar) {
+ appendTo(buffer, calendar.get(mField));
+ }
+
+ public final void appendTo(StringBuffer buffer, int value) {
+ if (value < 100) {
+ for (int i = mSize; --i >= 2; ) {
+ buffer.append('0');
+ }
+ buffer.append((char)(value / 10 + '0'));
+ buffer.append((char)(value % 10 + '0'));
+ } else {
+ int digits;
+ if (value < 1000) {
+ digits = 3;
+ } else {
+ digits = (int)(Math.log(value) / LOG_10) + 1;
+ }
+ for (int i = mSize; --i >= digits; ) {
+ buffer.append('0');
+ }
+ buffer.append(Integer.toString(value));
+ }
+ }
+ }
+
+ /**
+ * Inner class to output a two digit number.
+ */
+ private static class TwoDigitNumberField implements NumberRule {
+ private final int mField;
+
+ TwoDigitNumberField(int field) {
+ mField = field;
+ }
+
+ public int estimateLength() {
+ return 2;
+ }
+
+ public void appendTo(StringBuffer buffer, Calendar calendar) {
+ appendTo(buffer, calendar.get(mField));
+ }
+
+ public final void appendTo(StringBuffer buffer, int value) {
+ if (value < 100) {
+ buffer.append((char)(value / 10 + '0'));
+ buffer.append((char)(value % 10 + '0'));
+ } else {
+ buffer.append(Integer.toString(value));
+ }
+ }
+ }
+
+ /**
+ * Inner class to output a two digit year.
+ */
+ private static class TwoDigitYearField implements NumberRule {
+ static final TwoDigitYearField INSTANCE = new TwoDigitYearField();
+
+ TwoDigitYearField() {
+ }
+
+ public int estimateLength() {
+ return 2;
+ }
+
+ public void appendTo(StringBuffer buffer, Calendar calendar) {
+ appendTo(buffer, calendar.get(Calendar.YEAR) % 100);
+ }
+
+ public final void appendTo(StringBuffer buffer, int value) {
+ buffer.append((char)(value / 10 + '0'));
+ buffer.append((char)(value % 10 + '0'));
+ }
+ }
+
+ /**
+ * Inner class to output a two digit month.
+ */
+ private static class TwoDigitMonthField implements NumberRule {
+ static final TwoDigitMonthField INSTANCE = new TwoDigitMonthField();
+
+ TwoDigitMonthField() {
+ }
+
+ public int estimateLength() {
+ return 2;
+ }
+
+ public void appendTo(StringBuffer buffer, Calendar calendar) {
+ appendTo(buffer, calendar.get(Calendar.MONTH) + 1);
+ }
+
+ public final void appendTo(StringBuffer buffer, int value) {
+ buffer.append((char)(value / 10 + '0'));
+ buffer.append((char)(value % 10 + '0'));
+ }
+ }
+
+ /**
+ * Inner class to output the twelve hour field.
+ */
+ private static class TwelveHourField implements NumberRule {
+ private final NumberRule mRule;
+
+ TwelveHourField(NumberRule rule) {
+ mRule = rule;
+ }
+
+ public int estimateLength() {
+ return mRule.estimateLength();
+ }
+
+ public void appendTo(StringBuffer buffer, Calendar calendar) {
+ int value = calendar.get(Calendar.HOUR);
+ if (value == 0) {
+ value = calendar.getLeastMaximum(Calendar.HOUR) + 1;
+ }
+ mRule.appendTo(buffer, value);
+ }
+
+ public void appendTo(StringBuffer buffer, int value) {
+ mRule.appendTo(buffer, value);
+ }
+ }
+
+ /**
+ * Inner class to output the twenty four hour field.
+ */
+ private static class TwentyFourHourField implements NumberRule {
+ private final NumberRule mRule;
+
+ TwentyFourHourField(NumberRule rule) {
+ mRule = rule;
+ }
+
+ public int estimateLength() {
+ return mRule.estimateLength();
+ }
+
+ public void appendTo(StringBuffer buffer, Calendar calendar) {
+ int value = calendar.get(Calendar.HOUR_OF_DAY);
+ if (value == 0) {
+ value = calendar.getMaximum(Calendar.HOUR_OF_DAY) + 1;
+ }
+ mRule.appendTo(buffer, value);
+ }
+
+ public void appendTo(StringBuffer buffer, int value) {
+ mRule.appendTo(buffer, value);
+ }
+ }
+
+ /**
+ * Inner class to output a time zone name.
+ */
+ private static class TimeZoneNameRule implements Rule {
+ private final TimeZone mTimeZone;
+ private final boolean mTimeZoneForced;
+ private final Locale mLocale;
+ private final int mStyle;
+ private final String mStandard;
+ private final String mDaylight;
+
+ TimeZoneNameRule(TimeZone timeZone, boolean timeZoneForced, Locale locale, int style) {
+ mTimeZone = timeZone;
+ mTimeZoneForced = timeZoneForced;
+ mLocale = locale;
+ mStyle = style;
+
+ if (timeZoneForced) {
+ mStandard = getTimeZoneDisplay(timeZone, false, style, locale);
+ mDaylight = getTimeZoneDisplay(timeZone, true, style, locale);
+ } else {
+ mStandard = null;
+ mDaylight = null;
+ }
+ }
+
+ public int estimateLength() {
+ if (mTimeZoneForced) {
+ return Math.max(mStandard.length(), mDaylight.length());
+ } else if (mStyle == TimeZone.SHORT) {
+ return 4;
+ } else {
+ return 40;
+ }
+ }
+
+ public void appendTo(StringBuffer buffer, Calendar calendar) {
+ if (mTimeZoneForced) {
+ if (mTimeZone.useDaylightTime() && calendar.get(Calendar.DST_OFFSET) != 0) {
+ buffer.append(mDaylight);
+ } else {
+ buffer.append(mStandard);
+ }
+ } else {
+ TimeZone timeZone = calendar.getTimeZone();
+ if (timeZone.useDaylightTime() && calendar.get(Calendar.DST_OFFSET) != 0) {
+ buffer.append(getTimeZoneDisplay(timeZone, true, mStyle, mLocale));
+ } else {
+ buffer.append(getTimeZoneDisplay(timeZone, false, mStyle, mLocale));
+ }
+ }
+ }
+ }
+
+ /**
+ * Inner class to output a time zone as a number +/-HHMM or +/-HH:MM.
+ */
+ private static class TimeZoneNumberRule implements Rule {
+ static final TimeZoneNumberRule INSTANCE_COLON = new TimeZoneNumberRule(true);
+ static final TimeZoneNumberRule INSTANCE_NO_COLON = new TimeZoneNumberRule(false);
+
+ final boolean mColon;
+
+ TimeZoneNumberRule(boolean colon) {
+ mColon = colon;
+ }
+
+ public int estimateLength() {
+ return 5;
+ }
+
+ public void appendTo(StringBuffer buffer, Calendar calendar) {
+ int offset = calendar.get(Calendar.ZONE_OFFSET) + calendar.get(Calendar.DST_OFFSET);
+
+ if (offset < 0) {
+ buffer.append('-');
+ offset = -offset;
+ } else {
+ buffer.append('+');
+ }
+
+ int hours = offset / (60 * 60 * 1000);
+ buffer.append((char)(hours / 10 + '0'));
+ buffer.append((char)(hours % 10 + '0'));
+
+ if (mColon) {
+ buffer.append(':');
+ }
+
+ int minutes = offset / (60 * 1000) - 60 * hours;
+ buffer.append((char)(minutes / 10 + '0'));
+ buffer.append((char)(minutes % 10 + '0'));
+ }
+ }
+
+ // ----------------------------------------------------------------------
+ /**
+ * Inner class that acts as a compound key for time zone names.
+ */
+ private static class TimeZoneDisplayKey {
+ private final TimeZone mTimeZone;
+ private final int mStyle;
+ private final Locale mLocale;
+
+ TimeZoneDisplayKey(TimeZone timeZone,
+ boolean daylight, int style, Locale locale) {
+ mTimeZone = timeZone;
+ if (daylight) {
+ style |= 0x80000000;
+ }
+ mStyle = style;
+ mLocale = locale;
+ }
+
+ public int hashCode() {
+ return mStyle * 31 + mLocale.hashCode();
+ }
+
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof TimeZoneDisplayKey) {
+ TimeZoneDisplayKey other = (TimeZoneDisplayKey)obj;
+ return
+ mTimeZone.equals(other.mTimeZone) &&
+ mStyle == other.mStyle &&
+ mLocale.equals(other.mLocale);
+ }
+ return false;
+ }
+ }
+
+ // ----------------------------------------------------------------------
+ /**
+ * Helper class for creating compound objects. One use for this class is to create a
+ * hashtable key out of multiple objects.
+ */
+ private static class Pair {
+ private final Object mObj1;
+ private final Object mObj2;
+
+ public Pair(Object obj1, Object obj2) {
+ mObj1 = obj1;
+ mObj2 = obj2;
+ }
+
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+
+ if (!(obj instanceof Pair)) {
+ return false;
+ }
+
+ Pair key = (Pair)obj;
+
+ return
+ (mObj1 == null ?
+ key.mObj1 == null : mObj1.equals(key.mObj1)) &&
+ (mObj2 == null ?
+ key.mObj2 == null : mObj2.equals(key.mObj2));
+ }
+
+ public int hashCode() {
+ return
+ (mObj1 == null ? 0 : mObj1.hashCode()) +
+ (mObj2 == null ? 0 : mObj2.hashCode());
+ }
+
+ public String toString() {
+ return "[" + mObj1 + ':' + mObj2 + ']';
+ }
+ }
+
+}
diff --git a/examples/cl2/src/java/org/apache/commons/lang/time/StopWatch.java b/examples/cl2/src/java/org/apache/commons/lang/time/StopWatch.java
new file mode 100644
index 00000000..793e49bb
--- /dev/null
+++ b/examples/cl2/src/java/org/apache/commons/lang/time/StopWatch.java
@@ -0,0 +1,196 @@
+/* ====================================================================
+ * 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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
+ * .
+ */
+package org.apache.commons.lang.time;
+
+/**
+ *
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:
+ *
+ * - {@link #split()} the watch to get the time whilst the watch continues in the
+ * background. {@link #unsplit()} will remove the effect of the split. At this point,
+ * these three options are available again.
+ *
- {@link #suspend()} the watch to pause it. {@link #resume()} allows the watch
+ * to continue. Any time between the suspend and resume will not be counted in
+ * the total. At this point, these three options are available again.
+ *
- {@link #stop()} the watch to complete the timing session.
+ *
+ * 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
+ * @since 2.0
+ * @version $Id: StopWatch.java,v 1.4 2003/06/08 23:14:23 scolebourne Exp $
+ */
+public class StopWatch {
+
+ /** The start time */
+ private long startTime = -1;
+ /** The stop time */
+ private long stopTime = -1;
+
+ /**
+ * Constructor.
+ */
+ public StopWatch() {
+ }
+
+ /**
+ * Start the stopwatch.
+ *
+ * This method starts a new timing session, clearing any previous values.
+ */
+ public void start() {
+ stopTime = -1;
+ startTime = System.currentTimeMillis();
+ }
+
+ /**
+ * Stop the stopwatch.
+ *
+ * This method ends a new timing session, allowing the time to be retrieved.
+ */
+ public void stop() {
+ stopTime = System.currentTimeMillis();
+ }
+
+ /**
+ * Reset the stopwatch.
+ *
+ * This method clears the internal values to allow the object to be reused.
+ */
+ public void reset() {
+ startTime = -1;
+ stopTime = -1;
+ }
+
+ /**
+ * 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.
+ */
+ public void split() {
+ stopTime = System.currentTimeMillis();
+ }
+
+ /**
+ * Remove a split.
+ *
+ * This method clears the stop time. The start time is unaffected, enabling
+ * timing from the original start point to continue.
+ */
+ public void unsplit() {
+ stopTime = -1;
+ }
+
+ /**
+ * 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.
+ */
+ public void suspend() {
+ stopTime = System.currentTimeMillis();
+ }
+
+ /**
+ * 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.
+ */
+ public void resume() {
+ startTime += (System.currentTimeMillis() - stopTime);
+ stopTime = -1;
+ }
+
+ /**
+ * 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.
+ *
+ * @return the time in milliseconds
+ */
+ public long getTime() {
+ if (stopTime == -1) {
+ if (startTime == -1) {
+ return 0;
+ }
+ return (System.currentTimeMillis() - this.startTime);
+ }
+ return (this.stopTime - 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());
+ }
+
+}
diff --git a/examples/cl2/src/java/org/apache/commons/lang/util/BitField.java b/examples/cl2/src/java/org/apache/commons/lang/util/BitField.java
new file mode 100644
index 00000000..e090d740
--- /dev/null
+++ b/examples/cl2/src/java/org/apache/commons/lang/util/BitField.java
@@ -0,0 +1,324 @@
+/* ====================================================================
+ * 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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
+ * .
+ */
+package org.apache.commons.lang.util;
+
+/**
+ * Manage operations dealing with bit-mapped fields.
+ *
+ * Code originated from the POI project.
+ *
+ * @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
+ * @since 2.0
+ * @version $Id: BitField.java,v 1.5 2003/04/09 00:07:49 ggregory Exp $
+ */
+public class BitField {
+
+ private final int _mask;
+ private final int _shift_count;
+
+ /**
+ * Create a BitField instance
+ *
+ * @param mask the mask specifying which bits apply to this
+ * BitField. Bits that are set in this mask are the
+ * bits that this BitField operates on
+ */
+ public BitField(final int mask) {
+ _mask = mask;
+ int count = 0;
+ int bit_pattern = mask;
+
+ if (bit_pattern != 0) {
+ while ((bit_pattern & 1) == 0) {
+ count++;
+ bit_pattern >>= 1;
+ }
+ }
+ _shift_count = count;
+ }
+
+ /**
+ * Obtain the value for the specified BitField, appropriately
+ * shifted right. Many users of a BitField will want to treat the
+ * specified bits as an int value, and will not want to be aware
+ * that the value is stored as a BitField (and so shifted left so
+ * many bits)
+ *
+ * @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) {
+ return getRawValue(holder) >> _shift_count;
+ }
+
+ /**
+ * Obtain the value for the specified BitField, appropriately
+ * shifted right, as a short. Many users of a BitField will want
+ * to treat the specified bits as an int value, and will not want
+ * to be aware that the value is stored as a BitField (and so
+ * shifted left so many bits)
+ *
+ * @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) {
+ return (short) getValue(holder);
+ }
+
+ /**
+ * Obtain the value for the specified BitField, unshifted
+ *
+ * @param holder the int data containing the bits we're interested
+ * in
+ *
+ * @return the selected bits
+ */
+ public int getRawValue(final int holder) {
+ return (holder & _mask);
+ }
+
+ /**
+ * Obtain the value for the specified BitField, unshifted
+ *
+ * @param holder the short data containing the bits we're
+ * interested in
+ *
+ * @return the selected bits
+ */
+ public short getShortRawValue(final short holder) {
+ return (short) getRawValue(holder);
+ }
+
+ /**
+ * Returns whether the field is set or not. This is most commonly used for a
+ * single-bit field, which is often used to represent a boolean
+ * value; the results of using it for a multi-bit field is to
+ * determine whether *any* of its bits are set
+ *
+ * @param holder the int data containing the bits we're interested
+ * in
+ *
+ * @return true if any of the bits are set, else false
+ */
+ public boolean isSet(final int holder) {
+ return (holder & _mask) != 0;
+ }
+
+ /**
+ * Returns whether all of the bits are set or not. This is a stricter test than
+ * isSet, in that all of the bits in a multi-bit set must be set
+ * for this method to return true
+ *
+ * @param holder the int data containing the bits we're interested
+ * in
+ *
+ * @return true if all of the bits are set, else false
+ */
+ public boolean isAllSet(final int holder) {
+ return (holder & _mask) == _mask;
+ }
+
+ /**
+ * Replace the bits with new values.
+ *
+ * @param holder the int data containint 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) {
+ return (holder & ~_mask) | ((value << _shift_count) & _mask);
+ }
+
+ /**
+ * Replace the bits with new values.
+ *
+ * @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) {
+ return (short) setValue(holder, value);
+ }
+
+ /**
+ * Clear the bits.
+ *
+ * @param holder the int data containing the bits we're interested
+ * in
+ *
+ * @return the value of holder with the specified bits cleared
+ * (set to 0)
+ */
+ public int clear(final int holder) {
+ return holder & ~_mask;
+ }
+
+ /**
+ * Clear the bits.
+ *
+ * @param holder the short data containing the bits we're
+ * interested in
+ *
+ * @return the value of holder with the specified bits cleared
+ * (set to 0)
+ */
+ public short clearShort(final short holder) {
+ return (short) clear(holder);
+ }
+
+ /**
+ * Clear the bits.
+ *
+ * @param holder the byte data containing the bits we're
+ * interested in
+ *
+ * @return the value of holder with the specified bits cleared
+ * (set to 0)
+ */
+ public byte clearByte(final byte holder) {
+ return (byte) clear(holder);
+ }
+
+ /**
+ * Set the bits.
+ *
+ * @param holder the int data containing the bits we're interested
+ * in
+ *
+ * @return the value of holder with the specified bits set to 1
+ */
+ public int set(final int holder) {
+ return holder | _mask;
+ }
+
+ /**
+ * Set the bits.
+ *
+ * @param holder the short data containing the bits we're
+ * interested in
+ *
+ * @return the value of holder with the specified bits set to 1
+ */
+ public short setShort(final short holder) {
+ return (short) set(holder);
+ }
+
+ /**
+ * Set the bits.
+ *
+ * @param holder the byte data containing the bits we're
+ * interested in
+ *
+ * @return the value of holder with the specified bits set to 1
+ */
+ public byte setByte(final byte holder) {
+ return (byte) set(holder);
+ }
+
+ /**
+ * Set a boolean BitField
+ *
+ * @param holder the int data containing the bits we're interested
+ * in
+ * @param flag indicating whether to set or clear the bits
+ *
+ * @return the value of holder with the specified bits set or
+ * cleared
+ */
+ public int setBoolean(final int holder, final boolean flag) {
+ return flag ? set(holder) : clear(holder);
+ }
+
+ /**
+ * Set a boolean BitField
+ *
+ * @param holder the short data containing the bits we're
+ * interested in
+ * @param flag indicating whether to set or clear the bits
+ *
+ * @return the value of holder with the specified bits set or
+ * cleared
+ */
+ public short setShortBoolean(final short holder, final boolean flag) {
+ return flag ? setShort(holder) : clearShort(holder);
+ }
+
+ /**
+ * Set a boolean BitField
+ *
+ * @param holder the byte data containing the bits we're
+ * interested in
+ * @param flag indicating whether to set or clear the bits
+ *
+ * @return the value of holder with the specified bits set or
+ * cleared
+ */
+ public byte setByteBoolean(final byte holder, final boolean flag) {
+ return flag ? setByte(holder) : clearByte(holder);
+ }
+
+}
diff --git a/examples/cl2/src/java/org/apache/commons/lang/util/IdentifierFactory.java b/examples/cl2/src/java/org/apache/commons/lang/util/IdentifierFactory.java
new file mode 100644
index 00000000..d40d9258
--- /dev/null
+++ b/examples/cl2/src/java/org/apache/commons/lang/util/IdentifierFactory.java
@@ -0,0 +1,73 @@
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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
+ * .
+ */
+package org.apache.commons.lang.util;
+
+/**
+ *
IdentifierFactory
defines a simple interface for
+ * identifier generation.
+ *
+ * @author Stephen Colebourne
+ * @since 2.0
+ * @version $Id: IdentifierFactory.java,v 1.1 2003/05/16 22:06:43 scolebourne Exp $
+ */
+public interface IdentifierFactory {
+
+ /**
+ * Gets the next identifier in the sequence.
+ *
+ * @return the next identifier in sequence
+ */
+ Object nextIdentifier();
+
+}
diff --git a/examples/cl2/src/java/org/apache/commons/lang/util/IdentifierUtils.java b/examples/cl2/src/java/org/apache/commons/lang/util/IdentifierUtils.java
new file mode 100644
index 00000000..dc6961c8
--- /dev/null
+++ b/examples/cl2/src/java/org/apache/commons/lang/util/IdentifierUtils.java
@@ -0,0 +1,626 @@
+/* ====================================================================
+ * 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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
+ * .
+ */
+package org.apache.commons.lang.util;
+
+import java.io.Serializable;
+import java.util.Random;
+
+/**
+ * IdentifierUtils
provides a number of different identifier
+ * reference implementations.
+ *
+ * All the identifer factories are serializable and synchronized.
+ * The factories all implement one of the factory interfaces defined in this
+ * package. This allows you to obtain and use multiple factories for
+ * different reasons.
+ *
+ * @author Stephen Colebourne
+ * @since 2.0
+ * @version $Id: IdentifierUtils.java,v 1.5 2003/05/16 22:06:43 scolebourne Exp $
+ */
+public class IdentifierUtils {
+
+ /**
+ * Singleton instance of the
+ * LongIdentifierFactory
.
+ *
+ * The singleton instance will wrap, so in a long-lived server, the id
+ * may be duplicated.
+ *
+ * The objects returned are:
+ *
+ * - new Long(0L)
+ *
- new Long(1L)
+ *
- new Long(2L)
+ *
- ...
+ *
+ */
+ public static final LongIdentifierFactory LONG_IDENTIFIER_FACTORY = new LongNumericIdentifierFactory(true, 0L);
+ /**
+ * Singleton instance of the StringNumericIdentifierFactory
.
+ *
+ *
+ * The singleton instance will wrap, so in a long-lived server, the id
+ * may be duplicated.
+ *
+ * The objects returned are:
+ *
+ * - "0"
+ *
- "1"
+ *
- "2"
+ *
- ...
+ *
+ */
+ public static final StringIdentifierFactory STRING_NUMERIC_IDENTIFIER_FACTORY = new StringNumericIdentifierFactory(true, 0L);
+ /**
+ * Singleton instance of the
+ * StringAlphanumericIdentifierFactory
.
+ *
+ * The singleton instance will wrap, so in a long-lived server, the id
+ * may be duplicated. However, the length is 15 in base-36, so thats a
+ * lot of identifiers.
+ *
+ * The objects returned are:
+ *
+ * - "000000000000001"
+ *
- "000000000000002"
+ *
- "000000000000003"
+ *
- ...
+ *
- "00000000000000y"
+ *
- "00000000000000z"
+ *
- "000000000000010"
+ *
- "000000000000011"
+ *
- ...
+ *
- "00000000000001z"
+ *
- "000000000000020"
+ *
- ...
+ *
+ */
+ public static final StringIdentifierFactory STRING_ALPHANUMERIC_IDENTIFIER_FACTORY = new StringAlphanumericIdentifierFactory(true, 15);
+ /**
+ * Singleton instance of the
+ * StringSessionIdentifierFactory
.
+ *
+ * The singleton instance may produce duplicates in a long-lived server,
+ * but its unlikely.
+ *
+ * The objects returned are 10 or more base-36 digits.
+ */
+ public static final StringIdentifierFactory STRING_SESSION_IDENTIFIER_FACTORY = new StringSessionIdentifierFactory();
+
+ //---------------------------------------------------------------------------------
+
+ /**
+ * IdentifierUtils
instances should NOT be constructed in
+ * standard programming.
+ *
+ * This constructor is public to permit tools that require a JavaBean instance
+ * to operate.
+ */
+ public IdentifierUtils() {
+ super();
+ }
+
+ //---------------------------------------------------------------------------------
+
+ /**
+ * Gets the next identifier using the singleton instance of the
+ * Long factory.
+ *
+ *
+ * The singleton instance will wrap, so in a long-lived server, the id
+ * may be duplicated.
+ *
+ * @return a new identifier
+ */
+ public static Long nextLongIdentifier() {
+ return LONG_IDENTIFIER_FACTORY.nextLongIdentifier();
+ }
+
+ /**
+ * Gets a new identifier factory that returns a series of Long objects
+ * increasing in size.
+ *
+ * The factory will wrap when the maximum long
is
+ * reached and return negative numbers. It will start from zero.
+ *
+ * @return a new identifier factory
+ */
+ public static LongIdentifierFactory longIdentifierFactory() {
+ return new LongNumericIdentifierFactory(true, 0L);
+ }
+
+ /**
+ * Gets a new identifier factory that returns a series of Long objects
+ * increasing in size.
+ *
+ * @param wrap should the factory wrap when it reaches the maximum
+ * long value (or throw an IllegalStateException)
+ * @param initialValue the initial long value to start at
+ * @return a new identifier factory
+ */
+ public static LongIdentifierFactory longIdentifierFactory(boolean wrap, long initialValue) {
+ return new LongNumericIdentifierFactory(wrap, initialValue);
+ }
+
+ //---------------------------------------------------------------------------------
+
+ /**
+ * Gets the next identifier using the singleton instance of the
+ * String Numeric factory.
+ *
+ *
+ * The singleton instance will wrap, so in a long-lived server, the id
+ * may be duplicated.
+ *
+ * @return a new identifier
+ */
+ public static String nextStringNumericIdentifier() {
+ return STRING_NUMERIC_IDENTIFIER_FACTORY.nextStringIdentifier();
+ }
+
+ /**
+ * Gets a new identifier factory that returns a series of String objects
+ * representing numbers increasing in size.
+ *
+ * The factory will wrap when the maximum long
is
+ * reached and return negative numbers. It will start from zero.
+ *
+ * @return a new identifier factory
+ */
+ public static StringIdentifierFactory stringNumericIdentifierFactory() {
+ return new StringNumericIdentifierFactory(true, 0L);
+ }
+
+ /**
+ * Gets a new identifier factory that returns a series of String objects
+ * representing numbers increasing in size.
+ *
+ * @param wrap should the factory wrap when it reaches the maximum
+ * long value (or throw an IllegalStateException)
+ * @param initialValue the initial long value to start at
+ * @return a new identifier factory
+ */
+ public static StringIdentifierFactory stringNumericIdentifierFactory(boolean wrap, long initialValue) {
+ return new StringNumericIdentifierFactory(wrap, initialValue);
+ }
+
+ //---------------------------------------------------------------------------------
+
+ /**
+ * Gets the next identifier using the singleton instance of the
+ * String Alphanumeric factory.
+ *
+ *
+ * The singleton instance will wrap, so in a long-lived server, the id
+ * may be duplicated.
+ *
+ * @return a new identifier
+ */
+ public static String nextStringAlphanumericIdentifier() {
+ return STRING_ALPHANUMERIC_IDENTIFIER_FACTORY.nextStringIdentifier();
+ }
+
+ /**
+ * Gets a new identifier factory that returns a series of String objects
+ * representing numbers increasing in size in base-36.
+ *
+ * The factory will wrap when the maximum size (15) is reached.
+ *
+ * @return a new identifier factory
+ */
+ public static StringIdentifierFactory stringAlphanumericIdentifierFactory() {
+ return new StringAlphanumericIdentifierFactory(true, 15);
+ }
+
+ /**
+ * Gets a new identifier factory that returns a series of String objects
+ * representing numbers increasing in size in base-36.
+ *
+ * @param wrap should the factory wrap when it reaches the maximum
+ * size (or throw an IllegalStateException)
+ * @param size the number of characters the id should fill
+ * @return a new identifier factory
+ */
+ public static StringIdentifierFactory stringAlphanumericIdentifierFactory(boolean wrap, int size) {
+ return new StringAlphanumericIdentifierFactory(wrap, size);
+ }
+
+ //---------------------------------------------------------------------------------
+
+ /**
+ * Gets the next identifier using the singleton instance of the
+ * String Session factory.
+ *
+ *
+ * The generation routine is based on a random number and a counter
+ * within a 2 second time interval.
+ *
+ * @return a new identifier
+ */
+ public static String nextStringSessionIdentifier() {
+ return STRING_SESSION_IDENTIFIER_FACTORY.nextStringIdentifier();
+ }
+
+ /**
+ * Gets a new identifier factory that returns a series of String objects
+ * that appear to be random and are suitable for use as session identifiers.
+ *
+ *
+ * The generation routine is based on a random number and a counter
+ * within a 2 second time interval.
+ *
+ * @return a new identifier factory
+ */
+ public static StringIdentifierFactory stringSessionIdentifierFactory() {
+ return new StringSessionIdentifierFactory();
+ }
+
+ //---------------------------------------------------------------------------------
+
+ /**
+ * LongIdentifierFactory
is an Identifier Factory
+ * that generates an incrementing number as a Long object.
+ *
+ * @author Stephen Colebourne
+ */
+ private static class LongNumericIdentifierFactory implements LongIdentifierFactory, Serializable {
+
+ /** Should the counter wrap. */
+ private final boolean wrap;
+ /** The counter. */
+ private long count = 0;
+
+ /**
+ * Constructor.
+ *
+ * @param wrap should the factory wrap when it reaches the maximum
+ * long value (or throw an exception)
+ * @param initialValue the initial long value to start at
+ */
+ private LongNumericIdentifierFactory(boolean wrap, long initialValue) {
+ super();
+ this.wrap = wrap;
+ this.count = initialValue;
+ }
+
+ /**
+ * Gets the next new identifier.
+ *
+ * @return a new identifier as a Long
+ */
+ public Object nextIdentifier() {
+ return nextLongIdentifier();
+ }
+
+ /**
+ * Gets the next new identifier.
+ *
+ * @return a new identifier as a Long
+ */
+ public Long nextLongIdentifier() {
+ long value = 0;
+ if (wrap) {
+ synchronized (this) {
+ value = count++;
+ }
+ } else {
+ synchronized (this) {
+ if (count == Long.MAX_VALUE) {
+ throw new IllegalStateException("The maximum number of identifiers has been reached");
+ }
+ value = count++;
+ }
+ }
+ return new Long(value);
+ }
+ }
+
+ //---------------------------------------------------------------------------------
+
+ /**
+ * StringNumericIdentifierFactory
is an Identifier Factory
+ * that generates an incrementing number as a String object.
+ *
+ * @author Stephen Colebourne
+ */
+ private static class StringNumericIdentifierFactory implements StringIdentifierFactory, Serializable {
+
+ /** Should the counter wrap. */
+ private final boolean wrap;
+ /** The counter. */
+ private long count = 0;
+
+ /**
+ * Constructor.
+ *
+ * @param wrap should the factory wrap when it reaches the maximum
+ * long value (or throw an exception)
+ * @param initialValue the initial long value to start at
+ */
+ private StringNumericIdentifierFactory(boolean wrap, long initialValue) {
+ super();
+ this.wrap = wrap;
+ this.count = initialValue;
+ }
+
+ /**
+ * Gets the next new identifier.
+ *
+ * @return a new identifier as a String
+ */
+ public Object nextIdentifier() {
+ return nextStringIdentifier();
+ }
+
+ /**
+ * Gets the next new identifier.
+ *
+ * @return a new identifier as a String
+ */
+ public String nextStringIdentifier() {
+ long value = 0;
+ if (wrap) {
+ synchronized (this) {
+ value = count++;
+ }
+ } else {
+ synchronized (this) {
+ if (count == Long.MAX_VALUE) {
+ throw new IllegalStateException("The maximum number of identifiers has been reached");
+ }
+ value = count++;
+ }
+ }
+ return Long.toString(value);
+ }
+
+ }
+
+ //---------------------------------------------------------------------------------
+
+ /**
+ * StringAlphanumericIdentifierFactory
is an Identifier Factory
+ * that generates an incrementing incrementing number in base 36 as a String
+ * object.
+ *
+ * @author Stephen Colebourne
+ */
+ private static class StringAlphanumericIdentifierFactory implements StringIdentifierFactory, Serializable {
+
+ /** Should the counter wrap. */
+ private final boolean wrap;
+ /** The counter. */
+ private char[] count = null;
+
+ /**
+ * Constructor.
+ *
+ * @param wrap should the factory wrap when it reaches the maximum
+ * long value (or throw an exception)
+ * @param size the size of the identifier
+ */
+ private StringAlphanumericIdentifierFactory(boolean wrap, int size) {
+ super();
+ this.wrap = wrap;
+ if (size < 1) {
+ throw new IllegalArgumentException("The size must be at least one");
+ }
+ this.count = new char[size];
+ for (int i = 0; i < size; i++) {
+ count[i] = '0'; // zero
+ }
+ }
+
+ /**
+ * Gets the next new identifier.
+ *
+ * @return a new identifier as a String
+ */
+ public Object nextIdentifier() {
+ return nextStringIdentifier();
+ }
+
+ /**
+ * Gets the next new identifier.
+ *
+ * @return a new identifier as a String
+ */
+ public synchronized String nextStringIdentifier() {
+ for (int i = count.length - 1; i >= 0; i--) {
+ switch (count[i]) {
+ case 122: // z
+ count[i] = '0';
+ if (i == 0 && wrap == false) {
+ throw new IllegalStateException("The maximum number of identifiers has been reached");
+ }
+ break;
+
+ case 57: // 9
+ count[i] = 'a';
+ i = -1;
+ break;
+
+ default:
+ count[i]++;
+ i = -1;
+ break;
+ }
+ }
+ return new String(count);
+ }
+
+ }
+
+ //---------------------------------------------------------------------------------
+
+ /**
+ * StringSessionIdentifierFactory
is an Identifier
+ * Factory that generates an alphanumeric 10+ character identifier. The
+ * exact length depends on the number of ids requested per time period.
+ *
+ * Originally designed for JServ sessions. Uses synchronized count and
+ * time to ensure uniqueness. Not guaranteed unique across JVMs, but
+ * fairly safe none the less.
+ *
+ * @author Jon S. Stevens
+ * @author Neeme Praks
+ * @author Stephen Colebourne
+ */
+ private static class StringSessionIdentifierFactory implements StringIdentifierFactory, Serializable {
+
+ /**
+ * We want to have a random string with a length of 6 characters.
+ * Since we encode it base-36, we modulo the random number with
+ * this value.
+ */
+ private static final long MAX_RANDOM_LEN = 2176782336L; // 36 ** 6
+ /**
+ * The identifier must be unique within the typical lifespan of a
+ * session; the value can roll over after that.
3 characters:
+ * (this means a roll over after over a day, which is much larger
+ * than a typical lifespan).
+ */
+ private static final long MAX_TIME_SECTION_LEN = 46656L; // 36 ** 3
+ /**
+ * Milliseconds between different tics. The 3-character time
+ * string has a new value every 2 seconds.
+ */
+ private static final long TIC_DIFFERENCE = 2000;
+
+ /** The incrementing counter. */
+ private int counter = 0;
+ /** The last time. */
+ private long lastTimeValue = 0;
+ /** The randmonizer. */
+ private Random randomizer = new Random();
+
+ /**
+ * Constructor.
+ */
+ private StringSessionIdentifierFactory() {
+ super();
+ }
+
+ /**
+ * Gets the next identifier.
+ *
+ * @return the next 10 char String identifier
+ */
+ public Object nextIdentifier() {
+ return nextStringIdentifier();
+ }
+
+ /**
+ * Gets the next new identifier. Only guaranteed unique within
+ * this JVM, but fairly safe for cross JVM usage as well.
+ *
+ * Format of identifier is
+ * [6 chars random][3 chars time][1+ chars count]
+ *
+ * @return the next 10 char String identifier
+ */
+ public String nextStringIdentifier() {
+ // Random value
+ //--------------
+ long currentRandom = randomizer.nextLong();
+ if (currentRandom < 0) {
+ currentRandom = -currentRandom;
+ }
+ // force value into 6 char range, and add to pad with zeros
+ // this gives a length of 7, when converted to base 36, and
+ // the first character (always 1 from the add) is dropped
+ currentRandom %= MAX_RANDOM_LEN;
+ currentRandom += MAX_RANDOM_LEN;
+
+ long currentTimeValue = 0;
+ int currentCount = 0;
+
+ synchronized (this) {
+ // Time
+ //--------------
+ currentTimeValue = (System.currentTimeMillis() / TIC_DIFFERENCE);
+
+ // force value into 3 char range, and add to pad with zeros
+ // this gives a length of 4, when converted to base 36, and
+ // the first character (always 1 from the add) is dropped
+ currentTimeValue %= MAX_TIME_SECTION_LEN;
+ currentTimeValue += MAX_TIME_SECTION_LEN;
+
+ // Count
+ //--------------
+ // Make the string unique by appending the count since last
+ // time flip.
+
+ // Count sessions only within tics (so the 'real' counter
+ // isn't exposed to the public).
+ if (lastTimeValue != currentTimeValue) {
+ lastTimeValue = currentTimeValue;
+ counter = 0;
+ }
+ currentCount = counter++;
+ }
+
+ // build string
+ //--------------
+ StringBuffer id = new StringBuffer(15);
+ id.append(Long.toString(currentRandom, 36).substring(1)); // 6 chars
+ id.append(Long.toString(currentTimeValue, 36).substring(1)); // 3 chars
+ id.append(Long.toString(currentCount, 36)); // 1+ chars
+ return id.toString();
+ }
+
+ }
+
+}
diff --git a/examples/cl2/src/java/org/apache/commons/lang/util/LongIdentifierFactory.java b/examples/cl2/src/java/org/apache/commons/lang/util/LongIdentifierFactory.java
new file mode 100644
index 00000000..91ed477f
--- /dev/null
+++ b/examples/cl2/src/java/org/apache/commons/lang/util/LongIdentifierFactory.java
@@ -0,0 +1,73 @@
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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
+ * .
+ */
+package org.apache.commons.lang.util;
+
+/**
+ * LongIdentifierFactory
defines a simple interface for
+ * Long based identifier generation.
+ *
+ * @author Stephen Colebourne
+ * @since 2.0
+ * @version $Id: LongIdentifierFactory.java,v 1.1 2003/05/16 22:06:43 scolebourne Exp $
+ */
+public interface LongIdentifierFactory extends IdentifierFactory {
+
+ /**
+ * Gets the next identifier in the sequence.
+ *
+ * @return the next Long identifier in sequence
+ */
+ Long nextLongIdentifier();
+
+}
diff --git a/examples/cl2/src/java/org/apache/commons/lang/util/StringIdentifierFactory.java b/examples/cl2/src/java/org/apache/commons/lang/util/StringIdentifierFactory.java
new file mode 100644
index 00000000..41d38563
--- /dev/null
+++ b/examples/cl2/src/java/org/apache/commons/lang/util/StringIdentifierFactory.java
@@ -0,0 +1,73 @@
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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
+ * .
+ */
+package org.apache.commons.lang.util;
+
+/**
+ * StringIdentifierFactory
defines a simple interface for
+ * String based identifier generation.
+ *
+ * @author Stephen Colebourne
+ * @since 2.0
+ * @version $Id: StringIdentifierFactory.java,v 1.1 2003/05/16 22:06:43 scolebourne Exp $
+ */
+public interface StringIdentifierFactory extends IdentifierFactory {
+
+ /**
+ * Gets the next identifier in the sequence.
+ *
+ * @return the next String identifier in sequence
+ */
+ String nextStringIdentifier();
+
+}
diff --git a/examples/cl2/src/java/org/apache/commons/lang/util/Validate.java b/examples/cl2/src/java/org/apache/commons/lang/util/Validate.java
new file mode 100644
index 00000000..e13a0338
--- /dev/null
+++ b/examples/cl2/src/java/org/apache/commons/lang/util/Validate.java
@@ -0,0 +1,477 @@
+/* ====================================================================
+ * 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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
+ * .
+ */
+package org.apache.commons.lang.util;
+
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.Map;
+/**
+ * Validate is a static utility class for validating arguments.
+ *
+ *
The class is based along the lines of JUnit. If an argument value is
+ * deemed invalid, an IllegalArgumentException is thrown. For example:
+ *
+ *
+ * Validate.isTrue( i > 0, "The value must be greater than zero: ", i);
+ * Validate.notNull( surname, "The surname must not be null");
+ *
+ *
+ * @author Ola Berg
+ * @author Stephen Colebourne
+ * @since 2.0
+ * @version $Id: Validate.java,v 1.2 2003/03/23 17:52:25 scolebourne Exp $
+ */
+public class Validate {
+
+ /**
+ * Constructor. This class should not normally be instantiated.
+ */
+ public Validate() {
+ }
+
+ // 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.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.
+ *
+ * @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
+ * @throws IllegalArgumentException if expression is false
+ */
+ public static void isTrue(boolean expression, String message, Object value) {
+ if (expression == false) {
+ throw new IllegalArgumentException(message + value);
+ }
+ }
+
+ /**
+ *
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.isTrue( i > 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.
+ *
+ * @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
+ * @throws IllegalArgumentException if expression is false
+ */
+ public static void isTrue(boolean expression, String message, long value) {
+ if (expression == false) {
+ throw new IllegalArgumentException(message + value);
+ }
+ }
+
+ /**
+ *
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.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.
+ *
+ * @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
+ * @throws IllegalArgumentException if expression is false
+ */
+ public static void isTrue(boolean expression, String message, double value) {
+ if (expression == false) {
+ throw new IllegalArgumentException(message + value);
+ }
+ }
+
+ /**
+ *
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.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
+ * @throws IllegalArgumentException if expression is false
+ */
+ public static void isTrue(boolean expression, String message) {
+ if (expression == false) {
+ throw new IllegalArgumentException(message);
+ }
+ }
+
+ /**
+ *
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.isTrue( i > 0 );
+ * Validate.isTrue( myObject.isOk() );
+ *
+ * The message in the exception is 'The validated expression is false'.
+ *
+ * @param expression a boolean expression
+ * @throws IllegalArgumentException if expression is false
+ */
+ public static void isTrue(boolean expression) {
+ if (expression == false) {
+ throw new IllegalArgumentException("The validated expression is false");
+ }
+ }
+
+ // notNull
+ //---------------------------------------------------------------------------------
+
+ /**
+ *
Validate an argument, throwing IllegalArgumentException if the
+ * argument is null.
+ *
+ * Validate.notNull(myObject, "The object must not be 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
+ * @throws IllegalArgumentException if the object is null
+ */
+ public static void notNull(Object object, String message) {
+ if (object == null) {
+ throw new IllegalArgumentException(message);
+ }
+ }
+
+ /**
+ * Validate an argument, throwing IllegalArgumentException if the
+ * argument is null.
+ *
+ * Validate.notNull(myObject);
+ *
+ * The message in the exception is 'The validated object is null'.
+ *
+ * @param object the object to check is not null
+ * @throws IllegalArgumentException if the object is null
+ */
+ public static void notNull(Object object) {
+ if (object == null) {
+ throw new IllegalArgumentException("The validated object is null");
+ }
+ }
+
+ // notEmpty array
+ //---------------------------------------------------------------------------------
+
+ /**
+ *
Validate an argument, throwing IllegalArgumentException if the
+ * argument array is empty (null or no elements).
+ *
+ * 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
+ * @throws IllegalArgumentException if the array is empty
+ */
+ public static void notEmpty(Object[] array, String message) {
+ if (array == null || array.length == 0) {
+ throw new IllegalArgumentException(message);
+ }
+ }
+
+ /**
+ * Validate an argument, throwing IllegalArgumentException if the
+ * argument array is empty (null or no elements).
+ *
+ * Validate.notEmpty(myArray);
+ *
+ * The message in the exception is 'The validated array is empty'.
+ *
+ * @param array the array to check is not empty
+ * @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 collection
+ //---------------------------------------------------------------------------------
+
+ /**
+ *
Validate an argument, throwing IllegalArgumentException if the
+ * argument Collection is empty (null or no elements).
+ *
+ * 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
+ * @throws IllegalArgumentException if the collection is empty
+ */
+ public static void notEmpty(Collection collection, String message) {
+ if (collection == null || collection.size() == 0) {
+ throw new IllegalArgumentException(message);
+ }
+ }
+
+ /**
+ * Validate an argument, throwing IllegalArgumentException if the
+ * argument Collection is empty (null or no elements).
+ *
+ * Validate.notEmpty(myCollection);
+ *
+ * The message in the exception is 'The validated collection is empty'.
+ *
+ * @param collection the collection to check is not empty
+ * @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 map
+ //---------------------------------------------------------------------------------
+
+ /**
+ *
Validate an argument, throwing IllegalArgumentException if the
+ * argument Map is empty (null or no elements).
+ *
+ * Validate.notEmpty(myMap, "The collection 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
+ * @throws IllegalArgumentException if the map is empty
+ */
+ public static void notEmpty(Map map, String message) {
+ if (map == null || map.size() == 0) {
+ throw new IllegalArgumentException(message);
+ }
+ }
+
+ /**
+ * Validate an argument, throwing IllegalArgumentException if the
+ * argument Map is empty (null or no elements).
+ *
+ * Validate.notEmpty(myMap);
+ *
+ * The message in the exception is 'The validated map is empty'.
+ *
+ * @param map the map to check is not empty
+ * @throws IllegalArgumentException if the map is empty
+ */
+ public static void notEmpty(Map map) {
+ if (map == null || map.size() == 0) {
+ throw new IllegalArgumentException("The validated map is empty");
+ }
+ }
+
+ // notEmpty string
+ //---------------------------------------------------------------------------------
+
+ /**
+ *
Validate an argument, throwing IllegalArgumentException if the
+ * argument String is empty (null or zero length).
+ *
+ * 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
+ * @throws IllegalArgumentException if the string is empty
+ */
+ public static void notEmpty(String string, String message) {
+ if (string == null || string.length() == 0) {
+ throw new IllegalArgumentException(message);
+ }
+ }
+
+ /**
+ * Validate an argument, throwing IllegalArgumentException if the
+ * argument String is empty (null or zero length).
+ *
+ * Validate.notEmpty(myString);
+ *
+ * The message in the exception is 'The validated string is empty'.
+ *
+ * @param string the string to check is not empty
+ * @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");
+ }
+ }
+
+ // notNullElements array
+ //---------------------------------------------------------------------------------
+
+ /**
+ *
Validate an argument, throwing IllegalArgumentException if the
+ * argument array has null elements or is null.
+ *
+ * Validate.notEmpty(myArray, "The array must not contain null elements");
+ *
+ *
+ * @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
+ */
+ public static void noNullElements(Object[] array, String message) {
+ Validate.notNull(array);
+ for (int i = 0; i < array.length; i++) {
+ if (array[i] == null) {
+ throw new IllegalArgumentException(message);
+ }
+ }
+ }
+
+ /**
+ * Validate an argument, throwing IllegalArgumentException if the
+ * argument array has null elements or is null.
+ *
+ * Validate.notEmpty(myArray);
+ *
+ * The message in the exception is 'The validated array contains null element at index: '.
+ *
+ * @param array the array to check
+ * @throws IllegalArgumentException if the array has null elements or is null
+ */
+ public static void noNullElements(Object[] array) {
+ Validate.notNull(array);
+ for (int i = 0; i < array.length; i++) {
+ if (array[i] == null) {
+ throw new IllegalArgumentException("The validated array contains null element at index: " + i);
+ }
+ }
+ }
+
+ // notNullElements collection
+ //---------------------------------------------------------------------------------
+
+ /**
+ *
Validate an argument, throwing IllegalArgumentException if the
+ * argument collection has null elements or is null.
+ *
+ * Validate.notEmpty(myCollection, "The collection must not contain null elements");
+ *
+ *
+ * @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
+ */
+ public static void noNullElements(Collection collection, String message) {
+ Validate.notNull(collection);
+ int i = 0;
+ for (Iterator it = collection.iterator(); it.hasNext(); i++) {
+ if (it.next() == null) {
+ throw new IllegalArgumentException(message);
+ }
+ }
+ }
+
+ /**
+ * Validate an argument, throwing IllegalArgumentException if the
+ * argument collection has null elements or is null.
+ *
+ * Validate.notEmpty(myCollection);
+ *
+ * The message in the exception is 'The validated collection contains null element at index: '.
+ *
+ * @param collection the collection to check
+ * @throws IllegalArgumentException if the collection has null elements or 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("The validated collection contains null element at index: " + i);
+ }
+ }
+ }
+
+}
diff --git a/examples/cl2/src/test/org/apache/commons/lang/AllLangTestSuite.java b/examples/cl2/src/test/org/apache/commons/lang/AllLangTestSuite.java
new file mode 100644
index 00000000..7e6cf71e
--- /dev/null
+++ b/examples/cl2/src/test/org/apache/commons/lang/AllLangTestSuite.java
@@ -0,0 +1,105 @@
+/* ====================================================================
+ * 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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
+ * .
+ */
+package org.apache.commons.lang;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import junit.textui.TestRunner;
+
+import org.apache.commons.lang.builder.BuilderTestSuite;
+import org.apache.commons.lang.enums.EnumTestSuite;
+import org.apache.commons.lang.exception.ExceptionTestSuite;
+import org.apache.commons.lang.math.MathTestSuite;
+import org.apache.commons.lang.time.TimeTestSuite;
+import org.apache.commons.lang.util.UtilTestSuite;
+
+/**
+ * Test suite for [lang].
+ *
+ * @author Stephen Colebourne
+ * @version $Id: AllLangTestSuite.java,v 1.1 2003/06/10 06:20:19 scolebourne Exp $
+ */
+public class AllLangTestSuite extends TestCase {
+
+ /**
+ * Construct a new instance.
+ */
+ public AllLangTestSuite(String name) {
+ super(name);
+ }
+
+ /**
+ * Command-line interface.
+ */
+ public static void main(String[] args) {
+ TestRunner.run(suite());
+ }
+
+ /**
+ * Get the suite of tests
+ */
+ public static Test suite() {
+ TestSuite suite = new TestSuite();
+ suite.setName("Commons-Lang (all) Tests");
+ suite.addTest(LangTestSuite.suite());
+ suite.addTest(BuilderTestSuite.suite());
+ suite.addTest(EnumTestSuite.suite());
+ suite.addTest(ExceptionTestSuite.suite());
+ suite.addTest(MathTestSuite.suite());
+ suite.addTest(TimeTestSuite.suite());
+ suite.addTest(UtilTestSuite.suite());
+ return suite;
+ }
+}
diff --git a/examples/cl2/src/test/org/apache/commons/lang/ArrayUtilsTest.java b/examples/cl2/src/test/org/apache/commons/lang/ArrayUtilsTest.java
new file mode 100644
index 00000000..c531e51e
--- /dev/null
+++ b/examples/cl2/src/test/org/apache/commons/lang/ArrayUtilsTest.java
@@ -0,0 +1,709 @@
+/* ====================================================================
+ * 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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
+ * .
+ */
+package org.apache.commons.lang;
+
+import java.util.Arrays;
+import java.util.Map;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import junit.textui.TestRunner;
+
+/**
+ * Unit tests {@link org.apache.commons.lang.ArrayUtils}.
+ *
+ * @author Stephen Colebourne
+ * @author Moritz Petersen
+ * @author Nikolay Metchev
+ * @version $Id: ArrayUtilsTest.java,v 1.6 2003/03/23 21:47:30 scolebourne Exp $
+ */
+public class ArrayUtilsTest extends TestCase {
+
+ public ArrayUtilsTest(String name) {
+ super(name);
+ }
+
+ public static void main(String[] args) {
+ TestRunner.run(suite());
+ }
+
+ public static Test suite() {
+ TestSuite suite = new TestSuite(ArrayUtilsTest.class);
+ suite.setName("ArrayUtils Tests");
+ return suite;
+ }
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ //-----------------------------------------------------------------------
+ public void testToString() {
+ assertEquals("{}", ArrayUtils.toString(null));
+ assertEquals("{}", ArrayUtils.toString(new Object[0]));
+ assertEquals("{}", ArrayUtils.toString(new String[0]));
+ assertEquals("{}", ArrayUtils.toString(new String[] {null}));
+ assertEquals("{pink,blue}", ArrayUtils.toString(new String[] {"pink","blue"}));
+
+ assertEquals("", ArrayUtils.toString(null, ""));
+ assertEquals("{}", ArrayUtils.toString(new Object[0], ""));
+ assertEquals("{}", ArrayUtils.toString(new String[0], ""));
+ assertEquals("{}", ArrayUtils.toString(new String[] {null}, ""));
+ assertEquals("{pink,blue}", ArrayUtils.toString(new String[] {"pink","blue"}, ""));
+ }
+
+ //-----------------------------------------------------------------------
+ public void testHashCode() {
+ long[][] array1 = new long[][] {{2,5}, {4,5}};
+ long[][] array2 = new long[][] {{2,5}, {4,6}};
+ assertEquals(true, ArrayUtils.hashCode(array1) == ArrayUtils.hashCode(array1));
+ assertEquals(false, ArrayUtils.hashCode(array1) == ArrayUtils.hashCode(array2));
+
+ Object[] array3 = new Object[] {new String(new char[] {'A', 'B'})};
+ Object[] array4 = new Object[] {"AB"};
+ assertEquals(true, ArrayUtils.hashCode(array3) == ArrayUtils.hashCode(array3));
+ assertEquals(true, ArrayUtils.hashCode(array3) == ArrayUtils.hashCode(array4));
+ }
+
+ //-----------------------------------------------------------------------
+ public void testIsEquals() {
+ long[][] array1 = new long[][] {{2,5}, {4,5}};
+ long[][] array2 = new long[][] {{2,5}, {4,6}};
+ assertEquals(true, ArrayUtils.isEquals(array1, array1));
+ assertEquals(false, ArrayUtils.isEquals(array1, array2));
+
+ Object[] array3 = new Object[] {new String(new char[] {'A', 'B'})};
+ Object[] array4 = new Object[] {"AB"};
+ assertEquals(true, ArrayUtils.isEquals(array3, array3));
+ assertEquals(true, ArrayUtils.isEquals(array3, array4));
+ }
+
+ //-----------------------------------------------------------------------
+ public void testToMap() {
+ Map map = ArrayUtils.toMap(new String[][] {{"foo", "bar"}, {"hello", "world"}});
+
+ assertEquals("bar", map.get("foo"));
+ assertEquals("world", map.get("hello"));
+
+ try {
+ ArrayUtils.toMap(null);
+ fail("exception expected");
+ } catch (IllegalArgumentException ex) {}
+ try {
+ ArrayUtils.toMap(new String[][] {{"foo", "bar"}, {"short"}});
+ fail("exception expected");
+ } catch (IllegalArgumentException ex) {}
+ try {
+ ArrayUtils.toMap(new Object[] {new Object[] {"foo", "bar"}, "illegal type"});
+ fail("exception expected");
+ } catch (IllegalArgumentException ex) {}
+ try {
+ ArrayUtils.toMap(new Object[] {new Object[] {"foo", "bar"}, null});
+ fail("exception expected");
+ } catch (IllegalArgumentException ex) {}
+
+ map = ArrayUtils.toMap(new Object[] {new Map.Entry() {
+ public Object getKey() {
+ return "foo";
+ }
+ public Object getValue() {
+ return "bar";
+ }
+ public Object setValue(Object value) {
+ throw new UnsupportedOperationException();
+ }
+ public boolean equals(Object o) {
+ throw new UnsupportedOperationException();
+ }
+ public int hashCode() {
+ throw new UnsupportedOperationException();
+ }
+ }});
+ assertEquals("bar", map.get("foo"));
+ }
+
+ //-----------------------------------------------------------------------
+ public void testClone() {
+ assertEquals(null, ArrayUtils.clone((Object[]) null));
+ Object[] original1 = new Object[0];
+ Object[] cloned1 = ArrayUtils.clone(original1);
+ assertTrue(Arrays.equals(original1, cloned1));
+ assertTrue(original1 != cloned1);
+
+ StringBuffer buf = new StringBuffer("pick");
+ original1 = new Object[] {buf, "a", new String[] {"stick"}};
+ cloned1 = ArrayUtils.clone(original1);
+ assertTrue(Arrays.equals(original1, cloned1));
+ assertTrue(original1 != cloned1);
+ assertSame(original1[0], cloned1[0]);
+ assertSame(original1[1], cloned1[1]);
+ assertSame(original1[2], cloned1[2]);
+ }
+
+ public void testCloneBoolean() {
+ boolean[] original = new boolean[] {true, false};
+ boolean[] cloned = ArrayUtils.clone(original);
+ assertTrue(Arrays.equals(original, cloned));
+ assertTrue(original != cloned);
+ }
+
+ public void testCloneLong() {
+ long[] original = new long[] {0L, 1L};
+ long[] cloned = ArrayUtils.clone(original);
+ assertTrue(Arrays.equals(original, cloned));
+ assertTrue(original != cloned);
+ }
+
+ public void testCloneInt() {
+ int[] original = new int[] {5, 8};
+ int[] cloned = ArrayUtils.clone(original);
+ assertTrue(Arrays.equals(original, cloned));
+ assertTrue(original != cloned);
+ }
+
+ public void testCloneShort() {
+ short[] original = new short[] {1, 4};
+ short[] cloned = ArrayUtils.clone(original);
+ assertTrue(Arrays.equals(original, cloned));
+ assertTrue(original != cloned);
+ }
+
+ public void testCloneChar() {
+ char[] original = new char[] {'a', '4'};
+ char[] cloned = ArrayUtils.clone(original);
+ assertTrue(Arrays.equals(original, cloned));
+ assertTrue(original != cloned);
+ }
+
+ public void testCloneByte() {
+ byte[] original = new byte[] {1, 6};
+ byte[] cloned = ArrayUtils.clone(original);
+ assertTrue(Arrays.equals(original, cloned));
+ assertTrue(original != cloned);
+ }
+
+ public void testCloneDouble() {
+ double[] original = new double[] {2.4d, 5.7d};
+ double[] cloned = ArrayUtils.clone(original);
+ assertTrue(Arrays.equals(original, cloned));
+ assertTrue(original != cloned);
+ }
+
+ public void testCloneFloat() {
+ float[] original = new float[] {2.6f, 6.4f};
+ float[] cloned = ArrayUtils.clone(original);
+ assertTrue(Arrays.equals(original, cloned));
+ assertTrue(original != cloned);
+ }
+
+ //-----------------------------------------------------------------------
+ public void testSameLength() {
+ Object[] nullArray = null;
+ Object[] emptyArray = new Object[0];
+ Object[] oneArray = new Object[] {"pick"};
+ Object[] twoArray = new Object[] {"pick", "stick"};
+
+ assertEquals(true, ArrayUtils.isSameLength(nullArray, nullArray));
+ assertEquals(true, ArrayUtils.isSameLength(nullArray, emptyArray));
+ assertEquals(false, ArrayUtils.isSameLength(nullArray, oneArray));
+ assertEquals(false, ArrayUtils.isSameLength(nullArray, twoArray));
+
+ assertEquals(true, ArrayUtils.isSameLength(emptyArray, nullArray));
+ assertEquals(true, ArrayUtils.isSameLength(emptyArray, emptyArray));
+ assertEquals(false, ArrayUtils.isSameLength(emptyArray, oneArray));
+ assertEquals(false, ArrayUtils.isSameLength(emptyArray, twoArray));
+
+ assertEquals(false, ArrayUtils.isSameLength(oneArray, nullArray));
+ assertEquals(false, ArrayUtils.isSameLength(oneArray, emptyArray));
+ assertEquals(true, ArrayUtils.isSameLength(oneArray, oneArray));
+ assertEquals(false, ArrayUtils.isSameLength(oneArray, twoArray));
+
+ assertEquals(false, ArrayUtils.isSameLength(twoArray, nullArray));
+ assertEquals(false, ArrayUtils.isSameLength(twoArray, emptyArray));
+ assertEquals(false, ArrayUtils.isSameLength(twoArray, oneArray));
+ assertEquals(true, ArrayUtils.isSameLength(twoArray, twoArray));
+ }
+
+ public void testSameLengthBoolean() {
+ boolean[] nullArray = null;
+ boolean[] emptyArray = new boolean[0];
+ boolean[] oneArray = new boolean[] {true};
+ boolean[] twoArray = new boolean[] {true, false};
+
+ assertEquals(true, ArrayUtils.isSameLength(nullArray, nullArray));
+ assertEquals(true, ArrayUtils.isSameLength(nullArray, emptyArray));
+ assertEquals(false, ArrayUtils.isSameLength(nullArray, oneArray));
+ assertEquals(false, ArrayUtils.isSameLength(nullArray, twoArray));
+
+ assertEquals(true, ArrayUtils.isSameLength(emptyArray, nullArray));
+ assertEquals(true, ArrayUtils.isSameLength(emptyArray, emptyArray));
+ assertEquals(false, ArrayUtils.isSameLength(emptyArray, oneArray));
+ assertEquals(false, ArrayUtils.isSameLength(emptyArray, twoArray));
+
+ assertEquals(false, ArrayUtils.isSameLength(oneArray, nullArray));
+ assertEquals(false, ArrayUtils.isSameLength(oneArray, emptyArray));
+ assertEquals(true, ArrayUtils.isSameLength(oneArray, oneArray));
+ assertEquals(false, ArrayUtils.isSameLength(oneArray, twoArray));
+
+ assertEquals(false, ArrayUtils.isSameLength(twoArray, nullArray));
+ assertEquals(false, ArrayUtils.isSameLength(twoArray, emptyArray));
+ assertEquals(false, ArrayUtils.isSameLength(twoArray, oneArray));
+ assertEquals(true, ArrayUtils.isSameLength(twoArray, twoArray));
+ }
+
+ public void testSameLengthLong() {
+ long[] nullArray = null;
+ long[] emptyArray = new long[0];
+ long[] oneArray = new long[] {0L};
+ long[] twoArray = new long[] {0L, 76L};
+
+ assertEquals(true, ArrayUtils.isSameLength(nullArray, nullArray));
+ assertEquals(true, ArrayUtils.isSameLength(nullArray, emptyArray));
+ assertEquals(false, ArrayUtils.isSameLength(nullArray, oneArray));
+ assertEquals(false, ArrayUtils.isSameLength(nullArray, twoArray));
+
+ assertEquals(true, ArrayUtils.isSameLength(emptyArray, nullArray));
+ assertEquals(true, ArrayUtils.isSameLength(emptyArray, emptyArray));
+ assertEquals(false, ArrayUtils.isSameLength(emptyArray, oneArray));
+ assertEquals(false, ArrayUtils.isSameLength(emptyArray, twoArray));
+
+ assertEquals(false, ArrayUtils.isSameLength(oneArray, nullArray));
+ assertEquals(false, ArrayUtils.isSameLength(oneArray, emptyArray));
+ assertEquals(true, ArrayUtils.isSameLength(oneArray, oneArray));
+ assertEquals(false, ArrayUtils.isSameLength(oneArray, twoArray));
+
+ assertEquals(false, ArrayUtils.isSameLength(twoArray, nullArray));
+ assertEquals(false, ArrayUtils.isSameLength(twoArray, emptyArray));
+ assertEquals(false, ArrayUtils.isSameLength(twoArray, oneArray));
+ assertEquals(true, ArrayUtils.isSameLength(twoArray, twoArray));
+ }
+
+ public void testSameLengthInt() {
+ int[] nullArray = null;
+ int[] emptyArray = new int[0];
+ int[] oneArray = new int[] {4};
+ int[] twoArray = new int[] {5, 7};
+
+ assertEquals(true, ArrayUtils.isSameLength(nullArray, nullArray));
+ assertEquals(true, ArrayUtils.isSameLength(nullArray, emptyArray));
+ assertEquals(false, ArrayUtils.isSameLength(nullArray, oneArray));
+ assertEquals(false, ArrayUtils.isSameLength(nullArray, twoArray));
+
+ assertEquals(true, ArrayUtils.isSameLength(emptyArray, nullArray));
+ assertEquals(true, ArrayUtils.isSameLength(emptyArray, emptyArray));
+ assertEquals(false, ArrayUtils.isSameLength(emptyArray, oneArray));
+ assertEquals(false, ArrayUtils.isSameLength(emptyArray, twoArray));
+
+ assertEquals(false, ArrayUtils.isSameLength(oneArray, nullArray));
+ assertEquals(false, ArrayUtils.isSameLength(oneArray, emptyArray));
+ assertEquals(true, ArrayUtils.isSameLength(oneArray, oneArray));
+ assertEquals(false, ArrayUtils.isSameLength(oneArray, twoArray));
+
+ assertEquals(false, ArrayUtils.isSameLength(twoArray, nullArray));
+ assertEquals(false, ArrayUtils.isSameLength(twoArray, emptyArray));
+ assertEquals(false, ArrayUtils.isSameLength(twoArray, oneArray));
+ assertEquals(true, ArrayUtils.isSameLength(twoArray, twoArray));
+ }
+
+ public void testSameLengthShort() {
+ short[] nullArray = null;
+ short[] emptyArray = new short[0];
+ short[] oneArray = new short[] {4};
+ short[] twoArray = new short[] {6, 8};
+
+ assertEquals(true, ArrayUtils.isSameLength(nullArray, nullArray));
+ assertEquals(true, ArrayUtils.isSameLength(nullArray, emptyArray));
+ assertEquals(false, ArrayUtils.isSameLength(nullArray, oneArray));
+ assertEquals(false, ArrayUtils.isSameLength(nullArray, twoArray));
+
+ assertEquals(true, ArrayUtils.isSameLength(emptyArray, nullArray));
+ assertEquals(true, ArrayUtils.isSameLength(emptyArray, emptyArray));
+ assertEquals(false, ArrayUtils.isSameLength(emptyArray, oneArray));
+ assertEquals(false, ArrayUtils.isSameLength(emptyArray, twoArray));
+
+ assertEquals(false, ArrayUtils.isSameLength(oneArray, nullArray));
+ assertEquals(false, ArrayUtils.isSameLength(oneArray, emptyArray));
+ assertEquals(true, ArrayUtils.isSameLength(oneArray, oneArray));
+ assertEquals(false, ArrayUtils.isSameLength(oneArray, twoArray));
+
+ assertEquals(false, ArrayUtils.isSameLength(twoArray, nullArray));
+ assertEquals(false, ArrayUtils.isSameLength(twoArray, emptyArray));
+ assertEquals(false, ArrayUtils.isSameLength(twoArray, oneArray));
+ assertEquals(true, ArrayUtils.isSameLength(twoArray, twoArray));
+ }
+
+ public void testSameLengthChar() {
+ char[] nullArray = null;
+ char[] emptyArray = new char[0];
+ char[] oneArray = new char[] {'f'};
+ char[] twoArray = new char[] {'d', 't'};
+
+ assertEquals(true, ArrayUtils.isSameLength(nullArray, nullArray));
+ assertEquals(true, ArrayUtils.isSameLength(nullArray, emptyArray));
+ assertEquals(false, ArrayUtils.isSameLength(nullArray, oneArray));
+ assertEquals(false, ArrayUtils.isSameLength(nullArray, twoArray));
+
+ assertEquals(true, ArrayUtils.isSameLength(emptyArray, nullArray));
+ assertEquals(true, ArrayUtils.isSameLength(emptyArray, emptyArray));
+ assertEquals(false, ArrayUtils.isSameLength(emptyArray, oneArray));
+ assertEquals(false, ArrayUtils.isSameLength(emptyArray, twoArray));
+
+ assertEquals(false, ArrayUtils.isSameLength(oneArray, nullArray));
+ assertEquals(false, ArrayUtils.isSameLength(oneArray, emptyArray));
+ assertEquals(true, ArrayUtils.isSameLength(oneArray, oneArray));
+ assertEquals(false, ArrayUtils.isSameLength(oneArray, twoArray));
+
+ assertEquals(false, ArrayUtils.isSameLength(twoArray, nullArray));
+ assertEquals(false, ArrayUtils.isSameLength(twoArray, emptyArray));
+ assertEquals(false, ArrayUtils.isSameLength(twoArray, oneArray));
+ assertEquals(true, ArrayUtils.isSameLength(twoArray, twoArray));
+ }
+
+ public void testSameLengthByte() {
+ byte[] nullArray = null;
+ byte[] emptyArray = new byte[0];
+ byte[] oneArray = new byte[] {3};
+ byte[] twoArray = new byte[] {4, 6};
+
+ assertEquals(true, ArrayUtils.isSameLength(nullArray, nullArray));
+ assertEquals(true, ArrayUtils.isSameLength(nullArray, emptyArray));
+ assertEquals(false, ArrayUtils.isSameLength(nullArray, oneArray));
+ assertEquals(false, ArrayUtils.isSameLength(nullArray, twoArray));
+
+ assertEquals(true, ArrayUtils.isSameLength(emptyArray, nullArray));
+ assertEquals(true, ArrayUtils.isSameLength(emptyArray, emptyArray));
+ assertEquals(false, ArrayUtils.isSameLength(emptyArray, oneArray));
+ assertEquals(false, ArrayUtils.isSameLength(emptyArray, twoArray));
+
+ assertEquals(false, ArrayUtils.isSameLength(oneArray, nullArray));
+ assertEquals(false, ArrayUtils.isSameLength(oneArray, emptyArray));
+ assertEquals(true, ArrayUtils.isSameLength(oneArray, oneArray));
+ assertEquals(false, ArrayUtils.isSameLength(oneArray, twoArray));
+
+ assertEquals(false, ArrayUtils.isSameLength(twoArray, nullArray));
+ assertEquals(false, ArrayUtils.isSameLength(twoArray, emptyArray));
+ assertEquals(false, ArrayUtils.isSameLength(twoArray, oneArray));
+ assertEquals(true, ArrayUtils.isSameLength(twoArray, twoArray));
+ }
+
+ public void testSameLengthDouble() {
+ double[] nullArray = null;
+ double[] emptyArray = new double[0];
+ double[] oneArray = new double[] {1.3d};
+ double[] twoArray = new double[] {4.5d, 6.3d};
+
+ assertEquals(true, ArrayUtils.isSameLength(nullArray, nullArray));
+ assertEquals(true, ArrayUtils.isSameLength(nullArray, emptyArray));
+ assertEquals(false, ArrayUtils.isSameLength(nullArray, oneArray));
+ assertEquals(false, ArrayUtils.isSameLength(nullArray, twoArray));
+
+ assertEquals(true, ArrayUtils.isSameLength(emptyArray, nullArray));
+ assertEquals(true, ArrayUtils.isSameLength(emptyArray, emptyArray));
+ assertEquals(false, ArrayUtils.isSameLength(emptyArray, oneArray));
+ assertEquals(false, ArrayUtils.isSameLength(emptyArray, twoArray));
+
+ assertEquals(false, ArrayUtils.isSameLength(oneArray, nullArray));
+ assertEquals(false, ArrayUtils.isSameLength(oneArray, emptyArray));
+ assertEquals(true, ArrayUtils.isSameLength(oneArray, oneArray));
+ assertEquals(false, ArrayUtils.isSameLength(oneArray, twoArray));
+
+ assertEquals(false, ArrayUtils.isSameLength(twoArray, nullArray));
+ assertEquals(false, ArrayUtils.isSameLength(twoArray, emptyArray));
+ assertEquals(false, ArrayUtils.isSameLength(twoArray, oneArray));
+ assertEquals(true, ArrayUtils.isSameLength(twoArray, twoArray));
+ }
+
+ public void testSameLengthFloat() {
+ float[] nullArray = null;
+ float[] emptyArray = new float[0];
+ float[] oneArray = new float[] {2.5f};
+ float[] twoArray = new float[] {6.4f, 5.8f};
+
+ assertEquals(true, ArrayUtils.isSameLength(nullArray, nullArray));
+ assertEquals(true, ArrayUtils.isSameLength(nullArray, emptyArray));
+ assertEquals(false, ArrayUtils.isSameLength(nullArray, oneArray));
+ assertEquals(false, ArrayUtils.isSameLength(nullArray, twoArray));
+
+ assertEquals(true, ArrayUtils.isSameLength(emptyArray, nullArray));
+ assertEquals(true, ArrayUtils.isSameLength(emptyArray, emptyArray));
+ assertEquals(false, ArrayUtils.isSameLength(emptyArray, oneArray));
+ assertEquals(false, ArrayUtils.isSameLength(emptyArray, twoArray));
+
+ assertEquals(false, ArrayUtils.isSameLength(oneArray, nullArray));
+ assertEquals(false, ArrayUtils.isSameLength(oneArray, emptyArray));
+ assertEquals(true, ArrayUtils.isSameLength(oneArray, oneArray));
+ assertEquals(false, ArrayUtils.isSameLength(oneArray, twoArray));
+
+ assertEquals(false, ArrayUtils.isSameLength(twoArray, nullArray));
+ assertEquals(false, ArrayUtils.isSameLength(twoArray, emptyArray));
+ assertEquals(false, ArrayUtils.isSameLength(twoArray, oneArray));
+ assertEquals(true, ArrayUtils.isSameLength(twoArray, twoArray));
+ }
+
+ //-----------------------------------------------------------------------
+ public void testSameType() {
+ try {
+ ArrayUtils.isSameType(null, null);
+ fail();
+ } catch (IllegalArgumentException ex) {}
+ try {
+ ArrayUtils.isSameType(null, new Object[0]);
+ fail();
+ } catch (IllegalArgumentException ex) {}
+ try {
+ ArrayUtils.isSameType(new Object[0], null);
+ fail();
+ } catch (IllegalArgumentException ex) {}
+
+ assertEquals(true, ArrayUtils.isSameType(new Object[0], new Object[0]));
+ assertEquals(false, ArrayUtils.isSameType(new String[0], new Object[0]));
+ assertEquals(true, ArrayUtils.isSameType(new String[0][0], new String[0][0]));
+ assertEquals(false, ArrayUtils.isSameType(new String[0], new String[0][0]));
+ assertEquals(false, ArrayUtils.isSameType(new String[0][0], new String[0]));
+ }
+
+ //-----------------------------------------------------------------------
+ public void testReverse() {
+ StringBuffer str1 = new StringBuffer("pick");
+ String str2 = "a";
+ String[] str3 = new String[] {"stick"};
+ String str4 = "up";
+
+ Object[] array = new Object[] {str1, str2, str3};
+ ArrayUtils.reverse(array);
+ assertEquals(array[0], str3);
+ assertEquals(array[1], str2);
+ assertEquals(array[2], str1);
+
+ array = new Object[] {str1, str2, str3, str4};
+ ArrayUtils.reverse(array);
+ assertEquals(array[0], str4);
+ assertEquals(array[1], str3);
+ assertEquals(array[2], str2);
+ assertEquals(array[3], str1);
+
+ array = null;
+ ArrayUtils.reverse(array);
+ assertEquals(null, array);
+ }
+
+ public void testReverseLong() {
+ long[] array = new long[] {1L, 2L, 3L};
+ ArrayUtils.reverse(array);
+ assertEquals(array[0], 3L);
+ assertEquals(array[1], 2L);
+ assertEquals(array[2], 1L);
+
+ array = null;
+ ArrayUtils.reverse(array);
+ assertEquals(null, array);
+ }
+
+ public void testReverseInt() {
+ int[] array = new int[] {1, 2, 3};
+ ArrayUtils.reverse(array);
+ assertEquals(array[0], 3);
+ assertEquals(array[1], 2);
+ assertEquals(array[2], 1);
+
+ array = null;
+ ArrayUtils.reverse(array);
+ assertEquals(null, array);
+ }
+
+ public void testReverseShort() {
+ short[] array = new short[] {1, 2, 3};
+ ArrayUtils.reverse(array);
+ assertEquals(array[0], 3);
+ assertEquals(array[1], 2);
+ assertEquals(array[2], 1);
+
+ array = null;
+ ArrayUtils.reverse(array);
+ assertEquals(null, array);
+ }
+
+ public void testReverseChar() {
+ char[] array = new char[] {'a', 'f', 'C'};
+ ArrayUtils.reverse(array);
+ assertEquals(array[0], 'C');
+ assertEquals(array[1], 'f');
+ assertEquals(array[2], 'a');
+
+ array = null;
+ ArrayUtils.reverse(array);
+ assertEquals(null, array);
+ }
+
+ public void testReverseByte() {
+ byte[] array = new byte[] {2, 3, 4};
+ ArrayUtils.reverse(array);
+ assertEquals(array[0], 4);
+ assertEquals(array[1], 3);
+ assertEquals(array[2], 2);
+
+ array = null;
+ ArrayUtils.reverse(array);
+ assertEquals(null, array);
+ }
+
+ public void testReverseDouble() {
+ double[] array = new double[] {0.3d, 0.4d, 0.5d};
+ ArrayUtils.reverse(array);
+ assertEquals(array[0], 0.5d, 0.0d);
+ assertEquals(array[1], 0.4d, 0.0d);
+ assertEquals(array[2], 0.3d, 0.0d);
+
+ array = null;
+ ArrayUtils.reverse(array);
+ assertEquals(null, array);
+ }
+
+ public void testReverseFloat() {
+ float[] array = new float[] {0.3f, 0.4f, 0.5f};
+ ArrayUtils.reverse(array);
+ assertEquals(array[0], 0.5f, 0.0f);
+ assertEquals(array[1], 0.4f, 0.0f);
+ assertEquals(array[2], 0.3f, 0.0f);
+
+ array = null;
+ ArrayUtils.reverse(array);
+ assertEquals(null, array);
+ }
+
+ public void testReverseBoolean() {
+ boolean[] array = new boolean[] {false, false, true};
+ ArrayUtils.reverse(array);
+ assertEquals(array[0], true);
+ assertEquals(array[1], false);
+ assertEquals(array[2], false);
+
+ array = null;
+ ArrayUtils.reverse(array);
+ assertEquals(null, array);
+ }
+
+ //-----------------------------------------------------------------------
+ public void testIndexOf() {
+ Object[] array = new Object[] { "0", "1", "2", "3", null, "0" };
+ assertEquals(-1, ArrayUtils.indexOf(null, null));
+ assertEquals(-1, ArrayUtils.indexOf(null, "0"));
+ assertEquals(0, ArrayUtils.indexOf(array, "0"));
+ assertEquals(1, ArrayUtils.indexOf(array, "1"));
+ assertEquals(2, ArrayUtils.indexOf(array, "2"));
+ assertEquals(3, ArrayUtils.indexOf(array, "3"));
+ assertEquals(4, ArrayUtils.indexOf(array, null));
+ assertEquals(-1, ArrayUtils.indexOf(array, "notInArray"));
+ }
+
+ public void testIndexOfWithStartIndex() {
+ Object[] array = new Object[] { "0", "1", "2", "3", null, "0" };
+ assertEquals(-1, ArrayUtils.indexOf(null, null, 2));
+ assertEquals(-1, ArrayUtils.indexOf(null, "0", 2));
+ assertEquals(5, ArrayUtils.indexOf(array, "0", 2));
+ assertEquals(-1, ArrayUtils.indexOf(array, "1", 2));
+ assertEquals(2, ArrayUtils.indexOf(array, "2", 2));
+ assertEquals(3, ArrayUtils.indexOf(array, "3", 2));
+ assertEquals(4, ArrayUtils.indexOf(array, null, 2));
+ assertEquals(-1, ArrayUtils.indexOf(array, "notInArray"));
+
+ assertEquals(4, ArrayUtils.indexOf(array, null, -1));
+ assertEquals(-1, ArrayUtils.indexOf(array, "0", 6));
+ }
+
+ public void testLastIndexOf() {
+ Object[] array = new Object[] { "0", "1", "2", "3", null, "0" };
+ assertEquals(-1, ArrayUtils.lastIndexOf(null, null));
+ assertEquals(-1, ArrayUtils.lastIndexOf(null, "0"));
+ assertEquals(5, ArrayUtils.lastIndexOf(array, "0"));
+ assertEquals(1, ArrayUtils.lastIndexOf(array, "1"));
+ assertEquals(2, ArrayUtils.lastIndexOf(array, "2"));
+ assertEquals(3, ArrayUtils.lastIndexOf(array, "3"));
+ assertEquals(4, ArrayUtils.lastIndexOf(array, null));
+ assertEquals(-1, ArrayUtils.lastIndexOf(array, "notInArray"));
+ }
+
+ public void testLastIndexOfWithStartIndex() {
+ Object[] array = new Object[] { "0", "1", "2", "3", null, "0" };
+ assertEquals(-1, ArrayUtils.lastIndexOf(null, null, 2));
+ assertEquals(-1, ArrayUtils.lastIndexOf(null, "0", 2));
+ assertEquals(0, ArrayUtils.lastIndexOf(array, "0", 2));
+ assertEquals(1, ArrayUtils.lastIndexOf(array, "1", 2));
+ assertEquals(2, ArrayUtils.lastIndexOf(array, "2", 2));
+ assertEquals(-1, ArrayUtils.lastIndexOf(array, "3", 2));
+ assertEquals(4, ArrayUtils.lastIndexOf(array, null, 5));
+ assertEquals(-1, ArrayUtils.lastIndexOf(array, null, 2));
+ assertEquals(-1, ArrayUtils.lastIndexOf(array, "notInArray"));
+
+ assertEquals(-1, ArrayUtils.lastIndexOf(array, null, -1));
+ assertEquals(5, ArrayUtils.lastIndexOf(array, "0", 88));
+ }
+
+ public void testContains() {
+ Object[] array = new Object[] { "0", "1", "2", "3", null, "0" };
+ assertEquals(false, ArrayUtils.contains(null, null));
+ assertEquals(false, ArrayUtils.contains(null, "1"));
+ assertEquals(true, ArrayUtils.contains(array, "0"));
+ assertEquals(true, ArrayUtils.contains(array, "1"));
+ assertEquals(true, ArrayUtils.contains(array, "2"));
+ assertEquals(true, ArrayUtils.contains(array, "3"));
+ assertEquals(true, ArrayUtils.contains(array, null));
+ assertEquals(false, ArrayUtils.contains(array, "notInArray"));
+ }
+}
diff --git a/examples/cl2/src/test/org/apache/commons/lang/BooleanUtilsTest.java b/examples/cl2/src/test/org/apache/commons/lang/BooleanUtilsTest.java
new file mode 100644
index 00000000..f420efdc
--- /dev/null
+++ b/examples/cl2/src/test/org/apache/commons/lang/BooleanUtilsTest.java
@@ -0,0 +1,340 @@
+/* ====================================================================
+ * 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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
+ * .
+ */
+package org.apache.commons.lang;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import junit.textui.TestRunner;
+
+/**
+ * Unit tests {@link org.apache.commons.lang.BooleanUtils}.
+ *
+ * @author Stephen Colebourne
+ * @version $Id: BooleanUtilsTest.java,v 1.3 2003/03/23 21:47:30 scolebourne Exp $
+ */
+public class BooleanUtilsTest extends TestCase {
+
+ public BooleanUtilsTest(String name) {
+ super(name);
+ }
+
+ public static void main(String[] args) {
+ TestRunner.run(suite());
+ }
+
+ public static Test suite() {
+ TestSuite suite = new TestSuite(BooleanUtilsTest.class);
+ suite.setName("BooleanUtils Tests");
+ return suite;
+ }
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ //-----------------------------------------------------------------------
+ public void test_negate_Boolean() {
+ assertSame(null, BooleanUtils.negate(null));
+ assertSame(Boolean.TRUE, BooleanUtils.negate(Boolean.FALSE));
+ assertSame(Boolean.FALSE, BooleanUtils.negate(Boolean.TRUE));
+ }
+
+ //-----------------------------------------------------------------------
+ public void test_toBooleanObject_boolean() {
+ assertSame(Boolean.TRUE, BooleanUtils.toBooleanObject(true));
+ assertSame(Boolean.FALSE, BooleanUtils.toBooleanObject(false));
+ }
+
+ public void test_toBoolean_Boolean() {
+ assertEquals(true, BooleanUtils.toBoolean(Boolean.TRUE));
+ assertEquals(false, BooleanUtils.toBoolean(Boolean.FALSE));
+ assertEquals(false, BooleanUtils.toBoolean((Boolean) null));
+ }
+
+ public void test_toBooleanDefaultIfNull_Boolean_boolean() {
+ assertEquals(true, BooleanUtils.toBooleanDefaultIfNull(Boolean.TRUE, true));
+ assertEquals(true, BooleanUtils.toBooleanDefaultIfNull(Boolean.TRUE, false));
+ assertEquals(false, BooleanUtils.toBooleanDefaultIfNull(Boolean.FALSE, true));
+ assertEquals(false, BooleanUtils.toBooleanDefaultIfNull(Boolean.FALSE, false));
+ assertEquals(true, BooleanUtils.toBooleanDefaultIfNull((Boolean) null, true));
+ assertEquals(false, BooleanUtils.toBooleanDefaultIfNull((Boolean) null, false));
+ }
+
+ //-----------------------------------------------------------------------
+ //-----------------------------------------------------------------------
+ public void test_toBoolean_int() {
+ assertEquals(true, BooleanUtils.toBoolean(1));
+ assertEquals(true, BooleanUtils.toBoolean(-1));
+ assertEquals(false, BooleanUtils.toBoolean(0));
+ }
+
+ public void test_toBooleanObject_int() {
+ assertEquals(Boolean.TRUE, BooleanUtils.toBooleanObject(1));
+ assertEquals(Boolean.TRUE, BooleanUtils.toBooleanObject(-1));
+ assertEquals(Boolean.FALSE, BooleanUtils.toBooleanObject(0));
+ }
+
+ public void test_toBooleanObject_Integer() {
+ assertEquals(Boolean.TRUE, BooleanUtils.toBooleanObject(new Integer(1)));
+ assertEquals(Boolean.TRUE, BooleanUtils.toBooleanObject(new Integer(-1)));
+ assertEquals(Boolean.FALSE, BooleanUtils.toBooleanObject(new Integer(0)));
+ assertEquals(null, BooleanUtils.toBooleanObject((Integer) null));
+ }
+
+ //-----------------------------------------------------------------------
+ public void test_toBoolean_int_int_int() {
+ assertEquals(true, BooleanUtils.toBoolean(6, 6, 7));
+ assertEquals(false, BooleanUtils.toBoolean(7, 6, 7));
+ try {
+ BooleanUtils.toBoolean(8, 6, 7);
+ fail();
+ } catch (IllegalArgumentException ex) {}
+ }
+
+ public void test_toBoolean_Integer_Integer_Integer() {
+ Integer six = new Integer(6);
+ Integer seven = new Integer(7);
+ assertEquals(true, BooleanUtils.toBoolean(new Integer(6), six, seven));
+ assertEquals(false, BooleanUtils.toBoolean(new Integer(7), six, seven));
+ try {
+ BooleanUtils.toBoolean(new Integer(8), six, seven);
+ fail();
+ } catch (IllegalArgumentException ex) {}
+ }
+
+ //-----------------------------------------------------------------------
+ public void test_toBooleanObject_int_int_int() {
+ assertEquals(Boolean.TRUE, BooleanUtils.toBooleanObject(6, 6, 7, 8));
+ assertEquals(Boolean.FALSE, BooleanUtils.toBooleanObject(7, 6, 7, 8));
+ assertEquals(null, BooleanUtils.toBooleanObject(8, 6, 7, 8));
+ try {
+ BooleanUtils.toBooleanObject(9, 6, 7, 8);
+ fail();
+ } catch (IllegalArgumentException ex) {}
+ }
+
+ public void test_toBooleanObject_Integer_Integer_Integer() {
+ Integer six = new Integer(6);
+ Integer seven = new Integer(7);
+ Integer eight = new Integer(8);
+ assertEquals(Boolean.TRUE, BooleanUtils.toBooleanObject(new Integer(6), six, seven, eight));
+ assertEquals(Boolean.FALSE, BooleanUtils.toBooleanObject(new Integer(7), six, seven, eight));
+ assertEquals(null, BooleanUtils.toBooleanObject(new Integer(8), six, seven, eight));
+ try {
+ BooleanUtils.toBooleanObject(new Integer(9), six, seven, eight);
+ fail();
+ } catch (IllegalArgumentException ex) {}
+ }
+
+ //-----------------------------------------------------------------------
+ public void test_toInteger_boolean() {
+ assertEquals(1, BooleanUtils.toInteger(true));
+ assertEquals(0, BooleanUtils.toInteger(false));
+ }
+
+ public void test_toIntegerObject_boolean() {
+ assertEquals(new Integer(1), BooleanUtils.toIntegerObject(true));
+ assertEquals(new Integer(0), BooleanUtils.toIntegerObject(false));
+ }
+
+ public void test_toIntegerObject_Boolean() {
+ assertEquals(new Integer(1), BooleanUtils.toIntegerObject(Boolean.TRUE));
+ assertEquals(new Integer(0), BooleanUtils.toIntegerObject(Boolean.FALSE));
+ assertEquals(null, BooleanUtils.toIntegerObject((Boolean) null));
+ }
+
+ //-----------------------------------------------------------------------
+ public void test_toInteger_boolean_int_int() {
+ assertEquals(6, BooleanUtils.toInteger(true, 6, 7));
+ assertEquals(7, BooleanUtils.toInteger(false, 6, 7));
+ }
+
+ public void test_toInteger_Boolean_int_int_int() {
+ assertEquals(6, BooleanUtils.toInteger(Boolean.TRUE, 6, 7, 8));
+ assertEquals(7, BooleanUtils.toInteger(Boolean.FALSE, 6, 7, 8));
+ assertEquals(8, BooleanUtils.toInteger(null, 6, 7, 8));
+ }
+
+ public void test_toIntegerObject_boolean_Integer_Integer() {
+ Integer six = new Integer(6);
+ Integer seven = new Integer(7);
+ assertEquals(six, BooleanUtils.toIntegerObject(true, six, seven));
+ assertEquals(seven, BooleanUtils.toIntegerObject(false, six, seven));
+ }
+
+ public void test_toIntegerObject_Boolean_Integer_Integer_Integer() {
+ Integer six = new Integer(6);
+ Integer seven = new Integer(7);
+ Integer eight = new Integer(8);
+ assertEquals(six, BooleanUtils.toIntegerObject(Boolean.TRUE, six, seven, eight));
+ assertEquals(seven, BooleanUtils.toIntegerObject(Boolean.FALSE, six, seven, eight));
+ assertEquals(eight, BooleanUtils.toIntegerObject((Boolean) null, six, seven, eight));
+ assertEquals(null, BooleanUtils.toIntegerObject((Boolean) null, six, seven, null));
+ }
+
+ //-----------------------------------------------------------------------
+ //-----------------------------------------------------------------------
+ public void test_toBooleanObject_String() {
+ assertEquals(null, BooleanUtils.toBooleanObject((String) null));
+ assertEquals(null, BooleanUtils.toBooleanObject(""));
+ assertEquals(Boolean.FALSE, BooleanUtils.toBooleanObject("false"));
+ assertEquals(Boolean.FALSE, BooleanUtils.toBooleanObject("no"));
+ assertEquals(Boolean.FALSE, BooleanUtils.toBooleanObject("off"));
+ assertEquals(Boolean.FALSE, BooleanUtils.toBooleanObject("FALSE"));
+ assertEquals(Boolean.FALSE, BooleanUtils.toBooleanObject("NO"));
+ assertEquals(Boolean.FALSE, BooleanUtils.toBooleanObject("OFF"));
+ assertEquals(null, BooleanUtils.toBooleanObject("oof"));
+ assertEquals(Boolean.TRUE, BooleanUtils.toBooleanObject("true"));
+ assertEquals(Boolean.TRUE, BooleanUtils.toBooleanObject("yes"));
+ assertEquals(Boolean.TRUE, BooleanUtils.toBooleanObject("on"));
+ assertEquals(Boolean.TRUE, BooleanUtils.toBooleanObject("TRUE"));
+ assertEquals(Boolean.TRUE, BooleanUtils.toBooleanObject("ON"));
+ assertEquals(Boolean.TRUE, BooleanUtils.toBooleanObject("YES"));
+ assertEquals(Boolean.TRUE, BooleanUtils.toBooleanObject("TruE"));
+ }
+
+ public void test_toBooleanObject_String_String_String_String() {
+ assertEquals(Boolean.TRUE, BooleanUtils.toBooleanObject("Y", "Y", "N", "U"));
+ assertEquals(Boolean.FALSE, BooleanUtils.toBooleanObject("N", "Y", "N", "U"));
+ assertEquals(null, BooleanUtils.toBooleanObject("U", "Y", "N", "U"));
+ try {
+ BooleanUtils.toBooleanObject(null, "Y", "N", "U");
+ fail();
+ } catch (IllegalArgumentException ex) {}
+ try {
+ BooleanUtils.toBooleanObject("X", "Y", "N", "U");
+ fail();
+ } catch (IllegalArgumentException ex) {}
+ }
+
+ //-----------------------------------------------------------------------
+ public void test_toBoolean_String() {
+ assertEquals(false, BooleanUtils.toBoolean((String) null));
+ assertEquals(false, BooleanUtils.toBoolean(""));
+ assertEquals(false, BooleanUtils.toBoolean("off"));
+ assertEquals(false, BooleanUtils.toBoolean("oof"));
+ assertEquals(true, BooleanUtils.toBoolean("true"));
+ assertEquals(true, BooleanUtils.toBoolean("yes"));
+ assertEquals(true, BooleanUtils.toBoolean("on"));
+ assertEquals(true, BooleanUtils.toBoolean("TRUE"));
+ assertEquals(true, BooleanUtils.toBoolean("ON"));
+ assertEquals(true, BooleanUtils.toBoolean("YES"));
+ assertEquals(true, BooleanUtils.toBoolean("TruE"));
+ }
+
+ public void test_toBoolean_String_String_String() {
+ assertEquals(true, BooleanUtils.toBoolean("Y", "Y", "N"));
+ assertEquals(false, BooleanUtils.toBoolean("N", "Y", "N"));
+ try {
+ BooleanUtils.toBoolean(null, "Y", "N");
+ fail();
+ } catch (IllegalArgumentException ex) {}
+ try {
+ BooleanUtils.toBoolean("X", "Y", "N");
+ fail();
+ } catch (IllegalArgumentException ex) {}
+ }
+
+ //-----------------------------------------------------------------------
+ public void test_toStringTrueFalse_Boolean() {
+ assertEquals(null, BooleanUtils.toStringTrueFalse((Boolean) null));
+ assertEquals("true", BooleanUtils.toStringTrueFalse(Boolean.TRUE));
+ assertEquals("false", BooleanUtils.toStringTrueFalse(Boolean.FALSE));
+ }
+
+ public void test_toStringOnOff_Boolean() {
+ assertEquals(null, BooleanUtils.toStringOnOff((Boolean) null));
+ assertEquals("on", BooleanUtils.toStringOnOff(Boolean.TRUE));
+ assertEquals("off", BooleanUtils.toStringOnOff(Boolean.FALSE));
+ }
+
+ public void test_toStringYesNo_Boolean() {
+ assertEquals(null, BooleanUtils.toStringYesNo((Boolean) null));
+ assertEquals("yes", BooleanUtils.toStringYesNo(Boolean.TRUE));
+ assertEquals("no", BooleanUtils.toStringYesNo(Boolean.FALSE));
+ }
+
+ public void test_toString_Boolean_String_String_String() {
+ assertEquals("U", BooleanUtils.toString((Boolean) null, "Y", "N", "U"));
+ assertEquals("Y", BooleanUtils.toString(Boolean.TRUE, "Y", "N", "U"));
+ assertEquals("N", BooleanUtils.toString(Boolean.FALSE, "Y", "N", "U"));
+ }
+
+ //-----------------------------------------------------------------------
+ public void test_toStringTrueFalse_boolean() {
+ assertEquals("true", BooleanUtils.toStringTrueFalse(true));
+ assertEquals("false", BooleanUtils.toStringTrueFalse(false));
+ }
+
+ public void test_toStringOnOff_boolean() {
+ assertEquals("on", BooleanUtils.toStringOnOff(true));
+ assertEquals("off", BooleanUtils.toStringOnOff(false));
+ }
+
+ public void test_toStringYesNo_boolean() {
+ assertEquals("yes", BooleanUtils.toStringYesNo(true));
+ assertEquals("no", BooleanUtils.toStringYesNo(false));
+ }
+
+ public void test_toString_boolean_String_String_String() {
+ assertEquals("Y", BooleanUtils.toString(true, "Y", "N"));
+ assertEquals("N", BooleanUtils.toString(false, "Y", "N"));
+ }
+
+}
diff --git a/examples/cl2/src/test/org/apache/commons/lang/CharSetUtilsTest.java b/examples/cl2/src/test/org/apache/commons/lang/CharSetUtilsTest.java
new file mode 100644
index 00000000..4f84970a
--- /dev/null
+++ b/examples/cl2/src/test/org/apache/commons/lang/CharSetUtilsTest.java
@@ -0,0 +1,156 @@
+/* ====================================================================
+ * 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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
+ * .
+ */
+package org.apache.commons.lang;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import junit.textui.TestRunner;
+
+/**
+ * Unit tests {@link org.apache.commons.lang.CharSetUtils}.
+ *
+ * @author Henri Yandell
+ * @author Ringo De Smet
+ * @version $Id: CharSetUtilsTest.java,v 1.7 2003/03/23 21:47:30 scolebourne Exp $
+ */
+public class CharSetUtilsTest extends TestCase
+{
+ public CharSetUtilsTest(String name) {
+ super(name);
+ }
+
+ public static void main(String[] args) {
+ TestRunner.run(suite());
+ }
+
+ public static Test suite() {
+ TestSuite suite = new TestSuite(CharSetUtilsTest.class);
+ suite.setName("CharSetUtils Tests");
+ return suite;
+ }
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ //-----------------------------------------------------------------------
+
+ public void testSqueeze()
+ {
+ assertEquals("squeeze(String,String[]) failed",
+ "helo", CharSetUtils.squeeze("hello", new String[] {"el"}));
+ assertEquals("squeeze(String,String[]) failed",
+ "", CharSetUtils.squeeze("", new String[] {"el"}));
+ assertEquals("squeeze(String,String[]) failed",
+ "hello", CharSetUtils.squeeze("hello", new String[] {"e"}));
+ assertEquals("squeeze(String,String[]) failed",
+ "fofof", CharSetUtils.squeeze("fooffooff", new String[] {"of"}));
+ assertEquals("squeeze(String,String[]) failed",
+ "fof", CharSetUtils.squeeze("fooooff", new String[] {"fo"}));
+ }
+
+ public void testCount()
+ {
+ assertEquals("count(String,String[]) failed",
+ 3, CharSetUtils.count("hello", new String[] {"el"}));
+ assertEquals("count(String,String[]) failed",
+ 0, CharSetUtils.count("", new String[] {"el"}));
+ assertEquals("count(String,String[]) failed",
+ 0, CharSetUtils.count("hello", new String[] {"x"}));
+ assertEquals("count(String,String[]) failed",
+ 2, CharSetUtils.count("hello", new String[] {"e-i"}));
+ assertEquals("count(String,String[]) failed",
+ 5, CharSetUtils.count("hello", new String[] {"a-z"}));
+ assertEquals("count(String,String[]) failed",
+ 0, CharSetUtils.count("hello", new String[] {""}));
+ }
+
+ public void testKeep()
+ {
+ assertEquals("keep(String,String[]) failed",
+ "ell", CharSetUtils.keep("hello", new String[] {"el"}));
+ assertEquals("keep(String,String[]) failed",
+ "hello", CharSetUtils.keep("hello", new String[] {"elho"}));
+ assertEquals("keep(String,String[]) failed",
+ "", CharSetUtils.keep("hello", new String[] {""}));
+ assertEquals("keep(String,String[]) failed",
+ "hello", CharSetUtils.keep("hello", new String[] {"a-z"}));
+ assertEquals("keep(String,String[]) failed",
+ "----", CharSetUtils.keep("----", new String[] {"-"}));
+ assertEquals("keep(String,String[]) failed",
+ "ll", CharSetUtils.keep("hello", new String[] {"l"}));
+ }
+
+ public void testDelete()
+ {
+ assertEquals("delete(String,String[]) failed",
+ "ho", CharSetUtils.delete("hello", new String[] {"el"}));
+ assertEquals("delete(String,String[]) failed",
+ "", CharSetUtils.delete("hello", new String[] {"elho"}));
+ assertEquals("delete(String,String[]) failed",
+ "hello", CharSetUtils.delete("hello", new String[] {""}));
+ assertEquals("delete(String,String[]) failed",
+ "", CharSetUtils.delete("hello", new String[] {"a-z"}));
+ assertEquals("delete(String,String[]) failed",
+ "", CharSetUtils.delete("----", new String[] {"-"}));
+ assertEquals("delete(String,String[]) failed",
+ "heo", CharSetUtils.delete("hello", new String[] {"l"}));
+ }
+}
+
diff --git a/examples/cl2/src/test/org/apache/commons/lang/ClassUtilsTest.java b/examples/cl2/src/test/org/apache/commons/lang/ClassUtilsTest.java
new file mode 100644
index 00000000..ff73614f
--- /dev/null
+++ b/examples/cl2/src/test/org/apache/commons/lang/ClassUtilsTest.java
@@ -0,0 +1,391 @@
+/* ====================================================================
+ * 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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
+ * .
+ */
+package org.apache.commons.lang;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import junit.textui.TestRunner;
+
+/**
+ * Unit tests {@link org.apache.commons.lang.ClassUtils}.
+ *
+ * @author Stephen Colebourne
+ * @version $Id: ClassUtilsTest.java,v 1.3 2003/03/23 21:47:30 scolebourne Exp $
+ */
+public class ClassUtilsTest extends TestCase {
+
+ public ClassUtilsTest(String name) {
+ super(name);
+ }
+
+ public static void main(String[] args) {
+ TestRunner.run(suite());
+ }
+
+ public static Test suite() {
+ TestSuite suite = new TestSuite(ClassUtilsTest.class);
+ suite.setName("ClassUtils Tests");
+ return suite;
+ }
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ private static class Inner {
+ }
+
+ // -------------------------------------------------------------------------
+ public void test_getShortClassName_Object() {
+ assertEquals("ClassUtils", ClassUtils.getShortClassName(new ClassUtils(), ""));
+ assertEquals("ClassUtilsTest.Inner", ClassUtils.getShortClassName(new Inner(), ""));
+ assertEquals("String", ClassUtils.getShortClassName("hello", ""));
+ assertEquals("", ClassUtils.getShortClassName(null, ""));
+ }
+
+ public void test_getShortClassName_Class() {
+ assertEquals("ClassUtils", ClassUtils.getShortClassName(ClassUtils.class));
+ assertEquals("Map.Entry", ClassUtils.getShortClassName(Map.Entry.class));
+ try {
+ ClassUtils.getShortClassName((Class) null);
+ fail();
+ } catch (IllegalArgumentException ex) {}
+ }
+
+ public void test_getShortClassName_String() {
+ assertEquals("ClassUtils", ClassUtils.getShortClassName(ClassUtils.class.getName()));
+ assertEquals("Map.Entry", ClassUtils.getShortClassName(Map.Entry.class.getName()));
+ try {
+ ClassUtils.getShortClassName((String) null);
+ fail();
+ } catch (IllegalArgumentException ex) {}
+ try {
+ ClassUtils.getShortClassName("");
+ fail();
+ } catch (IllegalArgumentException ex) {}
+ }
+
+ // -------------------------------------------------------------------------
+ public void test_getPackageName_Object() {
+ assertEquals("org.apache.commons.lang", ClassUtils.getPackageName(new ClassUtils(), ""));
+ assertEquals("org.apache.commons.lang", ClassUtils.getPackageName(new Inner(), ""));
+ assertEquals("", ClassUtils.getPackageName(null, ""));
+ }
+
+ public void test_getPackageName_Class() {
+ assertEquals("java.lang", ClassUtils.getPackageName(String.class));
+ assertEquals("java.util", ClassUtils.getPackageName(Map.Entry.class));
+ try {
+ ClassUtils.getPackageName((Class) null);
+ fail();
+ } catch (IllegalArgumentException ex) {}
+ }
+
+ public void test_getPackageName_String() {
+ assertEquals("org.apache.commons.lang", ClassUtils.getPackageName(ClassUtils.class.getName()));
+ assertEquals("java.util", ClassUtils.getPackageName(Map.Entry.class.getName()));
+ try {
+ ClassUtils.getPackageName((String) null);
+ fail();
+ } catch (IllegalArgumentException ex) {}
+ try {
+ ClassUtils.getPackageName("");
+ fail();
+ } catch (IllegalArgumentException ex) {}
+ }
+
+ // -------------------------------------------------------------------------
+ public void test_getAllSuperclasses_Class() {
+ List list = ClassUtils.getAllSuperclasses(CY.class);
+ assertEquals(2, list.size());
+ assertEquals(CX.class, list.get(0));
+ assertEquals(Object.class, list.get(1));
+ try {
+ ClassUtils.getAllSuperclasses(null);
+ fail();
+ } catch (IllegalArgumentException ex) {}
+ }
+
+ public void test_getAllInterfaces_Class() {
+ List list = ClassUtils.getAllInterfaces(CY.class);
+ assertEquals(6, list.size());
+ assertEquals(IB.class, list.get(0));
+ assertEquals(IC.class, list.get(1));
+ assertEquals(ID.class, list.get(2));
+ assertEquals(IE.class, list.get(3));
+ assertEquals(IF.class, list.get(4));
+ assertEquals(IA.class, list.get(5));
+ try {
+ ClassUtils.getAllInterfaces(null);
+ fail();
+ } catch (IllegalArgumentException ex) {}
+ }
+
+ private static interface IA {
+ }
+ private static interface IB {
+ }
+ private static interface IC extends ID, IE {
+ }
+ private static interface ID {
+ }
+ private static interface IE extends IF {
+ }
+ private static interface IF {
+ }
+ private static class CX implements IB, IA, IE {
+ }
+ private static class CY extends CX implements IB, IC {
+ }
+
+ // -------------------------------------------------------------------------
+ public void test_convertClassNamesToClasses_List() {
+ List list = new ArrayList();
+ List result = ClassUtils.convertClassNamesToClasses(list);
+ assertEquals(0, result.size());
+
+ list.add("java.lang.String");
+ list.add("java.lang.xxx");
+ list.add("java.lang.Object");
+ result = ClassUtils.convertClassNamesToClasses(list);
+ assertEquals(3, result.size());
+ assertEquals(String.class, result.get(0));
+ assertEquals(null, result.get(1));
+ assertEquals(Object.class, result.get(2));
+
+ list.add(new Object());
+ try {
+ ClassUtils.convertClassNamesToClasses(list);
+ fail();
+ } catch (ClassCastException ex) {}
+
+ try {
+ ClassUtils.convertClassNamesToClasses(null);
+ fail();
+ } catch (IllegalArgumentException ex) {}
+ }
+
+ public void test_convertClassesToClassNames_List() {
+ List list = new ArrayList();
+ List result = ClassUtils.convertClassesToClassNames(list);
+ assertEquals(0, result.size());
+
+ list.add(String.class);
+ list.add(Object.class);
+ result = ClassUtils.convertClassesToClassNames(list);
+ assertEquals(2, result.size());
+ assertEquals("java.lang.String", result.get(0));
+ assertEquals("java.lang.Object", result.get(1));
+
+ list.add(new Object());
+ try {
+ ClassUtils.convertClassesToClassNames(list);
+ fail();
+ } catch (ClassCastException ex) {}
+
+ try {
+ ClassUtils.convertClassesToClassNames(null);
+ fail();
+ } catch (IllegalArgumentException ex) {}
+ }
+
+ // -------------------------------------------------------------------------
+ public void test_isInnerClass_Class() {
+ assertEquals(true, ClassUtils.isInnerClass(Inner.class));
+ assertEquals(true, ClassUtils.isInnerClass(Map.Entry.class));
+ assertEquals(true, ClassUtils.isInnerClass(new Cloneable() {
+ }.getClass()));
+ assertEquals(false, ClassUtils.isInnerClass(this.getClass()));
+ assertEquals(false, ClassUtils.isInnerClass(String.class));
+ try {
+ ClassUtils.isInnerClass(null);
+ fail();
+ } catch (IllegalArgumentException ex) {}
+ }
+
+ // -------------------------------------------------------------------------
+ public void test_isAssignable_ClassArray_ClassArray() throws Exception {
+ Class[] array2 = new Class[] {Object.class, Object.class};
+ Class[] array1 = new Class[] {Object.class};
+ Class[] array1s = new Class[] {String.class};
+ Class[] array0 = new Class[] {};
+
+ assertEquals(false, ClassUtils.isAssignable(array1, array2));
+ assertEquals(false, ClassUtils.isAssignable(null, array2));
+ assertEquals(true, ClassUtils.isAssignable(null, array0));
+ assertEquals(true, ClassUtils.isAssignable(array0, array0));
+ assertEquals(true, ClassUtils.isAssignable(array0, null));
+ assertEquals(true, ClassUtils.isAssignable((Class[]) null, (Class[]) null));
+
+ assertEquals(false, ClassUtils.isAssignable(array1, array1s));
+ assertEquals(true, ClassUtils.isAssignable(array1s, array1s));
+ assertEquals(true, ClassUtils.isAssignable(array1s, array1));
+ }
+
+ public void test_isAssignable() throws Exception {
+ try {
+ ClassUtils.isAssignable(String.class, null);
+ fail();
+ } catch (IllegalArgumentException ex) {}
+ try {
+ ClassUtils.isAssignable((Class) null, (Class) null);
+ fail();
+ } catch (IllegalArgumentException ex) {}
+ assertEquals(true, ClassUtils.isAssignable(null, Object.class));
+ assertEquals(true, ClassUtils.isAssignable(null, Integer.class));
+ assertEquals(false, ClassUtils.isAssignable(null, Integer.TYPE));
+ assertEquals(true, ClassUtils.isAssignable(String.class, Object.class));
+ assertEquals(true, ClassUtils.isAssignable(String.class, String.class));
+ assertEquals(false, ClassUtils.isAssignable(Object.class, String.class));
+ assertEquals(false, ClassUtils.isAssignable(Integer.TYPE, Integer.class));
+ assertEquals(false, ClassUtils.isAssignable(Integer.class, Integer.TYPE));
+ assertEquals(true, ClassUtils.isAssignable(Integer.TYPE, Integer.TYPE));
+ assertEquals(true, ClassUtils.isAssignable(Integer.class, Integer.class));
+ }
+
+ public void test_isAssignable_Widening() throws Exception {
+ // test byte conversions
+ assertEquals("byte -> char", false, ClassUtils.isAssignable(Byte.TYPE, Character.TYPE));
+ assertEquals("byte -> byte", true, ClassUtils.isAssignable(Byte.TYPE, Byte.TYPE));
+ assertEquals("byte -> short", true, ClassUtils.isAssignable(Byte.TYPE, Short.TYPE));
+ assertEquals("byte -> int", true, ClassUtils.isAssignable(Byte.TYPE, Integer.TYPE));
+ assertEquals("byte -> long", true, ClassUtils.isAssignable(Byte.TYPE, Long.TYPE));
+ assertEquals("byte -> float", true, ClassUtils.isAssignable(Byte.TYPE, Float.TYPE));
+ assertEquals("byte -> double", true, ClassUtils.isAssignable(Byte.TYPE, Double.TYPE));
+ assertEquals("byte -> boolean", false, ClassUtils.isAssignable(Byte.TYPE, Boolean.TYPE));
+
+ // test short conversions
+ assertEquals("short -> char", false, ClassUtils.isAssignable(Short.TYPE, Character.TYPE));
+ assertEquals("short -> byte", false, ClassUtils.isAssignable(Short.TYPE, Byte.TYPE));
+ assertEquals("short -> short", true, ClassUtils.isAssignable(Short.TYPE, Short.TYPE));
+ assertEquals("short -> int", true, ClassUtils.isAssignable(Short.TYPE, Integer.TYPE));
+ assertEquals("short -> long", true, ClassUtils.isAssignable(Short.TYPE, Long.TYPE));
+ assertEquals("short -> float", true, ClassUtils.isAssignable(Short.TYPE, Float.TYPE));
+ assertEquals("short -> double", true, ClassUtils.isAssignable(Short.TYPE, Double.TYPE));
+ assertEquals("short -> boolean", false, ClassUtils.isAssignable(Short.TYPE, Boolean.TYPE));
+
+ // test char conversions
+ assertEquals("char -> char", true, ClassUtils.isAssignable(Character.TYPE, Character.TYPE));
+ assertEquals("char -> byte", false, ClassUtils.isAssignable(Character.TYPE, Byte.TYPE));
+ assertEquals("char -> short", false, ClassUtils.isAssignable(Character.TYPE, Short.TYPE));
+ assertEquals("char -> int", true, ClassUtils.isAssignable(Character.TYPE, Integer.TYPE));
+ assertEquals("char -> long", true, ClassUtils.isAssignable(Character.TYPE, Long.TYPE));
+ assertEquals("char -> float", true, ClassUtils.isAssignable(Character.TYPE, Float.TYPE));
+ assertEquals("char -> double", true, ClassUtils.isAssignable(Character.TYPE, Double.TYPE));
+ assertEquals("char -> boolean", false, ClassUtils.isAssignable(Character.TYPE, Boolean.TYPE));
+
+ // test int conversions
+ assertEquals("int -> char", false, ClassUtils.isAssignable(Integer.TYPE, Character.TYPE));
+ assertEquals("int -> byte", false, ClassUtils.isAssignable(Integer.TYPE, Byte.TYPE));
+ assertEquals("int -> short", false, ClassUtils.isAssignable(Integer.TYPE, Short.TYPE));
+ assertEquals("int -> int", true, ClassUtils.isAssignable(Integer.TYPE, Integer.TYPE));
+ assertEquals("int -> long", true, ClassUtils.isAssignable(Integer.TYPE, Long.TYPE));
+ assertEquals("int -> float", true, ClassUtils.isAssignable(Integer.TYPE, Float.TYPE));
+ assertEquals("int -> double", true, ClassUtils.isAssignable(Integer.TYPE, Double.TYPE));
+ assertEquals("int -> boolean", false, ClassUtils.isAssignable(Integer.TYPE, Boolean.TYPE));
+
+ // test long conversions
+ assertEquals("long -> char", false, ClassUtils.isAssignable(Long.TYPE, Character.TYPE));
+ assertEquals("long -> byte", false, ClassUtils.isAssignable(Long.TYPE, Byte.TYPE));
+ assertEquals("long -> short", false, ClassUtils.isAssignable(Long.TYPE, Short.TYPE));
+ assertEquals("long -> int", false, ClassUtils.isAssignable(Long.TYPE, Integer.TYPE));
+ assertEquals("long -> long", true, ClassUtils.isAssignable(Long.TYPE, Long.TYPE));
+ assertEquals("long -> float", true, ClassUtils.isAssignable(Long.TYPE, Float.TYPE));
+ assertEquals("long -> double", true, ClassUtils.isAssignable(Long.TYPE, Double.TYPE));
+ assertEquals("long -> boolean", false, ClassUtils.isAssignable(Long.TYPE, Boolean.TYPE));
+
+ // test float conversions
+ assertEquals("float -> char", false, ClassUtils.isAssignable(Float.TYPE, Character.TYPE));
+ assertEquals("float -> byte", false, ClassUtils.isAssignable(Float.TYPE, Byte.TYPE));
+ assertEquals("float -> short", false, ClassUtils.isAssignable(Float.TYPE, Short.TYPE));
+ assertEquals("float -> int", false, ClassUtils.isAssignable(Float.TYPE, Integer.TYPE));
+ assertEquals("float -> long", false, ClassUtils.isAssignable(Float.TYPE, Long.TYPE));
+ assertEquals("float -> float", true, ClassUtils.isAssignable(Float.TYPE, Float.TYPE));
+ assertEquals("float -> double", true, ClassUtils.isAssignable(Float.TYPE, Double.TYPE));
+ assertEquals("float -> boolean", false, ClassUtils.isAssignable(Float.TYPE, Boolean.TYPE));
+
+ // test float conversions
+ assertEquals("double -> char", false, ClassUtils.isAssignable(Double.TYPE, Character.TYPE));
+ assertEquals("double -> byte", false, ClassUtils.isAssignable(Double.TYPE, Byte.TYPE));
+ assertEquals("double -> short", false, ClassUtils.isAssignable(Double.TYPE, Short.TYPE));
+ assertEquals("double -> int", false, ClassUtils.isAssignable(Double.TYPE, Integer.TYPE));
+ assertEquals("double -> long", false, ClassUtils.isAssignable(Double.TYPE, Long.TYPE));
+ assertEquals("double -> float", false, ClassUtils.isAssignable(Double.TYPE, Float.TYPE));
+ assertEquals("double -> double", true, ClassUtils.isAssignable(Double.TYPE, Double.TYPE));
+ assertEquals("double -> boolean", false, ClassUtils.isAssignable(Double.TYPE, Boolean.TYPE));
+
+ // test float conversions
+ assertEquals("boolean -> char", false, ClassUtils.isAssignable(Boolean.TYPE, Character.TYPE));
+ assertEquals("boolean -> byte", false, ClassUtils.isAssignable(Boolean.TYPE, Byte.TYPE));
+ assertEquals("boolean -> short", false, ClassUtils.isAssignable(Boolean.TYPE, Short.TYPE));
+ assertEquals("boolean -> int", false, ClassUtils.isAssignable(Boolean.TYPE, Integer.TYPE));
+ assertEquals("boolean -> long", false, ClassUtils.isAssignable(Boolean.TYPE, Long.TYPE));
+ assertEquals("boolean -> float", false, ClassUtils.isAssignable(Boolean.TYPE, Float.TYPE));
+ assertEquals("boolean -> double", false, ClassUtils.isAssignable(Boolean.TYPE, Double.TYPE));
+ assertEquals("boolean -> boolean", true, ClassUtils.isAssignable(Boolean.TYPE, Boolean.TYPE));
+ }
+
+// public static List getAssignableFrom(List classes, Class superclass) {
+// public static boolean isAssignable(Class[] classArray, Class[] toClassArray) {
+// public static boolean isAssignable(Class cls, Class toClass) {
+}
diff --git a/examples/cl2/src/test/org/apache/commons/lang/EntitiesPerformanceTest.java b/examples/cl2/src/test/org/apache/commons/lang/EntitiesPerformanceTest.java
new file mode 100644
index 00000000..6f960ae0
--- /dev/null
+++ b/examples/cl2/src/test/org/apache/commons/lang/EntitiesPerformanceTest.java
@@ -0,0 +1,204 @@
+/* ====================================================================
+ * 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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
+ * .
+ */
+package org.apache.commons.lang;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import junit.textui.TestRunner;
+
+public class EntitiesPerformanceTest extends TestCase {
+ private int COUNT = 10000;
+ private int STRING_LENGTH = 1000;
+
+ private static String stringWithUnicode;
+ private static String stringWithEntities;
+ private static Entities treeEntities;
+ private static Entities hashEntities;
+ private static Entities arrayEntities;
+ private static Entities binaryEntities;
+
+ public EntitiesPerformanceTest(String name) {
+ super(name);
+ }
+
+ public static void main(String[] args) {
+ TestRunner.run(suite());
+ }
+
+ public static Test suite() {
+ TestSuite suite = new TestSuite(EntitiesPerformanceTest.class);
+ return suite;
+ }
+
+ public void setUp() {
+ if (stringWithUnicode == null) {
+ StringBuffer buf = new StringBuffer(STRING_LENGTH);
+ for (int i = 0; i < STRING_LENGTH/5; ++i) {
+ buf.append("xxxx");
+ char ch = html40value(i);
+ buf.append(ch);
+ }
+ stringWithUnicode = buf.toString();
+ stringWithEntities = Entities.HTML40.unescape(stringWithUnicode);
+ }
+ }
+
+ private char html40value(int i) {
+ String entityValue = Entities.html40[i % Entities.html40.length][1];
+ char ch = (char) Integer.parseInt(entityValue);
+ return ch;
+ }
+
+ public void testBuildHash() throws Exception {
+ for (int i = 0; i < COUNT; ++i) {
+ hashEntities = new Entities();
+ hashEntities.map = new Entities.HashIntMap();
+ Entities.fillWithHtml40Entities(hashEntities);
+ }
+ }
+
+ public void testBuildTree() throws Exception {
+ for (int i = 0; i < COUNT; ++i) {
+ treeEntities = new Entities();
+ treeEntities.map = new Entities.TreeIntMap();
+ Entities.fillWithHtml40Entities(treeEntities);
+ }
+ }
+
+ public void testBuildArray() throws Exception {
+ for (int i = 0; i < COUNT; ++i) {
+ arrayEntities = new Entities();
+ arrayEntities.map = new Entities.ArrayIntMap();
+ Entities.fillWithHtml40Entities(arrayEntities);
+ }
+ }
+
+ public void testBuildBinary() throws Exception {
+ for (int i = 0; i < COUNT; ++i) {
+ binaryEntities = new Entities();
+ binaryEntities.map = new Entities.BinaryIntMap();
+ Entities.fillWithHtml40Entities(binaryEntities);
+ }
+ }
+
+ public void testLookupHash() throws Exception {
+ lookup(hashEntities);
+ }
+
+ public void testLookupTree() throws Exception {
+ lookup(treeEntities);
+ }
+
+ public void testLookupArray() throws Exception {
+ lookup(arrayEntities);
+ }
+
+ public void testLookupBinary() throws Exception {
+ lookup(binaryEntities);
+ }
+
+ public void testEscapeHash() throws Exception {
+ escapeIt(hashEntities);
+ }
+
+ public void testEscapeTree() throws Exception {
+ escapeIt(treeEntities);
+ }
+
+ public void testEscapeArray() throws Exception {
+ escapeIt(arrayEntities);
+ }
+
+ public void testEscapeBinary() throws Exception {
+ escapeIt(binaryEntities);
+ }
+
+ public void testUnescapeHash() throws Exception {
+ unescapeIt(hashEntities);
+ }
+
+ public void testUnescapeTree() throws Exception {
+ unescapeIt(treeEntities);
+ }
+
+ public void testUnescapeArray() throws Exception {
+ unescapeIt(arrayEntities);
+ }
+
+ public void testUnescapeBinary() throws Exception {
+ unescapeIt(binaryEntities);
+ }
+
+ private void lookup(Entities entities) {
+ for (int i = 0; i < COUNT*1000; ++i) {
+ entities.entityName(html40value(i));
+ }
+ }
+
+ private void escapeIt(Entities entities) {
+ for (int i = 0; i < COUNT; ++i) {
+ String escaped = entities.escape(stringWithUnicode);
+ assertEquals("xxxxƒ", escaped.substring(0,10));
+ }
+ }
+
+ private void unescapeIt(Entities entities) {
+ for (int i = 0; i < COUNT; ++i) {
+ String unescaped = entities.unescape(stringWithEntities);
+ assertEquals("xxxx\u0192", unescaped.substring(0,5));
+ }
+ }
+}
+
diff --git a/examples/cl2/src/test/org/apache/commons/lang/EntitiesTest.java b/examples/cl2/src/test/org/apache/commons/lang/EntitiesTest.java
new file mode 100644
index 00000000..d3c9efd4
--- /dev/null
+++ b/examples/cl2/src/test/org/apache/commons/lang/EntitiesTest.java
@@ -0,0 +1,168 @@
+/* ====================================================================
+ * 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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
+ * .
+ */
+package org.apache.commons.lang;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import junit.textui.TestRunner;
+
+/**
+ * Unit tests for {@link StringEscapeUtils}.
+ *
+ * @author of original StringUtilsTest.testEscape = ?
+ * @author Alexander Day Chaffee
+ * @version $Id: EntitiesTest.java,v 1.5 2003/05/24 19:24:15 ggregory Exp $
+ */
+public class EntitiesTest extends TestCase
+{
+ public EntitiesTest(String name) {
+ super(name);
+ }
+
+ public static void main(String[] args) {
+ TestRunner.run(suite());
+ }
+
+ public static Test suite() {
+ TestSuite suite = new TestSuite(EntitiesTest.class);
+ suite.setName("EntitiesTest Tests");
+ return suite;
+ }
+
+ Entities entities;
+
+ public void setUp()
+ {
+ entities = new Entities();
+ entities.addEntity("foo", 161);
+ entities.addEntity("bar", 162);
+ }
+
+ public void testEscapeNamedEntity() throws Exception
+ {
+ assertEquals("&foo;", entities.escape("\u00A1"));
+ assertEquals("x&foo;", entities.escape("x\u00A1"));
+ assertEquals("&foo;x", entities.escape("\u00A1x"));
+ assertEquals("x&foo;x", entities.escape("x\u00A1x"));
+ assertEquals("&foo;&bar;", entities.escape("\u00A1\u00A2"));
+ }
+
+ public void testUnescapeNamedEntity() throws Exception
+ {
+ assertEquals("\u00A1", entities.unescape("&foo;"));
+ assertEquals("x\u00A1", entities.unescape("x&foo;"));
+ assertEquals("\u00A1x", entities.unescape("&foo;x"));
+ assertEquals("x\u00A1x", entities.unescape("x&foo;x"));
+ assertEquals("\u00A1\u00A2", entities.unescape("&foo;&bar;"));
+ }
+
+ public void testUnescapeUnknownEntity() throws Exception
+ {
+ assertEquals("&zzzz;", entities.unescape("&zzzz;"));
+ }
+
+ public void testAddEntitiesArray() throws Exception
+ {
+ String[][] array = {{"foo", "100"}, {"bar", "101"}};
+ Entities e = new Entities();
+ e.addEntities(array);
+ assertEquals("foo", e.entityName(100));
+ assertEquals("bar", e.entityName(101));
+ assertEquals(100, e.entityValue("foo"));
+ assertEquals(101, e.entityValue("bar"));
+ }
+
+ public void testEntitiesXmlObject() throws Exception
+ {
+ assertEquals("gt", Entities.XML.entityName('>'));
+ assertEquals((int) '>', Entities.XML.entityValue("gt"));
+ assertEquals(-1, Entities.XML.entityValue("xyzzy"));
+ }
+
+ public void testArrayIntMap() throws Exception
+ {
+ Entities.ArrayIntMap map = new Entities.ArrayIntMap(2);
+ checkSomeIntMap(map);
+ }
+
+ public void testTreeIntMap() throws Exception
+ {
+ Entities.IntMap map = new Entities.TreeIntMap();
+ checkSomeIntMap(map);
+ }
+
+ public void testHashIntMap() throws Exception
+ {
+ Entities.IntMap map = new Entities.HashIntMap();
+ checkSomeIntMap(map);
+ }
+
+ public void testBinaryIntMap() throws Exception
+ {
+ Entities.BinaryIntMap map = new Entities.BinaryIntMap(2);
+ checkSomeIntMap(map);
+ }
+
+ private void checkSomeIntMap(Entities.IntMap map) {
+ map.add("foo", 1);
+ assertEquals(1, map.value("foo"));
+ assertEquals("foo", map.name(1));
+ map.add("bar", 2);
+ map.add("baz", 3);
+ assertEquals(3, map.value("baz"));
+ assertEquals("baz", map.name(3));
+ }
+}
+
diff --git a/examples/cl2/src/test/org/apache/commons/lang/IllegalClassExceptionTest.java b/examples/cl2/src/test/org/apache/commons/lang/IllegalClassExceptionTest.java
new file mode 100644
index 00000000..7c5302a1
--- /dev/null
+++ b/examples/cl2/src/test/org/apache/commons/lang/IllegalClassExceptionTest.java
@@ -0,0 +1,128 @@
+/* ====================================================================
+ * 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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
+ * .
+ */
+package org.apache.commons.lang;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import junit.textui.TestRunner;
+
+/**
+ * JUnit tests.
+ *
+ * @author Matthew Hawthorne
+ * @version $Id: IllegalClassExceptionTest.java,v 1.2 2003/06/06 07:04:12 rdonkin Exp $
+ * @see IllegalClassException
+ */
+public class IllegalClassExceptionTest extends TestCase {
+
+ public static void main(String[] args) {
+ TestRunner.run(suite());
+ }
+
+ public static Test suite() {
+ return new TestSuite(IllegalClassExceptionTest.class);
+ }
+
+ public IllegalClassExceptionTest(String testName) {
+ super(testName);
+ }
+
+ // testConstructor_classArgs
+
+ public void testConstructor_classArgs_allNullInput() {
+ new IllegalClassException(null, null);
+ }
+
+ public void testConstructor_classArgs_nullExpected() {
+ new IllegalClassException(null, String.class);
+ }
+
+ public void testConstructor_classArgs_nullActual() {
+ new IllegalClassException(String.class, null);
+ }
+
+ // testConstructor_stringArg
+
+ public void testConstructor_stringArg_nullInput() {
+ new IllegalClassException(null);
+ }
+
+ // testGetMessage
+
+ public void testGetMessage_classArgs_nullInput() {
+ final Throwable t = new IllegalClassException(null, null);
+ assertEquals("Expected: null, actual: null", t.getMessage());
+ }
+
+ public void testGetMessage_classArgs_normalInput() {
+ final Throwable t =
+ new IllegalClassException(String.class, Integer.class);
+ assertEquals(
+ "Expected: java.lang.String, actual: java.lang.Integer",
+ t.getMessage());
+ }
+
+ public void testGetMessage_stringArg_nullInput() {
+ final Throwable t = new IllegalClassException(null);
+ assertEquals(null, t.getMessage());
+ }
+
+ public void testGetMessage_stringArg_validInput() {
+ final String message = "message";
+ final Throwable t = new IllegalClassException(message);
+ assertEquals(message, t.getMessage());
+ }
+
+} // IllegalClassExceptionTest
diff --git a/examples/cl2/src/test/org/apache/commons/lang/IncompleteArgumentExceptionTest.java b/examples/cl2/src/test/org/apache/commons/lang/IncompleteArgumentExceptionTest.java
new file mode 100644
index 00000000..4e25724f
--- /dev/null
+++ b/examples/cl2/src/test/org/apache/commons/lang/IncompleteArgumentExceptionTest.java
@@ -0,0 +1,131 @@
+/* ====================================================================
+ * 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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
+ * .
+ */
+package org.apache.commons.lang;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import junit.textui.TestRunner;
+
+/**
+ * JUnit tests.
+ *
+ * @author Matthew Hawthorne
+ * @version $Id: IncompleteArgumentExceptionTest.java,v 1.1 2003/05/15 04:05:11 bayard Exp $
+ * @see IncompleteArgumentException
+ */
+public class IncompleteArgumentExceptionTest extends TestCase {
+
+ public static void main(String[] args) {
+ TestRunner.run(suite());
+ }
+
+ public static Test suite() {
+ return new TestSuite(IncompleteArgumentExceptionTest.class);
+ }
+
+ public IncompleteArgumentExceptionTest(String testName) {
+ super(testName);
+ }
+
+ // testConstructor
+
+ public void test1arg_nullInput() {
+ final Throwable t = new IncompleteArgumentException(null);
+ assertEquals("null is incomplete.", t.getMessage());
+ }
+
+ public void test1arg_validInput() {
+ final String name = "argument";
+ final Throwable t = new IncompleteArgumentException(name);
+ assertEquals(name + " is incomplete.", t.getMessage());
+ }
+
+ public void test2arg_allNullInput() {
+ final Throwable t = new IncompleteArgumentException(null, null);
+ assertEquals(
+ "null is missing the following items: null",
+ t.getMessage());
+ }
+
+ public void test2arg_nullString() {
+ final Throwable t =
+ new IncompleteArgumentException(
+ null,
+ new String[] { "one", "two" });
+ assertEquals(
+ "null is missing the following items: [one, two]",
+ t.getMessage());
+ }
+
+ public void test2arg_nullArray() {
+ final String name = "one";
+ final Throwable t = new IncompleteArgumentException(name, null);
+ assertEquals(
+ name + " is missing the following items: null",
+ t.getMessage());
+ }
+
+ public void test2arg_validInput() {
+ final String name = "input";
+ final Throwable t =
+ new IncompleteArgumentException(
+ name,
+ new String[] { "one", "two" });
+ assertEquals(
+ name + " is missing the following items: [one, two]",
+ t.getMessage());
+ }
+
+} // IncompleteArgumentExceptionTest
diff --git a/examples/cl2/src/test/org/apache/commons/lang/LangTestSuite.java b/examples/cl2/src/test/org/apache/commons/lang/LangTestSuite.java
new file mode 100644
index 00000000..97f176b4
--- /dev/null
+++ b/examples/cl2/src/test/org/apache/commons/lang/LangTestSuite.java
@@ -0,0 +1,115 @@
+/* ====================================================================
+ * 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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
+ * .
+ */
+package org.apache.commons.lang;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import junit.textui.TestRunner;
+
+/**
+ * Test suite for the Lang package.
+ *
+ * @author Stephen Colebourne
+ * @author Ringo De Smet
+ * @author Matthew Hawthorne
+ * @version $Id: LangTestSuite.java,v 1.18 2003/05/24 12:11:02 scolebourne Exp $
+ */
+public class LangTestSuite extends TestCase {
+
+ /**
+ * Construct a new instance.
+ */
+ public LangTestSuite(String name) {
+ super(name);
+ }
+
+ /**
+ * Command-line interface.
+ */
+ public static void main(String[] args) {
+ TestRunner.run(suite());
+ }
+
+ /**
+ * Get the suite of tests
+ */
+ public static Test suite() {
+ TestSuite suite = new TestSuite();
+ suite.setName("Commons-Lang Tests");
+ suite.addTest(ArrayUtilsTest.suite());
+ suite.addTest(BooleanUtilsTest.suite());
+ suite.addTest(CharSetUtilsTest.suite());
+ suite.addTest(ClassUtilsTest.suite());
+ suite.addTest(EntitiesTest.suite());
+ suite.addTest(IllegalClassExceptionTest.suite());
+ suite.addTest(IncompleteArgumentExceptionTest.suite());
+ suite.addTest(NotImplementedExceptionTest.suite());
+ suite.addTest(NullArgumentExceptionTest.suite());
+ suite.addTest(NumberRangeTest.suite());
+ suite.addTest(NumberUtilsTest.suite());
+ suite.addTest(ObjectUtilsTest.suite());
+ suite.addTest(RandomStringUtilsTest.suite());
+ suite.addTest(SerializationUtilsTest.suite());
+ suite.addTest(StringUtilsTrimEmptyTest.suite());
+ suite.addTest(StringUtilsSubstringTest.suite());
+ suite.addTest(StringUtilsEqualsIndexOfTest.suite());
+ suite.addTest(StringUtilsIsTest.suite());
+ suite.addTest(StringEscapeUtilsTest.suite());
+ suite.addTest(SystemUtilsTest.suite());
+ suite.addTest(UnhandledExceptionTest.suite());
+ suite.addTest(WordWrapUtilsTest.suite());
+ return suite;
+ }
+}
diff --git a/examples/cl2/src/test/org/apache/commons/lang/NotImplementedExceptionTest.java b/examples/cl2/src/test/org/apache/commons/lang/NotImplementedExceptionTest.java
new file mode 100644
index 00000000..0c506dd5
--- /dev/null
+++ b/examples/cl2/src/test/org/apache/commons/lang/NotImplementedExceptionTest.java
@@ -0,0 +1,121 @@
+/* ====================================================================
+ * 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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
+ * .
+ */
+package org.apache.commons.lang;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import junit.textui.TestRunner;
+
+/**
+ * JUnit tests.
+ *
+ * @author Matthew Hawthorne
+ * @version $Id: NotImplementedExceptionTest.java,v 1.1 2003/05/15 04:05:11 bayard Exp $
+ * @see NotImplementedException
+ */
+public class NotImplementedExceptionTest extends TestCase {
+
+ public static void main(String[] args) {
+ TestRunner.run(suite());
+ }
+
+ public static Test suite() {
+ return new TestSuite(NotImplementedExceptionTest.class);
+ }
+
+ public NotImplementedExceptionTest(String testName) {
+ super(testName);
+ }
+
+ // testConstructor
+
+ public void testConstructor_classArg_nullInput() {
+ final Class c = null;
+ new NotImplementedException(c);
+ }
+
+ public void testConstructor_stringArg_nullInput() {
+ final String s = null;
+ new NotImplementedException(s);
+ }
+
+ // testGetMessage
+
+ public void testGetMessage_classArg_nullInput() {
+ final Class c = null;
+ final Throwable t = new NotImplementedException(c);
+ assertEquals("Method is not implemented in class null", t.getMessage());
+ }
+
+ public void testGetMessage_classArg_validInput() {
+ final Throwable t = new NotImplementedException(String.class);
+ assertEquals(
+ "Method is not implemented in class java.lang.String",
+ t.getMessage());
+ }
+
+ public void testGetMessage_stringArg_nullInput() {
+ final String s = null;
+ final Throwable t = new NotImplementedException(s);
+ assertEquals(null, t.getMessage());
+ }
+
+ public void testGetMessage_stringArg_validInput() {
+ final String msg = "message";
+ final Throwable t = new NotImplementedException(msg);
+ assertEquals(msg, t.getMessage());
+ }
+
+} // NotImplementedExceptionTest
diff --git a/examples/cl2/src/test/org/apache/commons/lang/NullArgumentExceptionTest.java b/examples/cl2/src/test/org/apache/commons/lang/NullArgumentExceptionTest.java
new file mode 100644
index 00000000..f988d2b9
--- /dev/null
+++ b/examples/cl2/src/test/org/apache/commons/lang/NullArgumentExceptionTest.java
@@ -0,0 +1,102 @@
+/* ====================================================================
+ * 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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
+ * .
+ */
+package org.apache.commons.lang;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import junit.textui.TestRunner;
+
+/**
+ * JUnit tests.
+ *
+ * @author Matthew Hawthorne
+ * @version $Id: NullArgumentExceptionTest.java,v 1.1 2003/05/15 04:05:11 bayard Exp $
+ * @see NullArgumentException
+ */
+public class NullArgumentExceptionTest extends TestCase {
+
+ public static void main(String[] args) {
+ TestRunner.run(suite());
+ }
+
+ public static Test suite() {
+ return new TestSuite(NullArgumentExceptionTest.class);
+ }
+
+ public NullArgumentExceptionTest(String testName) {
+ super(testName);
+ }
+
+ // testConstructor
+
+ public void testConstructor_nullInput() {
+ new NullArgumentException(null);
+ }
+
+ // testGetMessage
+
+ public void testGetMessage_nullConstructorInput() {
+ final Throwable t = new NullArgumentException(null);
+ assertEquals("null cannot be null.", t.getMessage());
+ }
+
+ public void testGetMessage_validConstructorInput() {
+ final String argName = "name";
+ final Throwable t = new NullArgumentException(argName);
+ assertEquals(argName + " cannot be null.", t.getMessage());
+ }
+
+} // NullArgumentExceptionTest
+
diff --git a/examples/cl2/src/test/org/apache/commons/lang/NumberRangeTest.java b/examples/cl2/src/test/org/apache/commons/lang/NumberRangeTest.java
new file mode 100644
index 00000000..4c6e8d4d
--- /dev/null
+++ b/examples/cl2/src/test/org/apache/commons/lang/NumberRangeTest.java
@@ -0,0 +1,233 @@
+/* ====================================================================
+ * 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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
+ * .
+ */
+package org.apache.commons.lang;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+/**
+ * Test cases for the {@link NumberRange} class.
+ *
+ * @author Christopher Elkins
+ * @author Ringo De Smet
+ * @version $Revision: 1.4 $ $Date: 2003/03/23 21:49:13 $
+ */
+
+public final class NumberRangeTest extends TestCase {
+
+
+ private NumberRange tenToTwenty;
+ private Number five;
+ private Number ten;
+ private Number fifteen;
+ private Number twenty;
+ private Number twentyFive;
+
+
+ public NumberRangeTest(String name) {
+ super(name);
+ }
+
+
+ public void setUp() {
+ five = new Integer(5);
+ ten = new Integer(10);
+ fifteen = new Integer(15);
+ twenty = new Integer(20);
+ twentyFive = new Integer(25);
+
+ tenToTwenty = new NumberRange(ten, twenty);
+ }
+
+
+ public static Test suite() {
+ TestSuite suite = new TestSuite(NumberRangeTest.class);
+ suite.setName("NumberRange Tests");
+ return suite;
+ }
+
+ public void testMaxMin() {
+ boolean expected = true;
+ boolean result = tenToTwenty.getMaximum().equals(twenty);
+ assertEquals(expected, result);
+
+ expected = true;
+ result = tenToTwenty.getMinimum().equals(ten);
+ assertEquals(expected, result);
+ }
+
+ public void testEquals() {
+ boolean expected = false;
+ boolean result = tenToTwenty.equals(new NumberRange(five, ten));
+ assertEquals(expected, result);
+
+ expected = true;
+ result = tenToTwenty.equals(new NumberRange(ten, twenty));
+ assertEquals(expected, result);
+
+ expected = false;
+ result = tenToTwenty.equals(new NumberRange(ten, fifteen));
+ assertEquals(expected, result);
+
+ expected = false;
+ result = tenToTwenty.equals(new NumberRange(fifteen, twenty));
+ assertEquals(expected, result);
+ }
+
+
+ public void testIncludesNumber() {
+ boolean expected = false;
+ boolean result = tenToTwenty.includesNumber(five);
+ assertEquals(expected, result);
+
+ expected = true;
+ result = tenToTwenty.includesNumber(ten);
+ assertEquals(expected, result);
+
+ expected = true;
+ result = tenToTwenty.includesNumber(fifteen);
+ assertEquals(expected, result);
+
+ expected = true;
+ result = tenToTwenty.includesNumber(twenty);
+ assertEquals(expected, result);
+
+ expected = false;
+ result = tenToTwenty.includesNumber(twentyFive);
+ assertEquals(expected, result);
+ }
+
+
+ public void testIncludesRange() {
+ boolean expected = false;
+ boolean result = tenToTwenty.includesRange(new NumberRange(five, ten));
+ assertEquals(expected, result);
+
+ expected = false;
+ result = tenToTwenty.includesRange(new NumberRange(five, fifteen));
+ assertEquals(expected, result);
+
+ expected = true;
+ result = tenToTwenty.includesRange(new NumberRange(ten, fifteen));
+ assertEquals(expected, result);
+
+ expected = true;
+ result = tenToTwenty.includesRange(new NumberRange(ten, twenty));
+ assertEquals(expected, result);
+
+ expected = true;
+ result = tenToTwenty.includesRange(new NumberRange(fifteen, twenty));
+ assertEquals(expected, result);
+
+ expected = false;
+ result =
+ tenToTwenty.includesRange(new NumberRange(fifteen, twentyFive));
+ assertEquals(expected, result);
+
+ expected = false;
+ result =
+ tenToTwenty.includesRange(new NumberRange(twenty, twentyFive));
+ assertEquals(expected, result);
+ }
+
+ public void testConstructorNullParameters()
+ {
+ try
+ {
+ NumberRange nr = new NumberRange(null);
+ fail("NumberRange(null) did not throw an exception.");
+ }
+ catch (Exception e)
+ {
+ assertTrue(
+ "NumberRange(null)",
+ e instanceof NullPointerException);
+ }
+
+ try
+ {
+ NumberRange nr = new NumberRange(five, null);
+ fail("NumberRange(five, null) did not throw an exception.");
+ }
+ catch (Exception e)
+ {
+ assertTrue(
+ "NumberRange(five, null)",
+ e instanceof NullPointerException);
+ }
+
+ try
+ {
+ NumberRange nr = new NumberRange(null, five);
+ fail("NumberRange(null, five) did not throw an exception.");
+ }
+ catch (Exception e)
+ {
+ assertTrue(
+ "NumberRange(null, five)",
+ e instanceof NullPointerException);
+ }
+
+ }
+
+ public void testToString() {
+ String expected = "10-20";
+ String result = tenToTwenty.toString();
+ assertEquals(expected, result);
+ }
+
+
+}
+
diff --git a/examples/cl2/src/test/org/apache/commons/lang/NumberUtilsTest.java b/examples/cl2/src/test/org/apache/commons/lang/NumberUtilsTest.java
new file mode 100644
index 00000000..daf17aee
--- /dev/null
+++ b/examples/cl2/src/test/org/apache/commons/lang/NumberUtilsTest.java
@@ -0,0 +1,576 @@
+/* ====================================================================
+ * 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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
+ * .
+ */
+package org.apache.commons.lang;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+/**
+ * Unit tests {@link org.apache.commons.lang.NumberUtils}.
+ *
+ * @author Rand McNeely
+ * @author Ringo De Smet
+ * @author Eric Pugh
+ * @author Phil Steitz
+ * @author Stephen Colebourne
+ * @version $Id: NumberUtilsTest.java,v 1.7 2003/06/08 14:14:01 scolebourne Exp $
+ */
+public class NumberUtilsTest extends TestCase {
+
+ public NumberUtilsTest(String name) {
+ super(name);
+ }
+
+ public static Test suite() {
+ TestSuite suite = new TestSuite(NumberUtilsTest.class);
+ suite.setName("NumberUtils Tests");
+ return suite;
+ }
+
+ //---------------------------------------------------------------------
+
+ /**
+ * Test for int stringToInt(String)
+ */
+ public void testStringToIntString() {
+ assertTrue("stringToInt(String) 1 failed", NumberUtils.stringToInt("12345") == 12345);
+ assertTrue("stringToInt(String) 2 failed", NumberUtils.stringToInt("abc") == 0);
+ }
+
+ /**
+ * Test for int stringToInt(String, int)
+ */
+ public void testStringToIntStringI() {
+ assertTrue("stringToInt(String,int) 1 failed", NumberUtils.stringToInt("12345", 5) == 12345);
+ assertTrue("stringToInt(String,int) 2 failed", NumberUtils.stringToInt("1234.5", 5) == 5);
+ }
+
+ public void testCreateNumber() {
+ //a lot of things can go wrong
+ assertEquals("createNumber(String) 1 failed", new Float("1234.5"), NumberUtils.createNumber("1234.5"));
+ assertEquals("createNumber(String) 2 failed", new Integer("12345"), NumberUtils.createNumber("12345"));
+ assertEquals("createNumber(String) 3 failed", new Double("1234.5"), NumberUtils.createNumber("1234.5D"));
+ assertEquals("createNumber(String) 4 failed", new Float("1234.5"), NumberUtils.createNumber("1234.5F"));
+ assertEquals("createNumber(String) 5 failed", new Long(Integer.MAX_VALUE + 1L), NumberUtils.createNumber("" + (Integer.MAX_VALUE + 1L)));
+ assertEquals("createNumber(String) 6 failed", new Long(12345), NumberUtils.createNumber("12345L"));
+ assertEquals("createNumber(String) 7 failed", new Float("-1234.5"), NumberUtils.createNumber("-1234.5"));
+ assertEquals("createNumber(String) 8 failed", new Integer("-12345"), NumberUtils.createNumber("-12345"));
+ assertTrue("createNumber(String) 9 failed", 0xFADE == NumberUtils.createNumber("0xFADE").intValue());
+ assertTrue("createNumber(String) 10 failed", -0xFADE == NumberUtils.createNumber("-0xFADE").intValue());
+ assertEquals("createNumber(String) 11 failed", new Double("1.1E200"), NumberUtils.createNumber("1.1E200"));
+ assertEquals("createNumber(String) 12 failed", new Float("1.1E20"), NumberUtils.createNumber("1.1E20"));
+ assertEquals("createNumber(String) 13 failed", new Double("-1.1E200"), NumberUtils.createNumber("-1.1E200"));
+ assertEquals("createNumber(String) 14 failed", new Double("1.1E-200"), NumberUtils.createNumber("1.1E-200"));
+
+ // jdk 1.2 doesn't support this. unsure about jdk 1.2.2
+ if(SystemUtils.isJavaVersionAtLeast(1.3f)) {
+ assertEquals("createNumber(String) 15 failed", new BigDecimal("1.1E-700"), NumberUtils.createNumber("1.1E-700F"));
+ }
+ assertEquals(
+ "createNumber(String) 16 failed",
+ new Long("10" + Integer.MAX_VALUE),
+ NumberUtils.createNumber("10" + Integer.MAX_VALUE + "L"));
+ assertEquals(
+ "createNumber(String) 17 failed",
+ new Long("10" + Integer.MAX_VALUE),
+ NumberUtils.createNumber("10" + Integer.MAX_VALUE));
+ assertEquals(
+ "createNumber(String) 18 failed",
+ new BigInteger("10" + Long.MAX_VALUE),
+ NumberUtils.createNumber("10" + Long.MAX_VALUE));
+
+ }
+
+ public void testCreateFloat() {
+ assertEquals("createFloat(String) failed", new Float("1234.5"), NumberUtils.createFloat("1234.5"));
+ }
+
+ public void testCreateDouble() {
+ assertEquals("createDouble(String) failed", new Double("1234.5"), NumberUtils.createDouble("1234.5"));
+ }
+
+ public void testCreateInteger() {
+ assertEquals("createInteger(String) failed", new Integer("12345"), NumberUtils.createInteger("12345"));
+ }
+
+ public void testCreateLong() {
+ assertEquals("createInteger(String) failed", new Long("12345"), NumberUtils.createLong("12345"));
+ }
+
+ public void testCreateBigInteger() {
+ assertEquals("createBigInteger(String) failed", new BigInteger("12345"), NumberUtils.createBigInteger("12345"));
+ }
+
+ public void testCreateBigDecimal() {
+ assertEquals("createBigDecimal(String) failed", new BigDecimal("1234.5"), NumberUtils.createBigDecimal("1234.5"));
+ }
+
+ public void testMinimumLong() {
+ assertEquals("minimum(long,long,long) 1 failed", 12345L, NumberUtils.minimum(12345L, 12345L + 1L, 12345L + 2L));
+ assertEquals("minimum(long,long,long) 2 failed", 12345L, NumberUtils.minimum(12345L + 1L, 12345L, 12345 + 2L));
+ assertEquals("minimum(long,long,long) 3 failed", 12345L, NumberUtils.minimum(12345L + 1L, 12345L + 2L, 12345L));
+ assertEquals("minimum(long,long,long) 4 failed", 12345L, NumberUtils.minimum(12345L + 1L, 12345L, 12345L));
+ assertEquals("minimum(long,long,long) 5 failed", 12345L, NumberUtils.minimum(12345L, 12345L, 12345L));
+
+ }
+
+ public void testMinimumInt() {
+ assertEquals("minimum(int,int,int) 1 failed", 12345, NumberUtils.minimum(12345, 12345 + 1, 12345 + 2));
+ assertEquals("minimum(int,int,int) 2 failed", 12345, NumberUtils.minimum(12345 + 1, 12345, 12345 + 2));
+ assertEquals("minimum(int,int,int) 3 failed", 12345, NumberUtils.minimum(12345 + 1, 12345 + 2, 12345));
+ assertEquals("minimum(int,int,int) 4 failed", 12345, NumberUtils.minimum(12345 + 1, 12345, 12345));
+ assertEquals("minimum(int,int,int) 5 failed", 12345, NumberUtils.minimum(12345, 12345, 12345));
+
+ }
+
+ public void testMaximumLong() {
+ assertEquals("maximum(long,long,long) 1 failed", 12345L, NumberUtils.maximum(12345L, 12345L - 1L, 12345L - 2L));
+ assertEquals("maximum(long,long,long) 2 failed", 12345L, NumberUtils.maximum(12345L - 1L, 12345L, 12345L - 2L));
+ assertEquals("maximum(long,long,long) 3 failed", 12345L, NumberUtils.maximum(12345L - 1L, 12345L - 2L, 12345L));
+ assertEquals("maximum(long,long,long) 4 failed", 12345L, NumberUtils.maximum(12345L - 1L, 12345L, 12345L));
+ assertEquals("maximum(long,long,long) 5 failed", 12345L, NumberUtils.maximum(12345L, 12345L, 12345L));
+
+ }
+
+ public void testMaximumInt() {
+ assertEquals("maximum(int,int,int) 1 failed", 12345, NumberUtils.maximum(12345, 12345 - 1, 12345 - 2));
+ assertEquals("maximum(int,int,int) 2 failed", 12345, NumberUtils.maximum(12345 - 1, 12345, 12345 - 2));
+ assertEquals("maximum(int,int,int) 3 failed", 12345, NumberUtils.maximum(12345 - 1, 12345 - 2, 12345));
+ assertEquals("maximum(int,int,int) 4 failed", 12345, NumberUtils.maximum(12345 - 1, 12345, 12345));
+ assertEquals("maximum(int,int,int) 5 failed", 12345, NumberUtils.maximum(12345, 12345, 12345));
+
+ }
+
+ public void testCompareDouble() {
+ assertTrue(NumberUtils.compare(Double.NaN, Double.NaN) == 0);
+ assertTrue(NumberUtils.compare(Double.NaN, Double.POSITIVE_INFINITY) == +1);
+ assertTrue(NumberUtils.compare(Double.NaN, Double.MAX_VALUE) == +1);
+ assertTrue(NumberUtils.compare(Double.NaN, 1.2d) == +1);
+ assertTrue(NumberUtils.compare(Double.NaN, 0.0d) == +1);
+ assertTrue(NumberUtils.compare(Double.NaN, -0.0d) == +1);
+ assertTrue(NumberUtils.compare(Double.NaN, -1.2d) == +1);
+ assertTrue(NumberUtils.compare(Double.NaN, -Double.MAX_VALUE) == +1);
+ assertTrue(NumberUtils.compare(Double.NaN, Double.NEGATIVE_INFINITY) == +1);
+
+ assertTrue(NumberUtils.compare(Double.POSITIVE_INFINITY, Double.NaN) == -1);
+ assertTrue(NumberUtils.compare(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY) == 0);
+ assertTrue(NumberUtils.compare(Double.POSITIVE_INFINITY, Double.MAX_VALUE) == +1);
+ assertTrue(NumberUtils.compare(Double.POSITIVE_INFINITY, 1.2d) == +1);
+ assertTrue(NumberUtils.compare(Double.POSITIVE_INFINITY, 0.0d) == +1);
+ assertTrue(NumberUtils.compare(Double.POSITIVE_INFINITY, -0.0d) == +1);
+ assertTrue(NumberUtils.compare(Double.POSITIVE_INFINITY, -1.2d) == +1);
+ assertTrue(NumberUtils.compare(Double.POSITIVE_INFINITY, -Double.MAX_VALUE) == +1);
+ assertTrue(NumberUtils.compare(Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY) == +1);
+
+ assertTrue(NumberUtils.compare(Double.MAX_VALUE, Double.NaN) == -1);
+ assertTrue(NumberUtils.compare(Double.MAX_VALUE, Double.POSITIVE_INFINITY) == -1);
+ assertTrue(NumberUtils.compare(Double.MAX_VALUE, Double.MAX_VALUE) == 0);
+ assertTrue(NumberUtils.compare(Double.MAX_VALUE, 1.2d) == +1);
+ assertTrue(NumberUtils.compare(Double.MAX_VALUE, 0.0d) == +1);
+ assertTrue(NumberUtils.compare(Double.MAX_VALUE, -0.0d) == +1);
+ assertTrue(NumberUtils.compare(Double.MAX_VALUE, -1.2d) == +1);
+ assertTrue(NumberUtils.compare(Double.MAX_VALUE, -Double.MAX_VALUE) == +1);
+ assertTrue(NumberUtils.compare(Double.MAX_VALUE, Double.NEGATIVE_INFINITY) == +1);
+
+ assertTrue(NumberUtils.compare(1.2d, Double.NaN) == -1);
+ assertTrue(NumberUtils.compare(1.2d, Double.POSITIVE_INFINITY) == -1);
+ assertTrue(NumberUtils.compare(1.2d, Double.MAX_VALUE) == -1);
+ assertTrue(NumberUtils.compare(1.2d, 1.2d) == 0);
+ assertTrue(NumberUtils.compare(1.2d, 0.0d) == +1);
+ assertTrue(NumberUtils.compare(1.2d, -0.0d) == +1);
+ assertTrue(NumberUtils.compare(1.2d, -1.2d) == +1);
+ assertTrue(NumberUtils.compare(1.2d, -Double.MAX_VALUE) == +1);
+ assertTrue(NumberUtils.compare(1.2d, Double.NEGATIVE_INFINITY) == +1);
+
+ assertTrue(NumberUtils.compare(0.0d, Double.NaN) == -1);
+ assertTrue(NumberUtils.compare(0.0d, Double.POSITIVE_INFINITY) == -1);
+ assertTrue(NumberUtils.compare(0.0d, Double.MAX_VALUE) == -1);
+ assertTrue(NumberUtils.compare(0.0d, 1.2d) == -1);
+ assertTrue(NumberUtils.compare(0.0d, 0.0d) == 0);
+ assertTrue(NumberUtils.compare(0.0d, -0.0d) == +1);
+ assertTrue(NumberUtils.compare(0.0d, -1.2d) == +1);
+ assertTrue(NumberUtils.compare(0.0d, -Double.MAX_VALUE) == +1);
+ assertTrue(NumberUtils.compare(0.0d, Double.NEGATIVE_INFINITY) == +1);
+
+ assertTrue(NumberUtils.compare(-0.0d, Double.NaN) == -1);
+ assertTrue(NumberUtils.compare(-0.0d, Double.POSITIVE_INFINITY) == -1);
+ assertTrue(NumberUtils.compare(-0.0d, Double.MAX_VALUE) == -1);
+ assertTrue(NumberUtils.compare(-0.0d, 1.2d) == -1);
+ assertTrue(NumberUtils.compare(-0.0d, 0.0d) == -1);
+ assertTrue(NumberUtils.compare(-0.0d, -0.0d) == 0);
+ assertTrue(NumberUtils.compare(-0.0d, -1.2d) == +1);
+ assertTrue(NumberUtils.compare(-0.0d, -Double.MAX_VALUE) == +1);
+ assertTrue(NumberUtils.compare(-0.0d, Double.NEGATIVE_INFINITY) == +1);
+
+ assertTrue(NumberUtils.compare(-1.2d, Double.NaN) == -1);
+ assertTrue(NumberUtils.compare(-1.2d, Double.POSITIVE_INFINITY) == -1);
+ assertTrue(NumberUtils.compare(-1.2d, Double.MAX_VALUE) == -1);
+ assertTrue(NumberUtils.compare(-1.2d, 1.2d) == -1);
+ assertTrue(NumberUtils.compare(-1.2d, 0.0d) == -1);
+ assertTrue(NumberUtils.compare(-1.2d, -0.0d) == -1);
+ assertTrue(NumberUtils.compare(-1.2d, -1.2d) == 0);
+ assertTrue(NumberUtils.compare(-1.2d, -Double.MAX_VALUE) == +1);
+ assertTrue(NumberUtils.compare(-1.2d, Double.NEGATIVE_INFINITY) == +1);
+
+ assertTrue(NumberUtils.compare(-Double.MAX_VALUE, Double.NaN) == -1);
+ assertTrue(NumberUtils.compare(-Double.MAX_VALUE, Double.POSITIVE_INFINITY) == -1);
+ assertTrue(NumberUtils.compare(-Double.MAX_VALUE, Double.MAX_VALUE) == -1);
+ assertTrue(NumberUtils.compare(-Double.MAX_VALUE, 1.2d) == -1);
+ assertTrue(NumberUtils.compare(-Double.MAX_VALUE, 0.0d) == -1);
+ assertTrue(NumberUtils.compare(-Double.MAX_VALUE, -0.0d) == -1);
+ assertTrue(NumberUtils.compare(-Double.MAX_VALUE, -1.2d) == -1);
+ assertTrue(NumberUtils.compare(-Double.MAX_VALUE, -Double.MAX_VALUE) == 0);
+ assertTrue(NumberUtils.compare(-Double.MAX_VALUE, Double.NEGATIVE_INFINITY) == +1);
+
+ assertTrue(NumberUtils.compare(Double.NEGATIVE_INFINITY, Double.NaN) == -1);
+ assertTrue(NumberUtils.compare(Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY) == -1);
+ assertTrue(NumberUtils.compare(Double.NEGATIVE_INFINITY, Double.MAX_VALUE) == -1);
+ assertTrue(NumberUtils.compare(Double.NEGATIVE_INFINITY, 1.2d) == -1);
+ assertTrue(NumberUtils.compare(Double.NEGATIVE_INFINITY, 0.0d) == -1);
+ assertTrue(NumberUtils.compare(Double.NEGATIVE_INFINITY, -0.0d) == -1);
+ assertTrue(NumberUtils.compare(Double.NEGATIVE_INFINITY, -1.2d) == -1);
+ assertTrue(NumberUtils.compare(Double.NEGATIVE_INFINITY, -Double.MAX_VALUE) == -1);
+ assertTrue(NumberUtils.compare(Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY) == 0);
+ }
+
+ public void testCompareFloat() {
+ assertTrue(NumberUtils.compare(Float.NaN, Float.NaN) == 0);
+ assertTrue(NumberUtils.compare(Float.NaN, Float.POSITIVE_INFINITY) == +1);
+ assertTrue(NumberUtils.compare(Float.NaN, Float.MAX_VALUE) == +1);
+ assertTrue(NumberUtils.compare(Float.NaN, 1.2f) == +1);
+ assertTrue(NumberUtils.compare(Float.NaN, 0.0f) == +1);
+ assertTrue(NumberUtils.compare(Float.NaN, -0.0f) == +1);
+ assertTrue(NumberUtils.compare(Float.NaN, -1.2f) == +1);
+ assertTrue(NumberUtils.compare(Float.NaN, -Float.MAX_VALUE) == +1);
+ assertTrue(NumberUtils.compare(Float.NaN, Float.NEGATIVE_INFINITY) == +1);
+
+ assertTrue(NumberUtils.compare(Float.POSITIVE_INFINITY, Float.NaN) == -1);
+ assertTrue(NumberUtils.compare(Float.POSITIVE_INFINITY, Float.POSITIVE_INFINITY) == 0);
+ assertTrue(NumberUtils.compare(Float.POSITIVE_INFINITY, Float.MAX_VALUE) == +1);
+ assertTrue(NumberUtils.compare(Float.POSITIVE_INFINITY, 1.2f) == +1);
+ assertTrue(NumberUtils.compare(Float.POSITIVE_INFINITY, 0.0f) == +1);
+ assertTrue(NumberUtils.compare(Float.POSITIVE_INFINITY, -0.0f) == +1);
+ assertTrue(NumberUtils.compare(Float.POSITIVE_INFINITY, -1.2f) == +1);
+ assertTrue(NumberUtils.compare(Float.POSITIVE_INFINITY, -Float.MAX_VALUE) == +1);
+ assertTrue(NumberUtils.compare(Float.POSITIVE_INFINITY, Float.NEGATIVE_INFINITY) == +1);
+
+ assertTrue(NumberUtils.compare(Float.MAX_VALUE, Float.NaN) == -1);
+ assertTrue(NumberUtils.compare(Float.MAX_VALUE, Float.POSITIVE_INFINITY) == -1);
+ assertTrue(NumberUtils.compare(Float.MAX_VALUE, Float.MAX_VALUE) == 0);
+ assertTrue(NumberUtils.compare(Float.MAX_VALUE, 1.2f) == +1);
+ assertTrue(NumberUtils.compare(Float.MAX_VALUE, 0.0f) == +1);
+ assertTrue(NumberUtils.compare(Float.MAX_VALUE, -0.0f) == +1);
+ assertTrue(NumberUtils.compare(Float.MAX_VALUE, -1.2f) == +1);
+ assertTrue(NumberUtils.compare(Float.MAX_VALUE, -Float.MAX_VALUE) == +1);
+ assertTrue(NumberUtils.compare(Float.MAX_VALUE, Float.NEGATIVE_INFINITY) == +1);
+
+ assertTrue(NumberUtils.compare(1.2f, Float.NaN) == -1);
+ assertTrue(NumberUtils.compare(1.2f, Float.POSITIVE_INFINITY) == -1);
+ assertTrue(NumberUtils.compare(1.2f, Float.MAX_VALUE) == -1);
+ assertTrue(NumberUtils.compare(1.2f, 1.2f) == 0);
+ assertTrue(NumberUtils.compare(1.2f, 0.0f) == +1);
+ assertTrue(NumberUtils.compare(1.2f, -0.0f) == +1);
+ assertTrue(NumberUtils.compare(1.2f, -1.2f) == +1);
+ assertTrue(NumberUtils.compare(1.2f, -Float.MAX_VALUE) == +1);
+ assertTrue(NumberUtils.compare(1.2f, Float.NEGATIVE_INFINITY) == +1);
+
+ assertTrue(NumberUtils.compare(0.0f, Float.NaN) == -1);
+ assertTrue(NumberUtils.compare(0.0f, Float.POSITIVE_INFINITY) == -1);
+ assertTrue(NumberUtils.compare(0.0f, Float.MAX_VALUE) == -1);
+ assertTrue(NumberUtils.compare(0.0f, 1.2f) == -1);
+ assertTrue(NumberUtils.compare(0.0f, 0.0f) == 0);
+ assertTrue(NumberUtils.compare(0.0f, -0.0f) == +1);
+ assertTrue(NumberUtils.compare(0.0f, -1.2f) == +1);
+ assertTrue(NumberUtils.compare(0.0f, -Float.MAX_VALUE) == +1);
+ assertTrue(NumberUtils.compare(0.0f, Float.NEGATIVE_INFINITY) == +1);
+
+ assertTrue(NumberUtils.compare(-0.0f, Float.NaN) == -1);
+ assertTrue(NumberUtils.compare(-0.0f, Float.POSITIVE_INFINITY) == -1);
+ assertTrue(NumberUtils.compare(-0.0f, Float.MAX_VALUE) == -1);
+ assertTrue(NumberUtils.compare(-0.0f, 1.2f) == -1);
+ assertTrue(NumberUtils.compare(-0.0f, 0.0f) == -1);
+ assertTrue(NumberUtils.compare(-0.0f, -0.0f) == 0);
+ assertTrue(NumberUtils.compare(-0.0f, -1.2f) == +1);
+ assertTrue(NumberUtils.compare(-0.0f, -Float.MAX_VALUE) == +1);
+ assertTrue(NumberUtils.compare(-0.0f, Float.NEGATIVE_INFINITY) == +1);
+
+ assertTrue(NumberUtils.compare(-1.2f, Float.NaN) == -1);
+ assertTrue(NumberUtils.compare(-1.2f, Float.POSITIVE_INFINITY) == -1);
+ assertTrue(NumberUtils.compare(-1.2f, Float.MAX_VALUE) == -1);
+ assertTrue(NumberUtils.compare(-1.2f, 1.2f) == -1);
+ assertTrue(NumberUtils.compare(-1.2f, 0.0f) == -1);
+ assertTrue(NumberUtils.compare(-1.2f, -0.0f) == -1);
+ assertTrue(NumberUtils.compare(-1.2f, -1.2f) == 0);
+ assertTrue(NumberUtils.compare(-1.2f, -Float.MAX_VALUE) == +1);
+ assertTrue(NumberUtils.compare(-1.2f, Float.NEGATIVE_INFINITY) == +1);
+
+ assertTrue(NumberUtils.compare(-Float.MAX_VALUE, Float.NaN) == -1);
+ assertTrue(NumberUtils.compare(-Float.MAX_VALUE, Float.POSITIVE_INFINITY) == -1);
+ assertTrue(NumberUtils.compare(-Float.MAX_VALUE, Float.MAX_VALUE) == -1);
+ assertTrue(NumberUtils.compare(-Float.MAX_VALUE, 1.2f) == -1);
+ assertTrue(NumberUtils.compare(-Float.MAX_VALUE, 0.0f) == -1);
+ assertTrue(NumberUtils.compare(-Float.MAX_VALUE, -0.0f) == -1);
+ assertTrue(NumberUtils.compare(-Float.MAX_VALUE, -1.2f) == -1);
+ assertTrue(NumberUtils.compare(-Float.MAX_VALUE, -Float.MAX_VALUE) == 0);
+ assertTrue(NumberUtils.compare(-Float.MAX_VALUE, Float.NEGATIVE_INFINITY) == +1);
+
+ assertTrue(NumberUtils.compare(Float.NEGATIVE_INFINITY, Float.NaN) == -1);
+ assertTrue(NumberUtils.compare(Float.NEGATIVE_INFINITY, Float.POSITIVE_INFINITY) == -1);
+ assertTrue(NumberUtils.compare(Float.NEGATIVE_INFINITY, Float.MAX_VALUE) == -1);
+ assertTrue(NumberUtils.compare(Float.NEGATIVE_INFINITY, 1.2f) == -1);
+ assertTrue(NumberUtils.compare(Float.NEGATIVE_INFINITY, 0.0f) == -1);
+ assertTrue(NumberUtils.compare(Float.NEGATIVE_INFINITY, -0.0f) == -1);
+ assertTrue(NumberUtils.compare(Float.NEGATIVE_INFINITY, -1.2f) == -1);
+ assertTrue(NumberUtils.compare(Float.NEGATIVE_INFINITY, -Float.MAX_VALUE) == -1);
+ assertTrue(NumberUtils.compare(Float.NEGATIVE_INFINITY, Float.NEGATIVE_INFINITY) == 0);
+ }
+
+ public void testIsDigits() {
+ assertEquals("isDigits(null) failed", false, NumberUtils.isDigits(null));
+ assertEquals("isDigits('') failed", false, NumberUtils.isDigits(""));
+ assertEquals("isDigits(String) failed", true, NumberUtils.isDigits("12345"));
+ assertEquals("isDigits(String) neg 1 failed", false, NumberUtils.isDigits("1234.5"));
+ assertEquals("isDigits(String) neg 3 failed", false, NumberUtils.isDigits("1ab"));
+ assertEquals("isDigits(String) neg 4 failed", false, NumberUtils.isDigits("abc"));
+ }
+
+ /**
+ * Tests isNumber(String) and tests that createNumber(String) returns
+ * a valid number iff isNumber(String) returns false.
+ */
+ public void testIsNumber() {
+ String val = "12345";
+ assertTrue("isNumber(String) 1 failed", NumberUtils.isNumber(val));
+ assertTrue("isNumber(String)/createNumber(String) 1 failed", checkCreateNumber(val));
+ val = "1234.5";
+ assertTrue("isNumber(String) 2 failed", NumberUtils.isNumber(val));
+ assertTrue("isNumber(String)/createNumber(String) 2 failed", checkCreateNumber(val));
+ val = ".12345";
+ assertTrue("isNumber(String) 3 failed", NumberUtils.isNumber(val));
+ assertTrue("isNumber(String)/createNumber(String) 3 failed", checkCreateNumber(val));
+ val = "1234E5";
+ assertTrue("isNumber(String) 4 failed", NumberUtils.isNumber(val));
+ assertTrue("isNumber(String)/createNumber(String) 4 failed", checkCreateNumber(val));
+ val = "1234E+5";
+ assertTrue("isNumber(String) 5 failed", NumberUtils.isNumber(val));
+ assertTrue("isNumber(String)/createNumber(String) 5 failed", checkCreateNumber(val));
+ val = "1234E-5";
+ assertTrue("isNumber(String) 6 failed", NumberUtils.isNumber(val));
+ assertTrue("isNumber(String)/createNumber(String) 6 failed", checkCreateNumber(val));
+ val = "123.4E5";
+ assertTrue("isNumber(String) 7 failed", NumberUtils.isNumber(val));
+ assertTrue("isNumber(String)/createNumber(String) 7 failed", checkCreateNumber(val));
+ val = "-1234";
+ assertTrue("isNumber(String) 8 failed", NumberUtils.isNumber(val));
+ assertTrue("isNumber(String)/createNumber(String) 8 failed", checkCreateNumber(val));
+ val = "-1234.5";
+ assertTrue("isNumber(String) 9 failed", NumberUtils.isNumber(val));
+ assertTrue("isNumber(String)/createNumber(String) 9 failed", checkCreateNumber(val));
+ val = "-.12345";
+ assertTrue("isNumber(String) 10 failed", NumberUtils.isNumber(val));
+ assertTrue("isNumber(String)/createNumber(String) 10 failed", checkCreateNumber(val));
+ val = "-1234E5";
+ assertTrue("isNumber(String) 11 failed", NumberUtils.isNumber(val));
+ assertTrue("isNumber(String)/createNumber(String) 11 failed", checkCreateNumber(val));
+ val = "0";
+ assertTrue("isNumber(String) 12 failed", NumberUtils.isNumber(val));
+ assertTrue("isNumber(String)/createNumber(String) 12 failed", checkCreateNumber(val));
+ val = "-0";
+ assertTrue("isNumber(String) 13 failed", NumberUtils.isNumber(val));
+ assertTrue("isNumber(String)/createNumber(String) 13 failed", checkCreateNumber(val));
+ val = "01234";
+ assertTrue("isNumber(String) 14 failed", NumberUtils.isNumber(val));
+ assertTrue("isNumber(String)/createNumber(String) 14 failed", checkCreateNumber(val));
+ val = "-01234";
+ assertTrue("isNumber(String) 15 failed", NumberUtils.isNumber(val));
+ assertTrue("isNumber(String)/createNumber(String) 15 failed", checkCreateNumber(val));
+ val = "0xABC123";
+ assertTrue("isNumber(String) 16 failed", NumberUtils.isNumber(val));
+ assertTrue("isNumber(String)/createNumber(String) 16 failed", checkCreateNumber(val));
+ val = "0x0";
+ assertTrue("isNumber(String) 17 failed", NumberUtils.isNumber(val));
+ assertTrue("isNumber(String)/createNumber(String) 17 failed", checkCreateNumber(val));
+ val = "123.4E21D";
+ assertTrue("isNumber(String) 19 failed", NumberUtils.isNumber(val));
+ assertTrue("isNumber(String)/createNumber(String) 19 failed", checkCreateNumber(val));
+ val = "-221.23F";
+ assertTrue("isNumber(String) 20 failed", NumberUtils.isNumber(val));
+ assertTrue("isNumber(String)/createNumber(String) 20 failed", checkCreateNumber(val));
+ val = "22338L";
+ assertTrue("isNumber(String) 21 failed", NumberUtils.isNumber(val));
+ assertTrue("isNumber(String)/createNumber(String) 21 failed", checkCreateNumber(val));
+ val = null;
+ assertTrue("isNumber(String) 1 Neg failed", !NumberUtils.isNumber(val));
+ assertTrue("isNumber(String)/createNumber(String) 1 Neg failed", !checkCreateNumber(val));
+ val = "";
+ assertTrue("isNumber(String) 2 Neg failed", !NumberUtils.isNumber(val));
+ assertTrue("isNumber(String)/createNumber(String) 2 Neg failed", !checkCreateNumber(val));
+ val = "--2.3";
+ assertTrue("isNumber(String) 3 Neg failed", !NumberUtils.isNumber(val));
+ assertTrue("isNumber(String)/createNumber(String) 3 Neg failed", !checkCreateNumber(val));
+ val = ".12.3";
+ assertTrue("isNumber(String) 4 Neg failed", !NumberUtils.isNumber(val));
+ assertTrue("isNumber(String)/createNumber(String) 4 Neg failed", !checkCreateNumber(val));
+ val = "-123E";
+ assertTrue("isNumber(String) 5 Neg failed", !NumberUtils.isNumber(val));
+ assertTrue("isNumber(String)/createNumber(String) 5 Neg failed", !checkCreateNumber(val));
+ val = "-123E+-212";
+ assertTrue("isNumber(String) 6 Neg failed", !NumberUtils.isNumber(val));
+ assertTrue("isNumber(String)/createNumber(String) 6 Neg failed", !checkCreateNumber(val));
+ val = "-123E2.12";
+ assertTrue("isNumber(String) 7 Neg failed", !NumberUtils.isNumber(val));
+ assertTrue("isNumber(String)/createNumber(String) 7 Neg failed", !checkCreateNumber(val));
+ val = "0xGF";
+ assertTrue("isNumber(String) 8 Neg failed", !NumberUtils.isNumber(val));
+ assertTrue("isNumber(String)/createNumber(String) 8 Neg failed", !checkCreateNumber(val));
+ val = "0xFAE-1";
+ assertTrue("isNumber(String) 9 Neg failed", !NumberUtils.isNumber(val));
+ assertTrue("isNumber(String)/createNumber(String) 9 Neg failed", !checkCreateNumber(val));
+ val = ".";
+ assertTrue("isNumber(String) 10 Neg failed", !NumberUtils.isNumber(val));
+ assertTrue("isNumber(String)/createNumber(String) 10 Neg failed", !checkCreateNumber(val));
+ val = "-0ABC123";
+ assertTrue("isNumber(String) 11 Neg failed", !NumberUtils.isNumber(val));
+ assertTrue("isNumber(String)/createNumber(String) 11 Neg failed", !checkCreateNumber(val));
+ val = "123.4E-D";
+ assertTrue("isNumber(String) 12 Neg failed", !NumberUtils.isNumber(val));
+ assertTrue("isNumber(String)/createNumber(String) 12 Neg failed", !checkCreateNumber(val));
+ val = "123.4ED";
+ assertTrue("isNumber(String) 13 Neg failed", !NumberUtils.isNumber(val));
+ assertTrue("isNumber(String)/createNumber(String) 13 Neg failed", !checkCreateNumber(val));
+ val = "1234E5l";
+ assertTrue("isNumber(String) 14 Neg failed", !NumberUtils.isNumber(val));
+ assertTrue("isNumber(String)/createNumber(String) 14 Neg failed", !checkCreateNumber(val));
+ val = "11a";
+ assertTrue("isNumber(String) 15 Neg failed", !NumberUtils.isNumber(val));
+ assertTrue("isNumber(String)/createNumber(String) 15 Neg failed", !checkCreateNumber(val));
+ val = "1a";
+ assertTrue("isNumber(String) 16 Neg failed", !NumberUtils.isNumber(val));
+ assertTrue("isNumber(String)/createNumber(String) 16 Neg failed", !checkCreateNumber(val));
+ val = "a";
+ assertTrue("isNumber(String) 17 Neg failed", !NumberUtils.isNumber(val));
+ assertTrue("isNumber(String)/createNumber(String) 17 Neg failed", !checkCreateNumber(val));
+ val = "11g";
+ assertTrue("isNumber(String) 18 Neg failed", !NumberUtils.isNumber(val));
+ assertTrue("isNumber(String)/createNumber(String) 18 Neg failed", !checkCreateNumber(val));
+ val = "11z";
+ assertTrue("isNumber(String) 19 Neg failed", !NumberUtils.isNumber(val));
+ assertTrue("isNumber(String)/createNumber(String) 19 Neg failed", !checkCreateNumber(val));
+ val = "11def";
+ assertTrue("isNumber(String) 20 Neg failed", !NumberUtils.isNumber(val));
+ assertTrue("isNumber(String)/createNumber(String) 20 Neg failed", !checkCreateNumber(val));
+ val = "11d11";
+ assertTrue("isNumber(String) 21 Neg failed", !NumberUtils.isNumber(val));
+ assertTrue("isNumber(String)/createNumber(String) 21 Neg failed", !checkCreateNumber(val));
+
+ }
+
+ private boolean checkCreateNumber(String val) {
+ try {
+ Object obj = NumberUtils.createNumber(val);
+ if (obj == null) {
+ return false;
+ }
+ return true;
+ } catch (NumberFormatException e) {
+ return false;
+ } catch (NullPointerException e) {
+ return false;
+ }
+ }
+
+ public void testConstants() {
+ assertTrue(NumberUtils.LONG_ZERO instanceof Long);
+ assertTrue(NumberUtils.LONG_ONE instanceof Long);
+ assertTrue(NumberUtils.LONG_MINUS_ONE instanceof Long);
+ assertTrue(NumberUtils.INTEGER_ZERO instanceof Integer);
+ assertTrue(NumberUtils.INTEGER_ONE instanceof Integer);
+ assertTrue(NumberUtils.INTEGER_MINUS_ONE instanceof Integer);
+ assertTrue(NumberUtils.SHORT_ZERO instanceof Short);
+ assertTrue(NumberUtils.SHORT_ONE instanceof Short);
+ assertTrue(NumberUtils.SHORT_MINUS_ONE instanceof Short);
+ assertTrue(NumberUtils.BYTE_ZERO instanceof Byte);
+ assertTrue(NumberUtils.BYTE_ONE instanceof Byte);
+ assertTrue(NumberUtils.BYTE_MINUS_ONE instanceof Byte);
+ assertTrue(NumberUtils.DOUBLE_ZERO instanceof Double);
+ assertTrue(NumberUtils.DOUBLE_ONE instanceof Double);
+ assertTrue(NumberUtils.DOUBLE_MINUS_ONE instanceof Double);
+ assertTrue(NumberUtils.FLOAT_ZERO instanceof Float);
+ assertTrue(NumberUtils.FLOAT_ONE instanceof Float);
+ assertTrue(NumberUtils.FLOAT_MINUS_ONE instanceof Float);
+
+ assertTrue(NumberUtils.LONG_ZERO.longValue() == 0);
+ assertTrue(NumberUtils.LONG_ONE.longValue() == 1);
+ assertTrue(NumberUtils.LONG_MINUS_ONE.longValue() == -1);
+ assertTrue(NumberUtils.INTEGER_ZERO.intValue() == 0);
+ assertTrue(NumberUtils.INTEGER_ONE.intValue() == 1);
+ assertTrue(NumberUtils.INTEGER_MINUS_ONE.intValue() == -1);
+ assertTrue(NumberUtils.SHORT_ZERO.shortValue() == 0);
+ assertTrue(NumberUtils.SHORT_ONE.shortValue() == 1);
+ assertTrue(NumberUtils.SHORT_MINUS_ONE.shortValue() == -1);
+ assertTrue(NumberUtils.BYTE_ZERO.byteValue() == 0);
+ assertTrue(NumberUtils.BYTE_ONE.byteValue() == 1);
+ assertTrue(NumberUtils.BYTE_MINUS_ONE.byteValue() == -1);
+ assertTrue(NumberUtils.DOUBLE_ZERO.doubleValue() == 0.0d);
+ assertTrue(NumberUtils.DOUBLE_ONE.doubleValue() == 1.0d);
+ assertTrue(NumberUtils.DOUBLE_MINUS_ONE.doubleValue() == -1.0d);
+ assertTrue(NumberUtils.FLOAT_ZERO.floatValue() == 0.0f);
+ assertTrue(NumberUtils.FLOAT_ONE.floatValue() == 1.0f);
+ assertTrue(NumberUtils.FLOAT_MINUS_ONE.floatValue() == -1.0f);
+ }
+}
diff --git a/examples/cl2/src/test/org/apache/commons/lang/ObjectUtilsTest.java b/examples/cl2/src/test/org/apache/commons/lang/ObjectUtilsTest.java
new file mode 100644
index 00000000..114f675f
--- /dev/null
+++ b/examples/cl2/src/test/org/apache/commons/lang/ObjectUtilsTest.java
@@ -0,0 +1,129 @@
+/* ====================================================================
+ * 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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
+ * .
+ */
+package org.apache.commons.lang;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import junit.textui.TestRunner;
+
+/**
+ * Unit tests {@link org.apache.commons.lang.ObjectUtils}.
+ *
+ * @author John McNally
+ * @author Stephen Colebourne
+ * @author Ringo De Smet
+ * @version $Id: ObjectUtilsTest.java,v 1.4 2003/03/23 21:49:13 scolebourne Exp $
+ */
+public class ObjectUtilsTest extends TestCase {
+ private static final String FOO = "foo";
+ private static final String BAR = "bar";
+
+ public ObjectUtilsTest(String name) {
+ super(name);
+ }
+
+ public static void main(String[] args) {
+ TestRunner.run(suite());
+ }
+
+ public static Test suite() {
+ TestSuite suite = new TestSuite(ObjectUtilsTest.class);
+ suite.setName("ObjectUtils Tests");
+ return suite;
+ }
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ //-----------------------------------------------------------------------
+
+ public void testIsNull() {
+ Object o = FOO;
+ Object dflt = BAR;
+ assertSame("dflt was not returned when o was null", dflt, ObjectUtils.defaultIfNull(null, dflt));
+ assertSame("dflt was returned when o was not null", o, ObjectUtils.defaultIfNull(o, dflt));
+ }
+
+ public void testEquals() {
+ assertTrue("ObjectUtils.equals(null, null) returned false", ObjectUtils.equals(null, null));
+ assertTrue("ObjectUtils.equals(\"foo\", null) returned true", !ObjectUtils.equals(FOO, null));
+ assertTrue("ObjectUtils.equals(null, \"bar\") returned true", !ObjectUtils.equals(null, BAR));
+ assertTrue("ObjectUtils.equals(\"foo\", \"bar\") returned true", !ObjectUtils.equals(FOO, BAR));
+ assertTrue("ObjectUtils.equals(\"foo\", \"foo\") returned false", ObjectUtils.equals(FOO, FOO));
+ }
+
+ public void testIdentityToString() {
+ assertEquals(
+ "java.lang.String@" + Integer.toHexString(System.identityHashCode(FOO)),
+ ObjectUtils.identityToString(FOO));
+ Integer i = new Integer(90);
+ assertEquals(
+ "java.lang.Integer@" + Integer.toHexString(System.identityHashCode(i)),
+ ObjectUtils.identityToString(i));
+ assertEquals(null, ObjectUtils.identityToString(null));
+ }
+
+ public void testNull() {
+ assertTrue(ObjectUtils.NULL != null);
+ assertTrue(ObjectUtils.NULL instanceof ObjectUtils.Null);
+ assertSame(ObjectUtils.NULL, SerializationUtils.clone(ObjectUtils.NULL));
+ }
+
+}
diff --git a/examples/cl2/src/test/org/apache/commons/lang/RandomStringUtilsTest.java b/examples/cl2/src/test/org/apache/commons/lang/RandomStringUtilsTest.java
new file mode 100644
index 00000000..a9d03c72
--- /dev/null
+++ b/examples/cl2/src/test/org/apache/commons/lang/RandomStringUtilsTest.java
@@ -0,0 +1,313 @@
+/* ====================================================================
+ * 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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
+ * .
+ */
+package org.apache.commons.lang;
+
+import java.util.Random;
+
+import junit.framework.*;
+import junit.textui.TestRunner;
+
+/**
+ * Unit tests {@link org.apache.commons.lang.RandomStringUtils}.
+ *
+ * @author Steven Caswell
+ * @author Ringo De Smet
+ * @author Phil Steitz
+ * @version $Id: RandomStringUtilsTest.java,v 1.7 2003/06/09 21:36:03 scolebourne Exp $
+ */
+public class RandomStringUtilsTest extends junit.framework.TestCase {
+ /**
+ * Construct a new instance of RandomStringUtilsTest with the specified name
+ */
+ public RandomStringUtilsTest(String name) {
+ super(name);
+ }
+
+ public static Test suite() {
+ TestSuite suite = new TestSuite(RandomStringUtilsTest.class);
+ suite.setName("RandomStringUtils Tests");
+ return suite;
+ }
+
+ /**
+ * Set up instance variables required by this test case.
+ */
+ public void setUp() {
+ }
+
+ /**
+ * Tear down instance variables required by this test case.
+ */
+ public void tearDown() {
+ }
+
+ /**
+ * Test the implementation
+ */
+ public void testRandomStringUtils() {
+ String r1 = RandomStringUtils.random(50);
+ assertEquals("random(50) length", 50, r1.length());
+ String r2 = RandomStringUtils.random(50);
+ assertEquals("random(50) length", 50, r2.length());
+ assertTrue("!r1.equals(r2)", !r1.equals(r2));
+
+ r1 = RandomStringUtils.randomAscii(50);
+ assertEquals("randomAscii(50) length", 50, r1.length());
+ for(int i = 0; i < r1.length(); i++) {
+ assertTrue("char between 32 and 127", (int) r1.charAt(i) >= 32 && (int) r1.charAt(i) <= 127);
+ }
+ r2 = RandomStringUtils.randomAscii(50);
+ assertTrue("!r1.equals(r2)", !r1.equals(r2));
+
+ r1 = RandomStringUtils.randomAlphabetic(50);
+ assertEquals("randomAlphabetic(50)", 50, r1.length());
+ for(int i = 0; i < r1.length(); i++) {
+ assertEquals("r1 contains alphabetic", true, Character.isLetter(r1.charAt(i)) && !Character.isDigit(r1.charAt(i)));
+ }
+ r2 = RandomStringUtils.randomAlphabetic(50);
+ assertTrue("!r1.equals(r2)", !r1.equals(r2));
+
+ r1 = RandomStringUtils.randomAlphanumeric(50);
+ assertEquals("randomAlphanumeric(50)", 50, r1.length());
+ for(int i = 0; i < r1.length(); i++) {
+ assertEquals("r1 contains alphanumeric", true, Character.isLetterOrDigit(r1.charAt(i)));
+ }
+ r2 = RandomStringUtils.randomAlphabetic(50);
+ assertTrue("!r1.equals(r2)", !r1.equals(r2));
+
+ r1 = RandomStringUtils.randomNumeric(50);
+ assertEquals("randomNumeric(50)", 50, r1.length());
+ for(int i = 0; i < r1.length(); i++) {
+ assertEquals("r1 contains numeric", true, Character.isDigit(r1.charAt(i)) && !Character.isLetter(r1.charAt(i)));
+ }
+ r2 = RandomStringUtils.randomNumeric(50);
+ assertTrue("!r1.equals(r2)", !r1.equals(r2));
+
+ String set = "abcdefg";
+ r1 = RandomStringUtils.random(50, set);
+ assertEquals("random(50, \"abcdefg\")", 50, r1.length());
+ for(int i = 0; i < r1.length(); i++) {
+ assertTrue("random char in set", set.indexOf(r1.charAt(i)) > -1);
+ }
+ r2 = RandomStringUtils.random(50, set);
+ assertTrue("!r1.equals(r2)", !r1.equals(r2));
+
+ set = "stuvwxyz";
+ r1 = RandomStringUtils.random(50, set.toCharArray());
+ assertEquals("random(50, \"stuvwxyz\")", 50, r1.length());
+ for(int i = 0; i < r1.length(); i++) {
+ assertTrue("random char in set", set.indexOf(r1.charAt(i)) > -1);
+ }
+ r2 = RandomStringUtils.random(50, set);
+ assertTrue("!r1.equals(r2)", !r1.equals(r2));
+
+ long seed = System.currentTimeMillis();
+ r1 = RandomStringUtils.random(50,0,0,true,true,null,new Random(seed));
+ r2 = RandomStringUtils.random(50,0,0,true,true,null,new Random(seed));
+ assertEquals("r1.equals(r2)", r1, r2);
+
+ r1 = RandomStringUtils.random(0);
+ assertEquals("random(0).equals(\"\")", "", r1);
+
+ Exception e = null;
+ try {
+ r1 = RandomStringUtils.random(-1);
+ } catch (Exception e2) {
+ e = e2;
+ }
+ assertNotNull("random(<0) throws exception", e);
+ }
+
+ /**
+ * Make sure boundary alphanumeric characters are generated by randomAlphaNumeric
+ * This test will fail randomly with probability = 6 * (61/62)**1000 ~ 5.2E-7
+ */
+ public void testRandomAlphaNumeric() {
+ char[] testChars = {'a', 'z', 'A', 'Z', '0', '9'};
+ boolean[] found = {false, false, false, false, false, false};
+ for (int i = 0; i < 100; i++) {
+ String randString = RandomStringUtils.randomAlphanumeric(10);
+ for (int j = 0; j < testChars.length; j++) {
+ if (randString.indexOf(testChars[j]) > 0) {
+ found[j] = true;
+ }
+ }
+ }
+ for (int i = 0; i < testChars.length; i++) {
+ if (!found[i]) {
+ fail("alphanumeric character not generated in 1000 attempts: "
+ + testChars[i] +" -- repeated failures indicate a problem ");
+ }
+ }
+ }
+
+ /**
+ * Make sure '0' and '9' are generated by randomNumeric
+ * This test will fail randomly with probability = 2 * (9/10)**1000 ~ 3.5E-46
+ */
+ public void testRandomNumeric() {
+ char[] testChars = {'0','9'};
+ boolean[] found = {false, false};
+ for (int i = 0; i < 100; i++) {
+ String randString = RandomStringUtils.randomNumeric(10);
+ for (int j = 0; j < testChars.length; j++) {
+ if (randString.indexOf(testChars[j]) > 0) {
+ found[j] = true;
+ }
+ }
+ }
+ for (int i = 0; i < testChars.length; i++) {
+ if (!found[i]) {
+ fail("digit not generated in 1000 attempts: "
+ + testChars[i] +" -- repeated failures indicate a problem ");
+ }
+ }
+ }
+
+ /**
+ * Make sure boundary alpha characters are generated by randomAlphabetic
+ * This test will fail randomly with probability = 4 * (51/52)**1000 ~ 1.58E-8
+ */
+ public void testRandomAlphabetic() {
+ char[] testChars = {'a', 'z', 'A', 'Z'};
+ boolean[] found = {false, false, false, false};
+ for (int i = 0; i < 100; i++) {
+ String randString = RandomStringUtils.randomAlphabetic(10);
+ for (int j = 0; j < testChars.length; j++) {
+ if (randString.indexOf(testChars[j]) > 0) {
+ found[j] = true;
+ }
+ }
+ }
+ for (int i = 0; i < testChars.length; i++) {
+ if (!found[i]) {
+ fail("alphanumeric character not generated in 1000 attempts: "
+ + testChars[i] +" -- repeated failures indicate a problem ");
+ }
+ }
+ }
+
+ /**
+ * Make sure 32 and 127 are generated by randomNumeric
+ * This test will fail randomly with probability = 2*(95/96)**1000 ~ 5.7E-5
+ */
+ public void testRandomAscii() {
+ char[] testChars = {(char) 32, (char) 126};
+ boolean[] found = {false, false};
+ for (int i = 0; i < 100; i++) {
+ String randString = RandomStringUtils.randomAscii(10);
+ for (int j = 0; j < testChars.length; j++) {
+ if (randString.indexOf(testChars[j]) > 0) {
+ found[j] = true;
+ }
+ }
+ }
+ for (int i = 0; i < testChars.length; i++) {
+ if (!found[i]) {
+ fail("ascii character not generated in 1000 attempts: "
+ + (int) testChars[i] +
+ " -- repeated failures indicate a problem");
+ }
+ }
+ }
+
+ /**
+ * Test homogeneity of random strings generated --
+ * i.e., test that characters show up with expected frequencies
+ * in generated strings. Will fail randomly about 1 in 1000 times.
+ * Repeated failures indicate a problem.
+ */
+ public void testRandomStringUtilsHomog() {
+ String set = "abc";
+ char[] chars = set.toCharArray();
+ String gen = "";
+ int[] counts = {0,0,0};
+ int[] expected = {200,200,200};
+ for (int i = 0; i< 100; i++) {
+ gen = RandomStringUtils.random(6,chars);
+ for (int j = 0; j < 6; j++) {
+ switch (gen.charAt(j)) {
+ case 'a': {counts[0]++; break;}
+ case 'b': {counts[1]++; break;}
+ case 'c': {counts[2]++; break;}
+ default: {fail("generated character not in set");}
+ }
+ }
+ }
+ // Perform chi-square test with df = 3-1 = 2, testing at .001 level
+ assertTrue("test homogeneity -- will fail about 1 in 1000 times",
+ chiSquare(expected,counts) < 13.82);
+ }
+
+ /**
+ * Computes Chi-Square statistic given observed and expected counts
+ * @param observed array of observed frequency counts
+ * @param expected array of exptected frequency counts
+ */
+ private double chiSquare(int[] expected, int[] observed) {
+ double sumSq = 0.0d;
+ double dev = 0.0d;
+ for (int i = 0; i< observed.length; i++) {
+ dev = (double)(observed[i] - expected[i]);
+ sumSq += dev*dev/(double)expected[i];
+ }
+ return sumSq;
+ }
+
+
+ public static void main(String args[]) {
+ TestRunner.run(suite());
+ }
+}
+
diff --git a/examples/cl2/src/test/org/apache/commons/lang/SerializationUtilsTest.java b/examples/cl2/src/test/org/apache/commons/lang/SerializationUtilsTest.java
new file mode 100644
index 00000000..f5c5c651
--- /dev/null
+++ b/examples/cl2/src/test/org/apache/commons/lang/SerializationUtilsTest.java
@@ -0,0 +1,352 @@
+/* ====================================================================
+ * 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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
+ * .
+ */
+package org.apache.commons.lang;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+import java.io.ObjectOutputStream;
+import java.util.HashMap;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import junit.textui.TestRunner;
+
+/**
+ * Unit tests {@link org.apache.commons.lang.SerializationUtils}.
+ *
+ * @author Stephen Colebourne
+ * @author Ringo De Smet
+ * @version $Id: SerializationUtilsTest.java,v 1.2 2003/03/23 21:50:58 scolebourne Exp $
+ */
+public class SerializationUtilsTest extends TestCase {
+ private String iString;
+ private Integer iInteger;
+ private HashMap iMap;
+
+ public SerializationUtilsTest(String name) {
+ super(name);
+ }
+
+ public static void main(String[] args) {
+ TestRunner.run(suite());
+ }
+
+ public static Test suite() {
+ TestSuite suite = new TestSuite(SerializationUtilsTest.class);
+ suite.setName("SerializationUtils Tests");
+ return suite;
+ }
+
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ iString = "foo";
+ iInteger = new Integer(7);
+ iMap = new HashMap();
+ iMap.put("FOO", iString);
+ iMap.put("BAR", iInteger);
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ //-----------------------------------------------------------------------
+
+ public void testSerializeStream() throws Exception {
+ ByteArrayOutputStream streamTest = new ByteArrayOutputStream();
+ SerializationUtils.serialize(iMap, streamTest);
+
+ ByteArrayOutputStream streamReal = new ByteArrayOutputStream();
+ ObjectOutputStream oos = new ObjectOutputStream(streamReal);
+ oos.writeObject(iMap);
+ oos.flush();
+ oos.close();
+
+ byte[] testBytes = streamTest.toByteArray();
+ byte[] realBytes = streamReal.toByteArray();
+ assertEquals(testBytes.length, realBytes.length);
+ for (int i = 0; i < realBytes.length; i++) {
+ assertEquals(realBytes[i], testBytes[i]);
+ }
+ }
+
+ public void testSerializeStreamUnserializable() throws Exception {
+ ByteArrayOutputStream streamTest = new ByteArrayOutputStream();
+ try {
+ iMap.put(new Object(), new Object());
+ SerializationUtils.serialize(iMap, streamTest);
+ } catch (SerializationException ex) {
+ return;
+ }
+ fail();
+ }
+
+ public void testSerializeStreamNullObj() throws Exception {
+ ByteArrayOutputStream streamTest = new ByteArrayOutputStream();
+ SerializationUtils.serialize(null, streamTest);
+
+ ByteArrayOutputStream streamReal = new ByteArrayOutputStream();
+ ObjectOutputStream oos = new ObjectOutputStream(streamReal);
+ oos.writeObject(null);
+ oos.flush();
+ oos.close();
+
+ byte[] testBytes = streamTest.toByteArray();
+ byte[] realBytes = streamReal.toByteArray();
+ assertEquals(testBytes.length, realBytes.length);
+ for (int i = 0; i < realBytes.length; i++) {
+ assertEquals(realBytes[i], testBytes[i]);
+ }
+ }
+
+ public void testSerializeStreamObjNull() throws Exception {
+ ByteArrayOutputStream streamTest = new ByteArrayOutputStream();
+ try {
+ SerializationUtils.serialize(iMap, null);
+ } catch (NullPointerException ex) {
+ return;
+ }
+ fail();
+ }
+
+ public void testSerializeStreamNullNull() throws Exception {
+ ByteArrayOutputStream streamTest = new ByteArrayOutputStream();
+ try {
+ SerializationUtils.serialize(null, null);
+ } catch (NullPointerException ex) {
+ return;
+ }
+ fail();
+ }
+
+ //-----------------------------------------------------------------------
+
+ public void testDeserializeStream() throws Exception {
+ ByteArrayOutputStream streamReal = new ByteArrayOutputStream();
+ ObjectOutputStream oos = new ObjectOutputStream(streamReal);
+ oos.writeObject(iMap);
+ oos.flush();
+ oos.close();
+
+ ByteArrayInputStream inTest = new ByteArrayInputStream(streamReal.toByteArray());
+ Object test = SerializationUtils.deserialize(inTest);
+ assertNotNull(test);
+ assertTrue(test instanceof HashMap);
+ assertTrue(test != iMap);
+ HashMap testMap = (HashMap) test;
+ assertEquals(iString, testMap.get("FOO"));
+ assertTrue(iString != testMap.get("FOO"));
+ assertEquals(iInteger, testMap.get("BAR"));
+ assertTrue(iInteger != testMap.get("BAR"));
+ assertEquals(iMap, testMap);
+ }
+
+ public void testDeserializeStreamOfNull() throws Exception {
+ ByteArrayOutputStream streamReal = new ByteArrayOutputStream();
+ ObjectOutputStream oos = new ObjectOutputStream(streamReal);
+ oos.writeObject(null);
+ oos.flush();
+ oos.close();
+
+ ByteArrayInputStream inTest = new ByteArrayInputStream(streamReal.toByteArray());
+ Object test = SerializationUtils.deserialize(inTest);
+ assertNull(test);
+ }
+
+ public void testDeserializeStreamNull() throws Exception {
+ try {
+ SerializationUtils.deserialize((InputStream) null);
+ } catch (NullPointerException ex) {
+ return;
+ }
+ fail();
+ }
+
+ public void testDeserializeStreamBadStream() throws Exception {
+ try {
+ SerializationUtils.deserialize(new ByteArrayInputStream(new byte[0]));
+ } catch (SerializationException ex) {
+ return;
+ }
+ fail();
+ }
+
+ //-----------------------------------------------------------------------
+
+ public void testSerializeBytes() throws Exception {
+ byte[] testBytes = SerializationUtils.serialize(iMap);
+
+ ByteArrayOutputStream streamReal = new ByteArrayOutputStream();
+ ObjectOutputStream oos = new ObjectOutputStream(streamReal);
+ oos.writeObject(iMap);
+ oos.flush();
+ oos.close();
+
+ byte[] realBytes = streamReal.toByteArray();
+ assertEquals(testBytes.length, realBytes.length);
+ for (int i = 0; i < realBytes.length; i++) {
+ assertEquals(realBytes[i], testBytes[i]);
+ }
+ }
+
+ public void testSerializeBytesUnserializable() throws Exception {
+ try {
+ iMap.put(new Object(), new Object());
+ SerializationUtils.serialize(iMap);
+ } catch (SerializationException ex) {
+ return;
+ }
+ fail();
+ }
+
+ public void testSerializeBytesNull() throws Exception {
+ byte[] testBytes = SerializationUtils.serialize(null);
+
+ ByteArrayOutputStream streamReal = new ByteArrayOutputStream();
+ ObjectOutputStream oos = new ObjectOutputStream(streamReal);
+ oos.writeObject(null);
+ oos.flush();
+ oos.close();
+
+ byte[] realBytes = streamReal.toByteArray();
+ assertEquals(testBytes.length, realBytes.length);
+ for (int i = 0; i < realBytes.length; i++) {
+ assertEquals(realBytes[i], testBytes[i]);
+ }
+ }
+
+ //-----------------------------------------------------------------------
+
+ public void testDeserializeBytes() throws Exception {
+ ByteArrayOutputStream streamReal = new ByteArrayOutputStream();
+ ObjectOutputStream oos = new ObjectOutputStream(streamReal);
+ oos.writeObject(iMap);
+ oos.flush();
+ oos.close();
+
+ Object test = SerializationUtils.deserialize(streamReal.toByteArray());
+ assertNotNull(test);
+ assertTrue(test instanceof HashMap);
+ assertTrue(test != iMap);
+ HashMap testMap = (HashMap) test;
+ assertEquals(iString, testMap.get("FOO"));
+ assertTrue(iString != testMap.get("FOO"));
+ assertEquals(iInteger, testMap.get("BAR"));
+ assertTrue(iInteger != testMap.get("BAR"));
+ assertEquals(iMap, testMap);
+ }
+
+ public void testDeserializeBytesOfNull() throws Exception {
+ ByteArrayOutputStream streamReal = new ByteArrayOutputStream();
+ ObjectOutputStream oos = new ObjectOutputStream(streamReal);
+ oos.writeObject(null);
+ oos.flush();
+ oos.close();
+
+ Object test = SerializationUtils.deserialize(streamReal.toByteArray());
+ assertNull(test);
+ }
+
+ public void testDeserializeBytesNull() throws Exception {
+ try {
+ SerializationUtils.deserialize((byte[]) null);
+ } catch (NullPointerException ex) {
+ return;
+ }
+ fail();
+ }
+
+ public void testDeserializeBytesBadStream() throws Exception {
+ try {
+ SerializationUtils.deserialize(new byte[0]);
+ } catch (SerializationException ex) {
+ return;
+ }
+ fail();
+ }
+
+ //-----------------------------------------------------------------------
+
+ public void testClone() throws Exception {
+ Object test = SerializationUtils.clone(iMap);
+ assertNotNull(test);
+ assertTrue(test instanceof HashMap);
+ assertTrue(test != iMap);
+ HashMap testMap = (HashMap) test;
+ assertEquals(iString, testMap.get("FOO"));
+ assertTrue(iString != testMap.get("FOO"));
+ assertEquals(iInteger, testMap.get("BAR"));
+ assertTrue(iInteger != testMap.get("BAR"));
+ assertEquals(iMap, testMap);
+ }
+
+ public void testCloneNull() throws Exception {
+ Object test = SerializationUtils.clone(null);
+ assertNull(test);
+ }
+
+ public void testCloneUnserializable() throws Exception {
+ try {
+ iMap.put(new Object(), new Object());
+ SerializationUtils.clone(iMap);
+ } catch (SerializationException ex) {
+ return;
+ }
+ fail();
+ }
+
+}
diff --git a/examples/cl2/src/test/org/apache/commons/lang/StringEscapeUtilsTest.java b/examples/cl2/src/test/org/apache/commons/lang/StringEscapeUtilsTest.java
new file mode 100644
index 00000000..c224a8b2
--- /dev/null
+++ b/examples/cl2/src/test/org/apache/commons/lang/StringEscapeUtilsTest.java
@@ -0,0 +1,229 @@
+/* ====================================================================
+ * 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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
+ * .
+ */
+package org.apache.commons.lang;
+
+import java.io.IOException;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import junit.textui.TestRunner;
+
+/**
+ * Unit tests for {@link StringEscapeUtils}.
+ *
+ * @author of original StringUtilsTest.testEscape = ?
+ * @author Alexander Day Chaffee
+ * @version $Id: StringEscapeUtilsTest.java,v 1.7 2003/05/24 04:35:07 alex Exp $
+ */
+public class StringEscapeUtilsTest extends TestCase {
+ private final static String FOO = "foo";
+
+ public StringEscapeUtilsTest(String name) {
+ super(name);
+ }
+
+ public static void main(String[] args) {
+ TestRunner.run(suite());
+ }
+
+ public static Test suite() {
+ TestSuite suite = new TestSuite(StringEscapeUtilsTest.class);
+ suite.setName("StringEscapeUtilsTest Tests");
+ return suite;
+ }
+
+ //-----------------------------------------------------------------------
+
+ public void testEscapeJava() throws IOException {
+ assertEscapeJava("empty string", "", "");
+ assertEscapeJava(FOO, FOO);
+ assertEscapeJava("tab", "\\t", "\t");
+ assertEscapeJava("backslash", "\\\\", "\\");
+ assertEscapeJava("single quote should not be escaped", "'", "'");
+ assertEscapeJava("\\\\\\b\\t\\r", "\\\b\t\r");
+ assertEscapeJava("\\u1234", "\u1234");
+ assertEscapeJava("\\u0234", "\u0234");
+ assertEscapeJava("\\u00EF", "\u00ef");
+ assertEscapeJava("\\u0001", "\u0001");
+ assertEscapeJava("Should use capitalized unicode hex", "\\uABCD", "\uabcd");
+
+ assertEscapeJava("He didn't say, \\\"stop!\\\"",
+ "He didn't say, \"stop!\"");
+ assertEscapeJava("non-breaking space", "This space is non-breaking:" + "\\u00A0",
+ "This space is non-breaking:\u00a0");
+ assertEscapeJava("\\uABCD\\u1234\\u012C",
+ "\uABCD\u1234\u012C");
+ }
+
+ private void assertEscapeJava(String escaped, String original) throws IOException {
+ assertEscapeJava(null, escaped, original);
+ }
+
+ private void assertEscapeJava(String message, String expected, String original) throws IOException {
+ String converted = StringEscapeUtils.escapeJava(original);
+ message = "escapeJava(String) failed" + (message == null ? "" : (": " + message));
+ assertEquals(message, expected, converted);
+
+ StringPrintWriter writer = new StringPrintWriter();
+ StringEscapeUtils.escapeJava(writer, original);
+ assertEquals(expected, writer.getString());
+ }
+
+ public void testUnescapeJava() throws IOException {
+ assertUnescapeJava("", "");
+ assertUnescapeJava("test", "test");
+ assertUnescapeJava("\ntest\b", "\\ntest\\b");
+ assertUnescapeJava("\u123425foo\ntest\b", "\\u123425foo\\ntest\\b");
+ //foo
+ assertUnescapeJava("lowercase unicode", "\uABCDx", "\\uabcdx");
+ assertUnescapeJava("uppercase unicode", "\uABCDx", "\\uABCDx");
+ assertUnescapeJava("unicode as final character", "\uABCD", "\\uabcd");
+ }
+
+ private void assertUnescapeJava(String unescaped, String original) throws IOException {
+ assertUnescapeJava(null, unescaped, original);
+ }
+
+ private void assertUnescapeJava(String message, String unescaped, String original) throws IOException {
+ String expected = unescaped;
+ String actual = StringEscapeUtils.unescapeJava(original);
+
+ assertEquals("unescape(String) failed" +
+ (message == null ? "" : (": " + message)) +
+ ": expected '" + StringUtils.escape(expected) +
+ // we escape this so we can see it in the error message
+ "' actual '" + StringUtils.escape(actual) + "'",
+ expected, actual);
+
+ StringPrintWriter writer = new StringPrintWriter();
+ StringEscapeUtils.unescapeJava(writer, original);
+ assertEquals(unescaped, writer.getString());
+
+ }
+
+ public void testEscapeJavaScript() {
+ assertEquals("He didn\\'t say, \\\"stop!\\\"", StringEscapeUtils.escapeJavaScript("He didn't say, \"stop!\""));
+ }
+
+
+ // HTML and XML
+ //--------------------------------------------------------------
+
+ String[][] htmlEscapes = {
+ {"no escaping", "plain text", "plain text"},
+ {"no escaping", "plain text", "plain text"},
+ {"empty string", "", ""},
+ {"ampersand", "bread & butter", "bread & butter"},
+ {"quotes", ""bread" & butter", "\"bread\" & butter"},
+ {"final character only", "greater than >", "greater than >"},
+ {"first character only", "< less than", "< less than"},
+ {"apostrophe", "Huntington's chorea", "Huntington's chorea"},
+ {"languages", "English,Français,日本語 (nihongo)", "English,Fran\u00E7ais,\u65E5\u672C\u8A9E (nihongo)"},
+ {"8-bit ascii doesn't number-escape", "~\u007F", "\u007E\u007F"},
+ {"8-bit ascii does number-escape", "", "\u0080\u009F"},
+ };
+
+ public void testEscapeHtml() {
+ for (int i = 0; i < htmlEscapes.length; ++i) {
+ assertEquals(htmlEscapes[i][0], htmlEscapes[i][1], StringEscapeUtils.escapeHtml(htmlEscapes[i][2]));
+ // todo: add test for (and implement) Writer-based version
+ }
+ }
+
+ public void testUnescapeHtml() {
+ for (int i = 0; i < htmlEscapes.length; ++i) {
+ assertEquals(htmlEscapes[i][0], htmlEscapes[i][2], StringEscapeUtils.unescapeHtml(htmlEscapes[i][1]));
+ // todo: add test for (and implement) Writer-based version
+ }
+ // \u00E7 is a cedilla (ç)
+ // note that the test string must be 7-bit-clean (unicode escaped) or else it will compile incorrectly
+ // on some locales
+ assertEquals("funny chars pass through OK", "Fran\u00E7ais", StringEscapeUtils.unescapeHtml("Fran\u00E7ais"));
+ }
+
+ public void testUnescapeUnknownEntity() throws Exception
+ {
+ assertEquals("&zzzz;", StringEscapeUtils.unescapeHtml("&zzzz;"));
+ }
+
+ public void testEscapeHtmlVersions() throws Exception
+ {
+ assertEquals("Β", StringEscapeUtils.escapeHtml("\u0392"));
+ assertEquals("\u0392", StringEscapeUtils.unescapeHtml("Β"));
+
+ //todo: refine API for escaping/unescaping specific HTML versions
+
+ }
+
+ public void testEscapeXml() throws Exception {
+ assertEquals("<abc>", StringEscapeUtils.escapeXml(""));
+ assertEquals("", StringEscapeUtils.unescapeXml("<abc>"));
+
+ assertEquals("XML should use numbers, not names for HTML entities",
+ "¡", StringEscapeUtils.escapeXml("\u00A1"));
+ assertEquals("XML should use numbers, not names for HTML entities",
+ "\u00A0", StringEscapeUtils.unescapeXml(" "));
+
+ assertEquals("ain't", StringEscapeUtils.unescapeXml("ain't"));
+ assertEquals("ain't", StringEscapeUtils.escapeXml("ain't"));
+ }
+
+ // SQL
+ // see http://www.jguru.com/faq/view.jsp?EID=8881
+ //--------------------
+ // sql doubles-up single-quotes
+ //}
+}
+
diff --git a/examples/cl2/src/test/org/apache/commons/lang/StringUtilsEqualsIndexOfTest.java b/examples/cl2/src/test/org/apache/commons/lang/StringUtilsEqualsIndexOfTest.java
new file mode 100644
index 00000000..3dc4574c
--- /dev/null
+++ b/examples/cl2/src/test/org/apache/commons/lang/StringUtilsEqualsIndexOfTest.java
@@ -0,0 +1,136 @@
+/* ====================================================================
+ * 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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
+ * .
+ */
+package org.apache.commons.lang;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import junit.textui.TestRunner;
+
+/**
+ * Unit tests {@link org.apache.commons.lang.StringUtils} - Substring methods
+ *
+ * @author Stephen Colebourne
+ * @author Ringo De Smet
+ * @version $Id: StringUtilsEqualsIndexOfTest.java,v 1.2 2003/03/23 21:50:58 scolebourne Exp $
+ */
+public class StringUtilsEqualsIndexOfTest extends TestCase {
+ private static final String FOO = "foo";
+ private static final String BAR = "bar";
+ private static final String FOOBAR = "foobar";
+ private static final String[] FOOBAR_SUB_ARRAY = new String[] {"ob", "ba"};
+
+ public StringUtilsEqualsIndexOfTest(String name) {
+ super(name);
+ }
+
+ public static void main(String[] args) {
+ TestRunner.run(suite());
+ }
+
+ public static Test suite() {
+ TestSuite suite = new TestSuite(StringUtilsEqualsIndexOfTest.class);
+ suite.setName("StringUtilsEqualsIndexOf Tests");
+ return suite;
+ }
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ //-----------------------------------------------------------------------
+
+ public void testEquals() {
+ assertEquals(true, StringUtils.equals(null, null));
+ assertEquals(true, StringUtils.equals(FOO, FOO));
+ assertEquals(true, StringUtils.equals(FOO, new String(new char[] { 'f', 'o', 'o' })));
+ assertEquals(false, StringUtils.equals(FOO, new String(new char[] { 'f', 'O', 'O' })));
+ assertEquals(false, StringUtils.equals(FOO, BAR));
+ assertEquals(false, StringUtils.equals(FOO, null));
+ assertEquals(false, StringUtils.equals(null, FOO));
+ }
+
+ public void testEqualsIgnoreCase() {
+ assertEquals(true, StringUtils.equalsIgnoreCase(null, null));
+ assertEquals(true, StringUtils.equalsIgnoreCase(FOO, FOO));
+ assertEquals(true, StringUtils.equalsIgnoreCase(FOO, new String(new char[] { 'f', 'o', 'o' })));
+ assertEquals(true, StringUtils.equalsIgnoreCase(FOO, new String(new char[] { 'f', 'O', 'O' })));
+ assertEquals(false, StringUtils.equalsIgnoreCase(FOO, BAR));
+ assertEquals(false, StringUtils.equalsIgnoreCase(FOO, null));
+ assertEquals(false, StringUtils.equalsIgnoreCase(null, FOO));
+ }
+
+ public void testIndexOfAny() {
+ assertEquals(-1, StringUtils.indexOfAny(null, null));
+ assertEquals(-1, StringUtils.indexOfAny(null, FOOBAR_SUB_ARRAY));
+ assertEquals(-1, StringUtils.indexOfAny(FOOBAR, null));
+ assertEquals(2, StringUtils.indexOfAny(FOOBAR, FOOBAR_SUB_ARRAY));
+ assertEquals(-1, StringUtils.indexOfAny(FOOBAR, new String[0]));
+ assertEquals(-1, StringUtils.indexOfAny(FOOBAR, new String[] {"llll"}));
+ }
+
+ public void testLastIndexOfAny() {
+ assertEquals(-1, StringUtils.lastIndexOfAny(null, null));
+ assertEquals(-1, StringUtils.lastIndexOfAny(null, FOOBAR_SUB_ARRAY));
+ assertEquals(-1, StringUtils.lastIndexOfAny(FOOBAR, null));
+ assertEquals(3, StringUtils.lastIndexOfAny(FOOBAR, FOOBAR_SUB_ARRAY));
+ assertEquals(-1, StringUtils.lastIndexOfAny(FOOBAR, new String[0]));
+ assertEquals(-1, StringUtils.lastIndexOfAny(FOOBAR, new String[] {"llll"}));
+ }
+
+}
diff --git a/examples/cl2/src/test/org/apache/commons/lang/StringUtilsIsTest.java b/examples/cl2/src/test/org/apache/commons/lang/StringUtilsIsTest.java
new file mode 100644
index 00000000..35c87b84
--- /dev/null
+++ b/examples/cl2/src/test/org/apache/commons/lang/StringUtilsIsTest.java
@@ -0,0 +1,196 @@
+/* ====================================================================
+ * 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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
+ * .
+ */
+package org.apache.commons.lang;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import junit.textui.TestRunner;
+
+/**
+ * Unit tests {@link org.apache.commons.lang.StringUtils} - Substring methods
+ *
+ * @author Stephen Colebourne
+ * @version $Id: StringUtilsIsTest.java,v 1.5 2003/03/23 21:51:51 scolebourne Exp $
+ */
+public class StringUtilsIsTest extends TestCase {
+
+ public StringUtilsIsTest(String name) {
+ super(name);
+ }
+
+ public static void main(String[] args) {
+ TestRunner.run(suite());
+ }
+
+ public static Test suite() {
+ TestSuite suite = new TestSuite(StringUtilsIsTest.class);
+ suite.setName("StringUtilsIsXxx Tests");
+ return suite;
+ }
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ //-----------------------------------------------------------------------
+
+ public void testIsAlpha() {
+ assertEquals(false, StringUtils.isAlpha(null));
+ assertEquals(true, StringUtils.isAlpha(""));
+ assertEquals(false, StringUtils.isAlpha(" "));
+ assertEquals(true, StringUtils.isAlpha("a"));
+ assertEquals(true, StringUtils.isAlpha("A"));
+ assertEquals(true, StringUtils.isAlpha("kgKgKgKgkgkGkjkjlJlOKLgHdGdHgl"));
+ assertEquals(false, StringUtils.isAlpha("ham kso"));
+ assertEquals(false, StringUtils.isAlpha("1"));
+ assertEquals(false, StringUtils.isAlpha("hkHKHik6iUGHKJgU7tUJgKJGI87GIkug"));
+ assertEquals(false, StringUtils.isAlpha("_"));
+ assertEquals(false, StringUtils.isAlpha("hkHKHik*khbkuh"));
+ }
+
+ public void testIsAlphanumeric() {
+ assertEquals(false, StringUtils.isAlphanumeric(null));
+ assertEquals(true, StringUtils.isAlphanumeric(""));
+ assertEquals(false, StringUtils.isAlphanumeric(" "));
+ assertEquals(true, StringUtils.isAlphanumeric("a"));
+ assertEquals(true, StringUtils.isAlphanumeric("A"));
+ assertEquals(true, StringUtils.isAlphanumeric("kgKgKgKgkgkGkjkjlJlOKLgHdGdHgl"));
+ assertEquals(false, StringUtils.isAlphanumeric("ham kso"));
+ assertEquals(true, StringUtils.isAlphanumeric("1"));
+ assertEquals(true, StringUtils.isAlphanumeric("hkHKHik6iUGHKJgU7tUJgKJGI87GIkug"));
+ assertEquals(false, StringUtils.isAlphanumeric("_"));
+ assertEquals(false, StringUtils.isAlphanumeric("hkHKHik*khbkuh"));
+ }
+
+ public void testIsWhitespace() {
+ assertEquals(false, StringUtils.isWhitespace(null));
+ assertEquals(true, StringUtils.isWhitespace(""));
+ assertEquals(true, StringUtils.isWhitespace(" "));
+ assertEquals(true, StringUtils.isWhitespace("\t \n \t"));
+ assertEquals(false, StringUtils.isWhitespace("\t aa\n \t"));
+ assertEquals(true, StringUtils.isWhitespace(" "));
+ assertEquals(false, StringUtils.isWhitespace(" a "));
+ assertEquals(false, StringUtils.isWhitespace("a "));
+ assertEquals(false, StringUtils.isWhitespace(" a"));
+ assertEquals(false, StringUtils.isWhitespace("aba"));
+ }
+
+ public void testIsAlphaspace() {
+ assertEquals(false, StringUtils.isAlphaSpace(null));
+ assertEquals(true, StringUtils.isAlphaSpace(""));
+ assertEquals(true, StringUtils.isAlphaSpace(" "));
+ assertEquals(true, StringUtils.isAlphaSpace("a"));
+ assertEquals(true, StringUtils.isAlphaSpace("A"));
+ assertEquals(true, StringUtils.isAlphaSpace("kgKgKgKgkgkGkjkjlJlOKLgHdGdHgl"));
+ assertEquals(true, StringUtils.isAlphaSpace("ham kso"));
+ assertEquals(false, StringUtils.isAlphaSpace("1"));
+ assertEquals(false, StringUtils.isAlphaSpace("hkHKHik6iUGHKJgU7tUJgKJGI87GIkug"));
+ assertEquals(false, StringUtils.isAlphaSpace("_"));
+ assertEquals(false, StringUtils.isAlphaSpace("hkHKHik*khbkuh"));
+ }
+
+ public void testIsAlphanumericSpace() {
+ assertEquals(false, StringUtils.isAlphanumericSpace(null));
+ assertEquals(true, StringUtils.isAlphanumericSpace(""));
+ assertEquals(true, StringUtils.isAlphanumericSpace(" "));
+ assertEquals(true, StringUtils.isAlphanumericSpace("a"));
+ assertEquals(true, StringUtils.isAlphanumericSpace("A"));
+ assertEquals(true, StringUtils.isAlphanumericSpace("kgKgKgKgkgkGkjkjlJlOKLgHdGdHgl"));
+ assertEquals(true, StringUtils.isAlphanumericSpace("ham kso"));
+ assertEquals(true, StringUtils.isAlphanumericSpace("1"));
+ assertEquals(true, StringUtils.isAlphanumericSpace("hkHKHik6iUGHKJgU7tUJgKJGI87GIkug"));
+ assertEquals(false, StringUtils.isAlphanumericSpace("_"));
+ assertEquals(false, StringUtils.isAlphanumericSpace("hkHKHik*khbkuh"));
+ }
+
+ public void testIsNumeric() {
+ assertEquals(false, StringUtils.isNumeric(null));
+ assertEquals(true, StringUtils.isNumeric(""));
+ assertEquals(false, StringUtils.isNumeric(" "));
+ assertEquals(false, StringUtils.isNumeric("a"));
+ assertEquals(false, StringUtils.isNumeric("A"));
+ assertEquals(false, StringUtils.isNumeric("kgKgKgKgkgkGkjkjlJlOKLgHdGdHgl"));
+ assertEquals(false, StringUtils.isNumeric("ham kso"));
+ assertEquals(true, StringUtils.isNumeric("1"));
+ assertEquals(true, StringUtils.isNumeric("1000"));
+ assertEquals(false, StringUtils.isNumeric("2.3"));
+ assertEquals(false, StringUtils.isNumeric("10 00"));
+ assertEquals(false, StringUtils.isNumeric("hkHKHik6iUGHKJgU7tUJgKJGI87GIkug"));
+ assertEquals(false, StringUtils.isNumeric("_"));
+ assertEquals(false, StringUtils.isNumeric("hkHKHik*khbkuh"));
+ }
+
+ public void testIsNumericSpace() {
+ assertEquals(false, StringUtils.isNumericSpace(null));
+ assertEquals(true, StringUtils.isNumericSpace(""));
+ assertEquals(true, StringUtils.isNumericSpace(" "));
+ assertEquals(false, StringUtils.isNumericSpace("a"));
+ assertEquals(false, StringUtils.isNumericSpace("A"));
+ assertEquals(false, StringUtils.isNumericSpace("kgKgKgKgkgkGkjkjlJlOKLgHdGdHgl"));
+ assertEquals(false, StringUtils.isNumericSpace("ham kso"));
+ assertEquals(true, StringUtils.isNumericSpace("1"));
+ assertEquals(true, StringUtils.isNumericSpace("1000"));
+ assertEquals(false, StringUtils.isNumericSpace("2.3"));
+ assertEquals(true, StringUtils.isNumericSpace("10 00"));
+ assertEquals(false, StringUtils.isNumericSpace("hkHKHik6iUGHKJgU7tUJgKJGI87GIkug"));
+ assertEquals(false, StringUtils.isNumericSpace("_"));
+ assertEquals(false, StringUtils.isNumericSpace("hkHKHik*khbkuh"));
+ }
+
+}
diff --git a/examples/cl2/src/test/org/apache/commons/lang/StringUtilsSubstringTest.java b/examples/cl2/src/test/org/apache/commons/lang/StringUtilsSubstringTest.java
new file mode 100644
index 00000000..d43d5218
--- /dev/null
+++ b/examples/cl2/src/test/org/apache/commons/lang/StringUtilsSubstringTest.java
@@ -0,0 +1,224 @@
+/* ====================================================================
+ * 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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
+ * .
+ */
+package org.apache.commons.lang;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import junit.textui.TestRunner;
+
+/**
+ * Unit tests {@link org.apache.commons.lang.StringUtils} - Substring methods
+ *
+ * @author Stephen Colebourne
+ * @author Ringo De Smet
+ * @version $Id: StringUtilsSubstringTest.java,v 1.3 2003/03/23 21:51:19 scolebourne Exp $
+ */
+public class StringUtilsSubstringTest extends TestCase {
+ private static final String FOO = "foo";
+ private static final String BAR = "bar";
+ private static final String BAZ = "baz";
+ private static final String FOOBAR = "foobar";
+ private static final String SENTENCE = "foo bar baz";
+
+ public StringUtilsSubstringTest(String name) {
+ super(name);
+ }
+
+ public static void main(String[] args) {
+ TestRunner.run(suite());
+ }
+
+ public static Test suite() {
+ TestSuite suite = new TestSuite(StringUtilsSubstringTest.class);
+ suite.setName("StringUtilsSubstring Tests");
+ return suite;
+ }
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ //-----------------------------------------------------------------------
+
+
+ public void testSubstring2() {
+ assertEquals("", StringUtils.substring(SENTENCE, 80));
+ assertEquals(BAZ, StringUtils.substring(SENTENCE, 8));
+ assertEquals(BAZ, StringUtils.substring(SENTENCE, -3));
+ assertEquals(SENTENCE, StringUtils.substring(SENTENCE, 0));
+ }
+
+ public void testSubstring3() {
+ assertEquals("", StringUtils.substring(SENTENCE, 8, 6));
+ assertEquals(FOO, StringUtils.substring(SENTENCE, 0, 3));
+ assertEquals("o", StringUtils.substring(SENTENCE, -9, 3));
+ assertEquals(FOO, StringUtils.substring(SENTENCE, 0, -8));
+ assertEquals("o", StringUtils.substring(SENTENCE, -9, -8));
+ assertEquals(SENTENCE, StringUtils.substring(SENTENCE, 0, 80));
+ }
+
+ public void testLeft() {
+ assertSame(null, StringUtils.left(null, 0));
+ assertSame(null, StringUtils.left(null, 2));
+ assertSame("", StringUtils.left("", 0));
+ assertSame("", StringUtils.left("", 2));
+ assertEquals("", StringUtils.left(FOOBAR, 0));
+ assertEquals(FOO, StringUtils.left(FOOBAR, 3));
+ assertSame(FOOBAR, StringUtils.left(FOOBAR, 80));
+ }
+
+ public void testLeftEx() {
+ try {
+ StringUtils.left(FOOBAR, -1);
+ } catch (IllegalArgumentException ex) {
+ return;
+ }
+ fail();
+ }
+
+ public void testRight() {
+ assertSame(null, StringUtils.right(null, 0));
+ assertSame(null, StringUtils.right(null, 2));
+ assertSame("", StringUtils.right("", 0));
+ assertSame("", StringUtils.right("", 2));
+ assertEquals("", StringUtils.right(FOOBAR, 0));
+ assertEquals(BAR, StringUtils.right(FOOBAR, 3));
+ assertSame(FOOBAR, StringUtils.right(FOOBAR, 80));
+ }
+
+ public void testRightEx() {
+ try {
+ StringUtils.right(FOOBAR, -1);
+ } catch (IllegalArgumentException ex) {
+ return;
+ }
+ fail();
+ }
+
+ public void testMid() {
+ assertSame(null, StringUtils.mid(null, 3, 0));
+ assertSame(null, StringUtils.mid(null, 3, 2));
+ assertSame("", StringUtils.mid("", 0, 0));
+ assertSame("", StringUtils.mid("", 0, 2));
+ assertEquals("", StringUtils.mid(FOOBAR, 3, 0));
+ assertEquals("b", StringUtils.mid(FOOBAR, 3, 1));
+ assertEquals(FOO, StringUtils.mid(FOOBAR, 0, 3));
+ assertEquals(BAR, StringUtils.mid(FOOBAR, 3, 3));
+ assertEquals(FOOBAR, StringUtils.mid(FOOBAR, 0, 80));
+ assertEquals(BAR, StringUtils.mid(FOOBAR, 3, 80));
+ }
+
+ public void testMidEx1() {
+ try {
+ StringUtils.mid(FOOBAR, 0, -1);
+ } catch (IllegalArgumentException ex) {
+ return;
+ }
+ fail();
+ }
+
+ public void testMidEx2() {
+ try {
+ StringUtils.mid(FOOBAR, -1, 3);
+ } catch (IndexOutOfBoundsException ex) {
+ return;
+ }
+ fail();
+ }
+
+ public void testMidEx3() {
+ try {
+ StringUtils.mid(FOOBAR, 7, 3);
+ } catch (IndexOutOfBoundsException ex) {
+ return;
+ }
+ fail();
+ }
+
+ public void testCountMatches() {
+ try {
+ assertEquals(-1,
+ StringUtils.countMatches(null, null));
+ throw new RuntimeException("Should have thrown a NullPointerException. ");
+ } catch(NullPointerException npe) {
+ }
+
+ assertEquals(0,
+ StringUtils.countMatches("x", "") );
+ assertEquals(0,
+ StringUtils.countMatches("", "") );
+
+ assertEquals(3,
+ StringUtils.countMatches("one long someone sentence of one", "one"));
+ assertEquals(0,
+ StringUtils.countMatches("one long someone sentence of one", "two"));
+ assertEquals(4,
+ StringUtils.countMatches("oooooooooooo", "ooo"));
+ }
+
+ public void testGetNestedString() {
+ assertEquals( "", StringUtils.getNestedString("", "") );
+ assertEquals( "", StringUtils.getNestedString(" ", " ") );
+ assertEquals( "bar", StringUtils.getNestedString("\nbar\n", "\n") );
+ assertEquals( "", StringUtils.getNestedString("", "", "") );
+ assertEquals( "", StringUtils.getNestedString(" ", " ", " ") );
+ assertEquals( "bar", StringUtils.getNestedString("bar ", "", " ") );
+ }
+
+}
diff --git a/examples/cl2/src/test/org/apache/commons/lang/StringUtilsTest.java b/examples/cl2/src/test/org/apache/commons/lang/StringUtilsTest.java
new file mode 100644
index 00000000..f0ac4c31
--- /dev/null
+++ b/examples/cl2/src/test/org/apache/commons/lang/StringUtilsTest.java
@@ -0,0 +1,102 @@
+/* ====================================================================
+ * 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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
+ * .
+ */
+package org.apache.commons.lang;
+
+import java.util.Arrays;
+
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import junit.textui.TestRunner;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * Unit tests {@link org.apache.commons.lang.StringUtils}.
+ *
+ * @author Daniel Rall
+ * @author Henri Yandell
+ * @author Stephen Colebourne
+ * @author Ringo De Smet
+ * @author Fredrik Westermarck
+ * @author Holger Krauth
+ * @author Henning P. Schmiedehausen
+ * @version $Id: StringUtilsTest.java,v 1.21 2003/06/23 03:51:13 bayard Exp $
+ */
+public class StringUtilsTest {
+
+ private static final String[] ARRAY_LIST = { "foo", "bar", "baz" };
+ private static final String[] EMPTY_ARRAY_LIST = {};
+
+ private static final String SEPARATOR = ",";
+ private static final char SEPARATOR_CHAR = ';';
+
+ private static final String TEXT_LIST = "foo,bar,baz";
+ private static final String TEXT_LIST_CHAR = "foo;bar;baz";
+ private static final String TEXT_LIST_NOSEP = "foobarbaz";
+
+ private static final String FOO = "foo";
+ private static final String BAR = "bar";
+ private static final String CAP_FOO = "Foo";
+
+ private static final String SENTENCE = "foo bar baz";
+
+ @Test
+ public void testChopNewLine_8() {
+ assertEquals("chopNewline(String) failed","", StringUtils.chopNewline(""));
+ }
+
+}
+
diff --git a/examples/cl2/src/test/org/apache/commons/lang/StringUtilsTrimEmptyTest.java b/examples/cl2/src/test/org/apache/commons/lang/StringUtilsTrimEmptyTest.java
new file mode 100644
index 00000000..5115f71d
--- /dev/null
+++ b/examples/cl2/src/test/org/apache/commons/lang/StringUtilsTrimEmptyTest.java
@@ -0,0 +1,240 @@
+/* ====================================================================
+ * 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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
+ * .
+ */
+package org.apache.commons.lang;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import junit.textui.TestRunner;
+
+/**
+ * Unit tests {@link org.apache.commons.lang.StringUtils} - Trim/Empty methods
+ *
+ * @author Stephen Colebourne
+ * @author Ringo De Smet
+ * @version $Id: StringUtilsTrimEmptyTest.java,v 1.7 2003/03/24 00:47:02 scolebourne Exp $
+ */
+public class StringUtilsTrimEmptyTest extends TestCase {
+ private static final String FOO = "foo";
+
+ public StringUtilsTrimEmptyTest(String name) {
+ super(name);
+ }
+
+ public static void main(String[] args) {
+ TestRunner.run(suite());
+ }
+
+ public static Test suite() {
+ TestSuite suite = new TestSuite(StringUtilsTrimEmptyTest.class);
+ suite.setName("StringUtilsTrimEmpty Tests");
+ return suite;
+ }
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ //-----------------------------------------------------------------------
+
+ public void testClean() {
+ assertEquals(FOO, StringUtils.clean(FOO + " "));
+ assertEquals(FOO, StringUtils.clean(" " + FOO + " "));
+ assertEquals(FOO, StringUtils.clean(" " + FOO));
+ assertEquals(FOO, StringUtils.clean(FOO + ""));
+ assertEquals("", StringUtils.clean(" \t\r\n\b "));
+ assertEquals("", StringUtils.clean(""));
+ assertEquals("", StringUtils.clean(null));
+ }
+
+ public void testTrim() {
+ assertEquals(FOO, StringUtils.trim(FOO + " "));
+ assertEquals(FOO, StringUtils.trim(" " + FOO + " "));
+ assertEquals(FOO, StringUtils.trim(" " + FOO));
+ assertEquals(FOO, StringUtils.trim(FOO + ""));
+ assertEquals("", StringUtils.trim(" \t\r\n\b "));
+ assertEquals("", StringUtils.trim(""));
+ assertEquals(null, StringUtils.trim(null));
+ }
+
+ public void testTrimToNull() {
+ assertEquals(FOO, StringUtils.trimToNull(FOO + " "));
+ assertEquals(FOO, StringUtils.trimToNull(" " + FOO + " "));
+ assertEquals(FOO, StringUtils.trimToNull(" " + FOO));
+ assertEquals(FOO, StringUtils.trimToNull(FOO + ""));
+ assertEquals(null, StringUtils.trimToNull(" \t\r\n\b "));
+ assertEquals(null, StringUtils.trimToNull(""));
+ assertEquals(null, StringUtils.trimToNull(null));
+ }
+
+ public void testTrimToEmpty() {
+ assertEquals(FOO, StringUtils.trimToEmpty(FOO + " "));
+ assertEquals(FOO, StringUtils.trimToEmpty(" " + FOO + " "));
+ assertEquals(FOO, StringUtils.trimToEmpty(" " + FOO));
+ assertEquals(FOO, StringUtils.trimToEmpty(FOO + ""));
+ assertEquals("", StringUtils.trimToEmpty(" \t\r\n\b "));
+ assertEquals("", StringUtils.trimToEmpty(""));
+ assertEquals("", StringUtils.trimToEmpty(null));
+ }
+
+ public void testIsNotEmpty() {
+ assertEquals(true, StringUtils.isNotEmpty(FOO));
+ assertEquals(true, StringUtils.isNotEmpty(" "));
+ assertEquals(false, StringUtils.isNotEmpty(""));
+ assertEquals(false, StringUtils.isNotEmpty(null));
+ }
+
+ public void testIsEmpty() {
+ assertEquals(false, StringUtils.isEmpty(FOO));
+ assertEquals(true, StringUtils.isEmpty(" "));
+ assertEquals(true, StringUtils.isEmpty(""));
+ assertEquals(true, StringUtils.isEmpty(null));
+ }
+
+ public void testDeleteSpace() {
+ assertEquals("deleteWhitespace(String) failed",
+ "", StringUtils.deleteWhitespace(""));
+ assertEquals("deleteWhitespace(String) failed",
+ "", StringUtils.deleteWhitespace(" \u000C \t\t\u001F\n\n \u000B "));
+ // Note: u-2007 and u-000A both cause problems in the source code
+ // it should ignore 2007 but delete 000A
+ assertEquals("deleteWhitespace(String) failed",
+ "\u00A0\u202F", StringUtils.deleteWhitespace(" \u00A0 \t\t\n\n \u202F "));
+ assertEquals("deleteWhitespace(String) failed",
+ "\u00A0\u202F", StringUtils.deleteWhitespace("\u00A0\u202F"));
+ assertEquals("deleteWhitespace(String) failed",
+ "test", StringUtils.deleteWhitespace("\u000Bt \t\n\u0009e\rs\n\n \tt"));
+
+ assertEquals("deleteSpaces(String) failed",
+ "", StringUtils.deleteSpaces(""));
+ assertEquals("deleteSpaces(String) failed",
+ "", StringUtils.deleteSpaces(" \t\t\n\n "));
+ assertEquals("deleteSpaces(String) failed",
+ "test", StringUtils.deleteSpaces("t \t\ne\rs\n\n \tt"));
+ }
+
+ public void testStrip() {
+ // it's important that foo2Space is fooLeftSpace and fooRightSpace
+ // merged together. So same number of spaces to left as fLS and same
+ // to right as fLS. Same applies for foo2Dots.
+ String foo2Space = " "+FOO+" ";
+ String foo2Dots = "......"+FOO+".........";
+ String fooLeftSpace = " "+FOO;
+ String fooLeftDots = "......"+FOO;
+ String fooRightSpace = FOO+" ";
+ String fooRightDots = FOO+".........";
+
+ assertEquals("", StringUtils.strip(""));
+ assertEquals("", StringUtils.strip(" "));
+ assertEquals(FOO, StringUtils.strip(foo2Space));
+ assertEquals(FOO, StringUtils.strip(foo2Dots, "."));
+ assertEquals(FOO, StringUtils.strip(fooRightSpace));
+ assertEquals(FOO, StringUtils.strip(fooRightDots, "."));
+ assertEquals(FOO, StringUtils.strip(fooLeftSpace));
+ assertEquals(FOO, StringUtils.strip(fooLeftDots, "."));
+
+ assertEquals("", StringUtils.stripStart("", " "));
+ assertEquals(fooRightSpace, StringUtils.stripStart(foo2Space, " "));
+ assertEquals(fooRightDots, StringUtils.stripStart(foo2Dots, "."));
+ assertEquals(fooRightSpace, StringUtils.stripStart(fooRightSpace, " "));
+ assertEquals(fooRightDots, StringUtils.stripStart(fooRightDots, "."));
+ assertEquals(FOO, StringUtils.stripStart(fooLeftSpace, " "));
+ assertEquals(FOO, StringUtils.stripStart(fooLeftDots, "."));
+
+ assertEquals("", StringUtils.stripEnd("", " "));
+ assertEquals(fooLeftSpace, StringUtils.stripEnd(foo2Space, " "));
+ assertEquals(fooLeftDots, StringUtils.stripEnd(foo2Dots, "."));
+ assertEquals(FOO, StringUtils.stripEnd(fooRightSpace, " "));
+ assertEquals(FOO, StringUtils.stripEnd(fooRightDots, "."));
+ assertEquals(fooLeftSpace, StringUtils.stripEnd(fooLeftSpace, " "));
+ assertEquals(fooLeftDots, StringUtils.stripEnd(fooLeftDots, "."));
+
+ assertEquals(FOO, StringUtils.strip(". . . . ."+FOO+". . ", " ."));
+ assertEquals("-."+FOO, StringUtils.strip(". . . . -."+FOO+". . ", " ."));
+ assertEquals(FOO, StringUtils.strip(".. .."+FOO+".. ", " ."));
+ assertEquals(FOO, StringUtils.strip(".. .."+FOO+".. ", "+= ."));
+
+ // test stripAll method, merely an array version of the above strip
+ String[] empty = new String[0];
+ String[] fooSpace = new String[] { foo2Space, fooLeftSpace, fooRightSpace };
+ String[] fooDots = new String[] { foo2Dots, fooLeftDots, fooRightDots };
+ String[] foo = new String[] { FOO, FOO, FOO };
+
+ assertArrayEquals(empty, StringUtils.stripAll(empty));
+ assertArrayEquals(foo, StringUtils.stripAll(fooSpace));
+ assertArrayEquals(foo, StringUtils.stripAll(fooDots, "."));
+ }
+
+ private void assertArrayEquals(Object[] o1, Object[] o2) {
+ if(o1 == null) {
+ assertEquals(o1,o2);
+ return;
+ }
+ assertEquals("Length not equal. ", o1.length, o2.length);
+ int sz = o1.length;
+ for(int i=0; i .
+ */
+package org.apache.commons.lang;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import junit.textui.TestRunner;
+
+/**
+ * Unit tests {@link org.apache.commons.lang.SystemUtils}.
+ *
+ * Only limited testing can be performed.
+ *
+ * @author Stephen Colebourne
+ * @version $Id: SystemUtilsTest.java,v 1.2 2003/05/24 14:34:14 scolebourne Exp $
+ */
+public class SystemUtilsTest extends TestCase {
+
+ public SystemUtilsTest(String name) {
+ super(name);
+ }
+
+ public static void main(String[] args) {
+ TestRunner.run(suite());
+// SystemUtils s = new SystemUtils();
+// System.out.println(s.IS_OS_WINDOWS);
+// System.out.println(s.IS_OS_WINDOWS_95);
+// System.out.println(s.IS_OS_WINDOWS_98);
+// java.util.Properties p = System.getProperties();
+// java.util.Enumeration keys = p.keys();
+// java.util.List list = new java.util.ArrayList();
+// while( keys.hasMoreElements() ) {
+// list.add(keys.nextElement());
+// }
+// java.util.Collections.sort(list);
+// for (java.util.Iterator it = list.iterator(); it.hasNext();) {
+// String key = (String) it.next();
+// System.out.println(key + " " + p.getProperty(key));
+// }
+
+ }
+
+ public static Test suite() {
+ TestSuite suite = new TestSuite(SystemUtilsTest.class);
+ suite.setName("SystemUtils Tests");
+ return suite;
+ }
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ //-----------------------------------------------------------------------
+ // COPIED FROM SystemUtils
+ //-----------------------------------------------------------------------
+ private String JAVA_VERSION;
+ private String OS_NAME;
+ private String OS_VERSION;
+
+ /**
+ * Decides if the java version matches.
+ *
+ * @param versionPrefix the prefix for the java version
+ * @return true if matches, or false if not or can't determine
+ */
+ private boolean getJavaVersionMatches(String versionPrefix) {
+ if (JAVA_VERSION == null) {
+ return false;
+ }
+ return JAVA_VERSION.startsWith(versionPrefix);
+ }
+
+ /**
+ * Get the Java version number as a float
.
+ *
+ * Example output:
+ *
+ * 1.2f
for JDK 1.2
+ * 1.31f
for JDK 1.3.1
+ *
+ *
+ * Patch releases are not reported.
+ * Zero is returned if JAVA_VERSION is null
.
+ *
+ * @return the version, for example 1.31f for JDK 1.3.1
+ */
+ private 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);
+ }
+
+ /**
+ * Get the Java version number as an int
.
+ *
+ * Example output:
+ *
+ * 120
for JDK 1.2
+ * 131
for JDK 1.3.1
+ *
+ *
+ * Patch releases are not reported.
+ * Zero is returned if JAVA_VERSION is null
.
+ *
+ * @return the version, for example 131 for JDK 1.3.1
+ */
+ private 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);
+ }
+
+ /**
+ * Decides if the operating system matches.
+ *
+ * @param osNamePrefix the prefix for the os name
+ * @return true if matches, or false if not or can't determine
+ */
+ private boolean getOSMatches(String osNamePrefix) {
+ if (OS_NAME == null) {
+ return false;
+ }
+ return OS_NAME.startsWith(osNamePrefix);
+ }
+
+ /**
+ * Decides if the operating system matches.
+ *
+ * @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 boolean getOSMatches(String osNamePrefix, String osVersionPrefix) {
+ if (OS_NAME == null || OS_VERSION == null) {
+ return false;
+ }
+ return OS_NAME.startsWith(osNamePrefix) && OS_VERSION.startsWith(osVersionPrefix);
+ }
+
+ //-----------------------------------------------------------------------
+ public void testJavaVersionMatches() {
+ JAVA_VERSION = null;
+ assertEquals(false, getJavaVersionMatches("1.1"));
+ assertEquals(false, getJavaVersionMatches("1.2"));
+ assertEquals(false, getJavaVersionMatches("1.3"));
+ assertEquals(false, getJavaVersionMatches("1.4"));
+ assertEquals(false, getJavaVersionMatches("1.5"));
+ JAVA_VERSION = "1.1";
+ assertEquals(true, getJavaVersionMatches("1.1"));
+ assertEquals(false, getJavaVersionMatches("1.2"));
+ assertEquals(false, getJavaVersionMatches("1.3"));
+ assertEquals(false, getJavaVersionMatches("1.4"));
+ assertEquals(false, getJavaVersionMatches("1.5"));
+ JAVA_VERSION = "1.2";
+ assertEquals(false, getJavaVersionMatches("1.1"));
+ assertEquals(true, getJavaVersionMatches("1.2"));
+ assertEquals(false, getJavaVersionMatches("1.3"));
+ assertEquals(false, getJavaVersionMatches("1.4"));
+ assertEquals(false, getJavaVersionMatches("1.5"));
+ JAVA_VERSION = "1.3.0";
+ assertEquals(false, getJavaVersionMatches("1.1"));
+ assertEquals(false, getJavaVersionMatches("1.2"));
+ assertEquals(true, getJavaVersionMatches("1.3"));
+ assertEquals(false, getJavaVersionMatches("1.4"));
+ assertEquals(false, getJavaVersionMatches("1.5"));
+ JAVA_VERSION = "1.3.1";
+ assertEquals(false, getJavaVersionMatches("1.1"));
+ assertEquals(false, getJavaVersionMatches("1.2"));
+ assertEquals(true, getJavaVersionMatches("1.3"));
+ assertEquals(false, getJavaVersionMatches("1.4"));
+ assertEquals(false, getJavaVersionMatches("1.5"));
+ JAVA_VERSION = "1.4.0";
+ assertEquals(false, getJavaVersionMatches("1.1"));
+ assertEquals(false, getJavaVersionMatches("1.2"));
+ assertEquals(false, getJavaVersionMatches("1.3"));
+ assertEquals(true, getJavaVersionMatches("1.4"));
+ assertEquals(false, getJavaVersionMatches("1.5"));
+ JAVA_VERSION = "1.4.1";
+ assertEquals(false, getJavaVersionMatches("1.1"));
+ assertEquals(false, getJavaVersionMatches("1.2"));
+ assertEquals(false, getJavaVersionMatches("1.3"));
+ assertEquals(true, getJavaVersionMatches("1.4"));
+ assertEquals(false, getJavaVersionMatches("1.5"));
+ JAVA_VERSION = "1.5.0";
+ assertEquals(false, getJavaVersionMatches("1.1"));
+ assertEquals(false, getJavaVersionMatches("1.2"));
+ assertEquals(false, getJavaVersionMatches("1.3"));
+ assertEquals(false, getJavaVersionMatches("1.4"));
+ assertEquals(true, getJavaVersionMatches("1.5"));
+ JAVA_VERSION = "1.6.0";
+ assertEquals(false, getJavaVersionMatches("1.1"));
+ assertEquals(false, getJavaVersionMatches("1.2"));
+ assertEquals(false, getJavaVersionMatches("1.3"));
+ assertEquals(false, getJavaVersionMatches("1.4"));
+ assertEquals(false, getJavaVersionMatches("1.5"));
+ }
+
+ public void testJavaVersionAsFloat() {
+ JAVA_VERSION = null;
+ assertEquals(0f, getJavaVersionAsFloat(), 0.000001f);
+ JAVA_VERSION = "1.1";
+ assertEquals(1.1f, getJavaVersionAsFloat(), 0.000001f);
+ JAVA_VERSION = "1.2";
+ assertEquals(1.2f, getJavaVersionAsFloat(), 0.000001f);
+ JAVA_VERSION = "1.3.0";
+ assertEquals(1.3f, getJavaVersionAsFloat(), 0.000001f);
+ JAVA_VERSION = "1.3.1";
+ assertEquals(1.31f, getJavaVersionAsFloat(), 0.000001f);
+ JAVA_VERSION = "1.4.0";
+ assertEquals(1.4f, getJavaVersionAsFloat(), 0.000001f);
+ JAVA_VERSION = "1.4.1";
+ assertEquals(1.41f, getJavaVersionAsFloat(), 0.000001f);
+ JAVA_VERSION = "1.5.0";
+ assertEquals(1.5f, getJavaVersionAsFloat(), 0.000001f);
+ JAVA_VERSION = "1.6.0";
+ assertEquals(1.6f, getJavaVersionAsFloat(), 0.000001f);
+ }
+
+ public void testJavaVersionAsInt() {
+ JAVA_VERSION = null;
+ assertEquals(0, getJavaVersionAsInt());
+ JAVA_VERSION = "1.1";
+ assertEquals(110, getJavaVersionAsInt());
+ JAVA_VERSION = "1.2";
+ assertEquals(120, getJavaVersionAsInt());
+ JAVA_VERSION = "1.3.0";
+ assertEquals(130, getJavaVersionAsInt());
+ JAVA_VERSION = "1.3.1";
+ assertEquals(131, getJavaVersionAsInt());
+ JAVA_VERSION = "1.4.0";
+ assertEquals(140, getJavaVersionAsInt());
+ JAVA_VERSION = "1.4.1";
+ assertEquals(141, getJavaVersionAsInt());
+ JAVA_VERSION = "1.5.0";
+ assertEquals(150, getJavaVersionAsInt());
+ JAVA_VERSION = "1.6.0";
+ assertEquals(160, getJavaVersionAsInt());
+ }
+
+ public void testJavaVersionAtLeastFloat() {
+ float version = SystemUtils.JAVA_VERSION_FLOAT;
+ assertEquals(true, SystemUtils.isJavaVersionAtLeast(version));
+ version -= 0.1f;
+ assertEquals(true, SystemUtils.isJavaVersionAtLeast(version));
+ version += 0.2f;
+ assertEquals(false, SystemUtils.isJavaVersionAtLeast(version));
+ }
+
+ public void testJavaVersionAtLeastInt() {
+ int version = SystemUtils.JAVA_VERSION_INT;
+ assertEquals(true, SystemUtils.isJavaVersionAtLeast(version));
+ version -= 10;
+ assertEquals(true, SystemUtils.isJavaVersionAtLeast(version));
+ version += 20;
+ assertEquals(false, SystemUtils.isJavaVersionAtLeast(version));
+ }
+
+ public void testOSMatches() {
+ OS_NAME = null;
+ assertEquals(false, getOSMatches("Windows"));
+ OS_NAME = "Windows 95";
+ assertEquals(true, getOSMatches("Windows"));
+ OS_NAME = "Windows NT";
+ assertEquals(true, getOSMatches("Windows"));
+ OS_NAME = "OS/2";
+ assertEquals(false, getOSMatches("Windows"));
+ }
+
+ public void testOSMatches2() {
+ OS_NAME = null;
+ OS_VERSION = null;
+ assertEquals(false, getOSMatches("Windows 9", "4.1"));
+ OS_NAME = "Windows 95";
+ OS_VERSION = "4.0";
+ assertEquals(false, getOSMatches("Windows 9", "4.1"));
+ OS_NAME = "Windows 95";
+ OS_VERSION = "4.1";
+ assertEquals(true, getOSMatches("Windows 9", "4.1"));
+ OS_NAME = "Windows 98";
+ OS_VERSION = "4.1";
+ assertEquals(true, getOSMatches("Windows 9", "4.1"));
+ OS_NAME = "Windows NT";
+ OS_VERSION = "4.0";
+ assertEquals(false, getOSMatches("Windows 9", "4.1"));
+ OS_NAME = "OS/2";
+ OS_VERSION = "4.0";
+ assertEquals(false, getOSMatches("Windows 9", "4.1"));
+ }
+
+}
diff --git a/examples/cl2/src/test/org/apache/commons/lang/UnhandledExceptionTest.java b/examples/cl2/src/test/org/apache/commons/lang/UnhandledExceptionTest.java
new file mode 100644
index 00000000..6eca5767
--- /dev/null
+++ b/examples/cl2/src/test/org/apache/commons/lang/UnhandledExceptionTest.java
@@ -0,0 +1,111 @@
+/* ====================================================================
+ * 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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
+ * .
+ */
+package org.apache.commons.lang;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import junit.textui.TestRunner;
+
+import org.apache.commons.lang.exception.Nestable;
+
+/**
+ * JUnit tests.
+ *
+ * @author Matthew Hawthorne
+ * @version $Id: UnhandledExceptionTest.java,v 1.1 2003/05/15 04:05:11 bayard Exp $
+ * @see UnhandledException
+ */
+public class UnhandledExceptionTest extends TestCase {
+
+ public static void main(String[] args) {
+ TestRunner.run(suite());
+ }
+
+ public static Test suite() {
+ return new TestSuite(UnhandledExceptionTest.class);
+ }
+
+ public UnhandledExceptionTest(String testName) {
+ super(testName);
+ }
+
+ // testConstructor
+
+ public void testConstructor_throwable_nullInput() {
+ final Throwable t = null;
+ new UnhandledException(t);
+ }
+
+ public void testConstructor_stringAndThrowable_nullInput() {
+ new UnhandledException(null, null);
+ }
+
+ // testGetCause
+
+ public void testGetCause() {
+ final Throwable t = new NullPointerException();
+ final Nestable n = new UnhandledException(t);
+ assertEquals(t, n.getCause());
+ }
+
+ public void testGetCauseAndGetMessage() {
+ final Throwable t = new NullPointerException();
+ final String msg = "nullArg";
+ final Nestable n = new UnhandledException(msg, t);
+ assertEquals(t, n.getCause());
+ assertEquals(msg, n.getMessage());
+ }
+
+} // UnhandledExceptionTest
diff --git a/examples/cl2/src/test/org/apache/commons/lang/WordWrapUtilsTest.java b/examples/cl2/src/test/org/apache/commons/lang/WordWrapUtilsTest.java
new file mode 100644
index 00000000..28931652
--- /dev/null
+++ b/examples/cl2/src/test/org/apache/commons/lang/WordWrapUtilsTest.java
@@ -0,0 +1,110 @@
+/* ====================================================================
+ * 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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
+ * .
+ */
+package org.apache.commons.lang;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+/**
+ * Unit tests for the wrap methods of WordWrapUtils.
+ *
+ * @author Ringo De Smet
+ * @version $Id: WordWrapUtilsTest.java,v 1.1 2003/04/15 14:28:41 bayard Exp $
+ */
+public class WordWrapUtilsTest extends TestCase {
+
+ public WordWrapUtilsTest(String name) {
+ super(name);
+ }
+
+ public static Test suite() {
+ TestSuite suite = new TestSuite(WordWrapUtilsTest.class);
+ suite.setName("WordWrapperTests");
+ return suite;
+ }
+
+ /**
+ * Wrap text. This is the most general use.
+ */
+ public void testWrapText1() {
+ String input =
+ "Here is one line of text that is going to be wrapped after 20 columns.";
+ String expected =
+ "Here is one line of\ntext that is going\nto be wrapped after\n20 columns.";
+ assertEquals("Text didn't wrap correctly, ", expected, WordWrapUtils.wrapText(input, "\n", 20));
+ }
+
+ /**
+ * Wrap text with a tab character in the middle of a string.
+ */
+ public void testWrapText2() {
+ String input =
+ "Here is\tone line of text that is going to be wrapped after 20 columns.";
+ String expected =
+ "Here is\tone line of\ntext that is going\nto be wrapped after\n20 columns.";
+ assertEquals("Text with tab didn't wrap correctly, ", expected, WordWrapUtils.wrapText(input, "\n", 20));
+ }
+
+ /**
+ * Wrap text with a tab character located at the wrapping column index.
+ */
+ public void testWrapText3() {
+ String input =
+ "Here is one line of\ttext that is going to be wrapped after 20 columns.";
+ String expected =
+ "Here is one line\nof\ttext that is\ngoing to be wrapped\nafter 20 columns.";
+ assertEquals("Text with tab at wrapping index didn't wrap correctly, ", expected, WordWrapUtils.wrapText(input, "\n", 20));
+ }
+}
diff --git a/examples/cl2/src/test/org/apache/commons/lang/builder/BuilderTestSuite.java b/examples/cl2/src/test/org/apache/commons/lang/builder/BuilderTestSuite.java
new file mode 100644
index 00000000..b950514d
--- /dev/null
+++ b/examples/cl2/src/test/org/apache/commons/lang/builder/BuilderTestSuite.java
@@ -0,0 +1,100 @@
+/* ====================================================================
+ * 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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
+ * .
+ */
+package org.apache.commons.lang.builder;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import junit.textui.TestRunner;
+/**
+ * Test suite for the Lang Builder package.
+ *
+ * @author Stephen Colebourne
+ * @version $Id: BuilderTestSuite.java,v 1.5 2003/05/21 23:49:15 scolebourne Exp $
+ */
+public class BuilderTestSuite extends TestCase {
+
+ /**
+ * Construct a new instance.
+ */
+ public BuilderTestSuite(String name) {
+ super(name);
+ }
+
+ /**
+ * Command-line interface.
+ */
+ public static void main(String[] args) {
+ TestRunner.run(suite());
+ }
+
+ /**
+ * Get the suite of tests
+ */
+ public static Test suite() {
+ TestSuite suite = new TestSuite();
+ suite.setName("Commons-Lang-Builder Tests");
+ suite.addTest(CompareToBuilderTest.suite());
+ suite.addTest(EqualsBuilderTest.suite());
+ suite.addTest(HashCodeBuilderTest.suite());
+ suite.addTest(HashCodeBuilderAndEqualsBuilderTest.suite());
+ suite.addTest(ToStringBuilderTest.suite());
+ suite.addTest(DefaultToStringStyleTest.suite());
+ suite.addTest(NoFieldNamesToStringStyleTest.suite());
+ suite.addTest(MultiLineToStringStyleTest.suite());
+ suite.addTest(SimpleToStringStyleTest.suite());
+ suite.addTest(StandardToStringStyleTest.suite());
+ return suite;
+ }
+}
diff --git a/examples/cl2/src/test/org/apache/commons/lang/builder/CompareToBuilderTest.java b/examples/cl2/src/test/org/apache/commons/lang/builder/CompareToBuilderTest.java
new file mode 100644
index 00000000..c6c78017
--- /dev/null
+++ b/examples/cl2/src/test/org/apache/commons/lang/builder/CompareToBuilderTest.java
@@ -0,0 +1,1145 @@
+/* ====================================================================
+ * 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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
+ * .
+ */
+package org.apache.commons.lang.builder;
+
+import java.math.BigInteger;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import junit.textui.TestRunner;
+/**
+ * Unit tests {@link org.apache.commons.lang.CompareToBuilder}.
+ *
+ * @author Steve Downey
+ * @author Stephen Colebourne
+ * @version $Id: CompareToBuilderTest.java,v 1.5 2003/05/21 23:49:14 scolebourne Exp $
+ */
+public class CompareToBuilderTest extends TestCase {
+
+ public CompareToBuilderTest(String name) {
+ super(name);
+ }
+ public static void main(String[] args) {
+ TestRunner.run(suite());
+ }
+
+ public static Test suite() {
+ TestSuite suite = new TestSuite(CompareToBuilderTest.class);
+ suite.setName("CompareToBuilder Tests");
+ return suite;
+ }
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ //-----------------------------------------------------------------------
+
+ static class TestObject implements Comparable {
+ private int a;
+ public TestObject(int a) {
+ this.a = a;
+ }
+ public boolean equals(Object o) {
+ if (o == this) {
+ return true;
+ }
+ if (!(o instanceof TestObject)) {
+ return false;
+ }
+ TestObject rhs = (TestObject) o;
+ return (a == rhs.a);
+ }
+
+ public void setA(int a) {
+ this.a = a;
+ }
+
+ public int getA() {
+ return a;
+ }
+ public int compareTo(Object o) {
+ TestObject rhs = (TestObject) o;
+ return (a < rhs.a) ? -1 : (a > rhs.a) ? +1 : 0;
+ }
+ }
+
+ static class TestSubObject extends TestObject {
+ private int b;
+ public TestSubObject() {
+ super(0);
+ }
+ public TestSubObject(int a, int b) {
+ super(a);
+ this.b = b;
+ }
+ public boolean equals(Object o) {
+ if (o == this) {
+ return true;
+ }
+ if (!(o instanceof TestSubObject)) {
+ return false;
+ }
+ TestSubObject rhs = (TestSubObject) o;
+ return super.equals(o) && (b == rhs.b);
+ }
+ }
+
+ static class TestTransientSubObject extends TestObject {
+ private transient int t;
+ public TestTransientSubObject(int a, int t) {
+ super(a);
+ this.t = t;
+ }
+ }
+
+ public void testReflectionCompare() {
+ TestObject o1 = new TestObject(4);
+ TestObject o2 = new TestObject(4);
+ assertTrue(CompareToBuilder.reflectionCompare(o1, o1) == 0);
+ assertTrue(CompareToBuilder.reflectionCompare(o1, o2) == 0);
+ o2.setA(5);
+ assertTrue(CompareToBuilder.reflectionCompare(o1, o2) < 0);
+ assertTrue(CompareToBuilder.reflectionCompare(o2, o1) > 0);
+ }
+
+ public void testReflectionCompareEx1() {
+ TestObject o1 = new TestObject(4);
+ try {
+ CompareToBuilder.reflectionCompare(o1, null);
+ } catch (NullPointerException ex) {
+ return;
+ }
+ fail();
+ }
+
+ public void testReflectionCompareEx2() {
+ TestObject o1 = new TestObject(4);
+ Object o2 = new Object();
+ try {
+ CompareToBuilder.reflectionCompare(o1, o2);
+ fail();
+ } catch (ClassCastException ex) {}
+ }
+
+ public void testReflectionHierarchyCompare() {
+ testReflectionHierarchyCompare(false);
+ }
+
+ public void testReflectionHierarchyCompareTransients() {
+ testReflectionHierarchyCompare(true);
+
+ TestTransientSubObject x;
+ TestTransientSubObject y;
+ TestTransientSubObject z;
+
+ x = new TestTransientSubObject(1, 1);
+ y = new TestTransientSubObject(2, 2);
+ z = new TestTransientSubObject(3, 3);
+ assertXYZCompareOrder(x, y, z, true);
+
+ x = new TestTransientSubObject(1, 1);
+ y = new TestTransientSubObject(1, 2);
+ z = new TestTransientSubObject(1, 3);
+ assertXYZCompareOrder(x, y, z, true);
+ }
+
+ private void assertXYZCompareOrder(Object x, Object y, Object z, boolean testTransients) {
+ assertTrue(0 == CompareToBuilder.reflectionCompare(x, x, testTransients));
+ assertTrue(0 == CompareToBuilder.reflectionCompare(y, y, testTransients));
+ assertTrue(0 == CompareToBuilder.reflectionCompare(z, z, testTransients));
+
+ assertTrue(0 > CompareToBuilder.reflectionCompare(x, y, testTransients));
+ assertTrue(0 > CompareToBuilder.reflectionCompare(x, z, testTransients));
+ assertTrue(0 > CompareToBuilder.reflectionCompare(y, z, testTransients));
+
+ assertTrue(0 < CompareToBuilder.reflectionCompare(y, x, testTransients));
+ assertTrue(0 < CompareToBuilder.reflectionCompare(z, x, testTransients));
+ assertTrue(0 < CompareToBuilder.reflectionCompare(z, y, testTransients));
+ }
+
+ public void testReflectionHierarchyCompare(boolean testTransients) {
+ TestObject to1 = new TestObject(1);
+ TestObject to2 = new TestObject(2);
+ TestObject to3 = new TestObject(3);
+ TestSubObject tso1 = new TestSubObject(1, 1);
+ TestSubObject tso2 = new TestSubObject(2, 2);
+ TestSubObject tso3 = new TestSubObject(3, 3);
+
+ assertReflectionCompareContract(to1, to1, to1, false);
+ assertReflectionCompareContract(to1, to2, to3, false);
+ assertReflectionCompareContract(tso1, tso1, tso1, false);
+ assertReflectionCompareContract(tso1, tso2, tso3, false);
+ assertReflectionCompareContract("1", "2", "3", false);
+
+ assertTrue(0 != CompareToBuilder.reflectionCompare(tso1, new TestSubObject(1, 0), testTransients));
+ assertTrue(0 != CompareToBuilder.reflectionCompare(tso1, new TestSubObject(0, 1), testTransients));
+
+ // root class
+ assertXYZCompareOrder(to1, to2, to3, true);
+ // subclass
+ assertXYZCompareOrder(tso1, tso2, tso3, true);
+ }
+
+ /**
+ * See "Effective Java" under "Consider Implementing Comparable".
+ *
+ * @param x an object to compare
+ * @param y an object to compare
+ * @param z an object to compare
+ * @param testTransients Whether to include transients in the comparison
+ */
+ public void assertReflectionCompareContract(Object x, Object y, Object z, boolean testTransients) {
+
+ // signum
+ assertTrue(reflectionCompareSignum(x, y, testTransients) == -reflectionCompareSignum(y, x, testTransients));
+
+ // transitive
+ if (CompareToBuilder.reflectionCompare(x, y, testTransients) > 0 && CompareToBuilder.reflectionCompare(y, z, testTransients) > 0){
+ assertTrue(CompareToBuilder.reflectionCompare(x, z, testTransients) > 0);
+ }
+
+ // un-named
+ if (CompareToBuilder.reflectionCompare(x, y, testTransients) == 0) {
+ assertTrue(reflectionCompareSignum(x, z, testTransients) == -reflectionCompareSignum(y, z, testTransients));
+ }
+
+ // strongly recommended but not strictly required
+ assertTrue((CompareToBuilder.reflectionCompare(x, y, testTransients) ==0 ) == EqualsBuilder.reflectionEquals(x, y, testTransients));
+ }
+
+ /**
+ * Returns the signum of the result of comparing x and y with
+ * CompareToBuilder.reflectionCompare
+ *
+ * @param lhs The "left-hand-side" of the comparison.
+ * @param rhs The "right-hand-side" of the comparison.
+ * @param testTransients Whether to include transients in the comparison
+ * @return int The signum
+ */
+ private int reflectionCompareSignum(Object lhs, Object rhs, boolean testTransients) {
+ return BigInteger.valueOf(CompareToBuilder.reflectionCompare(lhs, rhs, testTransients)).signum();
+ }
+
+ public void testAppendSuper() {
+ TestObject o1 = new TestObject(4);
+ TestObject o2 = new TestObject(5);
+ assertTrue(new CompareToBuilder().appendSuper(0).append(o1, o1).toComparison() == 0);
+ assertTrue(new CompareToBuilder().appendSuper(0).append(o1, o2).toComparison() < 0);
+ assertTrue(new CompareToBuilder().appendSuper(0).append(o2, o1).toComparison() > 0);
+
+ assertTrue(new CompareToBuilder().appendSuper(-1).append(o1, o1).toComparison() < 0);
+ assertTrue(new CompareToBuilder().appendSuper(-1).append(o1, o2).toComparison() < 0);
+
+ assertTrue(new CompareToBuilder().appendSuper(1).append(o1, o1).toComparison() > 0);
+ assertTrue(new CompareToBuilder().appendSuper(1).append(o1, o2).toComparison() > 0);
+ }
+
+ public void testObject() {
+ TestObject o1 = new TestObject(4);
+ TestObject o2 = new TestObject(4);
+ assertTrue(new CompareToBuilder().append(o1, o1).toComparison() == 0);
+ assertTrue(new CompareToBuilder().append(o1, o2).toComparison() == 0);
+ o2.setA(5);
+ assertTrue(new CompareToBuilder().append(o1, o2).toComparison() < 0);
+ assertTrue(new CompareToBuilder().append(o2, o1).toComparison() > 0);
+
+ assertTrue(new CompareToBuilder().append(o1, null).toComparison() > 0);
+ assertTrue(new CompareToBuilder().append((Object) null, (Object) null).toComparison() == 0);
+ assertTrue(new CompareToBuilder().append(null, o1).toComparison() < 0);
+ }
+
+ public void testObjectEx2() {
+ TestObject o1 = new TestObject(4);
+ Object o2 = new Object();
+ try {
+ new CompareToBuilder().append(o1, o2);
+ fail();
+ } catch (ClassCastException ex) {}
+ }
+
+ public void testObjectComparator() {
+ String o1 = "Fred";
+ String o2 = "Fred";
+ assertTrue(new CompareToBuilder().append(o1, o1, String.CASE_INSENSITIVE_ORDER).toComparison() == 0);
+ assertTrue(new CompareToBuilder().append(o1, o2, String.CASE_INSENSITIVE_ORDER).toComparison() == 0);
+ o2 = "FRED";
+ assertTrue(new CompareToBuilder().append(o1, o2, String.CASE_INSENSITIVE_ORDER).toComparison() == 0);
+ assertTrue(new CompareToBuilder().append(o2, o1, String.CASE_INSENSITIVE_ORDER).toComparison() == 0);
+ o2 = "FREDA";
+ assertTrue(new CompareToBuilder().append(o1, o2, String.CASE_INSENSITIVE_ORDER).toComparison() < 0);
+ assertTrue(new CompareToBuilder().append(o2, o1, String.CASE_INSENSITIVE_ORDER).toComparison() > 0);
+
+ assertTrue(new CompareToBuilder().append(o1, null, String.CASE_INSENSITIVE_ORDER).toComparison() > 0);
+ assertTrue(new CompareToBuilder().append((Object) null, (Object) null, String.CASE_INSENSITIVE_ORDER).toComparison() == 0);
+ assertTrue(new CompareToBuilder().append(null, o1, String.CASE_INSENSITIVE_ORDER).toComparison() < 0);
+ }
+
+ public void testObjectComparatorNull() {
+ String o1 = "Fred";
+ String o2 = "Fred";
+ assertTrue(new CompareToBuilder().append(o1, o1, null).toComparison() == 0);
+ assertTrue(new CompareToBuilder().append(o1, o2, null).toComparison() == 0);
+ o2 = "Zebra";
+ assertTrue(new CompareToBuilder().append(o1, o2, null).toComparison() < 0);
+ assertTrue(new CompareToBuilder().append(o2, o1, null).toComparison() > 0);
+
+ assertTrue(new CompareToBuilder().append(o1, null, null).toComparison() > 0);
+ assertTrue(new CompareToBuilder().append((Object) null, (Object) null, null).toComparison() == 0);
+ assertTrue(new CompareToBuilder().append(null, o1, null).toComparison() < 0);
+ }
+
+ public void testLong() {
+ long o1 = 1L;
+ long o2 = 2L;
+ assertTrue(new CompareToBuilder().append(o1, o1).toComparison() == 0);
+ assertTrue(new CompareToBuilder().append(o1, o2).toComparison() < 0);
+ assertTrue(new CompareToBuilder().append(o2, o1).toComparison() > 0);
+ assertTrue(new CompareToBuilder().append(o1, Long.MAX_VALUE).toComparison() < 0);
+ assertTrue(new CompareToBuilder().append(Long.MAX_VALUE, o1).toComparison() > 0);
+ assertTrue(new CompareToBuilder().append(o1, Long.MIN_VALUE).toComparison() > 0);
+ assertTrue(new CompareToBuilder().append(Long.MIN_VALUE, o1).toComparison() < 0);
+ }
+
+ public void testInt() {
+ int o1 = 1;
+ int o2 = 2;
+ assertTrue(new CompareToBuilder().append(o1, o1).toComparison() == 0);
+ assertTrue(new CompareToBuilder().append(o1, o2).toComparison() < 0);
+ assertTrue(new CompareToBuilder().append(o2, o1).toComparison() > 0);
+ assertTrue(new CompareToBuilder().append(o1, Integer.MAX_VALUE).toComparison() < 0);
+ assertTrue(new CompareToBuilder().append(Integer.MAX_VALUE, o1).toComparison() > 0);
+ assertTrue(new CompareToBuilder().append(o1, Integer.MIN_VALUE).toComparison() > 0);
+ assertTrue(new CompareToBuilder().append(Integer.MIN_VALUE, o1).toComparison() < 0);
+ }
+
+ public void testShort() {
+ short o1 = 1;
+ short o2 = 2;
+ assertTrue(new CompareToBuilder().append(o1, o1).toComparison() == 0);
+ assertTrue(new CompareToBuilder().append(o1, o2).toComparison() < 0);
+ assertTrue(new CompareToBuilder().append(o2, o1).toComparison() > 0);
+ assertTrue(new CompareToBuilder().append(o1, Short.MAX_VALUE).toComparison() < 0);
+ assertTrue(new CompareToBuilder().append(Short.MAX_VALUE, o1).toComparison() > 0);
+ assertTrue(new CompareToBuilder().append(o1, Short.MIN_VALUE).toComparison() > 0);
+ assertTrue(new CompareToBuilder().append(Short.MIN_VALUE, o1).toComparison() < 0);
+ }
+
+ public void testChar() {
+ char o1 = 1;
+ char o2 = 2;
+ assertTrue(new CompareToBuilder().append(o1, o1).toComparison() == 0);
+ assertTrue(new CompareToBuilder().append(o1, o2).toComparison() < 0);
+ assertTrue(new CompareToBuilder().append(o2, o1).toComparison() > 0);
+ assertTrue(new CompareToBuilder().append(o1, Character.MAX_VALUE).toComparison() < 0);
+ assertTrue(new CompareToBuilder().append(Character.MAX_VALUE, o1).toComparison() > 0);
+ assertTrue(new CompareToBuilder().append(o1, Character.MIN_VALUE).toComparison() > 0);
+ assertTrue(new CompareToBuilder().append(Character.MIN_VALUE, o1).toComparison() < 0);
+ }
+
+ public void testByte() {
+ byte o1 = 1;
+ byte o2 = 2;
+ assertTrue(new CompareToBuilder().append(o1, o1).toComparison() == 0);
+ assertTrue(new CompareToBuilder().append(o1, o2).toComparison() < 0);
+ assertTrue(new CompareToBuilder().append(o2, o1).toComparison() > 0);
+ assertTrue(new CompareToBuilder().append(o1, Byte.MAX_VALUE).toComparison() < 0);
+ assertTrue(new CompareToBuilder().append(Byte.MAX_VALUE, o1).toComparison() > 0);
+ assertTrue(new CompareToBuilder().append(o1, Byte.MIN_VALUE).toComparison() > 0);
+ assertTrue(new CompareToBuilder().append(Byte.MIN_VALUE, o1).toComparison() < 0);
+ }
+
+ public void testDouble() {
+ double o1 = 1;
+ double o2 = 2;
+ assertTrue(new CompareToBuilder().append(o1, o1).toComparison() == 0);
+ assertTrue(new CompareToBuilder().append(o1, o2).toComparison() < 0);
+ assertTrue(new CompareToBuilder().append(o2, o1).toComparison() > 0);
+ assertTrue(new CompareToBuilder().append(o1, Double.MAX_VALUE).toComparison() < 0);
+ assertTrue(new CompareToBuilder().append(Double.MAX_VALUE, o1).toComparison() > 0);
+ assertTrue(new CompareToBuilder().append(o1, Double.MIN_VALUE).toComparison() > 0);
+ assertTrue(new CompareToBuilder().append(Double.MIN_VALUE, o1).toComparison() < 0);
+ assertTrue(new CompareToBuilder().append(Double.NaN, Double.NaN).toComparison() == 0);
+ assertTrue(new CompareToBuilder().append(Double.NaN, Double.MAX_VALUE).toComparison() > 0);
+ assertTrue(new CompareToBuilder().append(Double.POSITIVE_INFINITY, Double.MAX_VALUE).toComparison() > 0);
+ assertTrue(new CompareToBuilder().append(Double.NEGATIVE_INFINITY, Double.MIN_VALUE).toComparison() < 0);
+ assertTrue(new CompareToBuilder().append(o1, Double.NaN).toComparison() < 0);
+ assertTrue(new CompareToBuilder().append(Double.NaN, o1).toComparison() > 0);
+ assertTrue(new CompareToBuilder().append(-0.0, 0.0).toComparison() < 0);
+ assertTrue(new CompareToBuilder().append(0.0, -0.0).toComparison() > 0);
+ }
+
+ public void testFloat() {
+ float o1 = 1;
+ float o2 = 2;
+ assertTrue(new CompareToBuilder().append(o1, o1).toComparison() == 0);
+ assertTrue(new CompareToBuilder().append(o1, o2).toComparison() < 0);
+ assertTrue(new CompareToBuilder().append(o2, o1).toComparison() > 0);
+ assertTrue(new CompareToBuilder().append(o1, Float.MAX_VALUE).toComparison() < 0);
+ assertTrue(new CompareToBuilder().append(Float.MAX_VALUE, o1).toComparison() > 0);
+ assertTrue(new CompareToBuilder().append(o1, Float.MIN_VALUE).toComparison() > 0);
+ assertTrue(new CompareToBuilder().append(Float.MIN_VALUE, o1).toComparison() < 0);
+ assertTrue(new CompareToBuilder().append(Float.NaN, Float.NaN).toComparison() == 0);
+ assertTrue(new CompareToBuilder().append(Float.NaN, Float.MAX_VALUE).toComparison() > 0);
+ assertTrue(new CompareToBuilder().append(Float.POSITIVE_INFINITY, Float.MAX_VALUE).toComparison() > 0);
+ assertTrue(new CompareToBuilder().append(Float.NEGATIVE_INFINITY, Float.MIN_VALUE).toComparison() < 0);
+ assertTrue(new CompareToBuilder().append(o1, Float.NaN).toComparison() < 0);
+ assertTrue(new CompareToBuilder().append(Float.NaN, o1).toComparison() > 0);
+ assertTrue(new CompareToBuilder().append(-0.0, 0.0).toComparison() < 0);
+ assertTrue(new CompareToBuilder().append(0.0, -0.0).toComparison() > 0);
+ }
+
+ public void testBoolean() {
+ boolean o1 = true;
+ boolean o2 = false;
+ assertTrue(new CompareToBuilder().append(o1, o1).toComparison() == 0);
+ assertTrue(new CompareToBuilder().append(o2, o2).toComparison() == 0);
+ assertTrue(new CompareToBuilder().append(o1, o2).toComparison() > 0);
+ assertTrue(new CompareToBuilder().append(o2, o1).toComparison() < 0);
+ }
+
+ public void testObjectArray() {
+ TestObject[] obj1 = new TestObject[2];
+ obj1[0] = new TestObject(4);
+ obj1[1] = new TestObject(5);
+ TestObject[] obj2 = new TestObject[2];
+ obj2[0] = new TestObject(4);
+ obj2[1] = new TestObject(5);
+ TestObject[] obj3 = new TestObject[3];
+ obj3[0] = new TestObject(4);
+ obj3[1] = new TestObject(5);
+ obj3[2] = new TestObject(6);
+
+ assertTrue(new CompareToBuilder().append(obj1, obj1).toComparison() == 0);
+ assertTrue(new CompareToBuilder().append(obj1, obj2).toComparison() == 0);
+ assertTrue(new CompareToBuilder().append(obj1, obj3).toComparison() < 0);
+ assertTrue(new CompareToBuilder().append(obj3, obj1).toComparison() > 0);
+
+ obj1[1] = new TestObject(7);
+ assertTrue(new CompareToBuilder().append(obj1, obj2).toComparison() > 0);
+ assertTrue(new CompareToBuilder().append(obj2, obj1).toComparison() < 0);
+
+ assertTrue(new CompareToBuilder().append(obj1, null).toComparison() > 0);
+ assertTrue(new CompareToBuilder().append((Object[]) null, (Object[]) null).toComparison() == 0);
+ assertTrue(new CompareToBuilder().append(null, obj1).toComparison() < 0);
+ }
+
+ public void testLongArray() {
+ long[] obj1 = new long[2];
+ obj1[0] = 5L;
+ obj1[1] = 6L;
+ long[] obj2 = new long[2];
+ obj2[0] = 5L;
+ obj2[1] = 6L;
+ long[] obj3 = new long[3];
+ obj3[0] = 5L;
+ obj3[1] = 6L;
+ obj3[2] = 7L;
+
+ assertTrue(new CompareToBuilder().append(obj1, obj1).toComparison() == 0);
+ assertTrue(new CompareToBuilder().append(obj1, obj2).toComparison() == 0);
+ assertTrue(new CompareToBuilder().append(obj1, obj3).toComparison() < 0);
+ assertTrue(new CompareToBuilder().append(obj3, obj1).toComparison() > 0);
+
+ obj1[1] = 7;
+ assertTrue(new CompareToBuilder().append(obj1, obj2).toComparison() > 0);
+ assertTrue(new CompareToBuilder().append(obj2, obj1).toComparison() < 0);
+
+ assertTrue(new CompareToBuilder().append(obj1, null).toComparison() > 0);
+ assertTrue(new CompareToBuilder().append((long[]) null, (long[]) null).toComparison() == 0);
+ assertTrue(new CompareToBuilder().append(null, obj1).toComparison() < 0);
+ }
+
+ public void testIntArray() {
+ int[] obj1 = new int[2];
+ obj1[0] = 5;
+ obj1[1] = 6;
+ int[] obj2 = new int[2];
+ obj2[0] = 5;
+ obj2[1] = 6;
+ int[] obj3 = new int[3];
+ obj3[0] = 5;
+ obj3[1] = 6;
+ obj3[2] = 7;
+
+ assertTrue(new CompareToBuilder().append(obj1, obj1).toComparison() == 0);
+ assertTrue(new CompareToBuilder().append(obj1, obj2).toComparison() == 0);
+ assertTrue(new CompareToBuilder().append(obj1, obj3).toComparison() < 0);
+ assertTrue(new CompareToBuilder().append(obj3, obj1).toComparison() > 0);
+
+ obj1[1] = 7;
+ assertTrue(new CompareToBuilder().append(obj1, obj2).toComparison() > 0);
+ assertTrue(new CompareToBuilder().append(obj2, obj1).toComparison() < 0);
+
+ assertTrue(new CompareToBuilder().append(obj1, null).toComparison() > 0);
+ assertTrue(new CompareToBuilder().append((int[]) null, (int[]) null).toComparison() == 0);
+ assertTrue(new CompareToBuilder().append(null, obj1).toComparison() < 0);
+ }
+
+ public void testShortArray() {
+ short[] obj1 = new short[2];
+ obj1[0] = 5;
+ obj1[1] = 6;
+ short[] obj2 = new short[2];
+ obj2[0] = 5;
+ obj2[1] = 6;
+ short[] obj3 = new short[3];
+ obj3[0] = 5;
+ obj3[1] = 6;
+ obj3[2] = 7;
+
+ assertTrue(new CompareToBuilder().append(obj1, obj1).toComparison() == 0);
+ assertTrue(new CompareToBuilder().append(obj1, obj2).toComparison() == 0);
+ assertTrue(new CompareToBuilder().append(obj1, obj3).toComparison() < 0);
+ assertTrue(new CompareToBuilder().append(obj3, obj1).toComparison() > 0);
+
+ obj1[1] = 7;
+ assertTrue(new CompareToBuilder().append(obj1, obj2).toComparison() > 0);
+ assertTrue(new CompareToBuilder().append(obj2, obj1).toComparison() < 0);
+
+ assertTrue(new CompareToBuilder().append(obj1, null).toComparison() > 0);
+ assertTrue(new CompareToBuilder().append((short[]) null, (short[]) null).toComparison() == 0);
+ assertTrue(new CompareToBuilder().append(null, obj1).toComparison() < 0);
+ }
+
+ public void testCharArray() {
+ char[] obj1 = new char[2];
+ obj1[0] = 5;
+ obj1[1] = 6;
+ char[] obj2 = new char[2];
+ obj2[0] = 5;
+ obj2[1] = 6;
+ char[] obj3 = new char[3];
+ obj3[0] = 5;
+ obj3[1] = 6;
+ obj3[2] = 7;
+
+ assertTrue(new CompareToBuilder().append(obj1, obj1).toComparison() == 0);
+ assertTrue(new CompareToBuilder().append(obj1, obj2).toComparison() == 0);
+ assertTrue(new CompareToBuilder().append(obj1, obj3).toComparison() < 0);
+ assertTrue(new CompareToBuilder().append(obj3, obj1).toComparison() > 0);
+
+ obj1[1] = 7;
+ assertTrue(new CompareToBuilder().append(obj1, obj2).toComparison() > 0);
+ assertTrue(new CompareToBuilder().append(obj2, obj1).toComparison() < 0);
+
+ assertTrue(new CompareToBuilder().append(obj1, null).toComparison() > 0);
+ assertTrue(new CompareToBuilder().append((char[]) null, (char[]) null).toComparison() == 0);
+ assertTrue(new CompareToBuilder().append(null, obj1).toComparison() < 0);
+ }
+
+ public void testByteArray() {
+ byte[] obj1 = new byte[2];
+ obj1[0] = 5;
+ obj1[1] = 6;
+ byte[] obj2 = new byte[2];
+ obj2[0] = 5;
+ obj2[1] = 6;
+ byte[] obj3 = new byte[3];
+ obj3[0] = 5;
+ obj3[1] = 6;
+ obj3[2] = 7;
+
+ assertTrue(new CompareToBuilder().append(obj1, obj1).toComparison() == 0);
+ assertTrue(new CompareToBuilder().append(obj1, obj2).toComparison() == 0);
+ assertTrue(new CompareToBuilder().append(obj1, obj3).toComparison() < 0);
+ assertTrue(new CompareToBuilder().append(obj3, obj1).toComparison() > 0);
+
+ obj1[1] = 7;
+ assertTrue(new CompareToBuilder().append(obj1, obj2).toComparison() > 0);
+ assertTrue(new CompareToBuilder().append(obj2, obj1).toComparison() < 0);
+
+ assertTrue(new CompareToBuilder().append(obj1, null).toComparison() > 0);
+ assertTrue(new CompareToBuilder().append((byte[]) null, (byte[]) null).toComparison() == 0);
+ assertTrue(new CompareToBuilder().append(null, obj1).toComparison() < 0);
+ }
+
+ public void testDoubleArray() {
+ double[] obj1 = new double[2];
+ obj1[0] = 5;
+ obj1[1] = 6;
+ double[] obj2 = new double[2];
+ obj2[0] = 5;
+ obj2[1] = 6;
+ double[] obj3 = new double[3];
+ obj3[0] = 5;
+ obj3[1] = 6;
+ obj3[2] = 7;
+
+ assertTrue(new CompareToBuilder().append(obj1, obj1).toComparison() == 0);
+ assertTrue(new CompareToBuilder().append(obj1, obj2).toComparison() == 0);
+ assertTrue(new CompareToBuilder().append(obj1, obj3).toComparison() < 0);
+ assertTrue(new CompareToBuilder().append(obj3, obj1).toComparison() > 0);
+
+ obj1[1] = 7;
+ assertTrue(new CompareToBuilder().append(obj1, obj2).toComparison() > 0);
+ assertTrue(new CompareToBuilder().append(obj2, obj1).toComparison() < 0);
+
+ assertTrue(new CompareToBuilder().append(obj1, null).toComparison() > 0);
+ assertTrue(new CompareToBuilder().append((double[]) null, (double[]) null).toComparison() == 0);
+ assertTrue(new CompareToBuilder().append(null, obj1).toComparison() < 0);
+ }
+
+ public void testFloatArray() {
+ float[] obj1 = new float[2];
+ obj1[0] = 5;
+ obj1[1] = 6;
+ float[] obj2 = new float[2];
+ obj2[0] = 5;
+ obj2[1] = 6;
+ float[] obj3 = new float[3];
+ obj3[0] = 5;
+ obj3[1] = 6;
+ obj3[2] = 7;
+
+ assertTrue(new CompareToBuilder().append(obj1, obj1).toComparison() == 0);
+ assertTrue(new CompareToBuilder().append(obj1, obj2).toComparison() == 0);
+ assertTrue(new CompareToBuilder().append(obj1, obj3).toComparison() < 0);
+ assertTrue(new CompareToBuilder().append(obj3, obj1).toComparison() > 0);
+
+ obj1[1] = 7;
+ assertTrue(new CompareToBuilder().append(obj1, obj2).toComparison() > 0);
+ assertTrue(new CompareToBuilder().append(obj2, obj1).toComparison() < 0);
+
+ assertTrue(new CompareToBuilder().append(obj1, null).toComparison() > 0);
+ assertTrue(new CompareToBuilder().append((float[]) null, (float[]) null).toComparison() == 0);
+ assertTrue(new CompareToBuilder().append(null, obj1).toComparison() < 0);
+ }
+
+ public void testBooleanArray() {
+ boolean[] obj1 = new boolean[2];
+ obj1[0] = true;
+ obj1[1] = false;
+ boolean[] obj2 = new boolean[2];
+ obj2[0] = true;
+ obj2[1] = false;
+ boolean[] obj3 = new boolean[3];
+ obj3[0] = true;
+ obj3[1] = false;
+ obj3[2] = true;
+
+ assertTrue(new CompareToBuilder().append(obj1, obj1).toComparison() == 0);
+ assertTrue(new CompareToBuilder().append(obj1, obj2).toComparison() == 0);
+ assertTrue(new CompareToBuilder().append(obj1, obj3).toComparison() < 0);
+ assertTrue(new CompareToBuilder().append(obj3, obj1).toComparison() > 0);
+
+ obj1[1] = true;
+ assertTrue(new CompareToBuilder().append(obj1, obj2).toComparison() > 0);
+ assertTrue(new CompareToBuilder().append(obj2, obj1).toComparison() < 0);
+
+ assertTrue(new CompareToBuilder().append(obj1, null).toComparison() > 0);
+ assertTrue(new CompareToBuilder().append((boolean[]) null, (boolean[]) null).toComparison() == 0);
+ assertTrue(new CompareToBuilder().append(null, obj1).toComparison() < 0);
+ }
+
+ public void testMultiLongArray() {
+ long[][] array1 = new long[2][2];
+ long[][] array2 = new long[2][2];
+ long[][] array3 = new long[2][3];
+ for (int i = 0; i < array1.length; ++i) {
+ for (int j = 0; j < array1[0].length; j++) {
+ array1[i][j] = (i + 1) * (j + 1);
+ array2[i][j] = (i + 1) * (j + 1);
+ array3[i][j] = (i + 1) * (j + 1);
+ }
+ }
+ array3[1][2] = 100;
+ array3[1][2] = 100;
+
+ assertTrue(new CompareToBuilder().append(array1, array1).toComparison() == 0);
+ assertTrue(new CompareToBuilder().append(array1, array2).toComparison() == 0);
+ assertTrue(new CompareToBuilder().append(array1, array3).toComparison() < 0);
+ assertTrue(new CompareToBuilder().append(array3, array1).toComparison() > 0);
+ array1[1][1] = 200;
+ assertTrue(new CompareToBuilder().append(array1, array2).toComparison() > 0);
+ assertTrue(new CompareToBuilder().append(array2, array1).toComparison() < 0);
+ }
+
+ public void testMultiIntArray() {
+ int[][] array1 = new int[2][2];
+ int[][] array2 = new int[2][2];
+ int[][] array3 = new int[2][3];
+ for (int i = 0; i < array1.length; ++i) {
+ for (int j = 0; j < array1[0].length; j++) {
+ array1[i][j] = (i + 1) * (j + 1);
+ array2[i][j] = (i + 1) * (j + 1);
+ array3[i][j] = (i + 1) * (j + 1);
+ }
+ }
+ array3[1][2] = 100;
+ array3[1][2] = 100;
+
+ assertTrue(new CompareToBuilder().append(array1, array1).toComparison() == 0);
+ assertTrue(new CompareToBuilder().append(array1, array2).toComparison() == 0);
+ assertTrue(new CompareToBuilder().append(array1, array3).toComparison() < 0);
+ assertTrue(new CompareToBuilder().append(array3, array1).toComparison() > 0);
+ array1[1][1] = 200;
+ assertTrue(new CompareToBuilder().append(array1, array2).toComparison() > 0);
+ assertTrue(new CompareToBuilder().append(array2, array1).toComparison() < 0);
+ }
+
+ public void testMultiShortArray() {
+ short[][] array1 = new short[2][2];
+ short[][] array2 = new short[2][2];
+ short[][] array3 = new short[2][3];
+ for (short i = 0; i < array1.length; ++i) {
+ for (short j = 0; j < array1[0].length; j++) {
+ array1[i][j] = (short)((i + 1) * (j + 1));
+ array2[i][j] = (short)((i + 1) * (j + 1));
+ array3[i][j] = (short)((i + 1) * (j + 1));
+ }
+ }
+ array3[1][2] = 100;
+ array3[1][2] = 100;
+
+ assertTrue(new CompareToBuilder().append(array1, array1).toComparison() == 0);
+ assertTrue(new CompareToBuilder().append(array1, array2).toComparison() == 0);
+ assertTrue(new CompareToBuilder().append(array1, array3).toComparison() < 0);
+ assertTrue(new CompareToBuilder().append(array3, array1).toComparison() > 0);
+ array1[1][1] = 200;
+ assertTrue(new CompareToBuilder().append(array1, array2).toComparison() > 0);
+ assertTrue(new CompareToBuilder().append(array2, array1).toComparison() < 0);
+ }
+
+ public void testMultiCharArray() {
+ char[][] array1 = new char[2][2];
+ char[][] array2 = new char[2][2];
+ char[][] array3 = new char[2][3];
+ for (short i = 0; i < array1.length; ++i) {
+ for (short j = 0; j < array1[0].length; j++) {
+ array1[i][j] = (char)((i + 1) * (j + 1));
+ array2[i][j] = (char)((i + 1) * (j + 1));
+ array3[i][j] = (char)((i + 1) * (j + 1));
+ }
+ }
+ array3[1][2] = 100;
+ array3[1][2] = 100;
+
+ assertTrue(new CompareToBuilder().append(array1, array1).toComparison() == 0);
+ assertTrue(new CompareToBuilder().append(array1, array2).toComparison() == 0);
+ assertTrue(new CompareToBuilder().append(array1, array3).toComparison() < 0);
+ assertTrue(new CompareToBuilder().append(array3, array1).toComparison() > 0);
+ array1[1][1] = 200;
+ assertTrue(new CompareToBuilder().append(array1, array2).toComparison() > 0);
+ assertTrue(new CompareToBuilder().append(array2, array1).toComparison() < 0);
+ }
+
+ public void testMultiByteArray() {
+ byte[][] array1 = new byte[2][2];
+ byte[][] array2 = new byte[2][2];
+ byte[][] array3 = new byte[2][3];
+ for (byte i = 0; i < array1.length; ++i) {
+ for (byte j = 0; j < array1[0].length; j++) {
+ array1[i][j] = (byte)((i + 1) * (j + 1));
+ array2[i][j] = (byte)((i + 1) * (j + 1));
+ array3[i][j] = (byte)((i + 1) * (j + 1));
+ }
+ }
+ array3[1][2] = 100;
+ array3[1][2] = 100;
+
+ assertTrue(new CompareToBuilder().append(array1, array1).toComparison() == 0);
+ assertTrue(new CompareToBuilder().append(array1, array2).toComparison() == 0);
+ assertTrue(new CompareToBuilder().append(array1, array3).toComparison() < 0);
+ assertTrue(new CompareToBuilder().append(array3, array1).toComparison() > 0);
+ array1[1][1] = 127;
+ assertTrue(new CompareToBuilder().append(array1, array2).toComparison() > 0);
+ assertTrue(new CompareToBuilder().append(array2, array1).toComparison() < 0);
+ }
+
+ public void testMultiFloatArray() {
+ float[][] array1 = new float[2][2];
+ float[][] array2 = new float[2][2];
+ float[][] array3 = new float[2][3];
+ for (int i = 0; i < array1.length; ++i) {
+ for (int j = 0; j < array1[0].length; j++) {
+ array1[i][j] = ((i + 1) * (j + 1));
+ array2[i][j] = ((i + 1) * (j + 1));
+ array3[i][j] = ((i + 1) * (j + 1));
+ }
+ }
+ array3[1][2] = 100;
+ array3[1][2] = 100;
+
+ assertTrue(new CompareToBuilder().append(array1, array1).toComparison() == 0);
+ assertTrue(new CompareToBuilder().append(array1, array2).toComparison() == 0);
+ assertTrue(new CompareToBuilder().append(array1, array3).toComparison() < 0);
+ assertTrue(new CompareToBuilder().append(array3, array1).toComparison() > 0);
+ array1[1][1] = 127;
+ assertTrue(new CompareToBuilder().append(array1, array2).toComparison() > 0);
+ assertTrue(new CompareToBuilder().append(array2, array1).toComparison() < 0);
+ }
+
+ public void testMultiDoubleArray() {
+ double[][] array1 = new double[2][2];
+ double[][] array2 = new double[2][2];
+ double[][] array3 = new double[2][3];
+ for (int i = 0; i < array1.length; ++i) {
+ for (int j = 0; j < array1[0].length; j++) {
+ array1[i][j] = ((i + 1) * (j + 1));
+ array2[i][j] = ((i + 1) * (j + 1));
+ array3[i][j] = ((i + 1) * (j + 1));
+ }
+ }
+ array3[1][2] = 100;
+ array3[1][2] = 100;
+
+ assertTrue(new CompareToBuilder().append(array1, array1).toComparison() == 0);
+ assertTrue(new CompareToBuilder().append(array1, array2).toComparison() == 0);
+ assertTrue(new CompareToBuilder().append(array1, array3).toComparison() < 0);
+ assertTrue(new CompareToBuilder().append(array3, array1).toComparison() > 0);
+ array1[1][1] = 127;
+ assertTrue(new CompareToBuilder().append(array1, array2).toComparison() > 0);
+ assertTrue(new CompareToBuilder().append(array2, array1).toComparison() < 0);
+ }
+
+ public void testMultiBooleanArray() {
+ boolean[][] array1 = new boolean[2][2];
+ boolean[][] array2 = new boolean[2][2];
+ boolean[][] array3 = new boolean[2][3];
+ for (int i = 0; i < array1.length; ++i) {
+ for (int j = 0; j < array1[0].length; j++) {
+ array1[i][j] = ((i == 1) ^ (j == 1));
+ array2[i][j] = ((i == 1) ^ (j == 1));
+ array3[i][j] = ((i == 1) ^ (j == 1));
+ }
+ }
+ array3[1][2] = false;
+ array3[1][2] = false;
+
+ assertTrue(new CompareToBuilder().append(array1, array1).toComparison() == 0);
+ assertTrue(new CompareToBuilder().append(array1, array2).toComparison() == 0);
+ assertTrue(new CompareToBuilder().append(array1, array3).toComparison() < 0);
+ assertTrue(new CompareToBuilder().append(array3, array1).toComparison() > 0);
+ array1[1][1] = true;
+ assertTrue(new CompareToBuilder().append(array1, array2).toComparison() > 0);
+ assertTrue(new CompareToBuilder().append(array2, array1).toComparison() < 0);
+ }
+
+ public void testRaggedArray() {
+ long array1[][] = new long[2][];
+ long array2[][] = new long[2][];
+ long array3[][] = new long[3][];
+ for (int i = 0; i < array1.length; ++i) {
+ array1[i] = new long[2];
+ array2[i] = new long[2];
+ array3[i] = new long[3];
+ for (int j = 0; j < array1[i].length; ++j) {
+ array1[i][j] = (i + 1) * (j + 1);
+ array2[i][j] = (i + 1) * (j + 1);
+ array3[i][j] = (i + 1) * (j + 1);
+ }
+ }
+ array3[1][2] = 100;
+ array3[1][2] = 100;
+
+
+ assertTrue(new CompareToBuilder().append(array1, array1).toComparison() == 0);
+ assertTrue(new CompareToBuilder().append(array1, array2).toComparison() == 0);
+ assertTrue(new CompareToBuilder().append(array1, array3).toComparison() < 0);
+ assertTrue(new CompareToBuilder().append(array3, array1).toComparison() > 0);
+ array1[1][1] = 200;
+ assertTrue(new CompareToBuilder().append(array1, array2).toComparison() > 0);
+ assertTrue(new CompareToBuilder().append(array2, array1).toComparison() < 0);
+ }
+
+ public void testMixedArray() {
+ Object array1[] = new Object[2];
+ Object array2[] = new Object[2];
+ Object array3[] = new Object[2];
+ for (int i = 0; i < array1.length; ++i) {
+ array1[i] = new long[2];
+ array2[i] = new long[2];
+ array3[i] = new long[3];
+ for (int j = 0; j < 2; ++j) {
+ ((long[]) array1[i])[j] = (i + 1) * (j + 1);
+ ((long[]) array2[i])[j] = (i + 1) * (j + 1);
+ ((long[]) array3[i])[j] = (i + 1) * (j + 1);
+ }
+ }
+ ((long[]) array3[0])[2] = 1;
+ ((long[]) array3[1])[2] = 1;
+ assertTrue(new CompareToBuilder().append(array1, array1).toComparison() == 0);
+ assertTrue(new CompareToBuilder().append(array1, array2).toComparison() == 0);
+ assertTrue(new CompareToBuilder().append(array1, array3).toComparison() < 0);
+ assertTrue(new CompareToBuilder().append(array3, array1).toComparison() > 0);
+ ((long[]) array1[1])[1] = 200;
+ assertTrue(new CompareToBuilder().append(array1, array2).toComparison() > 0);
+ assertTrue(new CompareToBuilder().append(array2, array1).toComparison() < 0);
+ }
+
+ public void testObjectArrayHiddenByObject() {
+ TestObject[] array1 = new TestObject[2];
+ array1[0] = new TestObject(4);
+ array1[1] = new TestObject(5);
+ TestObject[] array2 = new TestObject[2];
+ array2[0] = new TestObject(4);
+ array2[1] = new TestObject(5);
+ TestObject[] array3 = new TestObject[3];
+ array3[0] = new TestObject(4);
+ array3[1] = new TestObject(5);
+ array3[2] = new TestObject(6);
+
+ Object obj1 = array1;
+ Object obj2 = array2;
+ Object obj3 = array3;
+
+ assertTrue(new CompareToBuilder().append(obj1, obj1).toComparison() == 0);
+ assertTrue(new CompareToBuilder().append(obj1, obj2).toComparison() == 0);
+ assertTrue(new CompareToBuilder().append(obj1, obj3).toComparison() < 0);
+ assertTrue(new CompareToBuilder().append(obj3, obj1).toComparison() > 0);
+
+ array1[1] = new TestObject(7);
+ assertTrue(new CompareToBuilder().append(obj1, obj2).toComparison() > 0);
+ assertTrue(new CompareToBuilder().append(obj2, obj1).toComparison() < 0);
+ }
+
+ public void testLongArrayHiddenByObject() {
+ long[] array1 = new long[2];
+ array1[0] = 5L;
+ array1[1] = 6L;
+ long[] array2 = new long[2];
+ array2[0] = 5L;
+ array2[1] = 6L;
+ long[] array3 = new long[3];
+ array3[0] = 5L;
+ array3[1] = 6L;
+ array3[2] = 7L;
+ Object obj1 = array1;
+ Object obj2 = array2;
+ Object obj3 = array3;
+ assertTrue(new CompareToBuilder().append(obj1, obj1).toComparison() == 0);
+ assertTrue(new CompareToBuilder().append(obj1, obj2).toComparison() == 0);
+ assertTrue(new CompareToBuilder().append(obj1, obj3).toComparison() < 0);
+ assertTrue(new CompareToBuilder().append(obj3, obj1).toComparison() > 0);
+
+ array1[1] = 7;
+ assertTrue(new CompareToBuilder().append(obj1, obj2).toComparison() > 0);
+ assertTrue(new CompareToBuilder().append(obj2, obj1).toComparison() < 0);
+ }
+
+ public void testIntArrayHiddenByObject() {
+ int[] array1 = new int[2];
+ array1[0] = 5;
+ array1[1] = 6;
+ int[] array2 = new int[2];
+ array2[0] = 5;
+ array2[1] = 6;
+ int[] array3 = new int[3];
+ array3[0] = 5;
+ array3[1] = 6;
+ array3[2] = 7;
+ Object obj1 = array1;
+ Object obj2 = array2;
+ Object obj3 = array3;
+ assertTrue(new CompareToBuilder().append(obj1, obj1).toComparison() == 0);
+ assertTrue(new CompareToBuilder().append(obj1, obj2).toComparison() == 0);
+ assertTrue(new CompareToBuilder().append(obj1, obj3).toComparison() < 0);
+ assertTrue(new CompareToBuilder().append(obj3, obj1).toComparison() > 0);
+
+ array1[1] = 7;
+ assertTrue(new CompareToBuilder().append(obj1, obj2).toComparison() > 0);
+ assertTrue(new CompareToBuilder().append(obj2, obj1).toComparison() < 0);
+ }
+
+ public void testShortArrayHiddenByObject() {
+ short[] array1 = new short[2];
+ array1[0] = 5;
+ array1[1] = 6;
+ short[] array2 = new short[2];
+ array2[0] = 5;
+ array2[1] = 6;
+ short[] array3 = new short[3];
+ array3[0] = 5;
+ array3[1] = 6;
+ array3[2] = 7;
+ Object obj1 = array1;
+ Object obj2 = array2;
+ Object obj3 = array3;
+ assertTrue(new CompareToBuilder().append(obj1, obj1).toComparison() == 0);
+ assertTrue(new CompareToBuilder().append(obj1, obj2).toComparison() == 0);
+ assertTrue(new CompareToBuilder().append(obj1, obj3).toComparison() < 0);
+ assertTrue(new CompareToBuilder().append(obj3, obj1).toComparison() > 0);
+
+ array1[1] = 7;
+ assertTrue(new CompareToBuilder().append(obj1, obj2).toComparison() > 0);
+ assertTrue(new CompareToBuilder().append(obj2, obj1).toComparison() < 0);
+ }
+
+ public void testCharArrayHiddenByObject() {
+ char[] array1 = new char[2];
+ array1[0] = 5;
+ array1[1] = 6;
+ char[] array2 = new char[2];
+ array2[0] = 5;
+ array2[1] = 6;
+ char[] array3 = new char[3];
+ array3[0] = 5;
+ array3[1] = 6;
+ array3[2] = 7;
+ Object obj1 = array1;
+ Object obj2 = array2;
+ Object obj3 = array3;
+ assertTrue(new CompareToBuilder().append(obj1, obj1).toComparison() == 0);
+ assertTrue(new CompareToBuilder().append(obj1, obj2).toComparison() == 0);
+ assertTrue(new CompareToBuilder().append(obj1, obj3).toComparison() < 0);
+ assertTrue(new CompareToBuilder().append(obj3, obj1).toComparison() > 0);
+
+ array1[1] = 7;
+ assertTrue(new CompareToBuilder().append(obj1, obj2).toComparison() > 0);
+ assertTrue(new CompareToBuilder().append(obj2, obj1).toComparison() < 0);
+ }
+
+ public void testByteArrayHiddenByObject() {
+ byte[] array1 = new byte[2];
+ array1[0] = 5;
+ array1[1] = 6;
+ byte[] array2 = new byte[2];
+ array2[0] = 5;
+ array2[1] = 6;
+ byte[] array3 = new byte[3];
+ array3[0] = 5;
+ array3[1] = 6;
+ array3[2] = 7;
+ Object obj1 = array1;
+ Object obj2 = array2;
+ Object obj3 = array3;
+ assertTrue(new CompareToBuilder().append(obj1, obj1).toComparison() == 0);
+ assertTrue(new CompareToBuilder().append(obj1, obj2).toComparison() == 0);
+ assertTrue(new CompareToBuilder().append(obj1, obj3).toComparison() < 0);
+ assertTrue(new CompareToBuilder().append(obj3, obj1).toComparison() > 0);
+
+ array1[1] = 7;
+ assertTrue(new CompareToBuilder().append(obj1, obj2).toComparison() > 0);
+ assertTrue(new CompareToBuilder().append(obj2, obj1).toComparison() < 0);
+ }
+
+ public void testDoubleArrayHiddenByObject() {
+ double[] array1 = new double[2];
+ array1[0] = 5;
+ array1[1] = 6;
+ double[] array2 = new double[2];
+ array2[0] = 5;
+ array2[1] = 6;
+ double[] array3 = new double[3];
+ array3[0] = 5;
+ array3[1] = 6;
+ array3[2] = 7;
+ Object obj1 = array1;
+ Object obj2 = array2;
+ Object obj3 = array3;
+ assertTrue(new CompareToBuilder().append(obj1, obj1).toComparison() == 0);
+ assertTrue(new CompareToBuilder().append(obj1, obj2).toComparison() == 0);
+ assertTrue(new CompareToBuilder().append(obj1, obj3).toComparison() < 0);
+ assertTrue(new CompareToBuilder().append(obj3, obj1).toComparison() > 0);
+
+ array1[1] = 7;
+ assertTrue(new CompareToBuilder().append(obj1, obj2).toComparison() > 0);
+ assertTrue(new CompareToBuilder().append(obj2, obj1).toComparison() < 0);
+ }
+
+ public void testFloatArrayHiddenByObject() {
+ float[] array1 = new float[2];
+ array1[0] = 5;
+ array1[1] = 6;
+ float[] array2 = new float[2];
+ array2[0] = 5;
+ array2[1] = 6;
+ float[] array3 = new float[3];
+ array3[0] = 5;
+ array3[1] = 6;
+ array3[2] = 7;
+ Object obj1 = array1;
+ Object obj2 = array2;
+ Object obj3 = array3;
+ assertTrue(new CompareToBuilder().append(obj1, obj1).toComparison() == 0);
+ assertTrue(new CompareToBuilder().append(obj1, obj2).toComparison() == 0);
+ assertTrue(new CompareToBuilder().append(obj1, obj3).toComparison() < 0);
+ assertTrue(new CompareToBuilder().append(obj3, obj1).toComparison() > 0);
+
+ array1[1] = 7;
+ assertTrue(new CompareToBuilder().append(obj1, obj2).toComparison() > 0);
+ assertTrue(new CompareToBuilder().append(obj2, obj1).toComparison() < 0);
+ }
+
+ public void testBooleanArrayHiddenByObject() {
+ boolean[] array1 = new boolean[2];
+ array1[0] = true;
+ array1[1] = false;
+ boolean[] array2 = new boolean[2];
+ array2[0] = true;
+ array2[1] = false;
+ boolean[] array3 = new boolean[3];
+ array3[0] = true;
+ array3[1] = false;
+ array3[2] = true;
+ Object obj1 = array1;
+ Object obj2 = array2;
+ Object obj3 = array3;
+ assertTrue(new CompareToBuilder().append(obj1, obj1).toComparison() == 0);
+ assertTrue(new CompareToBuilder().append(obj1, obj2).toComparison() == 0);
+ assertTrue(new CompareToBuilder().append(obj1, obj3).toComparison() < 0);
+ assertTrue(new CompareToBuilder().append(obj3, obj1).toComparison() > 0);
+
+ array1[1] = true;
+ assertTrue(new CompareToBuilder().append(obj1, obj2).toComparison() > 0);
+ assertTrue(new CompareToBuilder().append(obj2, obj1).toComparison() < 0);
+ }
+
+ }
diff --git a/examples/cl2/src/test/org/apache/commons/lang/builder/DefaultToStringStyleTest.java b/examples/cl2/src/test/org/apache/commons/lang/builder/DefaultToStringStyleTest.java
new file mode 100644
index 00000000..e2ec788c
--- /dev/null
+++ b/examples/cl2/src/test/org/apache/commons/lang/builder/DefaultToStringStyleTest.java
@@ -0,0 +1,164 @@
+/* ====================================================================
+ * 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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
+ * .
+ */
+// package org.apache.commons.lang.builder
+
+package org.apache.commons.lang.builder;
+import java.util.ArrayList;
+import java.util.HashMap;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import junit.textui.TestRunner;
+/**
+ * Unit tests {@link org.apache.commons.lang.ToStringStyle}.
+ *
+ * @author Stephen Colebourne
+ * @version $Id: DefaultToStringStyleTest.java,v 1.3 2003/05/21 23:49:14 scolebourne Exp $
+ */
+public class DefaultToStringStyleTest extends TestCase {
+
+ private final Integer base = new Integer(5);
+ private final String baseStr = base.getClass().getName() + "@" + Integer.toHexString(System.identityHashCode(base));
+
+ public DefaultToStringStyleTest(String name) {
+ super(name);
+ }
+
+ public static void main(String[] args) {
+ TestRunner.run(suite());
+ }
+
+ public static Test suite() {
+ TestSuite suite = new TestSuite(DefaultToStringStyleTest.class);
+ suite.setName("DefaultToStringStyle Tests");
+ return suite;
+ }
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ ToStringBuilder.setDefaultStyle(ToStringStyle.DEFAULT_STYLE);
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ ToStringBuilder.setDefaultStyle(ToStringStyle.DEFAULT_STYLE);
+ }
+
+ //----------------------------------------------------------------
+
+ public void testBlank() {
+ assertEquals(baseStr + "[]", new ToStringBuilder(base).toString());
+ }
+
+ public void testAppendSuper() {
+ assertEquals(baseStr + "[]", new ToStringBuilder(base).appendSuper("Integer@8888[]").toString());
+ assertEquals(baseStr + "[]", new ToStringBuilder(base).appendSuper("Integer@8888[]").toString());
+
+ assertEquals(baseStr + "[a=hello]", new ToStringBuilder(base).appendSuper("Integer@8888[]").append("a", "hello").toString());
+ assertEquals(baseStr + "[,a=hello]", new ToStringBuilder(base).appendSuper("Integer@8888[]").append("a", "hello").toString());
+ assertEquals(baseStr + "[a=hello]", new ToStringBuilder(base).appendSuper(null).append("a", "hello").toString());
+ }
+
+ public void testObject() {
+ Integer i3 = new Integer(3);
+ Integer i4 = new Integer(4);
+ assertEquals(baseStr + "[]", new ToStringBuilder(base).append((Object) null).toString());
+ assertEquals(baseStr + "[3]", new ToStringBuilder(base).append(i3).toString());
+ assertEquals(baseStr + "[a=]", new ToStringBuilder(base).append("a", (Object) null).toString());
+ assertEquals(baseStr + "[a=3]", new ToStringBuilder(base).append("a", i3).toString());
+ assertEquals(baseStr + "[a=3,b=4]", new ToStringBuilder(base).append("a", i3).append("b", i4).toString());
+ assertEquals(baseStr + "[a=]", new ToStringBuilder(base).append("a", i3, false).toString());
+ assertEquals(baseStr + "[a=]", new ToStringBuilder(base).append("a", new ArrayList(), false).toString());
+ assertEquals(baseStr + "[a=[]]", new ToStringBuilder(base).append("a", new ArrayList(), true).toString());
+ assertEquals(baseStr + "[a=]", new ToStringBuilder(base).append("a", new HashMap(), false).toString());
+ assertEquals(baseStr + "[a={}]", new ToStringBuilder(base).append("a", new HashMap(), true).toString());
+ assertEquals(baseStr + "[a=]", new ToStringBuilder(base).append("a", (Object) new String[0], false).toString());
+ assertEquals(baseStr + "[a={}]", new ToStringBuilder(base).append("a", (Object) new String[0], true).toString());
+ }
+
+ public void testLong() {
+ assertEquals(baseStr + "[3]", new ToStringBuilder(base).append(3L).toString());
+ assertEquals(baseStr + "[a=3]", new ToStringBuilder(base).append("a", 3L).toString());
+ assertEquals(baseStr + "[a=3,b=4]", new ToStringBuilder(base).append("a", 3L).append("b", 4L).toString());
+ }
+
+ public void testObjectArray() {
+ Object[] array = new Object[] {null, base, new int[] {3, 6}};
+ assertEquals(baseStr + "[{,5,{3,6}}]", new ToStringBuilder(base).append(array).toString());
+ assertEquals(baseStr + "[{,5,{3,6}}]", new ToStringBuilder(base).append((Object) array).toString());
+ array = null;
+ assertEquals(baseStr + "[]", new ToStringBuilder(base).append(array).toString());
+ assertEquals(baseStr + "[]", new ToStringBuilder(base).append((Object) array).toString());
+ }
+
+ public void testLongArray() {
+ long[] array = new long[] {1, 2, -3, 4};
+ assertEquals(baseStr + "[{1,2,-3,4}]", new ToStringBuilder(base).append(array).toString());
+ assertEquals(baseStr + "[{1,2,-3,4}]", new ToStringBuilder(base).append((Object) array).toString());
+ array = null;
+ assertEquals(baseStr + "[]", new ToStringBuilder(base).append(array).toString());
+ assertEquals(baseStr + "[]", new ToStringBuilder(base).append((Object) array).toString());
+ }
+
+ public void testLongArrayArray() {
+ long[][] array = new long[][] {{1, 2}, null, {5}};
+ assertEquals(baseStr + "[{{1,2},,{5}}]", new ToStringBuilder(base).append(array).toString());
+ assertEquals(baseStr + "[{{1,2},,{5}}]", new ToStringBuilder(base).append((Object) array).toString());
+ array = null;
+ assertEquals(baseStr + "[]", new ToStringBuilder(base).append(array).toString());
+ assertEquals(baseStr + "[]", new ToStringBuilder(base).append((Object) array).toString());
+ }
+
+}
diff --git a/examples/cl2/src/test/org/apache/commons/lang/builder/EqualsBuilderTest.java b/examples/cl2/src/test/org/apache/commons/lang/builder/EqualsBuilderTest.java
new file mode 100644
index 00000000..f09b5d65
--- /dev/null
+++ b/examples/cl2/src/test/org/apache/commons/lang/builder/EqualsBuilderTest.java
@@ -0,0 +1,887 @@
+/* ====================================================================
+ * 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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
+ * .
+ */
+package org.apache.commons.lang.builder;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import junit.textui.TestRunner;
+/**
+ * Unit tests {@link org.apache.commons.lang.EqualsBuilder}.
+ *
+ * @author Steve Downey
+ * @author Stephen Colebourne
+ * @author Gary Gregory
+ * @version $Id: EqualsBuilderTest.java,v 1.5 2003/05/21 23:49:14 scolebourne Exp $
+ */
+public class EqualsBuilderTest extends TestCase {
+
+ public EqualsBuilderTest(String name) {
+ super(name);
+ }
+
+ public static void main(String[] args) {
+ TestRunner.run(suite());
+ }
+
+ public static Test suite() {
+ TestSuite suite = new TestSuite(EqualsBuilderTest.class);
+ suite.setName("HashCodeBuilder Tests");
+ return suite;
+ }
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ //-----------------------------------------------------------------------
+
+ static class TestObject {
+ private int a;
+ public TestObject() {
+ }
+ public TestObject(int a) {
+ this.a = a;
+ }
+ public boolean equals(Object o) {
+ if (o == this) {
+ return true;
+ }
+ if (!(o instanceof TestObject)) {
+ return false;
+ }
+ TestObject rhs = (TestObject) o;
+ return (a == rhs.a);
+ }
+
+ public void setA(int a) {
+ this.a = a;
+ }
+
+ public int getA() {
+ return a;
+ }
+ }
+
+ static class TestSubObject extends TestObject {
+ private int b;
+ public TestSubObject() {
+ super(0);
+ }
+ public TestSubObject(int a, int b) {
+ super(a);
+ this.b = b;
+ }
+ public boolean equals(Object o) {
+ if (o == this) {
+ return true;
+ }
+ if (!(o instanceof TestSubObject)) {
+ return false;
+ }
+ TestSubObject rhs = (TestSubObject) o;
+ return super.equals(o) && (b == rhs.b);
+ }
+
+ public void setB(int b) {
+ this.b = b;
+ }
+
+ public int getB() {
+ return b;
+ }
+ }
+
+ static class TestEmptySubObject extends TestObject {
+ public TestEmptySubObject(int a) {
+ super(a);
+ }
+ }
+
+ static class TestTSubObject extends TestObject {
+ private transient int t;
+ public TestTSubObject(int a, int t) {
+ super(a);
+ this.t = t;
+ }
+ }
+
+ static class TestTTSubObject extends TestTSubObject {
+ private transient int tt;
+ public TestTTSubObject(int a, int t, int tt) {
+ super(a, t);
+ this.tt = tt;
+ }
+ }
+
+ static class TestTTLeafObject extends TestTTSubObject {
+ private int leafValue;
+ public TestTTLeafObject(int a, int t, int tt, int leafValue) {
+ super(a, t, tt);
+ this.leafValue = leafValue;
+ }
+ }
+
+ static class TestTSubObject2 extends TestObject {
+ private transient int t;
+ public TestTSubObject2(int a, int t) {
+ super(a);
+ }
+ public int getT() {
+ return t;
+ }
+ public void setT(int t) {
+ this.t = t;
+ }
+ }
+
+ public void testReflectionEquals() {
+ TestObject o1 = new TestObject(4);
+ TestObject o2 = new TestObject(5);
+ assertTrue(EqualsBuilder.reflectionEquals(o1, o1));
+ assertTrue(!EqualsBuilder.reflectionEquals(o1, o2));
+ o2.setA(4);
+ assertTrue(EqualsBuilder.reflectionEquals(o1, o2));
+
+ assertTrue(!EqualsBuilder.reflectionEquals(o1, this));
+
+ assertTrue(!EqualsBuilder.reflectionEquals(o1, null));
+ assertTrue(!EqualsBuilder.reflectionEquals(null, o2));
+ assertTrue(EqualsBuilder.reflectionEquals((Object) null, (Object) null));
+ }
+
+ public void testReflectionHierarchyEquals() {
+ testReflectionHierarchyEquals(false);
+ testReflectionHierarchyEquals(true);
+ // Transients
+ assertTrue(EqualsBuilder.reflectionEquals(new TestTTLeafObject(1, 2, 3, 4), new TestTTLeafObject(1, 2, 3, 4), true));
+ assertTrue(EqualsBuilder.reflectionEquals(new TestTTLeafObject(1, 2, 3, 4), new TestTTLeafObject(1, 2, 3, 4), false));
+ assertTrue(!EqualsBuilder.reflectionEquals(new TestTTLeafObject(1, 0, 0, 4), new TestTTLeafObject(1, 2, 3, 4), true));
+ assertTrue(!EqualsBuilder.reflectionEquals(new TestTTLeafObject(1, 2, 3, 4), new TestTTLeafObject(1, 2, 3, 0), true));
+ assertTrue(!EqualsBuilder.reflectionEquals(new TestTTLeafObject(0, 2, 3, 4), new TestTTLeafObject(1, 2, 3, 4), true));
+ }
+
+ public void testReflectionHierarchyEquals(boolean testTransients) {
+ TestObject to1 = new TestObject(4);
+ TestObject to1Bis = new TestObject(4);
+ TestObject to1Ter = new TestObject(4);
+ TestObject to2 = new TestObject(5);
+ TestEmptySubObject teso = new TestEmptySubObject(4);
+ TestTSubObject ttso = new TestTSubObject(4, 1);
+ TestTTSubObject tttso = new TestTTSubObject(4, 1, 2);
+ TestTTLeafObject ttlo = new TestTTLeafObject(4, 1, 2, 3);
+ TestSubObject tso1 = new TestSubObject(1, 4);
+ TestSubObject tso1bis = new TestSubObject(1, 4);
+ TestSubObject tso1ter = new TestSubObject(1, 4);
+ TestSubObject tso2 = new TestSubObject(2, 5);
+
+ testReflectionEqualsEquivalenceRelationship(to1, to1Bis, to1Ter, to2, new TestObject(), testTransients);
+ testReflectionEqualsEquivalenceRelationship(tso1, tso1bis, tso1ter, tso2, new TestSubObject(), testTransients);
+
+ // More sanity checks:
+
+ // same values
+ assertTrue(EqualsBuilder.reflectionEquals(ttlo, ttlo, testTransients));
+ assertTrue(EqualsBuilder.reflectionEquals(new TestSubObject(1, 10), new TestSubObject(1, 10), testTransients));
+ // same super values, diff sub values
+ assertTrue(!EqualsBuilder.reflectionEquals(new TestSubObject(1, 10), new TestSubObject(1, 11), testTransients));
+ assertTrue(!EqualsBuilder.reflectionEquals(new TestSubObject(1, 11), new TestSubObject(1, 10), testTransients));
+ // diff super values, same sub values
+ assertTrue(!EqualsBuilder.reflectionEquals(new TestSubObject(0, 10), new TestSubObject(1, 10), testTransients));
+ assertTrue(!EqualsBuilder.reflectionEquals(new TestSubObject(1, 10), new TestSubObject(0, 10), testTransients));
+
+ // mix super and sub types: equals
+ assertTrue(EqualsBuilder.reflectionEquals(to1, teso, testTransients));
+ assertTrue(EqualsBuilder.reflectionEquals(teso, to1, testTransients));
+
+ assertTrue(EqualsBuilder.reflectionEquals(to1, ttso, false)); // Force testTransients = false for this assert
+ assertTrue(EqualsBuilder.reflectionEquals(ttso, to1, false)); // Force testTransients = false for this assert
+
+ assertTrue(EqualsBuilder.reflectionEquals(to1, tttso, false)); // Force testTransients = false for this assert
+ assertTrue(EqualsBuilder.reflectionEquals(tttso, to1, false)); // Force testTransients = false for this assert
+
+ assertTrue(EqualsBuilder.reflectionEquals(ttso, tttso, false)); // Force testTransients = false for this assert
+ assertTrue(EqualsBuilder.reflectionEquals(tttso, ttso, false)); // Force testTransients = false for this assert
+
+ // mix super and sub types: NOT equals
+ assertTrue(!EqualsBuilder.reflectionEquals(new TestObject(0), new TestEmptySubObject(1), testTransients));
+ assertTrue(!EqualsBuilder.reflectionEquals(new TestEmptySubObject(1), new TestObject(0), testTransients));
+
+ assertTrue(!EqualsBuilder.reflectionEquals(new TestObject(0), new TestTSubObject(1, 1), testTransients));
+ assertTrue(!EqualsBuilder.reflectionEquals(new TestTSubObject(1, 1), new TestObject(0), testTransients));
+
+ assertTrue(!EqualsBuilder.reflectionEquals(new TestObject(1), new TestSubObject(0, 10), testTransients));
+ assertTrue(!EqualsBuilder.reflectionEquals(new TestSubObject(0, 10), new TestObject(1), testTransients));
+
+ assertTrue(!EqualsBuilder.reflectionEquals(to1, ttlo));
+ assertTrue(!EqualsBuilder.reflectionEquals(tso1, this));
+ }
+
+ /**
+ * Equivalence relationship tests inspired by "Effective Java":
+ *
+ * - reflection
+ * - symetry
+ * - transitive
+ * - consistency
+ * - non-null reference
+ *
+ * @param to a TestObject
+ * @param toBis a TestObject, equal to to and toTer
+ * @param toTer Left hand side, equal to to and toBis
+ * @param to2 a different TestObject
+ * @param oToChange a TestObject that will be changed
+ */
+ public void testReflectionEqualsEquivalenceRelationship(
+ TestObject to,
+ TestObject toBis,
+ TestObject toTer,
+ TestObject to2,
+ TestObject oToChange,
+ boolean testTransients) {
+
+ // reflection test
+ assertTrue(EqualsBuilder.reflectionEquals(to, to, testTransients));
+ assertTrue(EqualsBuilder.reflectionEquals(to2, to2, testTransients));
+
+ // symetry test
+ assertTrue(EqualsBuilder.reflectionEquals(to, toBis, testTransients) && EqualsBuilder.reflectionEquals(toBis, to, testTransients));
+
+ // transitive test
+ assertTrue(
+ EqualsBuilder.reflectionEquals(to, toBis, testTransients)
+ && EqualsBuilder.reflectionEquals(toBis, toTer, testTransients)
+ && EqualsBuilder.reflectionEquals(to, toTer, testTransients));
+
+ // consistency test
+ oToChange.setA(to.getA());
+ if (oToChange instanceof TestSubObject) {
+ ((TestSubObject) oToChange).setB(((TestSubObject) to).getB());
+ }
+ assertTrue(EqualsBuilder.reflectionEquals(oToChange, to, testTransients));
+ assertTrue(EqualsBuilder.reflectionEquals(oToChange, to, testTransients));
+ oToChange.setA(to.getA() + 1);
+ if (oToChange instanceof TestSubObject) {
+ ((TestSubObject) oToChange).setB(((TestSubObject) to).getB() + 1);
+ }
+ assertTrue(!EqualsBuilder.reflectionEquals(oToChange, to, testTransients));
+ assertTrue(!EqualsBuilder.reflectionEquals(oToChange, to, testTransients));
+
+ // non-null reference test
+ assertTrue(!EqualsBuilder.reflectionEquals(to, null, testTransients));
+ assertTrue(!EqualsBuilder.reflectionEquals(to2, null, testTransients));
+ assertTrue(!EqualsBuilder.reflectionEquals(null, to, testTransients));
+ assertTrue(!EqualsBuilder.reflectionEquals(null, to2, testTransients));
+ assertTrue(EqualsBuilder.reflectionEquals((Object) null, (Object) null, testTransients));
+ }
+
+ public void testSuper() {
+ TestObject o1 = new TestObject(4);
+ TestObject o2 = new TestObject(5);
+ assertEquals(true, new EqualsBuilder().appendSuper(true).append(o1, o1).isEquals());
+ assertEquals(false, new EqualsBuilder().appendSuper(false).append(o1, o1).isEquals());
+ assertEquals(false, new EqualsBuilder().appendSuper(true).append(o1, o2).isEquals());
+ assertEquals(false, new EqualsBuilder().appendSuper(false).append(o1, o2).isEquals());
+ }
+
+ public void testObject() {
+ TestObject o1 = new TestObject(4);
+ TestObject o2 = new TestObject(5);
+ assertTrue(new EqualsBuilder().append(o1, o1).isEquals());
+ assertTrue(!new EqualsBuilder().append(o1, o2).isEquals());
+ o2.setA(4);
+ assertTrue(new EqualsBuilder().append(o1, o2).isEquals());
+
+ assertTrue(!new EqualsBuilder().append(o1, this).isEquals());
+
+ assertTrue(!new EqualsBuilder().append(o1, null).isEquals());
+ assertTrue(!new EqualsBuilder().append(null, o2).isEquals());
+ assertTrue(new EqualsBuilder().append((Object) null, (Object) null).isEquals());
+ }
+
+ public void testLong() {
+ long o1 = 1L;
+ long o2 = 2L;
+ assertTrue(new EqualsBuilder().append(o1, o1).isEquals());
+ assertTrue(!new EqualsBuilder().append(o1, o2).isEquals());
+ }
+
+ public void testInt() {
+ int o1 = 1;
+ int o2 = 2;
+ assertTrue(new EqualsBuilder().append(o1, o1).isEquals());
+ assertTrue(!new EqualsBuilder().append(o1, o2).isEquals());
+ }
+
+ public void testShort() {
+ short o1 = 1;
+ short o2 = 2;
+ assertTrue(new EqualsBuilder().append(o1, o1).isEquals());
+ assertTrue(!new EqualsBuilder().append(o1, o2).isEquals());
+ }
+
+ public void testChar() {
+ char o1 = 1;
+ char o2 = 2;
+ assertTrue(new EqualsBuilder().append(o1, o1).isEquals());
+ assertTrue(!new EqualsBuilder().append(o1, o2).isEquals());
+ }
+
+ public void testByte() {
+ byte o1 = 1;
+ byte o2 = 2;
+ assertTrue(new EqualsBuilder().append(o1, o1).isEquals());
+ assertTrue(!new EqualsBuilder().append(o1, o2).isEquals());
+ }
+
+ public void testDouble() {
+ double o1 = 1;
+ double o2 = 2;
+ assertTrue(new EqualsBuilder().append(o1, o1).isEquals());
+ assertTrue(!new EqualsBuilder().append(o1, o2).isEquals());
+ assertTrue(!new EqualsBuilder().append(o1, Double.NaN).isEquals());
+ assertTrue(new EqualsBuilder().append(Double.NaN, Double.NaN).isEquals());
+ assertTrue(new EqualsBuilder().append(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY).isEquals());
+ }
+
+ public void testFloat() {
+ float o1 = 1;
+ float o2 = 2;
+ assertTrue(new EqualsBuilder().append(o1, o1).isEquals());
+ assertTrue(!new EqualsBuilder().append(o1, o2).isEquals());
+ assertTrue(!new EqualsBuilder().append(o1, Float.NaN).isEquals());
+ assertTrue(new EqualsBuilder().append(Float.NaN, Float.NaN).isEquals());
+ assertTrue(new EqualsBuilder().append(Float.POSITIVE_INFINITY, Float.POSITIVE_INFINITY).isEquals());
+ }
+
+ public void testBoolean() {
+ boolean o1 = true;
+ boolean o2 = false;
+ assertTrue(new EqualsBuilder().append(o1, o1).isEquals());
+ assertTrue(!new EqualsBuilder().append(o1, o2).isEquals());
+ }
+
+ public void testObjectArray() {
+ TestObject[] obj1 = new TestObject[2];
+ obj1[0] = new TestObject(4);
+ obj1[1] = new TestObject(5);
+ TestObject[] obj2 = new TestObject[2];
+ obj2[0] = new TestObject(4);
+ obj2[1] = new TestObject(5);
+ assertTrue(new EqualsBuilder().append(obj1, obj1).isEquals());
+ assertTrue(new EqualsBuilder().append(obj1, obj2).isEquals());
+ obj1[1].setA(6);
+ assertTrue(!new EqualsBuilder().append(obj1, obj2).isEquals());
+
+ obj2 = null;
+ assertTrue(!new EqualsBuilder().append(obj1, obj2).isEquals());
+ obj1 = null;
+ assertTrue(new EqualsBuilder().append(obj1, obj2).isEquals());
+ }
+
+ public void testLongArray() {
+ long[] obj1 = new long[2];
+ obj1[0] = 5L;
+ obj1[1] = 6L;
+ long[] obj2 = new long[2];
+ obj2[0] = 5L;
+ obj2[1] = 6L;
+ assertTrue(new EqualsBuilder().append(obj1, obj1).isEquals());
+ assertTrue(new EqualsBuilder().append(obj1, obj2).isEquals());
+ obj1[1] = 7;
+ assertTrue(!new EqualsBuilder().append(obj1, obj2).isEquals());
+
+ obj2 = null;
+ assertTrue(!new EqualsBuilder().append(obj1, obj2).isEquals());
+ obj1 = null;
+ assertTrue(new EqualsBuilder().append(obj1, obj2).isEquals());
+ }
+
+ public void testIntArray() {
+ int[] obj1 = new int[2];
+ obj1[0] = 5;
+ obj1[1] = 6;
+ int[] obj2 = new int[2];
+ obj2[0] = 5;
+ obj2[1] = 6;
+ assertTrue(new EqualsBuilder().append(obj1, obj1).isEquals());
+ assertTrue(new EqualsBuilder().append(obj1, obj2).isEquals());
+ obj1[1] = 7;
+ assertTrue(!new EqualsBuilder().append(obj1, obj2).isEquals());
+
+ obj2 = null;
+ assertTrue(!new EqualsBuilder().append(obj1, obj2).isEquals());
+ obj1 = null;
+ assertTrue(new EqualsBuilder().append(obj1, obj2).isEquals());
+ }
+
+ public void testShortArray() {
+ short[] obj1 = new short[2];
+ obj1[0] = 5;
+ obj1[1] = 6;
+ short[] obj2 = new short[2];
+ obj2[0] = 5;
+ obj2[1] = 6;
+ assertTrue(new EqualsBuilder().append(obj1, obj1).isEquals());
+ assertTrue(new EqualsBuilder().append(obj1, obj2).isEquals());
+ obj1[1] = 7;
+ assertTrue(!new EqualsBuilder().append(obj1, obj2).isEquals());
+
+ obj2 = null;
+ assertTrue(!new EqualsBuilder().append(obj1, obj2).isEquals());
+ obj1 = null;
+ assertTrue(new EqualsBuilder().append(obj1, obj2).isEquals());
+ }
+
+ public void testCharArray() {
+ char[] obj1 = new char[2];
+ obj1[0] = 5;
+ obj1[1] = 6;
+ char[] obj2 = new char[2];
+ obj2[0] = 5;
+ obj2[1] = 6;
+ assertTrue(new EqualsBuilder().append(obj1, obj1).isEquals());
+ assertTrue(new EqualsBuilder().append(obj1, obj2).isEquals());
+ obj1[1] = 7;
+ assertTrue(!new EqualsBuilder().append(obj1, obj2).isEquals());
+
+ obj2 = null;
+ assertTrue(!new EqualsBuilder().append(obj1, obj2).isEquals());
+ obj1 = null;
+ assertTrue(new EqualsBuilder().append(obj1, obj2).isEquals());
+ }
+
+ public void testByteArray() {
+ byte[] obj1 = new byte[2];
+ obj1[0] = 5;
+ obj1[1] = 6;
+ byte[] obj2 = new byte[2];
+ obj2[0] = 5;
+ obj2[1] = 6;
+ assertTrue(new EqualsBuilder().append(obj1, obj1).isEquals());
+ assertTrue(new EqualsBuilder().append(obj1, obj2).isEquals());
+ obj1[1] = 7;
+ assertTrue(!new EqualsBuilder().append(obj1, obj2).isEquals());
+
+ obj2 = null;
+ assertTrue(!new EqualsBuilder().append(obj1, obj2).isEquals());
+ obj1 = null;
+ assertTrue(new EqualsBuilder().append(obj1, obj2).isEquals());
+ }
+
+ public void testDoubleArray() {
+ double[] obj1 = new double[2];
+ obj1[0] = 5;
+ obj1[1] = 6;
+ double[] obj2 = new double[2];
+ obj2[0] = 5;
+ obj2[1] = 6;
+ assertTrue(new EqualsBuilder().append(obj1, obj1).isEquals());
+ assertTrue(new EqualsBuilder().append(obj1, obj2).isEquals());
+ obj1[1] = 7;
+ assertTrue(!new EqualsBuilder().append(obj1, obj2).isEquals());
+
+ obj2 = null;
+ assertTrue(!new EqualsBuilder().append(obj1, obj2).isEquals());
+ obj1 = null;
+ assertTrue(new EqualsBuilder().append(obj1, obj2).isEquals());
+ }
+
+ public void testFloatArray() {
+ float[] obj1 = new float[2];
+ obj1[0] = 5;
+ obj1[1] = 6;
+ float[] obj2 = new float[2];
+ obj2[0] = 5;
+ obj2[1] = 6;
+ assertTrue(new EqualsBuilder().append(obj1, obj1).isEquals());
+ assertTrue(new EqualsBuilder().append(obj1, obj2).isEquals());
+ obj1[1] = 7;
+ assertTrue(!new EqualsBuilder().append(obj1, obj2).isEquals());
+
+ obj2 = null;
+ assertTrue(!new EqualsBuilder().append(obj1, obj2).isEquals());
+ obj1 = null;
+ assertTrue(new EqualsBuilder().append(obj1, obj2).isEquals());
+ }
+
+ public void testBooleanArray() {
+ boolean[] obj1 = new boolean[2];
+ obj1[0] = true;
+ obj1[1] = false;
+ boolean[] obj2 = new boolean[2];
+ obj2[0] = true;
+ obj2[1] = false;
+ assertTrue(new EqualsBuilder().append(obj1, obj1).isEquals());
+ assertTrue(new EqualsBuilder().append(obj1, obj2).isEquals());
+ obj1[1] = true;
+ assertTrue(!new EqualsBuilder().append(obj1, obj2).isEquals());
+
+ obj2 = null;
+ assertTrue(!new EqualsBuilder().append(obj1, obj2).isEquals());
+ obj1 = null;
+ assertTrue(new EqualsBuilder().append(obj1, obj2).isEquals());
+ }
+
+ public void testMultiLongArray() {
+ long[][] array1 = new long[2][2];
+ long[][] array2 = new long[2][2];
+ for (int i = 0; i < array1.length; ++i) {
+ for (int j = 0; j < array1[0].length; j++) {
+ array1[i][j] = (i + 1) * (j + 1);
+ array2[i][j] = (i + 1) * (j + 1);
+ }
+ }
+ assertTrue(new EqualsBuilder().append(array1, array1).isEquals());
+ assertTrue(new EqualsBuilder().append(array1, array2).isEquals());
+ array1[1][1] = 0;
+ assertTrue(!new EqualsBuilder().append(array1, array2).isEquals());
+ }
+
+ public void testMultiIntArray() {
+ int[][] array1 = new int[2][2];
+ int[][] array2 = new int[2][2];
+ for (int i = 0; i < array1.length; ++i) {
+ for (int j = 0; j < array1[0].length; j++) {
+ array1[i][j] = (i + 1) * (j + 1);
+ array2[i][j] = (i + 1) * (j + 1);
+ }
+ }
+ assertTrue(new EqualsBuilder().append(array1, array1).isEquals());
+ assertTrue(new EqualsBuilder().append(array1, array2).isEquals());
+ array1[1][1] = 0;
+ assertTrue(!new EqualsBuilder().append(array1, array2).isEquals());
+ }
+
+ public void testMultiShortArray() {
+ short[][] array1 = new short[2][2];
+ short[][] array2 = new short[2][2];
+ for (short i = 0; i < array1.length; ++i) {
+ for (short j = 0; j < array1[0].length; j++) {
+ array1[i][j] = i;
+ array2[i][j] = i;
+ }
+ }
+ assertTrue(new EqualsBuilder().append(array1, array1).isEquals());
+ assertTrue(new EqualsBuilder().append(array1, array2).isEquals());
+ array1[1][1] = 0;
+ assertTrue(!new EqualsBuilder().append(array1, array2).isEquals());
+ }
+
+ public void testMultiCharArray() {
+ char[][] array1 = new char[2][2];
+ char[][] array2 = new char[2][2];
+ for (char i = 0; i < array1.length; ++i) {
+ for (char j = 0; j < array1[0].length; j++) {
+ array1[i][j] = i;
+ array2[i][j] = i;
+ }
+ }
+ assertTrue(new EqualsBuilder().append(array1, array1).isEquals());
+ assertTrue(new EqualsBuilder().append(array1, array2).isEquals());
+ array1[1][1] = 0;
+ assertTrue(!new EqualsBuilder().append(array1, array2).isEquals());
+ }
+
+ public void testMultiByteArray() {
+ byte[][] array1 = new byte[2][2];
+ byte[][] array2 = new byte[2][2];
+ for (byte i = 0; i < array1.length; ++i) {
+ for (byte j = 0; j < array1[0].length; j++) {
+ array1[i][j] = i;
+ array2[i][j] = i;
+ }
+ }
+ assertTrue(new EqualsBuilder().append(array1, array1).isEquals());
+ assertTrue(new EqualsBuilder().append(array1, array2).isEquals());
+ array1[1][1] = 0;
+ assertTrue(!new EqualsBuilder().append(array1, array2).isEquals());
+ }
+ public void testMultiFloatArray() {
+ float[][] array1 = new float[2][2];
+ float[][] array2 = new float[2][2];
+ for (int i = 0; i < array1.length; ++i) {
+ for (int j = 0; j < array1[0].length; j++) {
+ array1[i][j] = (i + 1) * (j + 1);
+ array2[i][j] = (i + 1) * (j + 1);
+ }
+ }
+ assertTrue(new EqualsBuilder().append(array1, array1).isEquals());
+ assertTrue(new EqualsBuilder().append(array1, array2).isEquals());
+ array1[1][1] = 0;
+ assertTrue(!new EqualsBuilder().append(array1, array2).isEquals());
+ }
+
+ public void testMultiDoubleArray() {
+ double[][] array1 = new double[2][2];
+ double[][] array2 = new double[2][2];
+ for (int i = 0; i < array1.length; ++i) {
+ for (int j = 0; j < array1[0].length; j++) {
+ array1[i][j] = (i + 1) * (j + 1);
+ array2[i][j] = (i + 1) * (j + 1);
+ }
+ }
+ assertTrue(new EqualsBuilder().append(array1, array1).isEquals());
+ assertTrue(new EqualsBuilder().append(array1, array2).isEquals());
+ array1[1][1] = 0;
+ assertTrue(!new EqualsBuilder().append(array1, array2).isEquals());
+ }
+
+ public void testMultiBooleanArray() {
+ boolean[][] array1 = new boolean[2][2];
+ boolean[][] array2 = new boolean[2][2];
+ for (int i = 0; i < array1.length; ++i) {
+ for (int j = 0; j < array1[0].length; j++) {
+ array1[i][j] = (i == 1) || (j == 1);
+ array2[i][j] = (i == 1) || (j == 1);
+ }
+ }
+ assertTrue(new EqualsBuilder().append(array1, array1).isEquals());
+ assertTrue(new EqualsBuilder().append(array1, array2).isEquals());
+ array1[1][1] = false;
+ assertTrue(!new EqualsBuilder().append(array1, array2).isEquals());
+ }
+
+ public void testRaggedArray() {
+ long array1[][] = new long[2][];
+ long array2[][] = new long[2][];
+ for (int i = 0; i < array1.length; ++i) {
+ array1[i] = new long[2];
+ array2[i] = new long[2];
+ for (int j = 0; j < array1[i].length; ++j) {
+ array1[i][j] = (i + 1) * (j + 1);
+ array2[i][j] = (i + 1) * (j + 1);
+ }
+ }
+ assertTrue(new EqualsBuilder().append(array1, array1).isEquals());
+ assertTrue(new EqualsBuilder().append(array1, array2).isEquals());
+ array1[1][1] = 0;
+ assertTrue(!new EqualsBuilder().append(array1, array2).isEquals());
+ }
+
+ public void testMixedArray() {
+ Object array1[] = new Object[2];
+ Object array2[] = new Object[2];
+ for (int i = 0; i < array1.length; ++i) {
+ array1[i] = new long[2];
+ array2[i] = new long[2];
+ for (int j = 0; j < 2; ++j) {
+ ((long[]) array1[i])[j] = (i + 1) * (j + 1);
+ ((long[]) array2[i])[j] = (i + 1) * (j + 1);
+ }
+ }
+ assertTrue(new EqualsBuilder().append(array1, array1).isEquals());
+ assertTrue(new EqualsBuilder().append(array1, array2).isEquals());
+ ((long[]) array1[1])[1] = 0;
+ assertTrue(!new EqualsBuilder().append(array1, array2).isEquals());
+ }
+
+ public void testObjectArrayHiddenByObject() {
+ TestObject[] array1 = new TestObject[2];
+ array1[0] = new TestObject(4);
+ array1[1] = new TestObject(5);
+ TestObject[] array2 = new TestObject[2];
+ array2[0] = new TestObject(4);
+ array2[1] = new TestObject(5);
+ Object obj1 = array1;
+ Object obj2 = array2;
+ assertTrue(new EqualsBuilder().append(obj1, obj1).isEquals());
+ assertTrue(new EqualsBuilder().append(obj1, array1).isEquals());
+ assertTrue(new EqualsBuilder().append(obj1, obj2).isEquals());
+ assertTrue(new EqualsBuilder().append(obj1, array2).isEquals());
+ array1[1].setA(6);
+ assertTrue(!new EqualsBuilder().append(obj1, obj2).isEquals());
+ }
+
+ public void testLongArrayHiddenByObject() {
+ long[] array1 = new long[2];
+ array1[0] = 5L;
+ array1[1] = 6L;
+ long[] array2 = new long[2];
+ array2[0] = 5L;
+ array2[1] = 6L;
+ Object obj1 = array1;
+ Object obj2 = array2;
+ assertTrue(new EqualsBuilder().append(obj1, obj1).isEquals());
+ assertTrue(new EqualsBuilder().append(obj1, array1).isEquals());
+ assertTrue(new EqualsBuilder().append(obj1, obj2).isEquals());
+ assertTrue(new EqualsBuilder().append(obj1, array2).isEquals());
+ array1[1] = 7;
+ assertTrue(!new EqualsBuilder().append(obj1, obj2).isEquals());
+ }
+
+ public void testIntArrayHiddenByObject() {
+ int[] array1 = new int[2];
+ array1[0] = 5;
+ array1[1] = 6;
+ int[] array2 = new int[2];
+ array2[0] = 5;
+ array2[1] = 6;
+ Object obj1 = array1;
+ Object obj2 = array2;
+ assertTrue(new EqualsBuilder().append(obj1, obj1).isEquals());
+ assertTrue(new EqualsBuilder().append(obj1, array1).isEquals());
+ assertTrue(new EqualsBuilder().append(obj1, obj2).isEquals());
+ assertTrue(new EqualsBuilder().append(obj1, array2).isEquals());
+ array1[1] = 7;
+ assertTrue(!new EqualsBuilder().append(obj1, obj2).isEquals());
+ }
+
+ public void testShortArrayHiddenByObject() {
+ short[] array1 = new short[2];
+ array1[0] = 5;
+ array1[1] = 6;
+ short[] array2 = new short[2];
+ array2[0] = 5;
+ array2[1] = 6;
+ Object obj1 = array1;
+ Object obj2 = array2;
+ assertTrue(new EqualsBuilder().append(obj1, obj1).isEquals());
+ assertTrue(new EqualsBuilder().append(obj1, array1).isEquals());
+ assertTrue(new EqualsBuilder().append(obj1, obj2).isEquals());
+ assertTrue(new EqualsBuilder().append(obj1, array2).isEquals());
+ array1[1] = 7;
+ assertTrue(!new EqualsBuilder().append(obj1, obj2).isEquals());
+ }
+
+ public void testCharArrayHiddenByObject() {
+ char[] array1 = new char[2];
+ array1[0] = 5;
+ array1[1] = 6;
+ char[] array2 = new char[2];
+ array2[0] = 5;
+ array2[1] = 6;
+ Object obj1 = array1;
+ Object obj2 = array2;
+ assertTrue(new EqualsBuilder().append(obj1, obj1).isEquals());
+ assertTrue(new EqualsBuilder().append(obj1, array1).isEquals());
+ assertTrue(new EqualsBuilder().append(obj1, obj2).isEquals());
+ assertTrue(new EqualsBuilder().append(obj1, array2).isEquals());
+ array1[1] = 7;
+ assertTrue(!new EqualsBuilder().append(obj1, obj2).isEquals());
+ }
+
+ public void testByteArrayHiddenByObject() {
+ byte[] array1 = new byte[2];
+ array1[0] = 5;
+ array1[1] = 6;
+ byte[] array2 = new byte[2];
+ array2[0] = 5;
+ array2[1] = 6;
+ Object obj1 = array1;
+ Object obj2 = array2;
+ assertTrue(new EqualsBuilder().append(obj1, obj1).isEquals());
+ assertTrue(new EqualsBuilder().append(obj1, array1).isEquals());
+ assertTrue(new EqualsBuilder().append(obj1, obj2).isEquals());
+ assertTrue(new EqualsBuilder().append(obj1, array2).isEquals());
+ array1[1] = 7;
+ assertTrue(!new EqualsBuilder().append(obj1, obj2).isEquals());
+ }
+
+ public void testDoubleArrayHiddenByObject() {
+ double[] array1 = new double[2];
+ array1[0] = 5;
+ array1[1] = 6;
+ double[] array2 = new double[2];
+ array2[0] = 5;
+ array2[1] = 6;
+ Object obj1 = array1;
+ Object obj2 = array2;
+ assertTrue(new EqualsBuilder().append(obj1, obj1).isEquals());
+ assertTrue(new EqualsBuilder().append(obj1, array1).isEquals());
+ assertTrue(new EqualsBuilder().append(obj1, obj2).isEquals());
+ assertTrue(new EqualsBuilder().append(obj1, array2).isEquals());
+ array1[1] = 7;
+ assertTrue(!new EqualsBuilder().append(obj1, obj2).isEquals());
+ }
+
+ public void testFloatArrayHiddenByObject() {
+ float[] array1 = new float[2];
+ array1[0] = 5;
+ array1[1] = 6;
+ float[] array2 = new float[2];
+ array2[0] = 5;
+ array2[1] = 6;
+ Object obj1 = array1;
+ Object obj2 = array2;
+ assertTrue(new EqualsBuilder().append(obj1, obj1).isEquals());
+ assertTrue(new EqualsBuilder().append(obj1, array1).isEquals());
+ assertTrue(new EqualsBuilder().append(obj1, obj2).isEquals());
+ assertTrue(new EqualsBuilder().append(obj1, array2).isEquals());
+ array1[1] = 7;
+ assertTrue(!new EqualsBuilder().append(obj1, obj2).isEquals());
+ }
+
+ public void testBooleanArrayHiddenByObject() {
+ boolean[] array1 = new boolean[2];
+ array1[0] = true;
+ array1[1] = false;
+ boolean[] array2 = new boolean[2];
+ array2[0] = true;
+ array2[1] = false;
+ Object obj1 = array1;
+ Object obj2 = array2;
+ assertTrue(new EqualsBuilder().append(obj1, obj1).isEquals());
+ assertTrue(new EqualsBuilder().append(obj1, array1).isEquals());
+ assertTrue(new EqualsBuilder().append(obj1, obj2).isEquals());
+ assertTrue(new EqualsBuilder().append(obj1, array2).isEquals());
+ array1[1] = true;
+ assertTrue(!new EqualsBuilder().append(obj1, obj2).isEquals());
+ }
+
+}
diff --git a/examples/cl2/src/test/org/apache/commons/lang/builder/HashCodeBuilderAndEqualsBuilderTest.java b/examples/cl2/src/test/org/apache/commons/lang/builder/HashCodeBuilderAndEqualsBuilderTest.java
new file mode 100644
index 00000000..04235413
--- /dev/null
+++ b/examples/cl2/src/test/org/apache/commons/lang/builder/HashCodeBuilderAndEqualsBuilderTest.java
@@ -0,0 +1,200 @@
+/* ====================================================================
+ * 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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
+ * .
+ */
+package org.apache.commons.lang.builder;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import junit.textui.TestRunner;
+
+/**
+ * Tests HashCodeBuilder and EqualsBuilderTest to insure that equal
+ * objects must have equal hash codes.
+ *
+ * @author Gary Gregory
+ * @version $Id: HashCodeBuilderAndEqualsBuilderTest.java,v 1.2 2003/05/21 23:49:15 scolebourne Exp $
+ */
+public class HashCodeBuilderAndEqualsBuilderTest extends TestCase {
+
+ /**
+ * Constructor for HashCodeBuilderAndEqualsBuilderTest.
+ * @param name
+ */
+ public HashCodeBuilderAndEqualsBuilderTest(String name) {
+ super(name);
+ }
+
+ public static void main(String[] args) {
+ TestRunner.run(suite());
+ }
+
+ public static Test suite() {
+ TestSuite suite = new TestSuite(HashCodeBuilderAndEqualsBuilderTest.class);
+ suite.setName("HashCodeBuilderAndEqualsBuilder Tests");
+ return suite;
+ }
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ //-----------------------------------------------------------------------
+
+ public void testInteger(boolean testTransients) {
+ Integer i1 = new Integer(12345);
+ Integer i2 = new Integer(12345);
+ assertEqualsAndHashCodeContract(i1, i2, testTransients);
+ }
+
+ public void testInteger() {
+ testInteger(false);
+ }
+
+ public void testIntegerWithTransients() {
+ testInteger(true);
+ }
+
+ public void testFixture() {
+ testFixture(false);
+ }
+
+ public void testFixtureWithTransients() {
+ testFixture(true);
+ }
+
+ public void testFixture(boolean testTransients) {
+ assertEqualsAndHashCodeContract(new TestFixture(2, 'c', "Test", (short) 2), new TestFixture(2, 'c', "Test", (short) 2), testTransients);
+ assertEqualsAndHashCodeContract(
+ new AllTransientFixture(2, 'c', "Test", (short) 2),
+ new AllTransientFixture(2, 'c', "Test", (short) 2),
+ testTransients);
+ assertEqualsAndHashCodeContract(
+ new SubTestFixture(2, 'c', "Test", (short) 2, "Same"),
+ new SubTestFixture(2, 'c', "Test", (short) 2, "Same"),
+ testTransients);
+ assertEqualsAndHashCodeContract(
+ new SubAllTransientFixture(2, 'c', "Test", (short) 2, "Same"),
+ new SubAllTransientFixture(2, 'c', "Test", (short) 2, "Same"),
+ testTransients);
+ }
+
+ /**
+ * Asserts that if lhs
equals rhs
+ * then their hash codes MUST be identical.
+ *
+ * @param lhs The Left-Hand-Side of the equals test
+ * @param rhs The Right-Hand-Side of the equals test
+ * @param testTransients wether to test transient fields
+ */
+ public void assertEqualsAndHashCodeContract(Object lhs, Object rhs, boolean testTransients) {
+ if (EqualsBuilder.reflectionEquals(lhs, rhs, testTransients)) {
+ // test a couple of times for consistency.
+ assertEquals(HashCodeBuilder.reflectionHashCode(lhs, testTransients), HashCodeBuilder.reflectionHashCode(rhs, testTransients));
+ assertEquals(HashCodeBuilder.reflectionHashCode(lhs, testTransients), HashCodeBuilder.reflectionHashCode(rhs, testTransients));
+ assertEquals(HashCodeBuilder.reflectionHashCode(lhs, testTransients), HashCodeBuilder.reflectionHashCode(rhs, testTransients));
+ }
+ }
+
+ static class TestFixture {
+ int i;
+ char c;
+ String string;
+ short s;
+
+ TestFixture(int i, char c, String string, short s) {
+ this.i = i;
+ this.c = c;
+ this.string = string;
+ this.s = s;
+ }
+ }
+
+ static class SubTestFixture extends TestFixture {
+ transient String tString;
+
+ SubTestFixture(int i, char c, String string, short s, String tString) {
+ super(i, c, string, s);
+ this.tString = tString;
+ }
+ }
+
+ static class AllTransientFixture {
+ transient int i;
+ transient char c;
+ transient String string;
+ transient short s;
+
+ AllTransientFixture(int i, char c, String string, short s) {
+ this.i = i;
+ this.c = c;
+ this.string = string;
+ this.s = s;
+ }
+ }
+
+ static class SubAllTransientFixture extends AllTransientFixture {
+ transient String tString;
+
+ SubAllTransientFixture(int i, char c, String string, short s, String tString) {
+ super(i, c, string, s);
+ this.tString = tString;
+ }
+ }
+
+
+}
diff --git a/examples/cl2/src/test/org/apache/commons/lang/builder/HashCodeBuilderTest.java b/examples/cl2/src/test/org/apache/commons/lang/builder/HashCodeBuilderTest.java
new file mode 100644
index 00000000..7991a29b
--- /dev/null
+++ b/examples/cl2/src/test/org/apache/commons/lang/builder/HashCodeBuilderTest.java
@@ -0,0 +1,477 @@
+/* ====================================================================
+ * 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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
+ * .
+ */
+package org.apache.commons.lang.builder;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import junit.textui.TestRunner;
+/**
+ * Unit tests {@link org.apache.commons.lang.HashCodeBuilder}.
+ *
+ * @author Stephen Colebourne
+ * @version $Id: HashCodeBuilderTest.java,v 1.4 2003/05/21 23:49:15 scolebourne Exp $
+ */
+public class HashCodeBuilderTest extends TestCase {
+
+ public HashCodeBuilderTest(String name) {
+ super(name);
+ }
+
+ public static void main(String[] args) {
+ TestRunner.run(suite());
+ }
+
+ public static Test suite() {
+ TestSuite suite = new TestSuite(HashCodeBuilderTest.class);
+ suite.setName("HashCodeBuilder Tests");
+ return suite;
+ }
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ //-----------------------------------------------------------------------
+
+ public void testConstructorEx1() {
+ try {
+ new HashCodeBuilder(0, 0);
+
+ } catch (IllegalArgumentException ex) {
+ return;
+ }
+ fail();
+ }
+
+ public void testConstructorEx2() {
+ try {
+ new HashCodeBuilder(2, 2);
+
+ } catch (IllegalArgumentException ex) {
+ return;
+ }
+ fail();
+ }
+
+ static class TestObject {
+ private int a;
+ public TestObject(int a) {
+ this.a = a;
+ }
+ public boolean equals(Object o) {
+ if (o == this) {
+ return true;
+ }
+ if (!(o instanceof TestObject)) {
+ return false;
+ }
+ TestObject rhs = (TestObject) o;
+ return (a == rhs.a);
+ }
+
+ public void setA(int a) {
+ this.a = a;
+ }
+
+ public int getA() {
+ return a;
+ }
+ }
+
+ static class TestSubObject extends TestObject {
+ private int b;
+ transient private int t;
+ public TestSubObject() {
+ super(0);
+ }
+ public TestSubObject(int a, int b, int t) {
+ super(a);
+ this.b = b;
+ this.t = t;
+ }
+ public boolean equals(Object o) {
+ if (o == this) {
+ return true;
+ }
+ if (!(o instanceof TestSubObject)) {
+ return false;
+ }
+ TestSubObject rhs = (TestSubObject) o;
+ return super.equals(o) && (b == rhs.b);
+ }
+ }
+
+ public void testReflectionHashCode() {
+ assertEquals(17 * 37, HashCodeBuilder.reflectionHashCode(new TestObject(0)));
+ assertEquals(17 * 37 + 123456, HashCodeBuilder.reflectionHashCode(new TestObject(123456)));
+ }
+
+ public void testReflectionHierarchyHashCode() {
+ assertEquals(17 * 37 * 37, HashCodeBuilder.reflectionHashCode(new TestSubObject(0, 0, 0)));
+ assertEquals(17 * 37 * 37 * 37, HashCodeBuilder.reflectionHashCode(new TestSubObject(0, 0, 0), true));
+ assertEquals((17 * 37 + 7890) * 37 + 123456, HashCodeBuilder.reflectionHashCode(new TestSubObject(123456, 7890, 0)));
+ assertEquals(((17 * 37 + 7890) * 37 + 0) * 37 + 123456, HashCodeBuilder.reflectionHashCode(new TestSubObject(123456, 7890, 0), true));
+ }
+
+ public void testReflectionHierarchyHashCodeEx1() {
+ try {
+ HashCodeBuilder.reflectionHashCode(0, 0, new TestSubObject(0, 0, 0), true);
+ } catch (IllegalArgumentException ex) {
+ return;
+ }
+ fail();
+ }
+
+ public void testReflectionHierarchyHashCodeEx2() {
+ try {
+ HashCodeBuilder.reflectionHashCode(2, 2, new TestSubObject(0, 0, 0), true);
+ } catch (IllegalArgumentException ex) {
+ return;
+ }
+ fail();
+ }
+
+ public void testReflectionHashCodeEx1() {
+ try {
+ HashCodeBuilder.reflectionHashCode(0, 0, new TestObject(0), true);
+ } catch (IllegalArgumentException ex) {
+ return;
+ }
+ fail();
+ }
+
+ public void testReflectionHashCodeEx2() {
+ try {
+ HashCodeBuilder.reflectionHashCode(2, 2, new TestObject(0), true);
+ } catch (IllegalArgumentException ex) {
+ return;
+ }
+ fail();
+ }
+
+ public void testReflectionHashCodeEx3() {
+ try {
+ HashCodeBuilder.reflectionHashCode(13, 19, null, true);
+ } catch (IllegalArgumentException ex) {
+ return;
+ }
+ fail();
+ }
+
+ public void testSuper() {
+ Object obj = new Object();
+ assertEquals(17 * 37 + (19 * 41 + obj.hashCode()), new HashCodeBuilder(17, 37).appendSuper(
+ new HashCodeBuilder(19, 41).append(obj).toHashCode()
+ ).toHashCode());
+ }
+
+ public void testObject() {
+ Object obj = null;
+ assertEquals(17 * 37, new HashCodeBuilder(17, 37).append(obj).toHashCode());
+ obj = new Object();
+ assertEquals(17 * 37 + obj.hashCode(), new HashCodeBuilder(17, 37).append(obj).toHashCode());
+ }
+
+ public void testLong() {
+ assertEquals(17 * 37, new HashCodeBuilder(17, 37).append((long) 0L).toHashCode());
+ assertEquals(17 * 37 + (int) (123456789L ^ (123456789L >> 32)), new HashCodeBuilder(17, 37).append((long) 123456789L).toHashCode());
+ }
+
+ public void testInt() {
+ assertEquals(17 * 37, new HashCodeBuilder(17, 37).append((int) 0).toHashCode());
+ assertEquals(17 * 37 + 123456, new HashCodeBuilder(17, 37).append((int) 123456).toHashCode());
+ }
+
+ public void testShort() {
+ assertEquals(17 * 37, new HashCodeBuilder(17, 37).append((short) 0).toHashCode());
+ assertEquals(17 * 37 + 12345, new HashCodeBuilder(17, 37).append((short) 12345).toHashCode());
+ }
+
+ public void testChar() {
+ assertEquals(17 * 37, new HashCodeBuilder(17, 37).append((char) 0).toHashCode());
+ assertEquals(17 * 37 + 1234, new HashCodeBuilder(17, 37).append((char) 1234).toHashCode());
+ }
+
+ public void testByte() {
+ assertEquals(17 * 37, new HashCodeBuilder(17, 37).append((byte) 0).toHashCode());
+ assertEquals(17 * 37 + 123, new HashCodeBuilder(17, 37).append((byte) 123).toHashCode());
+ }
+
+ public void testDouble() {
+ assertEquals(17 * 37, new HashCodeBuilder(17, 37).append((double) 0d).toHashCode());
+ double d = 1234567.89;
+ long l = Double.doubleToLongBits(d);
+ assertEquals(17 * 37 + (int) (l ^ (l >> 32)), new HashCodeBuilder(17, 37).append(d).toHashCode());
+ }
+
+ public void testFloat() {
+ assertEquals(17 * 37, new HashCodeBuilder(17, 37).append((float) 0f).toHashCode());
+ float f = 1234.89f;
+ int i = Float.floatToIntBits(f);
+ assertEquals(17 * 37 + i, new HashCodeBuilder(17, 37).append(f).toHashCode());
+ }
+
+ public void testBoolean() {
+ assertEquals(17 * 37 + 0, new HashCodeBuilder(17, 37).append(true).toHashCode());
+ assertEquals(17 * 37 + 1, new HashCodeBuilder(17, 37).append(false).toHashCode());
+ }
+
+ public void testObjectArray() {
+ assertEquals(17 * 37, new HashCodeBuilder(17, 37).append((Object[]) null).toHashCode());
+ Object[] obj = new Object[2];
+ assertEquals((17 * 37) * 37 , new HashCodeBuilder(17, 37).append(obj).toHashCode());
+ obj[0] = new Object();
+ assertEquals((17 * 37 + obj[0].hashCode()) * 37, new HashCodeBuilder(17, 37).append(obj).toHashCode());
+ obj[1] = new Object();
+ assertEquals( (17 * 37 + obj[0].hashCode()) * 37 + obj[1].hashCode(), new HashCodeBuilder(17, 37).append(obj).toHashCode());
+ }
+
+ public void testObjectArrayAsObject() {
+ Object[] obj = new Object[2];
+ assertEquals((17 * 37) * 37 , new HashCodeBuilder(17, 37).append((Object) obj).toHashCode());
+ obj[0] = new Object();
+ assertEquals((17 * 37 + obj[0].hashCode()) * 37, new HashCodeBuilder(17, 37).append((Object) obj).toHashCode());
+ obj[1] = new Object();
+ assertEquals( (17 * 37 + obj[0].hashCode()) * 37 + obj[1].hashCode(), new HashCodeBuilder(17, 37).append((Object) obj).toHashCode());
+ }
+
+ public void testLongArray() {
+ assertEquals(17 * 37, new HashCodeBuilder(17, 37).append((long[]) null).toHashCode());
+ long[] obj = new long[2];
+ assertEquals((17 * 37) * 37 , new HashCodeBuilder(17, 37).append(obj).toHashCode());
+ obj[0] = 5L;
+ int h1 = (int) (5L ^ (5L >> 32));
+ assertEquals((17 * 37 + h1) * 37, new HashCodeBuilder(17, 37).append(obj).toHashCode());
+ obj[1] = 6L;
+ int h2 = (int) (6L ^ (6L >> 32));
+ assertEquals( (17 * 37 + h1) * 37 + h2, new HashCodeBuilder(17, 37).append(obj).toHashCode());
+ }
+
+ public void testLongArrayAsObject() {
+ long[] obj = new long[2];
+ assertEquals((17 * 37) * 37 , new HashCodeBuilder(17, 37).append((Object) obj).toHashCode());
+ obj[0] = 5L;
+ int h1 = (int) (5L ^ (5L >> 32));
+ assertEquals((17 * 37 + h1) * 37, new HashCodeBuilder(17, 37).append((Object) obj).toHashCode());
+ obj[1] = 6L;
+ int h2 = (int) (6L ^ (6L >> 32));
+ assertEquals( (17 * 37 + h1) * 37 + h2, new HashCodeBuilder(17, 37).append((Object) obj).toHashCode());
+ }
+
+ public void testIntArray() {
+ assertEquals(17 * 37, new HashCodeBuilder(17, 37).append((int[]) null).toHashCode());
+ int[] obj = new int[2];
+ assertEquals((17 * 37) * 37 , new HashCodeBuilder(17, 37).append(obj).toHashCode());
+ obj[0] = 5;
+ assertEquals((17 * 37 + 5) * 37, new HashCodeBuilder(17, 37).append(obj).toHashCode());
+ obj[1] = 6;
+ assertEquals( (17 * 37 + 5) * 37 + 6, new HashCodeBuilder(17, 37).append(obj).toHashCode());
+ }
+
+ public void testIntArrayAsObject() {
+ int[] obj = new int[2];
+ assertEquals((17 * 37) * 37 , new HashCodeBuilder(17, 37).append((Object) obj).toHashCode());
+ obj[0] = 5;
+ assertEquals((17 * 37 + 5) * 37, new HashCodeBuilder(17, 37).append((Object) obj).toHashCode());
+ obj[1] = 6;
+ assertEquals( (17 * 37 + 5) * 37 + 6, new HashCodeBuilder(17, 37).append((Object) obj).toHashCode());
+ }
+
+ public void testShortArray() {
+ assertEquals(17 * 37, new HashCodeBuilder(17, 37).append((short[]) null).toHashCode());
+ short[] obj = new short[2];
+ assertEquals((17 * 37) * 37 , new HashCodeBuilder(17, 37).append(obj).toHashCode());
+ obj[0] = (short) 5;
+ assertEquals((17 * 37 + 5) * 37, new HashCodeBuilder(17, 37).append(obj).toHashCode());
+ obj[1] = (short) 6;
+ assertEquals( (17 * 37 + 5) * 37 + 6, new HashCodeBuilder(17, 37).append(obj).toHashCode());
+ }
+
+ public void testShortArrayAsObject() {
+ short[] obj = new short[2];
+ assertEquals((17 * 37) * 37 , new HashCodeBuilder(17, 37).append((Object) obj).toHashCode());
+ obj[0] = (short) 5;
+ assertEquals((17 * 37 + 5) * 37, new HashCodeBuilder(17, 37).append((Object) obj).toHashCode());
+ obj[1] = (short) 6;
+ assertEquals( (17 * 37 + 5) * 37 + 6, new HashCodeBuilder(17, 37).append((Object) obj).toHashCode());
+ }
+
+ public void testCharArray() {
+ assertEquals(17 * 37, new HashCodeBuilder(17, 37).append((char[]) null).toHashCode());
+ char[] obj = new char[2];
+ assertEquals((17 * 37) * 37 , new HashCodeBuilder(17, 37).append(obj).toHashCode());
+ obj[0] = (char) 5;
+ assertEquals((17 * 37 + 5) * 37, new HashCodeBuilder(17, 37).append(obj).toHashCode());
+ obj[1] = (char) 6;
+ assertEquals( (17 * 37 + 5) * 37 + 6, new HashCodeBuilder(17, 37).append(obj).toHashCode());
+ }
+
+ public void testCharArrayAsObject() {
+ char[] obj = new char[2];
+ assertEquals((17 * 37) * 37 , new HashCodeBuilder(17, 37).append((Object) obj).toHashCode());
+ obj[0] = (char) 5;
+ assertEquals((17 * 37 + 5) * 37, new HashCodeBuilder(17, 37).append((Object) obj).toHashCode());
+ obj[1] = (char) 6;
+ assertEquals( (17 * 37 + 5) * 37 + 6, new HashCodeBuilder(17, 37).append((Object) obj).toHashCode());
+ }
+
+ public void testByteArray() {
+ assertEquals(17 * 37, new HashCodeBuilder(17, 37).append((byte[]) null).toHashCode());
+ byte[] obj = new byte[2];
+ assertEquals((17 * 37) * 37 , new HashCodeBuilder(17, 37).append(obj).toHashCode());
+ obj[0] = (byte) 5;
+ assertEquals((17 * 37 + 5) * 37, new HashCodeBuilder(17, 37).append(obj).toHashCode());
+ obj[1] = (byte) 6;
+ assertEquals( (17 * 37 + 5) * 37 + 6, new HashCodeBuilder(17, 37).append(obj).toHashCode());
+ }
+
+ public void testByteArrayAsObject() {
+ byte[] obj = new byte[2];
+ assertEquals((17 * 37) * 37 , new HashCodeBuilder(17, 37).append((Object) obj).toHashCode());
+ obj[0] = (byte) 5;
+ assertEquals((17 * 37 + 5) * 37, new HashCodeBuilder(17, 37).append((Object) obj).toHashCode());
+ obj[1] = (byte) 6;
+ assertEquals( (17 * 37 + 5) * 37 + 6, new HashCodeBuilder(17, 37).append((Object) obj).toHashCode());
+ }
+
+ public void testDoubleArray() {
+ assertEquals(17 * 37, new HashCodeBuilder(17, 37).append((double[]) null).toHashCode());
+ double[] obj = new double[2];
+ assertEquals((17 * 37) * 37 , new HashCodeBuilder(17, 37).append(obj).toHashCode());
+ obj[0] = 5.4d;
+ long l1 = Double.doubleToLongBits(5.4d);
+ int h1 = (int) (l1 ^ (l1 >> 32));
+ assertEquals((17 * 37 + h1) * 37, new HashCodeBuilder(17, 37).append(obj).toHashCode());
+ obj[1] = 6.3d;
+ long l2 = Double.doubleToLongBits(6.3d);
+ int h2 = (int) (l2 ^ (l2 >> 32));
+ assertEquals( (17 * 37 + h1) * 37 + h2, new HashCodeBuilder(17, 37).append(obj).toHashCode());
+ }
+
+ public void testDoubleArrayAsObject() {
+ double[] obj = new double[2];
+ assertEquals((17 * 37) * 37 , new HashCodeBuilder(17, 37).append((Object) obj).toHashCode());
+ obj[0] = 5.4d;
+ long l1 = Double.doubleToLongBits(5.4d);
+ int h1 = (int) (l1 ^ (l1 >> 32));
+ assertEquals((17 * 37 + h1) * 37, new HashCodeBuilder(17, 37).append((Object) obj).toHashCode());
+ obj[1] = 6.3d;
+ long l2 = Double.doubleToLongBits(6.3d);
+ int h2 = (int) (l2 ^ (l2 >> 32));
+ assertEquals( (17 * 37 + h1) * 37 + h2, new HashCodeBuilder(17, 37).append((Object) obj).toHashCode());
+ }
+
+ public void testFloatArray() {
+ assertEquals(17 * 37, new HashCodeBuilder(17, 37).append((float[]) null).toHashCode());
+ float[] obj = new float[2];
+ assertEquals((17 * 37) * 37 , new HashCodeBuilder(17, 37).append(obj).toHashCode());
+ obj[0] = 5.4f;
+ int h1 = Float.floatToIntBits(5.4f);
+ assertEquals((17 * 37 + h1) * 37, new HashCodeBuilder(17, 37).append(obj).toHashCode());
+ obj[1] = 6.3f;
+ int h2 = Float.floatToIntBits(6.3f);
+ assertEquals( (17 * 37 + h1) * 37 + h2, new HashCodeBuilder(17, 37).append(obj).toHashCode());
+ }
+
+ public void testFloatArrayAsObject() {
+ float[] obj = new float[2];
+ assertEquals((17 * 37) * 37 , new HashCodeBuilder(17, 37).append((Object) obj).toHashCode());
+ obj[0] = 5.4f;
+ int h1 = Float.floatToIntBits(5.4f);
+ assertEquals((17 * 37 + h1) * 37, new HashCodeBuilder(17, 37).append((Object) obj).toHashCode());
+ obj[1] = 6.3f;
+ int h2 = Float.floatToIntBits(6.3f);
+ assertEquals( (17 * 37 + h1) * 37 + h2, new HashCodeBuilder(17, 37).append((Object) obj).toHashCode());
+ }
+
+ public void testBooleanArray() {
+ assertEquals(17 * 37, new HashCodeBuilder(17, 37).append((boolean[]) null).toHashCode());
+ boolean[] obj = new boolean[2];
+ assertEquals((17 * 37 + 1) * 37 + 1 , new HashCodeBuilder(17, 37).append(obj).toHashCode());
+ obj[0] = true;
+ assertEquals((17 * 37 + 0) * 37 + 1, new HashCodeBuilder(17, 37).append(obj).toHashCode());
+ obj[1] = false;
+ assertEquals( (17 * 37 + 0) * 37 + 1, new HashCodeBuilder(17, 37).append(obj).toHashCode());
+ }
+
+ public void testBooleanArrayAsObject() {
+ boolean[] obj = new boolean[2];
+ assertEquals((17 * 37 + 1) * 37 + 1 , new HashCodeBuilder(17, 37).append((Object) obj).toHashCode());
+ obj[0] = true;
+ assertEquals((17 * 37 + 0) * 37 + 1, new HashCodeBuilder(17, 37).append((Object) obj).toHashCode());
+ obj[1] = false;
+ assertEquals( (17 * 37 + 0) * 37 + 1, new HashCodeBuilder(17, 37).append((Object) obj).toHashCode());
+ }
+
+ public void testBooleanMultiArray() {
+ boolean[][] obj = new boolean[2][];
+ assertEquals((17 * 37) * 37, new HashCodeBuilder(17, 37).append(obj).toHashCode());
+ obj[0] = new boolean[0];
+ assertEquals(17 * 37, new HashCodeBuilder(17, 37).append(obj).toHashCode());
+ obj[0] = new boolean[1];
+ assertEquals((17 * 37 + 1) * 37, new HashCodeBuilder(17, 37).append(obj).toHashCode());
+ obj[0] = new boolean[2];
+ assertEquals(((17 * 37 + 1) * 37 + 1) * 37, new HashCodeBuilder(17, 37).append(obj).toHashCode());
+ obj[0][0] = true;
+ assertEquals(((17 * 37 + 0) * 37 + 1) * 37, new HashCodeBuilder(17, 37).append(obj).toHashCode());
+ obj[1] = new boolean[1];
+ assertEquals( (((17 * 37 + 0) * 37 + 1) * 37 + 1), new HashCodeBuilder(17, 37).append(obj).toHashCode());
+ }
+
+}
diff --git a/examples/cl2/src/test/org/apache/commons/lang/builder/MultiLineToStringStyleTest.java b/examples/cl2/src/test/org/apache/commons/lang/builder/MultiLineToStringStyleTest.java
new file mode 100644
index 00000000..fd3588ad
--- /dev/null
+++ b/examples/cl2/src/test/org/apache/commons/lang/builder/MultiLineToStringStyleTest.java
@@ -0,0 +1,166 @@
+/* ====================================================================
+ * 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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
+ * .
+ */
+// package org.apache.commons.lang.builder
+
+package org.apache.commons.lang.builder;
+import java.util.ArrayList;
+import java.util.HashMap;
+
+import org.apache.commons.lang.SystemUtils;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import junit.textui.TestRunner;
+/**
+ * Unit tests {@link org.apache.commons.lang.ToStringStyle}.
+ *
+ * @author Stephen Colebourne
+ * @version $Id: MultiLineToStringStyleTest.java,v 1.3 2003/05/21 23:49:15 scolebourne Exp $
+ */
+public class MultiLineToStringStyleTest extends TestCase {
+
+ private final Integer base = new Integer(5);
+ private final String baseStr = base.getClass().getName() + "@" + Integer.toHexString(System.identityHashCode(base));
+
+ public MultiLineToStringStyleTest(String name) {
+ super(name);
+ }
+
+ public static void main(String[] args) {
+ TestRunner.run(suite());
+ }
+
+ public static Test suite() {
+ TestSuite suite = new TestSuite(MultiLineToStringStyleTest.class);
+ suite.setName("DefaultToStringStyle Tests");
+ return suite;
+ }
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ ToStringBuilder.setDefaultStyle(ToStringStyle.MULTI_LINE_STYLE);
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ ToStringBuilder.setDefaultStyle(ToStringStyle.DEFAULT_STYLE);
+ }
+
+ //----------------------------------------------------------------
+
+ public void testBlank() {
+ assertEquals(baseStr + "[" + SystemUtils.LINE_SEPARATOR + "]", new ToStringBuilder(base).toString());
+ }
+
+ public void testAppendSuper() {
+ assertEquals(baseStr + "[" + SystemUtils.LINE_SEPARATOR + "]", new ToStringBuilder(base).appendSuper("Integer@8888[" + SystemUtils.LINE_SEPARATOR + "]").toString());
+ assertEquals(baseStr + "[" + SystemUtils.LINE_SEPARATOR + " " + SystemUtils.LINE_SEPARATOR + "]", new ToStringBuilder(base).appendSuper("Integer@8888[" + SystemUtils.LINE_SEPARATOR + " " + SystemUtils.LINE_SEPARATOR + "]").toString());
+
+ assertEquals(baseStr + "[" + SystemUtils.LINE_SEPARATOR + " a=hello" + SystemUtils.LINE_SEPARATOR + "]", new ToStringBuilder(base).appendSuper("Integer@8888[" + SystemUtils.LINE_SEPARATOR + "]").append("a", "hello").toString());
+ assertEquals(baseStr + "[" + SystemUtils.LINE_SEPARATOR + " " + SystemUtils.LINE_SEPARATOR + " a=hello" + SystemUtils.LINE_SEPARATOR + "]", new ToStringBuilder(base).appendSuper("Integer@8888[" + SystemUtils.LINE_SEPARATOR + " " + SystemUtils.LINE_SEPARATOR + "]").append("a", "hello").toString());
+ assertEquals(baseStr + "[" + SystemUtils.LINE_SEPARATOR + " a=hello" + SystemUtils.LINE_SEPARATOR + "]", new ToStringBuilder(base).appendSuper(null).append("a", "hello").toString());
+ }
+
+ public void testObject() {
+ Integer i3 = new Integer(3);
+ Integer i4 = new Integer(4);
+ assertEquals(baseStr + "[" + SystemUtils.LINE_SEPARATOR + " " + SystemUtils.LINE_SEPARATOR + "]", new ToStringBuilder(base).append((Object) null).toString());
+ assertEquals(baseStr + "[" + SystemUtils.LINE_SEPARATOR + " 3" + SystemUtils.LINE_SEPARATOR + "]", new ToStringBuilder(base).append(i3).toString());
+ assertEquals(baseStr + "[" + SystemUtils.LINE_SEPARATOR + " a=" + SystemUtils.LINE_SEPARATOR + "]", new ToStringBuilder(base).append("a", (Object) null).toString());
+ assertEquals(baseStr + "[" + SystemUtils.LINE_SEPARATOR + " a=3" + SystemUtils.LINE_SEPARATOR + "]", new ToStringBuilder(base).append("a", i3).toString());
+ assertEquals(baseStr + "[" + SystemUtils.LINE_SEPARATOR + " a=3" + SystemUtils.LINE_SEPARATOR + " b=4" + SystemUtils.LINE_SEPARATOR + "]", new ToStringBuilder(base).append("a", i3).append("b", i4).toString());
+ assertEquals(baseStr + "[" + SystemUtils.LINE_SEPARATOR + " a=" + SystemUtils.LINE_SEPARATOR + "]", new ToStringBuilder(base).append("a", i3, false).toString());
+ assertEquals(baseStr + "[" + SystemUtils.LINE_SEPARATOR + " a=" + SystemUtils.LINE_SEPARATOR + "]", new ToStringBuilder(base).append("a", new ArrayList(), false).toString());
+ assertEquals(baseStr + "[" + SystemUtils.LINE_SEPARATOR + " a=[]" + SystemUtils.LINE_SEPARATOR + "]", new ToStringBuilder(base).append("a", new ArrayList(), true).toString());
+ assertEquals(baseStr + "[" + SystemUtils.LINE_SEPARATOR + " a=" + SystemUtils.LINE_SEPARATOR + "]", new ToStringBuilder(base).append("a", new HashMap(), false).toString());
+ assertEquals(baseStr + "[" + SystemUtils.LINE_SEPARATOR + " a={}" + SystemUtils.LINE_SEPARATOR + "]", new ToStringBuilder(base).append("a", new HashMap(), true).toString());
+ assertEquals(baseStr + "[" + SystemUtils.LINE_SEPARATOR + " a=" + SystemUtils.LINE_SEPARATOR + "]", new ToStringBuilder(base).append("a", (Object) new String[0], false).toString());
+ assertEquals(baseStr + "[" + SystemUtils.LINE_SEPARATOR + " a={}" + SystemUtils.LINE_SEPARATOR + "]", new ToStringBuilder(base).append("a", (Object) new String[0], true).toString());
+ }
+
+ public void testLong() {
+ assertEquals(baseStr + "[" + SystemUtils.LINE_SEPARATOR + " 3" + SystemUtils.LINE_SEPARATOR + "]", new ToStringBuilder(base).append(3L).toString());
+ assertEquals(baseStr + "[" + SystemUtils.LINE_SEPARATOR + " a=3" + SystemUtils.LINE_SEPARATOR + "]", new ToStringBuilder(base).append("a", 3L).toString());
+ assertEquals(baseStr + "[" + SystemUtils.LINE_SEPARATOR + " a=3" + SystemUtils.LINE_SEPARATOR + " b=4" + SystemUtils.LINE_SEPARATOR + "]", new ToStringBuilder(base).append("a", 3L).append("b", 4L).toString());
+ }
+
+ public void testObjectArray() {
+ Object[] array = new Object[] {null, base, new int[] {3, 6}};
+ assertEquals(baseStr + "[" + SystemUtils.LINE_SEPARATOR + " {,5,{3,6}}" + SystemUtils.LINE_SEPARATOR + "]", new ToStringBuilder(base).append(array).toString());
+ assertEquals(baseStr + "[" + SystemUtils.LINE_SEPARATOR + " {,5,{3,6}}" + SystemUtils.LINE_SEPARATOR + "]", new ToStringBuilder(base).append((Object) array).toString());
+ array = null;
+ assertEquals(baseStr + "[" + SystemUtils.LINE_SEPARATOR + " " + SystemUtils.LINE_SEPARATOR + "]", new ToStringBuilder(base).append(array).toString());
+ assertEquals(baseStr + "[" + SystemUtils.LINE_SEPARATOR + " " + SystemUtils.LINE_SEPARATOR + "]", new ToStringBuilder(base).append((Object) array).toString());
+ }
+
+ public void testLongArray() {
+ long[] array = new long[] {1, 2, -3, 4};
+ assertEquals(baseStr + "[" + SystemUtils.LINE_SEPARATOR + " {1,2,-3,4}" + SystemUtils.LINE_SEPARATOR + "]", new ToStringBuilder(base).append(array).toString());
+ assertEquals(baseStr + "[" + SystemUtils.LINE_SEPARATOR + " {1,2,-3,4}" + SystemUtils.LINE_SEPARATOR + "]", new ToStringBuilder(base).append((Object) array).toString());
+ array = null;
+ assertEquals(baseStr + "[" + SystemUtils.LINE_SEPARATOR + " " + SystemUtils.LINE_SEPARATOR + "]", new ToStringBuilder(base).append(array).toString());
+ assertEquals(baseStr + "[" + SystemUtils.LINE_SEPARATOR + " " + SystemUtils.LINE_SEPARATOR + "]", new ToStringBuilder(base).append((Object) array).toString());
+ }
+
+ public void testLongArrayArray() {
+ long[][] array = new long[][] {{1, 2}, null, {5}};
+ assertEquals(baseStr + "[" + SystemUtils.LINE_SEPARATOR + " {{1,2},,{5}}" + SystemUtils.LINE_SEPARATOR + "]", new ToStringBuilder(base).append(array).toString());
+ assertEquals(baseStr + "[" + SystemUtils.LINE_SEPARATOR + " {{1,2},,{5}}" + SystemUtils.LINE_SEPARATOR + "]", new ToStringBuilder(base).append((Object) array).toString());
+ array = null;
+ assertEquals(baseStr + "[" + SystemUtils.LINE_SEPARATOR + " " + SystemUtils.LINE_SEPARATOR + "]", new ToStringBuilder(base).append(array).toString());
+ assertEquals(baseStr + "[" + SystemUtils.LINE_SEPARATOR + " " + SystemUtils.LINE_SEPARATOR + "]", new ToStringBuilder(base).append((Object) array).toString());
+ }
+
+}
diff --git a/examples/cl2/src/test/org/apache/commons/lang/builder/NoFieldNamesToStringStyleTest.java b/examples/cl2/src/test/org/apache/commons/lang/builder/NoFieldNamesToStringStyleTest.java
new file mode 100644
index 00000000..7319bf52
--- /dev/null
+++ b/examples/cl2/src/test/org/apache/commons/lang/builder/NoFieldNamesToStringStyleTest.java
@@ -0,0 +1,164 @@
+/* ====================================================================
+ * 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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
+ * .
+ */
+// package org.apache.commons.lang.builder
+
+package org.apache.commons.lang.builder;
+import java.util.ArrayList;
+import java.util.HashMap;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import junit.textui.TestRunner;
+/**
+ * Unit tests {@link org.apache.commons.lang.ToStringStyle}.
+ *
+ * @author Stephen Colebourne
+ * @version $Id: NoFieldNamesToStringStyleTest.java,v 1.3 2003/05/21 23:49:14 scolebourne Exp $
+ */
+public class NoFieldNamesToStringStyleTest extends TestCase {
+
+ private final Integer base = new Integer(5);
+ private final String baseStr = base.getClass().getName() + "@" + Integer.toHexString(System.identityHashCode(base));
+
+ public NoFieldNamesToStringStyleTest(String name) {
+ super(name);
+ }
+
+ public static void main(String[] args) {
+ TestRunner.run(suite());
+ }
+
+ public static Test suite() {
+ TestSuite suite = new TestSuite(NoFieldNamesToStringStyleTest.class);
+ suite.setName("NoFieldNamesToStringStyle Tests");
+ return suite;
+ }
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ ToStringBuilder.setDefaultStyle(ToStringStyle.NO_FIELD_NAMES_STYLE);
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ ToStringBuilder.setDefaultStyle(ToStringStyle.DEFAULT_STYLE);
+ }
+
+ //----------------------------------------------------------------
+
+ public void testBlank() {
+ assertEquals(baseStr + "[]", new ToStringBuilder(base).toString());
+ }
+
+ public void testAppendSuper() {
+ assertEquals(baseStr + "[]", new ToStringBuilder(base).appendSuper("Integer@8888[]").toString());
+ assertEquals(baseStr + "[]", new ToStringBuilder(base).appendSuper("Integer@8888[]").toString());
+
+ assertEquals(baseStr + "[hello]", new ToStringBuilder(base).appendSuper("Integer@8888[]").append("a", "hello").toString());
+ assertEquals(baseStr + "[,hello]", new ToStringBuilder(base).appendSuper("Integer@8888[]").append("a", "hello").toString());
+ assertEquals(baseStr + "[hello]", new ToStringBuilder(base).appendSuper(null).append("a", "hello").toString());
+ }
+
+ public void testObject() {
+ Integer i3 = new Integer(3);
+ Integer i4 = new Integer(4);
+ assertEquals(baseStr + "[]", new ToStringBuilder(base).append((Object) null).toString());
+ assertEquals(baseStr + "[3]", new ToStringBuilder(base).append(i3).toString());
+ assertEquals(baseStr + "[]", new ToStringBuilder(base).append("a", (Object) null).toString());
+ assertEquals(baseStr + "[3]", new ToStringBuilder(base).append("a", i3).toString());
+ assertEquals(baseStr + "[3,4]", new ToStringBuilder(base).append("a", i3).append("b", i4).toString());
+ assertEquals(baseStr + "[]", new ToStringBuilder(base).append("a", i3, false).toString());
+ assertEquals(baseStr + "[]", new ToStringBuilder(base).append("a", new ArrayList(), false).toString());
+ assertEquals(baseStr + "[[]]", new ToStringBuilder(base).append("a", new ArrayList(), true).toString());
+ assertEquals(baseStr + "[]", new ToStringBuilder(base).append("a", new HashMap(), false).toString());
+ assertEquals(baseStr + "[{}]", new ToStringBuilder(base).append("a", new HashMap(), true).toString());
+ assertEquals(baseStr + "[]", new ToStringBuilder(base).append("a", (Object) new String[0], false).toString());
+ assertEquals(baseStr + "[{}]", new ToStringBuilder(base).append("a", (Object) new String[0], true).toString());
+ }
+
+ public void testLong() {
+ assertEquals(baseStr + "[3]", new ToStringBuilder(base).append(3L).toString());
+ assertEquals(baseStr + "[3]", new ToStringBuilder(base).append("a", 3L).toString());
+ assertEquals(baseStr + "[3,4]", new ToStringBuilder(base).append("a", 3L).append("b", 4L).toString());
+ }
+
+ public void testObjectArray() {
+ Object[] array = new Object[] {null, base, new int[] {3, 6}};
+ assertEquals(baseStr + "[{,5,{3,6}}]", new ToStringBuilder(base).append(array).toString());
+ assertEquals(baseStr + "[{,5,{3,6}}]", new ToStringBuilder(base).append((Object) array).toString());
+ array = null;
+ assertEquals(baseStr + "[]", new ToStringBuilder(base).append(array).toString());
+ assertEquals(baseStr + "[]", new ToStringBuilder(base).append((Object) array).toString());
+ }
+
+ public void testLongArray() {
+ long[] array = new long[] {1, 2, -3, 4};
+ assertEquals(baseStr + "[{1,2,-3,4}]", new ToStringBuilder(base).append(array).toString());
+ assertEquals(baseStr + "[{1,2,-3,4}]", new ToStringBuilder(base).append((Object) array).toString());
+ array = null;
+ assertEquals(baseStr + "[]", new ToStringBuilder(base).append(array).toString());
+ assertEquals(baseStr + "[]", new ToStringBuilder(base).append((Object) array).toString());
+ }
+
+ public void testLongArrayArray() {
+ long[][] array = new long[][] {{1, 2}, null, {5}};
+ assertEquals(baseStr + "[{{1,2},,{5}}]", new ToStringBuilder(base).append(array).toString());
+ assertEquals(baseStr + "[{{1,2},,{5}}]", new ToStringBuilder(base).append((Object) array).toString());
+ array = null;
+ assertEquals(baseStr + "[]", new ToStringBuilder(base).append(array).toString());
+ assertEquals(baseStr + "[]", new ToStringBuilder(base).append((Object) array).toString());
+ }
+
+}
diff --git a/examples/cl2/src/test/org/apache/commons/lang/builder/SimpleToStringStyleTest.java b/examples/cl2/src/test/org/apache/commons/lang/builder/SimpleToStringStyleTest.java
new file mode 100644
index 00000000..fb9a5690
--- /dev/null
+++ b/examples/cl2/src/test/org/apache/commons/lang/builder/SimpleToStringStyleTest.java
@@ -0,0 +1,163 @@
+/* ====================================================================
+ * 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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
+ * .
+ */
+// package org.apache.commons.lang.builder
+
+package org.apache.commons.lang.builder;
+import java.util.ArrayList;
+import java.util.HashMap;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import junit.textui.TestRunner;
+/**
+ * Unit tests {@link org.apache.commons.lang.ToStringStyle}.
+ *
+ * @author Stephen Colebourne
+ * @version $Id: SimpleToStringStyleTest.java,v 1.3 2003/05/21 23:49:15 scolebourne Exp $
+ */
+public class SimpleToStringStyleTest extends TestCase {
+
+ private final Integer base = new Integer(5);
+
+ public SimpleToStringStyleTest(String name) {
+ super(name);
+ }
+
+ public static void main(String[] args) {
+ TestRunner.run(suite());
+ }
+
+ public static Test suite() {
+ TestSuite suite = new TestSuite(SimpleToStringStyleTest.class);
+ suite.setName("DefaultToStringStyle Tests");
+ return suite;
+ }
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ ToStringBuilder.setDefaultStyle(ToStringStyle.SIMPLE_STYLE);
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ ToStringBuilder.setDefaultStyle(ToStringStyle.DEFAULT_STYLE);
+ }
+
+ //----------------------------------------------------------------
+
+ public void testBlank() {
+ assertEquals("", new ToStringBuilder(base).toString());
+ }
+
+ public void testAppendSuper() {
+ assertEquals("", new ToStringBuilder(base).appendSuper("").toString());
+ assertEquals("", new ToStringBuilder(base).appendSuper("").toString());
+
+ assertEquals("hello", new ToStringBuilder(base).appendSuper("").append("a", "hello").toString());
+ assertEquals(",hello", new ToStringBuilder(base).appendSuper("").append("a", "hello").toString());
+ assertEquals("hello", new ToStringBuilder(base).appendSuper(null).append("a", "hello").toString());
+ }
+
+ public void testObject() {
+ Integer i3 = new Integer(3);
+ Integer i4 = new Integer(4);
+ assertEquals("", new ToStringBuilder(base).append((Object) null).toString());
+ assertEquals("3", new ToStringBuilder(base).append(i3).toString());
+ assertEquals("", new ToStringBuilder(base).append("a", (Object) null).toString());
+ assertEquals("3", new ToStringBuilder(base).append("a", i3).toString());
+ assertEquals("3,4", new ToStringBuilder(base).append("a", i3).append("b", i4).toString());
+ assertEquals("", new ToStringBuilder(base).append("a", i3, false).toString());
+ assertEquals("", new ToStringBuilder(base).append("a", new ArrayList(), false).toString());
+ assertEquals("[]", new ToStringBuilder(base).append("a", new ArrayList(), true).toString());
+ assertEquals("", new ToStringBuilder(base).append("a", new HashMap(), false).toString());
+ assertEquals("{}", new ToStringBuilder(base).append("a", new HashMap(), true).toString());
+ assertEquals("", new ToStringBuilder(base).append("a", (Object) new String[0], false).toString());
+ assertEquals("{}", new ToStringBuilder(base).append("a", (Object) new String[0], true).toString());
+ }
+
+ public void testLong() {
+ assertEquals("3", new ToStringBuilder(base).append(3L).toString());
+ assertEquals("3", new ToStringBuilder(base).append("a", 3L).toString());
+ assertEquals("3,4", new ToStringBuilder(base).append("a", 3L).append("b", 4L).toString());
+ }
+
+ public void testObjectArray() {
+ Object[] array = new Object[] {null, base, new int[] {3, 6}};
+ assertEquals("{,5,{3,6}}", new ToStringBuilder(base).append(array).toString());
+ assertEquals("{,5,{3,6}}", new ToStringBuilder(base).append((Object) array).toString());
+ array = null;
+ assertEquals("", new ToStringBuilder(base).append(array).toString());
+ assertEquals("", new ToStringBuilder(base).append((Object) array).toString());
+ }
+
+ public void testLongArray() {
+ long[] array = new long[] {1, 2, -3, 4};
+ assertEquals("{1,2,-3,4}", new ToStringBuilder(base).append(array).toString());
+ assertEquals("{1,2,-3,4}", new ToStringBuilder(base).append((Object) array).toString());
+ array = null;
+ assertEquals("", new ToStringBuilder(base).append(array).toString());
+ assertEquals("", new ToStringBuilder(base).append((Object) array).toString());
+ }
+
+ public void testLongArrayArray() {
+ long[][] array = new long[][] {{1, 2}, null, {5}};
+ assertEquals("{{1,2},,{5}}", new ToStringBuilder(base).append(array).toString());
+ assertEquals("{{1,2},,{5}}", new ToStringBuilder(base).append((Object) array).toString());
+ array = null;
+ assertEquals("", new ToStringBuilder(base).append(array).toString());
+ assertEquals("", new ToStringBuilder(base).append((Object) array).toString());
+ }
+
+}
diff --git a/examples/cl2/src/test/org/apache/commons/lang/builder/StandardToStringStyleTest.java b/examples/cl2/src/test/org/apache/commons/lang/builder/StandardToStringStyleTest.java
new file mode 100644
index 00000000..c6840e01
--- /dev/null
+++ b/examples/cl2/src/test/org/apache/commons/lang/builder/StandardToStringStyleTest.java
@@ -0,0 +1,179 @@
+/* ====================================================================
+ * 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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
+ * .
+ */
+// package org.apache.commons.lang.builder
+
+package org.apache.commons.lang.builder;
+import java.util.ArrayList;
+import java.util.HashMap;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import junit.textui.TestRunner;
+/**
+ * Unit tests {@link org.apache.commons.lang.ToStringStyle}.
+ *
+ * @author Stephen Colebourne
+ * @version $Id: StandardToStringStyleTest.java,v 1.3 2003/05/21 23:49:15 scolebourne Exp $
+ */
+public class StandardToStringStyleTest extends TestCase {
+
+ private final Integer base = new Integer(5);
+ private final String baseStr = "Integer";
+
+ private static final StandardToStringStyle STYLE = new StandardToStringStyle();
+
+ static {
+ STYLE.setShortClassName(true);
+ STYLE.setUseIdentityHashCode(false);
+ STYLE.setArrayStart("[");
+ STYLE.setArraySeparator(", ");
+ STYLE.setArrayEnd("]");
+ STYLE.setNullText("%NULL%");
+ STYLE.setSizeStartText("%SIZE=");
+ STYLE.setSizeEndText("%");
+ STYLE.setSummaryObjectStartText("%");
+ STYLE.setSummaryObjectEndText("%");
+ }
+
+ public StandardToStringStyleTest(String name) {
+ super(name);
+ }
+
+ public static void main(String[] args) {
+ TestRunner.run(suite());
+ }
+
+ public static Test suite() {
+ TestSuite suite = new TestSuite(StandardToStringStyleTest.class);
+ suite.setName("StandardToStringStyle Tests");
+ return suite;
+ }
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ ToStringBuilder.setDefaultStyle(STYLE);
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ ToStringBuilder.setDefaultStyle(STYLE);
+ }
+
+ //----------------------------------------------------------------
+
+ public void testBlank() {
+ assertEquals(baseStr + "[]", new ToStringBuilder(base).toString());
+ }
+
+ public void testAppendSuper() {
+ assertEquals(baseStr + "[]", new ToStringBuilder(base).appendSuper("Integer@8888[]").toString());
+ assertEquals(baseStr + "[%NULL%]", new ToStringBuilder(base).appendSuper("Integer@8888[%NULL%]").toString());
+
+ assertEquals(baseStr + "[a=hello]", new ToStringBuilder(base).appendSuper("Integer@8888[]").append("a", "hello").toString());
+ assertEquals(baseStr + "[%NULL%,a=hello]", new ToStringBuilder(base).appendSuper("Integer@8888[%NULL%]").append("a", "hello").toString());
+ assertEquals(baseStr + "[a=hello]", new ToStringBuilder(base).appendSuper(null).append("a", "hello").toString());
+ }
+
+ public void testObject() {
+ Integer i3 = new Integer(3);
+ Integer i4 = new Integer(4);
+ assertEquals(baseStr + "[%NULL%]", new ToStringBuilder(base).append((Object) null).toString());
+ assertEquals(baseStr + "[3]", new ToStringBuilder(base).append(i3).toString());
+ assertEquals(baseStr + "[a=%NULL%]", new ToStringBuilder(base).append("a", (Object) null).toString());
+ assertEquals(baseStr + "[a=3]", new ToStringBuilder(base).append("a", i3).toString());
+ assertEquals(baseStr + "[a=3,b=4]", new ToStringBuilder(base).append("a", i3).append("b", i4).toString());
+ assertEquals(baseStr + "[a=%Integer%]", new ToStringBuilder(base).append("a", i3, false).toString());
+ assertEquals(baseStr + "[a=%SIZE=0%]", new ToStringBuilder(base).append("a", new ArrayList(), false).toString());
+ assertEquals(baseStr + "[a=[]]", new ToStringBuilder(base).append("a", new ArrayList(), true).toString());
+ assertEquals(baseStr + "[a=%SIZE=0%]", new ToStringBuilder(base).append("a", new HashMap(), false).toString());
+ assertEquals(baseStr + "[a={}]", new ToStringBuilder(base).append("a", new HashMap(), true).toString());
+ assertEquals(baseStr + "[a=%SIZE=0%]", new ToStringBuilder(base).append("a", (Object) new String[0], false).toString());
+ assertEquals(baseStr + "[a=[]]", new ToStringBuilder(base).append("a", (Object) new String[0], true).toString());
+ }
+
+ public void testLong() {
+ assertEquals(baseStr + "[3]", new ToStringBuilder(base).append(3L).toString());
+ assertEquals(baseStr + "[a=3]", new ToStringBuilder(base).append("a", 3L).toString());
+ assertEquals(baseStr + "[a=3,b=4]", new ToStringBuilder(base).append("a", 3L).append("b", 4L).toString());
+ }
+
+ public void testObjectArray() {
+ Object[] array = new Object[] {null, base, new int[] {3, 6}};
+ assertEquals(baseStr + "[[%NULL%, 5, [3, 6]]]", new ToStringBuilder(base).append(array).toString());
+ assertEquals(baseStr + "[[%NULL%, 5, [3, 6]]]", new ToStringBuilder(base).append((Object) array).toString());
+ array = null;
+ assertEquals(baseStr + "[%NULL%]", new ToStringBuilder(base).append(array).toString());
+ assertEquals(baseStr + "[%NULL%]", new ToStringBuilder(base).append((Object) array).toString());
+ }
+
+ public void testLongArray() {
+ long[] array = new long[] {1, 2, -3, 4};
+ assertEquals(baseStr + "[[1, 2, -3, 4]]", new ToStringBuilder(base).append(array).toString());
+ assertEquals(baseStr + "[[1, 2, -3, 4]]", new ToStringBuilder(base).append((Object) array).toString());
+ array = null;
+ assertEquals(baseStr + "[%NULL%]", new ToStringBuilder(base).append(array).toString());
+ assertEquals(baseStr + "[%NULL%]", new ToStringBuilder(base).append((Object) array).toString());
+ }
+
+ public void testLongArrayArray() {
+ long[][] array = new long[][] {{1, 2}, null, {5}};
+ assertEquals(baseStr + "[[[1, 2], %NULL%, [5]]]", new ToStringBuilder(base).append(array).toString());
+ assertEquals(baseStr + "[[[1, 2], %NULL%, [5]]]", new ToStringBuilder(base).append((Object) array).toString());
+ array = null;
+ assertEquals(baseStr + "[%NULL%]", new ToStringBuilder(base).append(array).toString());
+ assertEquals(baseStr + "[%NULL%]", new ToStringBuilder(base).append((Object) array).toString());
+ }
+
+}
diff --git a/examples/cl2/src/test/org/apache/commons/lang/builder/ToStringBuilderTest.java b/examples/cl2/src/test/org/apache/commons/lang/builder/ToStringBuilderTest.java
new file mode 100644
index 00000000..abc4cdd7
--- /dev/null
+++ b/examples/cl2/src/test/org/apache/commons/lang/builder/ToStringBuilderTest.java
@@ -0,0 +1,843 @@
+/* ====================================================================
+ * 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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
+ * .
+ */
+// package org.apache.commons.lang.builder
+
+package org.apache.commons.lang.builder;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import junit.textui.TestRunner;
+/**
+ * Unit tests for {@link org.apache.commons.lang.ToStringBuilder}.
+ *
+ * @author Stephen Colebourne
+ * @author Gary Gregory
+ * @author Alex Chaffee
+ * @version $Id: ToStringBuilderTest.java,v 1.8 2003/06/03 20:15:32 ggregory Exp $
+ */
+public class ToStringBuilderTest extends TestCase {
+
+ private final Integer base = new Integer(5);
+ private final String baseStr = base.getClass().getName() + "@" + Integer.toHexString(System.identityHashCode(base));
+
+ public ToStringBuilderTest(String name) {
+ super(name);
+ }
+
+ public static void main(String[] args) {
+ TestRunner.run(suite());
+ }
+
+ public static Test suite() {
+ TestSuite suite = new TestSuite(ToStringBuilderTest.class);
+ suite.setName("ToStringBuilder Tests");
+ return suite;
+ }
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ //-----------------------------------------------------------------------
+
+ public void testConstructorEx1() {
+ try {
+ new ToStringBuilder(null);
+
+ } catch (IllegalArgumentException ex) {
+ return;
+ }
+ fail();
+ }
+
+ public void testConstructorEx2() {
+ try {
+ new ToStringBuilder(null, null);
+
+ } catch (IllegalArgumentException ex) {
+ try {
+ new ToStringBuilder(base, null);
+
+ } catch (Exception ex2) {
+ fail();
+ }
+ return;
+ }
+ fail();
+ }
+
+ public void testConstructorEx3() {
+ try {
+ new ToStringBuilder(null, null, null);
+
+ } catch (IllegalArgumentException ex) {
+ try {
+ new ToStringBuilder(base, null, null);
+ new ToStringBuilder(base, ToStringStyle.DEFAULT_STYLE, null);
+
+ } catch (Exception ex2) {
+ fail();
+ }
+ return;
+ }
+ fail();
+ }
+
+ public void testGetSetDefault() {
+ try {
+ ToStringBuilder.setDefaultStyle(ToStringStyle.NO_FIELD_NAMES_STYLE);
+ assertSame(ToStringStyle.NO_FIELD_NAMES_STYLE, ToStringBuilder.getDefaultStyle());
+ } finally {
+ // reset for other tests
+ ToStringBuilder.setDefaultStyle(ToStringStyle.DEFAULT_STYLE);
+ }
+ }
+
+ public void testSetDefaultEx() {
+ try {
+ ToStringBuilder.setDefaultStyle(null);
+
+ } catch (IllegalArgumentException ex) {
+ return;
+ }
+ fail();
+ }
+
+ public void testBlank() {
+ assertEquals(baseStr + "[]", new ToStringBuilder(base).toString());
+ }
+
+ /**
+ * Test wrapper for int primitive.
+ */
+ public void testReflectionInteger() {
+ assertEquals(baseStr + "[value=5]", ToStringBuilder.reflectionToString(base));
+ }
+
+ /**
+ * Test wrapper for char primitive.
+ */
+ public void testReflectionCharacter() {
+ Character c = new Character('A');
+ assertEquals(this.toBaseString(c) + "[value=A]", ToStringBuilder.reflectionToString(c));
+ }
+
+ /**
+ * Test wrapper for char boolean.
+ */
+ public void testReflectionBoolean() {
+ Boolean b;
+ b = Boolean.TRUE;
+ assertEquals(this.toBaseString(b) + "[value=true]", ToStringBuilder.reflectionToString(b));
+ b = Boolean.FALSE;
+ assertEquals(this.toBaseString(b) + "[value=false]", ToStringBuilder.reflectionToString(b));
+ }
+
+ /**
+ * Create the same toString() as Object.toString().
+ * @param o the object to create the string for.
+ * @return a String in the Object.toString format.
+ */
+ private String toBaseString(Object o) {
+ return o.getClass().getName() + "@" + Integer.toHexString(System.identityHashCode(o));
+ }
+
+ // Reflection Array tests
+
+ //
+ // Note on the following line of code repeated in the reflection array tests.
+ //
+ // assertReflectionArray("", array);
+ //
+ // The expected value is not baseStr + "[]" since array==null and is typed as Object.
+ // The null array does not carry array type information.
+ // If we added a primitive array type constructor and pile of associated methods,
+ // then type declaring type information could be carried forward. IMHO, null is null.
+ //
+ // Gary Gregory - 2003-03-12 - ggregory@seagullsw.com
+ //
+
+ public void assertReflectionArray(String expected, Object actual) {
+ if (actual == null) {
+ // Until ToStringBuilder supports null objects.
+ return;
+ }
+ assertEquals(expected, ToStringBuilder.reflectionToString(actual));
+ assertEquals(expected, ToStringBuilder.reflectionToString(actual, null));
+ assertEquals(expected, ToStringBuilder.reflectionToString(actual, null, true));
+ assertEquals(expected, ToStringBuilder.reflectionToString(actual, null, false));
+ }
+
+ public void testReflectionObjectArray() {
+ Object[] array = new Object[] { null, base, new int[] { 3, 6 } };
+ String baseStr = this.toBaseString(array);
+ assertEquals(baseStr + "[{,5,{3,6}}]", ToStringBuilder.reflectionToString(array));
+ array = null;
+ assertReflectionArray("", array);
+ this.validateEmptyReflectionRegistry();
+ }
+
+ public void testReflectionLongArray() {
+ long[] array = new long[] { 1, 2, -3, 4 };
+ String baseStr = this.toBaseString(array);
+ assertEquals(baseStr + "[{1,2,-3,4}]", ToStringBuilder.reflectionToString(array));
+ array = null;
+ assertReflectionArray("", array);
+ this.validateEmptyReflectionRegistry();
+ }
+
+ public void testReflectionIntArray() {
+ int[] array = new int[] { 1, 2, -3, 4 };
+ String baseStr = this.toBaseString(array);
+ assertEquals(baseStr + "[{1,2,-3,4}]", ToStringBuilder.reflectionToString(array));
+ array = null;
+ assertReflectionArray("", array);
+ this.validateEmptyReflectionRegistry();
+ }
+
+ public void testReflectionShortArray() {
+ short[] array = new short[] { 1, 2, -3, 4 };
+ String baseStr = this.toBaseString(array);
+ assertEquals(baseStr + "[{1,2,-3,4}]", ToStringBuilder.reflectionToString(array));
+ array = null;
+ assertReflectionArray("", array);
+ this.validateEmptyReflectionRegistry();
+ }
+
+ public void testReflectionyteArray() {
+ byte[] array = new byte[] { 1, 2, -3, 4 };
+ String baseStr = this.toBaseString(array);
+ assertEquals(baseStr + "[{1,2,-3,4}]", ToStringBuilder.reflectionToString(array));
+ array = null;
+ assertReflectionArray("", array);
+ this.validateEmptyReflectionRegistry();
+ }
+
+ public void testReflectionCharArray() {
+ char[] array = new char[] { 'A', '2', '_', 'D' };
+ String baseStr = this.toBaseString(array);
+ assertEquals(baseStr + "[{A,2,_,D}]", ToStringBuilder.reflectionToString(array));
+ array = null;
+ assertReflectionArray("", array);
+ this.validateEmptyReflectionRegistry();
+ }
+
+ public void testReflectionDoubleArray() {
+ double[] array = new double[] { 1.0, 2.9876, -3.00001, 4.3 };
+ String baseStr = this.toBaseString(array);
+ assertEquals(baseStr + "[{1.0,2.9876,-3.00001,4.3}]", ToStringBuilder.reflectionToString(array));
+ array = null;
+ assertReflectionArray("", array);
+ this.validateEmptyReflectionRegistry();
+ }
+
+ public void testReflectionFloatArray() {
+ float[] array = new float[] { 1.0f, 2.9876f, -3.00001f, 4.3f };
+ String baseStr = this.toBaseString(array);
+ assertEquals(baseStr + "[{1.0,2.9876,-3.00001,4.3}]", ToStringBuilder.reflectionToString(array));
+ array = null;
+ assertReflectionArray("", array);
+ this.validateEmptyReflectionRegistry();
+ }
+
+ public void testReflectionBooleanArray() {
+ boolean[] array = new boolean[] { true, false, false };
+ String baseStr = this.toBaseString(array);
+ assertEquals(baseStr + "[{true,false,false}]", ToStringBuilder.reflectionToString(array));
+ array = null;
+ assertReflectionArray("", array);
+ this.validateEmptyReflectionRegistry();
+ }
+
+ // Reflection Array Array tests
+
+ public void testReflectionFloatArrayArray() {
+ float[][] array = new float[][] { { 1.0f, 2.29686f }, null, { Float.NaN } };
+ String baseStr = this.toBaseString(array);
+ assertEquals(baseStr + "[{{1.0,2.29686},,{NaN}}]", ToStringBuilder.reflectionToString(array));
+ array = null;
+ assertReflectionArray("", array);
+ this.validateEmptyReflectionRegistry();
+ }
+
+
+ public void testReflectionLongArrayArray() {
+ long[][] array = new long[][] { { 1, 2 }, null, { 5 } };
+ String baseStr = this.toBaseString(array);
+ assertEquals(baseStr + "[{{1,2},,{5}}]", ToStringBuilder.reflectionToString(array));
+ array = null;
+ assertReflectionArray("", array);
+ this.validateEmptyReflectionRegistry();
+ }
+
+ public void testReflectionIntArrayArray() {
+ int[][] array = new int[][] { { 1, 2 }, null, { 5 } };
+ String baseStr = this.toBaseString(array);
+ assertEquals(baseStr + "[{{1,2},,{5}}]", ToStringBuilder.reflectionToString(array));
+ array = null;
+ assertReflectionArray("", array);
+ this.validateEmptyReflectionRegistry();
+ }
+
+ public void testReflectionhortArrayArray() {
+ short[][] array = new short[][] { { 1, 2 }, null, { 5 } };
+ String baseStr = this.toBaseString(array);
+ assertEquals(baseStr + "[{{1,2},,{5}}]", ToStringBuilder.reflectionToString(array));
+ array = null;
+ assertReflectionArray("", array);
+ this.validateEmptyReflectionRegistry();
+ }
+
+ public void testReflectionByteArrayArray() {
+ byte[][] array = new byte[][] { { 1, 2 }, null, { 5 } };
+ String baseStr = this.toBaseString(array);
+ assertEquals(baseStr + "[{{1,2},,{5}}]", ToStringBuilder.reflectionToString(array));
+ array = null;
+ assertReflectionArray("", array);
+ this.validateEmptyReflectionRegistry();
+ }
+
+ public void testReflectionCharArrayArray() {
+ char[][] array = new char[][] { { 'A', 'B' }, null, { 'p' } };
+ String baseStr = this.toBaseString(array);
+ assertEquals(baseStr + "[{{A,B},,{p}}]", ToStringBuilder.reflectionToString(array));
+ array = null;
+ assertReflectionArray("", array);
+ this.validateEmptyReflectionRegistry();
+ }
+
+ public void testReflectionDoubleArrayArray() {
+ double[][] array = new double[][] { { 1.0, 2.29686 }, null, { Double.NaN } };
+ String baseStr = this.toBaseString(array);
+ assertEquals(baseStr + "[{{1.0,2.29686},,{NaN}}]", ToStringBuilder.reflectionToString(array));
+ array = null;
+ assertReflectionArray("", array);
+ this.validateEmptyReflectionRegistry();
+ }
+
+ public void testReflectionBooleanArrayArray() {
+ boolean[][] array = new boolean[][] { { true, false }, null, { false } };
+ String baseStr = this.toBaseString(array);
+ assertEquals(baseStr + "[{{true,false},,{false}}]", ToStringBuilder.reflectionToString(array));
+ assertEquals(baseStr + "[{{true,false},,{false}}]", ToStringBuilder.reflectionToString(array));
+ array = null;
+ assertReflectionArray("", array);
+ this.validateEmptyReflectionRegistry();
+ }
+
+ // Reflection hierarchy tests
+
+ public void testReflectionHierarchyArrayList() {
+ List base = new ArrayList();
+ String baseStr = this.toBaseString(base);
+ assertEquals(baseStr + "[elementData={,,,,,,,,,},size=0,modCount=0]", ToStringBuilder.reflectionToString(base, null, true));
+ assertEquals(baseStr + "[size=0]", ToStringBuilder.reflectionToString(base, null, false));
+ this.validateEmptyReflectionRegistry();
+ }
+
+ public void testReflectionHierarchy() {
+ ReflectionTestFixtureA baseA = new ReflectionTestFixtureA();
+ String baseStr = this.toBaseString(baseA);
+ assertEquals(baseStr + "[a=a]", ToStringBuilder.reflectionToString(baseA));
+ assertEquals(baseStr + "[a=a]", ToStringBuilder.reflectionToString(baseA, null));
+ assertEquals(baseStr + "[a=a]", ToStringBuilder.reflectionToString(baseA, null, false));
+ assertEquals(baseStr + "[a=a,transientA=t]", ToStringBuilder.reflectionToString(baseA, null, true));
+ assertEquals(baseStr + "[a=a]", ToStringBuilder.reflectionToString(baseA, null, false, null));
+ assertEquals(baseStr + "[a=a]", ToStringBuilder.reflectionToString(baseA, null, false, Object.class));
+ assertEquals(baseStr + "[a=a]", ToStringBuilder.reflectionToString(baseA, null, false, List.class));
+ assertEquals(baseStr + "[a=a]", ToStringBuilder.reflectionToString(baseA, null, false, ReflectionTestFixtureA.class));
+
+ ReflectionTestFixtureB baseB = new ReflectionTestFixtureB();
+ baseStr = this.toBaseString(baseB);
+ assertEquals(baseStr + "[b=b,a=a]", ToStringBuilder.reflectionToString(baseB));
+ assertEquals(baseStr + "[b=b,a=a]", ToStringBuilder.reflectionToString(baseB));
+ assertEquals(baseStr + "[b=b,a=a]", ToStringBuilder.reflectionToString(baseB, null));
+ assertEquals(baseStr + "[b=b,a=a]", ToStringBuilder.reflectionToString(baseB, null, false));
+ assertEquals(baseStr + "[b=b,transientB=t,a=a,transientA=t]", ToStringBuilder.reflectionToString(baseB, null, true));
+ assertEquals(baseStr + "[b=b,a=a]", ToStringBuilder.reflectionToString(baseB, null, false, null));
+ assertEquals(baseStr + "[b=b,a=a]", ToStringBuilder.reflectionToString(baseB, null, false, Object.class));
+ assertEquals(baseStr + "[b=b,a=a]", ToStringBuilder.reflectionToString(baseB, null, false, List.class));
+ assertEquals(baseStr + "[b=b,a=a]", ToStringBuilder.reflectionToString(baseB, null, false, ReflectionTestFixtureA.class));
+ assertEquals(baseStr + "[b=b]", ToStringBuilder.reflectionToString(baseB, null, false, ReflectionTestFixtureB.class));
+ this.validateEmptyReflectionRegistry();
+ }
+
+ static class ReflectionTestFixtureA {
+ private char a='a';
+ private transient char transientA='t';
+ }
+
+ static class ReflectionTestFixtureB extends ReflectionTestFixtureA {
+ private char b='b';
+ private transient char transientB='t';
+ }
+
+ public void testInnerClassReflection() {
+ Outer outer = new Outer();
+ assertEquals(toBaseString(outer) + "[inner=" + toBaseString(outer.inner) + "[]]", outer.toString());
+ }
+
+ static class Outer {
+ Inner inner = new Inner();
+ class Inner {
+ public String toString() {
+ return ToStringBuilder.reflectionToString(this);
+ }
+ }
+ public String toString() {
+ return ToStringBuilder.reflectionToString(this);
+ }
+ }
+
+ // Reflection cycle tests
+
+ /**
+ * Test an array element pointing to its container.
+ */
+ public void testReflectionArrayCycle() throws Exception {
+ Object[] objects = new Object[1];
+ objects[0] = objects;
+ assertEquals(
+ this.toBaseString(objects) + "[{" + this.toBaseString(objects) + "}]",
+ ToStringBuilder.reflectionToString(objects));
+ this.validateEmptyReflectionRegistry();
+ }
+
+ /**
+ * Test an array element pointing to its container.
+ */
+ public void testReflectionArrayCycleLevel2() throws Exception {
+ Object[] objects = new Object[1];
+ Object[] objectsLevel2 = new Object[1];
+ objects[0] = objectsLevel2;
+ objectsLevel2[0] = (Object) objects;
+ assertEquals(
+ this.toBaseString(objects) + "[{{" + this.toBaseString(objects) + "}}]",
+ ToStringBuilder.reflectionToString(objects));
+ assertEquals(
+ this.toBaseString(objectsLevel2) + "[{{" + this.toBaseString(objectsLevel2) + "}}]",
+ ToStringBuilder.reflectionToString(objectsLevel2));
+ this.validateEmptyReflectionRegistry();
+ }
+
+ public void testReflectionArrayArrayCycle() throws Exception {
+ Object[][] objects = new Object[2][2];
+ objects[0][0] = objects;
+ objects[0][1] = objects;
+ objects[1][0] = objects;
+ objects[1][1] = objects;
+ String basicToString = this.toBaseString(objects);
+ assertEquals(
+ basicToString
+ + "[{{"
+ + basicToString
+ + ","
+ + basicToString
+ + "},{"
+ + basicToString
+ + ","
+ + basicToString
+ + "}}]",
+ ToStringBuilder.reflectionToString(objects));
+ this.validateEmptyReflectionRegistry();
+ }
+
+ /**
+ * A reflection test fixture.
+ */
+ static class ReflectionTestCycleA {
+ ReflectionTestCycleB b;
+
+ public String toString() {
+ return ToStringBuilder.reflectionToString(this);
+ }
+ }
+
+ /**
+ * A reflection test fixture.
+ */
+ static class ReflectionTestCycleB {
+ ReflectionTestCycleA a;
+
+ public String toString() {
+ return ToStringBuilder.reflectionToString(this);
+ }
+ }
+
+ /**
+ * A reflection test fixture.
+ */
+ static class SimpleReflectionTestFixture {
+ Object o;
+
+ public SimpleReflectionTestFixture() {
+ }
+
+ public SimpleReflectionTestFixture(Object o) {
+ this.o = o;
+ }
+
+ public String toString() {
+ return ToStringBuilder.reflectionToString(this);
+ }
+ }
+
+ /**
+ * Test an Object pointing to itself, the simplest test.
+ *
+ * @throws Exception
+ */
+ public void testSimpleReflectionObjectCycle() throws Exception {
+ SimpleReflectionTestFixture simple = new SimpleReflectionTestFixture();
+ simple.o = simple;
+ assertTrue(ReflectionToStringBuilder.getRegistry().isEmpty());
+ assertEquals(this.toBaseString(simple) + "[o=" + this.toBaseString(simple) + "]", simple.toString());
+ this.validateEmptyReflectionRegistry();
+ }
+
+ /**
+ * Test Objects pointing to each other.
+ *
+ * @throws Exception
+ */
+ public void testReflectionObjectCycle() throws Exception {
+ ReflectionTestCycleA a = new ReflectionTestCycleA();
+ ReflectionTestCycleB b = new ReflectionTestCycleB();
+ a.b = b;
+ b.a = a;
+ assertEquals(
+ this.toBaseString(a) + "[b=" + this.toBaseString(b) + "[a=" + this.toBaseString(a) + "]]",
+ a.toString());
+ this.validateEmptyReflectionRegistry();
+ }
+
+ /**
+ * Test a nasty combination of arrays and Objects pointing to each other.
+ * objects[0] -> SimpleReflectionTestFixture[ o -> objects ]
+ *
+ * @throws Exception
+ */
+ public void testReflectionArrayAndObjectCycle() throws Exception {
+ Object[] objects = new Object[1];
+ SimpleReflectionTestFixture simple = new SimpleReflectionTestFixture(objects);
+ objects[0] = (Object) simple;
+ assertEquals(
+ this.toBaseString(objects)
+ + "[{"
+ + this.toBaseString(simple)
+ + "[o="
+ + this.toBaseString(objects)
+ + "]"
+ + "}]",
+ ToStringBuilder.reflectionToString(objects));
+ assertEquals(
+ this.toBaseString(simple)
+ + "[o={"
+ + this.toBaseString(simple)
+ + "}]",
+ ToStringBuilder.reflectionToString(simple));
+ this.validateEmptyReflectionRegistry();
+ }
+
+ void validateEmptyReflectionRegistry() {
+ assertTrue(ReflectionToStringBuilder.getRegistry().isEmpty());
+ }
+ // End: Reflection cycle tests
+
+ public void testAppendSuper() {
+ assertEquals(baseStr + "[]", new ToStringBuilder(base).appendSuper("Integer@8888[]").toString());
+ assertEquals(baseStr + "[]", new ToStringBuilder(base).appendSuper("Integer@8888[]").toString());
+
+ assertEquals(baseStr + "[a=hello]", new ToStringBuilder(base).appendSuper("Integer@8888[]").append("a", "hello").toString());
+ assertEquals(baseStr + "[,a=hello]", new ToStringBuilder(base).appendSuper("Integer@8888[]").append("a", "hello").toString());
+ assertEquals(baseStr + "[a=hello]", new ToStringBuilder(base).appendSuper(null).append("a", "hello").toString());
+ }
+
+ public void testAppendToString() {
+ assertEquals(baseStr + "[]", new ToStringBuilder(base).appendToString("Integer@8888[]").toString());
+ assertEquals(baseStr + "[]", new ToStringBuilder(base).appendToString("Integer@8888[]").toString());
+
+ assertEquals(baseStr + "[a=hello]", new ToStringBuilder(base).appendToString("Integer@8888[]").append("a", "hello").toString());
+ assertEquals(baseStr + "[,a=hello]", new ToStringBuilder(base).appendToString("Integer@8888[]").append("a", "hello").toString());
+ assertEquals(baseStr + "[a=hello]", new ToStringBuilder(base).appendToString(null).append("a", "hello").toString());
+ }
+
+ public void testObject() {
+ Integer i3 = new Integer(3);
+ Integer i4 = new Integer(4);
+ assertEquals(baseStr + "[]", new ToStringBuilder(base).append((Object) null).toString());
+ assertEquals(baseStr + "[3]", new ToStringBuilder(base).append(i3).toString());
+ assertEquals(baseStr + "[a=]", new ToStringBuilder(base).append("a", (Object) null).toString());
+ assertEquals(baseStr + "[a=3]", new ToStringBuilder(base).append("a", i3).toString());
+ assertEquals(baseStr + "[a=3,b=4]", new ToStringBuilder(base).append("a", i3).append("b", i4).toString());
+ assertEquals(baseStr + "[a=]", new ToStringBuilder(base).append("a", i3, false).toString());
+ assertEquals(baseStr + "[a=]", new ToStringBuilder(base).append("a", new ArrayList(), false).toString());
+ assertEquals(baseStr + "[a=[]]", new ToStringBuilder(base).append("a", new ArrayList(), true).toString());
+ assertEquals(baseStr + "[a=]", new ToStringBuilder(base).append("a", new HashMap(), false).toString());
+ assertEquals(baseStr + "[a={}]", new ToStringBuilder(base).append("a", new HashMap(), true).toString());
+ assertEquals(baseStr + "[a=]", new ToStringBuilder(base).append("a", (Object) new String[0], false).toString());
+ assertEquals(baseStr + "[a={}]", new ToStringBuilder(base).append("a", (Object) new String[0], true).toString());
+ }
+
+ public void testLong() {
+ assertEquals(baseStr + "[3]", new ToStringBuilder(base).append(3L).toString());
+ assertEquals(baseStr + "[a=3]", new ToStringBuilder(base).append("a", 3L).toString());
+ assertEquals(baseStr + "[a=3,b=4]", new ToStringBuilder(base).append("a", 3L).append("b", 4L).toString());
+ }
+
+ public void testInt() {
+ assertEquals(baseStr + "[3]", new ToStringBuilder(base).append((int) 3).toString());
+ assertEquals(baseStr + "[a=3]", new ToStringBuilder(base).append("a", (int) 3).toString());
+ assertEquals(baseStr + "[a=3,b=4]", new ToStringBuilder(base).append("a", (int) 3).append("b", (int) 4).toString());
+ }
+
+ public void testShort() {
+ assertEquals(baseStr + "[3]", new ToStringBuilder(base).append((short) 3).toString());
+ assertEquals(baseStr + "[a=3]", new ToStringBuilder(base).append("a", (short) 3).toString());
+ assertEquals(baseStr + "[a=3,b=4]", new ToStringBuilder(base).append("a", (short) 3).append("b", (short) 4).toString());
+ }
+
+ public void testChar() {
+ assertEquals(baseStr + "[A]", new ToStringBuilder(base).append((char) 65).toString());
+ assertEquals(baseStr + "[a=A]", new ToStringBuilder(base).append("a", (char) 65).toString());
+ assertEquals(baseStr + "[a=A,b=B]", new ToStringBuilder(base).append("a", (char) 65).append("b", (char) 66).toString());
+ }
+
+ public void testByte() {
+ assertEquals(baseStr + "[3]", new ToStringBuilder(base).append((byte) 3).toString());
+ assertEquals(baseStr + "[a=3]", new ToStringBuilder(base).append("a", (byte) 3).toString());
+ assertEquals(baseStr + "[a=3,b=4]", new ToStringBuilder(base).append("a", (byte) 3).append("b", (byte) 4).toString());
+ }
+
+ public void testDouble() {
+ assertEquals(baseStr + "[3.2]", new ToStringBuilder(base).append((double) 3.2).toString());
+ assertEquals(baseStr + "[a=3.2]", new ToStringBuilder(base).append("a", (double) 3.2).toString());
+ assertEquals(baseStr + "[a=3.2,b=4.3]", new ToStringBuilder(base).append("a", (double) 3.2).append("b", (double) 4.3).toString());
+ }
+
+ public void testFloat() {
+ assertEquals(baseStr + "[3.2]", new ToStringBuilder(base).append((float) 3.2).toString());
+ assertEquals(baseStr + "[a=3.2]", new ToStringBuilder(base).append("a", (float) 3.2).toString());
+ assertEquals(baseStr + "[a=3.2,b=4.3]", new ToStringBuilder(base).append("a", (float) 3.2).append("b", (float) 4.3).toString());
+ }
+
+ public void testBoolean() {
+ assertEquals(baseStr + "[true]", new ToStringBuilder(base).append(true).toString());
+ assertEquals(baseStr + "[a=true]", new ToStringBuilder(base).append("a", true).toString());
+ assertEquals(baseStr + "[a=true,b=false]", new ToStringBuilder(base).append("a", true).append("b", false).toString());
+ }
+
+
+ public void testObjectArray() {
+ Object[] array = new Object[] {null, base, new int[] {3, 6}};
+ assertEquals(baseStr + "[{,5,{3,6}}]", new ToStringBuilder(base).append(array).toString());
+ assertEquals(baseStr + "[{,5,{3,6}}]", new ToStringBuilder(base).append((Object) array).toString());
+ array = null;
+ assertEquals(baseStr + "[]", new ToStringBuilder(base).append(array).toString());
+ assertEquals(baseStr + "[]", new ToStringBuilder(base).append((Object) array).toString());
+ }
+
+ public void testLongArray() {
+ long[] array = new long[] {1, 2, -3, 4};
+ assertEquals(baseStr + "[{1,2,-3,4}]", new ToStringBuilder(base).append(array).toString());
+ assertEquals(baseStr + "[{1,2,-3,4}]", new ToStringBuilder(base).append((Object) array).toString());
+ array = null;
+ assertEquals(baseStr + "[]", new ToStringBuilder(base).append(array).toString());
+ assertEquals(baseStr + "[]", new ToStringBuilder(base).append((Object) array).toString());
+ }
+
+ public void testIntArray() {
+ int[] array = new int[] {1, 2, -3, 4};
+ assertEquals(baseStr + "[{1,2,-3,4}]", new ToStringBuilder(base).append(array).toString());
+ assertEquals(baseStr + "[{1,2,-3,4}]", new ToStringBuilder(base).append((Object) array).toString());
+ array = null;
+ assertEquals(baseStr + "[]", new ToStringBuilder(base).append(array).toString());
+ assertEquals(baseStr + "[]", new ToStringBuilder(base).append((Object) array).toString());
+ }
+
+ public void testShortArray() {
+ short[] array = new short[] {1, 2, -3, 4};
+ assertEquals(baseStr + "[{1,2,-3,4}]", new ToStringBuilder(base).append(array).toString());
+ assertEquals(baseStr + "[{1,2,-3,4}]", new ToStringBuilder(base).append((Object) array).toString());
+ array = null;
+ assertEquals(baseStr + "[]", new ToStringBuilder(base).append(array).toString());
+ assertEquals(baseStr + "[]", new ToStringBuilder(base).append((Object) array).toString());
+ }
+
+ public void testByteArray() {
+ byte[] array = new byte[] {1, 2, -3, 4};
+ assertEquals(baseStr + "[{1,2,-3,4}]", new ToStringBuilder(base).append(array).toString());
+ assertEquals(baseStr + "[{1,2,-3,4}]", new ToStringBuilder(base).append((Object) array).toString());
+ array = null;
+ assertEquals(baseStr + "[]", new ToStringBuilder(base).append(array).toString());
+ assertEquals(baseStr + "[]", new ToStringBuilder(base).append((Object) array).toString());
+ }
+
+ public void testCharArray() {
+ char[] array = new char[] {'A', '2', '_', 'D'};
+ assertEquals(baseStr + "[{A,2,_,D}]", new ToStringBuilder(base).append(array).toString());
+ assertEquals(baseStr + "[{A,2,_,D}]", new ToStringBuilder(base).append((Object) array).toString());
+ array = null;
+ assertEquals(baseStr + "[]", new ToStringBuilder(base).append(array).toString());
+ assertEquals(baseStr + "[]", new ToStringBuilder(base).append((Object) array).toString());
+ }
+
+ public void testDoubleArray() {
+ double[] array = new double[] {1.0, 2.9876, -3.00001, 4.3};
+ assertEquals(baseStr + "[{1.0,2.9876,-3.00001,4.3}]", new ToStringBuilder(base).append(array).toString());
+ assertEquals(baseStr + "[{1.0,2.9876,-3.00001,4.3}]", new ToStringBuilder(base).append((Object) array).toString());
+ array = null;
+ assertEquals(baseStr + "[]", new ToStringBuilder(base).append(array).toString());
+ assertEquals(baseStr + "[]", new ToStringBuilder(base).append((Object) array).toString());
+ }
+
+ public void testFloatArray() {
+ float[] array = new float[] {1.0f, 2.9876f, -3.00001f, 4.3f};
+ assertEquals(baseStr + "[{1.0,2.9876,-3.00001,4.3}]", new ToStringBuilder(base).append(array).toString());
+ assertEquals(baseStr + "[{1.0,2.9876,-3.00001,4.3}]", new ToStringBuilder(base).append((Object) array).toString());
+ array = null;
+ assertEquals(baseStr + "[]", new ToStringBuilder(base).append(array).toString());
+ assertEquals(baseStr + "[]", new ToStringBuilder(base).append((Object) array).toString());
+ }
+
+ public void testBooleanArray() {
+ boolean[] array = new boolean[] {true, false, false};
+ assertEquals(baseStr + "[{true,false,false}]", new ToStringBuilder(base).append(array).toString());
+ assertEquals(baseStr + "[{true,false,false}]", new ToStringBuilder(base).append((Object) array).toString());
+ array = null;
+ assertEquals(baseStr + "[]", new ToStringBuilder(base).append(array).toString());
+ assertEquals(baseStr + "[]", new ToStringBuilder(base).append((Object) array).toString());
+ }
+
+ public void testLongArrayArray() {
+ long[][] array = new long[][] {{1, 2}, null, {5}};
+ assertEquals(baseStr + "[{{1,2},,{5}}]", new ToStringBuilder(base).append(array).toString());
+ assertEquals(baseStr + "[{{1,2},,{5}}]", new ToStringBuilder(base).append((Object) array).toString());
+ array = null;
+ assertEquals(baseStr + "[]", new ToStringBuilder(base).append(array).toString());
+ assertEquals(baseStr + "[]", new ToStringBuilder(base).append((Object) array).toString());
+ }
+
+ public void testIntArrayArray() {
+ int[][] array = new int[][] {{1, 2}, null, {5}};
+ assertEquals(baseStr + "[{{1,2},,{5}}]", new ToStringBuilder(base).append(array).toString());
+ assertEquals(baseStr + "[{{1,2},,{5}}]", new ToStringBuilder(base).append((Object) array).toString());
+ array = null;
+ assertEquals(baseStr + "[]", new ToStringBuilder(base).append(array).toString());
+ assertEquals(baseStr + "[]", new ToStringBuilder(base).append((Object) array).toString());
+ }
+
+ public void testShortArrayArray() {
+ short[][] array = new short[][] {{1, 2}, null, {5}};
+ assertEquals(baseStr + "[{{1,2},,{5}}]", new ToStringBuilder(base).append(array).toString());
+ assertEquals(baseStr + "[{{1,2},,{5}}]", new ToStringBuilder(base).append((Object) array).toString());
+ array = null;
+ assertEquals(baseStr + "[]", new ToStringBuilder(base).append(array).toString());
+ assertEquals(baseStr + "[]", new ToStringBuilder(base).append((Object) array).toString());
+ }
+
+ public void testByteArrayArray() {
+ byte[][] array = new byte[][] {{1, 2}, null, {5}};
+ assertEquals(baseStr + "[{{1,2},,{5}}]", new ToStringBuilder(base).append(array).toString());
+ assertEquals(baseStr + "[{{1,2},,{5}}]", new ToStringBuilder(base).append((Object) array).toString());
+ array = null;
+ assertEquals(baseStr + "[]", new ToStringBuilder(base).append(array).toString());
+ assertEquals(baseStr + "[]", new ToStringBuilder(base).append((Object) array).toString());
+ }
+
+ public void testCharArrayArray() {
+ char[][] array = new char[][] {{'A', 'B'}, null, {'p'}};
+ assertEquals(baseStr + "[{{A,B},,{p}}]", new ToStringBuilder(base).append(array).toString());
+ assertEquals(baseStr + "[{{A,B},,{p}}]", new ToStringBuilder(base).append((Object) array).toString());
+ array = null;
+ assertEquals(baseStr + "[]", new ToStringBuilder(base).append(array).toString());
+ assertEquals(baseStr + "[]", new ToStringBuilder(base).append((Object) array).toString());
+ }
+
+ public void testDoubleArrayArray() {
+ double[][] array = new double[][] {{1.0, 2.29686}, null, {Double.NaN}};
+ assertEquals(baseStr + "[{{1.0,2.29686},,{NaN}}]", new ToStringBuilder(base).append(array).toString());
+ assertEquals(baseStr + "[{{1.0,2.29686},,{NaN}}]", new ToStringBuilder(base).append((Object) array).toString());
+ array = null;
+ assertEquals(baseStr + "[]", new ToStringBuilder(base).append(array).toString());
+ assertEquals(baseStr + "[]", new ToStringBuilder(base).append((Object) array).toString());
+ }
+
+ public void testFloatArrayArray() {
+ float[][] array = new float[][] {{1.0f, 2.29686f}, null, {Float.NaN}};
+ assertEquals(baseStr + "[{{1.0,2.29686},,{NaN}}]", new ToStringBuilder(base).append(array).toString());
+ assertEquals(baseStr + "[{{1.0,2.29686},,{NaN}}]", new ToStringBuilder(base).append((Object) array).toString());
+ array = null;
+ assertEquals(baseStr + "[]", new ToStringBuilder(base).append(array).toString());
+ assertEquals(baseStr + "[]", new ToStringBuilder(base).append((Object) array).toString());
+ }
+
+ public void testBooleanArrayArray() {
+ boolean[][] array = new boolean[][] {{true, false}, null, {false}};
+ assertEquals(baseStr + "[{{true,false},,{false}}]", new ToStringBuilder(base).append(array).toString());
+ assertEquals(baseStr + "[{{true,false},,{false}}]", new ToStringBuilder(base).append((Object) array).toString());
+ array = null;
+ assertEquals(baseStr + "[]", new ToStringBuilder(base).append(array).toString());
+ assertEquals(baseStr + "[]", new ToStringBuilder(base).append((Object) array).toString());
+ }
+
+}
diff --git a/examples/cl2/src/test/org/apache/commons/lang/enums/Broken1Enum.java b/examples/cl2/src/test/org/apache/commons/lang/enums/Broken1Enum.java
new file mode 100644
index 00000000..59c250ed
--- /dev/null
+++ b/examples/cl2/src/test/org/apache/commons/lang/enums/Broken1Enum.java
@@ -0,0 +1,90 @@
+/* ====================================================================
+ * 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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
+ * .
+ */
+package org.apache.commons.lang.enums;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Broken color enumeration.
+ *
+ * @author Stephen Colebourne
+ * @version $Id: Broken1Enum.java,v 1.2 2003/05/22 22:00:06 scolebourne Exp $
+ */
+public final class Broken1Enum extends Enum {
+ public static final Broken1Enum RED = new Broken1Enum("Red");
+ public static final Broken1Enum GREEN = new Broken1Enum("Green");
+ public static final Broken1Enum GREENISH = new Broken1Enum("Green"); // duplicate not allowed
+
+ private Broken1Enum(String color) {
+ super(color);
+ }
+
+ public static Broken1Enum getEnum(String color) {
+ return (Broken1Enum) getEnum(Broken1Enum.class, color);
+ }
+
+ public static Map getEnumMap() {
+ return getEnumMap(Broken1Enum.class);
+ }
+
+ public static List getEnumList() {
+ return getEnumList(Broken1Enum.class);
+ }
+
+ public static Iterator iterator() {
+ return iterator(Broken1Enum.class);
+ }
+}
diff --git a/examples/cl2/src/test/org/apache/commons/lang/enums/Broken2Enum.java b/examples/cl2/src/test/org/apache/commons/lang/enums/Broken2Enum.java
new file mode 100644
index 00000000..640f1f53
--- /dev/null
+++ b/examples/cl2/src/test/org/apache/commons/lang/enums/Broken2Enum.java
@@ -0,0 +1,90 @@
+/* ====================================================================
+ * 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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
+ * .
+ */
+package org.apache.commons.lang.enums;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Broken color enumeration.
+ *
+ * @author Stephen Colebourne
+ * @version $Id: Broken2Enum.java,v 1.2 2003/05/22 22:00:06 scolebourne Exp $
+ */
+public final class Broken2Enum extends Enum {
+ public static final Broken2Enum RED = new Broken2Enum("Red");
+ public static final Broken2Enum GREEN = new Broken2Enum("Green");
+ public static final Broken2Enum BLUE = new Broken2Enum(""); // blank not allowed
+
+ private Broken2Enum(String color) {
+ super(color);
+ }
+
+ public static Broken2Enum getEnum(String color) {
+ return (Broken2Enum) getEnum(Broken2Enum.class, color);
+ }
+
+ public static Map getEnumMap() {
+ return getEnumMap(Broken2Enum.class);
+ }
+
+ public static List getEnumList() {
+ return getEnumList(Broken2Enum.class);
+ }
+
+ public static Iterator iterator() {
+ return iterator(Broken2Enum.class);
+ }
+}
diff --git a/examples/cl2/src/test/org/apache/commons/lang/enums/Broken3Enum.java b/examples/cl2/src/test/org/apache/commons/lang/enums/Broken3Enum.java
new file mode 100644
index 00000000..00df1948
--- /dev/null
+++ b/examples/cl2/src/test/org/apache/commons/lang/enums/Broken3Enum.java
@@ -0,0 +1,90 @@
+/* ====================================================================
+ * 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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
+ * .
+ */
+package org.apache.commons.lang.enums;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Broken color enumeration.
+ *
+ * @author Stephen Colebourne
+ * @version $Id: Broken3Enum.java,v 1.2 2003/05/22 22:00:06 scolebourne Exp $
+ */
+public final class Broken3Enum extends Enum {
+ public static final Broken3Enum RED = new Broken3Enum("Red");
+ public static final Broken3Enum GREEN = new Broken3Enum("Green");
+ public static final Broken3Enum BLUE = new Broken3Enum(null); // null not allowed
+
+ private Broken3Enum(String color) {
+ super(color);
+ }
+
+ public static Broken3Enum getEnum(String color) {
+ return (Broken3Enum) getEnum(Broken3Enum.class, color);
+ }
+
+ public static Map getEnumMap() {
+ return getEnumMap(Broken3Enum.class);
+ }
+
+ public static List getEnumList() {
+ return getEnumList(Broken3Enum.class);
+ }
+
+ public static Iterator iterator() {
+ return iterator(Broken3Enum.class);
+ }
+}
diff --git a/examples/cl2/src/test/org/apache/commons/lang/enums/ColorEnum.java b/examples/cl2/src/test/org/apache/commons/lang/enums/ColorEnum.java
new file mode 100644
index 00000000..08176465
--- /dev/null
+++ b/examples/cl2/src/test/org/apache/commons/lang/enums/ColorEnum.java
@@ -0,0 +1,91 @@
+/* ====================================================================
+ * 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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
+ * .
+ */
+package org.apache.commons.lang.enums;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Color enumeration.
+ *
+ * @author Stephen Colebourne
+ * @version $Id: ColorEnum.java,v 1.2 2003/05/22 22:00:06 scolebourne Exp $
+ */
+
+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);
+ }
+}
diff --git a/examples/cl2/src/test/org/apache/commons/lang/enums/EnumTest.java b/examples/cl2/src/test/org/apache/commons/lang/enums/EnumTest.java
new file mode 100644
index 00000000..563d55fa
--- /dev/null
+++ b/examples/cl2/src/test/org/apache/commons/lang/enums/EnumTest.java
@@ -0,0 +1,353 @@
+/* ====================================================================
+ * 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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
+ * .
+ */
+package org.apache.commons.lang.enums;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+import org.apache.commons.lang.SerializationUtils;
+
+/**
+ * Test cases for the {@link Enum} class.
+ *
+ * @author Stephen Colebourne
+ * @version $Id: EnumTest.java,v 1.7 2003/05/22 22:00:06 scolebourne Exp $
+ */
+
+public final class EnumTest extends TestCase {
+
+ public EnumTest(String name) {
+ super(name);
+ }
+
+ public void setUp() {
+ }
+
+ public static Test suite() {
+ TestSuite suite = new TestSuite(EnumTest.class);
+ suite.setName("Enum Tests");
+ return suite;
+ }
+
+ public void testName() {
+ assertEquals("Red", ColorEnum.RED.getName());
+ assertEquals("Green", ColorEnum.GREEN.getName());
+ assertEquals("Blue", ColorEnum.BLUE.getName());
+ }
+
+ public void testCompareTo() {
+ assertTrue(ColorEnum.BLUE.compareTo(ColorEnum.BLUE) == 0);
+ assertTrue(ColorEnum.RED.compareTo(ColorEnum.BLUE) > 0);
+ assertTrue(ColorEnum.BLUE.compareTo(ColorEnum.RED) < 0);
+ }
+
+ public void testEquals() {
+ assertSame(ColorEnum.RED, ColorEnum.RED);
+ assertSame(ColorEnum.getEnum("Red"), ColorEnum.RED);
+ }
+
+ public void testToString() {
+ assertEquals("ColorEnum[Red]", ColorEnum.RED.toString());
+ }
+
+ public void testIterator() {
+ Iterator it = ColorEnum.iterator();
+ assertSame(ColorEnum.RED, it.next());
+ assertSame(ColorEnum.GREEN, it.next());
+ assertSame(ColorEnum.BLUE, it.next());
+ }
+
+ public void testList() {
+ List list = ColorEnum.getEnumList();
+
+ assertNotNull(list);
+
+ assertEquals( list.size(),
+ ColorEnum.getEnumMap().keySet().size());
+
+ Iterator it = list.iterator();
+ assertSame(ColorEnum.RED, it.next());
+ assertSame(ColorEnum.GREEN, it.next());
+ assertSame(ColorEnum.BLUE, it.next());
+ }
+
+ public void testMap() {
+ Map map = ColorEnum.getEnumMap();
+
+ assertNotNull(map);
+
+ assertEquals( map.keySet().size(),
+ ColorEnum.getEnumList().size());
+
+ assertTrue(map.containsValue(ColorEnum.RED));
+ assertTrue(map.containsValue(ColorEnum.GREEN));
+ assertTrue(map.containsValue(ColorEnum.BLUE));
+ assertSame(ColorEnum.RED, map.get("Red"));
+ assertSame(ColorEnum.GREEN, map.get("Green"));
+ assertSame(ColorEnum.BLUE, map.get("Blue"));
+ }
+
+ public void testGet() {
+ assertSame(ColorEnum.RED, ColorEnum.getEnum("Red"));
+ assertSame(ColorEnum.GREEN, ColorEnum.getEnum("Green"));
+ assertSame(ColorEnum.BLUE, ColorEnum.getEnum("Blue"));
+ assertSame(null, ColorEnum.getEnum("Pink"));
+ }
+
+ public void testSerialization() {
+ assertSame(ColorEnum.RED, SerializationUtils.clone(ColorEnum.RED));
+ assertSame(ColorEnum.GREEN, SerializationUtils.clone(ColorEnum.GREEN));
+ assertSame(ColorEnum.BLUE, SerializationUtils.clone(ColorEnum.BLUE));
+ }
+
+ public void testBroken1() {
+ try {
+ Broken1Enum.RED.getName();
+ fail();
+ } catch (ExceptionInInitializerError ex) {
+ assertTrue(ex.getException() instanceof IllegalArgumentException);
+ }
+ }
+
+ public void testBroken2() {
+ try {
+ Broken2Enum.RED.getName();
+ fail();
+ } catch (ExceptionInInitializerError ex) {
+ assertTrue(ex.getException() instanceof IllegalArgumentException);
+ }
+ }
+
+ public void testBroken3() {
+ try {
+ Broken3Enum.RED.getName();
+ fail();
+ } catch (ExceptionInInitializerError ex) {
+ assertTrue(ex.getException() instanceof IllegalArgumentException);
+ }
+ }
+
+ public void testOperationGet() {
+ assertSame(OperationEnum.PLUS, OperationEnum.getEnum("Plus"));
+ assertSame(OperationEnum.MINUS, OperationEnum.getEnum("Minus"));
+ assertSame(null, OperationEnum.getEnum("Pink"));
+ }
+
+ public void testOperationSerialization() {
+ assertSame(OperationEnum.PLUS, SerializationUtils.clone(OperationEnum.PLUS));
+ assertSame(OperationEnum.MINUS, SerializationUtils.clone(OperationEnum.MINUS));
+ }
+
+ public void testOperationToString() {
+ assertEquals("OperationEnum[Plus]", OperationEnum.PLUS.toString());
+ }
+
+ public void testOperationList() {
+ List list = OperationEnum.getEnumList();
+ assertNotNull(list);
+ assertEquals(2, list.size());
+ assertEquals(list.size(), OperationEnum.getEnumMap().keySet().size());
+
+ Iterator it = list.iterator();
+ assertSame(OperationEnum.PLUS, it.next());
+ assertSame(OperationEnum.MINUS, it.next());
+ }
+
+ public void testOperationMap() {
+ Map map = OperationEnum.getEnumMap();
+ assertNotNull(map);
+ assertEquals(map.keySet().size(), OperationEnum.getEnumList().size());
+
+ assertTrue(map.containsValue(OperationEnum.PLUS));
+ assertTrue(map.containsValue(OperationEnum.MINUS));
+ assertSame(OperationEnum.PLUS, map.get("Plus"));
+ assertSame(OperationEnum.MINUS, map.get("Minus"));
+ }
+
+ public void testOperationCalculation() {
+ assertEquals(3, OperationEnum.PLUS.eval(1, 2));
+ assertEquals(-1, OperationEnum.MINUS.eval(1, 2));
+ }
+
+ //-----------------------------------------------------------------------
+ public void testExtended1Get() {
+ assertSame(Extended1Enum.ALPHA, Extended1Enum.getEnum("Alpha"));
+ assertSame(Extended1Enum.BETA, Extended1Enum.getEnum("Beta"));
+ assertSame(null, Extended1Enum.getEnum("Gamma"));
+ assertSame(null, Extended1Enum.getEnum("Delta"));
+ }
+
+ public void testExtended2Get() {
+ assertSame(Extended1Enum.ALPHA, Extended2Enum.ALPHA);
+ assertSame(Extended1Enum.BETA, Extended2Enum.BETA);
+
+ assertSame(Extended2Enum.ALPHA, Extended2Enum.getEnum("Alpha"));
+ assertSame(Extended2Enum.BETA, Extended2Enum.getEnum("Beta"));
+ assertSame(Extended2Enum.GAMMA, Extended2Enum.getEnum("Gamma"));
+ assertSame(null, Extended2Enum.getEnum("Delta"));
+ }
+
+ public void testExtended3Get() {
+ assertSame(Extended2Enum.ALPHA, Extended3Enum.ALPHA);
+ assertSame(Extended2Enum.BETA, Extended3Enum.BETA);
+ assertSame(Extended2Enum.GAMMA, Extended3Enum.GAMMA);
+
+ assertSame(Extended3Enum.ALPHA, Extended3Enum.getEnum("Alpha"));
+ assertSame(Extended3Enum.BETA, Extended3Enum.getEnum("Beta"));
+ assertSame(Extended3Enum.GAMMA, Extended3Enum.getEnum("Gamma"));
+ assertSame(Extended3Enum.DELTA, Extended3Enum.getEnum("Delta"));
+ }
+
+ public void testExtendedSerialization() {
+ assertSame(Extended1Enum.ALPHA, SerializationUtils.clone(Extended1Enum.ALPHA));
+ assertSame(Extended1Enum.BETA, SerializationUtils.clone(Extended1Enum.BETA));
+ assertSame(Extended2Enum.GAMMA, SerializationUtils.clone(Extended2Enum.GAMMA));
+ assertSame(Extended3Enum.DELTA, SerializationUtils.clone(Extended3Enum.DELTA));
+ }
+
+ public void testExtendedToString() {
+ assertEquals("Extended1Enum[Alpha]", Extended1Enum.ALPHA.toString());
+ assertEquals("Extended1Enum[Beta]", Extended1Enum.BETA.toString());
+
+ assertEquals("Extended1Enum[Alpha]", Extended2Enum.ALPHA.toString());
+ assertEquals("Extended1Enum[Beta]", Extended2Enum.BETA.toString());
+ assertEquals("Extended2Enum[Gamma]", Extended2Enum.GAMMA.toString());
+
+ assertEquals("Extended1Enum[Alpha]", Extended3Enum.ALPHA.toString());
+ assertEquals("Extended1Enum[Beta]", Extended3Enum.BETA.toString());
+ assertEquals("Extended2Enum[Gamma]", Extended3Enum.GAMMA.toString());
+ assertEquals("Extended3Enum[Delta]", Extended3Enum.DELTA.toString());
+ }
+
+ public void testExtended1List() {
+ List list = Extended1Enum.getEnumList();
+ assertNotNull(list);
+ assertEquals(2, list.size());
+ assertEquals(list.size(), Extended1Enum.getEnumMap().keySet().size());
+
+ Iterator it = list.iterator();
+ assertSame(Extended1Enum.ALPHA, it.next());
+ assertSame(Extended1Enum.BETA, it.next());
+ }
+
+ public void testExtended2List() {
+ List list = Extended2Enum.getEnumList();
+ assertNotNull(list);
+ assertEquals(3, list.size());
+ assertEquals(list.size(), Extended2Enum.getEnumMap().keySet().size());
+
+ Iterator it = list.iterator();
+ assertSame(Extended2Enum.ALPHA, it.next());
+ assertSame(Extended2Enum.BETA, it.next());
+ assertSame(Extended2Enum.GAMMA, it.next());
+ }
+
+ public void testExtended3List() {
+ List list = Extended3Enum.getEnumList();
+ assertNotNull(list);
+ assertEquals(4, list.size());
+ assertEquals(list.size(), Extended3Enum.getEnumMap().keySet().size());
+
+ Iterator it = list.iterator();
+ assertSame(Extended3Enum.ALPHA, it.next());
+ assertSame(Extended3Enum.BETA, it.next());
+ assertSame(Extended3Enum.GAMMA, it.next());
+ assertSame(Extended3Enum.DELTA, it.next());
+ }
+
+ public void testExtended1Map() {
+ Map map = Extended1Enum.getEnumMap();
+ assertNotNull(map);
+ assertEquals(map.keySet().size(), Extended1Enum.getEnumList().size());
+
+ assertTrue(map.containsValue(Extended1Enum.ALPHA));
+ assertTrue(map.containsValue(Extended1Enum.BETA));
+ assertSame(Extended1Enum.ALPHA, map.get("Alpha"));
+ assertSame(Extended1Enum.BETA, map.get("Beta"));
+ }
+
+ public void testExtended2Map() {
+ Map map = Extended2Enum.getEnumMap();
+ assertNotNull(map);
+ assertEquals(map.keySet().size(), Extended2Enum.getEnumList().size());
+
+ assertTrue(map.containsValue(Extended2Enum.ALPHA));
+ assertTrue(map.containsValue(Extended2Enum.BETA));
+ assertTrue(map.containsValue(Extended2Enum.GAMMA));
+ assertSame(Extended2Enum.ALPHA, map.get("Alpha"));
+ assertSame(Extended2Enum.BETA, map.get("Beta"));
+ assertSame(Extended2Enum.GAMMA, map.get("Gamma"));
+ }
+
+ public void testExtended3Map() {
+ Map map = Extended3Enum.getEnumMap();
+ assertNotNull(map);
+ assertEquals(map.keySet().size(), Extended3Enum.getEnumList().size());
+
+ assertTrue(map.containsValue(Extended3Enum.ALPHA));
+ assertTrue(map.containsValue(Extended3Enum.BETA));
+ assertTrue(map.containsValue(Extended3Enum.GAMMA));
+ assertTrue(map.containsValue(Extended3Enum.DELTA));
+ assertSame(Extended3Enum.ALPHA, map.get("Alpha"));
+ assertSame(Extended3Enum.BETA, map.get("Beta"));
+ assertSame(Extended3Enum.GAMMA, map.get("Gamma"));
+ assertSame(Extended3Enum.DELTA, map.get("Delta"));
+ }
+
+}
diff --git a/examples/cl2/src/test/org/apache/commons/lang/enums/EnumTestSuite.java b/examples/cl2/src/test/org/apache/commons/lang/enums/EnumTestSuite.java
new file mode 100644
index 00000000..233ce88d
--- /dev/null
+++ b/examples/cl2/src/test/org/apache/commons/lang/enums/EnumTestSuite.java
@@ -0,0 +1,94 @@
+/* ====================================================================
+ * 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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
+ * .
+ */
+package org.apache.commons.lang.enums;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import junit.textui.TestRunner;
+
+/**
+ * Test suite for the Enum package.
+ *
+ * @author Stephen Colebourne
+ * @version $Id: EnumTestSuite.java,v 1.2 2003/05/22 22:00:06 scolebourne Exp $
+ */
+public class EnumTestSuite extends TestCase {
+
+ /**
+ * Construct a new instance.
+ */
+ public EnumTestSuite(String name) {
+ super(name);
+ }
+
+ /**
+ * Command-line interface.
+ */
+ public static void main(String[] args) {
+ TestRunner.run(suite());
+ }
+
+ /**
+ * Get the suite of tests
+ */
+ public static Test suite() {
+ TestSuite suite = new TestSuite();
+ suite.setName("Commons-Lang-Enum Tests");
+ suite.addTest(EnumTest.suite());
+ suite.addTest(EnumUtilsTest.suite());
+ suite.addTest(ValuedEnumTest.suite());
+ return suite;
+ }
+}
diff --git a/examples/cl2/src/test/org/apache/commons/lang/enums/EnumUtilsTest.java b/examples/cl2/src/test/org/apache/commons/lang/enums/EnumUtilsTest.java
new file mode 100644
index 00000000..d6cf61b1
--- /dev/null
+++ b/examples/cl2/src/test/org/apache/commons/lang/enums/EnumUtilsTest.java
@@ -0,0 +1,170 @@
+/* ====================================================================
+ * 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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
+ * .
+ */
+package org.apache.commons.lang.enums;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+/**
+ * Test cases for the {@link Enum} class.
+ *
+ * @author Stephen Colebourne
+ * @version $Id: EnumUtilsTest.java,v 1.3 2003/05/22 22:00:06 scolebourne Exp $
+ */
+
+public final class EnumUtilsTest extends TestCase {
+
+ public EnumUtilsTest(String name) {
+ super(name);
+ }
+
+ public void setUp() {
+ }
+
+ public static Test suite() {
+ TestSuite suite = new TestSuite(EnumUtilsTest.class);
+ suite.setName("EnumUtils Tests");
+ return suite;
+ }
+
+ public void testIterator() {
+ Iterator it = EnumUtils.iterator(ColorEnum.class);
+ assertSame(ColorEnum.RED, it.next());
+ assertSame(ColorEnum.GREEN, it.next());
+ assertSame(ColorEnum.BLUE, it.next());
+ }
+
+ public void testIteratorEx() {
+ try {
+ EnumUtils.iterator(null);
+ } catch (IllegalArgumentException ex) {
+ return;
+ }
+ fail();
+ }
+
+ public void testList() {
+ List list = EnumUtils.getEnumList(ColorEnum.class);
+ Iterator it = list.iterator();
+ assertSame(ColorEnum.RED, it.next());
+ assertSame(ColorEnum.GREEN, it.next());
+ assertSame(ColorEnum.BLUE, it.next());
+ }
+
+ public void testListEx() {
+ try {
+ EnumUtils.getEnumList(null);
+ } catch (IllegalArgumentException ex) {
+ return;
+ }
+ fail();
+ }
+
+ public void testMap() {
+ Map map = EnumUtils.getEnumMap(ColorEnum.class);
+ assertTrue(map.containsValue(ColorEnum.RED));
+ assertTrue(map.containsValue(ColorEnum.GREEN));
+ assertTrue(map.containsValue(ColorEnum.BLUE));
+ assertSame(ColorEnum.RED, map.get("Red"));
+ assertSame(ColorEnum.GREEN, map.get("Green"));
+ assertSame(ColorEnum.BLUE, map.get("Blue"));
+ }
+
+ public void testMapEx() {
+ try {
+ EnumUtils.getEnumMap(null);
+ } catch (IllegalArgumentException ex) {
+ return;
+ }
+ fail();
+ }
+
+ public void testGet() {
+ assertSame(ColorEnum.RED, EnumUtils.getEnum(ColorEnum.class, "Red"));
+ assertSame(ColorEnum.GREEN, EnumUtils.getEnum(ColorEnum.class, "Green"));
+ assertSame(ColorEnum.BLUE, EnumUtils.getEnum(ColorEnum.class, "Blue"));
+ assertSame(null, EnumUtils.getEnum(ColorEnum.class, "Pink"));
+ }
+
+ public void testGetEx() {
+ try {
+ EnumUtils.getEnum(null, "");
+ } catch (IllegalArgumentException ex) {
+ return;
+ }
+ fail();
+ }
+
+ public void testGetValue() {
+ assertSame(ValuedColorEnum.RED, EnumUtils.getEnum(ValuedColorEnum.class, 1));
+ assertSame(ValuedColorEnum.GREEN, EnumUtils.getEnum(ValuedColorEnum.class, 2));
+ assertSame(ValuedColorEnum.BLUE, EnumUtils.getEnum(ValuedColorEnum.class, 3));
+ assertSame(null, EnumUtils.getEnum(ValuedColorEnum.class, 4));
+ }
+
+ public void testGetValueEx() {
+ try {
+ EnumUtils.getEnum(null, 0);
+ } catch (IllegalArgumentException ex) {
+ return;
+ }
+ fail();
+ }
+
+}
diff --git a/examples/cl2/src/test/org/apache/commons/lang/enums/Extended1Enum.java b/examples/cl2/src/test/org/apache/commons/lang/enums/Extended1Enum.java
new file mode 100644
index 00000000..4bc21840
--- /dev/null
+++ b/examples/cl2/src/test/org/apache/commons/lang/enums/Extended1Enum.java
@@ -0,0 +1,90 @@
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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
+ * .
+ */
+package org.apache.commons.lang.enums;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Base extended enumeration.
+ *
+ * @author Stephen Colebourne
+ * @version $Id: Extended1Enum.java,v 1.2 2003/05/22 22:00:06 scolebourne Exp $
+ */
+public class Extended1Enum extends Enum {
+ public static final Extended1Enum ALPHA = new Extended1Enum("Alpha");
+ public static final Extended1Enum BETA = new Extended1Enum("Beta");
+
+ protected Extended1Enum(String name) {
+ super(name);
+ }
+
+ public static Extended1Enum getEnum(String name) {
+ return (Extended1Enum) getEnum(Extended1Enum.class, name);
+ }
+
+ public static Map getEnumMap() {
+ return getEnumMap(Extended1Enum.class);
+ }
+
+ public static List getEnumList() {
+ return getEnumList(Extended1Enum.class);
+ }
+
+ public static Iterator iterator() {
+ return iterator(Extended1Enum.class);
+ }
+
+}
diff --git a/examples/cl2/src/test/org/apache/commons/lang/enums/Extended2Enum.java b/examples/cl2/src/test/org/apache/commons/lang/enums/Extended2Enum.java
new file mode 100644
index 00000000..625413fb
--- /dev/null
+++ b/examples/cl2/src/test/org/apache/commons/lang/enums/Extended2Enum.java
@@ -0,0 +1,89 @@
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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
+ * .
+ */
+package org.apache.commons.lang.enums;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Extended enumeration.
+ *
+ * @author Stephen Colebourne
+ * @version $Id: Extended2Enum.java,v 1.2 2003/05/22 22:00:06 scolebourne Exp $
+ */
+public class Extended2Enum extends Extended1Enum {
+ public static final Extended1Enum GAMMA = new Extended2Enum("Gamma");
+
+ protected Extended2Enum(String color) {
+ super(color);
+ }
+
+ public static Extended1Enum getEnum(String name) {
+ return (Extended1Enum) getEnum(Extended2Enum.class, name);
+ }
+
+ public static Map getEnumMap() {
+ return getEnumMap(Extended2Enum.class);
+ }
+
+ public static List getEnumList() {
+ return getEnumList(Extended2Enum.class);
+ }
+
+ public static Iterator iterator() {
+ return iterator(Extended2Enum.class);
+ }
+
+}
diff --git a/examples/cl2/src/test/org/apache/commons/lang/enums/Extended3Enum.java b/examples/cl2/src/test/org/apache/commons/lang/enums/Extended3Enum.java
new file mode 100644
index 00000000..64c2cf40
--- /dev/null
+++ b/examples/cl2/src/test/org/apache/commons/lang/enums/Extended3Enum.java
@@ -0,0 +1,89 @@
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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
+ * .
+ */
+package org.apache.commons.lang.enums;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Extended enumeration.
+ *
+ * @author Stephen Colebourne
+ * @version $Id: Extended3Enum.java,v 1.2 2003/05/22 22:00:06 scolebourne Exp $
+ */
+public class Extended3Enum extends Extended2Enum {
+ public static final Extended1Enum DELTA = new Extended3Enum("Delta");
+
+ protected Extended3Enum(String name) {
+ super(name);
+ }
+
+ public static Extended1Enum getEnum(String name) {
+ return (Extended1Enum) Enum.getEnum(Extended3Enum.class, name);
+ }
+
+ public static Map getEnumMap() {
+ return Enum.getEnumMap(Extended3Enum.class);
+ }
+
+ public static List getEnumList() {
+ return Enum.getEnumList(Extended3Enum.class);
+ }
+
+ public static Iterator iterator() {
+ return Enum.iterator(Extended3Enum.class);
+ }
+
+}
\ No newline at end of file
diff --git a/examples/cl2/src/test/org/apache/commons/lang/enums/OperationEnum.java b/examples/cl2/src/test/org/apache/commons/lang/enums/OperationEnum.java
new file mode 100644
index 00000000..34c1d9f5
--- /dev/null
+++ b/examples/cl2/src/test/org/apache/commons/lang/enums/OperationEnum.java
@@ -0,0 +1,99 @@
+/* ====================================================================
+ * 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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
+ * .
+ */
+package org.apache.commons.lang.enums;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Operator enumeration.
+ *
+ * @author Stephen Colebourne
+ * @version $Id: OperationEnum.java,v 1.2 2003/05/22 22:00:06 scolebourne Exp $
+ */
+public abstract class OperationEnum extends Enum {
+ public static final OperationEnum PLUS = new OperationEnum("Plus") {
+ public int eval(int a, int b) {
+ return (a + b);
+ }
+ };
+ public static final OperationEnum MINUS = new OperationEnum("Minus") {
+ public int eval(int a, int b) {
+ return (a - b);
+ }
+ };
+
+ private OperationEnum(String name) {
+ super(name);
+ }
+
+ public abstract int eval(int a, int 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);
+ }
+}
diff --git a/examples/cl2/src/test/org/apache/commons/lang/enums/ValuedColorEnum.java b/examples/cl2/src/test/org/apache/commons/lang/enums/ValuedColorEnum.java
new file mode 100644
index 00000000..22428979
--- /dev/null
+++ b/examples/cl2/src/test/org/apache/commons/lang/enums/ValuedColorEnum.java
@@ -0,0 +1,95 @@
+/* ====================================================================
+ * 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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
+ * .
+ */
+package org.apache.commons.lang.enums;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Color enumeration.
+ *
+ * @author Stephen Colebourne
+ * @version $Id: ValuedColorEnum.java,v 1.2 2003/05/22 22:00:06 scolebourne Exp $
+ */
+
+public final class ValuedColorEnum extends ValuedEnum {
+ public static final ValuedColorEnum RED = new ValuedColorEnum("Red", 1);
+ public static final ValuedColorEnum GREEN = new ValuedColorEnum("Green", 2);
+ public static final ValuedColorEnum BLUE = new ValuedColorEnum("Blue", 3);
+
+ private ValuedColorEnum(String color, int value) {
+ super(color, value);
+ }
+
+ public static ValuedColorEnum getEnum(String color) {
+ return (ValuedColorEnum) getEnum(ValuedColorEnum.class, color);
+ }
+
+ public static ValuedColorEnum getEnum(int value) {
+ return (ValuedColorEnum) getEnum(ValuedColorEnum.class, value);
+ }
+
+ public static Map getEnumMap() {
+ return getEnumMap(ValuedColorEnum.class);
+ }
+
+ public static List getEnumList() {
+ return getEnumList(ValuedColorEnum.class);
+ }
+
+ public static Iterator iterator() {
+ return iterator(ValuedColorEnum.class);
+ }
+}
diff --git a/examples/cl2/src/test/org/apache/commons/lang/enums/ValuedEnumTest.java b/examples/cl2/src/test/org/apache/commons/lang/enums/ValuedEnumTest.java
new file mode 100644
index 00000000..411f45dc
--- /dev/null
+++ b/examples/cl2/src/test/org/apache/commons/lang/enums/ValuedEnumTest.java
@@ -0,0 +1,172 @@
+/* ====================================================================
+ * 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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
+ * .
+ */
+package org.apache.commons.lang.enums;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+import org.apache.commons.lang.SerializationUtils;
+
+/**
+ * Test cases for the {@link Enum} class.
+ *
+ * @author Stephen Colebourne
+ * @version $Id: ValuedEnumTest.java,v 1.3 2003/05/22 22:00:06 scolebourne Exp $
+ */
+
+public final class ValuedEnumTest extends TestCase {
+
+ public ValuedEnumTest(String name) {
+ super(name);
+ }
+
+ public void setUp() {
+ }
+
+ public static Test suite() {
+ TestSuite suite = new TestSuite(ValuedEnumTest.class);
+ suite.setName("ValuedEnum Tests");
+ return suite;
+ }
+
+ public void testName() {
+ assertEquals("Red", ValuedColorEnum.RED.getName());
+ assertEquals("Green", ValuedColorEnum.GREEN.getName());
+ assertEquals("Blue", ValuedColorEnum.BLUE.getName());
+ }
+
+ public void testValue() {
+ assertEquals(1, ValuedColorEnum.RED.getValue());
+ assertEquals(2, ValuedColorEnum.GREEN.getValue());
+ assertEquals(3, ValuedColorEnum.BLUE.getValue());
+ }
+
+ public void testCompareTo() {
+ assertTrue(ValuedColorEnum.BLUE.compareTo(ValuedColorEnum.BLUE) == 0);
+ assertTrue(ValuedColorEnum.RED.compareTo(ValuedColorEnum.BLUE) < 0);
+ assertTrue(ValuedColorEnum.BLUE.compareTo(ValuedColorEnum.RED) > 0);
+ }
+
+ public void testEquals() {
+ assertSame(ValuedColorEnum.RED, ValuedColorEnum.RED);
+ assertSame(ValuedColorEnum.getEnum("Red"), ValuedColorEnum.RED);
+ }
+
+ public void testToString() {
+ assertEquals("ValuedColorEnum[Red=1]", ValuedColorEnum.RED.toString());
+ }
+
+ public void testIterator() {
+ Iterator it = ValuedColorEnum.iterator();
+ assertSame(ValuedColorEnum.RED, it.next());
+ assertSame(ValuedColorEnum.GREEN, it.next());
+ assertSame(ValuedColorEnum.BLUE, it.next());
+ }
+
+ public void testList() {
+ List list = ValuedColorEnum.getEnumList();
+
+ assertNotNull(list);
+
+ assertEquals( list.size(),
+ ValuedColorEnum.getEnumMap().keySet().size());
+
+ Iterator it = list.iterator();
+ assertSame(ValuedColorEnum.RED, it.next());
+ assertSame(ValuedColorEnum.GREEN, it.next());
+ assertSame(ValuedColorEnum.BLUE, it.next());
+ }
+
+ public void testMap() {
+ Map map = ValuedColorEnum.getEnumMap();
+
+ assertNotNull(map);
+
+ assertEquals( map.keySet().size(),
+ ValuedColorEnum.getEnumList().size());
+
+ assertTrue(map.containsValue(ValuedColorEnum.RED));
+ assertTrue(map.containsValue(ValuedColorEnum.GREEN));
+ assertTrue(map.containsValue(ValuedColorEnum.BLUE));
+ assertSame(ValuedColorEnum.RED, map.get("Red"));
+ assertSame(ValuedColorEnum.GREEN, map.get("Green"));
+ assertSame(ValuedColorEnum.BLUE, map.get("Blue"));
+ }
+
+ public void testGet() {
+ assertSame(ValuedColorEnum.RED, ValuedColorEnum.getEnum("Red"));
+ assertSame(ValuedColorEnum.GREEN, ValuedColorEnum.getEnum("Green"));
+ assertSame(ValuedColorEnum.BLUE, ValuedColorEnum.getEnum("Blue"));
+ assertSame(null, ValuedColorEnum.getEnum("Pink"));
+ }
+
+ public void testGetValue() {
+ assertSame(ValuedColorEnum.RED, ValuedColorEnum.getEnum(1));
+ assertSame(ValuedColorEnum.GREEN, ValuedColorEnum.getEnum(2));
+ assertSame(ValuedColorEnum.BLUE, ValuedColorEnum.getEnum(3));
+ assertSame(null, ValuedColorEnum.getEnum(4));
+ }
+
+ public void testSerialization() {
+ assertSame(ValuedColorEnum.RED, SerializationUtils.clone(ValuedColorEnum.RED));
+ assertSame(ValuedColorEnum.GREEN, SerializationUtils.clone(ValuedColorEnum.GREEN));
+ assertSame(ValuedColorEnum.BLUE, SerializationUtils.clone(ValuedColorEnum.BLUE));
+ }
+
+}
diff --git a/examples/cl2/src/test/org/apache/commons/lang/exception/AbstractNestableTestCase.java b/examples/cl2/src/test/org/apache/commons/lang/exception/AbstractNestableTestCase.java
new file mode 100644
index 00000000..5fcde8ea
--- /dev/null
+++ b/examples/cl2/src/test/org/apache/commons/lang/exception/AbstractNestableTestCase.java
@@ -0,0 +1,707 @@
+/* ====================================================================
+ * 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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
+ * .
+ */
+package org.apache.commons.lang.exception;
+
+import java.io.ByteArrayOutputStream;
+import java.io.PrintStream;
+import java.io.PrintWriter;
+
+import junit.framework.TestCase;
+/**
+ * Tests implementations of the org.apache.commons.lang.exception.Nestable
+ * interface.
+ *
+ * @author Steven Caswell
+ * @version $Id: AbstractNestableTestCase.java,v 1.4 2003/05/21 23:49:14 scolebourne Exp $
+ */
+public abstract class AbstractNestableTestCase extends TestCase
+{
+
+ /**
+ * Constructs an instance of
+ * AbstractNestableTestCase
.
+ *
+ * @param name the test name
+ */
+ public AbstractNestableTestCase(String name)
+ {
+ super(name);
+ }
+
+ /**
+ * Tests the getCause() operation.
+ */
+ public void testGetCause()
+ {
+ Nestable ne1 = getNestable();
+ assertNull("nestable exception() cause is null", ne1.getCause());
+
+ Nestable ne2 = getNestable("ne2");
+ assertNull("nestable exception(\"ne2\") cause is null", ne2.getCause());
+
+ Nestable ne3 = getNestable(getThrowable("ne3 exception"));
+ assertNotNull("nestable exception(Throwable(\"ne3 exception\") cause is not null",
+ ne3.getCause());
+ assertTrue("nestable exception(Throwable(\"ne3 exception\") cause message == ne3 exception",
+ ne3.getCause().getMessage().equals("ne3 exception"));
+
+ Nestable ne4 = getNestable("ne4", getThrowable("ne4 exception"));
+ assertNotNull("nestable exception(\"ne4\", Throwable(\"ne4 exception\") cause is not null",
+ ne4.getCause());
+
+ Nestable ne5 = getNestable("ne5", (Throwable) null);
+ assertNull("nestable exception(\"ne5\", null) cause is null",
+ ne5.getCause());
+
+ Nestable ne6 = getNestable(null, getThrowable("ne6 exception"));
+ assertNotNull("nestable exception(null, Throwable(\"ne6 exception\") cause is not null",
+ ne6.getCause());
+ }
+
+ /**
+ * Tests the getThrowableCount() operation.
+ */
+ public void testGetThrowableCount()
+ {
+ Nestable ne1 = getNestable();
+ assertEquals("ne1 throwable count", 1, ne1.getThrowableCount());
+
+ Nestable ne2 = getNestable("ne2");
+ assertEquals("ne2 throwable count", 1, ne2.getThrowableCount());
+
+ Nestable ne3 = getNestable(getThrowable("ne3 exception"));
+ assertEquals("ne3 throwable count", 2, ne3.getThrowableCount());
+
+ Nestable ne4 = getNestable("ne4", getThrowable("ne4 exception"));
+ assertEquals("ne4 throwable count", 2, ne4.getThrowableCount());
+
+ Nestable ne5 = getNestable("ne5", (Throwable) null);
+ assertEquals("ne 5 throwable count", 1, ne5.getThrowableCount());
+
+ Nestable ne6 = getNestable(null, getThrowable("ne6 exception"));
+ assertEquals("ne 6 throwable count", 2, ne6.getThrowableCount());
+
+ Nestable ne7 = getNestable("ne7o", getNestable("ne7i", getThrowable("ne7 exception")));
+ assertEquals("ne 7 throwable count", 3, ne7.getThrowableCount());
+
+ Nestable ne8 = getNestable("level 1", getNestable("level 2", getNestable(getNestable("level 4", getThrowable("level 5")))));
+ assertEquals("ne 8 throwable count", 5, ne8.getThrowableCount());
+ }
+
+ /**
+ * Tests the getMessage() operation.
+ */
+ public void testGetMessage()
+ {
+ Nestable ne1 = getNestable();
+ assertNull("nestable exception() message is null", ne1.getMessage());
+
+ Nestable ne2 = getNestable("ne2");
+ assertNotNull("nestable exception(\"ne2\") message is not null", ne2.getMessage());
+ assertEquals("nestable exception(\"ne2\") message == ne2", ne2.getMessage(), "ne2");
+
+ Nestable ne3 = getNestable(getThrowable("ne3 exception"));
+ assertNotNull("nestable exception(Throwable(\"ne3 exception\") message is not null",
+ ne3.getMessage());
+ assertEquals("nestable exception(Throwable(\"ne3 exception\") message equals cause.toString()",
+ ne3.getMessage(), ne3.getCause().toString());
+
+ Nestable ne4 = getNestable("ne4", getThrowable("ne4 exception"));
+ assertNotNull("nestable exception(\"ne4\", Throwable(\"ne4 exception\") message is not null",
+ ne4.getMessage());
+ assertEquals("nestable exception(\"ne4\", Throwable(\"ne4 exception\") message == ne4",
+ ne4.getMessage(), "ne4");
+
+ Nestable ne5 = getNestable("ne5", (Throwable) null);
+ assertNotNull("nestable exception(\"ne5\", null) message is not null",
+ ne5.getMessage());
+ assertEquals("nestable exception(\"ne5\", null) message == ne5",
+ ne5.getMessage(), "ne5");
+
+ Throwable t6 = getThrowable("ne6 exception");
+ Nestable ne6 = getNestable(null, t6);
+ assertNotNull("nestable exception(null, Throwable(\"ne6 exception\") message is not null",
+ ne6.getMessage());
+ assertEquals("nestable exception(null, Throwable(\"ne6 exception\") message equals cause.toString()",
+ ne6.getMessage(), ne6.getCause().toString());
+
+ Nestable ne7 = getNestable("ne7o", getNestable("ne7i", getThrowable("ne7 exception")));
+ assertEquals("nestable exception(\"ne7o\", getNestable(\"ne7i\", Throwable(\"ne7 exception\"))) message is ne7o: ne7i: ne7 exception",
+ ne7.getMessage(), "ne7o");
+
+ Nestable ne8 = getNestable();
+ assertNull("nestable exception() message is null",
+ ne8.getMessage());
+
+ }
+
+ /**
+ * Tests the getMessage(int) operation.
+ */
+ public void testGetMessageI()
+ {
+ String[] msgs = new String[5];
+ msgs[0] = "level 1";
+ msgs[1] = "level 2";
+ msgs[2] = null;
+ msgs[3] = "level 4";
+ msgs[4] = "level 5";
+ Nestable ne = getNestable(msgs[0], getNestable(msgs[1], getNestable(getNestable(msgs[3], getThrowable(msgs[4])))));
+ for(int i = 0; i < msgs.length; i++)
+ {
+ assertEquals("message " + i, msgs[i], ne.getMessage(i));
+ }
+
+ // Test for index out of bounds
+ try
+ {
+ String msg = ne.getMessage(-1);
+ fail("getMessage(-1) should have thrown IndexOutOfBoundsException");
+ }
+ catch(IndexOutOfBoundsException ioode)
+ {
+ }
+ try
+ {
+ String msg = ne.getMessage(msgs.length + 100);
+ fail("getMessage(999) should have thrown IndexOutOfBoundsException");
+ }
+ catch(IndexOutOfBoundsException ioode)
+ {
+ }
+ }
+
+ /**
+ * Tests the getMessages() operation.
+ */
+ public void testGetMessages()
+ {
+ String[] msgs = new String[5];
+ msgs[0] = "level 1";
+ msgs[1] = "level 2";
+ msgs[2] = null;
+ msgs[3] = "level 4";
+ msgs[4] = "level 5";
+ Nestable ne = getNestable(msgs[0], getNestable(msgs[1], getNestable(getNestable(msgs[3], getThrowable(msgs[4])))));
+ String[] nMsgs = ne.getMessages();
+ assertEquals("messages length", msgs.length, nMsgs.length);
+ for(int i = 0; i < nMsgs.length; i++)
+ {
+ assertEquals("message " + i, msgs[i], nMsgs[i]);
+ }
+ }
+
+ /**
+ * Tests the getThrowable(int) operation.
+ */
+ public void testGetThrowableI()
+ {
+ Nestable n = null;
+ String msgs[] = null;
+ Class[] throwables = null;
+
+ msgs = new String[2];
+ msgs[0] = null;
+ msgs[1] = "level 2";
+ throwables = new Class[2];
+ throwables[0] = getTester1Class();
+ throwables[1] = getThrowableClass();
+ n = getTester1(getThrowable(msgs[1]));
+ doNestableExceptionGetThrowableI(n, throwables, msgs);
+
+ msgs = new String[5];
+ msgs[0] = "level 1";
+ msgs[1] = "level 2";
+ msgs[2] = null;
+ msgs[3] = "level 4";
+ msgs[4] = "level 5";
+ throwables = new Class[5];
+ throwables[0] = getTester1Class();
+ throwables[1] = getTester2Class();
+ throwables[2] = getTester1Class();
+ throwables[3] = getTester2Class();
+ throwables[4] = getThrowableClass();
+ n = getTester1(msgs[0], getTester2(msgs[1], getTester1(getTester2(msgs[3], getThrowable(msgs[4])))));
+ doNestableExceptionGetThrowableI(n, throwables, msgs);
+ }
+
+ private void doNestableExceptionGetThrowableI(Nestable n, Class[] classes, String[] msgs)
+ {
+ Throwable t = null;
+ String msg = null;
+
+ for(int i = 0; i < classes.length; i++)
+ {
+ t = n.getThrowable(i);
+ assertEquals("throwable class", classes[i], t.getClass());
+ if(Nestable.class.isInstance(t))
+ {
+ msg = ((Nestable) t).getMessage(0);
+ }
+ else
+ {
+ msg = t.getMessage();
+ }
+ assertEquals("throwable message", msgs[i], msg);
+ }
+
+ // Test for index out of bounds
+ try
+ {
+ t = n.getThrowable(-1);
+ fail("getThrowable(-1) should have thrown IndexOutOfBoundsException");
+ }
+ catch(IndexOutOfBoundsException ioobe)
+ {
+ }
+ try
+ {
+ t = n.getThrowable(999);
+ fail("getThrowable(999) should have thrown IndexOutOfBoundsException");
+ }
+ catch(IndexOutOfBoundsException ioobe)
+ {
+ }
+ }
+
+ /**
+ * Tests the getThrowables() operation.
+ */
+ public void testGetThrowables()
+ {
+ Nestable n = null;
+ String msgs[] = null;
+ Class[] throwables = null;
+
+ msgs = new String[2];
+ msgs[0] = null;
+ msgs[1] = "level 2";
+ throwables = new Class[2];
+ throwables[0] = getTester1Class();
+ throwables[1] = getThrowableClass();
+ n = getTester1(getThrowable(msgs[1]));
+ doNestableExceptionGetThrowables(n, throwables, msgs);
+
+ msgs = new String[5];
+ msgs[0] = "level 1";
+ msgs[1] = "level 2";
+ msgs[2] = null;
+ msgs[3] = "level 4";
+ msgs[4] = "level 5";
+ throwables = new Class[5];
+ throwables[0] = getTester1Class();
+ throwables[1] = getTester2Class();
+ throwables[2] = getTester1Class();
+ throwables[3] = getTester2Class();
+ throwables[4] = getThrowableClass();
+ n = getTester1(msgs[0], getTester2(msgs[1], getTester1(getTester2(msgs[3], getThrowable(msgs[4])))));
+ doNestableExceptionGetThrowables(n, throwables, msgs);
+ }
+
+ private void doNestableExceptionGetThrowables(Nestable n, Class[] classes, String[] msgs)
+ {
+ String msg = null;
+
+ Throwable throwables[] = n.getThrowables();
+ assertEquals("throwables length", classes.length, throwables.length);
+ for(int i = 0; i < classes.length; i++)
+ {
+ assertEquals("throwable class", classes[i], throwables[i].getClass());
+ Throwable t = throwables[i];
+ if(Nestable.class.isInstance(t))
+ {
+ msg = ((Nestable) t).getMessage(0);
+ }
+ else
+ {
+ msg = t.getMessage();
+ }
+ assertEquals("throwable message", msgs[i], msg);
+ }
+ }
+
+ /**
+ * Tests the indexOfThrowable() operation.
+ */
+ public void testIndexOfThrowable()
+ {
+ Nestable n = null;
+ String msgs[] = null;
+ Class[] throwables = null;
+
+ msgs = new String[5];
+ msgs[0] = "level 1";
+ msgs[1] = "level 2";
+ msgs[2] = null;
+ msgs[3] = "level 4";
+ msgs[4] = "level 5";
+ throwables = new Class[5];
+ throwables[0] = getTester1Class();
+ throwables[1] = getTester2Class();
+ throwables[2] = getTester1Class();
+ throwables[3] = getTester2Class();
+ throwables[4] = getThrowableClass();
+ int[] indexes = {0, 1, 0, 1, 4};
+ n = getTester1(msgs[0], getTester2(msgs[1], getTester1(getTester2(msgs[3], getThrowable(msgs[4])))));
+ for(int i = 0; i < throwables.length; i++)
+ {
+ doNestableExceptionIndexOfThrowable(n, throwables[i], indexes[i], msgs[indexes[i]]);
+ }
+ doNestableExceptionIndexOfThrowable(n, java.util.Date.class, -1, null);
+ }
+
+ private void doNestableExceptionIndexOfThrowable(Nestable n, Class type, int expectedIndex, String expectedMsg)
+ {
+ Throwable t = null;
+
+ int index = n.indexOfThrowable(type);
+ assertEquals("index of throwable " + type.getName(), expectedIndex, index);
+ if(expectedIndex > -1)
+ {
+ t = n.getThrowable(index);
+ if(expectedMsg != null)
+ {
+ String msg = null;
+ if(Nestable.class.isInstance(t))
+ {
+ msg = ((Nestable) t).getMessage(0);
+ }
+ else
+ {
+ msg = t.getMessage();
+ }
+ assertEquals("message of indexed throwable", expectedMsg, msg);
+ }
+ }
+ }
+
+ /**
+ * Tests the indexOfThrowable(int) operation.
+ */
+ public void testIndexOfThrowableI()
+ {
+ Nestable n = null;
+ String msgs[] = null;
+ Class[] throwables = null;
+
+ msgs = new String[5];
+ msgs[0] = "level 1";
+ msgs[1] = "level 2";
+ msgs[2] = null;
+ msgs[3] = "level 4";
+ msgs[4] = "level 5";
+ throwables = new Class[5];
+ throwables[0] = getTester1Class();
+ throwables[1] = getTester2Class();
+ throwables[2] = getTester1Class();
+ throwables[3] = getTester2Class();
+ throwables[4] = getThrowableClass();
+ int[] indexes = {0, 1, 0, 1, 4};
+ n = getTester1(msgs[0], getTester2(msgs[1], getTester1(getTester2(msgs[3], getThrowable(msgs[4])))));
+ for(int i = 0; i < throwables.length; i++)
+ {
+ doNestableExceptionIndexOfThrowableI(n, throwables[i], 0, indexes[i], msgs[indexes[i]]);
+ }
+ doNestableExceptionIndexOfThrowableI(n, getTester2Class(), 2, 3, msgs[3]);
+ doNestableExceptionIndexOfThrowableI(n, getTester1Class(), 1, 2, msgs[2]);
+ doNestableExceptionIndexOfThrowableI(n, getTester1Class(), 3, -1, null);
+ doNestableExceptionIndexOfThrowableI(n, getTester1Class(), 4, -1, null);
+ doNestableExceptionIndexOfThrowableI(n, getThrowableClass(), 2, 4, msgs[4]);
+ doNestableExceptionIndexOfThrowableI(n, java.util.Date.class, 0, -1, null);
+
+ // Test for index out of bounds
+ try
+ {
+ int index = n.indexOfThrowable(getTester1Class(), -1);
+ fail("method should have thrown IndexOutOfBoundsException");
+ }
+ catch(IndexOutOfBoundsException iooob)
+ {
+ }
+ try
+ {
+ int index = n.indexOfThrowable(getTester1Class(), 5);
+ fail("method should have thrown IndexOutOfBoundsException");
+ }
+ catch(IndexOutOfBoundsException iooob)
+ {
+ }
+
+ }
+
+ private void doNestableExceptionIndexOfThrowableI(Nestable n, Class type, int fromIndex, int expectedIndex, String expectedMsg)
+ {
+ Throwable t = null;
+
+ int index = n.indexOfThrowable(type, fromIndex);
+ assertEquals("index of throwable " + type.getName(), expectedIndex, index);
+ if(expectedIndex > -1)
+ {
+ t = n.getThrowable(index);
+ if(expectedMsg != null)
+ {
+ String msg = null;
+ if(Nestable.class.isInstance(t))
+ {
+ msg = ((Nestable) t).getMessage(0);
+ }
+ else
+ {
+ msg = t.getMessage();
+ }
+ assertEquals("message of indexed throwable", expectedMsg, msg);
+ }
+ }
+
+ }
+
+ /**
+ * Tests the printPartialStackTrace() operation.
+ */
+ public void testPrintPartialStackTrace()
+ {
+ Nestable ne9 = getNestable("ne9", getThrowable("ne9 exception"));
+ ByteArrayOutputStream baos2 = new ByteArrayOutputStream();
+ PrintStream ps2 = new PrintStream(baos2);
+ PrintWriter pw2 = new PrintWriter(ps2, true);
+ ne9.printPartialStackTrace(pw2);
+ String stack2 = baos2.toString();
+ String startsWith = ne9.getClass().getName() + ": ne9";
+ assertTrue("stack trace startsWith == " + startsWith,
+ stack2.startsWith(startsWith));
+ assertEquals("stack trace indexOf rethrown == -1",
+ stack2.indexOf("rethrown"), -1);
+ }
+
+ /**
+ * Tests the printStackTrace() operation.
+ */
+ public void testPrintStackTrace()
+ {
+ Nestable ne8 = getNestable("ne8", getThrowable("ne8 exception"));
+ ByteArrayOutputStream baos1 = new ByteArrayOutputStream();
+ PrintStream ps1 = new PrintStream(baos1);
+ PrintWriter pw1 = new PrintWriter(ps1, true);
+ ne8.printStackTrace(pw1);
+ String stack1 = baos1.toString();
+ String startsWith = ne8.getClass().getName() + ": ne8";
+ assertTrue("stack trace startsWith == " + startsWith,
+ stack1.startsWith(startsWith));
+ String indexOf = getThrowableClass().getName() + ": ne8 exception";
+ assertTrue("stack trace indexOf " + indexOf + " > -1",
+ stack1.indexOf(indexOf) > -1);
+ }
+
+ /**
+ * Returns an instance of the Nestable
implementation being
+ * tested.
+ *
+ * @return the instance
+ */
+ public abstract Nestable getNestable();
+
+ /**
+ * Returns an instance of the Nestable
implementation being
+ * tested.
+ *
+ * @param n Nestable
argument to be provided to the instance
+ * constructor
+ * @return the instance
+ */
+ public abstract Nestable getNestable(Nestable n);
+
+ /**
+ * Returns an instance of the Nestable
implementation being
+ * tested.
+ *
+ * @param msg String
argument to be provided to the instance
+ * constructor
+ * @return the instance
+ */
+ public abstract Nestable getNestable(String msg);
+
+ /**
+ * Returns an instance of the Nestable
implementation being
+ * tested.
+ *
+ * @param msg String
argument to be provided to the instance
+ * constructor
+ * @param n Nestable
argument to be provided to the instance
+ * constructor
+ * @return the instance
+ */
+ public abstract Nestable getNestable(String msg, Nestable n);
+
+ /**
+ * Returns an instance of the Nestable
implementation being
+ * tested.
+ *
+ * @param msg String
argument to be provided to the instance
+ * constructor
+ * @param t Throwable
argument to be provided to the instance
+ * constructor
+ * @return the instance
+ */
+ public abstract Nestable getNestable(String msg, Throwable t);
+
+ /**
+ * Returns an instance of the Nestable
implementation being
+ * tested.
+ *
+ * @param t Throwable
argument to be provided to the instance
+ * constructor
+ * @return the instance
+ */
+ public abstract Nestable getNestable(Throwable t);
+
+ /**
+ * Returns an instance of a Throwable
to be used in
+ * constructing instances of the Nestable
implementation being
+ * tested.
+ *
+ * @param msg String
argument to be provided to the instance
+ * constructor
+ * @return the instance
+ */
+ public abstract Throwable getThrowable(String msg);
+
+ /**
+ * Returns an instance of one tester Nestable
implementation.
+ *
+ * @param n Nestable
argument to be provided to the instance
+ * constructor
+ * @return the instance
+ */
+ public abstract Nestable getTester1(Nestable n);
+
+ /**
+ * Returns an instance of one tester Nestable
implementation.
+ *
+ * @param t Throwable
argument to be provided to the instance
+ * constructor
+ * @return the instance
+ */
+ public abstract Nestable getTester1(Throwable t);
+
+ /**
+ * Returns an instance of one tester Nestable
implementation.
+ *
+ * @param msg String
argument to be provided to the instance
+ * constructor
+ * @param n Nestable
argument to be provided to the instance
+ * constructor
+ * @return the instance
+ */
+ public abstract Nestable getTester1(String msg, Nestable n);
+
+ /**
+ * Returns an instance of one tester Nestable
implementation.
+ *
+ * @param msg String
argument to be provided to the instance
+ * constructor
+ * @param t Throwable
argument to be provided to the instance
+ * constructor
+ * @return the instance
+ */
+ public abstract Nestable getTester1(String msg, Throwable t);
+
+ /**
+ * Returns an instance of a second tester Nestable
+ * implementation.
+ *
+ * @param msg String
argument to be provided to the instance
+ * constructor
+ * @param n Nestable
argument to be provided to the instance
+ * constructor
+ * @return the instance
+ */
+ public abstract Nestable getTester2(String msg, Nestable n);
+
+ /**
+ * Returns an instance of a second tester Nestable
+ * implementation.
+ *
+ * @param msg String
argument to be provided to the instance
+ * constructor
+ * @param t Throwable
argument to be provided to the instance
+ * constructor
+ * @return the instance
+ */
+ public abstract Nestable getTester2(String msg, Throwable t);
+
+ /**
+ * Returns the class of the first tester Nestable
+ * implementation.
+ *
+ * @return the class
+ */
+ public abstract Class getTester1Class();
+
+ /**
+ * Returns the class of the second tester Nestable
+ * implementation.
+ *
+ * @return the class
+ */
+ public abstract Class getTester2Class();
+
+ /**
+ * Returns the class of the Throwable
used in constructing
+ * instances of the Nestable
implementation being tested.
+ *
+ * @return the class
+ */
+ public abstract Class getThrowableClass();
+}
+
diff --git a/examples/cl2/src/test/org/apache/commons/lang/exception/ExceptionTestSuite.java b/examples/cl2/src/test/org/apache/commons/lang/exception/ExceptionTestSuite.java
new file mode 100644
index 00000000..6cc27149
--- /dev/null
+++ b/examples/cl2/src/test/org/apache/commons/lang/exception/ExceptionTestSuite.java
@@ -0,0 +1,94 @@
+/* ====================================================================
+ * 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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
+ * .
+ */
+package org.apache.commons.lang.exception;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import junit.textui.TestRunner;
+
+/**
+ * Test manager for the org.apache.commons.lang.exception classes.
+ *
+ * @author Steven Caswell
+ */
+public class ExceptionTestSuite extends TestCase
+{
+ /**
+ * Construct a new instance.
+ */
+ public ExceptionTestSuite(String name)
+ {
+ super(name);
+ }
+
+ /**
+ * Command-line interface.
+ */
+ public static void main(String[] args)
+ {
+ TestRunner.run(suite());
+ }
+
+ public static Test suite()
+ {
+ TestSuite suite = new TestSuite();
+ suite.addTest(NestableDelegateTestCase.suite());
+ suite.addTest(NestableErrorTestCase.suite());
+ suite.addTest(NestableExceptionTestCase.suite());
+ suite.addTest(NestableRuntimeExceptionTestCase.suite());
+ suite.addTest(ExceptionUtilsTestCase.suite());
+ return suite;
+ }
+}
diff --git a/examples/cl2/src/test/org/apache/commons/lang/exception/ExceptionUtilsTestCase.java b/examples/cl2/src/test/org/apache/commons/lang/exception/ExceptionUtilsTestCase.java
new file mode 100644
index 00000000..d70ed43e
--- /dev/null
+++ b/examples/cl2/src/test/org/apache/commons/lang/exception/ExceptionUtilsTestCase.java
@@ -0,0 +1,196 @@
+/* ====================================================================
+ * 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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
+ * .
+ */
+package org.apache.commons.lang.exception;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+/**
+ * Tests {@link org.apache.commons.lang.exception.ExceptionUtils}.
+ *
+ * @author Daniel Rall
+ * @aithor Steven Caswell
+ * @since 1.0
+ */
+public class ExceptionUtilsTestCase extends junit.framework.TestCase
+{
+ private NestableException nested;
+ private Throwable withCause;
+ private Throwable withoutCause;
+
+ public ExceptionUtilsTestCase(String name)
+ {
+ super(name);
+ }
+
+ public static Test suite()
+ {
+ return new TestSuite(ExceptionUtilsTestCase.class);
+ }
+
+ public void setUp()
+ {
+ withoutCause = createExceptionWithoutCause();
+ nested = new NestableException(withoutCause);
+ withCause = new ExceptionWithCause(nested);
+ }
+
+ private Throwable createExceptionWithoutCause(){
+ try {
+ throw new ExceptionWithoutCause();
+ }
+ catch (Throwable t){
+ return t;
+ }
+ }
+
+ private Throwable createExceptionWithCause(){
+ try {
+ try {
+ throw new ExceptionWithCause(createExceptionWithoutCause());
+ }
+ catch (Throwable t){
+ throw new ExceptionWithCause(t);
+ }
+ }
+ catch (Throwable t){
+ return t;
+ }
+ }
+
+ public void testGetCause()
+ {
+ assertNull(ExceptionUtils.getCause(withoutCause));
+ assertTrue(ExceptionUtils.getCause(nested) == withoutCause);
+ assertTrue(ExceptionUtils.getCause(withCause) == nested);
+ }
+
+ public void testGetRootCause()
+ {
+ assertNull(ExceptionUtils.getRootCause(withoutCause));
+ assertTrue(ExceptionUtils.getRootCause(withCause) == withoutCause);
+ assertTrue(ExceptionUtils.getRootCause(withCause) == withoutCause);
+ }
+
+ public void testGetThrowableCount()
+ {
+ assertEquals(ExceptionUtils.getThrowableCount(null), 0);
+ }
+
+ public void testPrintThrowables()
+ throws Exception
+ {
+ StringWriter writer = new StringWriter(1024);
+ Throwable withCause = createExceptionWithCause();
+ ExceptionUtils.printRootCauseStackTrace(withCause,
+ new PrintWriter(writer));
+ String stackTrace = writer.toString();
+ assertTrue("printRootCauseStackTrace(Throwable, PrintWriter) failed",
+ stackTrace.indexOf(ExceptionUtils.WRAPPED_MARKER) != -1);
+ writer = new StringWriter(1024);
+ ExceptionUtils.printRootCauseStackTrace(withoutCause,
+ new PrintWriter(writer));
+ stackTrace = writer.toString();
+ assertTrue("printRootCauseStackTrace(Throwable, PrintWriter) failed",
+ stackTrace.indexOf(ExceptionUtils.WRAPPED_MARKER) == -1);
+ }
+
+ public void testIsNestedThrowable() {
+ assertTrue("SQLException not nested",
+ ExceptionUtils.isNestedThrowable(new java.sql.SQLException() ) );
+ assertTrue("InvocationTargetException not nested",
+ ExceptionUtils.isNestedThrowable(new java.lang.reflect.InvocationTargetException( new Exception() ) ) );
+ assertTrue("NestableRuntimeException not nested",
+ ExceptionUtils.isNestedThrowable(new NestableRuntimeException() ) );
+
+ // TODO: Come up with a way to test if java.lang.Throwable is nested.
+ // bearing in mind that in JDK 1.4 it is, and in 1.3 and previous
+ // it isn't.
+ }
+
+ /**
+ * Provides a method with a well known chained/nested exception
+ * name which matches the full signature (e.g. has a return value
+ * of Throwable
.
+ */
+ private static class ExceptionWithCause extends Exception
+ {
+ private Throwable cause;
+
+ public ExceptionWithCause(Throwable cause)
+ {
+ this.cause = cause;
+ }
+
+ public Throwable getCause()
+ {
+ return cause;
+ }
+ }
+
+ /**
+ * Provides a method with a well known chained/nested exception
+ * name which does not match the full signature (e.g. lacks a
+ * return value of Throwable
.
+ */
+ private static class ExceptionWithoutCause extends Exception
+ {
+ public void getTargetException()
+ {
+ }
+ }
+}
diff --git a/examples/cl2/src/test/org/apache/commons/lang/exception/NestableDelegateTestCase.java b/examples/cl2/src/test/org/apache/commons/lang/exception/NestableDelegateTestCase.java
new file mode 100644
index 00000000..cd990932
--- /dev/null
+++ b/examples/cl2/src/test/org/apache/commons/lang/exception/NestableDelegateTestCase.java
@@ -0,0 +1,1196 @@
+/* ====================================================================
+ * 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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
+ * .
+ */
+package org.apache.commons.lang.exception;
+
+import java.io.ByteArrayOutputStream;
+import java.io.PrintStream;
+import java.io.PrintWriter;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+import junit.textui.TestRunner;
+
+/**
+ * Tests the org.apache.commons.lang.exception.NestableDelegate class.
+ *
+ * @author Steven Caswell
+ * @author Daniel Rall
+ * @version $Id: NestableDelegateTestCase.java,v 1.5 2003/05/21 23:49:14 scolebourne Exp $
+ */
+public class NestableDelegateTestCase extends junit.framework.TestCase {
+ private static final String CONSTRUCTOR_FAILED_MSG =
+ "The Nestable implementation passed to the NestableDelegate(Nestable) constructor must extend java.lang.Throwable";
+
+ private static final String PARTIAL_STACK_TRACE =
+ "ThrowableNestedNestable partial stack trace place-holder";
+
+ protected String lineSeparator;
+
+ /**
+ * Construct a new instance of NestableDelegateTestCase with the specified name
+ */
+ public NestableDelegateTestCase(String name)
+ {
+ super(name);
+ }
+
+ /**
+ * Set up instance variables required by this test case.
+ */
+ public void setUp()
+ {
+ lineSeparator = System.getProperty("line.separator");
+ }
+
+ public static Test suite()
+ {
+ return new TestSuite(NestableDelegateTestCase.class);
+ }
+
+ /**
+ * Tear down instance variables required by this test case.
+ */
+ public void tearDown()
+ {
+ lineSeparator = null;
+ }
+
+ /**
+ * Test the implementation
+ */
+ public void testNestableDelegateConstructor()
+ {
+ String msg = null;
+ boolean constructorFailed = false;
+ try
+ {
+ NestableDelegate nonThrowableCause = new NestableDelegate(new NonThrowableNestable());
+ }
+ catch(IllegalArgumentException iae)
+ {
+ constructorFailed = true;
+ msg = iae.getMessage();
+ }
+ assertTrue("nestable delegate constructor with non-throwable cause failed == true", constructorFailed);
+ assertTrue("constructor failed exception msg == " + CONSTRUCTOR_FAILED_MSG,
+ msg.equals(CONSTRUCTOR_FAILED_MSG));
+
+ constructorFailed = false;
+ try
+ {
+ NestableDelegate nd1 = new NestableDelegate(new ThrowableNestable());
+ }
+ catch(IllegalArgumentException iae)
+ {
+ constructorFailed = true;
+ }
+ assertTrue("nestable delegate constructor with throwable cause failed == false", !constructorFailed);
+ }
+
+ public void testNestableDelegateGetMessage()
+ {
+ Nestable ne1 = new ThrowableNestable();
+ assertTrue("ThrowableNestable ne1 getMessage() == ThrowableNestable exception",
+ ne1.getMessage().equals("ThrowableNestable exception"));
+ NestableDelegate nd1 = new NestableDelegate(ne1);
+ assertTrue("nd1 getMessage() == " + ne1.getCause().getMessage(),
+ nd1.getMessage("base").equals("base: " + ne1.getCause().getMessage()));
+
+ Nestable ne2 = new ThrowableNestedNestable(new Exception("nested exception 2"));
+ NestableDelegate nd2 = new NestableDelegate(ne2);
+ assertTrue("nd2 getMessage() == base: " + ne2.getCause().getMessage(),
+ nd2.getMessage("base").equals("base: " + ne2.getCause().getMessage()));
+ }
+
+ public void testNestableDelegateGetThrowableCount()
+ {
+ Nestable n = null;
+ NestableDelegate d = null;
+
+ n = new NestableDelegateTester1();
+ d = new NestableDelegate(n);
+ doNestableDelegateGetThrowableCount(d, 1);
+
+ n = new NestableDelegateTester1("level 1");
+ d = new NestableDelegate(n);
+ doNestableDelegateGetThrowableCount(d, 1);
+
+ n = new NestableDelegateTester1(new Exception());
+ d = new NestableDelegate(n);
+ doNestableDelegateGetThrowableCount(d, 2);
+
+ n = new NestableDelegateTester1(new Exception("level 2"));
+ d = new NestableDelegate(n);
+ doNestableDelegateGetThrowableCount(d, 2);
+
+ n = new NestableDelegateTester1("level 1",
+ new NestableDelegateTester2("level 2",
+ new NestableDelegateTester1(
+ new NestableDelegateTester2("level 4",
+ new Exception("level 5")
+ )
+ )
+ )
+ );
+ d = new NestableDelegate(n);
+ doNestableDelegateGetThrowableCount(d, 5);
+ }
+
+ private void doNestableDelegateGetThrowableCount(NestableDelegate d, int len)
+ {
+ // Compare the lengths
+ assertEquals("delegate length", len, d.getThrowableCount());
+ }
+
+ public void testNestableDelegateGetMessages()
+ {
+ Nestable n = null;
+ NestableDelegate d = null;
+ String msgs[] = null;
+
+ msgs = new String[1];
+ n = new NestableDelegateTester1();
+ d = new NestableDelegate(n);
+ doNestableDelegateGetMessages(d, msgs);
+
+ msgs = new String[1];
+ msgs[0] = "level 1";
+ n = new NestableDelegateTester1(msgs[0]);
+ d = new NestableDelegate(n);
+ doNestableDelegateGetMessages(d, msgs);
+
+ msgs = new String[2];
+ n = new NestableDelegateTester1(new Exception());
+ d = new NestableDelegate(n);
+ doNestableDelegateGetMessages(d, msgs);
+
+ msgs = new String[2];
+ msgs[0] = null;
+ msgs[1] = "level 2";
+ n = new NestableDelegateTester1(new Exception(msgs[1]));
+ d = new NestableDelegate(n);
+ doNestableDelegateGetMessages(d, msgs);
+
+ msgs = new String[5];
+ msgs[0] = "level 1";
+ msgs[1] = "level 2";
+ msgs[2] = null;
+ msgs[3] = "level 4";
+ msgs[4] = "level 5";
+ n = new NestableDelegateTester1(msgs[0],
+ new NestableDelegateTester2(msgs[1],
+ new NestableDelegateTester1(
+ new NestableDelegateTester2(msgs[3],
+ new Exception(msgs[4])
+ )
+ )
+ )
+ );
+ d = new NestableDelegate(n);
+ doNestableDelegateGetMessages(d, msgs);
+ }
+
+ private void doNestableDelegateGetMessages(NestableDelegate d, String[] nMsgs)
+ {
+ // Compare the messages
+ String[] dMsgs = d.getMessages();
+ assertEquals("messages length", nMsgs.length, dMsgs.length);
+ for(int i = 0; i < nMsgs.length; i++)
+ {
+ assertEquals("message " + i, nMsgs[i], dMsgs[i]);
+ }
+ }
+
+ public void testNestableDelegateGetMessageN()
+ {
+ Nestable n = null;
+ NestableDelegate d = null;
+ String[] msgs = new String[5];
+ msgs[0] = "level 1";
+ msgs[1] = "level 2";
+ msgs[2] = null;
+ msgs[3] = "level 4";
+ msgs[4] = "level 5";
+ n = new NestableDelegateTester1(msgs[0],
+ new NestableDelegateTester2(msgs[1],
+ new NestableDelegateTester1(
+ new NestableDelegateTester2(msgs[3],
+ new Exception(msgs[4])
+ )
+ )
+ )
+ );
+ d = new NestableDelegate(n);
+ for(int i = 0; i < msgs.length; i++)
+ {
+ assertEquals("message " + i, msgs[i], d.getMessage(i));
+ }
+
+ // Test for index out of bounds
+ try
+ {
+ String msg = d.getMessage(-1);
+ fail("getMessage(-1) should have thrown IndexOutOfBoundsException");
+ }
+ catch(IndexOutOfBoundsException ioode)
+ {
+ }
+ try
+ {
+ String msg = d.getMessage(msgs.length + 100);
+ fail("getMessage(999) should have thrown IndexOutOfBoundsException");
+ }
+ catch(IndexOutOfBoundsException ioode)
+ {
+ }
+ }
+
+ public void testNestableDelegateGetThrowableN()
+ {
+ Nestable n = null;
+ NestableDelegate d = null;
+ String msgs[] = null;
+ Class[] throwables = null;
+
+ msgs = new String[2];
+ msgs[0] = null;
+ msgs[1] = "level 2";
+ throwables = new Class[2];
+ throwables[0] = NestableDelegateTester1.class;
+ throwables[1] = Exception.class;
+ n = new NestableDelegateTester1(new Exception(msgs[1]));
+ d = new NestableDelegate(n);
+ doNestableDelegateGetThrowableN(d, throwables, msgs);
+
+ msgs = new String[5];
+ msgs[0] = "level 1";
+ msgs[1] = "level 2";
+ msgs[2] = null;
+ msgs[3] = "level 4";
+ msgs[4] = "level 5";
+ throwables = new Class[5];
+ throwables[0] = NestableDelegateTester1.class;
+ throwables[1] = NestableDelegateTester2.class;
+ throwables[2] = NestableDelegateTester1.class;
+ throwables[3] = NestableDelegateTester2.class;
+ throwables[4] = Exception.class;
+ n = new NestableDelegateTester1(msgs[0],
+ new NestableDelegateTester2(msgs[1],
+ new NestableDelegateTester1(
+ new NestableDelegateTester2(msgs[3],
+ new Exception(msgs[4])
+ )
+ )
+ )
+ );
+ d = new NestableDelegate(n);
+ doNestableDelegateGetThrowableN(d, throwables, msgs);
+ }
+
+ private void doNestableDelegateGetThrowableN(NestableDelegate d, Class[] classes, String[] msgs)
+ {
+ Throwable t = null;
+ String msg = null;
+
+ for(int i = 0; i < classes.length; i++)
+ {
+ t = d.getThrowable(i);
+ assertEquals("throwable class", classes[i], t.getClass());
+ if(Nestable.class.isInstance(t))
+ {
+ msg = ((Nestable) t).getMessage(0);
+ }
+ else
+ {
+ msg = t.getMessage();
+ }
+ assertEquals("throwable message", msgs[i], msg);
+ }
+
+ // Test for index out of bounds
+ try
+ {
+ t = d.getThrowable(-1);
+ fail("getThrowable(-1) should have thrown IndexOutOfBoundsException");
+ }
+ catch(IndexOutOfBoundsException ioobe)
+ {
+ }
+ try
+ {
+ t = d.getThrowable(999);
+ fail("getThrowable(999) should have thrown IndexOutOfBoundsException");
+ }
+ catch(IndexOutOfBoundsException ioobe)
+ {
+ }
+ }
+
+ public void testNestableDelegateGetThrowables()
+ {
+ Nestable n = null;
+ NestableDelegate d = null;
+ String msgs[] = null;
+ Class[] throwables = null;
+
+ msgs = new String[2];
+ msgs[0] = null;
+ msgs[1] = "level 2";
+ throwables = new Class[2];
+ throwables[0] = NestableDelegateTester1.class;
+ throwables[1] = Exception.class;
+ n = new NestableDelegateTester1(new Exception(msgs[1]));
+ d = new NestableDelegate(n);
+ doNestableDelegateGetThrowables(d, throwables, msgs);
+
+ msgs = new String[5];
+ msgs[0] = "level 1";
+ msgs[1] = "level 2";
+ msgs[2] = null;
+ msgs[3] = "level 4";
+ msgs[4] = "level 5";
+ throwables = new Class[5];
+ throwables[0] = NestableDelegateTester1.class;
+ throwables[1] = NestableDelegateTester2.class;
+ throwables[2] = NestableDelegateTester1.class;
+ throwables[3] = NestableDelegateTester2.class;
+ throwables[4] = Exception.class;
+ n = new NestableDelegateTester1(msgs[0],
+ new NestableDelegateTester2(msgs[1],
+ new NestableDelegateTester1(
+ new NestableDelegateTester2(msgs[3],
+ new Exception(msgs[4])
+ )
+ )
+ )
+ );
+ d = new NestableDelegate(n);
+ doNestableDelegateGetThrowables(d, throwables, msgs);
+ }
+
+ private void doNestableDelegateGetThrowables(NestableDelegate d, Class[] classes, String[] msgs)
+ {
+ Throwable[] throwables = null;
+ String msg = null;
+
+ throwables = d.getThrowables();
+ assertEquals("throwables length", classes.length, throwables.length);
+ for(int i = 0; i < classes.length; i++)
+ {
+ assertEquals("throwable class", classes[i], throwables[i].getClass());
+ Throwable t = throwables[i];
+ if(Nestable.class.isInstance(t))
+ {
+ msg = ((Nestable) t).getMessage(0);
+ }
+ else
+ {
+ msg = t.getMessage();
+ }
+ assertEquals("throwable message", msgs[i], msg);
+ }
+ }
+
+ public void testIndexOfThrowable()
+ {
+ Nestable n = null;
+ NestableDelegate d = null;
+ String msgs[] = null;
+ Class[] throwables = null;
+
+ msgs = new String[5];
+ msgs[0] = "level 1";
+ msgs[1] = "level 2";
+ msgs[2] = null;
+ msgs[3] = "level 4";
+ msgs[4] = "level 5";
+ throwables = new Class[5];
+ throwables[0] = NestableDelegateTester1.class;
+ throwables[1] = NestableDelegateTester2.class;
+ throwables[2] = NestableDelegateTester1.class;
+ throwables[3] = NestableDelegateTester2.class;
+ throwables[4] = Exception.class;
+ int[] indexes = {0, 1, 0, 1, 4};
+ n = new NestableDelegateTester1(msgs[0],
+ new NestableDelegateTester2(msgs[1],
+ new NestableDelegateTester1(
+ new NestableDelegateTester2(msgs[3],
+ new Exception(msgs[4])
+ )
+ )
+ )
+ );
+ d = new NestableDelegate(n);
+ for(int i = 0; i < throwables.length; i++)
+ {
+ doNestableDelegateIndexOfThrowable(d, throwables[i], 0, indexes[i], msgs[indexes[i]]);
+ }
+ doNestableDelegateIndexOfThrowable(d, NestableDelegateTester2.class, 2, 3, msgs[3]);
+ doNestableDelegateIndexOfThrowable(d, NestableDelegateTester1.class, 1, 2, msgs[2]);
+ doNestableDelegateIndexOfThrowable(d, NestableDelegateTester1.class, 3, -1, null);
+ doNestableDelegateIndexOfThrowable(d, NestableDelegateTester1.class, 4, -1, null);
+ doNestableDelegateIndexOfThrowable(d, Exception.class, 2, 4, msgs[4]);
+ doNestableDelegateIndexOfThrowable(d, java.util.Date.class, 0, -1, null);
+
+ // Test for index out of bounds
+ try
+ {
+ int index = d.indexOfThrowable(NestableDelegateTester1.class, -1);
+ fail("method should have thrown IndexOutOfBoundsException");
+ }
+ catch(IndexOutOfBoundsException iooob)
+ {
+ }
+ try
+ {
+ int index = d.indexOfThrowable(NestableDelegateTester1.class, 5);
+ fail("method should have thrown IndexOutOfBoundsException");
+ }
+ catch(IndexOutOfBoundsException iooob)
+ {
+ }
+ }
+
+ private void doNestableDelegateIndexOfThrowable(NestableDelegate d, Class type, int fromIndex, int expectedIndex, String expectedMsg)
+ {
+ Throwable t = null;
+
+ int index = d.indexOfThrowable(type, fromIndex);
+ assertEquals("index of throwable " + type.getName(), expectedIndex, index);
+ if(expectedIndex > -1)
+ {
+ t = d.getThrowable(index);
+ if(expectedMsg != null)
+ {
+ String msg = null;
+ if(Nestable.class.isInstance(t))
+ {
+ msg = ((Nestable) t).getMessage(0);
+ }
+ else
+ {
+ msg = t.getMessage();
+ }
+ assertEquals("message of indexed throwable", expectedMsg, msg);
+ }
+ }
+ }
+
+ public void testNestableDelegetePrintStackTrace()
+ {
+ int lineSepLen = lineSeparator.length();
+ int partialStackTraceLen = PARTIAL_STACK_TRACE.length();
+ Nestable ne3 = new ThrowableNestedNestable(new Exception("nested exception 3"));
+ NestableDelegate nd3 = new NestableDelegate(ne3);
+
+ ByteArrayOutputStream baos1 = new ByteArrayOutputStream();
+ PrintStream ps1 = new PrintStream(baos1);
+ nd3.printStackTrace(ps1);
+ String stack1 = baos1.toString();
+ assertTrue("stack trace startsWith", stack1.startsWith(PARTIAL_STACK_TRACE));
+
+ Nestable n = new NestableDelegateTester1("level 1",
+ new NestableDelegateTester2("level 2",
+ new NestableDelegateTester1(
+ new NestableDelegateTester2("level 4",
+ new Exception("level 5")
+ )
+ )
+ )
+ );
+ NestableDelegate d = new NestableDelegate(n);
+
+ // Only testing the flags for jdk1.3 and below
+ if (!ExceptionUtils.isThrowableNested()) {
+ d.topDown = true; d.trimStackFrames = true;
+ checkStackTrace(d, true, true, NestableDelegateTester1.class.getName()+": level 1", 24);
+ d.topDown = true; d.trimStackFrames = false;
+ checkStackTrace(d, true, false, NestableDelegateTester1.class.getName()+": level 1", 80);
+ d.topDown = false; d.trimStackFrames = true;
+ checkStackTrace(d, false, true, "java.lang.Exception: level 5", 24);
+ d.topDown = false; d.trimStackFrames = false;
+ checkStackTrace(d, false, false, "java.lang.Exception: level 5", 80);
+ d.topDown = true; d.trimStackFrames = true;
+ }
+ }
+ private void checkStackTrace(NestableDelegate d, boolean topDown, boolean trimStackFrames,
+ String startsWith, int expCount) {
+ ByteArrayOutputStream baos1 = new ByteArrayOutputStream();
+ PrintStream ps1 = new PrintStream(baos1);
+ d.printStackTrace(ps1);
+ String stack1 = baos1.toString();
+ int actCount = countLines(stack1);
+ assertTrue("topDown: "+topDown+", trimStackFrames: "+trimStackFrames+" startsWith",
+ stack1.startsWith(startsWith));
+ assertEquals("topDown: "+topDown+", trimStackFrames: "+trimStackFrames+" lineCount",
+ expCount, actCount);
+ }
+ private int countLines(String s) {
+ if (s == null) return 0;
+
+ int i = 0, ndx = -1;
+ while ((ndx = s.indexOf("\n", ndx+1)) != -1) {
+ i++;
+ }
+ return i;
+ }
+
+ public static void main(String args[])
+ {
+ TestRunner.run(suite());
+ }
+}
+
+/**
+ * Nestable and Throwable class which can be passed to the NestableDelegate
+ * constructor. Used for testing various methods which iterate through the
+ * nested causes.
+ */
+class NestableDelegateTester1 extends Exception implements Nestable
+{
+ private Throwable cause = null;
+
+ public NestableDelegateTester1()
+ {
+ super();
+ }
+
+ public NestableDelegateTester1(String reason, Throwable cause)
+ {
+ super(reason);
+ this.cause = cause;
+ }
+
+ public NestableDelegateTester1(String reason)
+ {
+ super(reason);
+ }
+
+ public NestableDelegateTester1(Throwable cause)
+ {
+ super();
+ this.cause = cause;
+ }
+
+ /**
+ * @see Nestable#getThrowables()
+ * Returns zero-length Throwable
array for this test.
+ */
+ public Throwable[] getThrowables()
+ {
+ return new Throwable[0];
+ }
+
+ /**
+ * @see Nestable#getMessages()
+ * Returns zero-length String array for this test.
+ */
+ public String[] getMessages()
+ {
+ return new String[0];
+ }
+
+ /**
+ * @see Nestable#indexOfThrowable(Class)
+ * Returns -1 for this test.
+ */
+ public int indexOfThrowable(Class type)
+ {
+ return -1;
+ }
+
+ /**
+ * @see Nestable#getThrowable(int)
+ * Returns null
for this test.
+ */
+ public Throwable getThrowable(int index)
+ {
+ return null;
+ }
+
+ /**
+ * @see Nestable#getThrowableCount()
+ * Returns 1 for this test.
+ */
+ public int getThrowableCount()
+ {
+ return 1;
+ }
+
+ /**
+ * @see Nestable#getCause()
+ */
+ public Throwable getCause()
+ {
+ return cause;
+ }
+
+ /**
+ * Empty method to satisfy the implemented interface. Does nothing
+ * in this test.
+ *
+ * @param out The writer to use.
+ */
+ public void printPartialStackTrace(PrintWriter out)
+ {
+ super.printStackTrace(out);
+ }
+
+ /**
+ * @see Nestable#getMessage(int)
+ */
+ public String getMessage(int index)
+ {
+ if(index == 0)
+ {
+ return super.getMessage();
+ }
+ else
+ {
+ return "";
+ }
+ }
+
+ /**
+ * @see Nestable#indexOfThrowable(Class, int)
+ * Returns -1 for this test.
+ */
+ public int indexOfThrowable(Class type, int fromIndex)
+ {
+ return -1;
+ }
+
+}
+
+/**
+ * Nestable and Throwable class which can be passed to the NestableDelegate
+ * constructor. Used for testing various methods which iterate through the
+ * nested causes.
+ */
+class NestableDelegateTester2 extends Throwable implements Nestable
+{
+ private Throwable cause = null;
+
+ public NestableDelegateTester2()
+ {
+ super();
+ }
+
+ public NestableDelegateTester2(String reason, Throwable cause)
+ {
+ super(reason);
+ this.cause = cause;
+ }
+
+ public NestableDelegateTester2(String reason)
+ {
+ super(reason);
+ }
+
+ public NestableDelegateTester2(Throwable cause)
+ {
+ super();
+ this.cause = cause;
+ }
+
+ /**
+ * @see Nestable#getThrowables()
+ * Returns zero-length Throwable
array for this test.
+ */
+ public Throwable[] getThrowables()
+ {
+ return new Throwable[0];
+ }
+
+ /**
+ * @see Nestable#getMessages()
+ * Returns zero-length String array for this test.
+ */
+ public String[] getMessages()
+ {
+ return new String[0];
+ }
+
+ /**
+ * @see Nestable#indexOfThrowable(Class)
+ * Returns -1 for this test.
+ */
+ public int indexOfThrowable(Class type)
+ {
+ return -1;
+ }
+
+ /**
+ * @see Nestable#getThrowable(int)
+ * Returns null
for this test.
+ */
+ public Throwable getThrowable(int index)
+ {
+ return null;
+ }
+
+ /**
+ * @see Nestable#getThrowableCount()
+ * Returns 1 for this test.
+ *
+ * @return 1
+ */
+ public int getThrowableCount()
+ {
+ return 1;
+ }
+
+ /**
+ * @see Nestable#getCause()
+ */
+ public Throwable getCause()
+ {
+ return cause;
+ }
+
+ /**
+ * Empty method to satisfy the implemented interface. Does nothing
+ * in this test.
+ *
+ * @param out The writer to use.
+ */
+ public void printPartialStackTrace(PrintWriter out)
+ {
+ super.printStackTrace(out);
+ }
+
+ /**
+ * @see Nestable#getMessage(int)
+ */
+ public String getMessage(int index)
+ {
+ if(index == 0)
+ {
+ return super.getMessage();
+ }
+ else
+ {
+ return "";
+ }
+ }
+
+ /**
+ * @see Nestable#indexOfThrowable(Class, int)
+ * Returns -1 for this test.
+ */
+ public int indexOfThrowable(Class type, int fromIndex)
+ {
+ return -1;
+ }
+
+}
+
+/**
+ * Used to test that the constructor passes when passed a throwable cause
+ * And, the NestableDelegate.getMessage() returns the message from underlying
+ * nestable (which also has to be a Throwable).
+ */
+class ThrowableNestable extends Throwable implements Nestable
+{
+ private Throwable cause = new Exception("ThrowableNestable cause");
+
+ /**
+ * @see Nestable#getThrowableCount()
+ * Returns 1 for this test.
+ */
+ public int getThrowableCount()
+ {
+ return 1;
+ }
+
+ /**
+ * @see Nestable#getMessage()
+ * Returns the hard-coded string "ThrowableNestable exception" for this
+ * test.
+ */
+ public String getMessage()
+ {
+ return "ThrowableNestable exception";
+ }
+
+ /**
+ * @see Nestable#getMessage(int)
+ * Returns the hard-coded string "ThrowableNestable exception" for this
+ * test.
+ */
+ public String getMessage(int index)
+ {
+ return getMessage();
+ }
+
+ /**
+ * @see Nestable#getMessages()
+ * Returns single-element string array with "ThrowableNestable exception".
+ */
+ public String[] getMessages()
+ {
+ String msgs[] = new String[1];
+ msgs[0] = getMessage();
+ return msgs;
+ }
+
+ /**
+ * @see Nestable#getCause()
+ */
+ public Throwable getCause()
+ {
+ return cause;
+ }
+
+ /**
+ * @see Nestable#printStackTrace(PrintWriter)
+ * Empty method to satisfy the implemented interface. Does nothing
+ * in this test.
+ */
+ public void printStackTrace(PrintWriter out)
+ {
+ }
+
+ /**
+ * @see Nestable#printPartialStackTrace(PrintWriter)
+ * Empty method to satisfy the implemented interface. Does nothing
+ * in this test.
+ */
+ public void printPartialStackTrace(PrintWriter out)
+ {
+ }
+
+ /**
+ * @see Nestable#getThrowable(int)
+ */
+ public Throwable getThrowable(int index)
+ {
+ return cause;
+ }
+
+ /**
+ * @see Nestable#getThrowables()
+ */
+ public Throwable[] getThrowables()
+ {
+ Throwable throwables[] = new Throwable[1];
+ throwables[0] = cause;
+ return throwables;
+ }
+
+ /**
+ * @see Nestable#indexOfThrowable(Class)
+ */
+ public int indexOfThrowable(Class type)
+ {
+ if(Exception.class.isInstance(type))
+ {
+ return 0;
+ }
+ return -1;
+ }
+
+ /**
+ * @see Nestable#indexOfThrowable(Class,int)
+ */
+ public int indexOfThrowable(Class type, int fromIndex)
+ {
+ return indexOfThrowable(type);
+ }
+
+}
+
+/**
+ * Nestable and Throwable class which takes in a 'cause' object.
+ * Returns a message wrapping the 'cause' message
+ * Prints a fixed stack trace and partial stack trace.
+ */
+class ThrowableNestedNestable extends Throwable implements Nestable
+{
+ private Throwable cause = null;
+
+ public ThrowableNestedNestable(Throwable cause)
+ {
+ this.cause = cause;
+ }
+
+ /**
+ * @see Nestable#getThrowableCount()
+ * Returns 1 for this test.
+ */
+ public int getThrowableCount()
+ {
+ return 1;
+ }
+
+ /**
+ * @see Nestable#getMessage()
+ * For this test, returns "ThrowableNestable exception (" appended to the
+ * message of the cause specified in the constructor.
+ */
+ public String getMessage()
+ {
+ return "ThrowableNestedNestable exception (" + cause.getMessage() + ")";
+ }
+
+ /**
+ * @see Nestable#getMessage(int)
+ * For this test, returns "ThrowableNestable exception (" appended to the
+ * message of the cause specified in the constructor.
+ */
+ public String getMessage(int index)
+ {
+ return "ThrowableNestedNestable exception (" + cause.getMessage() + ")";
+ }
+
+ /**
+ * @see Nestable#getMessages()
+ * For this test, returns a single-element string array containing
+ * "ThrowableNestable exception (" appended to the
+ * message of the cause specified in the constructor.
+ */
+ public String[] getMessages()
+ {
+ String[] msgs = new String[1];
+ msgs[0] = "ThrowableNestedNestable exception (" + cause.getMessage() + ")";
+ return msgs;
+ }
+
+ /**
+ * @see Nestable#getCause()
+ */
+ public Throwable getCause()
+ {
+ return cause;
+ }
+
+ /**
+ * @see Nestable#printStackTrace(PrintWriter)
+ * For this test, writes the string
+ * "ThrowableNestedNestable stack trace place-holder" to the print writer.
+ */
+ public void printStackTrace(PrintWriter out)
+ {
+ out.println("ThrowableNestedNestable stack trace place-holder");
+ }
+
+ /**
+ * @see Nestable#printPartialStackTrace(PrintWriter)
+ * For this test, writes the string
+ * "ThrowableNestedNestable partial stack trace place-holder" to the print
+ * writer.
+ */
+ public void printPartialStackTrace(PrintWriter out)
+ {
+ out.println("ThrowableNestedNestable partial stack trace place-holder");
+ }
+
+ /**
+ * @see Nestable#getThrowable(int)
+ */
+ public Throwable getThrowable(int index)
+ {
+ return cause;
+ }
+
+ /**
+ * @see Nestable#getThrowableS()
+ */
+ public Throwable[] getThrowables()
+ {
+ Throwable throwables[] = new Throwable[1];
+ throwables[0] = cause;
+ return throwables;
+ }
+
+ /**
+ * @see Nestable#indexOfThrowable(Class)
+ */
+ public int indexOfThrowable(Class type)
+ {
+ if(Exception.class.isInstance(type))
+ {
+ return 0;
+ }
+ return -1;
+ }
+
+ /**
+ * @see Nestable#indexOfThrowable(Class, int)
+ */
+ public int indexOfThrowable(Class type, int fromIndex)
+ {
+ return indexOfThrowable(type);
+ }
+
+}
+
+/**
+ * Used to test that the constructor fails when passed a non-throwable cause
+ */
+class NonThrowableNestable implements Nestable
+{
+ /**
+ * @see Nestable#getThrowableCount()
+ * Returns 1 for this test.
+ */
+ public int getThrowableCount()
+ {
+ return 1;
+ }
+
+ /**
+ * @see Nestable#getMessage()
+ * Returns the string "non-throwable" for this test.
+ */
+ public String getMessage()
+ {
+ return "non-throwable";
+ }
+
+ /**
+ * @see Nestable#getMessage(int)
+ * Returns the string "non-throwable" for this test.
+ */
+ public String getMessage(int index)
+ {
+ return "non-throwable";
+ }
+
+ /**
+ * @see Nestable#getMessage()
+ * Returns a single-element array containing the string "non-throwable" for
+ * this test.
+ */
+ public String[] getMessages()
+ {
+ String[] msgs = new String[1];
+ msgs[0] = "non-throwable";
+ return msgs;
+ }
+
+ /**
+ * @see Nestable#getCause()
+ * Returns null
for this test.
+ */
+ public Throwable getCause()
+ {
+ return null;
+ }
+
+ /**
+ * @see Nestable#printStackTrace(PrintWriter)
+ * Empty method to satisfy the implemented interface. Does nothing
+ * in this test.
+ */
+ public void printStackTrace(PrintWriter out)
+ {
+ }
+
+ /**
+ * @see Nestable#printStackTrace(PrintStream)
+ * Empty method to satisfy the implemented interface. Does nothing
+ * in this test.
+ */
+ public void printStackTrace(PrintStream out)
+ {
+ }
+
+ /**
+ * @see Nestable#printPartialStackTrace(PrintWriter)
+ * Empty method to satisfy the implemented interface. Does nothing
+ * in this test.
+ */
+ public void printPartialStackTrace(PrintWriter out)
+ {
+ }
+
+
+ /**
+ * @see Nestable#getThrowable(int)
+ * Returns null
for this test.
+ */
+ public Throwable getThrowable(int index)
+ {
+ return null;
+ }
+
+ /**
+ * @see Nestable#getThrowables()
+ * Returns zero-length Throwable
array.
+ */
+ public Throwable[] getThrowables()
+ {
+ return new Throwable[0];
+ }
+
+ /**
+ * @see Nestable#indexOfThrowable(Class)
+ * Returns -1 for this test.
+ */
+ public int indexOfThrowable(Class type)
+ {
+ return -1;
+ }
+
+ /**
+ * @see Nestable#indexOfThrowable(Class, int)
+ * Returns -1 for this test.
+ */
+ public int indexOfThrowable(Class type, int fromIndex)
+ {
+ return -1;
+ }
+
+}
diff --git a/examples/cl2/src/test/org/apache/commons/lang/exception/NestableErrorTestCase.java b/examples/cl2/src/test/org/apache/commons/lang/exception/NestableErrorTestCase.java
new file mode 100644
index 00000000..03d3ff34
--- /dev/null
+++ b/examples/cl2/src/test/org/apache/commons/lang/exception/NestableErrorTestCase.java
@@ -0,0 +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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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
+ * .
+ */
+package org.apache.commons.lang.exception;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+import junit.textui.TestRunner;
+
+/**
+ * Tests the org.apache.commons.lang.exception.NestableError class.
+ *
+ * @author Steven Caswell
+ * @version $Id: NestableErrorTestCase.java,v 1.4 2003/05/21 23:49:14 scolebourne Exp $
+ */
+public class NestableErrorTestCase extends AbstractNestableTestCase {
+
+ /**
+ * Construct a new instance of
+ * NestableErrorTestCase
.
+ *
+ * @param name test case name
+ */
+ public NestableErrorTestCase(String name)
+ {
+ super(name);
+ }
+
+ /**
+ * Sets up instance variables required by this test case.
+ */
+ public void setUp()
+ {
+ }
+
+ /**
+ * Returns the test suite
+ *
+ * @return the test suite
+ */
+ public static Test suite()
+ {
+ return new TestSuite(NestableErrorTestCase.class);
+ }
+
+ /**
+ * Tears down instance variables required by this test case.
+ */
+ public void tearDown()
+ {
+ }
+
+ /**
+ * Command line entry point for running the test suite.
+ *
+ * @param args array of command line arguments
+ */
+ public static void main(String args[])
+ {
+ TestRunner.run(suite());
+ }
+
+ /**
+ * @see AbstractNestableTestCase#getNestable()
+ */
+ public Nestable getNestable()
+ {
+ return new NestableError();
+ }
+
+ /**
+ * @see AbstractNestableTestCase#getNestable(Nestable)
+ */
+ public Nestable getNestable(Nestable n)
+ {
+ return new NestableError((Throwable) n);
+ }
+
+ /**
+ * @see AbstractNestableTestCase#getNestable(String)
+ */
+ public Nestable getNestable(String msg)
+ {
+ return new NestableError(msg);
+ }
+
+ /**
+ * @see AbstractNestableTestCase#getNestable(Throwable)
+ */
+ public Nestable getNestable(Throwable t)
+ {
+ return new NestableError(t);
+ }
+
+ /**
+ * @see AbstractNestableTestCase#getNestable(String, Throwable)
+ */
+ public Nestable getNestable(String msg, Throwable t)
+ {
+ return new NestableError(msg, t);
+ }
+
+ /**
+ * @see AbstractNestableTestCase#getNestable(String, Nestable)
+ */
+ public Nestable getNestable(String msg, Nestable n)
+ {
+ return new NestableError(msg, (Throwable) n);
+ }
+
+ /**
+ * @see AbstractNestableTestCase#getTester1(Throwable)
+ */
+ public Nestable getTester1(Throwable t)
+ {
+ return new NestableErrorTester1(t);
+ }
+
+ /**
+ * @see AbstractNestableTestCase#getTester1(Nestable)
+ */
+ public Nestable getTester1(Nestable n)
+ {
+ return new NestableErrorTester1((Throwable) n);
+ }
+
+ /**
+ * @see AbstractNestableTestCase#getTester1(String, Throwable)
+ */
+ public Nestable getTester1(String msg, Throwable t)
+ {
+ return new NestableErrorTester1(msg, t);
+ }
+
+ /**
+ * @see AbstractNestableTestCase#getTester1(String, Nestable)
+ */
+ public Nestable getTester1(String msg, Nestable n)
+ {
+ return new NestableErrorTester1(msg, (Throwable) n);
+ }
+
+ /**
+ * @see AbstractNestableTestCase#getTester1Class()
+ */
+ public Class getTester1Class()
+ {
+ return NestableErrorTester1.class;
+ }
+
+ /**
+ * @see AbstractNestableTestCase#getTester2(String, Throwable)
+ */
+ public Nestable getTester2(String msg, Throwable t)
+ {
+ return new NestableErrorTester2(msg, t);
+ }
+
+ /**
+ * @see AbstractNestableTestCase#getTester2(String, Nestable)
+ */
+ public Nestable getTester2(String msg, Nestable n)
+ {
+ return new NestableErrorTester2(msg, (Throwable) n);
+ }
+
+ /**
+ * @see AbstractNestableTestCase#getTester2Class()
+ */
+ public Class getTester2Class()
+ {
+ return NestableErrorTester2.class;
+ }
+
+ /**
+ * @see AbstractNestableTestCase#getThrowable(String)
+ */
+ public Throwable getThrowable(String msg)
+ {
+ return new Error(msg);
+ }
+
+ /**
+ * @see AbstractNestableTestCase#getThrowableClass()
+ */
+ public Class getThrowableClass()
+ {
+ return Error.class;
+ }
+
+}
+
+/**
+ * First nestable tester implementation for use in test cases.
+ */
+class NestableErrorTester1 extends NestableError
+{
+ public NestableErrorTester1()
+ {
+ super();
+ }
+
+ public NestableErrorTester1(String reason, Throwable cause)
+ {
+ super(reason, cause);
+ }
+
+ public NestableErrorTester1(String reason)
+ {
+ super(reason);
+ }
+
+ public NestableErrorTester1(Throwable cause)
+ {
+ super(cause);
+ }
+
+}
+
+/**
+ * Second nestable tester implementation for use in test cases.
+ */
+class NestableErrorTester2 extends NestableError
+{
+ public NestableErrorTester2()
+ {
+ super();
+ }
+
+ public NestableErrorTester2(String reason, Throwable cause)
+ {
+ super(reason, cause);
+ }
+
+ public NestableErrorTester2(String reason)
+ {
+ super(reason);
+ }
+
+ public NestableErrorTester2(Throwable cause)
+ {
+ super(cause);
+ }
+
+}
diff --git a/examples/cl2/src/test/org/apache/commons/lang/exception/NestableExceptionTestCase.java b/examples/cl2/src/test/org/apache/commons/lang/exception/NestableExceptionTestCase.java
new file mode 100644
index 00000000..0c504774
--- /dev/null
+++ b/examples/cl2/src/test/org/apache/commons/lang/exception/NestableExceptionTestCase.java
@@ -0,0 +1,358 @@
+/* ====================================================================
+ * 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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
+ * .
+ */
+package org.apache.commons.lang.exception;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+import junit.textui.TestRunner;
+
+/**
+ * Tests the org.apache.commons.lang.exception.NestableException class.
+ *
+ * @author Steven Caswell
+ * @version $Id: NestableExceptionTestCase.java,v 1.8 2003/05/21 23:49:14 scolebourne Exp $
+ */
+public class NestableExceptionTestCase extends AbstractNestableTestCase {
+
+ /**
+ * Construct a new instance of
+ * NestableExceptionTestCase
.
+ *
+ * @param name test case name
+ */
+ public NestableExceptionTestCase(String name)
+ {
+ super(name);
+ }
+
+ /**
+ * Sets up instance variables required by this test case.
+ */
+ public void setUp()
+ {
+ }
+
+ /**
+ * Returns the test suite
+ *
+ * @return the test suite
+ */
+ public static Test suite()
+ {
+ return new TestSuite(NestableExceptionTestCase.class);
+ }
+
+ /**
+ * Tears down instance variables required by this test case.
+ */
+ public void tearDown()
+ {
+ }
+
+ /**
+ * Command line entry point for running the test suite.
+ *
+ * @param args array of command line arguments
+ */
+ public static void main(String args[])
+ {
+ TestRunner.run(suite());
+ }
+
+ /**
+ * @see AbstractNestableTestCase#getNestable()
+ */
+ public Nestable getNestable()
+ {
+ return new NestableException();
+ }
+
+ /**
+ * @see AbstractNestableTestCase#getNestable(Nestable)
+ */
+ public Nestable getNestable(Nestable n)
+ {
+ return new NestableException((Throwable) n);
+ }
+
+ /**
+ * @see AbstractNestableTestCase#getNestable(String)
+ */
+ public Nestable getNestable(String msg)
+ {
+ return new NestableException(msg);
+ }
+
+ /**
+ * @see AbstractNestableTestCase#getNestable(Throwable)
+ */
+ public Nestable getNestable(Throwable t)
+ {
+ return new NestableException(t);
+ }
+
+ /**
+ * @see AbstractNestableTestCase#getNestable(String, Throwable)
+ */
+ public Nestable getNestable(String msg, Throwable t)
+ {
+ return new NestableException(msg, t);
+ }
+
+ /**
+ * @see AbstractNestableTestCase#getNestable(String, Nestable)
+ */
+ public Nestable getNestable(String msg, Nestable n)
+ {
+ return new NestableException(msg, (Throwable) n);
+ }
+
+ /**
+ * @see AbstractNestableTestCase#getTester1(Throwable)
+ */
+ public Nestable getTester1(Throwable t)
+ {
+ return new NestableExceptionTester1(t);
+ }
+
+ /**
+ * @see AbstractNestableTestCase#getTester1(Nestable)
+ */
+ public Nestable getTester1(Nestable n)
+ {
+ return new NestableExceptionTester1((Throwable) n);
+ }
+
+ /**
+ * @see AbstractNestableTestCase#getTester1(String, Throwable)
+ */
+ public Nestable getTester1(String msg, Throwable t)
+ {
+ return new NestableExceptionTester1(msg, t);
+ }
+
+ /**
+ * @see AbstractNestableTestCase#getTester1(String, Nestable)
+ */
+ public Nestable getTester1(String msg, Nestable n)
+ {
+ return new NestableExceptionTester1(msg, (Throwable) n);
+ }
+
+ /**
+ * @see AbstractNestableTestCase#getTester1Class()
+ */
+ public Class getTester1Class()
+ {
+ return NestableExceptionTester1.class;
+ }
+
+ /**
+ * @see AbstractNestableTestCase#getTester2(String, Throwable)
+ */
+ public Nestable getTester2(String msg, Throwable t)
+ {
+ return new NestableExceptionTester2(msg, t);
+ }
+
+ /**
+ * @see AbstractNestableTestCase#getTester2(String, Nestable)
+ */
+ public Nestable getTester2(String msg, Nestable n)
+ {
+ return new NestableExceptionTester2(msg, (Throwable) n);
+ }
+
+ /**
+ * @see AbstractNestableTestCase#getTester2Class()
+ */
+ public Class getTester2Class()
+ {
+ return NestableExceptionTester2.class;
+ }
+
+ /**
+ * @see AbstractNestableTestCase#getThrowable(String)
+ */
+ public Throwable getThrowable(String msg)
+ {
+ return new Exception(msg);
+ }
+
+ /**
+ * @see AbstractNestableTestCase#getThrowableClass()
+ */
+ public Class getThrowableClass()
+ {
+ return Exception.class;
+ }
+
+ public void testSerialization()
+ throws java.io.IOException, ClassNotFoundException
+ {
+ RuntimeException nestedEx = new RuntimeException("nested exception message");
+ NestableExceptionTester1 ex = new NestableExceptionTester1("serialization test", nestedEx);
+
+ assertTrue( "implements java.io.Serializable", nestedEx instanceof java.io.Serializable);
+
+ assertTrue( "implements java.io.Serializable", ex instanceof java.io.Serializable);
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ ByteArrayInputStream bais = null;
+ ObjectOutputStream oos = null;
+ ObjectInputStream ois = null;
+
+ try
+ {
+ oos = new ObjectOutputStream(baos);
+ oos.writeObject(ex);
+ oos.flush();
+ bais = new ByteArrayInputStream(baos.toByteArray());
+ ois = new ObjectInputStream(bais);
+ NestableExceptionTester1 deserializedEx = (NestableExceptionTester1) ois.readObject();
+ assertEquals(
+ "getThrowableCount() return value",
+ ex.getThrowableCount(),
+ deserializedEx.getThrowableCount());
+
+ for (int i = 0; i < ex.getThrowableCount(); i++)
+ {
+ Throwable t = ex.getThrowable(i);
+ Throwable deserializedThrowable = deserializedEx.getThrowable(i);
+
+ assertEquals( t.getClass(),
+ deserializedThrowable.getClass());
+
+ assertEquals(
+ t.getMessage(),
+ deserializedThrowable.getMessage());
+ }
+ }
+ finally
+ {
+ if (null != oos)
+ {
+ try
+ {
+ oos.close();
+ }
+ catch (Exception ignored)
+ {
+ // intentionally empty
+ }
+ }
+ }
+
+ }
+}
+
+/**
+ * First nestable tester implementation for use in test cases.
+ */
+class NestableExceptionTester1 extends NestableException
+{
+ public NestableExceptionTester1()
+ {
+ super();
+ }
+
+ public NestableExceptionTester1(String reason, Throwable cause)
+ {
+ super(reason, cause);
+ }
+
+ public NestableExceptionTester1(String reason)
+ {
+ super(reason);
+ }
+
+ public NestableExceptionTester1(Throwable cause)
+ {
+ super(cause);
+ }
+
+}
+
+/**
+ * Second nestable tester implementation for use in test cases.
+ */
+class NestableExceptionTester2 extends NestableException
+{
+ public NestableExceptionTester2()
+ {
+ super();
+ }
+
+ public NestableExceptionTester2(String reason, Throwable cause)
+ {
+ super(reason, cause);
+ }
+
+ public NestableExceptionTester2(String reason)
+ {
+ super(reason);
+ }
+
+ public NestableExceptionTester2(Throwable cause)
+ {
+ super(cause);
+ }
+
+}
+
diff --git a/examples/cl2/src/test/org/apache/commons/lang/exception/NestableRuntimeExceptionTestCase.java b/examples/cl2/src/test/org/apache/commons/lang/exception/NestableRuntimeExceptionTestCase.java
new file mode 100644
index 00000000..c44deadc
--- /dev/null
+++ b/examples/cl2/src/test/org/apache/commons/lang/exception/NestableRuntimeExceptionTestCase.java
@@ -0,0 +1,296 @@
+/* ====================================================================
+ * 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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
+ * .
+ */
+package org.apache.commons.lang.exception;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+import junit.textui.TestRunner;
+
+/**
+ * Tests the org.apache.commons.lang.exception.NestableRuntimeException class.
+ *
+ * @author Steven Caswell
+ * @version $Id: NestableRuntimeExceptionTestCase.java,v 1.7 2003/05/21 23:49:14 scolebourne Exp $
+ */
+public class NestableRuntimeExceptionTestCase extends AbstractNestableTestCase {
+
+ /**
+ * Construct a new instance of
+ * NestableRuntimeExceptionTestCase
.
+ *
+ * @param name test case name
+ */
+ public NestableRuntimeExceptionTestCase(String name)
+ {
+ super(name);
+ }
+
+ /**
+ * Sets up instance variables required by this test case.
+ */
+ public void setUp()
+ {
+ }
+
+ /**
+ * Returns the test suite
+ *
+ * @return the test suite
+ */
+ public static Test suite()
+ {
+ return new TestSuite(NestableRuntimeExceptionTestCase.class);
+ }
+
+ /**
+ * Tears down instance variables required by this test case.
+ */
+ public void tearDown()
+ {
+ }
+
+ /**
+ * Command line entry point for running the test suite.
+ *
+ * @param args array of command line arguments
+ */
+ public static void main(String args[])
+ {
+ TestRunner.run(suite());
+ }
+
+ /**
+ * @see AbstractNestableTestCase#getNestable()
+ */
+ public Nestable getNestable()
+ {
+ return new NestableRuntimeException();
+ }
+
+ /**
+ * @see AbstractNestableTestCase#getNestable(Nestable)
+ */
+ public Nestable getNestable(Nestable n)
+ {
+ return new NestableRuntimeException((Throwable) n);
+ }
+
+ /**
+ * @see AbstractNestableTestCase#getNestable(String)
+ */
+ public Nestable getNestable(String msg)
+ {
+ return new NestableRuntimeException(msg);
+ }
+
+ /**
+ * @see AbstractNestableTestCase#getNestable(Throwable)
+ */
+ public Nestable getNestable(Throwable t)
+ {
+ return new NestableRuntimeException(t);
+ }
+
+ /**
+ * @see AbstractNestableTestCase#getNestable(String, Throwable)
+ */
+ public Nestable getNestable(String msg, Throwable t)
+ {
+ return new NestableRuntimeException(msg, t);
+ }
+
+ /**
+ * @see AbstractNestableTestCase#getNestable(String, Nestable)
+ */
+ public Nestable getNestable(String msg, Nestable n)
+ {
+ return new NestableRuntimeException(msg, (Throwable) n);
+ }
+
+ /**
+ * @see AbstractNestableTestCase#getTester1(Throwable)
+ */
+ public Nestable getTester1(Throwable t)
+ {
+ return new NestableRuntimeExceptionTester1(t);
+ }
+
+ /**
+ * @see AbstractNestableTestCase#getTester1(Nestable)
+ */
+ public Nestable getTester1(Nestable n)
+ {
+ return new NestableRuntimeExceptionTester1((Throwable) n);
+ }
+
+ /**
+ * @see AbstractNestableTestCase#getTester1(String, Throwable)
+ */
+ public Nestable getTester1(String msg, Throwable t)
+ {
+ return new NestableRuntimeExceptionTester1(msg, t);
+ }
+
+ /**
+ * @see AbstractNestableTestCase#getTester1(String, Nestable)
+ */
+ public Nestable getTester1(String msg, Nestable n)
+ {
+ return new NestableRuntimeExceptionTester1(msg, (Throwable) n);
+ }
+
+ /**
+ * @see AbstractNestableTestCase#getTester1Class()
+ */
+ public Class getTester1Class()
+ {
+ return NestableRuntimeExceptionTester1.class;
+ }
+
+ /**
+ * @see AbstractNestableTestCase#getTester2(String, Throwable)
+ */
+ public Nestable getTester2(String msg, Throwable t)
+ {
+ return new NestableRuntimeExceptionTester2(msg, t);
+ }
+
+ /**
+ * @see AbstractNestableTestCase#getTester2(String, Nestable)
+ */
+ public Nestable getTester2(String msg, Nestable n)
+ {
+ return new NestableRuntimeExceptionTester2(msg, (Throwable) n);
+ }
+
+ /**
+ * @see AbstractNestableTestCase#getTester2Class()
+ */
+ public Class getTester2Class()
+ {
+ return NestableRuntimeExceptionTester2.class;
+ }
+
+ /**
+ * @see AbstractNestableTestCase#getThrowable(String)
+ */
+ public Throwable getThrowable(String msg)
+ {
+ return new RuntimeException(msg);
+ }
+
+ /**
+ * @see AbstractNestableTestCase#getThrowableClass()
+ */
+ public Class getThrowableClass()
+ {
+ return RuntimeException.class;
+ }
+
+}
+
+/**
+ * First nestable tester implementation for use in test cases.
+ */
+class NestableRuntimeExceptionTester1 extends NestableRuntimeException
+{
+ public NestableRuntimeExceptionTester1()
+ {
+ super();
+ }
+
+ public NestableRuntimeExceptionTester1(String reason, Throwable cause)
+ {
+ super(reason, cause);
+ }
+
+ public NestableRuntimeExceptionTester1(String reason)
+ {
+ super(reason);
+ }
+
+ public NestableRuntimeExceptionTester1(Throwable cause)
+ {
+ super(cause);
+ }
+
+}
+
+/**
+ * Second nestable tester implementation.
+ */
+class NestableRuntimeExceptionTester2 extends NestableRuntimeException
+{
+ public NestableRuntimeExceptionTester2()
+ {
+ super();
+ }
+
+ public NestableRuntimeExceptionTester2(String reason, Throwable cause)
+ {
+ super(reason, cause);
+ }
+
+ public NestableRuntimeExceptionTester2(String reason)
+ {
+ super(reason);
+ }
+
+ public NestableRuntimeExceptionTester2(Throwable cause)
+ {
+ super(cause);
+ }
+
+}
+
diff --git a/examples/cl2/src/test/org/apache/commons/lang/math/AbstractRangeTest.java b/examples/cl2/src/test/org/apache/commons/lang/math/AbstractRangeTest.java
new file mode 100644
index 00000000..49a587d0
--- /dev/null
+++ b/examples/cl2/src/test/org/apache/commons/lang/math/AbstractRangeTest.java
@@ -0,0 +1,390 @@
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2002 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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
+ * .
+ */
+package org.apache.commons.lang.math;
+
+import junit.framework.TestCase;
+
+/**
+ * Test cases for the {@link Range} classes.
+ *
+ * @author Stephen Colebourne
+ * @version $Id: AbstractRangeTest.java,v 1.2 2003/06/08 14:19:43 scolebourne Exp $
+ */
+public abstract class AbstractRangeTest extends TestCase {
+
+ protected Range tenToTwenty;
+ protected Range otherRange;
+
+ protected Integer five;
+ protected Integer ten;
+ protected Integer twelve;
+ protected Integer fifteen;
+ protected Integer twenty;
+ protected Integer twentyFive;
+ protected Long long8;
+ protected Long long10;
+ protected Long long12;
+ protected Long long20;
+ protected Long long21;
+ protected Double double8;
+ protected Double double10;
+ protected Double double12;
+ protected Double double20;
+ protected Double double21;
+ protected Float float8;
+ protected Float float10;
+ protected Float float12;
+ protected Float float20;
+ protected Float float21;
+
+ private static class InnerNumber extends Number {
+ public double doubleValue() {
+ return 12d;
+ }
+ public float floatValue() {
+ return 12f;
+ }
+ public int intValue() {
+ return 12;
+ }
+ public long longValue() {
+ return 12L;
+ }
+
+ }
+
+ protected InnerNumber nonComparable = new InnerNumber();
+
+
+ public AbstractRangeTest(String name) {
+ super(name);
+ }
+
+ public void setUp() {
+ five = new Integer(5);
+ ten = new Integer(10);
+ twelve = new Integer(12);
+ fifteen = new Integer(15);
+ twenty = new Integer(20);
+ twentyFive = new Integer(25);
+ long8 = new Long(8);
+ long10 = new Long(10);
+ long12 = new Long(12);
+ long20 = new Long(20);
+ long21 = new Long(21);
+ double8 = new Double(8);
+ double10 = new Double(10);
+ double12 = new Double(12);
+ double20 = new Double(20);
+ double21 = new Double(21);
+ float8 = new Float(8);
+ float10 = new Float(10);
+ float12 = new Float(12);
+ float20 = new Float(20);
+ float21 = new Float(21);
+ }
+
+ //--------------------------------------------------------------------------
+
+ public void testGetMinimum() {
+ assertEquals(10L, tenToTwenty.getMinimumLong());
+ assertEquals(10, tenToTwenty.getMinimumInteger());
+ assertEquals(10d, tenToTwenty.getMinimumDouble(), 0.00001d);
+ assertEquals(10f, tenToTwenty.getMinimumFloat(), 0.00001f);
+ }
+
+ public void testGetMaximum() {
+ assertEquals(20L, tenToTwenty.getMaximumLong());
+ assertEquals(20, tenToTwenty.getMaximumInteger());
+ assertEquals(20d, tenToTwenty.getMaximumDouble(), 0.00001d);
+ assertEquals(20f, tenToTwenty.getMaximumFloat(), 0.00001f);
+ }
+
+ //--------------------------------------------------------------------------
+
+ public void testIncludesLong() {
+ assertEquals(false, tenToTwenty.includesLong(null));
+ assertEquals(true, tenToTwenty.includesLong(nonComparable));
+
+ assertEquals(false, tenToTwenty.includesLong(five));
+ assertEquals(true, tenToTwenty.includesLong(ten));
+ assertEquals(true, tenToTwenty.includesLong(fifteen));
+ assertEquals(true, tenToTwenty.includesLong(twenty));
+ assertEquals(false, tenToTwenty.includesLong(twentyFive));
+
+ assertEquals(false, tenToTwenty.includesLong(long8));
+ assertEquals(true, tenToTwenty.includesLong(long10));
+ assertEquals(true, tenToTwenty.includesLong(long12));
+ assertEquals(true, tenToTwenty.includesLong(long20));
+ assertEquals(false, tenToTwenty.includesLong(long21));
+
+ assertEquals(false, tenToTwenty.includesLong(double8));
+ assertEquals(true, tenToTwenty.includesLong(double10));
+ assertEquals(true, tenToTwenty.includesLong(double12));
+ assertEquals(true, tenToTwenty.includesLong(double20));
+ assertEquals(false, tenToTwenty.includesLong(double21));
+
+ assertEquals(false, tenToTwenty.includesLong(float8));
+ assertEquals(true, tenToTwenty.includesLong(float10));
+ assertEquals(true, tenToTwenty.includesLong(float12));
+ assertEquals(true, tenToTwenty.includesLong(float20));
+ assertEquals(false, tenToTwenty.includesLong(float21));
+
+ assertEquals(false, tenToTwenty.includesLong(9L));
+ assertEquals(true, tenToTwenty.includesLong(10L));
+ assertEquals(true, tenToTwenty.includesLong(15L));
+ assertEquals(true, tenToTwenty.includesLong(20L));
+ assertEquals(false, tenToTwenty.includesLong(21L));
+ }
+
+ public void testIncludesInteger() {
+ assertEquals(false, tenToTwenty.includesInteger(null));
+ assertEquals(true, tenToTwenty.includesInteger(nonComparable));
+
+ assertEquals(false, tenToTwenty.includesInteger(five));
+ assertEquals(true, tenToTwenty.includesInteger(ten));
+ assertEquals(true, tenToTwenty.includesInteger(fifteen));
+ assertEquals(true, tenToTwenty.includesInteger(twenty));
+ assertEquals(false, tenToTwenty.includesInteger(twentyFive));
+
+ assertEquals(false, tenToTwenty.includesInteger(long8));
+ assertEquals(true, tenToTwenty.includesInteger(long10));
+ assertEquals(true, tenToTwenty.includesInteger(long12));
+ assertEquals(true, tenToTwenty.includesInteger(long20));
+ assertEquals(false, tenToTwenty.includesInteger(long21));
+
+ assertEquals(false, tenToTwenty.includesInteger(double8));
+ assertEquals(true, tenToTwenty.includesInteger(double10));
+ assertEquals(true, tenToTwenty.includesInteger(double12));
+ assertEquals(true, tenToTwenty.includesInteger(double20));
+ assertEquals(false, tenToTwenty.includesInteger(double21));
+
+ assertEquals(false, tenToTwenty.includesInteger(float8));
+ assertEquals(true, tenToTwenty.includesInteger(float10));
+ assertEquals(true, tenToTwenty.includesInteger(float12));
+ assertEquals(true, tenToTwenty.includesInteger(float20));
+ assertEquals(false, tenToTwenty.includesInteger(float21));
+
+ assertEquals(false, tenToTwenty.includesInteger(9));
+ assertEquals(true, tenToTwenty.includesInteger(10));
+ assertEquals(true, tenToTwenty.includesInteger(15));
+ assertEquals(true, tenToTwenty.includesInteger(20));
+ assertEquals(false, tenToTwenty.includesInteger(21));
+ }
+
+ public void testIncludesDouble() {
+ assertEquals(false, tenToTwenty.includesDouble(null));
+ assertEquals(true, tenToTwenty.includesDouble(nonComparable));
+
+ assertEquals(false, tenToTwenty.includesDouble(five));
+ assertEquals(true, tenToTwenty.includesDouble(ten));
+ assertEquals(true, tenToTwenty.includesDouble(fifteen));
+ assertEquals(true, tenToTwenty.includesDouble(twenty));
+ assertEquals(false, tenToTwenty.includesDouble(twentyFive));
+
+ assertEquals(false, tenToTwenty.includesDouble(long8));
+ assertEquals(true, tenToTwenty.includesDouble(long10));
+ assertEquals(true, tenToTwenty.includesDouble(long12));
+ assertEquals(true, tenToTwenty.includesDouble(long20));
+ assertEquals(false, tenToTwenty.includesDouble(long21));
+
+ assertEquals(false, tenToTwenty.includesDouble(double8));
+ assertEquals(true, tenToTwenty.includesDouble(double10));
+ assertEquals(true, tenToTwenty.includesDouble(double12));
+ assertEquals(true, tenToTwenty.includesDouble(double20));
+ assertEquals(false, tenToTwenty.includesDouble(double21));
+
+ assertEquals(false, tenToTwenty.includesDouble(float8));
+ assertEquals(true, tenToTwenty.includesDouble(float10));
+ assertEquals(true, tenToTwenty.includesDouble(float12));
+ assertEquals(true, tenToTwenty.includesDouble(float20));
+ assertEquals(false, tenToTwenty.includesDouble(float21));
+
+ assertEquals(false, tenToTwenty.includesDouble(9d));
+ assertEquals(true, tenToTwenty.includesDouble(10d));
+ assertEquals(true, tenToTwenty.includesDouble(15d));
+ assertEquals(true, tenToTwenty.includesDouble(20d));
+ assertEquals(false, tenToTwenty.includesDouble(21d));
+ }
+
+ public void testIncludesFloat() {
+ assertEquals(false, tenToTwenty.includesFloat(null));
+ assertEquals(true, tenToTwenty.includesFloat(nonComparable));
+
+ assertEquals(false, tenToTwenty.includesFloat(five));
+ assertEquals(true, tenToTwenty.includesFloat(ten));
+ assertEquals(true, tenToTwenty.includesFloat(fifteen));
+ assertEquals(true, tenToTwenty.includesFloat(twenty));
+ assertEquals(false, tenToTwenty.includesFloat(twentyFive));
+
+ assertEquals(false, tenToTwenty.includesFloat(long8));
+ assertEquals(true, tenToTwenty.includesFloat(long10));
+ assertEquals(true, tenToTwenty.includesFloat(long12));
+ assertEquals(true, tenToTwenty.includesFloat(long20));
+ assertEquals(false, tenToTwenty.includesFloat(long21));
+
+ assertEquals(false, tenToTwenty.includesFloat(double8));
+ assertEquals(true, tenToTwenty.includesFloat(double10));
+ assertEquals(true, tenToTwenty.includesFloat(double12));
+ assertEquals(true, tenToTwenty.includesFloat(double20));
+ assertEquals(false, tenToTwenty.includesFloat(double21));
+
+ assertEquals(false, tenToTwenty.includesFloat(float8));
+ assertEquals(true, tenToTwenty.includesFloat(float10));
+ assertEquals(true, tenToTwenty.includesFloat(float12));
+ assertEquals(true, tenToTwenty.includesFloat(float20));
+ assertEquals(false, tenToTwenty.includesFloat(float21));
+
+ assertEquals(false, tenToTwenty.includesFloat(9f));
+ assertEquals(true, tenToTwenty.includesFloat(10f));
+ assertEquals(true, tenToTwenty.includesFloat(15f));
+ assertEquals(true, tenToTwenty.includesFloat(20f));
+ assertEquals(false, tenToTwenty.includesFloat(21f));
+ }
+
+ //--------------------------------------------------------------------------
+
+ public void testIncludesRange() {
+ assertEquals(false, tenToTwenty.includesRange(createRange(five, five)));
+ assertEquals(false, tenToTwenty.includesRange(createRange(five, ten)));
+ assertEquals(false, tenToTwenty.includesRange(createRange(five, twelve)));
+ assertEquals(false, tenToTwenty.includesRange(createRange(five, fifteen)));
+ assertEquals(false, tenToTwenty.includesRange(createRange(five, twenty)));
+ assertEquals(false, tenToTwenty.includesRange(createRange(five, twentyFive)));
+
+ assertEquals(true, tenToTwenty.includesRange(createRange(ten, ten)));
+ assertEquals(true, tenToTwenty.includesRange(createRange(ten, twelve)));
+ assertEquals(true, tenToTwenty.includesRange(createRange(ten, fifteen)));
+ assertEquals(true, tenToTwenty.includesRange(createRange(ten, twenty)));
+ assertEquals(false, tenToTwenty.includesRange(createRange(ten, twentyFive)));
+
+ assertEquals(true, tenToTwenty.includesRange(createRange(twelve, twelve)));
+ assertEquals(true, tenToTwenty.includesRange(createRange(twelve, fifteen)));
+ assertEquals(true, tenToTwenty.includesRange(createRange(twelve, twenty)));
+ assertEquals(false, tenToTwenty.includesRange(createRange(twelve, twentyFive)));
+
+ assertEquals(true, tenToTwenty.includesRange(createRange(fifteen, fifteen)));
+ assertEquals(true, tenToTwenty.includesRange(createRange(fifteen, twenty)));
+ assertEquals(false, tenToTwenty.includesRange(createRange(fifteen, twentyFive)));
+
+ assertEquals(true, tenToTwenty.includesRange(createRange(twenty, twenty)));
+ assertEquals(false, tenToTwenty.includesRange(createRange(twenty, twentyFive)));
+
+ assertEquals(false, tenToTwenty.includesRange(createRange(twentyFive, twentyFive)));
+ }
+
+ public void testOverlapsRange() {
+ assertEquals(false, tenToTwenty.overlapsRange(createRange(five, five)));
+ assertEquals(true, tenToTwenty.overlapsRange(createRange(five, ten)));
+ assertEquals(true, tenToTwenty.overlapsRange(createRange(five, twelve)));
+ assertEquals(true, tenToTwenty.overlapsRange(createRange(five, fifteen)));
+ assertEquals(true, tenToTwenty.overlapsRange(createRange(five, twenty)));
+ assertEquals(true, tenToTwenty.overlapsRange(createRange(five, twentyFive)));
+
+ assertEquals(true, tenToTwenty.overlapsRange(createRange(ten, ten)));
+ assertEquals(true, tenToTwenty.overlapsRange(createRange(ten, twelve)));
+ assertEquals(true, tenToTwenty.overlapsRange(createRange(ten, fifteen)));
+ assertEquals(true, tenToTwenty.overlapsRange(createRange(ten, twenty)));
+ assertEquals(true, tenToTwenty.overlapsRange(createRange(ten, twentyFive)));
+
+ assertEquals(true, tenToTwenty.overlapsRange(createRange(twelve, twelve)));
+ assertEquals(true, tenToTwenty.overlapsRange(createRange(twelve, fifteen)));
+ assertEquals(true, tenToTwenty.overlapsRange(createRange(twelve, twenty)));
+ assertEquals(true, tenToTwenty.overlapsRange(createRange(twelve, twentyFive)));
+
+ assertEquals(true, tenToTwenty.overlapsRange(createRange(fifteen, fifteen)));
+ assertEquals(true, tenToTwenty.overlapsRange(createRange(fifteen, twenty)));
+ assertEquals(true, tenToTwenty.overlapsRange(createRange(fifteen, twentyFive)));
+
+ assertEquals(true, tenToTwenty.overlapsRange(createRange(twenty, twenty)));
+ assertEquals(true, tenToTwenty.overlapsRange(createRange(twenty, twentyFive)));
+
+ assertEquals(false, tenToTwenty.overlapsRange(createRange(twentyFive, twentyFive)));
+ }
+
+ //--------------------------------------------------------------------------
+
+ public void testEquals() {
+ assertEquals(false, tenToTwenty.equals(createRange(ten, fifteen)));
+ assertEquals(false, tenToTwenty.equals(createRange(ten, twentyFive)));
+
+ assertEquals(false, tenToTwenty.equals(createRange(fifteen, twenty)));
+ assertEquals(false, tenToTwenty.equals(createRange(five, twenty)));
+
+ assertEquals(false, tenToTwenty.equals(createRange(five, ten)));
+ assertEquals(false, tenToTwenty.equals(createRange(ten)));
+
+ assertEquals(true, tenToTwenty.equals(createRange(ten, twenty)));
+ assertEquals(true, tenToTwenty.equals(createRange(twenty, ten)));
+
+ assertEquals(false, tenToTwenty.equals(null));
+ assertEquals(false, tenToTwenty.equals(new Object()));
+ assertEquals(false, tenToTwenty.equals(otherRange));
+ }
+
+ public void testHashCode() {
+ assertEquals(tenToTwenty.hashCode(), tenToTwenty.hashCode());
+ assertTrue(tenToTwenty.hashCode() != 0);
+ }
+
+ public void testToString() {
+ assertEquals("Range[10,20]", tenToTwenty.toString());
+ assertEquals("Range[-20,-10]", createRange(new Integer(-20), new Integer(-10)).toString());
+ }
+
+
+ protected abstract Range createRange(Integer integer);
+ protected abstract Range createRange(Integer integer1, Integer integer2);
+
+}
diff --git a/examples/cl2/src/test/org/apache/commons/lang/math/DoubleRangeTest.java b/examples/cl2/src/test/org/apache/commons/lang/math/DoubleRangeTest.java
new file mode 100644
index 00000000..a62f65ed
--- /dev/null
+++ b/examples/cl2/src/test/org/apache/commons/lang/math/DoubleRangeTest.java
@@ -0,0 +1,206 @@
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2002 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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
+ * .
+ */
+package org.apache.commons.lang.math;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+/**
+ * Test cases for the {@link DoubleRange} class.
+ *
+ * @author Stephen Colebourne
+ * @version $Id: DoubleRangeTest.java,v 1.2 2003/06/08 14:19:43 scolebourne Exp $
+ */
+public final class DoubleRangeTest extends AbstractRangeTest {
+
+ public DoubleRangeTest(String name) {
+ super(name);
+ }
+
+ public static Test suite() {
+ TestSuite suite = new TestSuite(DoubleRangeTest.class);
+ suite.setName("DoubleRange Tests");
+ return suite;
+ }
+
+ public void setUp() {
+ super.setUp();
+ tenToTwenty = new DoubleRange(double10, double20);
+ otherRange = new NumberRange(ten, twenty);
+ }
+
+ protected Range createRange(Integer integer1, Integer integer2) {
+ return new DoubleRange(integer1, integer2);
+ }
+ protected Range createRange(Integer integer) {
+ return new NumberRange(integer);
+ }
+
+ //--------------------------------------------------------------------------
+
+ public void testConstructor1a() {
+ DoubleRange nr = new DoubleRange(8d);
+ assertEquals(double8, nr.getMinimumNumber());
+ assertEquals(double8, nr.getMaximumNumber());
+
+ try {
+ new DoubleRange(Double.NaN);
+ fail();
+ } catch (IllegalArgumentException ex) {}
+ }
+
+ public void testConstructor1b() {
+ DoubleRange nr = new DoubleRange(double8);
+ assertSame(double8, nr.getMinimumNumber());
+ assertSame(double8, nr.getMaximumNumber());
+
+ Range r = new DoubleRange(nonComparable);
+
+ try {
+ new DoubleRange(null);
+ fail();
+ } catch (IllegalArgumentException ex) {}
+ try {
+ new DoubleRange(new Double(Double.NaN));
+ fail();
+ } catch (IllegalArgumentException ex) {}
+ }
+
+ public void testConstructor2a() {
+ DoubleRange nr = new DoubleRange(8d, 10d);
+ assertEquals(double8, nr.getMinimumNumber());
+ assertEquals(double10, nr.getMaximumNumber());
+
+ nr = new DoubleRange(10d, 8d);
+ assertEquals(double8, nr.getMinimumNumber());
+ assertEquals(double10, nr.getMaximumNumber());
+
+ try {
+ new DoubleRange(Double.NaN, 8d);
+ fail();
+ } catch (IllegalArgumentException ex) {}
+ }
+
+ public void testConstructor2b() {
+ DoubleRange nr = new DoubleRange(double8, double10);
+ assertSame(double8, nr.getMinimumNumber());
+ assertSame(double10, nr.getMaximumNumber());
+
+ nr = new DoubleRange(double10, double8);
+ assertSame(double8, nr.getMinimumNumber());
+ assertSame(double10, nr.getMaximumNumber());
+
+ nr = new DoubleRange(double8, double10);
+ assertSame(double8, nr.getMinimumNumber());
+ assertEquals(double10, nr.getMaximumNumber());
+
+ // not null
+ try {
+ new DoubleRange(double8, null);
+ fail();
+ } catch (IllegalArgumentException ex) {}
+ try {
+ new DoubleRange(null, double8);
+ fail();
+ } catch (IllegalArgumentException ex) {}
+ try {
+ new DoubleRange(null, null);
+ fail();
+ } catch (IllegalArgumentException ex) {}
+
+ try {
+ new DoubleRange(new Double(Double.NaN), double10);
+ fail();
+ } catch (IllegalArgumentException ex) {}
+ }
+
+ //--------------------------------------------------------------------------
+
+ public void testIncludesNumber() {
+ assertEquals(false, tenToTwenty.includesNumber(null));
+ assertEquals(true, tenToTwenty.includesNumber(nonComparable));
+
+ assertEquals(false, tenToTwenty.includesNumber(five));
+ assertEquals(true, tenToTwenty.includesNumber(ten));
+ assertEquals(true, tenToTwenty.includesNumber(fifteen));
+ assertEquals(true, tenToTwenty.includesNumber(twenty));
+ assertEquals(false, tenToTwenty.includesNumber(twentyFive));
+
+ assertEquals(false, tenToTwenty.includesNumber(long8));
+ assertEquals(true, tenToTwenty.includesNumber(long10));
+ assertEquals(true, tenToTwenty.includesNumber(long12));
+ assertEquals(true, tenToTwenty.includesNumber(long20));
+ assertEquals(false, tenToTwenty.includesNumber(long21));
+
+ assertEquals(false, tenToTwenty.includesNumber(double8));
+ assertEquals(true, tenToTwenty.includesNumber(double10));
+ assertEquals(true, tenToTwenty.includesNumber(double12));
+ assertEquals(true, tenToTwenty.includesNumber(double20));
+ assertEquals(false, tenToTwenty.includesNumber(double21));
+
+ assertEquals(false, tenToTwenty.includesNumber(float8));
+ assertEquals(true, tenToTwenty.includesNumber(float10));
+ assertEquals(true, tenToTwenty.includesNumber(float12));
+ assertEquals(true, tenToTwenty.includesNumber(float20));
+ assertEquals(false, tenToTwenty.includesNumber(float21));
+ }
+
+ public void testToString() {
+ assertEquals("Range[10.0,20.0]", tenToTwenty.toString());
+ assertEquals("Range[-20.0,-10.0]", createRange(new Integer(-20), new Integer(-10)).toString());
+ }
+
+ //--------------------------------------------------------------------------
+
+}
diff --git a/examples/cl2/src/test/org/apache/commons/lang/math/FloatRangeTest.java b/examples/cl2/src/test/org/apache/commons/lang/math/FloatRangeTest.java
new file mode 100644
index 00000000..76beb2f4
--- /dev/null
+++ b/examples/cl2/src/test/org/apache/commons/lang/math/FloatRangeTest.java
@@ -0,0 +1,206 @@
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2002 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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
+ * .
+ */
+package org.apache.commons.lang.math;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+/**
+ * Test cases for the {@link FloatRange} class.
+ *
+ * @author Stephen Colebourne
+ * @version $Id: FloatRangeTest.java,v 1.2 2003/06/08 14:19:43 scolebourne Exp $
+ */
+public final class FloatRangeTest extends AbstractRangeTest {
+
+ public FloatRangeTest(String name) {
+ super(name);
+ }
+
+ public static Test suite() {
+ TestSuite suite = new TestSuite(FloatRangeTest.class);
+ suite.setName("FloatRange Tests");
+ return suite;
+ }
+
+ public void setUp() {
+ super.setUp();
+ tenToTwenty = new FloatRange(float10, float20);
+ otherRange = new NumberRange(ten, twenty);
+ }
+
+ protected Range createRange(Integer integer1, Integer integer2) {
+ return new FloatRange(integer1, integer2);
+ }
+ protected Range createRange(Integer integer) {
+ return new NumberRange(integer);
+ }
+
+ //--------------------------------------------------------------------------
+
+ public void testConstructor1a() {
+ FloatRange nr = new FloatRange(8f);
+ assertEquals(float8, nr.getMinimumNumber());
+ assertEquals(float8, nr.getMaximumNumber());
+
+ try {
+ new FloatRange(Float.NaN);
+ fail();
+ } catch (IllegalArgumentException ex) {}
+ }
+
+ public void testConstructor1b() {
+ FloatRange nr = new FloatRange(float8);
+ assertSame(float8, nr.getMinimumNumber());
+ assertSame(float8, nr.getMaximumNumber());
+
+ Range r = new FloatRange(nonComparable);
+
+ try {
+ new FloatRange(null);
+ fail();
+ } catch (IllegalArgumentException ex) {}
+ try {
+ new FloatRange(new Double(Double.NaN));
+ fail();
+ } catch (IllegalArgumentException ex) {}
+ }
+
+ public void testConstructor2a() {
+ FloatRange nr = new FloatRange(8f, 10f);
+ assertEquals(float8, nr.getMinimumNumber());
+ assertEquals(float10, nr.getMaximumNumber());
+
+ nr = new FloatRange(10f, 8f);
+ assertEquals(float8, nr.getMinimumNumber());
+ assertEquals(float10, nr.getMaximumNumber());
+
+ try {
+ new FloatRange(Float.NaN, 8f);
+ fail();
+ } catch (IllegalArgumentException ex) {}
+ }
+
+ public void testConstructor2b() {
+ FloatRange nr = new FloatRange(float8, float10);
+ assertSame(float8, nr.getMinimumNumber());
+ assertSame(float10, nr.getMaximumNumber());
+
+ nr = new FloatRange(float10, float8);
+ assertSame(float8, nr.getMinimumNumber());
+ assertSame(float10, nr.getMaximumNumber());
+
+ nr = new FloatRange(float8, float10);
+ assertSame(float8, nr.getMinimumNumber());
+ assertEquals(float10, nr.getMaximumNumber());
+
+ // not null
+ try {
+ new FloatRange(float8, null);
+ fail();
+ } catch (IllegalArgumentException ex) {}
+ try {
+ new FloatRange(null, float8);
+ fail();
+ } catch (IllegalArgumentException ex) {}
+ try {
+ new FloatRange(null, null);
+ fail();
+ } catch (IllegalArgumentException ex) {}
+
+ try {
+ new FloatRange(new Double(Double.NaN), float10);
+ fail();
+ } catch (IllegalArgumentException ex) {}
+ }
+
+ //--------------------------------------------------------------------------
+
+ public void testIncludesNumber() {
+ assertEquals(false, tenToTwenty.includesNumber(null));
+ assertEquals(true, tenToTwenty.includesNumber(nonComparable));
+
+ assertEquals(false, tenToTwenty.includesNumber(five));
+ assertEquals(true, tenToTwenty.includesNumber(ten));
+ assertEquals(true, tenToTwenty.includesNumber(fifteen));
+ assertEquals(true, tenToTwenty.includesNumber(twenty));
+ assertEquals(false, tenToTwenty.includesNumber(twentyFive));
+
+ assertEquals(false, tenToTwenty.includesNumber(long8));
+ assertEquals(true, tenToTwenty.includesNumber(long10));
+ assertEquals(true, tenToTwenty.includesNumber(long12));
+ assertEquals(true, tenToTwenty.includesNumber(long20));
+ assertEquals(false, tenToTwenty.includesNumber(long21));
+
+ assertEquals(false, tenToTwenty.includesNumber(double8));
+ assertEquals(true, tenToTwenty.includesNumber(double10));
+ assertEquals(true, tenToTwenty.includesNumber(double12));
+ assertEquals(true, tenToTwenty.includesNumber(double20));
+ assertEquals(false, tenToTwenty.includesNumber(double21));
+
+ assertEquals(false, tenToTwenty.includesNumber(float8));
+ assertEquals(true, tenToTwenty.includesNumber(float10));
+ assertEquals(true, tenToTwenty.includesNumber(float12));
+ assertEquals(true, tenToTwenty.includesNumber(float20));
+ assertEquals(false, tenToTwenty.includesNumber(float21));
+ }
+
+ public void testToString() {
+ assertEquals("Range[10.0,20.0]", tenToTwenty.toString());
+ assertEquals("Range[-20.0,-10.0]", createRange(new Integer(-20), new Integer(-10)).toString());
+ }
+
+ //--------------------------------------------------------------------------
+
+}
diff --git a/examples/cl2/src/test/org/apache/commons/lang/math/FractionTest.java b/examples/cl2/src/test/org/apache/commons/lang/math/FractionTest.java
new file mode 100644
index 00000000..75fe6df4
--- /dev/null
+++ b/examples/cl2/src/test/org/apache/commons/lang/math/FractionTest.java
@@ -0,0 +1,888 @@
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2002 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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
+ * .
+ */
+package org.apache.commons.lang.math;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+/**
+ * Test cases for the {@link Fraction} classes.
+ *
+ * @author Stephen Colebourne
+ * @version $Id: FractionTest.java,v 1.2 2002/12/22 21:18:51 scolebourne Exp $
+ */
+public class FractionTest extends TestCase {
+
+ private static final int SKIP = 17;
+
+ public FractionTest(String name) {
+ super(name);
+ }
+
+ public static Test suite() {
+ TestSuite suite = new TestSuite(FractionTest.class);
+ suite.setName("Fraction Tests");
+ return suite;
+ }
+
+ public void setUp() {
+ }
+
+ //--------------------------------------------------------------------------
+
+ public void testConstants() {
+ assertEquals(0, Fraction.ZERO.getNumerator());
+ assertEquals(1, Fraction.ZERO.getDenominator());
+
+ assertEquals(1, Fraction.ONE.getNumerator());
+ assertEquals(1, Fraction.ONE.getDenominator());
+
+ assertEquals(1, Fraction.ONE_HALF.getNumerator());
+ assertEquals(2, Fraction.ONE_HALF.getDenominator());
+
+ assertEquals(1, Fraction.ONE_THIRD.getNumerator());
+ assertEquals(3, Fraction.ONE_THIRD.getDenominator());
+
+ assertEquals(2, Fraction.TWO_THIRDS.getNumerator());
+ assertEquals(3, Fraction.TWO_THIRDS.getDenominator());
+
+ assertEquals(1, Fraction.ONE_QUARTER.getNumerator());
+ assertEquals(4, Fraction.ONE_QUARTER.getDenominator());
+
+ assertEquals(2, Fraction.TWO_QUARTERS.getNumerator());
+ assertEquals(4, Fraction.TWO_QUARTERS.getDenominator());
+
+ assertEquals(3, Fraction.THREE_QUARTERS.getNumerator());
+ assertEquals(4, Fraction.THREE_QUARTERS.getDenominator());
+
+ assertEquals(1, Fraction.ONE_FIFTH.getNumerator());
+ assertEquals(5, Fraction.ONE_FIFTH.getDenominator());
+
+ assertEquals(2, Fraction.TWO_FIFTHS.getNumerator());
+ assertEquals(5, Fraction.TWO_FIFTHS.getDenominator());
+
+ assertEquals(3, Fraction.THREE_FIFTHS.getNumerator());
+ assertEquals(5, Fraction.THREE_FIFTHS.getDenominator());
+
+ assertEquals(4, Fraction.FOUR_FIFTHS.getNumerator());
+ assertEquals(5, Fraction.FOUR_FIFTHS.getDenominator());
+ }
+
+ public void testFactory_int_int() {
+ Fraction f = null;
+
+ // zero
+ f = Fraction.getFraction(0, 1);
+ assertEquals(0, f.getNumerator());
+ assertEquals(1, f.getDenominator());
+
+ f = Fraction.getFraction(0, 2);
+ assertEquals(0, f.getNumerator());
+ assertEquals(2, f.getDenominator());
+
+ // normal
+ f = Fraction.getFraction(1, 1);
+ assertEquals(1, f.getNumerator());
+ assertEquals(1, f.getDenominator());
+
+ f = Fraction.getFraction(2, 1);
+ assertEquals(2, f.getNumerator());
+ assertEquals(1, f.getDenominator());
+
+ f = Fraction.getFraction(23, 345);
+ assertEquals(23, f.getNumerator());
+ assertEquals(345, f.getDenominator());
+
+ // improper
+ f = Fraction.getFraction(22, 7);
+ assertEquals(22, f.getNumerator());
+ assertEquals(7, f.getDenominator());
+
+ // negatives
+ f = Fraction.getFraction(-6, 10);
+ assertEquals(-6, f.getNumerator());
+ assertEquals(10, f.getDenominator());
+
+ f = Fraction.getFraction(6, -10);
+ assertEquals(-6, f.getNumerator());
+ assertEquals(10, f.getDenominator());
+
+ f = Fraction.getFraction(-6, -10);
+ assertEquals(6, f.getNumerator());
+ assertEquals(10, f.getDenominator());
+
+ // zero denominator
+ try {
+ f = Fraction.getFraction(1, 0);
+ } catch (ArithmeticException ex) {}
+
+ try {
+ f = Fraction.getFraction(2, 0);
+ } catch (ArithmeticException ex) {}
+
+ try {
+ f = Fraction.getFraction(-3, 0);
+ } catch (ArithmeticException ex) {}
+ }
+
+ public void testFactory_int_int_int() {
+ Fraction f = null;
+
+ // zero
+ f = Fraction.getFraction(0, 0, 2);
+ assertEquals(0, f.getNumerator());
+ assertEquals(2, f.getDenominator());
+
+ f = Fraction.getFraction(2, 0, 2);
+ assertEquals(4, f.getNumerator());
+ assertEquals(2, f.getDenominator());
+
+ f = Fraction.getFraction(0, 1, 2);
+ assertEquals(1, f.getNumerator());
+ assertEquals(2, f.getDenominator());
+
+ // normal
+ f = Fraction.getFraction(1, 1, 2);
+ assertEquals(3, f.getNumerator());
+ assertEquals(2, f.getDenominator());
+
+ // negatives
+ try {
+ f = Fraction.getFraction(1, -6, -10);
+ } catch (ArithmeticException ex) {}
+
+ try {
+ f = Fraction.getFraction(1, -6, -10);
+ } catch (ArithmeticException ex) {}
+
+ try {
+ f = Fraction.getFraction(1, -6, -10);
+ } catch (ArithmeticException ex) {}
+
+ // negative whole
+ f = Fraction.getFraction(-1, 6, 10);
+ assertEquals(-16, f.getNumerator());
+ assertEquals(10, f.getDenominator());
+
+ try {
+ f = Fraction.getFraction(-1, -6, 10);
+ } catch (ArithmeticException ex) {}
+
+ try {
+ f = Fraction.getFraction(-1, 6, -10);
+ } catch (ArithmeticException ex) {}
+
+ try {
+ f = Fraction.getFraction(-1, -6, -10);
+ } catch (ArithmeticException ex) {}
+
+ // zero denominator
+ try {
+ f = Fraction.getFraction(0, 1, 0);
+ } catch (ArithmeticException ex) {}
+
+ try {
+ f = Fraction.getFraction(1, 2, 0);
+ } catch (ArithmeticException ex) {}
+
+ try {
+ f = Fraction.getFraction(-1, -3, 0);
+ } catch (ArithmeticException ex) {}
+ }
+
+ public void testReducedFactory_int_int() {
+ Fraction f = null;
+
+ // zero
+ f = Fraction.getReducedFraction(0, 1);
+ assertEquals(0, f.getNumerator());
+ assertEquals(1, f.getDenominator());
+
+ // normal
+ f = Fraction.getReducedFraction(1, 1);
+ assertEquals(1, f.getNumerator());
+ assertEquals(1, f.getDenominator());
+
+ f = Fraction.getReducedFraction(2, 1);
+ assertEquals(2, f.getNumerator());
+ assertEquals(1, f.getDenominator());
+
+ // improper
+ f = Fraction.getReducedFraction(22, 7);
+ assertEquals(22, f.getNumerator());
+ assertEquals(7, f.getDenominator());
+
+ // negatives
+ f = Fraction.getReducedFraction(-6, 10);
+ assertEquals(-3, f.getNumerator());
+ assertEquals(5, f.getDenominator());
+
+ f = Fraction.getReducedFraction(6, -10);
+ assertEquals(-3, f.getNumerator());
+ assertEquals(5, f.getDenominator());
+
+ f = Fraction.getReducedFraction(-6, -10);
+ assertEquals(3, f.getNumerator());
+ assertEquals(5, f.getDenominator());
+
+ // zero denominator
+ try {
+ f = Fraction.getReducedFraction(1, 0);
+ } catch (ArithmeticException ex) {}
+
+ try {
+ f = Fraction.getReducedFraction(2, 0);
+ } catch (ArithmeticException ex) {}
+
+ try {
+ f = Fraction.getReducedFraction(-3, 0);
+ } catch (ArithmeticException ex) {}
+
+ // reduced
+ f = Fraction.getReducedFraction(0, 2);
+ assertEquals(0, f.getNumerator());
+ assertEquals(1, f.getDenominator());
+
+ f = Fraction.getReducedFraction(2, 2);
+ assertEquals(1, f.getNumerator());
+ assertEquals(1, f.getDenominator());
+
+ f = Fraction.getReducedFraction(2, 4);
+ assertEquals(1, f.getNumerator());
+ assertEquals(2, f.getDenominator());
+
+ f = Fraction.getReducedFraction(15, 10);
+ assertEquals(3, f.getNumerator());
+ assertEquals(2, f.getDenominator());
+
+ f = Fraction.getReducedFraction(121, 22);
+ assertEquals(11, f.getNumerator());
+ assertEquals(2, f.getDenominator());
+ }
+
+ public void testFactory_double() {
+ Fraction f = null;
+
+ try {
+ f = Fraction.getFraction(Double.NaN);
+ } catch (ArithmeticException ex) {}
+
+ try {
+ f = Fraction.getFraction(Double.POSITIVE_INFINITY);
+ } catch (ArithmeticException ex) {}
+
+ try {
+ f = Fraction.getFraction(Double.NEGATIVE_INFINITY);
+ } catch (ArithmeticException ex) {}
+
+ // zero
+ f = Fraction.getFraction(0.0d);
+ assertEquals(0, f.getNumerator());
+ assertEquals(1, f.getDenominator());
+
+ // one
+ f = Fraction.getFraction(1.0d);
+ assertEquals(1, f.getNumerator());
+ assertEquals(1, f.getDenominator());
+
+ // one half
+ f = Fraction.getFraction(0.5d);
+ assertEquals(1, f.getNumerator());
+ assertEquals(2, f.getDenominator());
+
+ // negative
+ f = Fraction.getFraction(-0.875d);
+ assertEquals(-7, f.getNumerator());
+ assertEquals(8, f.getDenominator());
+
+ // over 1
+ f = Fraction.getFraction(1.25d);
+ assertEquals(5, f.getNumerator());
+ assertEquals(4, f.getDenominator());
+
+ // two thirds
+ f = Fraction.getFraction(0.66666d);
+ assertEquals(2, f.getNumerator());
+ assertEquals(3, f.getDenominator());
+
+ // small
+ f = Fraction.getFraction(1.0d/10001d);
+ assertEquals(0, f.getNumerator());
+ assertEquals(1, f.getDenominator());
+
+ // normal
+ Fraction f2 = null;
+ int remainder, number1, number2 = 0;
+ for (int i = 1; i <= 100; i++) { // denominator
+ for (int j = 1; j <= i; j++) { // numerator
+ try {
+ f = Fraction.getFraction((double) j / (double) i);
+ } catch (ArithmeticException ex) {
+ System.err.println(j + " " + i);
+ throw ex;
+ }
+ f2 = Fraction.getReducedFraction(j, i);
+ assertEquals(f2.getNumerator(), f.getNumerator());
+ assertEquals(f2.getDenominator(), f.getDenominator());
+ }
+ }
+ // save time by skipping some tests!
+ for (int i = 1001; i <= 10000; i+=SKIP) { // denominator
+ for (int j = 1; j <= i; j++) { // numerator
+ try {
+ f = Fraction.getFraction((double) j / (double) i);
+ } catch (ArithmeticException ex) {
+ System.err.println(j + " " + i);
+ throw ex;
+ }
+ f2 = Fraction.getReducedFraction(j, i);
+ assertEquals(f2.getNumerator(), f.getNumerator());
+ assertEquals(f2.getDenominator(), f.getDenominator());
+ }
+ }
+ }
+
+ public void testFactory_String() {
+ try {
+ Fraction.getFraction(null);
+ } catch (IllegalArgumentException ex) {}
+ }
+
+ public void testFactory_String_double() {
+ Fraction f = null;
+
+ f = Fraction.getFraction("0.0");
+ assertEquals(0, f.getNumerator());
+ assertEquals(1, f.getDenominator());
+
+ f = Fraction.getFraction("0.2");
+ assertEquals(1, f.getNumerator());
+ assertEquals(5, f.getDenominator());
+
+ f = Fraction.getFraction("0.5");
+ assertEquals(1, f.getNumerator());
+ assertEquals(2, f.getDenominator());
+
+ f = Fraction.getFraction("0.66666");
+ assertEquals(2, f.getNumerator());
+ assertEquals(3, f.getDenominator());
+
+ try {
+ f = Fraction.getFraction("2.3R");
+ } catch (NumberFormatException ex) {}
+
+ try {
+ f = Fraction.getFraction(".");
+ } catch (NumberFormatException ex) {}
+ }
+
+ public void testFactory_String_proper() {
+ Fraction f = null;
+
+ f = Fraction.getFraction("0 0/1");
+ assertEquals(0, f.getNumerator());
+ assertEquals(1, f.getDenominator());
+
+ f = Fraction.getFraction("1 1/5");
+ assertEquals(6, f.getNumerator());
+ assertEquals(5, f.getDenominator());
+
+ f = Fraction.getFraction("7 1/2");
+ assertEquals(15, f.getNumerator());
+ assertEquals(2, f.getDenominator());
+
+ f = Fraction.getFraction("1 2/4");
+ assertEquals(6, f.getNumerator());
+ assertEquals(4, f.getDenominator());
+
+ try {
+ f = Fraction.getFraction("2 3");
+ } catch (NumberFormatException ex) {}
+
+ try {
+ f = Fraction.getFraction("a 3");
+ } catch (NumberFormatException ex) {}
+
+ try {
+ f = Fraction.getFraction("2 b/4");
+ } catch (NumberFormatException ex) {}
+
+ try {
+ f = Fraction.getFraction("2 ");
+ } catch (NumberFormatException ex) {}
+
+ try {
+ f = Fraction.getFraction(" 3");
+ } catch (NumberFormatException ex) {}
+
+ try {
+ f = Fraction.getFraction(" ");
+ } catch (NumberFormatException ex) {}
+ }
+
+ public void testFactory_String_improper() {
+ Fraction f = null;
+
+ f = Fraction.getFraction("0/1");
+ assertEquals(0, f.getNumerator());
+ assertEquals(1, f.getDenominator());
+
+ f = Fraction.getFraction("1/5");
+ assertEquals(1, f.getNumerator());
+ assertEquals(5, f.getDenominator());
+
+ f = Fraction.getFraction("1/2");
+ assertEquals(1, f.getNumerator());
+ assertEquals(2, f.getDenominator());
+
+ f = Fraction.getFraction("2/3");
+ assertEquals(2, f.getNumerator());
+ assertEquals(3, f.getDenominator());
+
+ f = Fraction.getFraction("7/3");
+ assertEquals(7, f.getNumerator());
+ assertEquals(3, f.getDenominator());
+
+ f = Fraction.getFraction("2/4");
+ assertEquals(2, f.getNumerator());
+ assertEquals(4, f.getDenominator());
+
+ try {
+ f = Fraction.getFraction("2/d");
+ } catch (NumberFormatException ex) {}
+
+ try {
+ f = Fraction.getFraction("2e/3");
+ } catch (NumberFormatException ex) {}
+
+ try {
+ f = Fraction.getFraction("2/");
+ } catch (NumberFormatException ex) {}
+
+ try {
+ f = Fraction.getFraction("/");
+ } catch (NumberFormatException ex) {}
+ }
+
+ public void testGets() {
+ Fraction f = null;
+
+ f = Fraction.getFraction(3, 5, 6);
+ assertEquals(23, f.getNumerator());
+ assertEquals(3, f.getProperWhole());
+ assertEquals(5, f.getProperNumerator());
+ assertEquals(6, f.getDenominator());
+
+ f = Fraction.getFraction(-3, 5, 6);
+ assertEquals(-23, f.getNumerator());
+ assertEquals(-3, f.getProperWhole());
+ assertEquals(5, f.getProperNumerator());
+ assertEquals(6, f.getDenominator());
+ }
+
+ public void testConversions() {
+ Fraction f = null;
+
+ f = Fraction.getFraction(3, 7, 8);
+ assertEquals(3, f.intValue());
+ assertEquals(3L, f.longValue());
+ assertEquals(3.875f, f.floatValue(), 0.00001f);
+ assertEquals(3.875d, f.doubleValue(), 0.00001d);
+ }
+
+ public void testReduce() {
+ Fraction f = null;
+
+ f = Fraction.getFraction(50, 75);
+ f = f.reduce();
+ assertEquals(2, f.getNumerator());
+ assertEquals(3, f.getDenominator());
+ }
+
+ public void testInvert() {
+ Fraction f = null;
+
+ f = Fraction.getFraction(50, 75);
+ f = f.invert();
+ assertEquals(75, f.getNumerator());
+ assertEquals(50, f.getDenominator());
+
+ f = Fraction.getFraction(4, 3);
+ f = f.invert();
+ assertEquals(3, f.getNumerator());
+ assertEquals(4, f.getDenominator());
+
+ f = Fraction.getFraction(0, 3);
+ try {
+ f = f.invert();
+ } catch (ArithmeticException ex) {}
+ }
+
+ public void testNegate() {
+ Fraction f = null;
+
+ f = Fraction.getFraction(50, 75);
+ f = f.negate();
+ assertEquals(-50, f.getNumerator());
+ assertEquals(75, f.getDenominator());
+
+ f = Fraction.getFraction(-50, 75);
+ f = f.negate();
+ assertEquals(50, f.getNumerator());
+ assertEquals(75, f.getDenominator());
+ }
+
+ public void testAbs() {
+ Fraction f = null;
+
+ f = Fraction.getFraction(50, 75);
+ f = f.abs();
+ assertEquals(50, f.getNumerator());
+ assertEquals(75, f.getDenominator());
+
+ f = Fraction.getFraction(-50, 75);
+ f = f.abs();
+ assertEquals(50, f.getNumerator());
+ assertEquals(75, f.getDenominator());
+ }
+
+ public void testPow() {
+ Fraction f = null;
+
+ f = Fraction.getFraction(3, 5);
+ assertEquals(Fraction.ONE, f.pow(0));
+
+ f = Fraction.getFraction(3, 5);
+ assertSame(f, f.pow(1));
+
+ f = Fraction.getFraction(3, 5);
+ f = f.pow(2);
+ assertEquals(9, f.getNumerator());
+ assertEquals(25, f.getDenominator());
+
+ f = Fraction.getFraction(3, 5);
+ f = f.pow(3);
+ assertEquals(27, f.getNumerator());
+ assertEquals(125, f.getDenominator());
+
+ f = Fraction.getFraction(3, 5);
+ f = f.pow(-1);
+ assertEquals(5, f.getNumerator());
+ assertEquals(3, f.getDenominator());
+
+ f = Fraction.getFraction(3, 5);
+ f = f.pow(-2);
+ assertEquals(25, f.getNumerator());
+ assertEquals(9, f.getDenominator());
+ }
+
+ public void testAdd() {
+ Fraction f = null;
+ Fraction f1 = null;
+ Fraction f2 = null;
+
+ f1 = Fraction.getFraction(3, 5);
+ f2 = Fraction.getFraction(1, 5);
+ f = f1.add(f2);
+ assertEquals(4, f.getNumerator());
+ assertEquals(5, f.getDenominator());
+
+ f1 = Fraction.getFraction(3, 5);
+ f2 = Fraction.getFraction(2, 5);
+ f = f1.add(f2);
+ assertEquals(1, f.getNumerator());
+ assertEquals(1, f.getDenominator());
+
+ f1 = Fraction.getFraction(3, 5);
+ f2 = Fraction.getFraction(3, 5);
+ f = f1.add(f2);
+ assertEquals(6, f.getNumerator());
+ assertEquals(5, f.getDenominator());
+
+ f1 = Fraction.getFraction(3, 5);
+ f2 = Fraction.getFraction(-4, 5);
+ f = f1.add(f2);
+ assertEquals(-1, f.getNumerator());
+ assertEquals(5, f.getDenominator());
+
+ f1 = Fraction.getFraction(3, 5);
+ f2 = Fraction.getFraction(1, 2);
+ f = f1.add(f2);
+ assertEquals(11, f.getNumerator());
+ assertEquals(10, f.getDenominator());
+
+ f1 = Fraction.getFraction(0, 5);
+ f2 = Fraction.getFraction(1, 5);
+ f = f1.add(f2);
+ assertSame(f2, f);
+ f = f2.add(f1);
+ assertSame(f2, f);
+
+ try {
+ f.add(null);
+ } catch (IllegalArgumentException ex) {}
+ }
+
+ public void testSubtract() {
+ Fraction f = null;
+ Fraction f1 = null;
+ Fraction f2 = null;
+
+ f1 = Fraction.getFraction(3, 5);
+ f2 = Fraction.getFraction(1, 5);
+ f = f1.subtract(f2);
+ assertEquals(2, f.getNumerator());
+ assertEquals(5, f.getDenominator());
+
+ f1 = Fraction.getFraction(7, 5);
+ f2 = Fraction.getFraction(2, 5);
+ f = f1.subtract(f2);
+ assertEquals(1, f.getNumerator());
+ assertEquals(1, f.getDenominator());
+
+ f1 = Fraction.getFraction(3, 5);
+ f2 = Fraction.getFraction(3, 5);
+ f = f1.subtract(f2);
+ assertEquals(0, f.getNumerator());
+ assertEquals(1, f.getDenominator());
+
+ f1 = Fraction.getFraction(3, 5);
+ f2 = Fraction.getFraction(-4, 5);
+ f = f1.subtract(f2);
+ assertEquals(7, f.getNumerator());
+ assertEquals(5, f.getDenominator());
+
+ f1 = Fraction.getFraction(3, 5);
+ f2 = Fraction.getFraction(1, 2);
+ f = f1.subtract(f2);
+ assertEquals(1, f.getNumerator());
+ assertEquals(10, f.getDenominator());
+
+ f1 = Fraction.getFraction(0, 5);
+ f2 = Fraction.getFraction(1, 5);
+ f = f2.subtract(f1);
+ assertSame(f2, f);
+
+ try {
+ f.subtract(null);
+ } catch (IllegalArgumentException ex) {}
+ }
+
+ public void testMultiply() {
+ Fraction f = null;
+ Fraction f1 = null;
+ Fraction f2 = null;
+
+ f1 = Fraction.getFraction(3, 5);
+ f2 = Fraction.getFraction(2, 5);
+ f = f1.multiplyBy(f2);
+ assertEquals(6, f.getNumerator());
+ assertEquals(25, f.getDenominator());
+
+ f1 = Fraction.getFraction(3, 5);
+ f2 = Fraction.getFraction(-2, 5);
+ f = f1.multiplyBy(f2);
+ assertEquals(-6, f.getNumerator());
+ assertEquals(25, f.getDenominator());
+
+ f1 = Fraction.getFraction(-3, 5);
+ f2 = Fraction.getFraction(-2, 5);
+ f = f1.multiplyBy(f2);
+ assertEquals(6, f.getNumerator());
+ assertEquals(25, f.getDenominator());
+
+ f1 = Fraction.getFraction(0, 5);
+ f2 = Fraction.getFraction(2, 7);
+ f = f1.multiplyBy(f2);
+ assertSame(Fraction.ZERO, f);
+
+ try {
+ f.multiplyBy(null);
+ } catch (IllegalArgumentException ex) {}
+ }
+
+ public void testDivide() {
+ Fraction f = null;
+ Fraction f1 = null;
+ Fraction f2 = null;
+
+ f1 = Fraction.getFraction(3, 5);
+ f2 = Fraction.getFraction(2, 5);
+ f = f1.divideBy(f2);
+ assertEquals(3, f.getNumerator());
+ assertEquals(2, f.getDenominator());
+
+ f1 = Fraction.getFraction(3, 5);
+ f2 = Fraction.ZERO;
+ try {
+ f = f1.divideBy(f2);
+ } catch (ArithmeticException ex) {}
+
+ f1 = Fraction.getFraction(0, 5);
+ f2 = Fraction.getFraction(2, 7);
+ f = f1.divideBy(f2);
+ assertSame(Fraction.ZERO, f);
+
+ try {
+ f.divideBy(null);
+ } catch (IllegalArgumentException ex) {}
+ }
+
+ public void testEquals() {
+ Fraction f1 = null;
+ Fraction f2 = null;
+
+ f1 = Fraction.getFraction(3, 5);
+ assertEquals(false, f1.equals(null));
+ assertEquals(false, f1.equals(new Object()));
+ assertEquals(false, f1.equals(new Integer(6)));
+
+ f1 = Fraction.getFraction(3, 5);
+ f2 = Fraction.getFraction(2, 5);
+ assertEquals(false, f1.equals(f2));
+ assertEquals(true, f1.equals(f1));
+ assertEquals(true, f2.equals(f2));
+
+ f2 = Fraction.getFraction(3, 5);
+ assertEquals(true, f1.equals(f2));
+
+ f2 = Fraction.getFraction(6, 10);
+ assertEquals(false, f1.equals(f2));
+ }
+
+ public void testHashCode() {
+ Fraction f1 = Fraction.getFraction(3, 5);
+ Fraction f2 = Fraction.getFraction(3, 5);
+
+ assertTrue(f1.hashCode() == f2.hashCode());
+
+ f2 = Fraction.getFraction(2, 5);
+ assertTrue(f1.hashCode() != f2.hashCode());
+
+ f2 = Fraction.getFraction(6, 10);
+ assertTrue(f1.hashCode() != f2.hashCode());
+ }
+
+ public void testCompareTo() {
+ Fraction f1 = null;
+ Fraction f2 = null;
+
+ f1 = Fraction.getFraction(3, 5);
+
+ try {
+ f1.compareTo(null);
+ } catch (NullPointerException ex) {}
+
+ try {
+ f1.compareTo(new Object());
+ } catch (ClassCastException ex) {}
+
+ f2 = Fraction.getFraction(2, 5);
+ assertTrue(f1.compareTo(f2) > 0);
+
+ f2 = Fraction.getFraction(4, 5);
+ assertTrue(f1.compareTo(f2) < 0);
+
+ f2 = Fraction.getFraction(3, 5);
+ assertTrue(f1.compareTo(f2) == 0);
+
+ f2 = Fraction.getFraction(6, 10);
+ assertTrue(f1.compareTo(f2) == 0);
+ }
+
+ public void testToString() {
+ Fraction f = null;
+
+ f = Fraction.getFraction(3, 5);
+ assertEquals("3/5", f.toString());
+
+ f = Fraction.getFraction(7, 5);
+ assertEquals("7/5", f.toString());
+
+ f = Fraction.getFraction(4, 2);
+ assertEquals("4/2", f.toString());
+
+ f = Fraction.getFraction(0, 2);
+ assertEquals("0/2", f.toString());
+
+ f = Fraction.getFraction(2, 2);
+ assertEquals("2/2", f.toString());
+ }
+
+ public void testToProperString() {
+ Fraction f = null;
+
+ f = Fraction.getFraction(3, 5);
+ assertEquals("3/5", f.toProperString());
+
+ f = Fraction.getFraction(7, 5);
+ assertEquals("1 2/5", f.toProperString());
+
+ f = Fraction.getFraction(14, 10);
+ assertEquals("1 4/10", f.toProperString());
+
+ f = Fraction.getFraction(4, 2);
+ assertEquals("2", f.toProperString());
+
+ f = Fraction.getFraction(0, 2);
+ assertEquals("0", f.toProperString());
+
+ f = Fraction.getFraction(2, 2);
+ assertEquals("1", f.toProperString());
+
+ f = Fraction.getFraction(-7, 5);
+ assertEquals("-1 2/5", f.toProperString());
+ }
+
+}
diff --git a/examples/cl2/src/test/org/apache/commons/lang/math/IntRangeTest.java b/examples/cl2/src/test/org/apache/commons/lang/math/IntRangeTest.java
new file mode 100644
index 00000000..e3f70e35
--- /dev/null
+++ b/examples/cl2/src/test/org/apache/commons/lang/math/IntRangeTest.java
@@ -0,0 +1,188 @@
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2002 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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
+ * .
+ */
+package org.apache.commons.lang.math;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+/**
+ * Test cases for the {@link IntRange} class.
+ *
+ * @author Stephen Colebourne
+ * @version $Id: IntRangeTest.java,v 1.2 2003/06/08 14:19:43 scolebourne Exp $
+ */
+public final class IntRangeTest extends AbstractRangeTest {
+
+ public IntRangeTest(String name) {
+ super(name);
+ }
+
+ public static Test suite() {
+ TestSuite suite = new TestSuite(IntRangeTest.class);
+ suite.setName("IntRange Tests");
+ return suite;
+ }
+
+ public void setUp() {
+ super.setUp();
+ tenToTwenty = new IntRange(ten, twenty);
+ otherRange = new NumberRange(ten, twenty);
+ }
+
+ protected Range createRange(Integer integer1, Integer integer2) {
+ return new IntRange(integer1, integer2);
+ }
+ protected Range createRange(Integer integer) {
+ return new NumberRange(integer);
+ }
+
+ //--------------------------------------------------------------------------
+
+ public void testConstructor1a() {
+ IntRange nr = new IntRange(5);
+ assertEquals(five, nr.getMinimumNumber());
+ assertEquals(five, nr.getMaximumNumber());
+ }
+
+ public void testConstructor1b() {
+ IntRange nr = new IntRange(five);
+ assertSame(five, nr.getMinimumNumber());
+ assertSame(five, nr.getMaximumNumber());
+
+ Range r = new IntRange(nonComparable);
+
+ try {
+ new IntRange(null);
+ fail();
+ } catch (IllegalArgumentException ex) {}
+ }
+
+ public void testConstructor2a() {
+ IntRange nr = new IntRange(5, 10);
+ assertEquals(five, nr.getMinimumNumber());
+ assertEquals(ten, nr.getMaximumNumber());
+
+ nr = new IntRange(5, 10);
+ assertEquals(five, nr.getMinimumNumber());
+ assertEquals(ten, nr.getMaximumNumber());
+ }
+
+ public void testConstructor2b() {
+ IntRange nr = new IntRange(five, ten);
+ assertSame(five, nr.getMinimumNumber());
+ assertSame(ten, nr.getMaximumNumber());
+
+ nr = new IntRange(ten, five);
+ assertSame(five, nr.getMinimumNumber());
+ assertSame(ten, nr.getMaximumNumber());
+
+ nr = new IntRange(five, long10);
+ assertSame(five, nr.getMinimumNumber());
+ assertEquals(ten, nr.getMaximumNumber());
+
+ // not null
+ try {
+ new IntRange(five, null);
+ fail();
+ } catch (IllegalArgumentException ex) {}
+ try {
+ new IntRange(null, five);
+ fail();
+ } catch (IllegalArgumentException ex) {}
+ try {
+ new IntRange(null, null);
+ fail();
+ } catch (IllegalArgumentException ex) {}
+ }
+
+ //--------------------------------------------------------------------------
+
+ public void testIncludesNumber() {
+ assertEquals(false, tenToTwenty.includesNumber(null));
+ assertEquals(true, tenToTwenty.includesNumber(nonComparable));
+
+ assertEquals(false, tenToTwenty.includesNumber(five));
+ assertEquals(true, tenToTwenty.includesNumber(ten));
+ assertEquals(true, tenToTwenty.includesNumber(fifteen));
+ assertEquals(true, tenToTwenty.includesNumber(twenty));
+ assertEquals(false, tenToTwenty.includesNumber(twentyFive));
+
+ assertEquals(false, tenToTwenty.includesNumber(long8));
+ assertEquals(true, tenToTwenty.includesNumber(long10));
+ assertEquals(true, tenToTwenty.includesNumber(long12));
+ assertEquals(true, tenToTwenty.includesNumber(long20));
+ assertEquals(false, tenToTwenty.includesNumber(long21));
+
+ assertEquals(false, tenToTwenty.includesNumber(double8));
+ assertEquals(true, tenToTwenty.includesNumber(double10));
+ assertEquals(true, tenToTwenty.includesNumber(double12));
+ assertEquals(true, tenToTwenty.includesNumber(double20));
+ assertEquals(false, tenToTwenty.includesNumber(double21));
+
+ assertEquals(false, tenToTwenty.includesNumber(float8));
+ assertEquals(true, tenToTwenty.includesNumber(float10));
+ assertEquals(true, tenToTwenty.includesNumber(float12));
+ assertEquals(true, tenToTwenty.includesNumber(float20));
+ assertEquals(false, tenToTwenty.includesNumber(float21));
+ }
+
+ public void testIncludesIntegerBig() {
+ IntRange big = new IntRange(Integer.MAX_VALUE, Integer.MAX_VALUE- 2);
+ assertEquals(true, big.includesInteger(Integer.MAX_VALUE - 1));
+ assertEquals(false, big.includesInteger(Integer.MAX_VALUE - 3));
+ }
+
+ //--------------------------------------------------------------------------
+
+}
diff --git a/examples/cl2/src/test/org/apache/commons/lang/math/LongRangeTest.java b/examples/cl2/src/test/org/apache/commons/lang/math/LongRangeTest.java
new file mode 100644
index 00000000..c4d4c77c
--- /dev/null
+++ b/examples/cl2/src/test/org/apache/commons/lang/math/LongRangeTest.java
@@ -0,0 +1,188 @@
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2002 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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
+ * .
+ */
+package org.apache.commons.lang.math;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+/**
+ * Test cases for the {@link LongRange} class.
+ *
+ * @author Stephen Colebourne
+ * @version $Id: LongRangeTest.java,v 1.2 2003/06/08 14:19:43 scolebourne Exp $
+ */
+public final class LongRangeTest extends AbstractRangeTest {
+
+ public LongRangeTest(String name) {
+ super(name);
+ }
+
+ public static Test suite() {
+ TestSuite suite = new TestSuite(LongRangeTest.class);
+ suite.setName("LongRange Tests");
+ return suite;
+ }
+
+ public void setUp() {
+ super.setUp();
+ tenToTwenty = new LongRange(long10, long20);
+ otherRange = new NumberRange(ten, twenty);
+ }
+
+ protected Range createRange(Integer integer1, Integer integer2) {
+ return new LongRange(integer1, integer2);
+ }
+ protected Range createRange(Integer integer) {
+ return new NumberRange(integer);
+ }
+
+ //--------------------------------------------------------------------------
+
+ public void testConstructor1a() {
+ LongRange nr = new LongRange(8L);
+ assertEquals(long8, nr.getMinimumNumber());
+ assertEquals(long8, nr.getMaximumNumber());
+ }
+
+ public void testConstructor1b() {
+ LongRange nr = new LongRange(long8);
+ assertSame(long8, nr.getMinimumNumber());
+ assertSame(long8, nr.getMaximumNumber());
+
+ Range r = new LongRange(nonComparable);
+
+ try {
+ new LongRange(null);
+ fail();
+ } catch (IllegalArgumentException ex) {}
+ }
+
+ public void testConstructor2a() {
+ LongRange nr = new LongRange(8L, 10L);
+ assertEquals(long8, nr.getMinimumNumber());
+ assertEquals(long10, nr.getMaximumNumber());
+
+ nr = new LongRange(10L, 8L);
+ assertEquals(long8, nr.getMinimumNumber());
+ assertEquals(long10, nr.getMaximumNumber());
+ }
+
+ public void testConstructor2b() {
+ LongRange nr = new LongRange(long8, long10);
+ assertSame(long8, nr.getMinimumNumber());
+ assertSame(long10, nr.getMaximumNumber());
+
+ nr = new LongRange(long10, long8);
+ assertSame(long8, nr.getMinimumNumber());
+ assertSame(long10, nr.getMaximumNumber());
+
+ nr = new LongRange(long8, long10);
+ assertSame(long8, nr.getMinimumNumber());
+ assertEquals(long10, nr.getMaximumNumber());
+
+ // not null
+ try {
+ new LongRange(long8, null);
+ fail();
+ } catch (IllegalArgumentException ex) {}
+ try {
+ new LongRange(null, long8);
+ fail();
+ } catch (IllegalArgumentException ex) {}
+ try {
+ new LongRange(null, null);
+ fail();
+ } catch (IllegalArgumentException ex) {}
+ }
+
+ //--------------------------------------------------------------------------
+
+ public void testIncludesNumber() {
+ assertEquals(false, tenToTwenty.includesNumber(null));
+ assertEquals(true, tenToTwenty.includesNumber(nonComparable));
+
+ assertEquals(false, tenToTwenty.includesNumber(five));
+ assertEquals(true, tenToTwenty.includesNumber(ten));
+ assertEquals(true, tenToTwenty.includesNumber(fifteen));
+ assertEquals(true, tenToTwenty.includesNumber(twenty));
+ assertEquals(false, tenToTwenty.includesNumber(twentyFive));
+
+ assertEquals(false, tenToTwenty.includesNumber(long8));
+ assertEquals(true, tenToTwenty.includesNumber(long10));
+ assertEquals(true, tenToTwenty.includesNumber(long12));
+ assertEquals(true, tenToTwenty.includesNumber(long20));
+ assertEquals(false, tenToTwenty.includesNumber(long21));
+
+ assertEquals(false, tenToTwenty.includesNumber(double8));
+ assertEquals(true, tenToTwenty.includesNumber(double10));
+ assertEquals(true, tenToTwenty.includesNumber(double12));
+ assertEquals(true, tenToTwenty.includesNumber(double20));
+ assertEquals(false, tenToTwenty.includesNumber(double21));
+
+ assertEquals(false, tenToTwenty.includesNumber(float8));
+ assertEquals(true, tenToTwenty.includesNumber(float10));
+ assertEquals(true, tenToTwenty.includesNumber(float12));
+ assertEquals(true, tenToTwenty.includesNumber(float20));
+ assertEquals(false, tenToTwenty.includesNumber(float21));
+ }
+
+ public void testIncludesLongBig() {
+ LongRange big = new LongRange(Long.MAX_VALUE, Long.MAX_VALUE- 2);
+ assertEquals(true, big.includesLong(Long.MAX_VALUE - 1));
+ assertEquals(false, big.includesLong(Long.MAX_VALUE - 3));
+ }
+
+ //--------------------------------------------------------------------------
+
+}
diff --git a/examples/cl2/src/test/org/apache/commons/lang/math/MathTestSuite.java b/examples/cl2/src/test/org/apache/commons/lang/math/MathTestSuite.java
new file mode 100644
index 00000000..c938d670
--- /dev/null
+++ b/examples/cl2/src/test/org/apache/commons/lang/math/MathTestSuite.java
@@ -0,0 +1,97 @@
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2002 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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
+ * .
+ */
+package org.apache.commons.lang.math;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import junit.textui.TestRunner;
+/**
+ * Test suite for the Math package.
+ *
+ * @author Stephen Colebourne
+ * @version $Id: MathTestSuite.java,v 1.3 2003/05/14 02:41:26 bayard Exp $
+ */
+public class MathTestSuite extends TestCase {
+
+ /**
+ * Construct a new instance.
+ */
+ public MathTestSuite(String name) {
+ super(name);
+ }
+
+ /**
+ * Command-line interface.
+ */
+ public static void main(String[] args) {
+ TestRunner.run(suite());
+ }
+
+ /**
+ * Get the suite of tests
+ */
+ public static Test suite() {
+ TestSuite suite = new TestSuite();
+ suite.setName("Commons-Lang-Math Tests");
+ suite.addTest(DoubleRangeTest.suite());
+ suite.addTest(FloatRangeTest.suite());
+ suite.addTest(FractionTest.suite());
+ suite.addTest(IntRangeTest.suite());
+ suite.addTest(LongRangeTest.suite());
+ suite.addTest(NumberRangeTest.suite());
+ suite.addTest(RandomUtilsTest.suite());
+ return suite;
+ }
+}
diff --git a/examples/cl2/src/test/org/apache/commons/lang/math/NumberRangeTest.java b/examples/cl2/src/test/org/apache/commons/lang/math/NumberRangeTest.java
new file mode 100644
index 00000000..670c7273
--- /dev/null
+++ b/examples/cl2/src/test/org/apache/commons/lang/math/NumberRangeTest.java
@@ -0,0 +1,192 @@
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2002 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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
+ * .
+ */
+package org.apache.commons.lang.math;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+/**
+ * Test cases for the {@link NumberRange} class.
+ *
+ * @author Christopher Elkins
+ * @author Ringo De Smet
+ * @author Stephen Colebourne
+ * @version $Id: NumberRangeTest.java,v 1.2 2003/06/08 14:19:43 scolebourne Exp $
+ */
+public final class NumberRangeTest extends AbstractRangeTest {
+
+ public NumberRangeTest(String name) {
+ super(name);
+ }
+
+ public static Test suite() {
+ TestSuite suite = new TestSuite(NumberRangeTest.class);
+ suite.setName("NumberRange Tests");
+ return suite;
+ }
+
+ public void setUp() {
+ super.setUp();
+ tenToTwenty = new NumberRange(ten, twenty);
+ otherRange = new IntRange(ten, twenty);
+ }
+
+ protected Range createRange(Integer integer1, Integer integer2) {
+ return new NumberRange(integer1, integer2);
+ }
+ protected Range createRange(Integer integer) {
+ return new NumberRange(integer);
+ }
+
+ //--------------------------------------------------------------------------
+
+ public void testConstructor1() {
+ NumberRange nr = new NumberRange(five);
+ assertSame(five, nr.getMinimumNumber());
+ assertSame(five, nr.getMaximumNumber());
+
+ try {
+ new NumberRange(null);
+ fail();
+ } catch (IllegalArgumentException ex) {}
+ try {
+ new NumberRange(nonComparable);
+ fail();
+ } catch (IllegalArgumentException ex) {}
+ }
+
+ public void testConstructor2() {
+ NumberRange nr = new NumberRange(five, ten);
+ assertSame(five, nr.getMinimumNumber());
+ assertSame(ten, nr.getMaximumNumber());
+
+ nr = new NumberRange(ten, five);
+ assertSame(five, nr.getMinimumNumber());
+ assertSame(ten, nr.getMaximumNumber());
+
+ // not null
+ try {
+ new NumberRange(five, null);
+ fail();
+ } catch (IllegalArgumentException ex) {}
+ try {
+ new NumberRange(null, five);
+ fail();
+ } catch (IllegalArgumentException ex) {}
+ try {
+ new NumberRange(null, null);
+ fail();
+ } catch (IllegalArgumentException ex) {}
+
+ // no mixed types
+ try {
+ new NumberRange(five, long21);
+ fail();
+ } catch (IllegalArgumentException ex) {}
+
+ // must be comparable
+ try {
+ new NumberRange(nonComparable, nonComparable);
+ fail();
+ } catch (IllegalArgumentException ex) {}
+
+ // no double NaN
+ try {
+ new NumberRange(new Double(0), new Double(Double.NaN));
+ fail();
+ } catch (IllegalArgumentException ex) {}
+
+ try {
+ new NumberRange(new Double(Double.NaN), new Double(0));
+ fail();
+ } catch (IllegalArgumentException ex) {}
+
+ // no float NaN
+ try {
+ new NumberRange(new Float(0), new Float(Float.NaN));
+ fail();
+ } catch (IllegalArgumentException ex) {}
+
+ try {
+ new NumberRange(new Float(Float.NaN), new Float(0));
+ fail();
+ } catch (IllegalArgumentException ex) {}
+ }
+
+ //--------------------------------------------------------------------------
+
+ public void testIncludesNumber() {
+ assertEquals(false, tenToTwenty.includesNumber(null));
+ assertEquals(false, tenToTwenty.includesNumber(five));
+ assertEquals(true, tenToTwenty.includesNumber(ten));
+ assertEquals(true, tenToTwenty.includesNumber(fifteen));
+ assertEquals(true, tenToTwenty.includesNumber(twenty));
+ assertEquals(false, tenToTwenty.includesNumber(twentyFive));
+
+ try {
+ tenToTwenty.includesNumber(long21);
+ fail();
+ } catch (IllegalArgumentException ex) {}
+ }
+
+ public void testIncludesLongBig() {
+ // original NumberRange class failed this test
+ NumberRange big = new NumberRange(new Long(Long.MAX_VALUE), new Long(Long.MAX_VALUE- 2));
+ assertEquals(true, big.includesLong(Long.MAX_VALUE - 1));
+ assertEquals(false, big.includesLong(Long.MAX_VALUE - 3));
+ }
+
+ //--------------------------------------------------------------------------
+
+}
diff --git a/examples/cl2/src/test/org/apache/commons/lang/math/RandomUtilsTest.java b/examples/cl2/src/test/org/apache/commons/lang/math/RandomUtilsTest.java
new file mode 100644
index 00000000..bad8bd67
--- /dev/null
+++ b/examples/cl2/src/test/org/apache/commons/lang/math/RandomUtilsTest.java
@@ -0,0 +1,335 @@
+/* ====================================================================
+ * 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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
+ * .
+ */
+package org.apache.commons.lang.math;
+
+import java.util.Random;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+/**
+ * Test cases for the {@link RandomUtils} class.
+ *
+ * @author Phil Steitz
+ * @version $Revision: 1.3 $ $Date: 2003/06/09 21:36:03 $
+ */
+
+public final class RandomUtilsTest extends TestCase {
+
+ public RandomUtilsTest(String name) {
+ super(name);
+ }
+
+ public void setUp() {
+ }
+
+ public static Test suite() {
+ TestSuite suite = new TestSuite(RandomUtilsTest.class);
+ suite.setName("RandomUtils Tests");
+ return suite;
+ }
+
+ /** test distribution of nextInt() */
+ public void testNextInt() {
+ tstNextInt(null);
+ }
+
+ /** test distribution of nextInt(Random) */
+ public void testNextInt2() {
+ Random rnd = new Random();
+ rnd.setSeed(System.currentTimeMillis());
+ tstNextInt(rnd);
+ }
+
+ /**
+ * Generate 1000 values for nextInt(bound) and compare
+ * the observed frequency counts to expected counts using
+ * a chi-square test.
+ * @param rnd Random to use if not null
+ */
+ private void tstNextInt(Random rnd) {
+ int bound = 0;
+ int result = 0;
+ // test boundary condition: n = Integer.MAX_VALUE;
+ bound = Integer.MAX_VALUE;
+ if (rnd == null) {
+ result = RandomUtils.nextInt(bound);
+ } else {
+ result = RandomUtils.nextInt(rnd,bound);
+ }
+ assertTrue("result less than bound",result < bound);
+ assertTrue("result non-negative",result >= 0);
+
+ // test uniformity -- use Chi-Square test at .01 level
+ bound = 4;
+ int[] expected = new int[] {250,250,250,250};
+ int[] observed = new int[] {0,0,0,0};
+ for (int i = 0; i < 1000; i ++) {
+ if (rnd == null) {
+ result = RandomUtils.nextInt(bound);
+ } else {
+ result = RandomUtils.nextInt(rnd,bound);
+ }
+ assertTrue(result < bound);
+ assertTrue(result >= 0);
+ observed[result]++;
+ }
+ /* Use ChiSquare dist with df = 4-1 = 3, alpha = .001
+ * Change to 11.34 for alpha = .01
+ */
+ assertTrue(
+ "chi-square test -- will fail about 1 in 1000 times",
+ chiSquare(expected,observed) < 16.27);
+ }
+
+ /** test distribution of nextLong() */
+ public void testNextLong() {
+ tstNextLong(null);
+ }
+
+ /** test distribution of nextLong(Random) BROKEN
+ * contract of nextLong(Random) is different from
+ * nextLong() */
+ public void testNextLong2() {
+ Random rnd = new Random();
+ rnd.setSeed(System.currentTimeMillis());
+ tstNextLong(rnd);
+ }
+
+ /**
+ * Generate 1000 values for nextLong and check that
+ * p(value < long.MAXVALUE/2) ~ 0.5. Use chi-square test
+ * with df = 2-1 = 1
+ * @param rnd Random to use if not null
+ */
+ private void tstNextLong(Random rnd) {
+ int[] expected = new int[] {500,500};
+ int[] observed = new int[] {0,0};
+ long result = 0;
+ long midPoint = Long.MAX_VALUE/2;
+ for (int i = 0; i < 1000; i ++) {
+ if (rnd == null) {
+ result = Math.abs(RandomUtils.nextLong());
+ } else {
+ result = Math.abs(RandomUtils.nextLong(rnd));
+ }
+ if (result < midPoint) {
+ observed[0]++;
+ } else {
+ observed[1]++;
+ }
+ }
+ /* Use ChiSquare dist with df = 2-1 = 1, alpha = .001
+ * Change to 6.64 for alpha = .01
+ */
+ assertTrue(
+ "chi-square test -- will fail about 1 in 1000 times",
+ chiSquare(expected,observed) < 10.83);
+ }
+
+
+ /** test distribution of nextBoolean() */
+ public void testNextBoolean() {
+ tstNextBoolean(null);
+ }
+
+ /** test distribution of nextBoolean(Random) */
+ public void testNextBoolean2() {
+ Random rnd = new Random();
+ rnd.setSeed(System.currentTimeMillis());
+ tstNextBoolean(rnd);
+ }
+
+ /**
+ * Generate 1000 values for nextBoolean and check that
+ * p(value = false) ~ 0.5. Use chi-square test
+ * with df = 2-1 = 1
+ * @param rnd Random to use if not null
+ */
+ private void tstNextBoolean(Random rnd) {
+ int[] expected = new int[] {500,500};
+ int[] observed = new int[] {0,0};
+ boolean result = false;
+ for (int i = 0; i < 1000; i ++) {
+ if (rnd == null) {
+ result = RandomUtils.nextBoolean();
+ } else {
+ result = RandomUtils.nextBoolean(rnd);
+ }
+ if (result) {
+ observed[0]++;
+ } else {
+ observed[1]++;
+ }
+ }
+ /* Use ChiSquare dist with df = 2-1 = 1, alpha = .001
+ * Change to 6.64 for alpha = .01
+ */
+ assertTrue(
+ "chi-square test -- will fail about 1 in 1000 times",
+ chiSquare(expected,observed) < 10.83 );
+ }
+
+ /** test distribution of nextFloat() */
+ public void testNextFloat() {
+ tstNextFloat(null);
+ }
+
+ /** test distribution of nextFloat(Random) */
+ public void testNextFloat2() {
+ Random rnd = new Random();
+ rnd.setSeed(System.currentTimeMillis());
+ tstNextFloat(rnd);
+ }
+
+ /**
+ * Generate 1000 values for nextFloat and check that
+ * p(value < 0.5) ~ 0.5. Use chi-square test
+ * with df = 2-1 = 1
+ * @param rnd Random to use if not null
+ */
+ private void tstNextFloat(Random rnd) {
+ int[] expected = new int[] {500,500};
+ int[] observed = new int[] {0,0};
+ float result = 0;
+ for (int i = 0; i < 1000; i ++) {
+ if (rnd == null) {
+ result = RandomUtils.nextFloat();
+ } else {
+ result = RandomUtils.nextFloat(rnd);
+ }
+ if (result < 0.5) {
+ observed[0]++;
+ } else {
+ observed[1]++;
+ }
+ }
+ /* Use ChiSquare dist with df = 2-1 = 1, alpha = .001
+ * Change to 6.64 for alpha = .01
+ */
+ assertTrue(
+ "chi-square test -- will fail about 1 in 1000 times",
+ chiSquare(expected,observed) < 10.83);
+ }
+
+ /** test distribution of nextDouble() */
+ public void testNextDouble() {
+ tstNextDouble(null);
+ }
+
+ /** test distribution of nextDouble(Random) */
+ public void testNextDouble2() {
+ Random rnd = new Random();
+ rnd.setSeed(System.currentTimeMillis());
+ tstNextDouble(rnd);
+ }
+
+ /**
+ * Generate 1000 values for nextFloat and check that
+ * p(value < 0.5) ~ 0.5. Use chi-square test
+ * with df = 2-1 = 1
+ * @param rnd Random to use if not null
+ */
+ private void tstNextDouble(Random rnd) {
+ int[] expected = new int[] {500,500};
+ int[] observed = new int[] {0,0};
+ double result = 0;
+ for (int i = 0; i < 1000; i ++) {
+ if (rnd == null) {
+ result = RandomUtils.nextDouble();
+ } else {
+ result = RandomUtils.nextDouble(rnd);
+ }
+ if (result < 0.5) {
+ observed[0]++;
+ } else {
+ observed[1]++;
+ }
+ }
+ /* Use ChiSquare dist with df = 2-1 = 1, alpha = .001
+ * Change to 6.64 for alpha = .01
+ */
+ assertTrue(
+ "chi-square test -- will fail about 1 in 1000 times",
+ chiSquare(expected,observed) < 10.83);
+ }
+
+ /** make sure that setSeed fails */
+ public void testSetSeed() {
+ try {
+ RandomUtils.JVM_RANDOM.setSeed(1000);
+ fail("expecting UnsupportedOperationException");
+ } catch (UnsupportedOperationException ex) {
+ ;
+ }
+ }
+
+ /**
+ * Computes Chi-Square statistic given observed and expected counts
+ * @param observed array of observed frequency counts
+ * @param expected array of exptected frequency counts
+ */
+ private double chiSquare(int[] expected, int[] observed) {
+ double sumSq = 0.0d;
+ double dev = 0.0d;
+ for (int i = 0; i< observed.length; i++) {
+ dev = (double)(observed[i] - expected[i]);
+ sumSq += dev*dev/(double)expected[i];
+ }
+ return sumSq;
+ }
+
+}
+
diff --git a/examples/cl2/src/test/org/apache/commons/lang/reflect/AbstractChild.java b/examples/cl2/src/test/org/apache/commons/lang/reflect/AbstractChild.java
new file mode 100644
index 00000000..ec9d78d3
--- /dev/null
+++ b/examples/cl2/src/test/org/apache/commons/lang/reflect/AbstractChild.java
@@ -0,0 +1,74 @@
+/*
+ * ====================================================================
+ *
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 1999-2002 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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 Group.
+ *
+ * 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
+ * .
+ *
+ */
+
+package org.apache.commons.lang.reflect;
+
+public class AbstractChild implements Child {
+
+ private String name;
+
+ protected void setName(String name)
+ {
+ this.name = name;
+ }
+
+ public String getName()
+ {
+ return name;
+ }
+
+}
diff --git a/examples/cl2/src/test/org/apache/commons/lang/reflect/AbstractParent.java b/examples/cl2/src/test/org/apache/commons/lang/reflect/AbstractParent.java
new file mode 100644
index 00000000..bdd560b1
--- /dev/null
+++ b/examples/cl2/src/test/org/apache/commons/lang/reflect/AbstractParent.java
@@ -0,0 +1,94 @@
+/*
+ * ====================================================================
+ *
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 1999-2002 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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 Group.
+ *
+ * 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
+ * .
+ *
+ */
+
+package org.apache.commons.lang.reflect;
+
+public abstract class AbstractParent {
+
+ private Child child;
+
+ public Child getChild()
+ {
+ return child;
+ }
+
+ /**
+ * Method which matches signature but which has wrong parameters
+ */
+ public String testAddChild(String badParameter) {
+ return null;
+ }
+
+ /**
+ * Method which matches signature but which has wrong parameters
+ */
+ public String testAddChild2(String ignore, String badParameter) {
+ return null;
+ }
+
+ public String testAddChild(Child child) {
+ this.child = child;
+ return child.getName();
+ }
+
+
+ public String testAddChild2(String ignore, Child child) {
+ this.child = child;
+ return child.getName();
+ }
+
+}
diff --git a/examples/cl2/src/test/org/apache/commons/lang/reflect/AlphaBean.java b/examples/cl2/src/test/org/apache/commons/lang/reflect/AlphaBean.java
new file mode 100644
index 00000000..1e0daa03
--- /dev/null
+++ b/examples/cl2/src/test/org/apache/commons/lang/reflect/AlphaBean.java
@@ -0,0 +1,80 @@
+/*
+ * ====================================================================
+ *
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 1999-2002 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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 Group.
+ *
+ * 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
+ * .
+ *
+ */
+
+package org.apache.commons.lang.reflect;
+
+public class AlphaBean extends AbstractParent implements Child {
+
+ private String name;
+
+ public AlphaBean(String name) {
+ setName(name);
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ /**
+ * Used for testing that correct exception is thrown.
+ */
+ public void bogus(String badParameter){}
+}
diff --git a/examples/cl2/src/test/org/apache/commons/lang/reflect/BetaBean.java b/examples/cl2/src/test/org/apache/commons/lang/reflect/BetaBean.java
new file mode 100644
index 00000000..5305305e
--- /dev/null
+++ b/examples/cl2/src/test/org/apache/commons/lang/reflect/BetaBean.java
@@ -0,0 +1,65 @@
+/*
+ * ====================================================================
+ *
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 1999-2002 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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 Group.
+ *
+ * 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
+ * .
+ *
+ */
+
+package org.apache.commons.lang.reflect;
+
+public class BetaBean extends AbstractChild {
+
+ public BetaBean(String name) {
+ setName(name);
+ }
+}
diff --git a/examples/cl2/src/test/org/apache/commons/lang/reflect/Child.java b/examples/cl2/src/test/org/apache/commons/lang/reflect/Child.java
new file mode 100644
index 00000000..f7a7dd54
--- /dev/null
+++ b/examples/cl2/src/test/org/apache/commons/lang/reflect/Child.java
@@ -0,0 +1,64 @@
+/*
+ * ====================================================================
+ *
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 1999-2002 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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 Group.
+ *
+ * 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
+ * .
+ *
+ */
+
+
+package org.apache.commons.lang.reflect;
+
+public interface Child {
+
+ public String getName();
+}
diff --git a/examples/cl2/src/test/org/apache/commons/lang/reflect/MethodUtilsTestCase.java b/examples/cl2/src/test/org/apache/commons/lang/reflect/MethodUtilsTestCase.java
new file mode 100644
index 00000000..6dc2e8d0
--- /dev/null
+++ b/examples/cl2/src/test/org/apache/commons/lang/reflect/MethodUtilsTestCase.java
@@ -0,0 +1,582 @@
+/*
+ * ====================================================================
+ *
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 1999-2002 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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 Group.
+ *
+ * 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
+ * .
+ *
+ */
+package org.apache.commons.lang.reflect;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+import org.apache.commons.lang.reflect.priv.PrivateBeanFactory;
+import org.apache.commons.lang.reflect.priv.PublicSubBean;
+
+/**
+ * Test case for MethodUtils
+ *
+ */
+public class MethodUtilsTestCase extends TestCase {
+
+ // ---------------------------------------------------- Instance Variables
+
+ protected PrivateBeanFactory privateBeanFactory;
+
+ // ---------------------------------------------------------- Constructors
+
+ /**
+ * Construct a new instance of this test case.
+ *
+ * @param name Name of the test case
+ */
+ public MethodUtilsTestCase(String name) {
+ super(name);
+ }
+
+
+ // -------------------------------------------------- Overall Test Methods
+
+
+ /**
+ * Set up instance variables required by this test case.
+ */
+ public void setUp() {
+ privateBeanFactory = new PrivateBeanFactory();
+ }
+
+
+ /**
+ * Return the tests included in this test suite.
+ */
+ public static Test suite() {
+ return (new TestSuite(MethodUtilsTestCase.class));
+ }
+
+ /**
+ * Tear down instance variables required by this test case.
+ */
+ public void tearDown() {
+ privateBeanFactory = null;
+ }
+
+
+ // ------------------------------------------------ Individual Test Methods
+
+ /**
+ * Test getAccessibleMethod
.
+ */
+ public void testGetAccessibleMethod() {
+ // test MethodUtils.getAccessibleMethod
+ // we'll make things easier by using the convenience methods
+
+ // easy bit first - find a public method
+ // METHOD ONE
+ Method method = MethodUtils.getMethod
+ (TestBean.class, "setStringProperty", String.class);
+
+ // check that we've found one that matches
+ assertNotNull(method);
+ assertEquals("method ONE is named correctly",
+ "setStringProperty", method.getName());
+ assertTrue("Method ONE is public",
+ Modifier.isPublic(method.getModifiers()));
+
+ // trickier this one - find a method in a direct interface
+ // METHOD TWO
+ method = MethodUtils.getMethod
+ (privateBeanFactory.create().getClass(),
+ "methodBar",
+ String.class);
+
+ // check that we've found one that matches
+ assertNotNull(method);
+ assertEquals("Method TWO is named correctly",
+ "methodBar", method.getName());
+ assertTrue("Method TWO is public",
+ Modifier.isPublic(method.getModifiers()));
+
+ // trickier this one - find a method in a indirect interface
+ // METHOD THREE
+ method = MethodUtils.getMethod
+ (privateBeanFactory.createSubclass().getClass(),
+ "methodBaz",
+ String.class);
+
+ // check that we've found one that matches
+ assertNotNull(method);
+ assertEquals("Method THREE is named correctly",
+ "methodBaz", method.getName());
+ assertTrue("Method THREE is public",
+ Modifier.isPublic(method.getModifiers()));
+
+ }
+
+
+ /**
+ *
Test invokeMethod
.
+ */
+ public void testinvokeMethod2() {
+ // test MethodUtils.invokeMethod
+ // easy bit first - invoke a public method
+ // METHOD ONE
+ try {
+
+ TestBean bean = new TestBean();
+ Object ret = MethodUtils.invokeMethod(bean, "setStringProperty", "TEST");
+ // check that the return's right and that the properties been set
+ assertNull(ret);
+ assertEquals("Method ONE was invoked", "TEST", bean.getStringProperty());
+
+ } catch (Throwable t) {
+ // ONE
+ fail("Exception in method ONE prevented invokation: " + t.toString());
+ }
+
+ // trickier this one - find a method in a direct interface
+ // METHOD TWO FAILURE
+ try {
+
+ Object ret = MethodUtils.invokeMethod(
+ privateBeanFactory.create(),
+ "methodBar",
+ "ANOTHER TEST");
+
+ // check that we've found one that matches
+ assertEquals("Method TWO was invoked correctly", "ANOTHER TEST", ret);
+
+ } catch (Throwable t) {
+ // METHOD TWO FAILURE
+ fail("Exception in method TWO prevented invokation: " + t.toString());
+ }
+
+
+ // trickier this one - find a method in a indirect interface
+ // METHOD THREE
+ try {
+
+ Object ret = MethodUtils.invokeMethod(
+ privateBeanFactory.createSubclass(),
+ "methodBaz",
+ "YET ANOTHER TEST");
+
+
+ // check that we've found one that matches
+ assertEquals("Method TWO was invoked correctly", "YET ANOTHER TEST", ret);
+
+
+ } catch (Throwable t) {
+ // METHOD THREE FAILURE
+ fail("Exception in method THREE prevented invokation: " + t.toString());
+
+ }
+ }
+
+ /**
+ *
Test invokeMethod
.
+ */
+ public void testInvokeMethod() throws Exception {
+ // i'm going to test that the actual calls work first and then try them via reflection
+
+ AbstractParent parent = new AlphaBean("parent");
+
+ // try testAddChild through abstract superclass
+ BetaBean childOne = new BetaBean("ChildOne");
+
+ assertEquals("Oh no! Badly coded test case! (1)", "ChildOne", parent.testAddChild(childOne));
+
+ // let's try MethodUtils version
+ assertEquals(
+ "Cannot invoke through abstract class (1)",
+ "ChildOne",
+ MethodUtils.invokeMethod(parent, "testAddChild", childOne));
+
+
+ // try adding through interface
+ AlphaBean childTwo = new AlphaBean("ChildTwo");
+
+ assertEquals("Oh no! Badly coded test case! (2)", "ChildTwo", parent.testAddChild(childTwo));
+
+ // let's try MethodUtils version
+ assertEquals(
+ "Cannot invoke through interface (1)",
+ "ChildTwo",
+ MethodUtils.invokeMethod(parent, "testAddChild", childTwo));
+
+
+ Object[] params = new Object[2];
+
+ assertEquals("Oh no! Badly coded test case! (3)", "ChildOne", parent.testAddChild2("parameter", childOne));
+
+
+ // let's try MethodUtils version
+ params[0] = "parameter";
+ params[1] = childOne;
+
+ assertEquals(
+ "Cannot invoke through abstract class (1)",
+ "ChildOne",
+ MethodUtils.invokeMethod(parent, "testAddChild2", params));
+
+ assertEquals("Oh no! Badly coded test case! (4)", "ChildTwo", parent.testAddChild2("parameter", childTwo));
+
+ // let's try MethodUtils version
+ params[0] = "parameter";
+ params[1] = childTwo;
+
+ assertEquals(
+ "Cannot invoke through abstract class (1)",
+ "ChildTwo",
+ MethodUtils.invokeMethod(parent, "testAddChild2", params));
+
+ // test that exception is correctly thrown when a method cannot be found with matching params
+ try {
+ // the next line
+ parent = new AlphaBean("parent");
+ childOne = new BetaBean("ChildOne");
+ MethodUtils.invokeMethod(parent, "bogus", childOne);
+ // should get here!
+ fail("No exception thrown when no appropriate method exists");
+
+ } catch (ReflectionException e) {
+ // this is what we're expecting!
+ }
+
+ MethodUtils.invokeMethod(parent, "getName", null);
+ MethodUtils.invokeMethod(parent, "getName", null, null);
+ MethodUtils.invokeMethod(parent, "getName", null);
+ MethodUtils.invokeMethod(parent, "getName", null, null);
+ }
+
+
+ /**
+ *
Test invokeMethod
with a primitive.
+ */
+ public void testInvokeMethodWithPrimitives() throws Exception {
+ // first test that the bean works
+ PrimitiveBean bean = new PrimitiveBean();
+ bean.setFloat(20.0f);
+ bean.setLong(10l);
+ bean.setBoolean(true);
+ bean.setInt(12);
+ bean.setDouble(25.5d);
+
+ assertEquals("Bug in PrimitiveBean (1)", 20.0f, bean.getFloat(), 0.01f);
+ assertEquals("Bug in PrimitiveBean (2)", 10, bean.getLong());
+ assertEquals("Bug in PrimitiveBean (3)", true, bean.getBoolean());
+ assertEquals("Bug in PrimitiveBean (4)", 12, bean.getInt());
+ assertEquals("Bug in PrimitiveBean (5)", 25.5d, bean.getDouble(), 0.01f);
+
+ bean = new PrimitiveBean();
+ MethodUtils.invokeMethod(bean, "setBoolean", new Boolean(true));
+ assertEquals("Call boolean property using invokeMethod", true, bean.getBoolean());
+
+ bean = new PrimitiveBean();
+ MethodUtils.invokeMethod(bean, "setFloat", new Float(20.0f));
+ assertEquals("Call float property using invokeMethod", 20.0f, bean.getFloat(), 0.01f);
+
+ bean = new PrimitiveBean();
+ MethodUtils.invokeMethod(bean, "setLong", new Long(10));
+ assertEquals("Call float property using invokeMethod", 10, bean.getLong());
+
+ bean = new PrimitiveBean();
+ MethodUtils.invokeMethod(bean, "setInt", new Integer(12));
+ assertEquals("Set float property using invokeMethod", 12, bean.getInt());
+
+ bean = new PrimitiveBean();
+ MethodUtils.invokeMethod(bean, "setDouble", new Double(25.5d));
+ assertEquals("Set float property using invokeMethod", 25.5d, bean.getDouble(), 0.01d);
+ }
+
+
+ /**
+ * Simple tests for accessing static methods via invokeMethod().
+ */
+ public void testSimpleStatic1() {
+
+ TestBean bean = new TestBean();
+ Object value = null;
+ int current = TestBean.currentCounter();
+
+ try {
+
+ // Return initial value of the counter
+ value = MethodUtils.invokeMethod
+ (bean, "currentCounter", new Object[0], new Class[0]);
+ assertNotNull("currentCounter exists", value);
+ assertTrue("currentCounter type",
+ value instanceof Integer);
+ assertEquals("currentCounter value",
+ current,
+ ((Integer) value).intValue());
+
+ // Increment via no-arguments version
+ MethodUtils.invokeMethod
+ (bean, "incrementCounter", new Object[0], new Class[0]);
+
+ // Validate updated value
+ current++;
+ value = MethodUtils.invokeMethod
+ (bean, "currentCounter", new Object[0], new Class[0]);
+ assertNotNull("currentCounter exists", value);
+ assertTrue("currentCounter type",
+ value instanceof Integer);
+ assertEquals("currentCounter value",
+ current,
+ ((Integer) value).intValue());
+
+ // Increment via specified-argument version
+ MethodUtils.invokeMethod
+ (bean, "incrementCounter",
+ new Object[] { new Integer(5) },
+ new Class[] { Integer.TYPE });
+
+ // Validate updated value
+ current += 5;
+ value = MethodUtils.invokeMethod
+ (bean, "currentCounter", new Object[0], new Class[0]);
+ assertNotNull("currentCounter exists", value);
+ assertTrue("currentCounter type",
+ value instanceof Integer);
+ assertEquals("currentCounter value",
+ current,
+ ((Integer) value).intValue());
+
+ } catch (Exception e) {
+ fail("Threw exception" + e);
+ }
+
+ }
+
+
+ /**
+ * Simple tests for accessing static methods via invokeMethod().
+ */
+ public void testSimpleStatic2() {
+
+ TestBean bean = new TestBean();
+ Object value = null;
+ int current = TestBean.currentCounter();
+
+ try {
+
+ // Return initial value of the counter
+ value = MethodUtils.invokeMethod
+ (bean, "currentCounter", new Object[0], new Class[0]);
+ assertNotNull("currentCounter exists", value);
+ assertTrue("currentCounter type",
+ value instanceof Integer);
+ assertEquals("currentCounter value",
+ current,
+ ((Integer) value).intValue());
+
+ // Increment via no-arguments version
+ MethodUtils.invokeMethod
+ (bean, "incrementCounter", new Object[0], new Class[0]);
+
+ // Validate updated value
+ current++;
+ value = MethodUtils.invokeMethod
+ (bean, "currentCounter", new Object[0], new Class[0]);
+ assertNotNull("currentCounter exists", value);
+ assertTrue("currentCounter type",
+ value instanceof Integer);
+ assertEquals("currentCounter value",
+ current,
+ ((Integer) value).intValue());
+
+ // Increment via specified-argument version
+ MethodUtils.invokeMethod
+ (bean, "incrementCounter",
+ new Object[] { new Integer(5) },
+ new Class[] { Integer.TYPE });
+
+ // Validate updated value
+ current += 5;
+ value = MethodUtils.invokeMethod
+ (bean, "currentCounter", new Object[0], new Class[0]);
+ assertNotNull("currentCounter exists", value);
+ assertTrue("currentCounter type",
+ value instanceof Integer);
+ assertEquals("currentCounter value",
+ current,
+ ((Integer) value).intValue());
+
+
+ } catch (Exception e) {
+ fail("Threw exception" + e);
+ }
+
+ }
+
+
+ /**
+ * Simple tests for accessing static methods via getAccessibleMethod()
+ */
+ public void testSimpleStatic3() {
+
+ Object value = null;
+ int current = TestBean.currentCounter();
+
+ try {
+
+ // Acquire the methods we need
+ Method currentCounterMethod = MethodUtils.getMethod
+ (TestBean.class, "currentCounter",
+ new Class[0]);
+ assertNotNull("currentCounterMethod exists",
+ currentCounterMethod);
+ assertEquals("currentCounterMethod name",
+ "currentCounter",
+ currentCounterMethod.getName());
+ assertEquals("currentCounterMethod args",
+ 0,
+ currentCounterMethod.getParameterTypes().length);
+ assertTrue("currentCounterMethod public",
+ Modifier.isPublic(currentCounterMethod.getModifiers()));
+ assertTrue("currentCounterMethod static",
+ Modifier.isStatic(currentCounterMethod.getModifiers()));
+ Method incrementCounterMethod1 = MethodUtils.getMethod
+ (TestBean.class, "incrementCounter",
+ new Class[0]);
+ assertNotNull("incrementCounterMethod1 exists",
+ incrementCounterMethod1);
+ assertEquals("incrementCounterMethod1 name",
+ "incrementCounter",
+ incrementCounterMethod1.getName());
+ assertEquals("incrementCounterMethod1 args",
+ 0,
+ incrementCounterMethod1.getParameterTypes().length);
+ assertTrue("incrementCounterMethod1 public",
+ Modifier.isPublic(incrementCounterMethod1.getModifiers()));
+ assertTrue("incrementCounterMethod1 static",
+ Modifier.isStatic(incrementCounterMethod1.getModifiers()));
+ Method incrementCounterMethod2 = MethodUtils.getMethod
+ (TestBean.class, "incrementCounter",
+ new Class[] { Integer.TYPE });
+ assertNotNull("incrementCounterMethod2 exists",
+ incrementCounterMethod2);
+ assertEquals("incrementCounterMethod2 name",
+ "incrementCounter",
+ incrementCounterMethod2.getName());
+ assertEquals("incrementCounterMethod2 args",
+ 1,
+ incrementCounterMethod2.getParameterTypes().length);
+ assertTrue("incrementCounterMethod2 public",
+ Modifier.isPublic(incrementCounterMethod2.getModifiers()));
+ assertTrue("incrementCounterMethod2 static",
+ Modifier.isStatic(incrementCounterMethod2.getModifiers()));
+
+ // Return initial value of the counter
+ value = currentCounterMethod.invoke(null, new Object[0]);
+ assertNotNull("currentCounter exists", value);
+ assertTrue("currentCounter type",
+ value instanceof Integer);
+ assertEquals("currentCounter value",
+ current,
+ ((Integer) value).intValue());
+
+ // Increment via no-arguments version
+ incrementCounterMethod1.invoke(null, new Object[0]);
+
+ // Validate updated value
+ current++;
+ value = currentCounterMethod.invoke(null, new Object[0]);
+ assertNotNull("currentCounter exists", value);
+ assertTrue("currentCounter type",
+ value instanceof Integer);
+ assertEquals("currentCounter value",
+ current,
+ ((Integer) value).intValue());
+
+ // Increment via specified-argument version
+ incrementCounterMethod2.invoke(null,
+ new Object[] { new Integer(5) });
+
+ // Validate updated value
+ current += 5;
+ value = currentCounterMethod.invoke(null, new Object[0]);
+ assertNotNull("currentCounter exists", value);
+ assertTrue("currentCounter type",
+ value instanceof Integer);
+ assertEquals("currentCounter value",
+ current,
+ ((Integer) value).intValue());
+
+ } catch (Exception e) {
+ fail("Threw exception" + e);
+ }
+
+ }
+
+ public void testPublicSub() throws Exception {
+ // make sure that bean does what it should
+ PublicSubBean bean = new PublicSubBean();
+ assertEquals("Start value (foo)", bean.getFoo(), "This is foo");
+ assertEquals("Start value (bar)", bean.getBar(), "This is bar");
+ bean.setFoo("new foo");
+ bean.setBar("new bar");
+ assertEquals("Set value (foo)", bean.getFoo(), "new foo");
+ assertEquals("Set value (bar)", bean.getBar(), "new bar");
+
+ // see if we can access public methods in a default access superclass
+ // from a public access subclass instance
+ MethodUtils.invokeMethod(bean, "setFoo", "alpha");
+ assertEquals("Set value (foo:2)", bean.getFoo(), "alpha");
+ MethodUtils.invokeMethod(bean, "setBar", "beta");
+ assertEquals("Set value (bar:2)", bean.getFoo(), "alpha");
+ }
+}
diff --git a/examples/cl2/src/test/org/apache/commons/lang/reflect/PrimitiveBean.java b/examples/cl2/src/test/org/apache/commons/lang/reflect/PrimitiveBean.java
new file mode 100644
index 00000000..3c2bcf1d
--- /dev/null
+++ b/examples/cl2/src/test/org/apache/commons/lang/reflect/PrimitiveBean.java
@@ -0,0 +1,119 @@
+/*
+ * ====================================================================
+ *
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 1999-2002 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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 Group.
+ *
+ * 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
+ * .
+ *
+ */
+
+package org.apache.commons.lang.reflect;
+
+/**
+ * Bean that has primitive properties
+ */
+public class PrimitiveBean {
+
+ private float _float;
+ private double _double;
+ private boolean _boolean;
+ private long _long;
+ private int _int;
+ private short _short;
+
+ public short getShort() {
+ return _short;
+ }
+
+ public void setShort(short _short) {
+ this._short = _short;
+ }
+
+ public float getFloat() {
+ return _float;
+ }
+
+ public void setFloat(float _float) {
+ this._float = _float;
+ }
+
+ public double getDouble() {
+ return _double;
+ }
+
+ public void setDouble(double _double) {
+ this._double = _double;
+ }
+
+ public boolean getBoolean() {
+ return _boolean;
+ }
+
+ public void setBoolean(boolean _boolean) {
+ this._boolean = _boolean;
+ }
+
+ public long getLong() {
+ return _long;
+ }
+
+ public void setLong(long _long) {
+ this._long = _long;
+ }
+
+ public int getInt() {
+ return _int;
+ }
+
+ public void setInt(int _int) {
+ this._int = _int;
+ }
+}
diff --git a/examples/cl2/src/test/org/apache/commons/lang/reflect/ReflectTestSuite.java b/examples/cl2/src/test/org/apache/commons/lang/reflect/ReflectTestSuite.java
new file mode 100644
index 00000000..f01647d5
--- /dev/null
+++ b/examples/cl2/src/test/org/apache/commons/lang/reflect/ReflectTestSuite.java
@@ -0,0 +1,94 @@
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2002 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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
+ * .
+ */
+package org.apache.commons.lang.reflect;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import junit.textui.TestRunner;
+
+/**
+ * Test suite for the Reflect packages.
+ *
+ * @author Stephen Colebourne (of original copied from)
+ * @author Robert Burrell Donkin
+ * @version $Id: ReflectTestSuite.java,v 1.2 2002/11/18 23:01:36 rdonkin Exp $
+ */
+public class ReflectTestSuite extends TestCase {
+
+ /**
+ * Construct a new instance.
+ */
+ public ReflectTestSuite(String name) {
+ super(name);
+ }
+
+ /**
+ * Executor-line interface.
+ */
+ public static void main(String[] args) {
+ TestRunner.run(suite());
+ }
+
+ /**
+ * Get the suite of tests
+ */
+ public static Test suite() {
+ TestSuite suite = new TestSuite();
+ suite.addTest(MethodUtilsTestCase.suite());
+ suite.addTest(ReflectionUtilsTestCase.suite());
+ return suite;
+ }
+
+}
diff --git a/examples/cl2/src/test/org/apache/commons/lang/reflect/ReflectionUtilsTestCase.java b/examples/cl2/src/test/org/apache/commons/lang/reflect/ReflectionUtilsTestCase.java
new file mode 100644
index 00000000..4a04e731
--- /dev/null
+++ b/examples/cl2/src/test/org/apache/commons/lang/reflect/ReflectionUtilsTestCase.java
@@ -0,0 +1,279 @@
+/*
+ * ====================================================================
+ *
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 1999-2002 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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 Group.
+ *
+ * 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
+ * .
+ *
+ */
+package org.apache.commons.lang.reflect;
+
+import java.lang.reflect.Member;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+/**
+ *
Test case for ReflectionUtils
+ *
+ */
+public class ReflectionUtilsTestCase extends TestCase {
+
+ // ---------------------------------------------------- Instance Variables
+
+ // ---------------------------------------------------------- Constructors
+
+ /**
+ * Construct a new instance of this test case.
+ *
+ * @param name Name of the test case
+ */
+ public ReflectionUtilsTestCase(String name) {
+ super(name);
+ }
+
+
+ // -------------------------------------------------- Overall Test Methods
+
+
+ /**
+ * Set up instance variables required by this test case.
+ */
+ public void setUp() {
+ // any set up goes here
+ }
+
+
+ /**
+ * Return the tests included in this test suite.
+ */
+ public static Test suite() {
+ return (new TestSuite(ReflectionUtilsTestCase.class));
+ }
+
+ /**
+ * Tear down instance variables required by this test case.
+ */
+ public void tearDown() {
+ // any tear down goes here
+ }
+
+
+ // ------------------------------------------------ Individual Test Methods
+
+
+ public void testScopeUtils() throws Exception {
+ ScopeBean bean = new ScopeBean();
+ Member field = bean.getPrivateField();
+ assertEquals("Private scope (field) [isFinal]", false ,ReflectionUtils.isFinal(field));
+ assertEquals("Private scope (field) [isPackageScope]", false, ReflectionUtils.isPackageScope(field));
+ assertEquals("Private scope (field) [isPrivateScope]", true, ReflectionUtils.isPrivateScope(field));
+ assertEquals("Private scope (field) [isProtectedScope]", false, ReflectionUtils.isProtectedScope(field));
+ assertEquals("Private scope (field) [isPublicScope]", false, ReflectionUtils.isPublicScope(field));
+ assertEquals("Private scope (field) [isStatic]", false, ReflectionUtils.isStatic(field));
+
+ Member method = bean.getPrivateMethod();
+ assertEquals("Private scope (method) [isFinal]", false, ReflectionUtils.isFinal(method));
+ assertEquals("Private scope (method) [isPackageScope]", false, ReflectionUtils.isPackageScope(method));
+ assertEquals("Private scope (method) [isPrivateScope]", true, ReflectionUtils.isPrivateScope(method));
+ assertEquals("Private scope (method) [isProtectedScope]", false, ReflectionUtils.isProtectedScope(method));
+ assertEquals("Private scope (method) [isPublicScope]", false, ReflectionUtils.isPublicScope(method));
+ assertEquals("Private scope (method) [isStatic]", false, ReflectionUtils.isStatic(method));
+
+ field = bean.getPackageField();
+ assertEquals("Package scope (field) [isFinal]", false, ReflectionUtils.isFinal(field));
+ assertEquals("Package scope (field) [isPackageScope]", true, ReflectionUtils.isPackageScope(field));
+ assertEquals("Package scope (field) [isPrivateScope]", false, ReflectionUtils.isPrivateScope(field));
+ assertEquals("Package scope (field) [isProtectedScope]", false, ReflectionUtils.isProtectedScope(field));
+ assertEquals("Package scope (field) [isPublicScope]", false, ReflectionUtils.isPublicScope(field));
+ assertEquals("Package scope (field) [isStatic]", false, ReflectionUtils.isStatic(field));
+
+ method = bean.getPackageMethod();
+ assertEquals("Package scope (method) [isFinal]", false, ReflectionUtils.isFinal(method));
+ assertEquals("Package scope (method) [isPackageScope]", true, ReflectionUtils.isPackageScope(method));
+ assertEquals("Package scope (method) [isPrivateScope]", false, ReflectionUtils.isPrivateScope(method));
+ assertEquals("Package scope (method) [isProtectedScope]", false, ReflectionUtils.isProtectedScope(method));
+ assertEquals("Package scope (method) [isPublicScope]", false, ReflectionUtils.isPublicScope(method));
+ assertEquals("Packages scope (method) [isStatic]", false, ReflectionUtils.isStatic(method));
+
+ field = bean.getPublicField();
+ assertEquals("Public scope (field) [isFinal]", false, ReflectionUtils.isFinal(field));
+ assertEquals("Public scope (field) [isPackageScope]", false, ReflectionUtils.isPackageScope(field));
+ assertEquals("Public scope (field) [isPrivateScope]", false, ReflectionUtils.isPrivateScope(field));
+ assertEquals("Public scope (field) [isProtectedScope]", false, ReflectionUtils.isProtectedScope(field));
+ assertEquals("Public scope (field) [isPublicScope]", true, ReflectionUtils.isPublicScope(field));
+ assertEquals("Public scope (field) [isStatic]", false, ReflectionUtils.isStatic(field));
+
+ method = bean.getPublicMethod();
+ assertEquals("Public scope (method) [isFinal]", false, ReflectionUtils.isFinal(method));
+ assertEquals("Public scope (method) [isPackageScope]", false, ReflectionUtils.isPackageScope(method));
+ assertEquals("Public scope (method) [isPrivateScope]", false, ReflectionUtils.isPrivateScope(method));
+ assertEquals("Public scope (method) [isProtectedScope]", false, ReflectionUtils.isProtectedScope(method));
+ assertEquals("Public scope (method) [isPublicScope]", true, ReflectionUtils.isPublicScope(method));
+ assertEquals("Public scope (method) [isStatic]", false, ReflectionUtils.isStatic(method));
+
+ field = bean.getFinalField();
+ assertEquals("Final scope (field) [isFinal]", true, ReflectionUtils.isFinal(field));
+ assertEquals("Final scope (field) [isPackageScope]", false, ReflectionUtils.isPackageScope(field));
+ assertEquals("Final scope (field) [isPrivateScope]", false, ReflectionUtils.isPrivateScope(field));
+ assertEquals("Final scope (field) [isProtectedScope]", false, ReflectionUtils.isProtectedScope(field));
+ assertEquals("Final scope (field) [isPublicScope]", true, ReflectionUtils.isPublicScope(field));
+ assertEquals("Final scope (field) [isStatic]", false, ReflectionUtils.isStatic(field));
+
+ method = bean.getFinalMethod();
+ assertEquals("Final scope (method) [isFinal]", true, ReflectionUtils.isFinal(method));
+ assertEquals("Final scope (method) [isPackageScope]", false, ReflectionUtils.isPackageScope(method));
+ assertEquals("Final scope (method) [isPrivateScope]", false, ReflectionUtils.isPrivateScope(method));
+ assertEquals("Final scope (method) [isProtectedScope]", false, ReflectionUtils.isProtectedScope(method));
+ assertEquals("Final scope (method) [isPublicScope]", true, ReflectionUtils.isPublicScope(method));
+ assertEquals("Final scope (method) [isStatic]", false, ReflectionUtils.isStatic(method));
+
+ field = bean.getStaticField();
+ assertEquals("Static scope (field) [isFinal]", false, ReflectionUtils.isFinal(field));
+ assertEquals("Static scope (field) [isPackageScope]", false, ReflectionUtils.isPackageScope(field));
+ assertEquals("Static scope (field) [isPrivateScope]", false, ReflectionUtils.isPrivateScope(field));
+ assertEquals("Static scope (field) [isProtectedScope]", false, ReflectionUtils.isProtectedScope(field));
+ assertEquals("Static scope (field) [isPublicScope]", true, ReflectionUtils.isPublicScope(field));
+ assertEquals("Static scope (field) [isStatic]", true, ReflectionUtils.isStatic(field));
+
+ method = bean.getStaticMethod();
+ assertEquals("Static scope (method) [isFinal]", false, ReflectionUtils.isFinal(method));
+ assertEquals("Static scope (method) [isPackageScope]", false, ReflectionUtils.isPackageScope(method));
+ assertEquals("Static scope (method) [isPrivateScope]", false, ReflectionUtils.isPrivateScope(method));
+ assertEquals("Static scope (method) [isProtectedScope]", false, ReflectionUtils.isProtectedScope(method));
+ assertEquals("Static scope (method) [isPublicScope]", true, ReflectionUtils.isPublicScope(method));
+ assertEquals("Static scope (method) [isStatic]", true, ReflectionUtils.isStatic(method));
+ }
+
+ public void testWidening() throws Exception
+ {
+ // test byte conversions
+ assertEquals("byte -> char", ReflectionUtils.isCompatible(Byte.class, char.class), false);
+ assertEquals("byte -> byte", ReflectionUtils.isCompatible(Byte.class, byte.class), true);
+ assertEquals("byte -> short", ReflectionUtils.isCompatible(Byte.class, short.class), true);
+ assertEquals("byte -> int", ReflectionUtils.isCompatible(Byte.class, int.class), true);
+ assertEquals("byte -> long", ReflectionUtils.isCompatible(Byte.class, long.class), true);
+ assertEquals("byte -> float", ReflectionUtils.isCompatible(Byte.class, float.class), true);
+ assertEquals("byte -> double", ReflectionUtils.isCompatible(Byte.class, double.class), true);
+ assertEquals("byte -> boolean", ReflectionUtils.isCompatible(Byte.class, boolean.class), false);
+
+ // test short conversions
+ assertEquals("short -> char", ReflectionUtils.isCompatible(Short.class, char.class), false);
+ assertEquals("short -> byte", ReflectionUtils.isCompatible(Short.class, byte.class), false);
+ assertEquals("short -> short", ReflectionUtils.isCompatible(Short.class, short.class), true);
+ assertEquals("short -> int", ReflectionUtils.isCompatible(Short.class, int.class), true);
+ assertEquals("short -> long", ReflectionUtils.isCompatible(Short.class, long.class), true);
+ assertEquals("short -> float", ReflectionUtils.isCompatible(Short.class, float.class), true);
+ assertEquals("short -> double", ReflectionUtils.isCompatible(Short.class, double.class), true);
+ assertEquals("short -> boolean", ReflectionUtils.isCompatible(Short.class, boolean.class), false);
+
+ // test char conversions
+ assertEquals("char -> char", ReflectionUtils.isCompatible(Character.class, char.class), true);
+ assertEquals("char -> byte", ReflectionUtils.isCompatible(Character.class, byte.class), false);
+ assertEquals("char -> short", ReflectionUtils.isCompatible(Character.class, short.class), false);
+ assertEquals("char -> int", ReflectionUtils.isCompatible(Character.class, int.class), true);
+ assertEquals("char -> long", ReflectionUtils.isCompatible(Character.class, long.class), true);
+ assertEquals("char -> float", ReflectionUtils.isCompatible(Character.class, float.class), true);
+ assertEquals("char -> double", ReflectionUtils.isCompatible(Character.class, double.class), true);
+ assertEquals("char -> boolean", ReflectionUtils.isCompatible(Character.class, boolean.class), false);
+
+ // test int conversions
+ assertEquals("int -> char", ReflectionUtils.isCompatible(Integer.class, char.class), false);
+ assertEquals("int -> byte", ReflectionUtils.isCompatible(Integer.class, byte.class), false);
+ assertEquals("int -> short", ReflectionUtils.isCompatible(Integer.class, short.class), false);
+ assertEquals("int -> int", ReflectionUtils.isCompatible(Integer.class, int.class), true);
+ assertEquals("int -> long", ReflectionUtils.isCompatible(Integer.class, long.class), true);
+ assertEquals("int -> float", ReflectionUtils.isCompatible(Integer.class, float.class), true);
+ assertEquals("int -> double", ReflectionUtils.isCompatible(Integer.class, double.class), true);
+ assertEquals("int -> boolean", ReflectionUtils.isCompatible(Integer.class, boolean.class), false);
+
+ // test long conversions
+ assertEquals("long -> char", ReflectionUtils.isCompatible(Long.class, char.class), false);
+ assertEquals("long -> byte", ReflectionUtils.isCompatible(Long.class, byte.class), false);
+ assertEquals("long -> short", ReflectionUtils.isCompatible(Long.class, short.class), false);
+ assertEquals("long -> int", ReflectionUtils.isCompatible(Long.class, int.class), false);
+ assertEquals("long -> long", ReflectionUtils.isCompatible(Long.class, long.class), true);
+ assertEquals("long -> float", ReflectionUtils.isCompatible(Long.class, float.class), true);
+ assertEquals("long -> double", ReflectionUtils.isCompatible(Long.class, double.class), true);
+ assertEquals("long -> boolean", ReflectionUtils.isCompatible(Long.class, boolean.class), false);
+
+ // test float conversions
+ assertEquals("float -> char", ReflectionUtils.isCompatible(Float.class, char.class), false);
+ assertEquals("float -> byte", ReflectionUtils.isCompatible(Float.class, byte.class), false);
+ assertEquals("float -> short", ReflectionUtils.isCompatible(Float.class, short.class), false);
+ assertEquals("float -> int", ReflectionUtils.isCompatible(Float.class, int.class), false);
+ assertEquals("float -> long", ReflectionUtils.isCompatible(Float.class, long.class), false);
+ assertEquals("float -> float", ReflectionUtils.isCompatible(Float.class, float.class), true);
+ assertEquals("float -> double", ReflectionUtils.isCompatible(Float.class, double.class), true);
+ assertEquals("float -> boolean", ReflectionUtils.isCompatible(Float.class, boolean.class), false);
+
+ // test float conversions
+ assertEquals("double -> char", ReflectionUtils.isCompatible(Double.class, char.class), false);
+ assertEquals("double -> byte", ReflectionUtils.isCompatible(Double.class, byte.class), false);
+ assertEquals("double -> short", ReflectionUtils.isCompatible(Double.class, short.class), false);
+ assertEquals("double -> int", ReflectionUtils.isCompatible(Double.class, int.class), false);
+ assertEquals("double -> long", ReflectionUtils.isCompatible(Double.class, long.class), false);
+ assertEquals("double -> float", ReflectionUtils.isCompatible(Double.class, float.class), false);
+ assertEquals("double -> double", ReflectionUtils.isCompatible(Double.class, double.class), true);
+ assertEquals("double -> boolean", ReflectionUtils.isCompatible(Double.class, boolean.class), false);
+
+ // test float conversions
+ assertEquals("boolean -> char", ReflectionUtils.isCompatible(Boolean.class, char.class), false);
+ assertEquals("boolean -> byte", ReflectionUtils.isCompatible(Boolean.class, byte.class), false);
+ assertEquals("boolean -> short", ReflectionUtils.isCompatible(Boolean.class, short.class), false);
+ assertEquals("boolean -> int", ReflectionUtils.isCompatible(Boolean.class, int.class), false);
+ assertEquals("boolean -> long", ReflectionUtils.isCompatible(Boolean.class, long.class), false);
+ assertEquals("boolean -> float", ReflectionUtils.isCompatible(Boolean.class, float.class), false);
+ assertEquals("boolean -> double", ReflectionUtils.isCompatible(Boolean.class, double.class), false);
+ assertEquals("boolean -> boolean", ReflectionUtils.isCompatible(Boolean.class, boolean.class), true);
+ }
+}
diff --git a/examples/cl2/src/test/org/apache/commons/lang/reflect/ScopeBean.java b/examples/cl2/src/test/org/apache/commons/lang/reflect/ScopeBean.java
new file mode 100644
index 00000000..f6d185e4
--- /dev/null
+++ b/examples/cl2/src/test/org/apache/commons/lang/reflect/ScopeBean.java
@@ -0,0 +1,127 @@
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2002 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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
+ * .
+ */
+package org.apache.commons.lang.reflect;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+
+/**
+ * Bean with examples of different scoped fields and methods.
+ */
+public class ScopeBean {
+
+ private int privateField;
+ int packageField;
+ protected int protectedField;
+ public int publicField;
+ public static int staticField;
+ public final int finalField = 42;
+
+ public ScopeBean() {}
+
+ private void privateMethod() {}
+ protected void protectedMethod() {}
+ void packageMethod() {}
+ public void publicMethod() {}
+ public static void staticMethod() {}
+ public final void finalMethod() {}
+
+ public Field getPrivateField() throws NoSuchFieldException {
+ return ScopeBean.class.getDeclaredField("privateField");
+ }
+
+ public Field getProtectedField() throws NoSuchFieldException {
+ return ScopeBean.class.getDeclaredField("protectedField");
+ }
+
+ public Field getPackageField() throws NoSuchFieldException {
+ return ScopeBean.class.getDeclaredField("packageField");
+ }
+
+ public Field getPublicField() throws NoSuchFieldException {
+ return ScopeBean.class.getDeclaredField("publicField");
+ }
+
+ public Field getStaticField() throws NoSuchFieldException {
+ return ScopeBean.class.getDeclaredField("staticField");
+ }
+
+ public Field getFinalField() throws NoSuchFieldException {
+ return ScopeBean.class.getDeclaredField("finalField");
+ }
+
+ public Method getPrivateMethod() throws NoSuchMethodException {
+ return ScopeBean.class.getDeclaredMethod("privateMethod", null);
+ }
+
+ public Method getProtectedMethod() throws NoSuchMethodException {
+ return ScopeBean.class.getDeclaredMethod("protectedMethod", null);
+ }
+
+ public Method getPackageMethod() throws NoSuchMethodException {
+ return ScopeBean.class.getDeclaredMethod("packageMethod", null);
+ }
+
+ public Method getPublicMethod() throws NoSuchMethodException {
+ return ScopeBean.class.getDeclaredMethod("publicMethod", null);
+ }
+
+ public Method getStaticMethod() throws NoSuchMethodException {
+ return ScopeBean.class.getDeclaredMethod("staticMethod", null);
+ }
+
+ public Method getFinalMethod() throws NoSuchMethodException {
+ return ScopeBean.class.getDeclaredMethod("finalMethod", null);
+ }
+}
diff --git a/examples/cl2/src/test/org/apache/commons/lang/reflect/TestBean.java b/examples/cl2/src/test/org/apache/commons/lang/reflect/TestBean.java
new file mode 100755
index 00000000..eb7e66c6
--- /dev/null
+++ b/examples/cl2/src/test/org/apache/commons/lang/reflect/TestBean.java
@@ -0,0 +1,506 @@
+/*
+ * $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//lang/src/test/org/apache/commons/lang/reflect/Attic/TestBean.java,v 1.1 2002/11/14 18:53:36 rdonkin Exp $
+ * $Revision: 1.1 $
+ * $Date: 2002/11/14 18:53:36 $
+ *
+ * ====================================================================
+ *
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 1999-2002 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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 Group.
+ *
+ * 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
+ * .
+ *
+ */
+
+
+package org.apache.commons.lang.reflect;
+
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+
+/**
+ * General purpose test bean for JUnit tests for the "beanutils" component.
+ *
+ * @author Craig R. McClanahan
+ * @version $Revision: 1.1 $ $Date: 2002/11/14 18:53:36 $
+ */
+
+public class TestBean {
+
+
+ // ------------------------------------------------------------- Properties
+
+
+ /**
+ * A boolean property.
+ */
+ private boolean booleanProperty = true;
+
+ public boolean getBooleanProperty() {
+ return (booleanProperty);
+ }
+
+ public void setBooleanProperty(boolean booleanProperty) {
+ this.booleanProperty = booleanProperty;
+ }
+
+
+ /**
+ * A boolean property that uses an "is" method for the getter.
+ */
+ private boolean booleanSecond = true;
+
+ public boolean isBooleanSecond() {
+ return (booleanSecond);
+ }
+
+ public void setBooleanSecond(boolean booleanSecond) {
+ this.booleanSecond = booleanSecond;
+ }
+
+
+ /**
+ * A double property.
+ */
+ private double doubleProperty = 321.0;
+
+ public double getDoubleProperty() {
+ return (this.doubleProperty);
+ }
+
+ public void setDoubleProperty(double doubleProperty) {
+ this.doubleProperty = doubleProperty;
+ }
+
+
+ /**
+ * An "indexed property" accessible via both array and subscript
+ * based getters and setters.
+ */
+ private String dupProperty[] =
+ { "Dup 0", "Dup 1", "Dup 2", "Dup 3", "Dup 4" };
+
+ public String[] getDupProperty() {
+ return (this.dupProperty);
+ }
+
+ public String getDupProperty(int index) {
+ return (this.dupProperty[index]);
+ }
+
+ public void setDupProperty(int index, String value) {
+ this.dupProperty[index] = value;
+ }
+
+ public void setDupProperty(String dupProperty[]) {
+ this.dupProperty = dupProperty;
+ }
+
+
+ /**
+ * A float property.
+ */
+ private float floatProperty = (float) 123.0;
+
+ public float getFloatProperty() {
+ return (this.floatProperty);
+ }
+
+ public void setFloatProperty(float floatProperty) {
+ this.floatProperty = floatProperty;
+ }
+
+
+ /**
+ * An integer array property accessed as an array.
+ */
+ private int intArray[] = { 0, 10, 20, 30, 40 };
+
+ public int[] getIntArray() {
+ return (this.intArray);
+ }
+
+ public void setIntArray(int intArray[]) {
+ this.intArray = intArray;
+ }
+
+
+ /**
+ * An integer array property accessed as an indexed property.
+ */
+ private int intIndexed[] = { 0, 10, 20, 30, 40 };
+
+ public int getIntIndexed(int index) {
+ return (intIndexed[index]);
+ }
+
+ public void setIntIndexed(int index, int value) {
+ intIndexed[index] = value;
+ }
+
+
+ /**
+ * An integer property.
+ */
+ private int intProperty = 123;
+
+ public int getIntProperty() {
+ return (this.intProperty);
+ }
+
+ public void setIntProperty(int intProperty) {
+ this.intProperty = intProperty;
+ }
+
+
+ /**
+ * A List property accessed as an indexed property.
+ */
+ private static List listIndexed = new ArrayList();
+
+ static {
+ listIndexed.add("String 0");
+ listIndexed.add("String 1");
+ listIndexed.add("String 2");
+ listIndexed.add("String 3");
+ listIndexed.add("String 4");
+ }
+
+ public List getListIndexed() {
+ return (listIndexed);
+ }
+
+
+ /**
+ * A long property.
+ */
+ private long longProperty = 321;
+
+ public long getLongProperty() {
+ return (this.longProperty);
+ }
+
+ public void setLongProperty(long longProperty) {
+ this.longProperty = longProperty;
+ }
+
+
+ /**
+ * A mapped property with only a getter and setter for a Map.
+ */
+ private Map mapProperty = null;
+
+ public Map getMapProperty() {
+ // Create the map the very first time
+ if (mapProperty == null) {
+ mapProperty = new HashMap();
+ mapProperty.put("First Key", "First Value");
+ mapProperty.put("Second Key", "Second Value");
+ }
+ return (mapProperty);
+ }
+
+ public void setMapProperty(Map mapProperty) {
+ // Create the map the very first time
+ if (mapProperty == null) {
+ mapProperty = new HashMap();
+ mapProperty.put("First Key", "First Value");
+ mapProperty.put("Second Key", "Second Value");
+ }
+ this.mapProperty = mapProperty;
+ }
+
+
+ /**
+ * A mapped property that has String keys and Object values.
+ */
+ private HashMap mappedObjects = null;
+
+ public Object getMappedObjects(String key) {
+ // Create the map the very first time
+ if (mappedObjects == null) {
+ mappedObjects = new HashMap();
+ mappedObjects.put("First Key", "First Value");
+ mappedObjects.put("Second Key", "Second Value");
+ }
+ return (mappedObjects.get(key));
+ }
+
+ public void setMappedObjects(String key, Object value) {
+ // Create the map the very first time
+ if (mappedObjects == null) {
+ mappedObjects = new HashMap();
+ mappedObjects.put("First Key", "First Value");
+ mappedObjects.put("Second Key", "Second Value");
+ }
+ mappedObjects.put(key, value);
+ }
+
+
+ /**
+ * A mapped property that has String keys and String values.
+ */
+ private HashMap mappedProperty = null;
+
+ public String getMappedProperty(String key) {
+ // Create the map the very first time
+ if (mappedProperty == null) {
+ mappedProperty = new HashMap();
+ mappedProperty.put("First Key", "First Value");
+ mappedProperty.put("Second Key", "Second Value");
+ }
+ return ((String) mappedProperty.get(key));
+ }
+
+ public void setMappedProperty(String key, String value) {
+ // Create the map the very first time
+ if (mappedProperty == null) {
+ mappedProperty = new HashMap();
+ mappedProperty.put("First Key", "First Value");
+ mappedProperty.put("Second Key", "Second Value");
+ }
+ mappedProperty.put(key, value);
+ }
+
+
+ /**
+ * A mapped property that has String keys and int values.
+ */
+ private HashMap mappedIntProperty = null;
+
+ public int getMappedIntProperty(String key) {
+ // Create the map the very first time
+ if (mappedProperty == null) {
+ mappedProperty = new HashMap();
+ mappedProperty.put("One", new Integer(1));
+ mappedProperty.put("Two", new Integer(2));
+ }
+ Integer x = (Integer) mappedIntProperty.get(key);
+ return ((x == null) ? 0 : x.intValue());
+ }
+
+ public void setMappedIntProperty(String key, int value) {
+ mappedIntProperty.put(key, new Integer(value));
+ }
+
+
+ /**
+ * A nested reference to another test bean (populated as needed).
+ */
+ private TestBean nested = null;
+
+ public TestBean getNested() {
+ if (nested == null)
+ nested = new TestBean();
+ return (nested);
+ }
+
+
+ /*
+ * Another nested reference to a bean containing mapp properties
+ */
+ class MappedTestBean {
+ public void setValue(String key,String val) { }
+ public String getValue(String key) { return "Mapped Value"; }
+ }
+
+ private MappedTestBean mappedNested = null;
+
+ public MappedTestBean getMappedNested() {
+ if (mappedNested == null)
+ {
+ mappedNested = new MappedTestBean();
+ }
+ return mappedNested;
+ }
+
+ /**
+ * A String property with an initial value of null.
+ */
+ private String nullProperty = null;
+
+ public String getNullProperty() {
+ return (this.nullProperty);
+ }
+
+ public void setNullProperty(String nullProperty) {
+ this.nullProperty = nullProperty;
+ }
+
+
+ /**
+ * A read-only String property.
+ */
+ private String readOnlyProperty = "Read Only String Property";
+
+ public String getReadOnlyProperty() {
+ return (this.readOnlyProperty);
+ }
+
+
+ /**
+ * A short property.
+ */
+ private short shortProperty = (short) 987;
+
+ public short getShortProperty() {
+ return (this.shortProperty);
+ }
+
+ public void setShortProperty(short shortProperty) {
+ this.shortProperty = shortProperty;
+ }
+
+
+ /**
+ * A String array property accessed as a String.
+ */
+ private String stringArray[] =
+ { "String 0", "String 1", "String 2", "String 3", "String 4" };
+
+ public String[] getStringArray() {
+ return (this.stringArray);
+ }
+
+ public void setStringArray(String stringArray[]) {
+ this.stringArray = stringArray;
+ }
+
+
+ /**
+ * A String array property accessed as an indexed property.
+ */
+ private String stringIndexed[] =
+ { "String 0", "String 1", "String 2", "String 3", "String 4" };
+
+ public String getStringIndexed(int index) {
+ return (stringIndexed[index]);
+ }
+
+ public void setStringIndexed(int index, String value) {
+ stringIndexed[index] = value;
+ }
+
+
+ /**
+ * A String property.
+ */
+ private String stringProperty = "This is a string";
+
+ public String getStringProperty() {
+ return (this.stringProperty);
+ }
+
+ public void setStringProperty(String stringProperty) {
+ this.stringProperty = stringProperty;
+ }
+
+
+ /**
+ * A write-only String property.
+ */
+ private String writeOnlyProperty = "Write Only String Property";
+
+ public String getWriteOnlyPropertyValue() {
+ return (this.writeOnlyProperty);
+ }
+
+ public void setWriteOnlyProperty(String writeOnlyProperty) {
+ this.writeOnlyProperty = writeOnlyProperty;
+ }
+
+
+ // ------------------------------------------------------- Static Variables
+
+
+ /**
+ * A static variable that is accessed and updated via static methods
+ * for MethodUtils testing.
+ */
+ private static int counter = 0;
+
+
+ /**
+ * Return the current value of the counter.
+ */
+ public static int currentCounter() {
+
+ return (counter);
+
+ }
+
+
+ /**
+ * Increment the current value of the counter by 1.
+ */
+ public static void incrementCounter() {
+
+ incrementCounter(1);
+
+ }
+
+
+ /**
+ * Increment the current value of the counter by the specified amount.
+ *
+ * @param amount Amount to be added to the current counter
+ */
+ public static void incrementCounter(int amount) {
+
+ counter += amount;
+
+ }
+
+
+}
diff --git a/examples/cl2/src/test/org/apache/commons/lang/reflect/priv/PackageBean.java b/examples/cl2/src/test/org/apache/commons/lang/reflect/priv/PackageBean.java
new file mode 100644
index 00000000..18c3559c
--- /dev/null
+++ b/examples/cl2/src/test/org/apache/commons/lang/reflect/priv/PackageBean.java
@@ -0,0 +1,114 @@
+/*
+ * $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//lang/src/test/org/apache/commons/lang/reflect/priv/Attic/PackageBean.java,v 1.1 2002/11/14 18:53:36 rdonkin Exp $
+ * $Revision: 1.1 $
+ * $Date: 2002/11/14 18:53:36 $
+ *
+ * ====================================================================
+ *
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 1999-2002 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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 Group.
+ *
+ * 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
+ * .
+ *
+ */
+
+
+package org.apache.commons.lang.reflect.priv;
+
+
+/**
+ * This class is designed to test the default access jvm problem workaround.
+ * The issue is that public methods of a public subclass contained in a default access
+ * superclass are returned by reflection but an IllegalAccessException is thrown
+ * when they are invoked.
+ *
+ * This is the default access superclass
+ *
+ * @author Robert Burrell Donkin
+ * @version $Revision: 1.1 $ $Date: 2002/11/14 18:53:36 $
+ */
+
+class PackageBean {
+
+
+ // ----------------------------------------------------------- Constructors
+
+
+ /**
+ * Package private constructor - can only use factory method to create
+ * beans.
+ */
+ PackageBean() {
+
+ super();
+
+ }
+
+
+ // ------------------------------------------------------------- Properties
+
+
+ /**
+ */
+ private String bar = "This is bar";
+
+ public String getBar() {
+
+ return (this.bar);
+
+ }
+
+ public void setBar(String bar) {
+
+ this.bar = bar;
+
+ }
+
+}
diff --git a/examples/cl2/src/test/org/apache/commons/lang/reflect/priv/PrivateBean.java b/examples/cl2/src/test/org/apache/commons/lang/reflect/priv/PrivateBean.java
new file mode 100644
index 00000000..be5944ca
--- /dev/null
+++ b/examples/cl2/src/test/org/apache/commons/lang/reflect/priv/PrivateBean.java
@@ -0,0 +1,155 @@
+/*
+ * $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//lang/src/test/org/apache/commons/lang/reflect/priv/Attic/PrivateBean.java,v 1.1 2002/11/14 18:53:36 rdonkin Exp $
+ * $Revision: 1.1 $
+ * $Date: 2002/11/14 18:53:36 $
+ *
+ * ====================================================================
+ *
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 1999-2002 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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 Group.
+ *
+ * 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
+ * .
+ *
+ */
+
+
+package org.apache.commons.lang.reflect.priv;
+
+
+/**
+ * Bean that has a private constructor that exposes properties via
+ * various mechanisms (based on property name):
+ *
+ * - foo - Via direct public method
+ *
- bar - Via directly implemented interface
+ *
- baz - Via indirectly implemented interface
+ *
+ *
+ * @author Craig R. McClanahan
+ * @version $Revision: 1.1 $ $Date: 2002/11/14 18:53:36 $
+ */
+
+class PrivateBean implements PrivateDirect {
+
+
+ // ----------------------------------------------------------- Constructors
+
+
+ /**
+ * Package private constructor - can only use factory method to create
+ * beans.
+ */
+ PrivateBean() {
+
+ super();
+
+ }
+
+
+ // ------------------------------------------------------------- Properties
+
+
+ /**
+ * A directly implemented property.
+ */
+ private String foo = "This is foo";
+
+ public String getFoo() {
+
+ return (this.foo);
+
+ }
+
+
+ /**
+ * A property accessible via a directly implemented interface.
+ */
+ private String bar = "This is bar";
+
+ public String getBar() {
+
+ return (this.bar);
+
+ }
+
+
+ /**
+ * A method accessible via a directly implemented interface.
+ */
+ public String methodBar(String in) {
+
+ return (in);
+
+ }
+
+
+ /**
+ * A property accessible via an indirectly implemented interface.
+ */
+ private String baz = "This is baz";
+
+ public String getBaz() {
+
+ return (this.baz);
+
+ }
+
+
+ /**
+ * A method accessible via an indirectly implemented interface.
+ */
+ public String methodBaz(String in) {
+
+ return (in);
+
+ }
+
+
+}
diff --git a/examples/cl2/src/test/org/apache/commons/lang/reflect/priv/PrivateBeanFactory.java b/examples/cl2/src/test/org/apache/commons/lang/reflect/priv/PrivateBeanFactory.java
new file mode 100644
index 00000000..e405b497
--- /dev/null
+++ b/examples/cl2/src/test/org/apache/commons/lang/reflect/priv/PrivateBeanFactory.java
@@ -0,0 +1,97 @@
+/*
+ * $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//lang/src/test/org/apache/commons/lang/reflect/priv/Attic/PrivateBeanFactory.java,v 1.1 2002/11/14 18:53:36 rdonkin Exp $
+ * $Revision: 1.1 $
+ * $Date: 2002/11/14 18:53:36 $
+ *
+ * ====================================================================
+ *
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 1999-2002 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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 Group.
+ *
+ * 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
+ * .
+ *
+ */
+
+
+package org.apache.commons.lang.reflect.priv;
+
+
+/**
+ * Factory class for PrivateBean instances.
+ *
+ * @author Craig R. McClanahan
+ * @author Jan Sorensen
+ * @version $Revision: 1.1 $ $Date: 2002/11/14 18:53:36 $
+ */
+
+public class PrivateBeanFactory {
+
+
+ /**
+ * Factory method to create new beans.
+ */
+ public static PrivateDirect create() {
+
+ return (new PrivateBean());
+
+ }
+
+
+ /**
+ * Factory method to create new beans.
+ */
+ public static PrivateDirect createSubclass() {
+
+ return (new PrivateBeanSubclass());
+
+ }
+
+
+}
diff --git a/examples/cl2/src/test/org/apache/commons/lang/reflect/priv/PrivateBeanSubclass.java b/examples/cl2/src/test/org/apache/commons/lang/reflect/priv/PrivateBeanSubclass.java
new file mode 100644
index 00000000..8aa86bdc
--- /dev/null
+++ b/examples/cl2/src/test/org/apache/commons/lang/reflect/priv/PrivateBeanSubclass.java
@@ -0,0 +1,103 @@
+/*
+ * $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//lang/src/test/org/apache/commons/lang/reflect/priv/Attic/PrivateBeanSubclass.java,v 1.1 2002/11/14 18:53:36 rdonkin Exp $
+ * $Revision: 1.1 $
+ * $Date: 2002/11/14 18:53:36 $
+ *
+ * ====================================================================
+ *
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 1999-2002 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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 Group.
+ *
+ * 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
+ * .
+ *
+ */
+
+
+package org.apache.commons.lang.reflect.priv;
+
+
+/**
+ * Bean that exposes methods defined by an interface that is implemented
+ * in the superclass.
+ *
+ * @author Jan Sorensen
+ * @version $Revision: 1.1 $ $Date: 2002/11/14 18:53:36 $
+ */
+
+class PrivateBeanSubclass extends PrivateBean {
+
+
+ // ----------------------------------------------------------- Constructors
+
+
+ /**
+ * Create a new PrivateBeanSubclass instance.
+ */
+ PrivateBeanSubclass() {
+
+ super();
+
+ }
+
+
+ // ------------------------------------------------------------- Properties
+
+
+ /**
+ * A property accessible via the superclass.
+ */
+ public String getBar() {
+
+ return (super.getBar());
+
+ }
+
+
+}
diff --git a/examples/cl2/src/test/org/apache/commons/lang/reflect/priv/PrivateDirect.java b/examples/cl2/src/test/org/apache/commons/lang/reflect/priv/PrivateDirect.java
new file mode 100644
index 00000000..6eae95f0
--- /dev/null
+++ b/examples/cl2/src/test/org/apache/commons/lang/reflect/priv/PrivateDirect.java
@@ -0,0 +1,90 @@
+/*
+ * $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//lang/src/test/org/apache/commons/lang/reflect/priv/Attic/PrivateDirect.java,v 1.1 2002/11/14 18:53:36 rdonkin Exp $
+ * $Revision: 1.1 $
+ * $Date: 2002/11/14 18:53:36 $
+ *
+ * ====================================================================
+ *
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 1999-2002 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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 Group.
+ *
+ * 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
+ * .
+ *
+ */
+
+
+package org.apache.commons.lang.reflect.priv;
+
+
+/**
+ * Interface that is directly implemented by PrivateBean.
+ *
+ * @author Craig R. McClanahan
+ * @version $Revision: 1.1 $ $Date: 2002/11/14 18:53:36 $
+ */
+
+public interface PrivateDirect extends PrivateIndirect {
+
+
+ // ------------------------------------------------------------- Properties
+
+
+ /**
+ * A property accessible via a directly implemented interface.
+ */
+ String getBar();
+
+
+ /**
+ * A method accessible via a directly implemented interface.
+ */
+ String methodBar(String in);
+
+}
diff --git a/examples/cl2/src/test/org/apache/commons/lang/reflect/priv/PrivateIndirect.java b/examples/cl2/src/test/org/apache/commons/lang/reflect/priv/PrivateIndirect.java
new file mode 100644
index 00000000..3a0976ab
--- /dev/null
+++ b/examples/cl2/src/test/org/apache/commons/lang/reflect/priv/PrivateIndirect.java
@@ -0,0 +1,91 @@
+/*
+ * $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//lang/src/test/org/apache/commons/lang/reflect/priv/Attic/PrivateIndirect.java,v 1.1 2002/11/14 18:53:36 rdonkin Exp $
+ * $Revision: 1.1 $
+ * $Date: 2002/11/14 18:53:36 $
+ *
+ * ====================================================================
+ *
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 1999-2002 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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 Group.
+ *
+ * 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
+ * .
+ *
+ */
+
+
+package org.apache.commons.lang.reflect.priv;
+
+
+/**
+ * Interface that is indirectly implemented by PrivateBean.
+ *
+ * @author Craig R. McClanahan
+ * @version $Revision: 1.1 $ $Date: 2002/11/14 18:53:36 $
+ */
+
+public interface PrivateIndirect {
+
+
+ // ------------------------------------------------------------- Properties
+
+
+ /**
+ * A property accessible via an indirectly implemented interface.
+ */
+ public String getBaz();
+
+
+ /**
+ * A method accessible via an indirectly implemented interface.
+ */
+ public String methodBaz(String in);
+
+
+}
diff --git a/examples/cl2/src/test/org/apache/commons/lang/reflect/priv/PublicSubBean.java b/examples/cl2/src/test/org/apache/commons/lang/reflect/priv/PublicSubBean.java
new file mode 100644
index 00000000..80cbbaca
--- /dev/null
+++ b/examples/cl2/src/test/org/apache/commons/lang/reflect/priv/PublicSubBean.java
@@ -0,0 +1,114 @@
+/*
+ * $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//lang/src/test/org/apache/commons/lang/reflect/priv/Attic/PublicSubBean.java,v 1.1 2002/11/14 18:53:36 rdonkin Exp $
+ * $Revision: 1.1 $
+ * $Date: 2002/11/14 18:53:36 $
+ *
+ * ====================================================================
+ *
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 1999-2002 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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 Group.
+ *
+ * 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
+ * .
+ *
+ */
+
+
+package org.apache.commons.lang.reflect.priv;
+
+
+/**
+ * This class is designed to test the default access jvm problem workaround.
+ * The issue is that public methods of a public subclass contained in a default access
+ * superclass are returned by reflection but an IllegalAccessException is thrown
+ * when they are invoked.
+ *
+ * This is the default access superclass
+ *
+ * @author Robert Burrell Donkin
+ * @version $Revision: 1.1 $ $Date: 2002/11/14 18:53:36 $
+ */
+
+public class PublicSubBean extends PackageBean {
+
+
+ // ----------------------------------------------------------- Constructors
+
+
+ /**
+ * Package private constructor - can only use factory method to create
+ * beans.
+ */
+ public PublicSubBean() {
+
+ super();
+
+ }
+
+
+ // ------------------------------------------------------------- Properties
+
+
+ /**
+ * A directly implemented property.
+ */
+ private String foo = "This is foo";
+
+ public String getFoo() {
+
+ return (this.foo);
+
+ }
+
+ public void setFoo(String foo) {
+
+ this.foo = foo;
+
+ }
+}
diff --git a/examples/cl2/src/test/org/apache/commons/lang/time/DateFormatUtilsTest.java b/examples/cl2/src/test/org/apache/commons/lang/time/DateFormatUtilsTest.java
new file mode 100644
index 00000000..bd83416f
--- /dev/null
+++ b/examples/cl2/src/test/org/apache/commons/lang/time/DateFormatUtilsTest.java
@@ -0,0 +1,199 @@
+/* ====================================================================
+ * 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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
+ * .
+ */
+package org.apache.commons.lang.time;
+
+import java.util.Calendar;
+import java.util.TimeZone;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import junit.textui.TestRunner;
+
+/**
+ * TestCase for DateFormatUtils.
+ *
+ * @author Apache Ant - DateUtilsTest
+ * @author Stephane Bailliez
+ * @author Stefan Bodewig
+ * @author Stephen Colebourne
+ */
+public class DateFormatUtilsTest extends TestCase {
+
+ public static void main(String[] args) {
+ TestRunner.run(suite());
+ }
+
+ public static Test suite() {
+ TestSuite suite = new TestSuite(DateFormatUtilsTest.class);
+ suite.setName("DateFormatUtils Tests");
+ return suite;
+ }
+
+ public DateFormatUtilsTest(String s) {
+ super(s);
+ }
+
+ public void testDateTimeISO(){
+ TimeZone timeZone = TimeZone.getTimeZone("GMT-3");
+ Calendar cal = Calendar.getInstance(timeZone);
+ cal.set(2002,1,23,9,11,12);
+ String text = DateFormatUtils.format(cal.getTime(),
+ DateFormatUtils.ISO_DATETIME_FORMAT.getPattern(), timeZone);
+ assertEquals("2002-02-23T09:11:12", text);
+ text = DateFormatUtils.format(cal.getTime().getTime(),
+ DateFormatUtils.ISO_DATETIME_FORMAT.getPattern(), timeZone);
+ assertEquals("2002-02-23T09:11:12", text);
+ text = DateFormatUtils.ISO_DATETIME_FORMAT.format(cal);
+ assertEquals("2002-02-23T09:11:12", text);
+
+ text = DateFormatUtils.format(cal.getTime(),
+ DateFormatUtils.ISO_DATETIME_TIMEZONE_FORMAT.getPattern(), timeZone);
+ assertEquals("2002-02-23T09:11:12-03:00", text);
+ text = DateFormatUtils.format(cal.getTime().getTime(),
+ DateFormatUtils.ISO_DATETIME_TIMEZONE_FORMAT.getPattern(), timeZone);
+ assertEquals("2002-02-23T09:11:12-03:00", text);
+ text = DateFormatUtils.ISO_DATETIME_TIMEZONE_FORMAT.format(cal);
+ assertEquals("2002-02-23T09:11:12-03:00", text);
+ }
+
+ public void testDateISO(){
+ TimeZone timeZone = TimeZone.getTimeZone("GMT-3");
+ Calendar cal = Calendar.getInstance(timeZone);
+ cal.set(2002,1,23,10,11,12);
+ String text = DateFormatUtils.format(cal.getTime(),
+ DateFormatUtils.ISO_DATE_FORMAT.getPattern(), timeZone);
+ assertEquals("2002-02-23", text);
+ text = DateFormatUtils.format(cal.getTime().getTime(),
+ DateFormatUtils.ISO_DATE_FORMAT.getPattern(), timeZone);
+ assertEquals("2002-02-23", text);
+ text = DateFormatUtils.ISO_DATE_FORMAT.format(cal);
+ assertEquals("2002-02-23", text);
+
+ text = DateFormatUtils.format(cal.getTime(),
+ DateFormatUtils.ISO_DATE_TIMEZONE_FORMAT.getPattern(), timeZone);
+ assertEquals("2002-02-23-03:00", text);
+ text = DateFormatUtils.format(cal.getTime().getTime(),
+ DateFormatUtils.ISO_DATE_TIMEZONE_FORMAT.getPattern(), timeZone);
+ assertEquals("2002-02-23-03:00", text);
+ text = DateFormatUtils.ISO_DATE_TIMEZONE_FORMAT.format(cal);
+ assertEquals("2002-02-23-03:00", text);
+ }
+
+ public void testTimeISO(){
+ TimeZone timeZone = TimeZone.getTimeZone("GMT-3");
+ Calendar cal = Calendar.getInstance(timeZone);
+ cal.set(2002,1,23,10,11,12);
+ String text = DateFormatUtils.format(cal.getTime(),
+ DateFormatUtils.ISO_TIME_FORMAT.getPattern(), timeZone);
+ assertEquals("T10:11:12", text);
+ text = DateFormatUtils.format(cal.getTime().getTime(),
+ DateFormatUtils.ISO_TIME_FORMAT.getPattern(), timeZone);
+ assertEquals("T10:11:12", text);
+ text = DateFormatUtils.ISO_TIME_FORMAT.format(cal);
+ assertEquals("T10:11:12", text);
+
+ text = DateFormatUtils.format(cal.getTime(),
+ DateFormatUtils.ISO_TIME_TIMEZONE_FORMAT.getPattern(), timeZone);
+ assertEquals("T10:11:12-03:00", text);
+ text = DateFormatUtils.format(cal.getTime().getTime(),
+ DateFormatUtils.ISO_TIME_TIMEZONE_FORMAT.getPattern(), timeZone);
+ assertEquals("T10:11:12-03:00", text);
+ text = DateFormatUtils.ISO_TIME_TIMEZONE_FORMAT.format(cal);
+ assertEquals("T10:11:12-03:00", text);
+ }
+
+ public void testTimeNoTISO(){
+ TimeZone timeZone = TimeZone.getTimeZone("GMT-3");
+ Calendar cal = Calendar.getInstance(timeZone);
+ cal.set(2002,1,23,10,11,12);
+ String text = DateFormatUtils.format(cal.getTime(),
+ DateFormatUtils.ISO_TIME_NO_T_FORMAT.getPattern(), timeZone);
+ assertEquals("10:11:12", text);
+ text = DateFormatUtils.format(cal.getTime().getTime(),
+ DateFormatUtils.ISO_TIME_NO_T_FORMAT.getPattern(), timeZone);
+ assertEquals("10:11:12", text);
+ text = DateFormatUtils.ISO_TIME_NO_T_FORMAT.format(cal);
+ assertEquals("10:11:12", text);
+
+ text = DateFormatUtils.format(cal.getTime(),
+ DateFormatUtils.ISO_TIME_NO_T_TIMEZONE_FORMAT.getPattern(), timeZone);
+ assertEquals("10:11:12-03:00", text);
+ text = DateFormatUtils.format(cal.getTime().getTime(),
+ DateFormatUtils.ISO_TIME_NO_T_TIMEZONE_FORMAT.getPattern(), timeZone);
+ assertEquals("10:11:12-03:00", text);
+ text = DateFormatUtils.ISO_TIME_NO_T_TIMEZONE_FORMAT.format(cal);
+ assertEquals("10:11:12-03:00", text);
+ }
+
+ public void testSMTP(){
+ TimeZone timeZone = TimeZone.getTimeZone("GMT-3");
+ Calendar cal = Calendar.getInstance(timeZone);
+ cal.set(2003,5,8,10,11,12);
+ String text = DateFormatUtils.format(cal.getTime(),
+ DateFormatUtils.SMTP_DATETIME_FORMAT.getPattern(), timeZone);
+ assertEquals("Sun, 08 Jun 2003 10:11:12 -0300", text);
+ text = DateFormatUtils.format(cal.getTime().getTime(),
+ DateFormatUtils.SMTP_DATETIME_FORMAT.getPattern(), timeZone);
+ assertEquals("Sun, 08 Jun 2003 10:11:12 -0300", text);
+ text = DateFormatUtils.SMTP_DATETIME_FORMAT.format(cal);
+ assertEquals("Sun, 08 Jun 2003 10:11:12 -0300", text);
+
+ // format UTC
+ text = DateFormatUtils.formatUTC(cal.getTime().getTime(),
+ DateFormatUtils.SMTP_DATETIME_FORMAT.getPattern());
+ assertEquals("Sun, 08 Jun 2003 13:11:12 +0000", text);
+ }
+
+}
diff --git a/examples/cl2/src/test/org/apache/commons/lang/time/DateUtilsTest.java b/examples/cl2/src/test/org/apache/commons/lang/time/DateUtilsTest.java
new file mode 100644
index 00000000..43a2dd10
--- /dev/null
+++ b/examples/cl2/src/test/org/apache/commons/lang/time/DateUtilsTest.java
@@ -0,0 +1,385 @@
+/* ====================================================================
+ * 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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
+ * .
+ */
+package org.apache.commons.lang.time;
+
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.Iterator;
+
+import junit.framework.AssertionFailedError;
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import junit.textui.TestRunner;
+
+/**
+ * Unit tests {@link org.apache.commons.lang.CalendarUtils}.
+ *
+ * @author Serge Knystautas
+ */
+public class DateUtilsTest extends TestCase {
+ DateFormat dateParser = null;
+ DateFormat dateTimeParser = null;
+ Date date1 = null;
+ Date date2 = null;
+
+ public DateUtilsTest(String name) {
+ super(name);
+ }
+
+ public static void main(String[] args) {
+ TestRunner.run(suite());
+ }
+
+ public static Test suite() {
+ TestSuite suite = new TestSuite(DateUtilsTest.class);
+ suite.setName("CalendarUtilsTest Tests");
+ return suite;
+ }
+
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ dateParser = new SimpleDateFormat("MMM dd, yyyy");
+ dateTimeParser = new SimpleDateFormat("MMM dd, yyyy H:mm:ss.SSS");
+
+ date1 = dateTimeParser.parse("February 12, 2002 12:34:56.789");
+ date2 = dateTimeParser.parse("November 18, 2001 1:23:11.321");
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ //-----------------------------------------------------------------------
+
+
+ /**
+ * Tests various values with the round method
+ */
+ public void testRound() throws Exception {
+ assertEquals("round year-1 failed",
+ dateParser.parse("January 1, 2002"),
+ DateUtils.round(date1, Calendar.YEAR));
+ assertEquals("round year-2 failed",
+ dateParser.parse("January 1, 2002"),
+ DateUtils.round(date2, Calendar.YEAR));
+ assertEquals("round month-1 failed",
+ dateParser.parse("February 1, 2002"),
+ DateUtils.round(date1, Calendar.MONTH));
+ assertEquals("round month-2 failed",
+ dateParser.parse("December 1, 2001"),
+ DateUtils.round(date2, Calendar.MONTH));
+ assertEquals("round semimonth-1 failed",
+ dateParser.parse("February 16, 2002"),
+ DateUtils.round(date1, DateUtils.SEMI_MONTH));
+ assertEquals("round semimonth-2 failed",
+ dateParser.parse("November 16, 2001"),
+ DateUtils.round(date2, DateUtils.SEMI_MONTH));
+ assertEquals("round date-1 failed",
+ dateParser.parse("February 13, 2002"),
+ DateUtils.round(date1, Calendar.DATE));
+ assertEquals("round date-2 failed",
+ dateParser.parse("November 18, 2001"),
+ DateUtils.round(date2, Calendar.DATE));
+ assertEquals("round hour-1 failed",
+ dateTimeParser.parse("February 12, 2002 13:00:00.000"),
+ DateUtils.round(date1, Calendar.HOUR));
+ assertEquals("round hour-2 failed",
+ dateTimeParser.parse("November 18, 2001 1:00:00.000"),
+ DateUtils.round(date2, Calendar.HOUR));
+ assertEquals("round minute-1 failed",
+ dateTimeParser.parse("February 12, 2002 12:35:00.000"),
+ DateUtils.round(date1, Calendar.MINUTE));
+ assertEquals("round minute-2 failed",
+ dateTimeParser.parse("November 18, 2001 1:23:00.000"),
+ DateUtils.round(date2, Calendar.MINUTE));
+ assertEquals("round second-1 failed",
+ dateTimeParser.parse("February 12, 2002 12:34:57.000"),
+ DateUtils.round(date1, Calendar.SECOND));
+ assertEquals("round second-2 failed",
+ dateTimeParser.parse("November 18, 2001 1:23:11.000"),
+ DateUtils.round(date2, Calendar.SECOND));
+ }
+
+ /**
+ * Tests various values with the trunc method
+ */
+ public void testTrunc() throws Exception {
+ assertEquals("trunc year-1 failed",
+ dateParser.parse("January 1, 2002"),
+ DateUtils.trunc(date1, Calendar.YEAR));
+ assertEquals("trunc year-2 failed",
+ dateParser.parse("January 1, 2001"),
+ DateUtils.trunc(date2, Calendar.YEAR));
+ assertEquals("trunc month-1 failed",
+ dateParser.parse("February 1, 2002"),
+ DateUtils.trunc(date1, Calendar.MONTH));
+ assertEquals("trunc month-2 failed",
+ dateParser.parse("November 1, 2001"),
+ DateUtils.trunc(date2, Calendar.MONTH));
+ assertEquals("trunc semimonth-1 failed",
+ dateParser.parse("February 1, 2002"),
+ DateUtils.trunc(date1, DateUtils.SEMI_MONTH));
+ assertEquals("trunc semimonth-2 failed",
+ dateParser.parse("November 16, 2001"),
+ DateUtils.trunc(date2, DateUtils.SEMI_MONTH));
+ assertEquals("trunc date-1 failed",
+ dateParser.parse("February 12, 2002"),
+ DateUtils.trunc(date1, Calendar.DATE));
+ assertEquals("trunc date-2 failed",
+ dateParser.parse("November 18, 2001"),
+ DateUtils.trunc(date2, Calendar.DATE));
+ assertEquals("trunc hour-1 failed",
+ dateTimeParser.parse("February 12, 2002 12:00:00.000"),
+ DateUtils.trunc(date1, Calendar.HOUR));
+ assertEquals("trunc hour-2 failed",
+ dateTimeParser.parse("November 18, 2001 1:00:00.000"),
+ DateUtils.trunc(date2, Calendar.HOUR));
+ assertEquals("trunc minute-1 failed",
+ dateTimeParser.parse("February 12, 2002 12:34:00.000"),
+ DateUtils.trunc(date1, Calendar.MINUTE));
+ assertEquals("trunc minute-2 failed",
+ dateTimeParser.parse("November 18, 2001 1:23:00.000"),
+ DateUtils.trunc(date2, Calendar.MINUTE));
+ assertEquals("trunc second-1 failed",
+ dateTimeParser.parse("February 12, 2002 12:34:56.000"),
+ DateUtils.trunc(date1, Calendar.SECOND));
+ assertEquals("trunc second-2 failed",
+ dateTimeParser.parse("November 18, 2001 1:23:11.000"),
+ DateUtils.trunc(date2, Calendar.SECOND));
+
+ }
+
+ /**
+ * Tests the parse method, which is supposed to handle various strings
+ * as flexibly as CVS supports.
+ */
+ public void testParse() throws Exception {
+ //This is difficult to test since the "now" used in the
+ // parse function cannot be controlled. We could possibly control
+ // it by trying before and after and making sure the value we expect
+ // is between the two values calculated.
+ //For now we're just using the custom assertEquals that takes a delta
+
+ Calendar now = null;
+
+ now = Calendar.getInstance();
+ now.add(Calendar.MINUTE, -1);
+ assertEquals("parse 1 minute ago",
+ now, DateUtils.parse("1 minute ago"), 50);
+ now = Calendar.getInstance();
+ now.add(Calendar.MINUTE, -8);
+ assertEquals("parse 8 minutes ago",
+ now, DateUtils.parse("8 minutes ago"), 50);
+
+ now = Calendar.getInstance();
+ now.add(Calendar.DATE, -1);
+ assertEquals("parse yesterday",
+ now, DateUtils.parse("yesterday"), 50);
+
+ now = Calendar.getInstance();
+ now.add(Calendar.DATE, 1);
+ assertEquals("parse tomorrow",
+ now, DateUtils.parse("tomorrow"), 50);
+
+ now = Calendar.getInstance();
+ //Sunday would be 1, Saturday would be 7, so we walk back up to 6 days.
+ if (now.get(Calendar.DAY_OF_WEEK) == 1) {
+ //If Sunday already, we go back a full week
+ now.add(Calendar.DATE, -7);
+ } else {
+ now.add(Calendar.DATE, 1 - now.get(Calendar.DAY_OF_WEEK));
+ }
+ assertEquals("parse last Sunday",
+ now, DateUtils.parse("last Sunday"), 50);
+
+ now = Calendar.getInstance();
+ now.add(Calendar.DATE, -7);
+ assertEquals("parse last week",
+ now, DateUtils.parse("last week"), 50);
+
+ now = Calendar.getInstance();
+ //January would be 0, December would be 11, so we walk back up to 11 months
+ if (now.get(Calendar.MONTH) == 0) {
+ //If January already, we go back a full year
+ now.add(Calendar.MONTH, -12);
+ } else {
+ now.add(Calendar.MONTH, 0 - now.get(Calendar.MONTH));
+ }
+ assertEquals("parse last January",
+ now, DateUtils.parse("last January"), 50);
+ }
+
+ /**
+ * Tests the calendar iterator for week ranges
+ */
+ public void testWeekIterator() throws Exception {
+ Calendar now = Calendar.getInstance();
+ for (int i = 0; i< 7; i++) {
+ Calendar today = DateUtils.trunc(now, Calendar.DATE);
+ Calendar sunday = DateUtils.trunc(now, Calendar.DATE);
+ sunday.add(Calendar.DATE, 1 - sunday.get(Calendar.DAY_OF_WEEK));
+ Calendar monday = DateUtils.trunc(now, Calendar.DATE);
+ if (monday.get(Calendar.DAY_OF_WEEK) == 1) {
+ //This is sunday... roll back 6 days
+ monday.add(Calendar.DATE, -6);
+ } else {
+ monday.add(Calendar.DATE, 2 - monday.get(Calendar.DAY_OF_WEEK));
+ }
+ Calendar centered = DateUtils.trunc(now, Calendar.DATE);
+ centered.add(Calendar.DATE, -3);
+
+ Iterator it = DateUtils.getCalendarIterator(now, DateUtils.RANGE_WEEK_SUNDAY);
+ assertWeekIterator(it, sunday);
+ it = DateUtils.getCalendarIterator(now, DateUtils.RANGE_WEEK_MONDAY);
+ assertWeekIterator(it, monday);
+ it = DateUtils.getCalendarIterator(now, DateUtils.RANGE_WEEK_RELATIVE);
+ assertWeekIterator(it, today);
+ it = DateUtils.getCalendarIterator(now, DateUtils.RANGE_WEEK_CENTER);
+ assertWeekIterator(it, centered);
+ now.add(Calendar.DATE,1);
+ }
+ }
+
+ /**
+ * Tests the calendar iterator for month-based ranges
+ */
+ public void testMonthIterator() throws Exception {
+ Iterator it = DateUtils.getCalendarIterator(date1, DateUtils.RANGE_MONTH_SUNDAY);
+ assertWeekIterator(it,
+ dateParser.parse("January 27, 2002"),
+ dateParser.parse("March 2, 2002"));
+
+ it = DateUtils.getCalendarIterator(date1, DateUtils.RANGE_MONTH_MONDAY);
+ assertWeekIterator(it,
+ dateParser.parse("January 28, 2002"),
+ dateParser.parse("March 3, 2002"));
+
+ it = DateUtils.getCalendarIterator(date2, DateUtils.RANGE_MONTH_SUNDAY);
+ assertWeekIterator(it,
+ dateParser.parse("October 28, 2001"),
+ dateParser.parse("December 1, 2001"));
+
+ it = DateUtils.getCalendarIterator(date2, DateUtils.RANGE_MONTH_MONDAY);
+ assertWeekIterator(it,
+ dateParser.parse("October 29, 2001"),
+ dateParser.parse("December 2, 2001"));
+ }
+
+ /**
+ * This checks that this is a 7 element iterator of Calendar objects
+ * that are dates (no time), and exactly 1 day spaced after each other.
+ */
+ private static void assertWeekIterator(Iterator it, Calendar start) {
+ Calendar end = (Calendar) start.clone();
+ end.add(Calendar.DATE, 6);
+
+ assertWeekIterator(it, start, end);
+ }
+
+ /**
+ * Convenience method for when working with Date objects
+ */
+ private static void assertWeekIterator(Iterator it, Date start, Date end) {
+ Calendar calStart = Calendar.getInstance();
+ calStart.setTime(start);
+ Calendar calEnd = Calendar.getInstance();
+ calEnd.setTime(end);
+
+ assertWeekIterator(it, calStart, calEnd);
+ }
+
+ /**
+ * This checks that this is a 7 divisble iterator of Calendar objects
+ * that are dates (no time), and exactly 1 day spaced after each other
+ * (in addition to the proper start and stop dates)
+ */
+ private static void assertWeekIterator(Iterator it, Calendar start, Calendar end) {
+ Calendar cal = (Calendar) it.next();
+ assertEquals("", start, cal, 0);
+ Calendar last = null;
+ int count = 1;
+ while (it.hasNext()) {
+ //Check this is just a date (no time component)
+ assertEquals("", cal, DateUtils.trunc(cal, Calendar.DATE), 0);
+
+ last = cal;
+ cal = (Calendar) it.next();
+ count++;
+
+ //Check that this is one day more than the last date
+ last.add(Calendar.DATE, 1);
+ assertEquals("", last, cal, 0);
+ }
+ if (count % 7 != 0) {
+ throw new AssertionFailedError("There were " + count + " days in this iterator");
+ }
+ assertEquals("", end, cal, 0);
+ }
+
+ /**
+ * Used to check that Calendar objects are close enough
+ * delta is in milliseconds
+ */
+ public static void assertEquals(String message, Calendar cal1, Calendar cal2, long delta) {
+ if (Math.abs(cal1.getTime().getTime() - cal2.getTime().getTime()) > delta) {
+ throw new AssertionFailedError(
+ message + " expected " + cal1.getTime() + " but got " + cal2.getTime());
+ }
+ }
+}
+
diff --git a/examples/cl2/src/test/org/apache/commons/lang/time/DurationFormatUtilsTest.java b/examples/cl2/src/test/org/apache/commons/lang/time/DurationFormatUtilsTest.java
new file mode 100644
index 00000000..75365b80
--- /dev/null
+++ b/examples/cl2/src/test/org/apache/commons/lang/time/DurationFormatUtilsTest.java
@@ -0,0 +1,162 @@
+/* ====================================================================
+ * 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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
+ * .
+ */
+package org.apache.commons.lang.time;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import junit.textui.TestRunner;
+
+/**
+ * TestCase for DurationFormatUtils.
+ *
+ * @author Apache Ant - DateUtilsTest
+ * @author Stephane Bailliez
+ * @author Stefan Bodewig
+ * @author Stephen Colebourne
+ */
+public class DurationFormatUtilsTest extends TestCase {
+
+ public static void main(String[] args) {
+ TestRunner.run(suite());
+ }
+
+ public static Test suite() {
+ TestSuite suite = new TestSuite(DurationFormatUtilsTest.class);
+ suite.setName("DurationFormatUtils Tests");
+ return suite;
+ }
+
+ public DurationFormatUtilsTest(String s) {
+ super(s);
+ }
+
+ public void testFormatWords(){
+ String text = null;
+
+ text = DurationFormatUtils.formatWords(50*1000, true, false);
+ assertEquals("50 seconds", text);
+ text = DurationFormatUtils.formatWords(65*1000, true, false);
+ assertEquals("1 minute 5 seconds", text);
+ text = DurationFormatUtils.formatWords(120*1000, true, false);
+ assertEquals("2 minutes 0 seconds", text);
+ text = DurationFormatUtils.formatWords(121*1000, true, false);
+ assertEquals("2 minutes 1 second", text);
+ text = DurationFormatUtils.formatWords(72*60*1000, true, false);
+ assertEquals("1 hour 12 minutes 0 seconds", text);
+
+ text = DurationFormatUtils.formatWords(50*1000, true, true);
+ assertEquals("50 seconds", text);
+ text = DurationFormatUtils.formatWords(65*1000, true, true);
+ assertEquals("1 minute 5 seconds", text);
+ text = DurationFormatUtils.formatWords(120*1000, true, true);
+ assertEquals("2 minutes", text);
+ text = DurationFormatUtils.formatWords(121*1000, true, true);
+ assertEquals("2 minutes 1 second", text);
+ text = DurationFormatUtils.formatWords(72*60*1000, true, true);
+ assertEquals("1 hour 12 minutes", text);
+
+ text = DurationFormatUtils.formatWords(50*1000, false, true);
+ assertEquals("0 days 0 hours 0 minutes 50 seconds", text);
+ text = DurationFormatUtils.formatWords(65*1000, false, true);
+ assertEquals("0 days 0 hours 1 minute 5 seconds", text);
+ text = DurationFormatUtils.formatWords(120*1000, false, true);
+ assertEquals("0 days 0 hours 2 minutes", text);
+ text = DurationFormatUtils.formatWords(121*1000, false, true);
+ assertEquals("0 days 0 hours 2 minutes 1 second", text);
+ text = DurationFormatUtils.formatWords(72*60*1000, false, true);
+ assertEquals("0 days 1 hour 12 minutes", text);
+
+ text = DurationFormatUtils.formatWords(50*1000, false, false);
+ assertEquals("0 days 0 hours 0 minutes 50 seconds", text);
+ text = DurationFormatUtils.formatWords(65*1000, false, false);
+ assertEquals("0 days 0 hours 1 minute 5 seconds", text);
+ text = DurationFormatUtils.formatWords(120*1000, false, false);
+ assertEquals("0 days 0 hours 2 minutes 0 seconds", text);
+ text = DurationFormatUtils.formatWords(121*1000, false, false);
+ assertEquals("0 days 0 hours 2 minutes 1 second", text);
+ text = DurationFormatUtils.formatWords(72*60*1000, false, false);
+ assertEquals("0 days 1 hour 12 minutes 0 seconds", text);
+ }
+
+ public void testFormatISOStyle(){
+ long time = 0;
+ assertEquals("0:00:00.000", DurationFormatUtils.formatISO(time));
+
+ time = 1;
+ assertEquals("0:00:00.001", DurationFormatUtils.formatISO(time));
+
+ time = 15;
+ assertEquals("0:00:00.015", DurationFormatUtils.formatISO(time));
+
+ time = 165;
+ assertEquals("0:00:00.165", DurationFormatUtils.formatISO(time));
+
+ time = 1675;
+ assertEquals("0:00:01.675", DurationFormatUtils.formatISO(time));
+
+ time = 13465;
+ assertEquals("0:00:13.465", DurationFormatUtils.formatISO(time));
+
+ time = 72789;
+ assertEquals("0:01:12.789", DurationFormatUtils.formatISO(time));
+
+ time = 12789 + 32 * 60000;
+ assertEquals("0:32:12.789", DurationFormatUtils.formatISO(time));
+
+ time = 12789 + 62 * 60000;
+ assertEquals("1:02:12.789", DurationFormatUtils.formatISO(time));
+ }
+
+}
diff --git a/examples/cl2/src/test/org/apache/commons/lang/time/FastDateFormatTest.java b/examples/cl2/src/test/org/apache/commons/lang/time/FastDateFormatTest.java
new file mode 100644
index 00000000..2b651132
--- /dev/null
+++ b/examples/cl2/src/test/org/apache/commons/lang/time/FastDateFormatTest.java
@@ -0,0 +1,250 @@
+/* ====================================================================
+ * 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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
+ * .
+ */
+package org.apache.commons.lang.time;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.GregorianCalendar;
+import java.util.Locale;
+import java.util.TimeZone;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import junit.textui.TestRunner;
+
+/**
+ * Unit tests {@link org.apache.commons.lang.time.FastDateFormat}.
+ *
+ * @author Sean Schofield
+ * @since 2.0
+ * @version $Id: FastDateFormatTest.java,v 1.4 2003/06/08 23:14:23 scolebourne Exp $
+ */
+public class FastDateFormatTest extends TestCase {
+
+ private FastDateFormat fastDateFormat = null;
+
+ public FastDateFormatTest(String name) {
+ super(name);
+ }
+
+ public static void main(String[] args) {
+ TestRunner.run(suite());
+ }
+
+ public static Test suite() {
+ TestSuite suite = new TestSuite(FastDateFormatTest.class);
+ suite.setName("FastDateFormat Tests");
+
+ return suite;
+ }
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ public void test_getInstance() {
+ FastDateFormat format1 = FastDateFormat.getInstance();
+ FastDateFormat format2 = FastDateFormat.getInstance();
+ assertSame(format1, format2);
+ assertEquals(new SimpleDateFormat().toPattern(), format1.getPattern());
+ }
+
+ public void test_getInstance_String() {
+ FastDateFormat format1 = FastDateFormat.getInstance("MM/DD/yyyy");
+ FastDateFormat format2 = FastDateFormat.getInstance("MM-DD-yyyy");
+ FastDateFormat format3 = FastDateFormat.getInstance("MM-DD-yyyy");
+
+ assertTrue(format1 != format2); // -- junit 3.8 version -- assertFalse(format1 == format2);
+ assertSame(format2, format3);
+ assertEquals("MM/DD/yyyy", format1.getPattern());
+ assertEquals(TimeZone.getDefault(), format1.getTimeZone());
+ assertEquals(TimeZone.getDefault(), format2.getTimeZone());
+ assertEquals(false, format1.getTimeZoneOverridesCalendar());
+ assertEquals(false, format2.getTimeZoneOverridesCalendar());
+ }
+
+ public void test_getInstance_String_TimeZone() {
+ Locale realDefaultLocale = Locale.getDefault();
+ TimeZone realDefaultZone = TimeZone.getDefault();
+ try {
+ Locale.setDefault(Locale.US);
+ TimeZone.setDefault(TimeZone.getTimeZone("America/New_York"));
+
+ FastDateFormat format1 = FastDateFormat.getInstance("MM/DD/yyyy",
+ TimeZone.getTimeZone("Atlantic/Reykjavik"));
+ FastDateFormat format2 = FastDateFormat.getInstance("MM/DD/yyyy");
+ FastDateFormat format3 = FastDateFormat.getInstance("MM/DD/yyyy", TimeZone.getDefault());
+ FastDateFormat format4 = FastDateFormat.getInstance("MM/DD/yyyy", TimeZone.getDefault());
+ FastDateFormat format5 = FastDateFormat.getInstance("MM-DD-yyyy", TimeZone.getDefault());
+ FastDateFormat format6 = FastDateFormat.getInstance("MM-DD-yyyy");
+
+ assertTrue(format1 != format2); // -- junit 3.8 version -- assertFalse(format1 == format2);
+ assertEquals(TimeZone.getTimeZone("Atlantic/Reykjavik"), format1.getTimeZone());
+ assertEquals(true, format1.getTimeZoneOverridesCalendar());
+ assertEquals(TimeZone.getDefault(), format2.getTimeZone());
+ assertEquals(false, format2.getTimeZoneOverridesCalendar());
+ assertSame(format3, format4);
+ assertTrue(format3 != format5); // -- junit 3.8 version -- assertFalse(format3 == format5);
+ assertTrue(format4 != format6); // -- junit 3.8 version -- assertFalse(format3 == format5);
+
+ } finally {
+ Locale.setDefault(realDefaultLocale);
+ TimeZone.setDefault(realDefaultZone);
+ }
+ }
+
+ public void test_getInstance_String_Locale() {
+ Locale realDefaultLocale = Locale.getDefault();
+ try {
+ Locale.setDefault(Locale.US);
+ FastDateFormat format1 = FastDateFormat.getInstance("MM/DD/yyyy", Locale.GERMANY);
+ FastDateFormat format2 = FastDateFormat.getInstance("MM/DD/yyyy");
+ FastDateFormat format3 = FastDateFormat.getInstance("MM/DD/yyyy", Locale.GERMANY);
+
+ assertTrue(format1 != format2); // -- junit 3.8 version -- assertFalse(format1 == format2);
+ assertSame(format1, format3);
+ assertSame(Locale.GERMANY, format1.getLocale());
+
+ } finally {
+ Locale.setDefault(realDefaultLocale);
+ }
+ }
+
+ public void test_getInstance_String_TimeZone_Locale() {
+ Locale realDefaultLocale = Locale.getDefault();
+ TimeZone realDefaultZone = TimeZone.getDefault();
+ try {
+ Locale.setDefault(Locale.US);
+ TimeZone.setDefault(TimeZone.getTimeZone("America/New_York"));
+
+ FastDateFormat format1 = FastDateFormat.getInstance("MM/DD/yyyy",
+ TimeZone.getTimeZone("Atlantic/Reykjavik"), Locale.GERMANY);
+ FastDateFormat format2 = FastDateFormat.getInstance("MM/DD/yyyy", Locale.GERMANY);
+ FastDateFormat format3 = FastDateFormat.getInstance("MM/DD/yyyy",
+ TimeZone.getDefault(), Locale.GERMANY);
+
+ assertTrue(format1 != format2); // -- junit 3.8 version -- assertNotSame(format1, format2);
+ assertEquals(TimeZone.getTimeZone("Atlantic/Reykjavik"), format1.getTimeZone());
+ assertEquals(TimeZone.getDefault(), format2.getTimeZone());
+ assertEquals(TimeZone.getDefault(), format3.getTimeZone());
+ assertEquals(true, format1.getTimeZoneOverridesCalendar());
+ assertEquals(false, format2.getTimeZoneOverridesCalendar());
+ assertEquals(true, format3.getTimeZoneOverridesCalendar());
+ assertEquals(Locale.GERMANY, format1.getLocale());
+ assertEquals(Locale.GERMANY, format2.getLocale());
+ assertEquals(Locale.GERMANY, format3.getLocale());
+
+ } finally {
+ Locale.setDefault(realDefaultLocale);
+ TimeZone.setDefault(realDefaultZone);
+ }
+ }
+
+ public void testFormat() {
+ Locale realDefaultLocale = Locale.getDefault();
+ TimeZone realDefaultZone = TimeZone.getDefault();
+ try {
+ Locale.setDefault(Locale.US);
+ TimeZone.setDefault(TimeZone.getTimeZone("America/New_York"));
+ FastDateFormat fdf = null;
+ SimpleDateFormat sdf = null;
+
+ GregorianCalendar cal1 = new GregorianCalendar(2003, 0, 10, 15, 33, 20);
+ GregorianCalendar cal2 = new GregorianCalendar(2003, 6, 10, 9, 00, 00);
+ Date date1 = cal1.getTime();
+ Date date2 = cal2.getTime();
+
+ fdf = FastDateFormat.getInstance("yyyy-MM-dd'T'HH:mm:ss");
+ sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
+ assertEquals(sdf.format(date1), fdf.format(date1));
+ assertEquals("2003-01-10T15:33:20", fdf.format(date1));
+ assertEquals("2003-01-10T15:33:20", fdf.format(cal1));
+ assertEquals("2003-07-10T09:00:00", fdf.format(date2));
+ assertEquals("2003-07-10T09:00:00", fdf.format(cal2));
+
+ fdf = FastDateFormat.getInstance("Z");
+ assertEquals("-0500", fdf.format(date1));
+ assertEquals("-0500", fdf.format(cal1));
+
+ fdf = FastDateFormat.getInstance("Z");
+ assertEquals("-0400", fdf.format(date2));
+ assertEquals("-0400", fdf.format(cal2));
+
+ fdf = FastDateFormat.getInstance("ZZ");
+ assertEquals("-05:00", fdf.format(date1));
+ assertEquals("-05:00", fdf.format(cal1));
+
+ fdf = FastDateFormat.getInstance("ZZ");
+ assertEquals("-04:00", fdf.format(date2));
+ assertEquals("-04:00", fdf.format(cal2));
+
+ String pattern = "GGGG GGG GG G yyyy yyy yy y MMMM MMM MM M" +
+ " dddd ddd dd d DDDD DDD DD D EEEE EEE EE E aaaa aaa aa a zzzz zzz zz z";
+ fdf = FastDateFormat.getInstance(pattern);
+ sdf = new SimpleDateFormat(pattern);
+ assertEquals(sdf.format(date1), fdf.format(date1));
+ assertEquals(sdf.format(date2), fdf.format(date2));
+
+ } finally {
+ Locale.setDefault(realDefaultLocale);
+ TimeZone.setDefault(realDefaultZone);
+ }
+ }
+
+}
diff --git a/examples/cl2/src/test/org/apache/commons/lang/time/StopWatchTest.java b/examples/cl2/src/test/org/apache/commons/lang/time/StopWatchTest.java
new file mode 100644
index 00000000..eeb055fc
--- /dev/null
+++ b/examples/cl2/src/test/org/apache/commons/lang/time/StopWatchTest.java
@@ -0,0 +1,138 @@
+/* ====================================================================
+ * 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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
+ * .
+ */
+package org.apache.commons.lang.time;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import junit.textui.TestRunner;
+
+/**
+ * TestCase for StopWatch.
+ *
+ * @author Stephen Colebourne
+ * @version $Id: StopWatchTest.java,v 1.3 2003/06/08 23:14:23 scolebourne Exp $
+ */
+public class StopWatchTest extends TestCase {
+
+ public static void main(String[] args) {
+ TestRunner.run(suite());
+ }
+
+ public static Test suite() {
+ TestSuite suite = new TestSuite(StopWatchTest.class);
+ suite.setName("StopWatch Tests");
+ return suite;
+ }
+
+ public StopWatchTest(String s) {
+ super(s);
+ }
+
+ public void testStopWatchSimple(){
+ StopWatch watch = new StopWatch();
+ assertEquals(0, watch.getTime());
+
+ watch.start();
+ try {Thread.sleep(550);} catch (InterruptedException ex) {}
+ watch.stop();
+ long time = watch.getTime();
+ assertEquals(time, watch.getTime());
+
+ assertTrue(time >= 500);
+ assertTrue(time < 650);
+
+ watch.reset();
+ assertEquals(0, watch.getTime());
+ }
+
+ public void testStopWatchSplit(){
+ StopWatch watch = new StopWatch();
+ watch.start();
+ try {Thread.sleep(550);} catch (InterruptedException ex) {}
+ watch.split();
+ long splitTime = watch.getTime();
+ try {Thread.sleep(550);} catch (InterruptedException ex) {}
+ watch.unsplit();
+ try {Thread.sleep(550);} catch (InterruptedException ex) {}
+ watch.stop();
+ long totalTime = watch.getTime();
+
+// System.err.println(splitTime +" "+totalTime);
+ assertTrue(splitTime >= 500);
+ assertTrue(splitTime < 650);
+ assertTrue(totalTime >= 1500);
+ assertTrue(totalTime < 1800);
+ }
+
+ public void testStopWatchSuspend(){
+ StopWatch watch = new StopWatch();
+ watch.start();
+ try {Thread.sleep(550);} catch (InterruptedException ex) {}
+ watch.suspend();
+ long suspendTime = watch.getTime();
+ try {Thread.sleep(550);} catch (InterruptedException ex) {}
+ watch.resume();
+ try {Thread.sleep(550);} catch (InterruptedException ex) {}
+ watch.stop();
+ long totalTime = watch.getTime();
+
+// System.err.println(suspendTime +" "+totalTime);
+ assertTrue(suspendTime >= 500);
+ assertTrue(suspendTime < 600);
+ assertTrue(totalTime >= 1000);
+ assertTrue(totalTime < 1200);
+ }
+
+}
diff --git a/examples/cl2/src/test/org/apache/commons/lang/time/TimeTestSuite.java b/examples/cl2/src/test/org/apache/commons/lang/time/TimeTestSuite.java
new file mode 100644
index 00000000..65c232b9
--- /dev/null
+++ b/examples/cl2/src/test/org/apache/commons/lang/time/TimeTestSuite.java
@@ -0,0 +1,96 @@
+/* ====================================================================
+ * 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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
+ * .
+ */
+package org.apache.commons.lang.time;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import junit.textui.TestRunner;
+
+/**
+ * Test suite for the Time package.
+ *
+ * @author Stephen Colebourne
+ * @version $Id: TimeTestSuite.java,v 1.4 2003/06/08 23:14:23 scolebourne Exp $
+ */
+public class TimeTestSuite extends TestCase {
+
+ /**
+ * Construct a new instance.
+ */
+ public TimeTestSuite(String name) {
+ super(name);
+ }
+
+ /**
+ * Command-line interface.
+ */
+ public static void main(String[] args) {
+ TestRunner.run(suite());
+ }
+
+ /**
+ * Get the suite of tests
+ */
+ public static Test suite() {
+ TestSuite suite = new TestSuite();
+ suite.setName("Commons-Lang-Time Tests");
+ suite.addTest(DateUtilsTest.suite());
+ suite.addTest(DateFormatUtilsTest.suite());
+ suite.addTest(DurationFormatUtilsTest.suite());
+ suite.addTest(StopWatchTest.suite());
+ suite.addTest(FastDateFormatTest.suite());
+ return suite;
+ }
+}
diff --git a/examples/cl2/src/test/org/apache/commons/lang/util/BitFieldTest.java b/examples/cl2/src/test/org/apache/commons/lang/util/BitFieldTest.java
new file mode 100644
index 00000000..bd997b80
--- /dev/null
+++ b/examples/cl2/src/test/org/apache/commons/lang/util/BitFieldTest.java
@@ -0,0 +1,337 @@
+/*
+ * $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//lang/src/test/org/apache/commons/lang/util/Attic/BitFieldTest.java,v 1.1 2002/12/18 02:50:36 bayard Exp $
+ * $Revision: 1.1 $
+ * $Date: 2002/12/18 02:50:36 $
+ *
+ * ====================================================================
+ *
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2002 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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 Group.
+ *
+ * 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
+ * .
+ *
+ */
+
+package org.apache.commons.lang.util;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import junit.textui.TestRunner;
+
+/**
+ * Class to test BitField functionality
+ *
+ * @author Scott Sanders (sanders at apache dot org)
+ * @author Marc Johnson
+ * @author Glen Stampoultzis (gstamp@iprimus.com.au)
+ * @version $Id: BitFieldTest.java,v 1.1 2002/12/18 02:50:36 bayard Exp $
+ */
+
+public class BitFieldTest
+ extends TestCase
+{
+
+ public static void main(String[] args) {
+ TestRunner.run(suite());
+ }
+
+ public static Test suite() {
+ TestSuite suite = new TestSuite(BitFieldTest.class);
+ suite.setName("BitField Tests");
+ return suite;
+ }
+
+ private static BitField bf_multi = new BitField(0x3F80);
+ private static BitField bf_single = new BitField(0x4000);
+
+ /**
+ * Constructor BitFieldTest
+ *
+ * @param name
+ */
+
+ public BitFieldTest(String name)
+ {
+ super(name);
+ }
+
+ /**
+ * test the getValue() method
+ */
+
+ public void testGetValue()
+ {
+ assertEquals(bf_multi.getValue(-1), 127);
+ assertEquals(bf_multi.getValue(0), 0);
+ assertEquals(bf_single.getValue(-1), 1);
+ assertEquals(bf_single.getValue(0), 0);
+ }
+
+ /**
+ * test the getShortValue() method
+ */
+
+ public void testGetShortValue()
+ {
+ assertEquals(bf_multi.getShortValue(( short ) -1), ( short ) 127);
+ assertEquals(bf_multi.getShortValue(( short ) 0), ( short ) 0);
+ assertEquals(bf_single.getShortValue(( short ) -1), ( short ) 1);
+ assertEquals(bf_single.getShortValue(( short ) 0), ( short ) 0);
+ }
+
+ /**
+ * test the getRawValue() method
+ */
+
+ public void testGetRawValue()
+ {
+ assertEquals(bf_multi.getRawValue(-1), 0x3F80);
+ assertEquals(bf_multi.getRawValue(0), 0);
+ assertEquals(bf_single.getRawValue(-1), 0x4000);
+ assertEquals(bf_single.getRawValue(0), 0);
+ }
+
+ /**
+ * test the getShortRawValue() method
+ */
+
+ public void testGetShortRawValue()
+ {
+ assertEquals(bf_multi.getShortRawValue(( short ) -1),
+ ( short ) 0x3F80);
+ assertEquals(bf_multi.getShortRawValue(( short ) 0), ( short ) 0);
+ assertEquals(bf_single.getShortRawValue(( short ) -1),
+ ( short ) 0x4000);
+ assertEquals(bf_single.getShortRawValue(( short ) 0), ( short ) 0);
+ }
+
+ /**
+ * test the isSet() method
+ */
+
+ public void testIsSet()
+ {
+ assertTrue(!bf_multi.isSet(0));
+ for (int j = 0x80; j <= 0x3F80; j += 0x80)
+ {
+ assertTrue(bf_multi.isSet(j));
+ }
+ assertTrue(!bf_single.isSet(0));
+ assertTrue(bf_single.isSet(0x4000));
+ }
+
+ /**
+ * test the isAllSet() method
+ */
+
+ public void testIsAllSet()
+ {
+ for (int j = 0; j < 0x3F80; j += 0x80)
+ {
+ assertTrue(!bf_multi.isAllSet(j));
+ }
+ assertTrue(bf_multi.isAllSet(0x3F80));
+ assertTrue(!bf_single.isAllSet(0));
+ assertTrue(bf_single.isAllSet(0x4000));
+ }
+
+ /**
+ * test the setValue() method
+ */
+
+ public void testSetValue()
+ {
+ for (int j = 0; j < 128; j++)
+ {
+ assertEquals(bf_multi.getValue(bf_multi.setValue(0, j)), j);
+ assertEquals(bf_multi.setValue(0, j), j << 7);
+ }
+
+ // verify that excess bits are stripped off
+ assertEquals(bf_multi.setValue(0x3f80, 128), 0);
+ for (int j = 0; j < 2; j++)
+ {
+ assertEquals(bf_single.getValue(bf_single.setValue(0, j)), j);
+ assertEquals(bf_single.setValue(0, j), j << 14);
+ }
+
+ // verify that excess bits are stripped off
+ assertEquals(bf_single.setValue(0x4000, 2), 0);
+ }
+
+ /**
+ * test the setShortValue() method
+ */
+
+ public void testSetShortValue()
+ {
+ for (int j = 0; j < 128; j++)
+ {
+ assertEquals(bf_multi
+ .getShortValue(bf_multi
+ .setShortValue(( short ) 0, ( short ) j)), ( short ) j);
+ assertEquals(bf_multi.setShortValue(( short ) 0, ( short ) j),
+ ( short ) (j << 7));
+ }
+
+ // verify that excess bits are stripped off
+ assertEquals(bf_multi.setShortValue(( short ) 0x3f80, ( short ) 128),
+ ( short ) 0);
+ for (int j = 0; j < 2; j++)
+ {
+ assertEquals(bf_single
+ .getShortValue(bf_single
+ .setShortValue(( short ) 0, ( short ) j)), ( short ) j);
+ assertEquals(bf_single.setShortValue(( short ) 0, ( short ) j),
+ ( short ) (j << 14));
+ }
+
+ // verify that excess bits are stripped off
+ assertEquals(bf_single.setShortValue(( short ) 0x4000, ( short ) 2),
+ ( short ) 0);
+ }
+
+ public void testByte()
+ {
+ assertEquals(1, new BitField(1).setByteBoolean(( byte ) 0, true));
+ assertEquals(2, new BitField(2).setByteBoolean(( byte ) 0, true));
+ assertEquals(4, new BitField(4).setByteBoolean(( byte ) 0, true));
+ assertEquals(8, new BitField(8).setByteBoolean(( byte ) 0, true));
+ assertEquals(16, new BitField(16).setByteBoolean(( byte ) 0, true));
+ assertEquals(32, new BitField(32).setByteBoolean(( byte ) 0, true));
+ assertEquals(64, new BitField(64).setByteBoolean(( byte ) 0, true));
+ assertEquals(-128,
+ new BitField(128).setByteBoolean(( byte ) 0, true));
+ assertEquals(0, new BitField(1).setByteBoolean(( byte ) 1, false));
+ assertEquals(0, new BitField(2).setByteBoolean(( byte ) 2, false));
+ assertEquals(0, new BitField(4).setByteBoolean(( byte ) 4, false));
+ assertEquals(0, new BitField(8).setByteBoolean(( byte ) 8, false));
+ assertEquals(0, new BitField(16).setByteBoolean(( byte ) 16, false));
+ assertEquals(0, new BitField(32).setByteBoolean(( byte ) 32, false));
+ assertEquals(0, new BitField(64).setByteBoolean(( byte ) 64, false));
+ assertEquals(0, new BitField(128).setByteBoolean(( byte ) 128,
+ false));
+ assertEquals(-2, new BitField(1).setByteBoolean(( byte ) 255, false));
+ byte clearedBit = new BitField(0x40).setByteBoolean(( byte ) -63,
+ false);
+
+ assertEquals(false, new BitField(0x40).isSet(clearedBit));
+ }
+
+ /**
+ * test the clear() method
+ */
+
+ public void testClear()
+ {
+ assertEquals(bf_multi.clear(-1), 0xFFFFC07F);
+ assertEquals(bf_single.clear(-1), 0xFFFFBFFF);
+ }
+
+ /**
+ * test the clearShort() method
+ */
+
+ public void testClearShort()
+ {
+ assertEquals(bf_multi.clearShort(( short ) -1), ( short ) 0xC07F);
+ assertEquals(bf_single.clearShort(( short ) -1), ( short ) 0xBFFF);
+ }
+
+ /**
+ * test the set() method
+ */
+
+ public void testSet()
+ {
+ assertEquals(bf_multi.set(0), 0x3F80);
+ assertEquals(bf_single.set(0), 0x4000);
+ }
+
+ /**
+ * test the setShort() method
+ */
+
+ public void testSetShort()
+ {
+ assertEquals(bf_multi.setShort(( short ) 0), ( short ) 0x3F80);
+ assertEquals(bf_single.setShort(( short ) 0), ( short ) 0x4000);
+ }
+
+ /**
+ * test the setBoolean() method
+ */
+
+ public void testSetBoolean()
+ {
+ assertEquals(bf_multi.set(0), bf_multi.setBoolean(0, true));
+ assertEquals(bf_single.set(0), bf_single.setBoolean(0, true));
+ assertEquals(bf_multi.clear(-1), bf_multi.setBoolean(-1, false));
+ assertEquals(bf_single.clear(-1), bf_single.setBoolean(-1, false));
+ }
+
+ /**
+ * test the setShortBoolean() method
+ */
+
+ public void testSetShortBoolean()
+ {
+ assertEquals(bf_multi.setShort(( short ) 0),
+ bf_multi.setShortBoolean(( short ) 0, true));
+ assertEquals(bf_single.setShort(( short ) 0),
+ bf_single.setShortBoolean(( short ) 0, true));
+ assertEquals(bf_multi.clearShort(( short ) -1),
+ bf_multi.setShortBoolean(( short ) -1, false));
+ assertEquals(bf_single.clearShort(( short ) -1),
+ bf_single.setShortBoolean(( short ) -1, false));
+ }
+
+}
diff --git a/examples/cl2/src/test/org/apache/commons/lang/util/IdentifierUtilsTest.java b/examples/cl2/src/test/org/apache/commons/lang/util/IdentifierUtilsTest.java
new file mode 100644
index 00000000..0444464a
--- /dev/null
+++ b/examples/cl2/src/test/org/apache/commons/lang/util/IdentifierUtilsTest.java
@@ -0,0 +1,318 @@
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2002 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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
+ * .
+ */
+package org.apache.commons.lang.util;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+/**
+ * Tests the org.apache.commons.lang.util.IdentifierUtils class.
+ *
+ * @author Stephen Colebourne
+ * @version $Id: IdentifierUtilsTest.java,v 1.2 2003/05/16 22:07:38 scolebourne Exp $
+ */
+public class IdentifierUtilsTest extends junit.framework.TestCase {
+
+ /**
+ * Construct
+ */
+ public IdentifierUtilsTest(String name) {
+ super(name);
+ }
+
+ /**
+ * Return class aa a test suite.
+ */
+ public static Test suite() {
+ TestSuite suite = new TestSuite(IdentifierUtilsTest.class);
+ suite.setName("IdentifierUtils Tests");
+ return suite;
+ }
+
+ //--------------------------------------------------------------------------
+
+ public void testLongIncrementing() {
+ LongIdentifierFactory f = IdentifierUtils.LONG_IDENTIFIER_FACTORY;
+ assertEquals(new Long(0), f.nextLongIdentifier());
+ assertEquals(new Long(1), f.nextLongIdentifier());
+ assertEquals(new Long(2), f.nextIdentifier());
+ assertEquals(new Long(3), f.nextLongIdentifier());
+ assertEquals(new Long(4), IdentifierUtils.nextLongIdentifier());
+ assertEquals(new Long(5), f.nextLongIdentifier());
+ assertEquals(new Long(6), IdentifierUtils.nextLongIdentifier());
+ assertEquals(new Long(7), IdentifierUtils.nextLongIdentifier());
+ }
+
+ public void testLongIncrementingNoArgs() {
+ LongIdentifierFactory f = IdentifierUtils.longIdentifierFactory();
+ assertEquals(new Long(0), f.nextLongIdentifier());
+ assertEquals(new Long(1), f.nextLongIdentifier());
+ assertTrue(f != IdentifierUtils.LONG_IDENTIFIER_FACTORY);
+ }
+
+ public void testLongIncrementingInit() {
+ LongIdentifierFactory f = IdentifierUtils.longIdentifierFactory(true, 100);
+ assertEquals(new Long(100), f.nextLongIdentifier());
+ assertEquals(new Long(101), f.nextLongIdentifier());
+ }
+
+ public void testLongIncrementingWrap() {
+ LongIdentifierFactory f = IdentifierUtils.longIdentifierFactory(true, Long.MAX_VALUE);
+ assertEquals(new Long(Long.MAX_VALUE), f.nextLongIdentifier());
+ assertEquals(new Long(Long.MIN_VALUE), f.nextLongIdentifier());
+ }
+
+ public void testLongIncrementingNoWrap() {
+ LongIdentifierFactory f = IdentifierUtils.longIdentifierFactory(false, Long.MAX_VALUE);
+ try {
+ f.nextLongIdentifier();
+ fail();
+ } catch (IllegalStateException ex) {}
+ }
+
+ //--------------------------------------------------------------------------
+
+ public void testStringNumericLong() {
+ StringIdentifierFactory f = IdentifierUtils.STRING_NUMERIC_IDENTIFIER_FACTORY;
+ assertEquals("0", f.nextStringIdentifier());
+ assertEquals("1", f.nextStringIdentifier());
+ assertEquals("2", f.nextIdentifier());
+ assertEquals("3", f.nextStringIdentifier());
+ assertEquals("4", IdentifierUtils.nextStringNumericIdentifier());
+ assertEquals("5", f.nextStringIdentifier());
+ assertEquals("6", IdentifierUtils.nextStringNumericIdentifier());
+ assertEquals("7", IdentifierUtils.nextStringNumericIdentifier());
+ }
+
+ public void testStringNumericNoArgs() {
+ StringIdentifierFactory f = IdentifierUtils.stringNumericIdentifierFactory();
+ assertEquals("0", f.nextStringIdentifier());
+ assertEquals("1", f.nextStringIdentifier());
+ assertTrue(f != IdentifierUtils.STRING_NUMERIC_IDENTIFIER_FACTORY);
+ }
+
+ public void testStringNumericInit() {
+ StringIdentifierFactory f = IdentifierUtils.stringNumericIdentifierFactory(true, 100);
+ assertEquals("100", f.nextStringIdentifier());
+ assertEquals("101", f.nextStringIdentifier());
+ }
+
+ public void testStringNumericWrap() {
+ StringIdentifierFactory f = IdentifierUtils.stringNumericIdentifierFactory(true, Long.MAX_VALUE);
+ assertEquals(Long.toString(Long.MAX_VALUE), f.nextStringIdentifier());
+ assertEquals(Long.toString(Long.MIN_VALUE), f.nextStringIdentifier());
+ }
+
+ public void testStringNumericNoWrap() {
+ StringIdentifierFactory f = IdentifierUtils.stringNumericIdentifierFactory(false, Long.MAX_VALUE);
+ try {
+ f.nextStringIdentifier();
+ fail();
+ } catch (IllegalStateException ex) { }
+ }
+
+ //--------------------------------------------------------------------------
+
+ public void testStringAlphanumeric() {
+ StringIdentifierFactory f = IdentifierUtils.STRING_ALPHANUMERIC_IDENTIFIER_FACTORY;
+ assertEquals("000000000000001", f.nextStringIdentifier());
+ assertEquals("000000000000002", f.nextStringIdentifier());
+ assertEquals("000000000000003", f.nextStringIdentifier());
+ assertEquals("000000000000004", f.nextStringIdentifier());
+ assertEquals("000000000000005", f.nextStringIdentifier());
+ assertEquals("000000000000006", f.nextStringIdentifier());
+ assertEquals("000000000000007", f.nextStringIdentifier());
+ assertEquals("000000000000008", f.nextStringIdentifier());
+ assertEquals("000000000000009", f.nextStringIdentifier());
+ assertEquals("00000000000000a", f.nextStringIdentifier());
+ assertEquals("00000000000000b", f.nextStringIdentifier());
+ assertEquals("00000000000000c", f.nextStringIdentifier());
+ assertEquals("00000000000000d", IdentifierUtils.nextStringAlphanumericIdentifier());
+ assertEquals("00000000000000e", f.nextStringIdentifier());
+ assertEquals("00000000000000f", f.nextStringIdentifier());
+ assertEquals("00000000000000g", f.nextStringIdentifier());
+ assertEquals("00000000000000h", f.nextStringIdentifier());
+ assertEquals("00000000000000i", f.nextStringIdentifier());
+ assertEquals("00000000000000j", f.nextStringIdentifier());
+ assertEquals("00000000000000k", f.nextStringIdentifier());
+ assertEquals("00000000000000l", f.nextStringIdentifier());
+ assertEquals("00000000000000m", f.nextStringIdentifier());
+ assertEquals("00000000000000n", f.nextStringIdentifier());
+ assertEquals("00000000000000o", f.nextStringIdentifier());
+ assertEquals("00000000000000p", f.nextStringIdentifier());
+ assertEquals("00000000000000q", f.nextStringIdentifier());
+ assertEquals("00000000000000r", f.nextStringIdentifier());
+ assertEquals("00000000000000s", f.nextStringIdentifier());
+ assertEquals("00000000000000t", f.nextStringIdentifier());
+ assertEquals("00000000000000u", f.nextStringIdentifier());
+ assertEquals("00000000000000v", f.nextStringIdentifier());
+ assertEquals("00000000000000w", f.nextStringIdentifier());
+ assertEquals("00000000000000x", f.nextStringIdentifier());
+ assertEquals("00000000000000y", f.nextStringIdentifier());
+ assertEquals("00000000000000z", f.nextStringIdentifier());
+ assertEquals("000000000000010", f.nextStringIdentifier());
+ assertEquals("000000000000011", f.nextStringIdentifier());
+ assertEquals("000000000000012", f.nextStringIdentifier());
+ assertEquals("000000000000013", f.nextStringIdentifier());
+ }
+
+ public void testLongAlphanumericNoArgs() {
+ StringIdentifierFactory f = IdentifierUtils.stringAlphanumericIdentifierFactory();
+ assertEquals("000000000000001", f.nextStringIdentifier());
+ assertEquals("000000000000002", f.nextStringIdentifier());
+ assertTrue(f != IdentifierUtils.STRING_ALPHANUMERIC_IDENTIFIER_FACTORY);
+ }
+
+ public void testStringAlphanumericWrap() {
+ StringIdentifierFactory f = IdentifierUtils.stringAlphanumericIdentifierFactory(true, 1);
+ assertEquals("1", f.nextStringIdentifier());
+ assertEquals("2", f.nextStringIdentifier());
+ assertEquals("3", f.nextStringIdentifier());
+ assertEquals("4", f.nextStringIdentifier());
+ assertEquals("5", f.nextStringIdentifier());
+ assertEquals("6", f.nextStringIdentifier());
+ assertEquals("7", f.nextStringIdentifier());
+ assertEquals("8", f.nextStringIdentifier());
+ assertEquals("9", f.nextStringIdentifier());
+ assertEquals("a", f.nextStringIdentifier());
+ assertEquals("b", f.nextStringIdentifier());
+ assertEquals("c", f.nextStringIdentifier());
+ assertEquals("d", f.nextStringIdentifier());
+ assertEquals("e", f.nextStringIdentifier());
+ assertEquals("f", f.nextStringIdentifier());
+ assertEquals("g", f.nextStringIdentifier());
+ assertEquals("h", f.nextStringIdentifier());
+ assertEquals("i", f.nextStringIdentifier());
+ assertEquals("j", f.nextStringIdentifier());
+ assertEquals("k", f.nextStringIdentifier());
+ assertEquals("l", f.nextStringIdentifier());
+ assertEquals("m", f.nextStringIdentifier());
+ assertEquals("n", f.nextStringIdentifier());
+ assertEquals("o", f.nextStringIdentifier());
+ assertEquals("p", f.nextStringIdentifier());
+ assertEquals("q", f.nextStringIdentifier());
+ assertEquals("r", f.nextStringIdentifier());
+ assertEquals("s", f.nextStringIdentifier());
+ assertEquals("t", f.nextStringIdentifier());
+ assertEquals("u", f.nextStringIdentifier());
+ assertEquals("v", f.nextStringIdentifier());
+ assertEquals("w", f.nextStringIdentifier());
+ assertEquals("x", f.nextStringIdentifier());
+ assertEquals("y", f.nextStringIdentifier());
+ assertEquals("z", f.nextStringIdentifier());
+ assertEquals("0", f.nextStringIdentifier());
+ }
+
+ public void testStringAlphanumericNoWrap() {
+ StringIdentifierFactory f = IdentifierUtils.stringAlphanumericIdentifierFactory(false, 1);
+ assertEquals("1", f.nextStringIdentifier());
+ assertEquals("2", f.nextStringIdentifier());
+ assertEquals("3", f.nextStringIdentifier());
+ assertEquals("4", f.nextStringIdentifier());
+ assertEquals("5", f.nextStringIdentifier());
+ assertEquals("6", f.nextStringIdentifier());
+ assertEquals("7", f.nextStringIdentifier());
+ assertEquals("8", f.nextStringIdentifier());
+ assertEquals("9", f.nextStringIdentifier());
+ assertEquals("a", f.nextStringIdentifier());
+ assertEquals("b", f.nextStringIdentifier());
+ assertEquals("c", f.nextStringIdentifier());
+ assertEquals("d", f.nextStringIdentifier());
+ assertEquals("e", f.nextStringIdentifier());
+ assertEquals("f", f.nextStringIdentifier());
+ assertEquals("g", f.nextStringIdentifier());
+ assertEquals("h", f.nextStringIdentifier());
+ assertEquals("i", f.nextStringIdentifier());
+ assertEquals("j", f.nextStringIdentifier());
+ assertEquals("k", f.nextStringIdentifier());
+ assertEquals("l", f.nextStringIdentifier());
+ assertEquals("m", f.nextStringIdentifier());
+ assertEquals("n", f.nextStringIdentifier());
+ assertEquals("o", f.nextStringIdentifier());
+ assertEquals("p", f.nextStringIdentifier());
+ assertEquals("q", f.nextStringIdentifier());
+ assertEquals("r", f.nextStringIdentifier());
+ assertEquals("s", f.nextStringIdentifier());
+ assertEquals("t", f.nextStringIdentifier());
+ assertEquals("u", f.nextStringIdentifier());
+ assertEquals("v", f.nextStringIdentifier());
+ assertEquals("w", f.nextStringIdentifier());
+ assertEquals("x", f.nextStringIdentifier());
+ assertEquals("y", f.nextStringIdentifier());
+ assertEquals("z", f.nextStringIdentifier());
+ try {
+ f.nextStringIdentifier();
+ fail();
+ } catch (IllegalStateException ex) {}
+ }
+
+ //--------------------------------------------------------------------------
+
+ public void testStringSession() {
+ StringIdentifierFactory f = IdentifierUtils.STRING_SESSION_IDENTIFIER_FACTORY;
+ assertTrue(f != IdentifierUtils.stringSessionIdentifierFactory());
+
+ String a = (String) f.nextStringIdentifier();
+ String b = (String) IdentifierUtils.nextStringSessionIdentifier();
+ assertTrue(a.length() >= 10);
+ assertTrue(b.length() >= 10);
+ // could fail, but unlikely
+ assertTrue(a.substring(6, 9) != b.substring(6, 9));
+ assertEquals("0", a.substring(9));
+ assertEquals("1", b.substring(9));
+ }
+
+ //--------------------------------------------------------------------------
+
+}
diff --git a/examples/cl2/src/test/org/apache/commons/lang/util/UtilTestSuite.java b/examples/cl2/src/test/org/apache/commons/lang/util/UtilTestSuite.java
new file mode 100644
index 00000000..7ad025d1
--- /dev/null
+++ b/examples/cl2/src/test/org/apache/commons/lang/util/UtilTestSuite.java
@@ -0,0 +1,94 @@
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2002 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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
+ * .
+ */
+package org.apache.commons.lang.util;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import junit.textui.TestRunner;
+/**
+ * Test suite for the Util package.
+ *
+ * @author Henri Yandell
+ * @author Stephen Colebourne
+ * @version $Id: UtilTestSuite.java,v 1.3 2002/12/29 22:09:53 scolebourne Exp $
+ */
+public class UtilTestSuite extends TestCase {
+
+ /**
+ * Construct a new instance.
+ */
+ public UtilTestSuite(String name) {
+ super(name);
+ }
+
+ /**
+ * Command-line interface.
+ */
+ public static void main(String[] args) {
+ TestRunner.run(suite());
+ }
+
+ /**
+ * Get the suite of tests
+ */
+ public static Test suite() {
+ TestSuite suite = new TestSuite();
+ suite.setName("Commons-Lang-Util Tests");
+ suite.addTest(BitFieldTest.suite());
+ suite.addTest(IdentifierUtilsTest.suite());
+ suite.addTest(ValidateTest.suite());
+ return suite;
+ }
+}
diff --git a/examples/cl2/src/test/org/apache/commons/lang/util/ValidateTest.java b/examples/cl2/src/test/org/apache/commons/lang/util/ValidateTest.java
new file mode 100644
index 00000000..cbaeeed3
--- /dev/null
+++ b/examples/cl2/src/test/org/apache/commons/lang/util/ValidateTest.java
@@ -0,0 +1,367 @@
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2002 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements 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
+ * .
+ */
+package org.apache.commons.lang.util;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import junit.textui.TestRunner;
+/**
+ * Unit tests {@link org.apache.commons.lang.util.Validate}.
+ *
+ * @author Stephen Colebourne
+ * @version $Id: ValidateTest.java,v 1.1 2002/12/29 22:09:53 scolebourne Exp $
+ */
+public class ValidateTest extends TestCase {
+
+ public ValidateTest(String name) {
+ super(name);
+ }
+
+ public static void main(String[] args) {
+ TestRunner.run(suite());
+ }
+
+ public static Test suite() {
+ TestSuite suite = new TestSuite(ValidateTest.class);
+ suite.setName("Validate Tests");
+ return suite;
+ }
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ //-----------------------------------------------------------------------
+ public void testIsTrue1() {
+ Validate.isTrue(true);
+ try {
+ Validate.isTrue(false);
+ } catch (IllegalArgumentException ex) {
+ assertEquals("The validated expression is false", ex.getMessage());
+ }
+ }
+
+ //-----------------------------------------------------------------------
+ public void testIsTrue2() {
+ Validate.isTrue(true, "MSG");
+ try {
+ Validate.isTrue(false, "MSG");
+ } catch (IllegalArgumentException ex) {
+ assertEquals("MSG", ex.getMessage());
+ }
+ }
+
+ //-----------------------------------------------------------------------
+ public void testIsTrue3() {
+ Validate.isTrue(true, "MSG", new Integer(6));
+ try {
+ Validate.isTrue(false, "MSG", new Integer(6));
+ } catch (IllegalArgumentException ex) {
+ assertEquals("MSG6", ex.getMessage());
+ }
+ }
+
+ //-----------------------------------------------------------------------
+ public void testIsTrue4() {
+ Validate.isTrue(true, "MSG", 7);
+ try {
+ Validate.isTrue(false, "MSG", 7);
+ } catch (IllegalArgumentException ex) {
+ assertEquals("MSG7", ex.getMessage());
+ }
+ }
+
+ //-----------------------------------------------------------------------
+ public void testIsTrue5() {
+ Validate.isTrue(true, "MSG", 7.4d);
+ try {
+ Validate.isTrue(false, "MSG", 7.4d);
+ } catch (IllegalArgumentException ex) {
+ assertEquals("MSG7.4", ex.getMessage());
+ }
+ }
+
+ //-----------------------------------------------------------------------
+ public void testNotNull1() {
+ Validate.notNull(new Object());
+ try {
+ Validate.notNull(null);
+ } catch (IllegalArgumentException ex) {
+ assertEquals("The validated object is null", ex.getMessage());
+ }
+ }
+
+ //-----------------------------------------------------------------------
+ public void testNotNull2() {
+ Validate.notNull(new Object(), "MSG");
+ try {
+ Validate.notNull(null, "MSG");
+ } catch (IllegalArgumentException ex) {
+ assertEquals("MSG", ex.getMessage());
+ }
+ }
+
+ //-----------------------------------------------------------------------
+ public void testNotEmptyArray1() {
+ Validate.notEmpty(new Object[] {null});
+ try {
+ Validate.notEmpty((Object[]) null);
+ } catch (IllegalArgumentException ex) {
+ assertEquals("The validated array is empty", ex.getMessage());
+ }
+ try {
+ Validate.notEmpty(new Object[0]);
+ } catch (IllegalArgumentException ex) {
+ assertEquals("The validated array is empty", ex.getMessage());
+ }
+ }
+
+ //-----------------------------------------------------------------------
+ public void testNotEmptyArray2() {
+ Validate.notEmpty(new Object[] {null}, "MSG");
+ try {
+ Validate.notEmpty((Object[]) null, "MSG");
+ } catch (IllegalArgumentException ex) {
+ assertEquals("MSG", ex.getMessage());
+ }
+ try {
+ Validate.notEmpty(new Object[0], "MSG");
+ } catch (IllegalArgumentException ex) {
+ assertEquals("MSG", ex.getMessage());
+ }
+ }
+
+ //-----------------------------------------------------------------------
+ public void testNotEmptyCollection1() {
+ Collection coll = new ArrayList();
+ try {
+ Validate.notEmpty((Collection) null);
+ } catch (IllegalArgumentException ex) {
+ assertEquals("The validated collection is empty", ex.getMessage());
+ }
+ try {
+ Validate.notEmpty(coll);
+ } catch (IllegalArgumentException ex) {
+ assertEquals("The validated collection is empty", ex.getMessage());
+ }
+ coll.add(new Integer(8));
+ Validate.notEmpty(coll);
+ }
+
+ //-----------------------------------------------------------------------
+ public void testNotEmptyCollection2() {
+ Collection coll = new ArrayList();
+ try {
+ Validate.notEmpty((Collection) null, "MSG");
+ } catch (IllegalArgumentException ex) {
+ assertEquals("MSG", ex.getMessage());
+ }
+ try {
+ Validate.notEmpty(coll, "MSG");
+ } catch (IllegalArgumentException ex) {
+ assertEquals("MSG", ex.getMessage());
+ }
+ coll.add(new Integer(8));
+ Validate.notEmpty(coll, "MSG");
+ }
+
+ //-----------------------------------------------------------------------
+ public void testNotEmptyMap1() {
+ Map map = new HashMap();
+ try {
+ Validate.notEmpty((Map) null);
+ } catch (IllegalArgumentException ex) {
+ assertEquals("The validated map is empty", ex.getMessage());
+ }
+ try {
+ Validate.notEmpty(map);
+ } catch (IllegalArgumentException ex) {
+ assertEquals("The validated map is empty", ex.getMessage());
+ }
+ map.put("ll", new Integer(8));
+ Validate.notEmpty(map);
+ }
+
+ //-----------------------------------------------------------------------
+ public void testNotEmptyMap2() {
+ Map map = new HashMap();
+ try {
+ Validate.notEmpty((Map) null, "MSG");
+ } catch (IllegalArgumentException ex) {
+ assertEquals("MSG", ex.getMessage());
+ }
+ try {
+ Validate.notEmpty(map, "MSG");
+ } catch (IllegalArgumentException ex) {
+ assertEquals("MSG", ex.getMessage());
+ }
+ map.put("ll", new Integer(8));
+ Validate.notEmpty(map, "MSG");
+ }
+
+ //-----------------------------------------------------------------------
+ public void testNotEmptyString1() {
+ Validate.notEmpty("hjl");
+ try {
+ Validate.notEmpty((String) null);
+ } catch (IllegalArgumentException ex) {
+ assertEquals("The validated string is empty", ex.getMessage());
+ }
+ try {
+ Validate.notEmpty("");
+ } catch (IllegalArgumentException ex) {
+ assertEquals("The validated string is empty", ex.getMessage());
+ }
+ }
+
+ //-----------------------------------------------------------------------
+ public void testNotEmptyString2() {
+ Validate.notEmpty(new Object[] {null}, "MSG");
+ try {
+ Validate.notEmpty((String) null, "MSG");
+ } catch (IllegalArgumentException ex) {
+ assertEquals("MSG", ex.getMessage());
+ }
+ try {
+ Validate.notEmpty("", "MSG");
+ } catch (IllegalArgumentException ex) {
+ assertEquals("MSG", ex.getMessage());
+ }
+ }
+
+ //-----------------------------------------------------------------------
+ public void testNoNullElementsArray1() {
+ String[] array = new String[] {"a", "b"};
+ Validate.noNullElements(array);
+ try {
+ Validate.noNullElements((Object[]) null);
+ } catch (IllegalArgumentException ex) {
+ assertEquals("The validated object is null", ex.getMessage());
+ }
+ array[1] = null;
+ try {
+ Validate.notEmpty(array);
+ } catch (IllegalArgumentException ex) {
+ assertEquals("The validated array contains null element at index: 1", ex.getMessage());
+ }
+ }
+
+ //-----------------------------------------------------------------------
+ public void testNoNullElementsArray2() {
+ String[] array = new String[] {"a", "b"};
+ Validate.noNullElements(array, "MSG");
+ try {
+ Validate.noNullElements((Object[]) null, "MSG");
+ } catch (IllegalArgumentException ex) {
+ assertEquals("The validated object is null", ex.getMessage());
+ }
+ array[1] = null;
+ try {
+ Validate.notEmpty(array, "MSG");
+ } catch (IllegalArgumentException ex) {
+ assertEquals("MSG", ex.getMessage());
+ }
+ }
+
+ //-----------------------------------------------------------------------
+ public void testNoNullElementsCollection1() {
+ List coll = new ArrayList();
+ coll.add("a");
+ coll.add("b");
+ Validate.noNullElements(coll);
+ try {
+ Validate.noNullElements((Collection) null);
+ } catch (IllegalArgumentException ex) {
+ assertEquals("The validated object is null", ex.getMessage());
+ }
+ coll.set(1, null);
+ try {
+ Validate.notEmpty(coll);
+ } catch (IllegalArgumentException ex) {
+ assertEquals("The validated collection contains null element at index: 1", ex.getMessage());
+ }
+ }
+
+ //-----------------------------------------------------------------------
+ public void testNoNullElementsCollection2() {
+ List coll = new ArrayList();
+ coll.add("a");
+ coll.add("b");
+ Validate.noNullElements(coll, "MSG");
+ try {
+ Validate.noNullElements((Collection) null, "MSG");
+ } catch (IllegalArgumentException ex) {
+ assertEquals("The validated object is null", ex.getMessage());
+ }
+ coll.set(1, null);
+ try {
+ Validate.notEmpty(coll, "MSG");
+ } catch (IllegalArgumentException ex) {
+ assertEquals("MSG", ex.getMessage());
+ }
+ }
+
+ //-----------------------------------------------------------------------
+}
diff --git a/src/main/java/fr/spoonlabs/flacoco/core/coverage/CoverageMatrix.java b/src/main/java/fr/spoonlabs/flacoco/core/coverage/CoverageMatrix.java
index 47b42b5b..0fa795d1 100644
--- a/src/main/java/fr/spoonlabs/flacoco/core/coverage/CoverageMatrix.java
+++ b/src/main/java/fr/spoonlabs/flacoco/core/coverage/CoverageMatrix.java
@@ -8,12 +8,14 @@
import fr.spoonlabs.flacoco.api.result.Location;
import fr.spoonlabs.flacoco.core.config.FlacocoConfig;
import fr.spoonlabs.flacoco.core.test.method.TestMethod;
+import fr.spoonlabs.flacoco.utils.spoon.SpoonBlockInspector;
import org.apache.log4j.Logger;
+import org.apache.maven.plugin.surefire.util.DirectoryScanner;
+import org.apache.maven.surefire.api.testset.TestListResolver;
+import org.jacoco.core.runtime.WildcardMatcher;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
+import java.io.File;
+import java.util.*;
import java.util.stream.Collectors;
/**
@@ -92,8 +94,7 @@ public void processSingleTest(CoverageFromSingleTestUnit iCovWrapper, Set locations = blockMatcher.getBlockLocations(element);
+
+ for (Location blockLocation : locations) {
+ logger.debug("Adding a line from the block where an exception was thrown: " + blockLocation);
+ this.add(blockLocation, testMethod, 1, false);
+ }
}
}
}
@@ -156,4 +167,47 @@ public void add(Location location, TestMethod testMethod, int instExecutedAtLine
this.tests.put(testMethod, testResult);
}
+ /**
+ * Computes if a given class is to be included in the post-coverage computation
+ *
+ * If we have include-exclude patterns for Jacoco:
+ * - We include the class if it matches the include patterns and does not match the excludes patterns
+ * Else:
+ * - We include the class if it is available in the binary directories
+ * @param className
+ * @return true if the class should be included in the coverage result, false otherwise
+ */
+ private boolean classToInclude(String className) {
+ // False if it matches an excludes pattern
+ for (String pattern : config.getJacocoExcludes()) {
+ WildcardMatcher matcher = new WildcardMatcher(pattern);
+ if (matcher.matches(className)) {
+ return false;
+ }
+ }
+ // True if it matches an includes pattern and doesn't match any excludes pattern
+ for (String pattern : config.getJacocoIncludes()) {
+ WildcardMatcher matcher = new WildcardMatcher(pattern);
+ if (matcher.matches(className)) {
+ return true;
+ }
+ }
+
+ // True if it is present in the available binaries
+ for (String dir : config.getBinJavaDir()) {
+ DirectoryScanner directoryScanner = new DirectoryScanner(new File(dir), TestListResolver.getWildcard());
+ if (directoryScanner.scan().getClasses().contains(className)) {
+ return true;
+ }
+ }
+ for (String dir : config.getBinTestDir()) {
+ DirectoryScanner directoryScanner = new DirectoryScanner(new File(dir), TestListResolver.getWildcard());
+ if (directoryScanner.scan().getClasses().contains(className)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
}
diff --git a/src/main/java/fr/spoonlabs/flacoco/utils/spoon/SpoonBlockFilter.java b/src/main/java/fr/spoonlabs/flacoco/utils/spoon/SpoonBlockFilter.java
new file mode 100644
index 00000000..22b765cf
--- /dev/null
+++ b/src/main/java/fr/spoonlabs/flacoco/utils/spoon/SpoonBlockFilter.java
@@ -0,0 +1,25 @@
+package fr.spoonlabs.flacoco.utils.spoon;
+
+import spoon.reflect.code.CtBlock;
+import spoon.reflect.visitor.Filter;
+
+/**
+ * Filters CtBlocks according to a given source code line number.
+ */
+public class SpoonBlockFilter implements Filter> {
+
+ private int lineNumber;
+
+ public SpoonBlockFilter(int lineNumber) {
+ this.lineNumber = lineNumber;
+ }
+
+ /**
+ * @param ctBlock The CtBlock to be analyzed
+ * @return true if the line number is comprehended in the ctBlock, false otherwise
+ */
+ @Override
+ public boolean matches(CtBlock> ctBlock) {
+ return ctBlock.getPosition() != null && ctBlock.getPosition().isValidPosition() && lineNumber >= ctBlock.getPosition().getLine() && lineNumber <= ctBlock.getPosition().getEndLine();
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/fr/spoonlabs/flacoco/utils/spoon/SpoonBlockInspector.java b/src/main/java/fr/spoonlabs/flacoco/utils/spoon/SpoonBlockInspector.java
new file mode 100644
index 00000000..6e2d47d8
--- /dev/null
+++ b/src/main/java/fr/spoonlabs/flacoco/utils/spoon/SpoonBlockInspector.java
@@ -0,0 +1,75 @@
+package fr.spoonlabs.flacoco.utils.spoon;
+
+import fr.spoonlabs.flacoco.api.result.Location;
+import fr.spoonlabs.flacoco.core.config.FlacocoConfig;
+import org.apache.log4j.Logger;
+import spoon.Launcher;
+import spoon.reflect.code.CtStatement;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Inspects the analyzed project to find the locations corresponding to the lines
+ * executed before the line corresponding to the given stack-trace element.
+ */
+public class SpoonBlockInspector {
+
+ private static final Logger logger = Logger.getLogger(SpoonBlockInspector.class);
+
+ private FlacocoConfig config;
+
+ public SpoonBlockInspector(FlacocoConfig config) {
+ this.config = config;
+ }
+
+ public List getBlockLocations(StackTraceElement element) {
+ // Find the corresponding source code file
+ String path = element.getClassName().replace(".", "/") + ".java";
+ for (String dir : config.getSrcJavaDir()) {
+ if (new File(new File(dir), path).exists()) {
+ path = new File(new File(dir), path).getAbsolutePath();
+ break;
+ }
+ }
+
+ // If we cannot find the source code file, we return an empty location list
+ if (!new File(path).exists()) {
+ logger.debug("No source code file was found for stack-trace element: " + element);
+ return new ArrayList<>();
+ }
+
+
+ // Init spoon Launcher
+ Launcher launcher = new Launcher();
+ launcher.addInputResource(path);
+ launcher.buildModel();
+ launcher.addProcessor(new SpoonBlockLocationsFinder());
+
+ // Process the source code to find the block of the given stack-trace element
+ SpoonBlockLocationsFinder.fullyQualifiedClassName = element.getClassName();
+ SpoonBlockLocationsFinder.lineNumber = element.getLineNumber();
+ SpoonBlockLocationsFinder.found = null;
+ launcher.process();
+
+ if (SpoonBlockLocationsFinder.found == null) {
+ logger.debug("No block was found for stack-trace element: " + element);
+ return new ArrayList<>();
+ }
+
+ // Process the block
+ List locations = new ArrayList<>();
+ for (CtStatement ctStatement : SpoonBlockLocationsFinder.found.getStatements()) {
+ if (ctStatement.getPosition().getLine() <= element.getLineNumber()) {
+ locations.add(new Location(element.getClassName(), ctStatement.getPosition().getLine()));
+ }
+ }
+
+ // Clean results
+ SpoonBlockLocationsFinder.found = null;
+
+ return locations;
+ }
+
+}
\ No newline at end of file
diff --git a/src/main/java/fr/spoonlabs/flacoco/utils/spoon/SpoonBlockLocationsFinder.java b/src/main/java/fr/spoonlabs/flacoco/utils/spoon/SpoonBlockLocationsFinder.java
new file mode 100644
index 00000000..a83b0ab0
--- /dev/null
+++ b/src/main/java/fr/spoonlabs/flacoco/utils/spoon/SpoonBlockLocationsFinder.java
@@ -0,0 +1,68 @@
+package fr.spoonlabs.flacoco.utils.spoon;
+
+import org.apache.log4j.Logger;
+import spoon.processing.AbstractProcessor;
+import spoon.reflect.code.CtBlock;
+import spoon.reflect.cu.SourcePosition;
+import spoon.reflect.declaration.CtType;
+
+import java.util.List;
+
+/**
+ * Processes CtTypes to find the CtType corresponding to the given class name.
+ * Then, it finds the CtBlock that corresponds to the deepest scope that includes the given line number.
+ */
+public class SpoonBlockLocationsFinder extends AbstractProcessor> {
+
+ private static final Logger logger = Logger.getLogger(SpoonBlockLocationsFinder.class);
+
+ public static String fullyQualifiedClassName;
+ public static int lineNumber;
+
+ public static CtBlock> found;
+
+ @Override
+ public boolean isToBeProcessed(CtType> candidate) {
+ return candidate.getQualifiedName().equals(fullyQualifiedClassName);
+ }
+
+ @Override
+ public void process(CtType> ctType) {
+ List> result = ctType.filterChildren(new SpoonBlockFilter(lineNumber)).list();
+
+ CtBlock> bestFit = null;
+ SourcePosition curPos = null;
+ for (CtBlock> ctBlock : result) {
+ SourcePosition pos = ctBlock.getPosition();
+ if (bestFit == null || curPos == null) {
+ bestFit = ctBlock;
+ curPos = pos;
+ } else {
+ int curStart = curPos.getLine();
+ int start = pos.getLine();
+ int curEnd = curPos.getEndLine();
+ int end = pos.getEndLine();
+ if (curStart < start) {
+ // In this case, we always want the block that begins closest to the identified line
+ bestFit = ctBlock;
+ curPos = pos;
+ } else if (curStart == lineNumber && curEnd == lineNumber &&
+ start == lineNumber && end == lineNumber) {
+ // They are both in the same line, keep the top-most
+ if (curPos.getSourceStart() >= pos.getSourceStart() &&
+ pos.getSourceEnd() >= curPos.getSourceEnd() &&
+ curPos.getSourceStart() + curPos.getSourceEnd() != pos.getSourceStart() + pos.getSourceEnd()) {
+ bestFit = ctBlock;
+ curPos = pos;
+ }
+ } else if (end < curEnd) {
+ // New one is tighter
+ bestFit = ctBlock;
+ curPos = pos;
+ }
+ }
+ }
+
+ found = bestFit;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/fr/spoonlabs/flacoco/utils/spoon/SpoonConverter.java b/src/main/java/fr/spoonlabs/flacoco/utils/spoon/SpoonConverter.java
index f70da997..f821aa37 100644
--- a/src/main/java/fr/spoonlabs/flacoco/utils/spoon/SpoonConverter.java
+++ b/src/main/java/fr/spoonlabs/flacoco/utils/spoon/SpoonConverter.java
@@ -47,6 +47,7 @@ public FlacocoResult convertResult(FlacocoResult flacocoResult) {
// Compute location information
SpoonLocalizedFaultFinder.fullyQualifiedClassName = location.getClassName();
SpoonLocalizedFaultFinder.lineNumber = location.getLineNumber();
+ SpoonLocalizedFaultFinder.found = null;
// Launch processor to find the top-most CtStatement of the given line
launcher.process();
diff --git a/src/test/java/fr/spoonlabs/flacoco/api/FlacocoTest.java b/src/test/java/fr/spoonlabs/flacoco/api/FlacocoTest.java
index 6d22f5a9..9ab85f66 100644
--- a/src/test/java/fr/spoonlabs/flacoco/api/FlacocoTest.java
+++ b/src/test/java/fr/spoonlabs/flacoco/api/FlacocoTest.java
@@ -20,8 +20,7 @@
import java.util.stream.Collectors;
import java.util.stream.Stream;
-import static fr.spoonlabs.flacoco.TestUtils.getCompilerVersion;
-import static fr.spoonlabs.flacoco.TestUtils.isLessThanJava11;
+import static fr.spoonlabs.flacoco.TestUtils.*;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
@@ -1303,6 +1302,41 @@ public void testExampleFL12SpectrumBasedOchiaiDefaultMode() {
assertOrdered(susp, locations);
}
+ /**
+ * This test captures the functionality of computing the coverage even when an exception is
+ * thrown during execution and there are lines ignored by JaCoCo before the line throwing exception
+ *
+ * See:
+ * - https://github.com/jacoco/jacoco/issues/1223#issuecomment-926636606
+ * - https://github.com/SpoonLabs/flacoco/issues/109
+ */
+ @Test
+ public void testExampleCL2SpectrumBasedOchiaiDefaultMode() {
+ // Run only on java 8
+ Assume.assumeTrue(getCompilerVersion() >= 5);
+ Assume.assumeTrue(getJavaVersion() == 8);
+
+ // Setup config
+ FlacocoConfig config = getDefaultFlacocoConfig();
+ LogManager.getRootLogger().setLevel(Level.INFO);
+ config.setTestRunnerVerbose(false);
+ config.setProjectPath(new File("./examples/cl2").getAbsolutePath());
+ config.setSrcJavaDir(Collections.singletonList(new File("./examples/cl2/src/java").getAbsolutePath()));
+
+ // Run Flacoco
+ Flacoco flacoco = new Flacoco(config);
+
+ // Run default mode
+ FlacocoResult result = flacoco.run();
+
+ Map susp = result.getDefaultSuspiciousnessMap();
+
+ // Lines not included by JaCoCo
+ assertTrue(result.getDefaultSuspiciousnessMap().containsKey(new Location("org.apache.commons.lang.StringUtils", 1050)));
+ assertTrue(result.getDefaultSuspiciousnessMap().containsKey(new Location("org.apache.commons.lang.StringUtils", 1051)));
+ assertTrue(result.getDefaultSuspiciousnessMap().containsKey(new Location("org.apache.commons.lang.StringUtils", 1054)));
+ }
+
private FlacocoConfig getDefaultFlacocoConfig() {
FlacocoConfig config = new FlacocoConfig();
config.setWorkspace(workspaceDir.getRoot().getAbsolutePath());