tags:

views:

420

answers:

7

I'm trying to declare an enum type based on data that I'm retrieving from a database. I have a method that returns a string array of all the rows in the table that I want to make into an enumerated type. Is there any way to construct an enum with an array?

This is what I tried, but from the way it looked in eclipse, it seemed like this just created a method by that name:

public enum ConditionCodes{
    Condition.getDescriptions();
}

Thank you in advance!

+9  A: 

You can't.

The values of an enum must be known at compile time. If you have anything else, then it's not an enum.

You could come rather close via an implementation that's similar to the old typesafe enums that were used before the Java language introduced support for this technique via the enum keyword. You could use those techniques but simply replace the static final fields with values read from the DB.

Joachim Sauer
That's what I thought. Thank you!
chama
A: 

No, that's not possible because the enum type must be defined at compile time and what you're looking for is to dynamically create it.

Perhaps you'll be better if use a class instead.

OscarRyz
+3  A: 

For your enum to be useful it has to be nailed down at compile time. Generating the enum from the database query would imply you expect to see new enum values at runtime. Even if you created a code generator to create your enum class on the fly using the database query, you wouldn't be able to reference those enum values in your code, which is the point of having them.

Nathan Hughes
Good point - thank you!
chama
A: 

If you want to get really crazy, I think annotation processing can do this. Annotation processing lets you hook the compiler and have it magically modify things when your @annotation is present.

Naturally, the values in the enum will be whatever values were available at compile time.

Matti Virkkunen
A: 

I think here you are going to need a List or Set along with some utility methods for searching and comparison.

So here's your List

List<String> conditionCodes = new ArrayList<String>();
//Somehow get Rows or POJO Beans from database with your favorite framework
Collection<Row> dbRows = getConditionCodes();
for(Row curRow : dbRows)
     conditionCodes.add(curRow.getName());

And to search

public boolean conditionExists(String name) {
    return conditonCodes.contains(name);
}

public String getCondition(String name) {
    return conditionCodes.get(name);
}

(of course you would probably want to use List's own methods instead of making your own)

TheLQ
A: 

More than you can't, you don't want to. Every enum, even Java's fairly cool enums, is code oriented.

It's exactly the same as a collection, but with an enum you tend to write duplicate code whenever you encounter it--with a collection you are more likely to write a loop.

I suggest you create a class with a private constructor and have it create the instances of itself, then provide a getInstance(String) to retrieve an instance. This is like the old typesafe enum pattern.

In the long run, however, it's better if you can manage to get enough intelligence into that class where you aren't ever differentiating on a specific instance--going from the "Enum" way of doing it:

if(myEnum.stringValue.equals("EnumTarget"))
    executeCode();

To the OO way of doing it:

myEnumLikeObject.executeCode();

Moving the code you wish into the "enum"--preferably delegating directly to a contained object that is instantiated and set into the "enum" at creation time.

Bill K
+1  A: 

It's difficult to see how any compiler could support this.

The whole point of an enum is supposed to be that you get compile-time checking of the validity of your values. If, say, you declare an enum "enum MyStatusCode {FOO, BAR, PLUGH}", then in your code if you write "MyStatusCode.FOO" everything is good, but if you write "MyStatusCode.ZORK" you get a compile-time error. This protects you from mis-spelling values or getting confused about the values for one enum versus another. (I just had a problem recently where a programmer accidentally assigned a delivery method to a transaction type, thus magically changing a sale into an inventory adjustment when he meant to change a home delivery into a customer pick-up.)

But if your values are defined dynamically at run-time, how could the compiler do this? If you wrote MyStatusCode.ZORK in the above example, there is no way the compiler could know if this value will or will not be in the database at runtime. Even if you imagined a compiler smart enough to figure out how the enum was being populated and checking the database to see if that value is present in the appropriate table NOW, it would have no way of knowing if it will be there when you actually run.

In short, what you want is something very different from an enum.

Jay