Package net.sourceforge.javautil.groovy.builder.interceptor.objectfactory

Source Code of net.sourceforge.javautil.groovy.builder.interceptor.objectfactory.PackageInstantiator

package net.sourceforge.javautil.groovy.builder.interceptor.objectfactory;

import groovy.lang.MetaClass;
import groovy.lang.MetaMethod;

import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CopyOnWriteArrayList;

import net.sourceforge.javautil.groovy.builder.GroovyBuilder;
import net.sourceforge.javautil.groovy.builder.interceptor.annotation.Alias;
import net.sourceforge.javautil.groovy.builder.interceptor.annotation.Node;

import org.codehaus.groovy.runtime.InvokerHelper;

/**
* This will take one or more packages as the source of objects who's
* names should match the node names called with a capitalized first letter.
*
* @author elponderador
*
* @param <T> The type of object this instantiator should be producing.
*/
public class PackageInstantiator<B extends GroovyBuilder,T> implements ObjectFactoryInstantiator<B,T> {

  private static final Object[] EMPTY_ARRAY = new Object[0];
 
  public static String[] getPackageNames (Class... classes) {
    String[] array = new String[classes.length];
    for (int c=0; c<classes.length; c++) array[c] = classes[c].getPackage().getName();
    return array;
  }
 
  private List<String> pkgs = new CopyOnWriteArrayList<String>();
 
  private Map<String, Class> aliases = new LinkedHashMap<String, Class>();

  /**
   * This is convenience constructor that passes the package(s) name of the class passed onto the {@link #PackageInstantiator(String...)} constructor.
   *
   * @param clazz The class(es) whose package(s) will provide the classes that are targets of node building calls
   */
  public PackageInstantiator(Class... classes) {
    this(getPackageNames(classes));
   
    for (Class<?> clazz : classes) {
      Node node = clazz.getAnnotation(Node.class);
      if (node != null && node.aliases().length > 0) {
        for (Alias alias : node.aliases()) {
          this.aliases.put(alias.name(), alias.type());
        }
      }
    }
  }
 
  /**
   * This allows you to specify if you want the proxy to be called before any possible found
   * meta methods on the builder.
   *
   * @param passParentToChild See {@link #isPassParentToConstructor()}
   * @param callProxyFirst See {@link #isCallProxyFirst()}
   * @param pkgs The package(s) that contain the object that will be the targets of node building calls.
   * 
   * @see #handleInvokedMethod(GroovyBuilder, GroovyBuilderStack, MetaMethod, String, Object[])
   * @see {@link #isCallProxyFirst()}
   */
  public PackageInstantiator(String... pkgs) {
    Collections.addAll(this.pkgs, pkgs);
  }
 
  /**
   * This can be used to allow certain classes to be referenced by different names.
   *
   * @param name The alias for the type
   * @param type The type the alias routes to
   */
  public void alias (String name, Class type) {
    this.aliases.put(name, type);
  }

  public T instantiateNode (B builder, ObjectFactoryInterceptor ofi, String nodeName, T parent) {
    MetaClass mc = ofi.getMetaClassForNode(nodeName);
   
    if (mc == null) {
      if (this.aliases.containsKey(nodeName)) {
        ofi.setMetaClassForNode(nodeName, InvokerHelper.getMetaClass(this.aliases.get(nodeName)));
      } else {
        String newNodeName = nodeName.substring(0, 1).toUpperCase() + nodeName.substring(1);
        for (String pkg : this.pkgs) {
          try {
            Class clazz = Class.forName(pkg + "." + newNodeName, false, Thread.currentThread().getContextClassLoader());
            ofi.setMetaClassForNode(nodeName, mc = InvokerHelper.getMetaClass(clazz));
            break;
          } catch (ClassNotFoundException e) {}
        }
        if (mc == null) ofi.setMetaClassForNode(nodeName, null);
      }
    }
   
    return (T) (mc == null ? null : mc.invokeConstructor(parent == null || !ofi.isPassParentToConstructor() ? EMPTY_ARRAY : new Object[] { parent }));
  }
 
}
TOP

Related Classes of net.sourceforge.javautil.groovy.builder.interceptor.objectfactory.PackageInstantiator

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.