Reputation: 1461
I'm writing a IRC bot that responds to commands like !time
, !sayHello
and similar. One of the challenges I've had is that parsing these commands ended up with a long if/else bundle. To get around this problem of a big if/else tumble, I'm trying to use annotations to add extra commands into the bot, this makes the code look far cleaner and is easier to maintain and extend.
It looks like this;
public class ExampleChatPlugin extends Plugin {
@CommandMessage(command="!time")
public void handleTime(Bot bot, String channel, Command fullMessage) {
bot.sendMessage(channel, "I don't know the time :(");
}
@CommandMessage(command="!sayHello")
public void handleSayHello(Bot bot, String channel, Command fullMessage) {
bot.sendMessage(channel, "Oh, hi there.");
}
// etc...
}
So! I have message handling method in the superclass Plugin
that works out which method to call when a message is received. This method is here;
public void callCommandMessages(String channel, String sender, String input) {
Command command = new Command(input);
for (Method m : this.getMethodsWithAnnotation()) {
String keyword = m.getAnnotation(CommandMessage.class).keyword();
if (keyword.isEmpty()) {
keyword = m.getName();
}
if (command.supportsKeyword(keyword)) {
if (m.getGenericParameterTypes().length < 4) {
MessagePlugin.LOG.debug("InputSelector method found for " + input + ", but this method needs to 4 arguments");
} else {
try {
m.invoke(this, channel, sender, command);
return;
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
System.out.println("Could not find: " + input);
}
So, my problem is that this method checks if the @CommandMessage
method takes 4 parameters, but this isn't very strict and most importantly it's only detected at runtime. It sucks!
Is there I way that I get get an annotated method to be forced to have the parameters Bot bot, String channel, String sender, Command command
I know the most obvious way would be an interface as that is precisely what they were designed for, but this means having a class for every single @CommandMessage
and that really sucks too.
Upvotes: 2
Views: 96
Reputation: 2365
I'd recommend a soltution like this:
public interface PluginMethod {
void execute(Bot bot, Channel channel, Sender sender, Command command);
String getCommand();
}
public interface Plugin {
List<PluginMethod> getPluginMethods();
}
Not so fancy as with annotaitons but you enforce that each method uses the 4-Attribute-Interface.
Upvotes: 1
Reputation: 5197
Is there I way that I get get an annotated method to be forced to have the parameters Bot bot, String channel, String sender, Command command
I can't immediately think of actually enforcing this in a standard way. I have however "solved" similar things by writing unit tests that check these kind of things by using reflection and package scanning.
@CommandMessage
annotation is present check if the method signature is correctHowever this depends on a continuous integration workflow, specifically that a build of your code only succeeds when all tests run successfully.
Upvotes: 0