Different enums within another enum? [duplicate] - java

I'm trying to have an enum correspond to a class or return that class but I get to resolve. Is this behavior possible if I use the CommandType.SELLSHARES for it to return SellShares.class? Or can I organize the enums with different categories that inherit from the parent type?
Commands - ADMIN, USER, CLIENT
public enum CommandType {
// SELLSHARES, BUYSHARES, UPDATEUSER, ADDUSER, ADMINASSIGNMENT, BANUSER, CHANGESTATUS, REMOVEUSER
SELLSHARES (SellShares.class),
BUYSHARES (BuyShares.class);
private Class<Command> command;
CommandType(Class<Command> command) {
this.command = command;
}
private Class<Command> command() { return command; }
public static <T extends Enum<T>> T getInstance(final String value,
final Class<T> enumClass) {
return Enum.valueOf(enumClass, value);
}
}
OR
public enum CommandType {
AdminCommands,
UserCommands
}
enum AdminCommands {
UPDATEUSER,
ADDUSER,
ADMINASSIGNMENT,
BANUSER,
CHANGESTATUS,
REMOVEUSER
}
enum User {
SELLSHARES,
BUYSHARES
}
Having problem with getByType
void initialCommands() throws Exception
{
listCommands = Commands.getByType(Commands.Type.ADMIN);
for (Commands command : listCommands)
{
Command commandss = command.newInstance();
//addCommand(command.getCommand());
//log.trace(command.newInstance());
}
}

You must be looking for something like this:
public enum Commands {
UPDATE_USER(Type.ADMIN, UpdateUser.class),
ADD_USER(Type.ADMIN, AddUser.class),
ADMIN_ASSIGNMENT(Type.ADMIN, AdminAssignment.class),
BAN_USER(Type.ADMIN, BanUser.class),
CHANGE_STATUS(Type.ADMIN, ChangeStatus.class),
REMOVE_USER(Type.ADMIN, RemoveUser.class),
SELL_SHARES(Type.USER, SellShares.class),
BUY_SHARES(Type.USER, BuyShares.class);
public enum Type {
ADMIN,
USER;
}
public static List<Commands> getByType(Type type) {
List<Commands> commands = new ArrayList<Commands>();
for (Commands command : values()) {
if (command.type.equals(type)) {
commands.add(command);
}
}
return commands;
}
private final Type type;
private final Class<? extends Command> command;
private Commands(Type type, Class<? extends Command> command) {
this.type = type;
this.command = command;
}
public Class<? extends Command> getCommand() {
return command;
}
public Command newInstance() throws Exception {
return command.newInstance();
}
}
To create an instance, simply use:
Commands.UPDATE_USER.newInstance();
To get all the commands for a given type:
Commands.getByType(Commands.Type.ADMIN);
Note that using this method, the Commands subclasses must implement a public nullary constructor.

I wish to offer this advice and pattern.
Do not ever use for/while/loops on an enum.
Reduce use of if-then-else on an enum.
But exploit the fact that an enum is an efficient hashmap. Build actions into the enum so that you don't have to iterate on the enum to resolve actions due to an enum.
Avoid using if blocks to resolve the appropriate action for an enum, but build the function lambda into the enum.
Design your code to use EnumSet as much as possible to "sub class" your enum.
Redesign the flow of your code to make use of EnumSet.
Don't use the plural but Command as the enum class name. So that you'd reference a command holder as Command.ADDUSER rather than Commands.ADDUSER.
Example of using EnumSet to categorize items in the enum,
enum Command {
UPDATEUSER,
ADDUSER,
ADMINASSIGNMENT,
BANUSER,
CHANGESTATUS,
REMOVEUSER,
SELLSHARES,
BUYSHARES,
;
final static public EnumSet<AdminCommands> ADMIN = EnumSet.of(
UPDATEUSER,
ADDUSER,
ADMINASSIGNMENT,
BANUSER,
CHANGESTATUS,
REMOVEUSER
);
final static public EnumSet<AdminCommands> USER= EnumSet.of(
SELLSHARES,
BUYSHARES
);
}
Building the class constructor call, and their respective actions into the enum:
interface Commander{}
#FunctionalInterface
public interface CommanderNoArg extends Commander {
Action getAction();
}
#FunctionalInterface
public interface Commander1Arg extends Commander {
Action getAction(ActionContext ctx);
}
#FunctionalInterface
public interface Commander2Arg extends Commander {
Action getAction(ActionContext ctx, Options opts);
}
// Auxiliary casters needed due to Java's silly deficient treatment of generics
static private CommanderNoArg hasNoArg(CommanderNoArg lambd) {
return lambd;
}
static private Commander1Arg has1Arg(Commander1Arg lambd) {
return lambd;
}
static private Commander2Arg has2Args(Commander2Arg lambd) {
return lambd;
}
enum Command {
UPDATEUSER(hasNoArg(UserContext::new) ),
ADDUSER(hasNoArg(UserContext::new) ),
ADMINASSIGNMENT(has1Arg(AdminContext::new) ),
BANUSER(hasNoArg(UserContext::new) ),
CHANGESTATUS(hasNoNoArg(UserContext::new) ),
REMOVEUSER(hasNoNoArg(UserContext::new) ),
SELLSHARES(has2Args(UserContext::new) ),
BUYSHARES(has2Args(UserContext::new) ),
;
final public Commander commander;
private Command(Commander cmdr) {
this.commander = cmdr;
}
}
Where because
UserContext has constructor that requires no argument
UserContext also has constructor that requires 2 arguments
AdminContext has constructor that requires 1 argument.
You would get the Action class by, e.g.,
// AdminContext requires 1 argument
Assignment assg = getAssgFromSomewhere();
Action act =
((Commander1Arg )Command.ADMINASSIGNMENT.commander)
.getAction(assg);
Or perhaps, you could feed in lambdas of static methods into the enum items rather than a class.

Related

Generics and selecting correct interface implementation at runtime

I'm working on a PoC of an ES & CQRS system.
I have defined following classes to represent commands and events that represent an output of command being handled
public class CreateEstateCommand extends Command {}
public class ChangeEstateOwnerCommand extends Command {}
public class EstateCreatedEvent extends DomainEvent {}
public class EstateOwnerChangedEvent extends DomainEvent {}
The commands are being handled in classes that implement the following interface
/**
* Specific command handlers define what logic should be carried out during handling a command of type C.
* Single command execution results in an outcome of domain event of type E
*/
public interface CommandHandler<C extends Command, E extends DomainEvent> {
E handleCommand(C command);
}
public class EstateCreatedCommandHandler implements CommandHandler<CreateEstateCommand, EstateCreatedEvent> {
#Override
public EstateCreatedEvent handleCommand(CreateEstateCommand command) { /***/ }
}
public class ChangeEstateOwnerCommandHandler implements CommandHandler<ChangeEstateOwnerCommand, EstateOwnerChangedEvent> {
#Override
public EstateOwnerChangedEvent handleCommand(ChangeEstateOwnerCommand command) { /***/ }
}
Now there's the part where I want to use those specific handlers. The flow of command handling can be represented as follows:
Command gets into the system through the API, and they are forwarded to CommandServce class for handling
public class CommandService {
private final EventService eventService;
private final CommandGateway commandGateway;
public void handleCommand(CreateEstateCommand command) {
EstateCreatedEvent event = commandGateway.handleCommand(command);
eventService.handleEvent(event);
}
public void handleCommand(ChangeEstateOwnerCommand command) {
EstateOwnerChangedEvent event = commandGateway.handleCommand(command);
eventService.handleEvent(event);
}
}
As you can see, the handleCommand() methods are duplicated for each of the command submitted. The reason behind this is the problem I have with selecting appropriate handler implementation at runtime, depending on Command.commandType:
#Service
public class CommandGateway {
private final Map<String, CommandHandler<?, ?>> commandHandlers;
#Autowired
public CommandGateway(Map<String, CommandHandler<?, ?>> commandHandlers) {
this.commandHandlers = commandHandlers;
}
public EstateCreatedEvent handleCommand(CreateEstateCommand command) {
EstateCreatedCommandHandler handler = (EstateCreatedCommandHandler) commandHandlers.get(command.getCommandType());
return handler.handleCommand(command);
}
public EstateOwnerChangedEvent handleCommand(ChangeEstateOwnerCommand command) {
ChangeEstateOwnerCommandHandler handler = (ChangeEstateOwnerCommandHandler) commandHandlers.get(command.getCommandType());
return handler.handleCommand(command);
}
}
The snippet above is the part I cannot generify. Is it possible, to implement CommandGateway class, so CommandService can look as follows:
public class CommandService {
public <C extends Command, E extends DomainEvent> void handleCommand(C command) {
E event = commandGateway.handleCommand(command);
}
}
And provide type-safe objects?
The root problem is the map, whose values are wildcard typed, ie effectively untyped, and more particularly, not typed to align with the key.
You've already ripped up some typed safety by trusting the injected map's entries, so just take it one step further by using a raw CommandHandler, which will accept any command, and use an unchecked cast for a properly typed return value:
#SuppressWarnings({"unchecked", "rawtypes"})
public <C extends Command, E extends DomainEvent> E handleCommand(C command) {
CommandHandler handler = commandHandlers.get(command.getCommandType());
return (E)handler.handleCommand(command);
}
#SuppressWarnings added so neither your IDE nor build complain.
While this might seem brutal, you haven't actually lost any type safety. That was lost when you typed your map as you did, which unfortunately was unavoidable given that map typing does not bind the value type to the key type.
What if you do something like this:
static abstract class Command {
public abstract String getCommandType();
public abstract Class<? extends DomainEvent> type();
}
And your implementation:
public class CreateEstateCommand extends Command {
#Override
public String getCommandType() {
return null; // whatever here
}
#Override
public Class<EstateCreatedEvent> type() {
return EstateCreatedEvent.class;
}
}
And usage would be:
public DomainEvent handleCommand(Command command) {
return command.type().cast(commandHandlers.get(command.getCommandType()));
}
The difficulty in achieving this end-to-end with generics is that we are mixing runtime type decisions with compile-time type checks. You design is close to an MVC design, where handlers are retrieved at runtime. So, only limited type-safety checks are possible at compile-time.
Let us look at a flow:
An API recieves a command with its inputs
You may have a specific controller method that knows the command and its inputs and can construct one of CreateEstateCommand or ChangeEstateOwnerCommand
Now, at runtime we have to access the map to know the associated CommandHandler. Now, the very reason we have to do this at runtime is because the decision cannot be made at compile time, due to the design of using a Map.
If you have the following method in CommandGateway, it can never be sure if the Command instance passed from the service class is really the specific child that the mapped CommandHandler wants. Hence, it will not compile.
public DomainEvent handleCommand( Command command ) {
CommandHandler<? extends Command, ? extends DomainEvent> cmdHandler = commandHandlers.get(command.getCommandType());
return cmdHandler.handleCommand( command );
}
Hence, you have to do away with either the end-to-end type safety requirement or with the "factory" style map that gives you the CommandHandler instance. Leaving out the latter will mean that the API method, right in the beginning, knows which CommandHandler it needs.

Default/Mixin Generic In java

I am wondering if i can replace the generic type upon class initialization ( without inheritance ).
The case is as below .
I have bunch of generic actor + builder class in my module and distribute this to people who wants to use it in my team while keeping the actor and the entry point of fluent interface generic.
The requirement is how can people supply their own builder ( not extending ) to do the stuff they want.
Current state:
class MessageBuilder {
public MessageBuilder msg(String msg) {
//do something
}
}
class Actor {
public MessageBuilder newMessage() {
return new MessageBuilder();
}
}
class Main {
#Test
public void testActor() {
Actor actor = new Actor();
actor.newMessage().msg("sss").send();
}
}
Desired state:
class MessageBuilder{
public MessageBuilder msg(String msg) {
//do something
}
//more fluent api...
}
// project specific - dont want to extend from generic one as this should be contains its own fluent interface
class MyCustomMessageBuilder {
public MyCustomMessageBuilder rawstr(String rawstr) {
//do something
}
}
class Actor<T> {
public T newMessage() {
return (T)builderFactory.getInstance();
}
}
class Main {
#Test
public void testActor() {
Actor<MyCustomMessageBuilder> actor = new Actor(BuilderFactory);
actor.newMessage().rawstr("sss").send();
}
}
It's not possible without some known tricks.
First, Java implements Generics with type erasure (more information on type erasure), therefore the compiler will:
Replace all type parameters in generic types with their bounds or Object if the type parameters are unbounded. The produced bytecode, therefore, contains only ordinary classes, interfaces, and methods.
In practice, this means that Actor<Builder1> and Actor<Builder2> are the exact same class after it gets compiled. In both cases, newMessage is implemented as follows:
class Actor {
public Object newMessage() {
...
}
}
It's not possible for newMessage to have different implementations based on the type parameter and it's not possible for newMessage to ask for the type of T because it gets removed.
Having said that, you can pass in type information:
class Actor<T> {
private Class<T> klass;
public Actor(Class<T> klass) {
this.klass = klass;
}
public T newMessage() {
return klass.newInstance();
}
}
class Main {
#Test
public void testActor() {
Actor<MyCustomMessageBuilder> actor = new Actor<>(MyCustomMessageBuilder.class);
actor.newMessage().rawstr("sss").send();
}
}
I'd go with a factory approach. The builder should be supplied by a factory:
class Actor<MsgBuilder> {
private final Supplier<MsgBuilder> messageBuilderFactory;
public Actor(Supplier<MsgBuilder> builderFactory) {
this.messageBuilderFactory = builderFactory;
}
public MsgBuilder newMessage() {
return messageBuilderFactory.get();
}
}
This way offers flexibility in creating the message builder without sacrificing type safety and also no need for ugly casting.

Getting Enum from an integer having a Class<? extends Enum> object

I have seen this which is pretty nice solution if i had a string instead of integer, but in case all i have is the specific enum's class object and an integer, how to do i get the specific enum constant instance?
Relying on the ordinal value of Java enum constants is poor practice -- it's too easy to accidentally reorder them, which would then break your code. The better solution is to simply provide your own integer that you can use instead:
public enum MyThing {
FOO(1),
BAR(2),
BAZ(3);
private final int thingId;
private MyThing(int thingId) {
this.thingId = thingId;
}
public int getThingId() {
return thingId;
}
}
Then whenever you want to get the thingId from a MyThing, just call the getThingId() method:
void doSomething(MyThing thing) {
System.out.printf("Got MyThing object %s with ID %d\n",
thing.name(), thing.getThingId());
}
If you want to be able to look up a MyThing by its thingId, you can build a lookup table yourself and store it in a static final field:
private static final Map<Integer, MyThing> LOOKUP
= createLookupMap();
private static Map<Integer, MyThing> createLookupMap() {
Map<Integer, MyThing> lookupMap = new HashMap<>();
for (MyThing thing : MyThing.values()) {
lookupMap.put(thing.getThingId(), thing);
}
return Collections.unmodifiableMap(lookupMap);
}
public static MyThing getThingById(int thingId) {
MyThing result = LOOKUP.get(thingId);
if (result == null) {
throw new IllegalArgumentException(
"This is not a valid thingId: " + thingId);
}
return result;
}
If you end up having a lot of enum classes and you want to do a similar thing with each of them, you can define an interface for that:
public interface Identifiable {
int getId();
}
And then make your enum implement that interface:
public enum MyThing implements Identifiable {
...
#Override
public int getId() {
return thingId;
}
}
And then you could build a reusable mechanism for looking up an Identifiable object based on its ID.
seem to have found the answer :
((Class<? extends Enum>)clazz).getEnumConstants()[index]
although for any-one looking for that, you should consider following #Daniel Pryden answer as most likely that using this in most use cases i can think of is bad practice.

Can the compiler verify a generic type of an object through a generic method?

First of all, sorry for the bad title. I don't know how to describe the problem in a few words (maybe not even in many)...
I am refactoring some settings in our system to be more abstract. The current solution has multiple tables in the DB, one for each settings area. In order to add a new setting, you'll need to extend the schema, the hibernate class, all transfer object classes, getters/setters, etc. I felt that this is violating OCP (open-closed principle), thus the refactoring.
I've spent some time coming up with ideas on how to implement such an abstraction. My favourite idea so far is the following:
1 enum for each settings area
1 enum value for each setting
Each setting is a SettingsDefinition<T> class using a generic type
A SettingsService is using static get/set methods with generic types
So for example, a settings area could be:
public enum SettingsABC{
A(new SettingDefinition<Integer>("A", 123)),
B(new SettingDefinition<String>("B", "Hello")),
C(new SettingDefinition<Boolean>("C", false));
private SettingDefinition settingDefinition;
SettingsABC(SettingDefinition settingDefinition) {
this.settingDefinition = settingDefinition;
}
public SettingDefinition getDefinition() {
return settingDefinition;
}
}
Where the SettingDefinition is the following:
public class SettingDefinition<T> {
private String name;
private T defaultValue;
public SettingDefinition(String name, T defaultValue) {
this.name = name;
this.defaultValue = defaultValue;
}
public String getName() {
return name;
}
public T getDefaultValue() {
return defaultValue;
}
}
And the service to get/set the values would be:
public class SettingsService {
public static <T> T getSetting(SettingDefinition setting) {
// hit db to read
// return value
}
public static <T> void setSetting(SettingDefinition setting, T value) {
// hit db to write
}
}
And the consumer would look something like this:
String value = SettingsService.getSetting(SettingsABC.B.getDefinition());
SettingsService.setSetting(SettingsABC.A.getDefinition(), 123);
My problem is that I cannot enforce a compiler type check between the generic type of the SettingDefinition inside SettingsABC and the generic type of get/set methods of the service. So in essence, I can do this:
Integer value = SettingsService.getSetting(SettingsABC.B.getDefinition());
Where B's definition is of type String.
Also, I can do this:
SettingsService.setSetting(SettingsABC.A.getDefinition(), "A");
Where A's definition is an Integer.
Is there any way to use generics to force these two different generic types match?
You can convert the enum to the class:
public final class SettingsABC<T> {
public static final SettingsABC<Integer> A =
new SettingsABC<>(new SettingDefinition<>("A", 123));
public static final SettingsABC<String> B =
new SettingsABC<>(new SettingDefinition<>("B", "Hello"));
public static final SettingsABC<Boolean> C =
new SettingsABC<>(new SettingDefinition<>("C", false));
private final SettingDefinition<T> settingDefinition;
// private constructor, so nobody else would instantiate it
private SettingsABC(SettingDefinition<T> settingDefinition) {
this.settingDefinition = settingDefinition;
}
public SettingDefinition<T> getDefinition() {
return settingDefinition;
}
}
This way individual constants will be typed. Now you can use the type arguments for SettingService as well:
public static <T> T getSetting(SettingDefinition<T> setting) {
...
}
public static <T> void setSetting(SettingDefinition<T> setting, T value) {
...
}
Although it's not an enum anymore, it can be used mostly in the same way. If you need other methods which are usually available in enum, you can mimic them like this:
public String name() {
return settingDefinition.getName();
}
#Override
public String toString() {
return settingDefinition.getName();
}
// and so on

How can I eliminate duplicated Enum code?

I have a large number of Enums that implement this interface:
/**
* Interface for an enumeration, each element of which can be uniquely identified by its code
*/
public interface CodableEnum {
/**
* Get the element with a particular code
* #param code
* #return
*/
public CodableEnum getByCode(String code);
/**
* Get the code that identifies an element of the enum
* #return
*/
public String getCode();
}
A typical example is:
public enum IMType implements CodableEnum {
MSN_MESSENGER("msn_messenger"),
GOOGLE_TALK("google_talk"),
SKYPE("skype"),
YAHOO_MESSENGER("yahoo_messenger");
private final String code;
IMType (String code) {
this.code = code;
}
public String getCode() {
return code;
}
public IMType getByCode(String code) {
for (IMType e : IMType.values()) {
if (e.getCode().equalsIgnoreCase(code)) {
return e;
}
}
}
}
As you can imagine these methods are virtually identical in all implementations of CodableEnum. I would like to eliminate this duplication, but frankly don't know how. I tried using a class such as the following:
public abstract class DefaultCodableEnum implements CodableEnum {
private final String code;
DefaultCodableEnum(String code) {
this.code = code;
}
public String getCode() {
return this.code;
}
public abstract CodableEnum getByCode(String code);
}
But this turns out to be fairly useless because:
An enum cannot extend a class
Elements of an enum (SKYPE, GOOGLE_TALK, etc.) cannot extend a class
I cannot provide a default implementation of getByCode(), because DefaultCodableEnum is not itself an Enum. I tried changing DefaultCodableEnum to extend java.lang.Enum, but this doesn't appear to be allowed.
Any suggestions that do not rely on reflection?
Thanks,
Don
You could factor the duplicated code into a CodeableEnumHelper class:
public class CodeableEnumHelper {
public static CodeableEnum getByCode(String code, CodeableEnum[] values) {
for (CodeableEnum e : values) {
if (e.getCode().equalsIgnoreCase(code)) {
return e;
}
}
return null;
}
}
Each CodeableEnum class would still have to implement a getByCode method, but the actual implementation of the method has at least been centralized to a single place.
public enum IMType implements CodeableEnum {
...
public IMType getByCode(String code) {
return (IMType)CodeableEnumHelper.getByCode(code, this.values());
}
}
Abstract enums are potentially very useful (and currently not allowed). But a proposal and prototype exists if you'd like to lobby someone in Sun to add it:
http://freddy33.blogspot.com/2007/11/abstract-enum-ricky-carlson-way.html
Sun RFE:
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6570766
To tidy up dave's code:
public class CodeableEnumHelper {
public static <E extends CodeableEnum> E getByCode(
String code, E[] values
) {
for (E e : values) {
if (e.getCode().equalsIgnoreCase(code)) {
return e;
}
}
return null;
}
}
public enum IMType implements CodableEnum {
...
public IMType getByCode(String code) {
return CodeableEnumHelper.getByCode(code, values());
}
}
Or more efficiently:
public class CodeableEnumHelper {
public static <E extends CodeableEnum> Map<String,E> mapByCode(
E[] values
) {
Map<String,E> map = new HashMap<String,E>();
for (E e : values) {
map.put(e.getCode().toLowerCase(Locale.ROOT), value) {
}
return map;
}
}
public enum IMType implements CodableEnum {
...
private static final Map<String,IMType> byCode =
CodeableEnumHelper.mapByCode(values());
public IMType getByCode(String code) {
return byCode.get(code.toLowerCase(Locale.ROOT));
}
}
I had a similar issue with a localization component that I wrote. My component is designed to access localized messages with enum constants that index into a resource bundle, not a hard problem.
I found that I was copying and pasting the same "template" enum code all over the place. My solution to avoid the duplication is a code generator that accepts an XML configuration file with the enum constant names and constructor args. The output is the Java source code with the "duplicated" behaviors.
Now, I maintain the configuration files and the generator, not all of the duplicated code. Everywhere I would have had enum source code, there is now an XML config file. My build scripts detect out-of-date generated files and invoke the code generator to create the enum code.
You can see this component here. The template that I was copying and pasting is factored out into an XSLT stylesheet. The code generator runs the stylesheet transformation. An input file is quite concise compared to the generated enum source code.
HTH,
Greg
Unfortunately, I don't think that there is a way to do this. Your best bet would pro ably be to give up in emums altogether and use conventional class extension and static members. Otherwise, get used to duplicating that code. Sorry.
Create a type-safe utility class which will load enums by code:
The interface comes down to:
public interface CodeableEnum {
String getCode();
}
The utility class is:
import java.lang.reflect.InvocationTargetException;
public class CodeableEnumUtils {
#SuppressWarnings("unchecked")
public static <T extends CodeableEnum> T getByCode(String code, Class<T> enumClass) throws IllegalArgumentException, SecurityException, IllegalAccessException, InvocationTargetException, NoSuchMethodException {
T[] allValues = (T[]) enumClass.getMethod("values", new Class[0]).invoke(null, new Object[0]);
for (T value : allValues) {
if (value.getCode().equals(code)) {
return value;
}
}
return null;
}
}
A test case demonstrating usage:
import junit.framework.TestCase;
public class CodeableEnumUtilsTest extends TestCase {
public void testWorks() throws Exception {
assertEquals(A.ONE, CodeableEnumUtils.getByCode("one", A.class));
assertEquals(null, CodeableEnumUtils.getByCode("blah", A.class));
}
enum A implements CodeableEnum {
ONE("one"), TWO("two"), THREE("three");
private String code;
private A(String code) {
this.code = code;
}
public String getCode() {
return code;
}
}
}
Now you are only duplicating the getCode() method and the getByCode() method is in one place. It might be nice to wrap all the exceptions in a single RuntimeException too :)
Here I have another solution:
interface EnumTypeIF {
String getValue();
EnumTypeIF fromValue(final String theValue);
EnumTypeIF[] getValues();
class FromValue {
private FromValue() {
}
public static EnumTypeIF valueOf(final String theValue, EnumTypeIF theEnumClass) {
for (EnumTypeIF c : theEnumClass.getValues()) {
if (c.getValue().equals(theValue)) {
return c;
}
}
throw new IllegalArgumentException(theValue);
}
}
The trick is that the inner class can be used to hold "global methods".
Worked pretty fine for me. OK, you have to implement 3 Methods, but those methods,
are just delegators.
It seems like you are actually implementing run time type information. Java provides this as a language feature.
I suggest you look up RTTI or reflection.
I don't think this is possible. However, you could use the enum's valueOf(String name) method if you were going to use the enum value's name as your code.
How about a static generic method? You could reuse it from within your enum's getByCode() methods or simply use it directly. I always user integer ids for my enums, so my getById() method only has do do this: return values()[id]. It's a lot faster and simpler.
If you really want inheritance, don't forget that you can implement the enum pattern yourself, like in the bad old Java 1.4 days.
About as close as I got to what you want was to create a template in IntelliJ that would 'implement' the generic code (using enum's valueOf(String name)). Not perfect but works quite well.
In your specific case, the getCode() / getByCode(String code) methods seems very closed (euphemistically speaking) to the behaviour of the toString() / valueOf(String value) methods provided by all enumeration. Why don't you want to use them?
Another solution would be not to put anything into the enum itself, and just provide a bi-directional map Enum <-> Code for each enum. You could e.g. use ImmutableBiMap from Google Collections for this.
That way there no duplicate code at all.
Example:
public enum MYENUM{
VAL1,VAL2,VAL3;
}
/** Map MYENUM to its ID */
public static final ImmutableBiMap<MYENUM, Integer> MYENUM_TO_ID =
new ImmutableBiMap.Builder<MYENUM, Integer>().
put(MYENUM.VAL1, 1).
put(MYENUM.VAL2, 2).
put(MYENUM.VAL3, 3).
build();
In my opinion, this would be the easiest way, without reflection and without adding any extra wrapper to your enum.
You create an interface that your enum implements:
public interface EnumWithId {
public int getId();
}
Then in a helper class you just create a method like this one:
public <T extends EnumWithId> T getById(Class<T> enumClass, int id) {
T[] values = enumClass.getEnumConstants();
if (values != null) {
for (T enumConst : values) {
if (enumConst.getId() == id) {
return enumConst;
}
}
}
return null;
}
This method could be then used like this:
MyUtil.getInstance().getById(MyEnum.class, myEnumId);

Categories

Resources