You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by tr...@apache.org on 2006/01/20 14:48:55 UTC

svn commit: r370807 [13/22] - in /directory/sandbox/trustin/mina-spi: ./ core/src/main/java/org/apache/mina/common/ core/src/main/java/org/apache/mina/common/support/ core/src/main/java/org/apache/mina/common/support/discovery/ core/src/main/java/org/a...

Added: directory/sandbox/trustin/mina-spi/core/src/main/java/org/apache/mina/common/support/lang/builder/HashCodeBuilder.java
URL: http://svn.apache.org/viewcvs/directory/sandbox/trustin/mina-spi/core/src/main/java/org/apache/mina/common/support/lang/builder/HashCodeBuilder.java?rev=370807&view=auto
==============================================================================
--- directory/sandbox/trustin/mina-spi/core/src/main/java/org/apache/mina/common/support/lang/builder/HashCodeBuilder.java (added)
+++ directory/sandbox/trustin/mina-spi/core/src/main/java/org/apache/mina/common/support/lang/builder/HashCodeBuilder.java Fri Jan 20 05:47:50 2006
@@ -0,0 +1,630 @@
+/*
+ * Copyright 2002-2005 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.mina.common.support.lang.builder;
+
+import java.lang.reflect.AccessibleObject;
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+
+/**
+ * <p>Assists in implementing {@link Object#hashCode()} methods.</p>
+ *
+ * <p> This class enables a good <code>hashCode</code> method to be built for any class. It
+ * follows the rules laid out in the book
+ * <a href="http://java.sun.com/docs/books/effective/index.html">Effective Java</a>
+ * by Joshua Bloch. Writing a good <code>hashCode</code> method is actually quite
+ * difficult. This class aims to simplify the process.</p>
+ *
+ * <p>All relevant fields from the object should be included in the
+ * <code>hashCode</code> method. Derived fields may be excluded. In general, any
+ * field used in the <code>equals</code> method must be used in the <code>hashCode</code>
+ * method.</p>
+ *
+ * <p>To use this class write code as follows:</p>
+ * <pre>
+ * 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();
+ *   }
+ * }
+ * </pre>
+ *
+ * <p>If required, the superclass <code>hashCode()</code> can be added
+ * using {@link #appendSuper}.</p>
+ *
+ * <p>Alternatively, there is a method that uses reflection to determine
+ * the fields to test. Because these fields are usually private, the method,
+ * <code>reflectionHashCode</code>, uses <code>AccessibleObject.setAccessible</code> 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.</p>
+ *
+ * <p>A typical invocation for this method would look like:</p>
+ * <pre>
+ * public int hashCode() {
+ *   return HashCodeBuilder.reflectionHashCode(this);
+ * }
+ * </pre>
+ *
+ * @author Stephen Colebourne
+ * @author Gary Gregory
+ * @author Pete Gieser
+ * @since 1.0
+ * @version $Id$
+ */
+public class HashCodeBuilder {
+
+    /**
+     * Constant to use in building the hashCode.
+     */
+    private final int iConstant;
+    /**
+     * Running total of the hashCode.
+     */
+    private int iTotal = 0;
+
+    /**
+     * <p>Uses two hard coded choices for the constants
+     * needed to build a <code>hashCode</code>.</p>
+     */
+    public HashCodeBuilder() {
+        iConstant = 37;
+        iTotal = 17;
+    }
+
+    /**
+     * <p>Two randomly chosen, non-zero, odd numbers must be passed in.
+     * Ideally these should be different for each class, however this is
+     * not vital.</p>
+     *
+     * <p>Prime numbers are preferred, especially for the multiplier.</p>
+     *
+     * @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) {
+        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;
+    }
+
+    //-------------------------------------------------------------------------
+
+    /**
+     * <p>This method uses reflection to build a valid hash code.</p>
+     *
+     * <p>This constructor uses two hard coded choices for the constants
+     * needed to build a hash code.</p>
+     *
+     * <p>It uses <code>AccessibleObject.setAccessible</code> to gain access to private
+     * fields. This means that it will throw a security exception if run under
+     * a security manager, if the permissions are not set up correctly. It is
+     * also not as efficient as testing explicitly.</p>
+     *
+     * <p>Transient members will be not be used, as they are likely derived
+     * fields, and not part of the value of the <code>Object</code>.</p>
+     *
+     * <p>Static fields will not be tested. Superclass fields will be included.</p>
+     *
+     * @param object  the Object to create a <code>hashCode</code> for
+     * @return int hash code
+     * @throws IllegalArgumentException if the object is <code>null</code>
+     */
+    public static int reflectionHashCode(Object object) {
+        return reflectionHashCode(17, 37, object, false, null);
+    }
+
+    /**
+     * <p>This method uses reflection to build a valid hash code.</p>
+     *
+     * <p>This constructor uses two hard coded choices for the constants needed
+     * to build a hash code.</p>
+     *
+     * <p> It uses <code>AccessibleObject.setAccessible</code> to gain access to private
+     * fields. This means that it will throw a security exception if run under
+     * a security manager, if the permissions are not set up correctly. It is
+     * also not as efficient as testing explicitly.</p>
+     *
+     * <P>If the TestTransients parameter is set to <code>true</code>, transient
+     * members will be tested, otherwise they are ignored, as they are likely
+     * derived fields, and not part of the value of the <code>Object</code>.</p>
+     *
+     * <p>Static fields will not be tested. Superclass fields will be included.</p>
+     *
+     * @param object  the Object to create a <code>hashCode</code> for
+     * @param testTransients  whether to include transient fields
+     * @return int hash code
+     * @throws IllegalArgumentException if the object is <code>null</code>
+     */
+    public static int reflectionHashCode(Object object, boolean testTransients) {
+        return reflectionHashCode(17, 37, object, testTransients, null);
+    }
+
+    /**
+     * <p>This method uses reflection to build a valid hash code.</p>
+     *
+     * <p>It uses <code>AccessibleObject.setAccessible</code> to gain access to private
+     * fields. This means that it will throw a security exception if run under
+     * a security manager, if the permissions are not set up correctly. It is
+     * also not as efficient as testing explicitly.</p>
+     *
+     * <p>Transient members will be not be used, as they are likely derived
+     * fields, and not part of the value of the <code>Object</code>.</p>
+     *
+     * <p>Static fields will not be tested. Superclass fields will be included.</p>
+     *
+     * <p>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.</p>
+     *
+     * @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 <code>hashCode</code> for
+     * @return int hash code
+     * @throws IllegalArgumentException if the Object is <code>null</code>
+     * @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);
+    }
+
+    /**
+     * <p>This method uses reflection to build a valid hash code.</p>
+     *
+     * <p>It uses <code>AccessibleObject.setAccessible</code> to gain access to private
+     * fields. This means that it will throw a security exception if run under
+     * a security manager, if the permissions are not set up correctly. It is also
+     * not as efficient as testing explicitly.</p>
+     *
+     * <p>If the TestTransients parameter is set to <code>true</code>, transient
+     * members will be tested, otherwise they are ignored, as they are likely
+     * derived fields, and not part of the value of the <code>Object</code>.</p>
+     *
+     * <p>Static fields will not be tested. Superclass fields will be included.</p>
+     *
+     * <p>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.</p>
+     *
+     * @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 <code>hashCode</code> for
+     * @param testTransients  whether to include transient fields
+     * @return int hash code
+     * @throws IllegalArgumentException if the Object is <code>null</code>
+     * @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);
+    }
+            
+    /**
+     * <p>This method uses reflection to build a valid hash code.</p>
+     *
+     * <p>It uses <code>AccessibleObject.setAccessible</code> to gain access to private
+     * fields. This means that it will throw a security exception if run under
+     * a security manager, if the permissions are not set up correctly. It is also
+     * not as efficient as testing explicitly.</p>
+     *
+     * <p>If the TestTransients parameter is set to <code>true</code>, transient
+     * members will be tested, otherwise they are ignored, as they are likely
+     * derived fields, and not part of the value of the <code>Object</code>.</p>
+     *
+     * <p>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.</p>
+     *
+     * <p>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.</p>
+     *
+     * @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 <code>hashCode</code> for
+     * @param testTransients  whether to include transient fields
+     * @param reflectUpToClass  the superclass to reflect up to (inclusive),
+     *  may be <code>null</code>
+     * @return int hash code
+     * @throws IllegalArgumentException if the Object is <code>null</code>
+     * @throws IllegalArgumentException if the number is zero or even
+     * @since 2.0
+     */
+    public static int reflectionHashCode(
+        int initialNonZeroOddNumber,
+        int multiplierNonZeroOddNumber,
+        Object object,
+        boolean testTransients,
+        Class reflectUpToClass) {
+
+        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();
+    }
+
+    /**
+     * <p>Appends the fields and values defined by the given object of the
+     * given <code>Class</code>.</p>
+     * 
+     * @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();
+        AccessibleObject.setAccessible(fields, true);
+        for (int i = 0; i < fields.length; i++) {
+            Field f = fields[i];
+            if ((f.getName().indexOf('$') == -1)
+                && (useTransients || !Modifier.isTransient(f.getModifiers()))
+                && (!Modifier.isStatic(f.getModifiers()))) {
+                try {
+                    builder.append(f.get(object));
+                } catch (IllegalAccessException e) {
+                    //this can't happen. Would get a Security exception instead
+                    //throw a runtime exception in case the impossible happens.
+                    throw new InternalError("Unexpected IllegalAccessException");
+                }
+            }
+        }
+    }
+
+    //-------------------------------------------------------------------------
+
+    /**
+     * <p>Adds the result of super.hashCode() to this builder.</p>
+     *
+     * @param superHashCode  the result of calling <code>super.hashCode()</code>
+     * @return this HashCodeBuilder, used to chain calls.
+     * @since 2.0
+     */
+    public HashCodeBuilder appendSuper(int superHashCode) {
+        iTotal = iTotal * iConstant + superHashCode;
+        return this;
+    }
+
+    //-------------------------------------------------------------------------
+
+    /**
+     * <p>Append a <code>hashCode</code> for an <code>Object</code>.</p>
+     *
+     * @param object  the Object to add to the <code>hashCode</code>
+     * @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;
+    }
+
+    /**
+     * <p>Append a <code>hashCode</code> for a <code>long</code>.</p>
+     *
+     * @param value  the long to add to the <code>hashCode</code>
+     * @return this
+     */
+    public HashCodeBuilder append(long value) {
+        iTotal = iTotal * iConstant + ((int) (value ^ (value >> 32)));
+        return this;
+    }
+
+    /**
+     * <p>Append a <code>hashCode</code> for an <code>int</code>.</p>
+     *
+     * @param value  the int to add to the <code>hashCode</code>
+     * @return this
+     */
+    public HashCodeBuilder append(int value) {
+        iTotal = iTotal * iConstant + value;
+        return this;
+    }
+
+    /**
+     * <p>Append a <code>hashCode</code> for a <code>short</code>.</p>
+     *
+     * @param value  the short to add to the <code>hashCode</code>
+     * @return this
+     */
+    public HashCodeBuilder append(short value) {
+        iTotal = iTotal * iConstant + value;
+        return this;
+    }
+
+    /**
+     * <p>Append a <code>hashCode</code> for a <code>char</code>.</p>
+     *
+     * @param value  the char to add to the <code>hashCode</code>
+     * @return this
+     */
+    public HashCodeBuilder append(char value) {
+        iTotal = iTotal * iConstant + value;
+        return this;
+    }
+
+    /**
+     * <p>Append a <code>hashCode</code> for a <code>byte</code>.</p>
+     *
+     * @param value  the byte to add to the <code>hashCode</code>
+     * @return this
+     */
+    public HashCodeBuilder append(byte value) {
+        iTotal = iTotal * iConstant + value;
+        return this;
+    }
+
+    /**
+     * <p>Append a <code>hashCode</code> for a <code>double</code>.</p>
+     *
+     * @param value  the double to add to the <code>hashCode</code>
+     * @return this
+     */
+    public HashCodeBuilder append(double value) {
+        return append(Double.doubleToLongBits(value));
+    }
+
+    /**
+     * <p>Append a <code>hashCode</code> for a <code>float</code>.</p>
+     *
+     * @param value  the float to add to the <code>hashCode</code>
+     * @return this
+     */
+    public HashCodeBuilder append(float value) {
+        iTotal = iTotal * iConstant + Float.floatToIntBits(value);
+        return this;
+    }
+
+    /**
+     * <p>Append a <code>hashCode</code> for a <code>boolean</code>.</p>
+     * <p>This adds <code>iConstant * 1</code> to the <code>hashCode</code>
+     * and not a <code>1231</code> or <code>1237</code> as done in java.lang.Boolean. 
+     * This is in accordance with the <quote>Effective Java</quote> design. </p>
+     *
+     * @param value  the boolean to add to the <code>hashCode</code>
+     * @return this
+     */
+    public HashCodeBuilder append(boolean value) {
+        iTotal = iTotal * iConstant + (value ? 0 : 1);
+        return this;
+    }
+
+    /**
+     * <p>Append a <code>hashCode</code> for an <code>Object</code> array.</p>
+     *
+     * @param array  the array to add to the <code>hashCode</code>
+     * @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;
+    }
+
+    /**
+     * <p>Append a <code>hashCode</code> for a <code>long</code> array.</p>
+     *
+     * @param array  the array to add to the <code>hashCode</code>
+     * @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;
+    }
+
+    /**
+     * <p>Append a <code>hashCode</code> for an <code>int</code> array.</p>
+     *
+     * @param array  the array to add to the <code>hashCode</code>
+     * @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;
+    }
+
+    /**
+     * <p>Append a <code>hashCode</code> for a <code>short</code> array.</p>
+     *
+     * @param array  the array to add to the <code>hashCode</code>
+     * @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;
+    }
+
+    /**
+     * <p>Append a <code>hashCode</code> for a <code>char</code> array.</p>
+     *
+     * @param array  the array to add to the <code>hashCode</code>
+     * @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;
+    }
+
+    /**
+     * <p>Append a <code>hashCode</code> for a <code>byte</code> array.</p>
+     *
+     * @param array  the array to add to the <code>hashCode</code>
+     * @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;
+    }
+
+    /**
+     * <p>Append a <code>hashCode</code> for a <code>double</code> array.</p>
+     *
+     * @param array  the array to add to the <code>hashCode</code>
+     * @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;
+    }
+
+    /**
+     * <p>Append a <code>hashCode</code> for a <code>float</code> array.</p>
+     *
+     * @param array  the array to add to the <code>hashCode</code>
+     * @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;
+    }
+
+    /**
+     * <p>Append a <code>hashCode</code> for a <code>boolean</code> array.</p>
+     *
+     * @param array  the array to add to the <code>hashCode</code>
+     * @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;
+    }
+
+    /**
+     * <p>Return the computed <code>hashCode</code>.</p>
+     *
+     * @return <code>hashCode</code> based on the fields appended
+     */
+    public int toHashCode() {
+        return iTotal;
+    }
+
+}

Propchange: directory/sandbox/trustin/mina-spi/core/src/main/java/org/apache/mina/common/support/lang/builder/HashCodeBuilder.java
------------------------------------------------------------------------------
    svn:keywords = HeadURL Id LastChangedBy LastChangedDate LastChangedRevision

Added: directory/sandbox/trustin/mina-spi/core/src/main/java/org/apache/mina/common/support/lang/builder/ReflectionToStringBuilder.java
URL: http://svn.apache.org/viewcvs/directory/sandbox/trustin/mina-spi/core/src/main/java/org/apache/mina/common/support/lang/builder/ReflectionToStringBuilder.java?rev=370807&view=auto
==============================================================================
--- directory/sandbox/trustin/mina-spi/core/src/main/java/org/apache/mina/common/support/lang/builder/ReflectionToStringBuilder.java (added)
+++ directory/sandbox/trustin/mina-spi/core/src/main/java/org/apache/mina/common/support/lang/builder/ReflectionToStringBuilder.java Fri Jan 20 05:47:50 2006
@@ -0,0 +1,806 @@
+/*
+ * Copyright 2002-2005 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.mina.common.support.lang.builder;
+
+import java.lang.reflect.AccessibleObject;
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.apache.mina.common.support.lang.ClassUtils;
+
+/**
+ * <p>
+ * Assists in implementing {@link Object#toString()} methods using reflection.
+ * </p>
+ * 
+ * <p>
+ * This class uses reflection to determine the fields to append. Because these
+ * fields are usually private, the class uses
+ * {@link java.lang.reflect.AccessibleObject#setAccessible(java.lang.reflect.AccessibleObject[], boolean)}
+ * to change the visibility of the fields. This will fail under a security
+ * manager, unless the appropriate permissions are set up correctly.
+ * </p>
+ * 
+ * <p>
+ * A typical invocation for this method would look like:
+ * </p>
+ * 
+ * <pre>
+ * public String toString() {
+ *   return ReflectionToStringBuilder.toString(this);
+ * }</pre>
+ * 
+ * 
+ * 
+ * <p>
+ * You can also use the builder to debug 3rd party objects:
+ * </p>
+ * 
+ * <pre>
+ * System.out.println("An object: " + ReflectionToStringBuilder.toString(anObject));</pre>
+ * 
+ * 
+ * 
+ * <p>
+ * A subclass can control field output by overriding the methods:
+ * <ul>
+ * <li>{@link #accept(java.lang.reflect.Field)}</li>
+ * <li>{@link #getValue(java.lang.reflect.Field)}</li>
+ * </ul>
+ * </p>
+ * <p>
+ * For example, this method does <i>not</i> include the <code>password</code>
+ * field in the returned <code>String</code>:
+ * </p>
+ * 
+ * <pre>
+ * public String toString() {
+ *     return (new ReflectionToStringBuilder(this) {
+ *         protected boolean accept(Field f) {
+ *             return super.accept(f) && !f.getName().equals("password");
+ *         }
+ *     }).toString();
+ * }</pre>
+ * 
+ * 
+ * 
+ * <p>
+ * The exact format of the <code>toString</code> is determined by the
+ * {@link ToStringStyle} passed into the constructor.
+ * </p>
+ * 
+ * @author Gary Gregory
+ * @author Stephen Colebourne
+ * @author Pete Gieser
+ * @since 2.0
+ * @version $Id: ReflectionToStringBuilder.java,v 1.15 2003/12/02 19:11:58
+ *               ggregory Exp $
+ */
+public class ReflectionToStringBuilder extends ToStringBuilder {
+    /**
+     * <p>
+     * A registry of objects used by <code>reflectionToString</code> methods
+     * to detect cyclical object references and avoid infinite loops.
+     * </p>
+     */
+    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();
+        }
+    };
+
+    /**
+     * <p>
+     * Returns the registry of objects being traversed by the <code>reflectionToString</code>
+     * methods in the current thread.
+     * </p>
+     * 
+     * @return Set the registry of objects being traversed
+     */
+    static Set getRegistry() {
+        return (Set) registry.get();
+    }
+
+    /**
+     * <p>
+     * Returns <code>true</code> if the registry contains the given object.
+     * Used by the reflection methods to avoid infinite loops.
+     * </p>
+     * 
+     * @param value
+     *                  The object to lookup in the registry.
+     * @return boolean <code>true</code> if the registry contains the given
+     *             object.
+     */
+    static boolean isRegistered(Object value) {
+        return getRegistry().contains(value);
+    }
+
+    /**
+     * <p>
+     * Registers the given object. Used by the reflection methods to avoid
+     * infinite loops.
+     * </p>
+     * 
+     * @param value
+     *                  The object to register.
+     */
+    static void register(Object value) {
+        getRegistry().add(value);
+    }
+
+    /**
+     * <p>
+     * This method uses reflection to build a suitable <code>toString</code>
+     * using the default <code>ToStringStyle</code>.
+     * 
+     * <p>
+     * It uses <code>AccessibleObject.setAccessible</code> to gain access to
+     * private fields. This means that it will throw a security exception if
+     * run under a security manager, if the permissions are not set up
+     * correctly. It is also not as efficient as testing explicitly.
+     * </p>
+     * 
+     * <p>
+     * Transient members will be not be included, as they are likely derived.
+     * Static fields will not be included. Superclass fields will be appended.
+     * </p>
+     * 
+     * @param object
+     *                  the Object to be output
+     * @return the String result
+     * @throws IllegalArgumentException
+     *                  if the Object is <code>null</code>
+     */
+    public static String toString(Object object) {
+        return toString(object, null, false, false, null);
+    }
+
+    /**
+     * <p>
+     * This method uses reflection to build a suitable <code>toString</code>.
+     * </p>
+     * 
+     * <p>
+     * It uses <code>AccessibleObject.setAccessible</code> to gain access to
+     * private fields. This means that it will throw a security exception if
+     * run under a security manager, if the permissions are not set up
+     * correctly. It is also not as efficient as testing explicitly.
+     * </p>
+     * 
+     * <p>
+     * Transient members will be not be included, as they are likely derived.
+     * Static fields will not be included. Superclass fields will be appended.
+     * </p>
+     * 
+     * <p>
+     * If the style is <code>null</code>, the default <code>ToStringStyle</code>
+     * is used.
+     * </p>
+     * 
+     * @param object
+     *                  the Object to be output
+     * @param style
+     *                  the style of the <code>toString</code> to create, may be
+     *                  <code>null</code>
+     * @return the String result
+     * @throws IllegalArgumentException
+     *                  if the Object or <code>ToStringStyle</code> is <code>null</code>
+     */
+    public static String toString(Object object, ToStringStyle style) {
+        return toString(object, style, false, false, null);
+    }
+
+    /**
+     * <p>
+     * This method uses reflection to build a suitable <code>toString</code>.
+     * </p>
+     * 
+     * <p>
+     * It uses <code>AccessibleObject.setAccessible</code> to gain access to
+     * private fields. This means that it will throw a security exception if
+     * run under a security manager, if the permissions are not set up
+     * correctly. It is also not as efficient as testing explicitly.
+     * </p>
+     * 
+     * <p>
+     * If the <code>outputTransients</code> is <code>true</code>,
+     * transient members will be output, otherwise they are ignored, as they
+     * are likely derived fields, and not part of the value of the Object.
+     * </p>
+     * 
+     * <p>
+     * Static fields will not be included. Superclass fields will be appended.
+     * </p>
+     * 
+     * <p>
+     * If the style is <code>null</code>, the default <code>ToStringStyle</code>
+     * is used.
+     * </p>
+     * 
+     * @param object
+     *                  the Object to be output
+     * @param style
+     *                  the style of the <code>toString</code> to create, may be
+     *                  <code>null</code>
+     * @param outputTransients
+     *                  whether to include transient fields
+     * @return the String result
+     * @throws IllegalArgumentException
+     *                  if the Object is <code>null</code>
+     */
+    public static String toString(Object object, ToStringStyle style, boolean outputTransients) {
+        return toString(object, style, outputTransients, false, null);
+    }
+
+    /**
+     * <p>
+     * This method uses reflection to build a suitable <code>toString</code>.
+     * </p>
+     * 
+     * <p>
+     * It uses <code>AccessibleObject.setAccessible</code> to gain access to
+     * private fields. This means that it will throw a security exception if
+     * run under a security manager, if the permissions are not set up
+     * correctly. It is also not as efficient as testing explicitly.
+     * </p>
+     * 
+     * <p>
+     * If the <code>outputTransients</code> is <code>true</code>,
+     * transient fields will be output, otherwise they are ignored, as they are
+     * likely derived fields, and not part of the value of the Object.
+     * </p>
+     * 
+     * <p>
+     * If the <code>outputStatics</code> is <code>true</code>, static
+     * fields will be output, otherwise they are ignored.
+     * </p>
+     * 
+     * <p>
+     * Static fields will not be included. Superclass fields will be appended.
+     * </p>
+     * 
+     * <p>
+     * If the style is <code>null</code>, the default <code>ToStringStyle</code>
+     * is used.
+     * </p>
+     * 
+     * @param object
+     *                  the Object to be output
+     * @param style
+     *                  the style of the <code>toString</code> to create, may be
+     *                  <code>null</code>
+     * @param outputTransients
+     *                  whether to include transient fields
+     * @param outputStatics
+     *                  whether to include transient fields
+     * @return the String result
+     * @throws IllegalArgumentException
+     *                  if the Object is <code>null</code>
+     * @since 2.1
+     */
+    public static String toString(Object object, ToStringStyle style, boolean outputTransients, boolean outputStatics) {
+        return toString(object, style, outputTransients, outputStatics, null);
+    }
+
+    /**
+     * <p>
+     * This method uses reflection to build a suitable <code>toString</code>.
+     * </p>
+     * 
+     * <p>
+     * It uses <code>AccessibleObject.setAccessible</code> to gain access to
+     * private fields. This means that it will throw a security exception if
+     * run under a security manager, if the permissions are not set up
+     * correctly. It is also not as efficient as testing explicitly.
+     * </p>
+     * 
+     * <p>
+     * If the <code>outputTransients</code> is <code>true</code>,
+     * transient fields will be output, otherwise they are ignored, as they are
+     * likely derived fields, and not part of the value of the Object.
+     * </p>
+     * 
+     * <p>
+     * If the <code>outputStatics</code> is <code>true</code>, static
+     * fields will be output, otherwise they are ignored.
+     * </p>
+     * 
+     * <p>
+     * Superclass fields will be appended up to and including the specified
+     * superclass. A null superclass is treated as <code>java.lang.Object</code>.
+     * </p>
+     * 
+     * <p>
+     * If the style is <code>null</code>, the default <code>ToStringStyle</code>
+     * is used.
+     * </p>
+     * 
+     * @param object
+     *                  the Object to be output
+     * @param style
+     *                  the style of the <code>toString</code> to create, may be
+     *                  <code>null</code>
+     * @param outputTransients
+     *                  whether to include transient fields
+     * @param outputStatics
+     *                  whether to include static fields
+     * @param reflectUpToClass
+     *                  the superclass to reflect up to (inclusive), may be <code>null</code>
+     * @return the String result
+     * @throws IllegalArgumentException
+     *                  if the Object is <code>null</code>
+     * @since 2.1
+     */
+    public static String toString(Object object, ToStringStyle style, boolean outputTransients, boolean outputStatics,
+            Class reflectUpToClass) {
+        return new ReflectionToStringBuilder(object, style, null, reflectUpToClass, outputTransients, outputStatics)
+                .toString();
+    }
+
+    /**
+     * <p>
+     * This method uses reflection to build a suitable <code>toString</code>.
+     * </p>
+     * 
+     * <p>
+     * It uses <code>AccessibleObject.setAccessible</code> to gain access to
+     * private fields. This means that it will throw a security exception if
+     * run under a security manager, if the permissions are not set up
+     * correctly. It is also not as efficient as testing explicitly.
+     * </p>
+     * 
+     * <p>
+     * If the <code>outputTransients</code> is <code>true</code>,
+     * transient members will be output, otherwise they are ignored, as they
+     * are likely derived fields, and not part of the value of the Object.
+     * </p>
+     * 
+     * <p>
+     * Static fields will not be included. Superclass fields will be appended
+     * up to and including the specified superclass. A null superclass is
+     * treated as <code>java.lang.Object</code>.
+     * </p>
+     * 
+     * <p>
+     * If the style is <code>null</code>, the default <code>ToStringStyle</code>
+     * is used.
+     * </p>
+     * 
+     * @deprecated Use
+     *                     {@link #toString(Object,ToStringStyle,boolean,boolean,Class)}
+     * 
+     * @param object
+     *                  the Object to be output
+     * @param style
+     *                  the style of the <code>toString</code> to create, may be
+     *                  <code>null</code>
+     * @param outputTransients
+     *                  whether to include transient fields
+     * @param reflectUpToClass
+     *                  the superclass to reflect up to (inclusive), may be <code>null</code>
+     * @return the String result
+     * @throws IllegalArgumentException
+     *                  if the Object is <code>null</code>
+     * @since 2.0
+     */
+    public static String toString(Object object, ToStringStyle style, boolean outputTransients, 
+            Class reflectUpToClass) {
+        return new ReflectionToStringBuilder(object, style, null, reflectUpToClass, outputTransients).toString();
+    }
+
+    /**
+     * <p>
+     * Unregisters the given object.
+     * </p>
+     * 
+     * <p>
+     * Used by the reflection methods to avoid infinite loops.
+     * </p>
+     * 
+     * @param value
+     *                  The object to unregister.
+     */
+    static void unregister(Object value) {
+        getRegistry().remove(value);
+    }
+
+    /**
+     * Whether or not to append static fields.
+     */
+    private boolean appendStatics = false;
+
+    /**
+     * Whether or not to append transient fields.
+     */
+    private boolean appendTransients = false;
+
+    /**
+     * The last super class to stop appending fields for.
+     */
+    private Class upToClass = null;
+
+    /**
+     * <p>
+     * Constructor.
+     * </p>
+     * 
+     * <p>
+     * This constructor outputs using the default style set with <code>setDefaultStyle</code>.
+     * </p>
+     * 
+     * @param object
+     *                  the Object to build a <code>toString</code> for, must not
+     *                  be <code>null</code>
+     * @throws IllegalArgumentException
+     *                  if the Object passed in is <code>null</code>
+     */
+    public ReflectionToStringBuilder(Object object) {
+        super(object);
+    }
+
+    /**
+     * <p>
+     * Constructor.
+     * </p>
+     * 
+     * <p>
+     * If the style is <code>null</code>, the default style is used.
+     * </p>
+     * 
+     * @param object
+     *                  the Object to build a <code>toString</code> for, must not
+     *                  be <code>null</code>
+     * @param style
+     *                  the style of the <code>toString</code> to create, may be
+     *                  <code>null</code>
+     * @throws IllegalArgumentException
+     *                  if the Object passed in is <code>null</code>
+     */
+    public ReflectionToStringBuilder(Object object, ToStringStyle style) {
+        super(object, style);
+    }
+
+    /**
+     * <p>
+     * Constructor.
+     * </p>
+     * 
+     * <p>
+     * If the style is <code>null</code>, the default style is used.
+     * </p>
+     * 
+     * <p>
+     * If the buffer is <code>null</code>, a new one is created.
+     * </p>
+     * 
+     * @param object
+     *                  the Object to build a <code>toString</code> for
+     * @param style
+     *                  the style of the <code>toString</code> to create, may be
+     *                  <code>null</code>
+     * @param buffer
+     *                  the <code>StringBuffer</code> to populate, may be <code>null</code>
+     * @throws IllegalArgumentException
+     *                  if the Object passed in is <code>null</code>
+     */
+    public ReflectionToStringBuilder(Object object, ToStringStyle style, StringBuffer buffer) {
+        super(object, style, buffer);
+    }
+
+    /**
+     * Constructor.
+     * 
+     * @deprecated Use
+     *                     {@link #ReflectionToStringBuilder(Object,ToStringStyle,StringBuffer,Class,boolean,boolean)}.
+     * 
+     * @param object
+     *                  the Object to build a <code>toString</code> for
+     * @param style
+     *                  the style of the <code>toString</code> to create, may be
+     *                  <code>null</code>
+     * @param buffer
+     *                  the <code>StringBuffer</code> to populate, may be <code>null</code>
+     * @param reflectUpToClass
+     *                  the superclass to reflect up to (inclusive), may be <code>null</code>
+     * @param outputTransients
+     *                  whether to include transient fields
+     */
+    public ReflectionToStringBuilder(Object object, ToStringStyle style, StringBuffer buffer, Class reflectUpToClass,
+            boolean outputTransients) {
+        super(object, style, buffer);
+        this.setUpToClass(reflectUpToClass);
+        this.setAppendTransients(outputTransients);
+    }
+
+    /**
+     * Constructor.
+     * 
+     * @param object
+     *                  the Object to build a <code>toString</code> for
+     * @param style
+     *                  the style of the <code>toString</code> to create, may be
+     *                  <code>null</code>
+     * @param buffer
+     *                  the <code>StringBuffer</code> to populate, may be <code>null</code>
+     * @param reflectUpToClass
+     *                  the superclass to reflect up to (inclusive), may be <code>null</code>
+     * @param outputTransients
+     *                  whether to include transient fields
+     * @param outputStatics
+     *                  whether to include static fields
+     * @since 2.1
+     */
+    public ReflectionToStringBuilder(Object object, ToStringStyle style, StringBuffer buffer, Class reflectUpToClass,
+            boolean outputTransients, boolean outputStatics) {
+        super(object, style, buffer);
+        this.setUpToClass(reflectUpToClass);
+        this.setAppendTransients(outputTransients);
+        this.setAppendStatics(outputStatics);
+    }
+
+    /**
+     * Returns whether or not to append the given <code>Field</code>.
+     * <ul>
+     * <li>Transient fields are appended only if {@link #isAppendTransients()}
+     * returns <code>true</code>.
+     * <li>Static fields are appended only if {@link #isAppendStatics()}
+     * returns <code>true</code>.
+     * <li>Inner class fields are not appened.</li>
+     * </ul>
+     * 
+     * @param field
+     *                  The Field to test.
+     * @return Whether or not to append the given <code>Field</code>.
+     */
+    protected boolean accept(Field field) {
+        if (field.getName().indexOf(ClassUtils.INNER_CLASS_SEPARATOR_CHAR) != -1) {
+            // Reject field from inner class.
+            return false;
+        }
+        if (Modifier.isTransient(field.getModifiers()) && !this.isAppendTransients()) {
+            // transients.
+            return false;
+        }
+        if (Modifier.isStatic(field.getModifiers()) && !this.isAppendStatics()) {
+            // transients.
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * <p>
+     * Appends the fields and values defined by the given object of the given
+     * Class.
+     * </p>
+     * 
+     * <p>
+     * If a cycle is detected as an object is &quot;toString()'ed&quot;, such
+     * an object is rendered as if <code>Object.toString()</code> had been
+     * called and not implemented by the object.
+     * </p>
+     * 
+     * @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();
+            AccessibleObject.setAccessible(fields, true);
+            for (int i = 0; i < fields.length; i++) {
+                Field field = fields[i];
+                String fieldName = field.getName();
+                if (this.accept(field)) {
+                    try {
+                        // Warning: Field.get(Object) creates wrappers objects
+                        // for primitive types.
+                        Object fieldValue = this.getValue(field);
+                        if (isRegistered(fieldValue) && !field.getType().isPrimitive()) {
+                            // A known field value has already been appended,
+                            // therefore we have an object cycle,
+                            // append a simple Object.toString style string.
+                            this.getStyle().appendFieldStart(this.getStringBuffer(), fieldName);
+                            this.appendAsObjectToString(fieldValue);
+                            this.getStyle().appendFieldEnd(this.getStringBuffer(), fieldName);
+                            // 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();
+        }
+    }
+
+    /**
+     * <p>
+     * Gets the last super class to stop appending fields for.
+     * </p>
+     * 
+     * @return The last super class to stop appending fields for.
+     */
+    public Class getUpToClass() {
+        return this.upToClass;
+    }
+
+    /**
+     * <p>
+     * Calls <code>java.lang.reflect.Field.get(Object)</code>.
+     * </p>
+     * 
+     * @param field
+     *                  The Field to query.
+     * @return The Object from the given Field.
+     * 
+     * @throws IllegalArgumentException
+     *                  see {@link java.lang.reflect.Field#get(Object)}
+     * @throws IllegalAccessException
+     *                  see {@link java.lang.reflect.Field#get(Object)}
+     * 
+     * @see java.lang.reflect.Field#get(Object)
+     */
+    protected Object getValue(Field field) throws IllegalArgumentException, IllegalAccessException {
+        return field.get(this.getObject());
+    }
+
+    /**
+     * <p>
+     * Gets whether or not to append static fields.
+     * </p>
+     * 
+     * @return Whether or not to append static fields.
+     * @since 2.1
+     */
+    public boolean isAppendStatics() {
+        return this.appendStatics;
+    }
+
+    /**
+     * <p>
+     * Gets whether or not to append transient fields.
+     * </p>
+     * 
+     * @return Whether or not to append transient fields.
+     */
+    public boolean isAppendTransients() {
+        return this.appendTransients;
+    }
+
+    /**
+     * <p>
+     * Append to the <code>toString</code> an <code>Object</code> array.
+     * </p>
+     * 
+     * @param array
+     *                  the array to add to the <code>toString</code>
+     * @return this
+     */
+    public ToStringBuilder reflectionAppendArray(Object array) {
+        this.getStyle().reflectionAppendArrayDetail(this.getStringBuffer(), null, array);
+        return this;
+    }
+
+    /**
+     * <p>
+     * Registers this builder's source object to avoid infinite loops when
+     * processing circular object references.
+     * </p>
+     */
+    void registerObject() {
+        register(this.getObject());
+    }
+
+    /**
+     * <p>
+     * Sets whether or not to append static fields.
+     * </p>
+     * 
+     * @param appendStatics
+     *                  Whether or not to append static fields.
+     * @since 2.1
+     */
+    public void setAppendStatics(boolean appendStatics) {
+        this.appendStatics = appendStatics;
+    }
+
+    /**
+     * <p>
+     * Sets whether or not to append transient fields.
+     * </p>
+     * 
+     * @param appendTransients
+     *                  Whether or not to append transient fields.
+     */
+    public void setAppendTransients(boolean appendTransients) {
+        this.appendTransients = appendTransients;
+    }
+
+    /**
+     * <p>
+     * Sets the last super class to stop appending fields for.
+     * </p>
+     * 
+     * @param clazz
+     *                  The last super class to stop appending fields for.
+     */
+    public void setUpToClass(Class clazz) {
+        this.upToClass = clazz;
+    }
+
+    /**
+     * <p>
+     * Gets the String built by this builder.
+     * </p>
+     * 
+     * @return the built string
+     */
+    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();
+    }
+
+    /**
+     * <p>
+     * Unregisters this builder's source object to avoid infinite loops when
+     * processing circular object references.
+     * </p>
+     */
+    void unregisterObject() {
+        unregister(this.getObject());
+    }
+}

Propchange: directory/sandbox/trustin/mina-spi/core/src/main/java/org/apache/mina/common/support/lang/builder/ReflectionToStringBuilder.java
------------------------------------------------------------------------------
    svn:keywords = HeadURL Id LastChangedBy LastChangedDate LastChangedRevision

Added: directory/sandbox/trustin/mina-spi/core/src/main/java/org/apache/mina/common/support/lang/builder/StandardToStringStyle.java
URL: http://svn.apache.org/viewcvs/directory/sandbox/trustin/mina-spi/core/src/main/java/org/apache/mina/common/support/lang/builder/StandardToStringStyle.java?rev=370807&view=auto
==============================================================================
--- directory/sandbox/trustin/mina-spi/core/src/main/java/org/apache/mina/common/support/lang/builder/StandardToStringStyle.java (added)
+++ directory/sandbox/trustin/mina-spi/core/src/main/java/org/apache/mina/common/support/lang/builder/StandardToStringStyle.java Fri Jan 20 05:47:50 2006
@@ -0,0 +1,537 @@
+/*
+ * Copyright 2002-2005 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.mina.common.support.lang.builder;
+
+/**
+ * <p>Works with {@link ToStringBuilder} to create a <code>toString</code>.</p>
+ *
+ * <p>This class is intended to be used as a singleton.
+ * There is no need to instantiate a new style each time.
+ * Simply instantiate the class once, customize the values as required, and
+ * store the result in a public static final variable for the rest of the
+ * program to access.</p>
+ *
+ * @author Stephen Colebourne
+ * @author Pete Gieser
+ * @author Gary Gregory
+ * @since 1.0
+ * @version $Id$
+ */
+public class StandardToStringStyle extends ToStringStyle {
+    
+    /**
+     * <p>Constructor.</p>
+     */
+    public StandardToStringStyle() {
+        super();
+    }
+    
+    //---------------------------------------------------------------------
+    
+    /**
+     * <p>Gets whether to use the class name.</p>
+     *
+     * @return the current useClassName flag
+     */
+    public boolean isUseClassName() {
+        return super.isUseClassName();
+    }
+
+    /**
+     * <p>Sets whether to use the class name.</p>
+     *
+     * @param useClassName  the new useClassName flag
+     */
+    public void setUseClassName(boolean useClassName) {
+        super.setUseClassName(useClassName);
+    }
+
+    //---------------------------------------------------------------------
+    
+    /**
+     * <p>Gets whether to output short or long class names.</p>
+     *
+     * @return the current useShortClassName flag
+     * @since 2.0
+     */
+    public boolean isUseShortClassName() {
+        return super.isUseShortClassName();
+    }
+
+    /**
+     * <p>Gets whether to output short or long class names.</p>
+     *
+     * @return the current shortClassName flag
+     * @deprecated Use {@link #isUseShortClassName()}
+     *             Method will be removed in Commons Lang 3.0.
+     */
+    public boolean isShortClassName() {
+        return super.isUseShortClassName();
+    }
+
+    /**
+     * <p>Sets whether to output short or long class names.</p>
+     *
+     * @param useShortClassName  the new useShortClassName flag
+     * @since 2.0
+     */
+    public void setUseShortClassName(boolean useShortClassName) {
+        super.setUseShortClassName(useShortClassName);
+    }
+
+    /**
+     * <p>Sets whether to output short or long class names.</p>
+     *
+     * @param shortClassName  the new shortClassName flag
+     * @deprecated Use {@link #setUseShortClassName(boolean)}
+     *             Method will be removed in Commons Lang 3.0.
+     */
+    public void setShortClassName(boolean shortClassName) {
+        super.setUseShortClassName(shortClassName);
+    }
+
+    //---------------------------------------------------------------------
+    
+    /**
+     * <p>Gets whether to use the identity hash code.</p>
+     * @return the current useIdentityHashCode flag
+     */
+    public boolean isUseIdentityHashCode() {
+        return super.isUseIdentityHashCode();
+    }
+
+    /**
+     * <p>Sets whether to use the identity hash code.</p>
+     *
+     * @param useIdentityHashCode  the new useIdentityHashCode flag
+     */
+    public void setUseIdentityHashCode(boolean useIdentityHashCode) {
+        super.setUseIdentityHashCode(useIdentityHashCode);
+    }
+
+    //---------------------------------------------------------------------
+    
+    /**
+     * <p>Gets whether to use the field names passed in.</p>
+     *
+     * @return the current useFieldNames flag
+     */
+    public boolean isUseFieldNames() {
+        return super.isUseFieldNames();
+    }
+
+    /**
+     * <p>Sets whether to use the field names passed in.</p>
+     *
+     * @param useFieldNames  the new useFieldNames flag
+     */
+    public void setUseFieldNames(boolean useFieldNames) {
+        super.setUseFieldNames(useFieldNames);
+    }
+
+    //---------------------------------------------------------------------
+    
+    /**
+     * <p>Gets whether to use full detail when the caller doesn't
+     * specify.</p>
+     *
+     * @return the current defaultFullDetail flag
+     */
+    public boolean isDefaultFullDetail() {
+        return super.isDefaultFullDetail();
+    }
+
+    /**
+     * <p>Sets whether to use full detail when the caller doesn't
+     * specify.</p>
+     *
+     * @param defaultFullDetail  the new defaultFullDetail flag
+     */
+    public void setDefaultFullDetail(boolean defaultFullDetail) {
+        super.setDefaultFullDetail(defaultFullDetail);
+    }
+
+    //---------------------------------------------------------------------
+    
+    /**
+     * <p>Gets whether to output array content detail.</p>
+     *
+     * @return the current array content detail setting
+     */
+    public boolean isArrayContentDetail() {
+        return super.isArrayContentDetail();
+    }
+    
+    /**
+     * <p>Sets whether to output array content detail.</p>
+     *
+     * @param arrayContentDetail  the new arrayContentDetail flag
+     */
+    public void setArrayContentDetail(boolean arrayContentDetail) {
+        super.setArrayContentDetail(arrayContentDetail);
+    }
+
+    //---------------------------------------------------------------------
+    
+    /**
+     * <p>Gets the array start text.</p>
+     *
+     * @return the current array start text
+     */
+    public String getArrayStart() {
+        return super.getArrayStart();
+    }
+
+    /**
+     * <p>Sets the array start text.</p>
+     *
+     * <p><code>null</code> is accepted, but will be converted
+     * to an empty String.</p>
+     *
+     * @param arrayStart  the new array start text
+     */
+    public void setArrayStart(String arrayStart) {
+        super.setArrayStart(arrayStart);
+    }
+
+    //---------------------------------------------------------------------
+    
+    /**
+     * <p>Gets the array end text.</p>
+     *
+     * @return the current array end text
+     */
+    public String getArrayEnd() {
+        return super.getArrayEnd();
+    }
+
+    /**
+     * <p>Sets the array end text.</p>
+     *
+     * <p><code>null</code> is accepted, but will be converted
+     * to an empty String.</p>
+     *
+     * @param arrayEnd  the new array end text
+     */
+    public void setArrayEnd(String arrayEnd) {
+        super.setArrayEnd(arrayEnd);
+    }
+
+    //---------------------------------------------------------------------
+    
+    /**
+     * <p>Gets the array separator text.</p>
+     *
+     * @return the current array separator text
+     */
+    public String getArraySeparator() {
+        return super.getArraySeparator();
+    }
+
+    /**
+     * <p>Sets the array separator text.</p>
+     *
+     * <p><code>null</code> is accepted, but will be converted
+     * to an empty String.</p>
+     *
+     * @param arraySeparator  the new array separator text
+     */
+    public void setArraySeparator(String arraySeparator) {
+        super.setArraySeparator(arraySeparator);
+    }
+
+    //---------------------------------------------------------------------
+    
+    /**
+     * <p>Gets the content start text.</p>
+     *
+     * @return the current content start text
+     */
+    public String getContentStart() {
+        return super.getContentStart();
+    }
+
+    /**
+     * <p>Sets the content start text.</p>
+     *
+     * <p><code>null</code> is accepted, but will be converted
+     * to an empty String.</p>
+     *
+     * @param contentStart  the new content start text
+     */
+    public void setContentStart(String contentStart) {
+        super.setContentStart(contentStart);
+    }
+
+    //---------------------------------------------------------------------
+    
+    /**
+     * <p>Gets the content end text.</p>
+     *
+     * @return the current content end text
+     */
+    public String getContentEnd() {
+        return super.getContentEnd();
+    }
+
+    /**
+     * <p>Sets the content end text.</p>
+     *
+     * <p><code>null</code> is accepted, but will be converted
+     * to an empty String.</p>
+     *
+     * @param contentEnd  the new content end text
+     */
+    public void setContentEnd(String contentEnd) {
+        super.setContentEnd(contentEnd);
+    }
+
+    //---------------------------------------------------------------------
+    
+    /**
+     * <p>Gets the field name value separator text.</p>
+     *
+     * @return the current field name value separator text
+     */
+    public String getFieldNameValueSeparator() {
+        return super.getFieldNameValueSeparator();
+    }
+
+    /**
+     * <p>Sets the field name value separator text.</p>
+     *
+     * <p><code>null</code> is accepted, but will be converted
+     * to an empty String.</p>
+     *
+     * @param fieldNameValueSeparator  the new field name value separator text
+     */
+    public void setFieldNameValueSeparator(String fieldNameValueSeparator) {
+        super.setFieldNameValueSeparator(fieldNameValueSeparator);
+    }
+
+    //---------------------------------------------------------------------
+    
+    /**
+     * <p>Gets the field separator text.</p>
+     *
+     * @return the current field separator text
+     */
+    public String getFieldSeparator() {
+        return super.getFieldSeparator();
+    }
+
+    /**
+     * <p>Sets the field separator text.</p>
+     *
+     * <p><code>null</code> is accepted, but will be converted
+     * to an empty String.</p>
+     *
+     * @param fieldSeparator  the new field separator text
+     */
+    public void setFieldSeparator(String fieldSeparator) {
+        super.setFieldSeparator(fieldSeparator);
+    }
+
+    //---------------------------------------------------------------------
+    
+    /**
+     * <p>Gets whether the field separator should be added at the start 
+     * of each buffer.</p>
+     * 
+     * @return the fieldSeparatorAtStart flag
+     * @since 2.0
+     */
+    public boolean isFieldSeparatorAtStart() {
+        return super.isFieldSeparatorAtStart();
+    }
+
+    /**
+     * <p>Sets whether the field separator should be added at the start 
+     * of each buffer.</p>
+     * 
+     * @param fieldSeparatorAtStart  the fieldSeparatorAtStart flag
+     * @since 2.0
+     */
+    public void setFieldSeparatorAtStart(boolean fieldSeparatorAtStart) {
+        super.setFieldSeparatorAtStart(fieldSeparatorAtStart);
+    }
+
+    //---------------------------------------------------------------------
+    
+    /**
+     * <p>Gets whether the field separator should be added at the end 
+     * of each buffer.</p>
+     * 
+     * @return fieldSeparatorAtEnd flag
+     * @since 2.0
+     */
+    public boolean isFieldSeparatorAtEnd() {
+        return super.isFieldSeparatorAtEnd();
+    }
+
+    /**
+     * <p>Sets whether the field separator should be added at the end 
+     * of each buffer.</p>
+     * 
+     * @param fieldSeparatorAtEnd  the fieldSeparatorAtEnd flag
+     * @since 2.0
+     */
+    public void setFieldSeparatorAtEnd(boolean fieldSeparatorAtEnd) {
+        super.setFieldSeparatorAtEnd(fieldSeparatorAtEnd);
+    }
+
+    //---------------------------------------------------------------------
+    
+    /**
+     * <p>Gets the text to output when <code>null</code> found.</p>
+     *
+     * @return the current text to output when <code>null</code> found
+     */
+    public String getNullText() {
+        return super.getNullText();
+    }
+
+    /**
+     * <p>Sets the text to output when <code>null</code> found.</p>
+     *
+     * <p><code>null</code> is accepted, but will be converted
+     * to an empty String.</p>
+     *
+     * @param nullText  the new text to output when <code>null</code> found
+     */
+    public void setNullText(String nullText) {
+        super.setNullText(nullText);
+    }
+
+    //---------------------------------------------------------------------
+    
+    /**
+     * <p>Gets the text to output when a <code>Collection</code>,
+     * <code>Map</code> or <code>Array</code> size is output.</p>
+     *
+     * <p>This is output before the size value.</p>
+     *
+     * @return the current start of size text
+     */
+    public String getSizeStartText() {
+        return super.getSizeStartText();
+    }
+
+    /**
+     * <p>Sets the start text to output when a <code>Collection</code>,
+     * <code>Map</code> or <code>Array</code> size is output.</p>
+     *
+     * <p>This is output before the size value.</p>
+     *
+     * <p><code>null</code> is accepted, but will be converted to
+     * an empty String.</p>
+     *
+     * @param sizeStartText  the new start of size text
+     */
+    public void setSizeStartText(String sizeStartText) {
+        super.setSizeStartText(sizeStartText);
+    }
+
+    //---------------------------------------------------------------------
+    
+    /**
+     * Gets the end text to output when a <code>Collection</code>,
+     * <code>Map</code> or <code>Array</code> size is output.</p>
+     *
+     * <p>This is output after the size value.</p>
+     *
+     * @return the current end of size text
+     */
+    public String getSizeEndText() {
+        return super.getSizeEndText();
+    }
+
+    /**
+     * <p>Sets the end text to output when a <code>Collection</code>,
+     * <code>Map</code> or <code>Array</code> size is output.</p>
+     *
+     * <p>This is output after the size value.</p>
+     *
+     * <p><code>null</code> is accepted, but will be converted
+     * to an empty String.</p>
+     *
+     * @param sizeEndText  the new end of size text
+     */
+    public void setSizeEndText(String sizeEndText) {
+        super.setSizeEndText(sizeEndText);
+    }
+
+    //---------------------------------------------------------------------
+    
+    /**
+     * <p>Gets the start text to output when an <code>Object</code> is
+     * output in summary mode.</p>
+     *
+     * <P>This is output before the size value.</p>
+     *
+     * @return the current start of summary text
+     */
+    public String getSummaryObjectStartText() {
+        return super.getSummaryObjectStartText();
+    }
+
+    /**
+     * <p>Sets the start text to output when an <code>Object</code> is
+     * output in summary mode.</p>
+     *
+     * <p>This is output before the size value.</p>
+     *
+     * <p><code>null</code> is accepted, but will be converted to
+     * an empty String.</p>
+     *
+     * @param summaryObjectStartText  the new start of summary text
+     */
+    public void setSummaryObjectStartText(String summaryObjectStartText) {
+        super.setSummaryObjectStartText(summaryObjectStartText);
+    }
+
+    //---------------------------------------------------------------------
+    
+    /**
+     * <p>Gets the end text to output when an <code>Object</code> is
+     * output in summary mode.</p>
+     *
+     * <p>This is output after the size value.</p>
+     *
+     * @return the current end of summary text
+     */
+    public String getSummaryObjectEndText() {
+        return super.getSummaryObjectEndText();
+    }
+
+    /**
+     * <p>Sets the end text to output when an <code>Object</code> is
+     * output in summary mode.</p>
+     *
+     * <p>This is output after the size value.</p>
+     *
+     * <p><code>null</code> is accepted, but will be converted to
+     * an empty String.</p>
+     *
+     * @param summaryObjectEndText  the new end of summary text
+     */
+    public void setSummaryObjectEndText(String summaryObjectEndText) {
+        super.setSummaryObjectEndText(summaryObjectEndText);
+    }
+
+    //---------------------------------------------------------------------
+    
+}

Propchange: directory/sandbox/trustin/mina-spi/core/src/main/java/org/apache/mina/common/support/lang/builder/StandardToStringStyle.java
------------------------------------------------------------------------------
    svn:keywords = HeadURL Id LastChangedBy LastChangedDate LastChangedRevision