package org.cryptocoinpartners.command;
import org.apache.commons.lang.StringUtils;
import org.cryptocoinpartners.module.Context;
import org.cryptocoinpartners.util.Injector;
import org.cryptocoinpartners.util.ReflectionUtil;
import org.reflections.Reflections;
import javax.inject.Inject;
import java.lang.reflect.Modifier;
import java.util.*;
/**
* @author Tim Olson
*/
public abstract class CommandBase implements Command {
@Override
public String getUsageHelp() { return StringUtils.join(getCommandNames(getClass()),"|"); }
@Override
public void parse(String commandArguments) { }
// these 2 are injected by ConsoleRunMode
@Inject
protected Context context;
@Inject
protected ConsoleWriter out;
@Inject
protected Injector injector;
public static List<String> allCommandNames() {
ArrayList<String> names = new ArrayList<>(commandClassesByName.keySet());
Collections.sort(names);
return names;
}
public static Command commandForName( String name, Context context ) {
Class<? extends Command> commandClass = commandClassesByName.get(name.toLowerCase());
if( commandClass == null )
return null;
return context.attach(commandClass);
}
private static Map<String,Class<? extends Command>> commandClassesByName;
static {
commandClassesByName = new HashMap<>();
Reflections reflections = ReflectionUtil.getCommandReflections();
Set<Class<? extends Command>> commandClasses = reflections.getSubTypesOf(Command.class);
for( Class<? extends Command> commandClass : commandClasses ) {
int modifiers = commandClass.getModifiers();
if( Modifier.isAbstract(modifiers) || Modifier.isInterface(modifiers) )
continue;
for( String commandName : getCommandNames(commandClass) )
commandClassesByName.put(commandName.toLowerCase(),commandClass);
}
}
private static String[] getCommandNames(Class<? extends Command> commandClass) {
String[] commandNames;
String className;
CommandName commandNameAnn = commandClass.getAnnotation(CommandName.class);
if( commandNameAnn != null ) {
commandNames = commandNameAnn.value();
}
else {
className = commandClass.getSimpleName();
if( !className.endsWith("Command") ) {
throw new Error("If the name of your subclass of CommandBase doesn't end with \"Command\" then you need to use the @CommandName(name) annotation to declare the name of your command");
}
commandNames = new String[]{className.substring(0,className.length() - "Command".length()).toLowerCase()};
}
return commandNames;
}
}