Posted on Apr 25, 2008

Binding data to Java enums…

Paul Stovell blogged about binding data to enums in C#. Here is how I would implement this technique in Java….

First, an annotation that I will use to bind data to my enum


@Target(Element.FIELD)
@Retention(RententionPolicy.RUNTIME)
public @interface Config {
	String name();
	String alias();
}

Then, here is my enum


public enum Role {
@Config(name="James Bond", alias = "Agent 007")
AGENT;

// static attribute that will allow us to
// config the enum only once.
private static boolean isConfigured = false;
static {
if(!isConfigured){
    configureRole();
}
}

private RoleValue value;
Role(){
}

public RoleValue getValue(){
    if(value == null){
        throw new IllegalStateException();
    }
    return new RoleValue(value);
}

private static void configureRole(){
    final Field[] declaredEnums = Role.class.getDeclaredFields();
    for(Field eachField : declaredEnums){
        final Config placedConfig = eachField.getAnnotation(Config.class);

        final boolean isValuesField     = eachField.getName().equals("$VALUES");
        final boolean isRefreshedField  = eachField.getName().equals("isConfigured");
        final boolean isValueField      = eachField.getName().equals("value");

        // ... we want to igonore the VALUES, isConfigured, and value fields.
        // ... we care only about the Role's enum instances.
        if(isValuesField || isRefreshedField || isValueField){
            continue;
        }

        final String name           = placedConfig.name();
        final String alias          = placedConfig.alias();
        final Enum<Role> actualEnum = valueOf(eachField.getName());

        final RoleValue enumValue   = new RoleValue(name, alias);

        try {
            final Field field = actualEnum.getDeclaringClass().getDeclaredField(
                  "value"
             );
            field.setAccessible(true);
            field.set(actualEnum, enumValue);
        } catch (NoSuchFieldException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        }

        isConfigured = true;

    }
}

/**
 * a updatable value
 */
public static class RoleValue {
    private final String name;
    private final String alias;
    public RoleValue(String name, String alias){
        this.name   = name;
        this.alias  = alias;
    }

    public RoleValue(RoleValue value){
        this(value.getName(), value.getAlias());
    }

    public String getName(){
        return name;
    }

    public String getAlias(){
        return alias;
    }
}
}

interesting way to play with Java 5.0′s enums…. cool :)

Spam Protection by WP-SpamFree