1

I have a use case where I would like to access an enum instance with an alias of that enum.

The reason that I would like to access the enum instance with an alias is to allow accessing a value of an enum with non English characters (my specific use case is Hebrew).

The thing is that this is part of a framework and I need to be able to add multiple aliases to any given enum. It is needed to allow more natural language, as for the alias given would be used as part of a specification (gauge-java).

Any suggestions on how to do it properly?

EDIT: I'm adding an example:

Go to "בית"

this is a step that would be mapped to a method:

@Step("Go to <page>")
public void goToPage(Page page) {...}
Boaz Berman
  • 230
  • 4
  • 13
  • 2
    The requirement isn't quite clear (at least to me). Could you share some pseudo-code of what you'd like to achieve here? – Mureinik Jan 05 '17 at 20:28
  • 1
    You can do something like this: `enum E { A, B; static final E C = A, D = B; }`. Or you can use string aliases and a map lookup. – shmosel Jan 05 '17 at 20:34
  • @Mureinik Well gauge is meant to allow creating a running specifications writen in natural language. As such I would like to allow: 'in page "home" do stuff'. That will be mapped to a method whose signature is: @Step("in page do stuff") public void doStuffInPage(Page page) But in my use case I need the page to be in Hebrew. Therefor I need an alias for the enum. – Boaz Berman Jan 05 '17 at 20:37
  • @shmosel Well I cant because you can only use English letters for that, and I need Hebrew letters. – Boaz Berman Jan 05 '17 at 20:38
  • You should be able to use Hebrew for either of my suggestions. – shmosel Jan 05 '17 at 20:40
  • @shmosel The thing is that I need a generic solution that will allow me to lookup an enum instance by its name or alias. At the moment the lookup is made by Enum.valueOf(E.class, "A"), which in neither of your suggestions would work. – Boaz Berman Jan 05 '17 at 20:50
  • [Java identifiers can contain non-English characters.](http://stackoverflow.com/questions/1422655/java-unicode-variable-names) – Kevin Krumwiede Jan 05 '17 at 20:50
  • @KevinKrumwiede I was wrong, this is not the problem with this solution. Check my last comment. – Boaz Berman Jan 05 '17 at 20:53

2 Answers2

2

Enums can contain static and instance fields and have constructors like any other class:

enum Foo {
    A("alias1", "alias2"),
    B("alias3");

    private static final Map<String, Foo> gAliases = new HashMap<>();

    private Foo(String... aliases) {
        for(final String alias : aliases) {
            gAliases.put(alias, this);
        }
    }

    public static Foo forAlias(String alias) {
        return gAliases.get(alias);
    }
}

You could also omit the constructor and populate the alias map in a static initializer. But I like how the constructor makes it easy to read and maintain which aliases correspond to which constants.

Kevin Krumwiede
  • 9,868
  • 4
  • 34
  • 82
  • Yes, I'm aware of that, but I need a solution that will fit any Enum. Static methods are not a solution that would fit multiple Enums at once. – Boaz Berman Jan 05 '17 at 21:07
  • @BoazBerman Mapping aliases to multiple enum types would seem to defeat the purpose of the strong typing provided by enums. – Kevin Krumwiede Jan 05 '17 at 21:09
  • Enums can also implement interfaces, so you could have several that implement the same interface, and put the alias map in some utility class. – Kevin Krumwiede Jan 05 '17 at 21:12
  • Why? In gauge I would like to enable the QA that is writing the specification to use as natural language as possible, and as the developer which is implementing the steps I would like to avoid handling multiple variations of the same thing. If enum is not the solution, then what is? – Boaz Berman Jan 05 '17 at 21:13
  • I've thought of the use of an Interface, but I've came to seek wisdom as for what would be best. Any specific suggestion on how to do it the best way possible? I would love to see some code... – Boaz Berman Jan 05 '17 at 21:16
1

Since enum values are not good for specification by means of readability then you want to replace them with readable words. According to documentation you can pass enum as step parameter but in your case you can pass string as you want and then in the step method just to create enum from string using Factory class:

public class MyEnumUtil {

    private MyEnumUtil() {}

    public static MyEnum fromHerbew(String stringValue) {
        switch (stringValue) {
            case "צָפוֹן,": return MyEnum.NORTH;
            case "מזרח,": return MyEnum.EAST;
            case " מַעֲרָב,": return MyEnum.WEST;
            case "  דָרוֹם": return MyEnum.SOUTH;
            default: return null;
        }
    }
}

Then your step will be (of course in Herbew)

@Step("Navigate towards <directionString>")
public void navigate(String directionString) {
    MyEnum direction = MyEnumUtil.fromHerbew(directionString);
    // use enum
}
Dmitry Gorkovets
  • 2,208
  • 1
  • 10
  • 19
  • Yep, but comming from the framework side I would like to save users the need to do it. I would like to create a solution that would allow this ability without then need to write that boilerplate code. – Boaz Berman Jan 05 '17 at 20:58
  • I don't see the whole picture but in this case you can move aliases to property file and map Herbew variant with actual enum value there. – Dmitry Gorkovets Jan 05 '17 at 21:00
  • Yep, but that is not an elegant solution I would expect from a framework. I would like a solution where the user of the framework (a developer) would need to write as less code (files such as property file are even worse) as possible to get that functionality. – Boaz Berman Jan 05 '17 at 21:03