Package net.sourceforge.javautil.ui.command

Source Code of net.sourceforge.javautil.ui.command.UICommandMethod

package net.sourceforge.javautil.ui.command;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import net.sourceforge.javautil.common.ReflectionUtil;
import net.sourceforge.javautil.common.exception.ThrowableManagerRegistry;
import net.sourceforge.javautil.common.reflection.cache.ClassMethod;
import net.sourceforge.javautil.common.reflection.cache.ClassProperty;
import net.sourceforge.javautil.ui.UserInterfaceException;
import net.sourceforge.javautil.ui.command.UICommandArguments.PassedArgument;
import net.sourceforge.javautil.ui.command.UICommandArguments.PassedOption;
import net.sourceforge.javautil.ui.command.annotation.Argument;
import net.sourceforge.javautil.ui.command.annotation.Command;
import net.sourceforge.javautil.ui.command.annotation.Flag;
import net.sourceforge.javautil.ui.command.annotation.Option;

/**
* This will use a {@link ClassMethod} as the target for the command. The
* parameters can be defined as {@link Argument}'s, {@link Option}'s or
* {@link Flag}'s. This will also inject the context into the instance
* if a getter/setter exists on the class for the type {@link UICommandContext}
* or one of it's sub classes.
*
* @author elponderador
* @author $Author: ponderator $
* @version $Id: UICommandMethod.java 1527 2009-11-30 23:40:46Z ponderator $
*/
public class UICommandMethod<CTX extends UICommandContext, ARG extends UICommandArguments> extends UICommandAbstract<CTX, ARG> {
 
  protected final Object instance;
  protected final ClassMethod method;
  protected final UICommandSetClass set;
  protected List<String> defs = new ArrayList<String>();
  protected ClassProperty contextProperty;
  protected Command command;

  public UICommandMethod(UICommandSetClass set, Object instance, ClassMethod method, String name, String description) {
    super(name, description);
    this.set = set;
    this.method = method;
    this.instance = instance;
    this.getArgumentDefs(this.command = method.getAnnotation(Command.class));
   
    this.contextProperty = method.getDescriptor().getProperty(net.sourceforge.javautil.ui.command.annotation.UICommandContext.class);
    if (this.contextProperty != null && !UICommandContext.class.isAssignableFrom( this.contextProperty.getType() ))
      throw new IllegalArgumentException("Context properties must be a sub class of UICommandContext");
  }

  public Object execute(CTX ctx, ARG arguments) {
    try {
      if (this.contextProperty != null) this.contextProperty.setValue(instance, ctx);
      return method.invoke(instance, arguments == null ? new Object[method.getParameterTypes().length] : this.mapArgumentDefs(arguments));
    } catch (UICommandException e) {
      throw ThrowableManagerRegistry.caught(e);
    } catch (UserInterfaceException e) {
      throw ThrowableManagerRegistry.caught(e);
    } catch (Exception e) {
      throw ThrowableManagerRegistry.caught(new UICommandException(this, e));
    }
  }
 
  /**
   * @param arguments The passed command line arguments
   * @return The array of values for the arguments
   */
  protected Object[] mapArgumentDefs (ARG arguments) {
    Object[] newargs = new Object[defs.size()];
    Class[] types = method.getParameterTypes();
   
    Argument[] args = command.arguments();
    Option[] options = command.options();
    Flag[] flags = command.flags();
   
    for (int a=0; a<newargs.length; a++) {
      String def = defs.get(a);
      Class type = types[a];
      Object value = null;
     
      boolean required = false;
      if (a >= args.length) {
        int offset = a - args.length;
        if (offset >= options.length) {
          offset = offset - options.length;
          if (offset < flags.length) {
            value = arguments.isEnabled(def);
          }
        } else {
          Option opt = options[offset];
          PassedOption option = arguments.getOption(def);
          value = option == null ? null : option.getValue();
        }
      } else {
        PassedArgument pa = arguments.getArgument(a);
        if (pa == null) throw new IllegalArgumentException("Missing argument: " + a);
       
        required = true;
        value = pa.getValue();
      }
     
      if (value == null && type.isPrimitive()) newargs[a] = ReflectionUtil.getPrimitiveDefault(type);
      else newargs[a] = value == null ? null : set.convert(value, type);
     
      if (required && newargs[a] == null) throw new UICommandException(this, "Argument missing or invalid: " + def);
    }
    return newargs;
  }
 
  /**
   * Preprocess what arguments are expected
   */
  protected void getArgumentDefs (Command command) {
    Class[] types = method.getParameterTypes();
   
    Argument[] args = command.arguments();
    Option[] options = command.options();
    Flag[] flags = command.flags();
   
    for (int t=0; t<types.length; t++) {
      Class type = types[t];

      if (t >= args.length) {
        int offset = t - args.length;
        if (offset >= options.length) {
          offset = offset - options.length;
          if (offset >= flags.length) break;
         
          Flag fla = flags[offset];
          if (fla != null) {
            if (type != boolean.class && type != Boolean.class)
              throw new IllegalArgumentException("Invalid flag definition, can only be used on boolean types");
           
            defs.add(fla.name());
            this.addFlag(fla.name(), fla.value(), fla.defaultValue());
          }
        } else {
          Option opt = options[offset];
          defs.add(opt.name());
          this.addOption(opt.name(), type, opt.desc(), opt.defaultDesc());
        }
      } else {
        Argument arg = args[t];
        defs.add(arg.name());
        this.addArgument(arg.name(), type, arg.value());
      }
    }
  }

}
TOP

Related Classes of net.sourceforge.javautil.ui.command.UICommandMethod

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.