Reputation: 1605
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());
}
}
Upvotes: 3
Views: 5121
Reputation: 21664
I wish to offer this advice and pattern.
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
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.
Upvotes: 0
Reputation: 48827
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.
Upvotes: 1