Package net.sourceforge.javautil.groovy.dsl.impl.standard

Source Code of net.sourceforge.javautil.groovy.dsl.impl.standard.GroovyDSLCategoryClass

package net.sourceforge.javautil.groovy.dsl.impl.standard;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import groovy.lang.MetaClass;
import net.sourceforge.javautil.common.CollectionUtil;
import net.sourceforge.javautil.common.ReflectionUtil;
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.groovy.dsl.GroovyDSL;
import net.sourceforge.javautil.groovy.dsl.GroovyDSLMethod;
import net.sourceforge.javautil.groovy.dsl.GroovyDSLProperty;

import org.codehaus.groovy.runtime.GroovyCategorySupport;

/**
* A groovy DSL based on the {@link GroovyCategorySupport} pattern. It also
* allows new properties via static property getter/setter pattern.
*
* @author elponderador
* @author $Author$
* @version $Id$
*/
public class GroovyDSLCategoryClass implements GroovyDSL {
 
  protected final Class<?>[] classes;
  protected final Map<String, List<ClassDescriptor>> lookup = new HashMap<String, List<ClassDescriptor>>();
  protected final Map<String, GroovyDSLCategoryProperty> properties = new HashMap<String, GroovyDSLCategoryProperty>();
 
  public GroovyDSLCategoryClass (Class<?>... categoryClasses) {
    Set<Class<?>> classes = new LinkedHashSet<Class<?>>();
   
    for (Class<?> categoryClass : categoryClasses) {
      ClassDescriptor cd = ClassCache.getFor(categoryClass);
      Map<String, List<ClassMethod>> methodMap = cd.getMethods();
      for (String name : methodMap.keySet()) {
        boolean property = name.startsWith("get") && name.length() > 3 || name.startsWith("is") && name.length() > 2;
       
        String setterName = null;
        String getterName = null;
        String propertyName = null;
        if (property) {
          getterName = name;
          setterName = name.startsWith("is") ? name.substring(2) : name.substring(3);
          propertyName = setterName.length() > 1 ? setterName.substring(0, 1).toLowerCase() + setterName.substring(1) : setterName.toLowerCase();
          setterName = "set" + setterName;
        }
       
        List<ClassMethod> methods = methodMap.get(name);
        for (ClassMethod method : methods) {
          if (method.isStatic() && method.getParameterTypes().length > 0) {
            Class forType = method.getParameterTypes()[0];
            this.addCategory(classes, forType, cd);
           
            if (forType.isPrimitive() || ReflectionUtil.isBoxedType(forType))
              this.addCategory(classes, forType.isPrimitive() ? ReflectionUtil.getBoxedType(forType) : ReflectionUtil.getPrimitiveType(forType), cd);
           
            if (property && method.getParameterTypes().length == 1) {
              ClassMethod setter = null;
              for (ClassMethod setterp : cd.getMethods(setterName)) {
                if (setterp.getParameterTypes().length == 2 && setterp.getParameterTypes()[0] == forType && setterp.getParameterTypes()[1] == method.getReturnType()) {
                  setter = setterp; break;
                }
              }
              this.properties.put(forType.getName() + ":" + propertyName, new GroovyDSLCategoryProperty(method, setter));
            }
          }
        }
      }
    }
   
    this.classes = classes.toArray(new Class<?>[classes.size()]);
  }

  public Class<?>[] getForClasses() { return this.classes; }

  public GroovyDSLMethod getMethod(MetaClass clazz, Object instance, String name, Object... arguments) {
    List<ClassDescriptor> categories = this.lookup.get(instance instanceof Class ? "java.lang.Class" : clazz.getTheClass().getName());
    for (int i=0; i<categories.size(); i++) {
      ClassMethod method = categories.get(i).findMethod(name, CollectionUtil.insert(arguments, 0, instance));
      if (method != null) return new GroovyDSLCategoryMethod(method);
    }
    return null;
  }

  public GroovyDSLProperty getProperty(MetaClass clazz, Object instance, String name) {
    return this.properties.get((instance instanceof Class ? "java.lang.Class" : clazz.getTheClass().getName()) + ":" + name);
  }
 
  /**
   * @param classes The set of classes this DSL provides methods/properties for
   * @param forType The type to add
   * @param descriptor The corresponding category descriptor
   */
  protected void addCategory (Set<Class<?>> classes, Class forType, ClassDescriptor descriptor) {
    classes.add(forType);
    if (!this.lookup.containsKey(forType.getName())) this.lookup.put(forType.getName(), new ArrayList<ClassDescriptor>());
    this.lookup.get(forType.getName()).add(descriptor);
  }

}
TOP

Related Classes of net.sourceforge.javautil.groovy.dsl.impl.standard.GroovyDSLCategoryClass

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.