package net.sourceforge.javautil.ui.command;
import java.util.LinkedHashMap;
import java.util.Map;
import net.sourceforge.javautil.common.exception.ThrowableManagerRegistry;
import net.sourceforge.javautil.common.reflection.cache.ClassCache;
import net.sourceforge.javautil.common.reflection.cache.ClassDescriptor;
import net.sourceforge.javautil.common.reflection.cache.ClassMethod;
import net.sourceforge.javautil.common.reflection.cache.ClassProperty;
import net.sourceforge.javautil.ui.command.annotation.Argument;
import net.sourceforge.javautil.ui.command.annotation.Command;
import net.sourceforge.javautil.ui.command.annotation.Execution;
import net.sourceforge.javautil.ui.command.annotation.Flag;
import net.sourceforge.javautil.ui.command.annotation.Option;
/**
* This will instantiate a new instance of the {@link ClassDescriptor} and call its {@link Execution} method.
*
* @author elponderador
* @author $Author: ponderator $
* @version $Id: UICommandClass.java 912 2009-09-09 20:43:46Z ponderator $
*/
public class UICommandClass<CTX extends UICommandContext, ARG extends UICommandArguments> extends UICommandAbstract<CTX, ARG> {
/**
* @param clazz A class that must have a {@link Command} set on it.
* @return A command class for the target class, or null if the class passed does not have the required annotation
*/
public static UICommandClass getFor (Class clazz) {
Command command = (Command) clazz.getAnnotation(Command.class);
if (command == null) return null;
return new UICommandClass(command, ClassCache.getFor(clazz));
}
protected ClassDescriptor descriptor;
protected ClassMethod execute;
protected Command command;
public UICommandClass(Command command, ClassDescriptor descriptor) {
this(command.name(), command.value(), descriptor);
}
/**
* @param name The name of the command
* @param description The description of the command
* @param descriptor A descriptor that must have an {@link Execution} annotation on one of its methods.
*/
public UICommandClass(String name, String description, ClassDescriptor descriptor) {
super(name, description);
this.descriptor = descriptor;
this.execute = descriptor.getMethod(Execution.class);
if (this.execute == null)
throw new IllegalArgumentException("Not a command class: " + descriptor);
this.getArgumentDefs();
}
public Object execute(CTX ctx, ARG arguments) {
try {
Object executor = descriptor.newInstance();
// TODO: finish implementing this
return execute.invoke(executor, ctx);
} catch (Throwable t) {
throw ThrowableManagerRegistry.caught(new UICommandException(this, t));
}
}
private void getArgumentDefs () {
ClassProperty[] properties = descriptor.getProperties(Argument.class);
for (ClassProperty property : properties) {
Argument argument = property.getAnnotation(Argument.class);
String name = "".equals(argument) ? property.getName() : argument.name();
this.addArgument(name, property.getType(), argument.value());
}
properties = descriptor.getProperties(Option.class);
for (ClassProperty property : properties) {
Option option = property.getAnnotation(Option.class);
String name = "".equals(option) ? property.getName() : option.name();
this.addOption(name, property.getType(), option.desc(), option.defaultDesc());
}
properties = descriptor.getProperties(Flag.class);
for (ClassProperty property : properties) {
Flag flag = property.getAnnotation(Flag.class);
String name = "".equals(flag) ? property.getName() : flag.name();
this.addFlag(name, flag.value(), flag.defaultValue());
}
}
}