/** * Register an class that contains commands (denoted by {@link Command}. If no dependency injector * is specified, then the methods of the class will be registered to be called statically. * Otherwise, new instances will be created of the command classes and methods will not be called * statically. * * @param cls */ public void register(Class<?> cls) { registerMethods(cls, null); }
/** * Register the methods of a class. * * @param cls * @param parent * @param obj * @return */ private List<Command> registerMethods(Class<?> cls, Method parent, Object obj) { Map<String, Method> map; List<Command> registered = new ArrayList<Command>(); // Make a new hash map to cache the commands for this class // as looking up methods via reflection is fairly slow if (commands.containsKey(parent)) { map = commands.get(parent); } else { map = new HashMap<String, Method>(); commands.put(parent, map); } for (Method method : cls.getMethods()) { if (!method.isAnnotationPresent(Command.class)) { continue; } boolean isStatic = Modifier.isStatic(method.getModifiers()); Command cmd = method.getAnnotation(Command.class); // Cache the aliases too for (String alias : cmd.aliases()) { map.put(alias, method); } // We want to be able invoke with an instance if (!isStatic) { // Can't register this command if we don't have an instance if (obj == null) { continue; } instances.put(method, obj); } // Build a list of commands and their usage details, at least for // root level commands if (parent == null) { final String commandName = cmd.aliases()[0]; final String desc = cmd.desc(); final String usage = cmd.usage(); if (usage.length() == 0) { descs.put(commandName, desc); } else { descs.put(commandName, usage + " - " + desc); } String help = cmd.help(); if (help.length() == 0) { help = desc; } final CharSequence arguments = getArguments(cmd); for (String alias : cmd.aliases()) { final String helpMessage = "/" + alias + " " + arguments + "\n\n" + help; final String key = alias.replaceAll("/", ""); String previous = helpMessages.put(key, helpMessage); if (previous != null && !previous .replaceAll("^/[^ ]+ ", "") .equals(helpMessage.replaceAll("^/[^ ]+ ", ""))) { helpMessages.put(key, previous + "\n\n" + helpMessage); } } } // Add the command to the registered command list for return registered.add(cmd); // Look for nested commands -- if there are any, those have // to be cached too so that they can be quickly looked // up when processing commands if (method.isAnnotationPresent(NestedCommand.class)) { NestedCommand nestedCmd = method.getAnnotation(NestedCommand.class); for (Class<?> nestedCls : nestedCmd.value()) { registerMethods(nestedCls, method); } } } if (cls.getSuperclass() != null) { registerMethods(cls.getSuperclass(), parent, obj); } return registered; }