samedi 2 mai 2020

Convert string to enum value using reflection, where the enum type can be any of several

Suppose I have a class that takes another object as an id:

public SomeClass
{
    private final ID id;

    ...
}

ID is then defined as below. Note that the reason that the enum is split up (into logical groupings) is because a single enum would otherwise contain 1000+ values. The interface is then necessary to still have all the enums fall under the same type.

public interface ID
{
    public enum Name1 implements ID { ... constants ... }
    public enum Name2 implements ID { ... constants ... }
    public enum Name3 implements ID { ... constants ... }

    ...
}

And an object of SomeClass is constructed like so:

SomeClass object = new SomeClass(ID.Name2.SOME_VALUE, ... more parameters};

However, the parameters necessary to construct the SomeClass object are stored in a json file, like so:

{
    "id": "SOME_VALUE",

    ...
}

What I want to do is to map the string "SOME_VALUE" to ID.Name2.SOME_VALUE. Now, I could do this by having a giant map:

Map<String, ID> conversionMap = HashMap<>();
conversionMap.put("SOME_VALUE", ID.Name2.SOME_VALUE);
conversionMap.put("SOME_OTHER_VALUE", ID.Name3.SOME_OTHER_VALUE);
... etc

but I want to do it automatically using reflection from a static method inside the ID interface (some very rough pseudocode):

public interface ID
{
    public static ID getIdFromString(String key)
    {
        List<Enum> declaredEnums = ID.class.getDeclaredEnums();
        for (Enum declaredEnum : declaredEnums)
        {
            for (EnumValue value : declaredEnum)
            {
                if (value.equals(key)
                    return value;
            }
        }
    }

    public enum Name1 implements ID { ... constants ... }
    public enum Name2 implements ID { ... constants ... }
    public enum Name3 implements ID { ... constants ... }

    ...
}

How would I do such a thing? I am getting lost in the reflection here, and having searched through many other questions and answers I still seem to not be any closer to the answer.

Note that I could also implement this using 1000+ integer constants and providing a string > integer mapping for that, but using enums feels cleaner. Now that I have hit this snag I am not so convinced of the cleanliness anymore though.





Aucun commentaire:

Enregistrer un commentaire