0

Consider below inner Enum implementing an interface:

public interface NotificationTypes {

    public enum CONTACT_LIST implements NotificationTypes{
        ADDED("CONTACT_LIST-ADDED"),
        REMOVED("CONTACT_LIST-REMOVED");
        public enum INVITATION implements NotificationTypes{
            ACCEPTED("CONTACT_LIST-INVITATION-ACCEPTED"),
            REJECTED("CONTACT_LIST-INVITATION-REJECTED");

            String name = "";
            private INVITATION(String name){
                this.name = name;
            }

            public String getName(){
                return name;
            }
        };

        String name = "";
        private CONTACT_LIST(String name){
            this.name = name;
        }

        public String getName(){
            return name;
        }
    }
    public String getName();
}

Now consider that data in database/mongodb is stored in the form of String for NotificationTypes in a table/document.

{
    "_id" : ObjectId("59882ba49e5d82c72ba44fde"),
    "template" : "Contact list Invitation accepted by your friend",
    "type" : "CONTACT_LIST-INVITATION-ACCEPTED"
}

So my question is: How to convert that string back into specific enum at runtime without knowing exactly the name of enum to be mapped?

Domain class is looks like this:

@Document(collection = CollectionNames.XXX_TEMPLATE)
public class XXXTemplate {

    private NotificationTypes type;
    //Other parameters, getters & setters + Constructor
}
Afridi
  • 6,753
  • 2
  • 18
  • 27

3 Answers3

1

I'd build a Map<String, NotificationTypes> and populate that with all instances you have. You can then look up from that map.

I don't think the compiler can help you a lot with keeping that in sync, other than that you can loop over EnumType.values() (but you have to remember to do it for all of your enum types).

Thilo
  • 257,207
  • 101
  • 511
  • 656
  • Ok thanks for reply. But in case if I have nested enums upto 3-4 levels, then I have to loop through all enums, isn't?? Is there any short way to loop through all enums implementing given interface(NotificationTypes)? – Afridi Aug 07 '17 at 10:05
  • 1
    No, you have to build that map (statically, spelling out all types in source code). But then the lookup from that map is trivial and fast. – Thilo Aug 07 '17 at 10:07
  • If you really, really want to have code find all implementations of your interface: https://stackoverflow.com/questions/347248/how-can-i-get-a-list-of-all-the-implementations-of-an-interface-programmatically But don't. Live with the map or rethink your design. – Thilo Aug 07 '17 at 10:09
0

How to convert that string back into specific enum at runtime without knowing exactly the name of enum to be mapped?

Via Enum.valueOf().

user207421
  • 305,947
  • 44
  • 307
  • 483
  • 1
    But for that you need to know which kind of `enum` it is. And it works with the identifier, not with the custom `name`. – Thilo Aug 07 '17 at 09:55
  • @EJP thanks for replay. But this method requires enum type as well, and I don't know about that it runtime. There are so many inner enums implementing same interface. – Afridi Aug 07 '17 at 09:59
  • 1
    @Afridi Then you've designed yourself into a corner that isn't supported by the language. – user207421 Aug 07 '17 at 10:02
0

Basically just building on @Thilo's answer, but perhaps a more 'Springified' way if it's something that you'd want - you could define a @Bean in your config that contains all your enum values, like:

@Configuration
public class Config {
    @Bean
    public List<NotificationTypes> notificationTypes() {
        List<NotificationTypes> notificationTypes = new ArrayList<>();

        notificationTypes.addAll(Arrays.asList(NotificationTypes.CONTACT_LIST.values()));
        notificationTypes.addAll(Arrays.asList(NotificationTypes.CONTACT_LIST.INVITATION.values()));

        return notificationTypes;
    }
}

And then @Autowire this @Bean into a parser to do the actual matching of String to enum, something like:

@Component
public class NotificationTypeParser {
    @Autowired
    private List<NotificationTypes> notificationTypes;

    public NotificationTypes parseNotificationType(String type) {
        for (NotificationTypes notificationType : notificationTypes) {
            if (notificationType.getName().equals(type)) {
                return notificationType;
            }
        }
        return null;
    }
}

Obviously you probably want something better than just returning null if the enum isn't found, and you could potentially do something smarter in the @Bean definition to validate that the enums all have different names, etc. Or, conceivably, use reflection in there to find all the implementations of NotificationTypes.

I'm not sure that this really gives you any additional benefits over just storing all the possible values in a Map, but, as I say, I suppose it's a bit Spring-ier.

DaveyDaveDave
  • 9,821
  • 11
  • 64
  • 77