Sunday, January 01, 2006

More enum reinvention in Java

I posted earlier on reinventing the enum in Java for pre-JDK5 code. But I am also annoyed by one limitation in JDK5 enums, than they are not extendable at runtime or otherwise. So I copied the Enum class from the JDK and modified it to support non-final subclasses.

An example class and its extension from the unit tests, also demonstrating the abstract feature present in the JDK enum:

  1     private abstract static class TestEnumA
  2             extends ExtensibleEnum<TestEnumA> {
  3         public static final TestEnumA A = new TestEnumA("A") {
  4             void foo() {
  5             }
  6         };
  7         public static final TestEnumA B = new TestEnumA("B") {
  8             void foo() {
  9             }
 10         };
 11 
 12         static {
 13             new TestEnumA("C") {
 14                 void foo() {
 15                 }
 16             };
 17         }
 18 
 19         abstract void foo();
 20 
 21         public static TestEnumA[] values() {
 22             return ExtensibleEnum.values(TestEnumA.class);
 23         }
 24 
 25         public static TestEnumA valueOf(final String name) {
 26             return ExtensibleEnum.valueOf(TestEnumA.class, name);
 27         }
 28 
 29         protected TestEnumA(final String name) {
 30             super(name);
 31         }
 32     }
 33 
 34     private static abstract class TestEnumB
 35             extends TestEnumA {
 36         public static final TestEnumB D = new TestEnumB("D") {
 37             void foo() {
 38             }
 39         };
 40 
 41         public static TestEnumB[] values() {
 42             return ExtensibleEnum.values(TestEnumB.class);
 43         }
 44 
 45         public static TestEnumB valueOf(final String name) {
 46             return ExtensibleEnum.valueOf(TestEnumB.class, name);
 47         }
 48 
 49         protected TestEnumB(final String name) {
 50             super(name);
 51         }
 52     }
 53 }

Note that if you ask for values() from TestEnumA, they include TestEnumB.D—a TestEnumA by subclassing.

Here is the base class. I am also trying out the "Code as HTML" plugin for IDEA—I hope the colorizing is not too much:

  1 /*
  2  * Copyright (c) 2006 B. K. Oxley (binkley) <binkley@alumni.rice.edu> under the
  3  * terms of the Artistic License, including Clause 8.  See
  4  * http://www.opensource.org/licenses/artistic-license.php.
  5  */
  6 
  7 import java.io.Serializable;
  8 import java.lang.reflect.Array;
  9 import java.util.ArrayList;
 10 import java.util.EnumMap;
 11 import java.util.HashMap;
 12 import java.util.List;
 13 import java.util.Map;
 14 
 15 /**
 16  * {@code ExtensibleEnum} <strong>needs documentation</strong>.
 17  *
 18  * @author <a href="mailto:binkley@alumni.rice.edu">B. K. Oxley (binkley)</a>
 19  * @version $Id$
 20  * @todo {@code RuntimeExtensibleEnum} needs documentation
 21  * @noinspection FinalizeDoesntCallSuperFinalize
 22  * @since Dec 31, 2005 8:38:03 AM
 23  */
 24 public abstract class ExtensibleEnum<E extends ExtensibleEnum<E>>
 25         implements Comparable<E>, Serializable {
 26     private static final Map<Class<? extends ExtensibleEnum<?>>,
 27             Map<String, ? extends ExtensibleEnum<?>>> BY_NAME
 28             = new HashMap<Class<? extends ExtensibleEnum<?>>,
 29             Map<String, ? extends ExtensibleEnum<?>>>(4);
 30     private static final Map<Class<? extends ExtensibleEnum<?>>,
 31             List<? extends ExtensibleEnum<?>>> BY_ORDINAL
 32             = new HashMap<Class<? extends ExtensibleEnum<?>>,
 33             List<? extends ExtensibleEnum<?>>>(4);
 34     /**
 35      * The JDK5 enum has ordinals in stepwise order; this implementation relaxes
 36      * the constraint to simply monotonically increasing.
 37      *
 38      * @noinspection StaticNonFinalField
 39      */
 40     private static int ORDINAL;
 41 
 42     /**
 43      * The name of this enum constant, as declared in the enum declaration. Most
 44      * programmers should use the {@link #toString} method rather than accessing
 45      * this field.
 46      */
 47     private final String name;
 48 
 49     /**
 50      * Returns the name of this enum constant, exactly as declared in its enum
 51      * declaration.
 52      * <p/>
 53      * <b>Most programmers should use the {@link #toString} method in preference
 54      * to this one, as the toString method may return a more user-friendly
 55      * name.</b>  This method is designed primarily for use in specialized
 56      * situations where correctness depends on getting the exact name, which
 57      * will not vary from release to release.
 58      *
 59      * @return the name of this enum constant
 60      */
 61     public final String name() {
 62         return name;
 63     }
 64 
 65     /**
 66      * The ordinal of this enumeration constant (its position in the enum
 67      * declaration, where the initial constant is assigned an ordinal of zero).
 68      * <p/>
 69      * Most programmers will have no use for this field.  It is designed for use
 70      * by sophisticated enum-based data structures, such as {@link
 71      * java.util.EnumSet} and {@link EnumMap}.
 72      */
 73     private final int ordinal = ORDINAL++;
 74 
 75     /**
 76      * Returns the ordinal of this enumeration constant (its position in its
 77      * enum declaration, where the initial constant is assigned an ordinal of
 78      * zero).
 79      * <p/>
 80      * Most programmers will have no use for this method.  It is designed for
 81      * use by sophisticated enum-based data structures, such as {@link
 82      * java.util.EnumSet} and {@link EnumMap}.
 83      *
 84      * @return the ordinal of this enumeration constant
 85      */
 86     public final int ordinal() {
 87         return ordinal;
 88     }
 89 
 90     /**
 91      * Sole constructor.  Programmers cannot invoke this constructor. It is for
 92      * use by code emitted by the compiler in response to enum type
 93      * declarations.
 94      *
 95      * @param name - The name of this enum constant, which is the identifier
 96      * used to declare it.
 97      */
 98     protected ExtensibleEnum(final String name) {
 99         if (null == name)
100             throw new NullPointerException("Missing name");
101 
102         this.name = name;
103 
104         new EnumInstall(getDeclaringClass(), name, this).install();
105     }
106 
107     private static class EnumInstall<T extends ExtensibleEnum<T>, U extends T> {
108         private final Class<T> enumType;
109         private final String name;
110         private final U instance;
111 
112         EnumInstall(final Class<T> enumType, final String name,
113                 final U instance) {
114             this.enumType = enumType;
115             this.name = name;
116             this.instance = instance;
117         }
118 
119         void install() {
120             if (!ExtensibleEnum.class.isAssignableFrom(enumType))
121                 return;
122 
123             final EnumInstall<? super T, ? super U> parentInstall
124                     = new EnumInstall(enumType.getSuperclass(), name, instance);
125 
126             parentInstall.install();
127 
128             try {
129                 putEnum(enumType, name, instance);
130 
131             } catch (final IllegalArgumentException e) {
132                 parentInstall.uninstall();
133 
134                 throw e;
135             }
136         }
137 
138         void uninstall() {
139             unputEnum(enumType, name);
140         }
141     }
142 
143     private static <T extends ExtensibleEnum<T>, U extends T> void putEnum(
144             final Class<T> enumType, final String name, final U instance) {
145         if (!BY_NAME.containsKey(enumType)) {
146             BY_NAME.put(enumType, new HashMap<String, T>(4));
147             BY_ORDINAL.put(enumType, new ArrayList<T>(4));
148         }
149 
150         final Map<String, T> nameMap = byName(enumType);
151 
152         if (nameMap.containsKey(name))
153             throw new IllegalArgumentException("Duplicate name: " + name);
154 
155         nameMap.put(name, instance);
156         byOrdinal(enumType).add(instance);
157     }
158 
159     private static <T extends ExtensibleEnum<T>> void unputEnum(
160             final Class<T> enumType, final String name) {
161         if (!BY_NAME.containsKey(enumType))
162             return;
163 
164         byName(enumType).remove(name);
165 
166         final List<T> list = byOrdinal(enumType);
167 
168         list.remove(list.size() - 1);
169     }
170 
171     /**
172      * Returns the name of this enum constant, as contained in the declaration.
173      * This method may be overridden, though it typically isn't necessary or
174      * desirable.  An enum type should override this method when a more
175      * "programmer-friendly" string form exists.
176      *
177      * @return the name of this enum constant
178      */
179     @Override
180     public String toString() {
181         return name;
182     }
183 
184     /**
185      * Returns true if the specified object is equal to this enum constant.
186      *
187      * @param other the object to be compared for equality with this object.
188      *
189      * @return true if the specified object is equal to this enum constant.
190      */
191     @Override
192     public final boolean equals(final Object other) {
193         return this == other;
194     }
195 
196     /**
197      * Returns a hash code for this enum constant.
198      *
199      * @return a hash code for this enum constant.
200      */
201     @Override
202     public final int hashCode() {
203         return System.identityHashCode(this);
204     }
205 
206     /**
207      * Throws CloneNotSupportedException.  This guarantees that enums are never
208      * cloned, which is necessary to preserve their "singleton" status.
209      *
210      * @return (never returns)
211      */
212     @Override
213     protected final Object clone()
214             throws CloneNotSupportedException {
215         throw new CloneNotSupportedException();
216     }
217 
218     /**
219      * Compares this enum with the specified object for order.  Returns a
220      * negative integer, zero, or a positive integer as this object is less
221      * than, equal to, or greater than the specified object.
222      * <p/>
223      * ExtensibleEnum constants are only comparable to other enum constants of
224      * the same enum type.  The natural order implemented by this method is the
225      * order in which the constants are declared.
226      *
227      * @noinspection ObjectEquality
228      */
229     public final int compareTo(final E o) {
230         if (getClass() != o.getClass() // optimization
231                 && getDeclaringClass() != o.getDeclaringClass())
232             throw new ClassCastException();
233 
234         return new Integer(ordinal).compareTo(o.ordinal);
235     }
236 
237     public static <T extends ExtensibleEnum> T[] values(
238             final Class<T> enumType) {
239         final List<T> values = byOrdinal(enumType);
240 
241         return values.toArray((T[]) Array.newInstance(enumType, values.size()));
242     }
243 
244     /**
245      * Returns the enum constant of the specified enum type with the specified
246      * name.  The name must match exactly an identifier used to declare an enum
247      * constant in this type.  (Extraneous whitespace characters are not
248      * permitted.)
249      *
250      * @param enumType the <tt>Class</tt> object of the enum type from which to
251      * return a constant
252      * @param name the name of the constant to return
253      *
254      * @return the enum constant of the specified enum type with the specified
255      *         name
256      *
257      * @throws IllegalArgumentException if the specified enum type has no
258      * constant with the specified name, or the specified class object does not
259      * represent an enum type
260      * @throws NullPointerException if <tt>enumType</tt> or <tt>name</tt> is
261      * null
262      * @since 1.5
263      */
264     public static <T extends ExtensibleEnum> T valueOf(final Class<T> enumType,
265             final String name) {
266         // IDEA says cast is useless; JDK5 javac says it is necessary
267         //noinspection RedundantCast
268         final T result = (T) byName(enumType).get(name);
269 
270         if (null != result)
271             return result;
272         if (null == name)
273             throw new NullPointerException("Name is null");
274 
275         throw new IllegalArgumentException(
276                 "No enum const " + enumType + '.' + name);
277     }
278 
279     /**
280      * enum classes cannot have finalize methods.
281      */
282     @Override
283     protected final void finalize() { }
284 
285     protected Class<?> getDeclaringClass() {
286         final Class<?> enumType = getClass();
287 
288         return enumType.isAnonymousClass()
289                 ? enumType.getSuperclass()
290                 : enumType;
291     }
292 
293     private static <T extends ExtensibleEnum<T>> Map<String, T> byName(
294             final Class<T> enumType) {
295         return (Map<String, T>) BY_NAME.get(enumType);
296     }
297 
298     private static <T extends ExtensibleEnum<T>> List<T> byOrdinal(
299             final Class<T> enumType) {
300         return (List<T>) BY_ORDINAL.get(enumType);
301     }
302 }

Happy New Year!

Tuesday, December 27, 2005

Emulating static import

It may seem a trivial feature in JDK5, but static import is growing on me. It especially helps me read code to see the flow of method calls without package prefixes.

So at work I'm on a JDK1.4.2 project and miss static import. The solution is quite simple: I put same-named private static methods at the bottom of my class files to emulate the static import, thus:

import javax.swing.UIManager;

/**
 * A toy example: not production code.
 * <p/>
 * Throwing <code>RuntimeException</code> is in poor taste.
 */
public class TopLevel {
    static {
        // Set up font smoothing
        System.setProperty("swing.aatext", "true");

        try {
            setLookAndFeel("net.java.plaf.windows.WindowsLookAndFeel");

        } catch (final IllegalAccessException e) {
            throw new RuntimeException(e);

        } catch (final UnsupportedLookAndFeelException e) {
            throw new RuntimeException(e);

        } catch (final InstantiationException e) {
            throw new RuntimeException(e);

        } catch (final ClassNotFoundException e) {
            throw new RuntimeException(e);
        }
    }

    // Real work goes here.

    // Simple forwarding to emulate static import:
    private static void setLookAndFeel(final String name)
            throws ClassNotFoundException,
            InstantiationException, IllegalAccessException,
            UnsupportedLookAndFeelException {
        UIManager.setLookAndFeel(name);
    }
}

It's not rocket science, but it makes my day just a little bit nicer.

Monday, December 19, 2005

New math functions in JDK6

I've been watching the releases of JDK6 closely and have noticed that the math facilities continue to mature. Following in the footsteps of java.lang.StrictMath in JDK5, I see that JDK6 adds more useful static methods (for each method, there are similar methods for floats):

double copySign(double magnitude, double sign)
Returns the first floating-point argument with the sign of the second floating-point argument.
int getExponent(double d)
Returns the unbiased exponent used in the representation of a double.
double nextAfter(double start, double direction)
Returns the floating-point number adjacent to the first argument in the direction of the second argument.
public static double nextUp(double d)
Returns the floating-point value adjacent to d in the direction of positive infinity.
double scalb(double d, int scaleFactor)
Return d × 2scaleFactor rounded as if performed by a single correctly rounded floating-point multiply to a member of the double value set.

The only drawback is that several common operations are still missing. I wish the JDK would provide the comprehensiveness of C's libm.

Wednesday, December 14, 2005

Reinventing the enum in Java

I'm working on a Java project which uses JDK 1.4.2, so I do not have the useful enum keyword available to me. What to do? Reinvent the enum, of course. I try following the pattern set by JDK5, suitable for JDK 1.4.2. Merry Christmas:

/**
 * <code>AbstractEnum</code> models <a href="http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Enum.html">the
 * JDK5 <code>enum</code> feature</a>.
 * <p/>
 * Extending classes should follow this example: <pre>
 * public class Suit
 *         extends AbstractEnum {
 *     public static final Suit CLUBS = new Suit("CLUBS");
 *     public static final Suit DIAMONDS = new Suit("DIAMONDS");
 *     public static final Suit HEARTS = new Suit("HEARTS");
 *     public static final Suit SPADES = new Suit("SPADES");
 *
 *     public static Suit[] values() {
 *          return (Suit[]) values0(Suit.class, new Suit[count(Suit.class)]);
 *     }
 *
 *     public static Suit valueOf(final String name) {
 *         return (Suit) valueOf0(Suit.class, name);
 *     }
 *
 *     private Suit(final String name) {
 *         super(name);
 *     }
 * }</pre>
 *
 * @author <a href="mailto:binkley@alumni.rice.edu">B. K. Oxley (binkley)</a>
 * @version $Id$
 * @since Dec 14, 2005 6:32:23 PM
 */
public abstract class AbstractEnum
        implements Comparable {
    private static final Map ALL_VALUES_BY_NAME = new HashMap(4);
    private static final Map ALL_VALUES_BY_ORDINAL = new HashMap(4);
    private static final Map ALL_COUNTS = new HashMap(4);

    /**
     * The ordinal of this enumeration constant (its position in the enum
     * declaration, where the initial constant is assigned an ordinal of zero).
     * <p/>
     * Most programmers will have no use for this field.  It is designed for use
     * by sophisticated enum-based data structures.
     */
    private final int ordinal = createNextOrdinal(getClass());

    /**
     * The name of this enum constant, as declared in the enum declaration. Most
     * programmers should use the {@link #toString} method rather than accessing
     * this field.
     */
    private final String name;

    /**
     * Gets all enum values of type <var>clazz</var> into <var>array</var>.  Use
     * {@link #count(Class)} to size the array parameter.
     * <p/>
     * Concrete subclasses <em>should</em> provide <code>values()</code> which
     * follows the example:
     * <pre>
     * public static Suit[] values() {
     *     return (Suit[]) valuesOf(Suit.class, new Suit[count(Suit.class)]);
     * }</pre>
     *
     * @param clazz the enum type
     * @param array the array
     *
     * @return the enum values
     *
     * @throws ClassCastException if <var>clazz</var> is not an enum class
     */
    protected static AbstractEnum[] values0(final Class clazz,
            final AbstractEnum[] array) {
        checkClassIsEnum(clazz);

        int i = 0;

        for (final Iterator valueIt = getValuesByOrdinal(clazz).iterator();
                valueIt.hasNext(); ++i)
            array[i] = (AbstractEnum) valueIt.next();

        return array;
    }

    /**
     * Gets the count of enums of type <var>clazz</var>, zero (0) if none.
     *
     * @param clazz the enum type
     *
     * @return the enum count
     *
     * @throws ClassCastException if <var>clazz</var> is not an enum class
     */
    protected static int count(final Class clazz) {
        checkClassIsEnum(clazz);

        return ALL_COUNTS.containsKey(clazz)
                ? ((Integer) ALL_COUNTS.get(clazz)).intValue()
                : 0;
    }

    /**
     * Gets an enum with the given <var>name</var>.
     * <p/>
     * Concrete subclasses <em>should</em> provide <code>valuesOf(String)</code>
     * which follows the example:
     * <pre>
     * public static Suit valueOf(final String name) {
     *     return (Suit) valueOf(Suit.class, name);
     * }</pre>
     *
     * @param clazz the enum class
     * @param name the enum name
     *
     * @return the corresponding enum value
     *
     * @throws ClassCastException if <var>clazz</var> is not an enum class
     * @throws IllegalArgumentException if <var>name</var> is not an enum name
     */
    protected static AbstractEnum valueOf0(final Class clazz,
            final String name)
            throws IllegalArgumentException {
        checkClassIsEnum(clazz);

        final Map values = getValuesByName(clazz);

        if (values.containsKey(name))
            return (AbstractEnum) values.get(name);

        throw new IllegalArgumentException(name);
    }

    /**
     * Constructs a new <code>AbstractEnum</code> with the given
     * <var>name</var>.
     *
     * @param name the name of this enum constant, which is the identifier used
     * to declare it
     */
    protected AbstractEnum(final String name) {
        this.name = name;

        getValuesByName(getClass()).put(name, this);
        getValuesByOrdinal(getClass()).add(this);
    }

    /**
     * Returns the name of this enum constant, exactly as declared in its enum
     * declaration.
     * <p/>
     * <b>Most programmers should use the {@link #toString} method in preference
     * to this one, as the toString method may return a more user-friendly
     * name.</b>  This method is designed primarily for use in specialized
     * situations where correctness depends on getting the exact name, which
     * will not vary from release to release.
     *
     * @return the name of this enum constant
     */
    public String name() {
        return name;
    }

    /**
     * Returns the ordinal of this enumeration constant (its position in its
     * enum declaration, where the initial constant is assigned an ordinal of
     * zero).
     * <p/>
     * Most programmers will have no use for this method.  It is designed for
     * use by sophisticated enum-based data structures.
     *
     * @return the ordinal of this enumeration constant
     */
    public int ordinal() {
        return ordinal;
    }

    // Object

    /**
     * Throws CloneNotSupportedException.  This guarantees that enums are never
     * cloned, which is necessary to preserve their "singleton" status.
     *
     * @return (never returns)
     *
     * @throws CloneNotSupportedException if called
     */
    protected Object clone()
            throws CloneNotSupportedException {
        throw new CloneNotSupportedException();
    }

    /**
     * Returns the name of this enum constant, as contained in the declaration.
     * This method may be overridden, though it typically isn't necessary or
     * desirable.  An enum type should override this method when a more
     * "programmer-friendly" string form exists.
     *
     * @return the name of this enum constant
     */
    public String toString() {
        return name;
    }

    // Comparable

    /**
     * Compares this enum with the specified object for order.  Returns a
     * negative integer, zero, or a positive integer as this object is less
     * than, equal to, or greater than the specified object.
     * <p/>
     * Enum constants are only comparable to other enum constants of the same
     * enum type.  The natural order implemented by this method is the order in
     * which the constants are declared.
     */
    public int compareTo(final Object o) {
        if (!getClass().equals(o.getClass()))
            throw new ClassCastException(o.getClass().toString());
        return ordinal - ((AbstractEnum) o).ordinal;
    }

    private static Map getValuesByName(final Class clazz) {
        final Map values;

        if (ALL_VALUES_BY_NAME.containsKey(clazz))
            values = (Map) ALL_VALUES_BY_NAME.get(clazz);
        else
            ALL_VALUES_BY_NAME.put(clazz, values = new HashMap(8));

        return values;
    }

    private static SortedSet getValuesByOrdinal(final Class clazz) {
        final SortedSet values;

        if (ALL_VALUES_BY_ORDINAL.containsKey(clazz))
            values = (SortedSet) ALL_VALUES_BY_ORDINAL.get(clazz);
        else
            ALL_VALUES_BY_ORDINAL.put(clazz, values = new TreeSet());

        return values;
    }

    private static int createNextOrdinal(final Class clazz) {
        final int count = count(clazz);

        ALL_COUNTS.put(clazz, new Integer(count + 1));

        return count;
    }

    private static void checkClassIsEnum(final Class clazz) {
        if (!AbstractEnum.class.isAssignableFrom(clazz))
            throw new ClassCastException(clazz.toString());
    }
}

Tuesday, November 22, 2005

The Extensible Enum Pattern in Java

There is a long history of the enum pattern in Java. What I have seen and used several times on different projects is a variant which we called the Extensible Enum Pattern. My fellow ex-ThoughtWorker, Andrew McCormick, first showed it to me.

Here is what I wrote the PCGen developer's list about this pattern when the question arose about processing program-defined and user-defined tokens together:

We have a set of conditions based on integer codes, some which we define themselves, others which are read from 3rd-party files and cannot all be known ahead of time.

The basic class for our extensible enum looks like this:

public class Status {
    private final int code;
    private final String remark;

    private Status(final int code, final String remark) {
        if (null == remark) throw new NPE;

        this.code = code;
        this.remark = remark;
    }
}

Ok, so the object is immutable: there are no setters or editable fields. That is the first step towards being an enum. And so far there are no public way to create new ones. Lets open the class and add a factory method:

    private static final Map CODES = new HashMap();

    public static Status create(final int code, final String remark) {
        final Integer key = new Integer(code);
        final Status status;

        if (!CODES.containsKey(key))
            CODES.put(key, status = new Status(code, remark));
        else
            status = (Status) CODES.get(key);

        return status;
    }

Now we have the other half of being an enum: no two instances of the same value are distinguishable. Whenever you try to create a new enum, if there is already an instance with the same code, you get back that instance rather than a new instance. (However, as the remark is just satellite data, not part of the identity of Status, you can see that you also get back the original remark.) Let's reinforce this message, and open the class again:

    public int hashCode() {
        return code;
    }

    public boolean equals(final Object o) {
        if (this == o) return true;
        if (null == o) return false;
        if (getClass() != o.getClass()) return false;

        return code == ((Status) o).code;
    }

Lastly, let's open the class one final time to prepopulate it with our defined instances (be careful to initialize CODES before creating static instances or you'll get a NPE when trying to access the cache):

    public static final Status SUCCESS = create(0, "Success");
    public static final Status BARNEY_DIED = create(-10,
            "Barney died: please reinsert purple dinosaur.");
    public static final Status OLL_KORRECT = create(10,
            "All your answers are correct!");

Now in code, I use Status like this:

    if (somethingHorribleHappened())
        return Status.BARNEY_DIED;
    else
        return Status.create(readCodeFromElsewhere(),
                "Out of body experience: external status");

So that we got well-defined static instances for internal codes, and can generate new instances as required for external codes.

At bottom, I'll paste in a JDK5 version (generics, auto-boxing, annotations) along with some business methods. Note that the new JDK enum feature is not extensible. Otherwise, it is a thing of beauty, and in fact my next revision of this class for my client will model the JDK enum class more closely but retain the extensible property.

And lastly, the same thing updated for JDK5 and with some comments:

import java.util.HashMap;
import java.util.Map;

/**
 * {@code Status} represents extensible enums for status codes.
 *
 * @author <a href="mailto:binkley@alumni.rice.edu">B. K. Oxley (binkley)</a>
 */
public class Status {
    private static final Map<Integer, Status> CODES
            = new HashMap<Integer, Status>();

    /**
     * An unremarkable success.
     */
    public static final Status SUCCESS = create(0, "Success");
    /**
     * An unknown failure.
     */
    public static final Status UNKNOWN_FAILURE = create(-1, "Unknown failure");

    /**
     * Creates a new {@code Status} or reuses an existing instance for a given
     * <var>code</var>.
     *
     * @param code the status code
     * @param remark the status remark
     *
     * @throws NullPointerException if <var>remark</var> is {@code null}
     */
    public static Status create(final int code, final String remark) {
        final Status status;

        if (!CODES.containsKey(code))
            CODES.put(code, status = new Status(code, remark));
        else
            status = CODES.get(code);

        return status;
    }

    private final int code;
    private final String remark;

    private Status(final int code, final String remark) {
        if (null == remark) throw new NullPointerException();

        this.code = code;
        this.remark = remark;
    }

    public int getCode() {
        return code;
    }

    public String getRemark() {
        return remark;
    }

    /**
     * Checks if a success or failure status.  All non-negative codes
     * are successful.
     *
     * @return {@code true} if a success status
     */
    public boolean isSuccess() {
        return 0 <= code;
    }

    /**
     * Checks if {@link #getRemark()} is meaningful.  All non-zero codes
     * are remarkable.
     *
     * @return {@code true} if {@link #getRemark()} is useful
     */
    public boolean isRemarkable() {
        return 0 != code;
    }

    /**
     * {@inheritDoc}
     * <p/>
     * Returns <em>"(code) remark"</em>.
     */
    @Override
    public String toString() {
        return "(" + code + ") " + remark;
    }

    /**
     * {@inheritDoc}
     * <p/>
     * Considers only {@link #code} for equality.
     */
    @Override
    public boolean equals(final Object o) {
        if (this == o) return true;
        if (null == o) return false;
        if (getClass() != o.getClass()) return false;

        return code == ((Status) o).code;
    }

    /**
     * {@inheritDoc}
     * <p/>
     * Returns {@link #code} as the hash code.
     */
    @Override
    public int hashCode() {
        return code;
    }
}

Tuesday, November 15, 2005

Spashscreen for Java startup

I'm not sure how long it's been there (at least since September, when this post came out), but java now supports a splash screen option on startup:

-splash:<imagepath>
              show splash screen with specified image

Nifty.

Saturday, October 22, 2005

Qt for Java

Aaron Seigo writes a good amount about the TrollTech developer's social in San Diego. The part that made my ears perk up:

haavard announced that by Q1-06 they'll be releasing a tech preview of java bindings for qt4 that will be officially supported. wow.

Wow indeed.

Friday, October 21, 2005

Jeff Biggler's Tack Filters

I heard about this gem of an article on the XP Yahoo! Groups list, Tact Filters. As any of my friends will point out, my native tact filter is applied to the incoming direction. Age has granted me an add-on tact filter for the outgoing direction, not as operative as the native filter but better than none.

Monday, October 17, 2005

Ruby in Eclipse

An interesting article from IBM on the Ruby extension for Eclipse, Using the Ruby Development Tools plug-in for Eclipse. The blurb:

This article introduces using the Ruby Development Tools (RDT) plug-in for Eclipse, which allows Eclipse to become a first-rate Ruby development environment. Ruby developers who want to learn how to use the rich infrastructure of the Eclipse community to support their language will benefit, as will Java™ developers who are interested in using Ruby.

Fortunately, the article is more than just a description and includes setup and all that. And what pretty screenshots!

Wednesday, October 12, 2005

Agile leadership

One of the things that draws me to agile programming styles is the agile approach to leadership.

Waterfall processes naturally fit within a top-down organization where leadership is a direct chain of control in the shape of a pyramid. The exemplar of waterfall leadership is a military organization.

Agile leadership follows from agile processes. It emphasizes change, collaboration and consultation. To adapt is more important than to plan; to listen is more important than to order; to trust is more important than to manage. The shape is that of a network.

But agile leadership is not the opposite of waterfall leadership. A good leader keeps both in mind and applies the best principle to the problem at hand.

For example, new junior programmers are often bewildered by the array of technical approaches available for a given problem. In an agile environment, pair the young Jedi with a senior developer who can share his craft and training.

However, there may not be a senior developer available. Lacking a suitable guide, it is better to task the apprentice with short, straight-forward steps—spell out a likely solution that the junior programmer can learn from as he codes, and provide supervision as requested.

Again, a problem arises: what sort of supervision? If possible, instill in the new peer that you trust him to follow simple instructions but that you are approachable for questions and suggestions. The goal is not to simply train the fingers to type good code, but also teach the mind good values. I believe those values to be agile ones; you may believe otherwise.

None of this is controversial, yet I encounter such mentoring more often with agile leadership than with waterfall leadership. Perhaps it is more a measure of where I worked than how I worked, but I prefer to believe the manifesto.

The big picture

Am I a details person? The impression of most people is that I am; this blog certainly is detail-oriented. But I would argue otherwise.

I approach most topics as scaling problems. If you are talking about atoms, the appropriate level of detail is the atomic; if you are talking about aggregates, the appropriate level of detail is small but at the macro scale; if you are talking about galaxies, the appropriate level of detail is stars and dust.

On this blog, most entries are detail-oriented simply because small domains are easier to describe than large domains and the answers are more satisfactory and complete. (Even so, I often miss interesting points; I am grateful for comments.)

Contrast the small scale of algorithms where behaviors can in many cases be analyzed fully with the large scale of company-wide systems where behaviors are imprecise and many factors difficult to analyze come into play.

For a short blog entry written to a general audience, I would rather approach an algorithm as the level of detail. I believe it is more satisfying for the reader and less time-consuming for the author. For a white paper (such as this one I wrote while at EBS) I have more freedom in exposition to tackle a larger topic. Perhaps more opportunities will come for me to write about the bigger picture.

Arrays and Collections

Keith Devens makes a good point of recommending Arrays.asList(...) over hand-crafted lists. Thus he suggests that in place of:

List<Foo> foolist = new ArrayList<Foo>();
foolist.add(foo);
return foolist;

You instead use:

return Arrays.asList(foo);

This has much to recommend it, especially conciseness and clarity. However, as the hawker on late night TV says, But there's more!

In addition to the useful Arrays class of static helper methods, there is Collections which has more useful static helper methods. So the example could have also been written as:

return Collections.singletonList(foo);

What's the difference? This is an interesting question. There is no way to select between Arrays and Collections without further information.

If the requirement were to return an unmodifiable view, then the easy route is:

return Collections.singletonList(foo);

Which is an even more clear way to express the intention of the code than Arrays.toList—the singleton pattern is one of the first grokked by any programmer. What if the code fragment were part of this method?

/**
 * Returns a modifiable list of just the topmost foo.
 *
 * @return Modifiable list containing just the topmost foo
 */
public List<Foo> copyTopFooAsList() {
    return ???;
}

Now it is clear from the javadocs for Arrays.asList that this is not quite what we want:

Returns a fixed-size list backed by the specified array. (Changes to the returned list "write through" to the array.) This method acts as bridge between array-based and collection-based APIs, in combination with Collection.toArray.

And clearly Collections.singletonList(T) is not right either—when is a proper singleton modifiable? And Collections.toArray is clearly useful, but not what we are looking for (it returns an array, not a list).

After some thought, the solution is not hard to find: look at the constructors for ArrayList, and at ArrayList(Collection) in particular. Although the javadocs do not explicitly say copies from the input, they do hint at that (and a quick peek at the source code confirms it is so):

Constructs a list containing the elements of the specified collection, in the order they are returned by the collection's iterator.

So the solution becomes:

return new ArrayList(Collections.singleton(foo));

A handy one-liner to keep in the back pocket for future use.

Tuesday, October 11, 2005

Better GC in JDK6 (Mustang)

As noted in OSnews, IBM has a great article on GC in the Java VM entitled Java Urban Legends. One of the developments in the ever-improving JVM really caught my eye:

Escape analysis is an optimization that has been talked about for a long time, and it is finally here -- the current builds of Mustang (Java SE 6) can do escape analysis and convert heap allocation to stack allocation (or no allocation) where appropriate. The use of escape analysis to eliminate some allocations results in even faster average allocation times, reduced memory footprint, and fewer cache misses. Further, optimizing away some allocations reduces pressure on the garbage collector and allows collection to run less often.

Escape analysis can find opportunities for stack allocation even where it might not be practical to do so in the source code, even if the language provided the option, because whether a particular allocation gets optimized away is determined based on how the result of an object-returning method is actually used in a particular code path. The Point returned from getLocation() may not be suitable for stack allocation in all cases, but once the JVM inlines getLocation(), it is free to optimize each invocation separately, offering us the best of both worlds: optimal performance with less time spent making low-level, performance-tuning decisions.

The referenced code before optimization:

public double getDistanceFrom(Component other) {
    Point otherLocation = new Point(other.x, other.y);
    int deltaX = otherLocation.x - location.x;
    int deltaY = otherLocation.y - location.y;
    return Math.sqrt(deltaX*deltaX + deltaY*deltaY);
}

And after:

public double getDistanceFrom(Component other) {
    int tempX = other.x, tempY = other.y;
    int deltaX = tempX - location.x;
    int deltaY = tempY - location.y;
    return Math.sqrt(deltaX*deltaX + deltaY*deltaY);
}

A nice win for Sun's JVM, to be sure.

Thursday, October 06, 2005

Testing protected methods with JUnit 4

One of the pains of JUnit is testing protected methods. Public methods offer no impediment to testing, and private methods in well-designed classes can be ignored as implementation details called by the public methods. But protected methods are important for frameworks and central to the Template Method pattern; they need testing.

The most common ways to test protected methods that I've seen are to invoke the protected method with reflection, to use a private inner helper class which extends the class under test, and similarly to extend the class under test and change the access of the protected methods to public. All have their drawbacks.

Enter JUnit 4. No longer must test classes extend TestCase. Using annotations, the test framework finds and runs your test methods without inheritance, and static imports keep calls to assertTrue and friends looking clean and tidy.

Your test class itself can extend the class under test and access the protected methods without the need for reflection or a second, helper class. This is another blow struck for small, clean code thanks to JDK 5.

UPDATE: As Sam in the comments pointed out, one could just put the tests in the same package as the class under test. For silly reasons, I left this out of the list of workarounds.