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

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

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

import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.MethodDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Map;

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.builder.GroovyBuilder;
import net.sourceforge.javautil.groovy.builder.interceptor.annotation.AddChildNode;
import net.sourceforge.javautil.groovy.builder.interceptor.annotation.Node;
import net.sourceforge.javautil.groovy.builder.interceptor.annotation.Parent;

/**
* This will map node relationships for child/parent nodes.
*
* @author elponderador
* @author $Author: ponderator $
* @version $Id: AnnotatedNodeMapper.java 1844 2010-02-19 05:21:05Z ponderator $
*/
public class AnnotatedNodeMapper extends StandardNodeMapper {

  protected Map<Class, ClassMethod> addChild = new HashMap<Class, ClassMethod>();
  protected Map<Class, ClassMethod> setParent = new HashMap<Class, ClassMethod>();
  protected Map<Class, ClassMethod> nodeType = new HashMap<Class, ClassMethod>();
 
  /**
   * Parent nodes should use the {@link AddChildNode} annotation in order to
   * specify which method should be used, if any, to add children to some internal
   * collection. Child nodes should use the {@link Parent} annotation in order to
   * specify which method should be used, if any, to set the parent to child node.
   */
  public void associate(GroovyBuilder builder, ObjectFactoryInterceptor ofi, Object child, Object parent) {
    Node.Type type = null;
    boolean parentRequired = true;
    Node cnode = child.getClass().getAnnotation(Node.class);
   
    if (cnode != null) {
      type = cnode.value();
      parentRequired = cnode.parentRequired();
    } else {
      ClassMethod method = this.getTypeIndicator(child.getClass());
      if (method != null) {
        cnode = method.getAnnotation(Node.class);
        parentRequired = cnode.parentRequired();
        type = (Node.Type) method.invoke(child);
      } else {
        type = Node.Type.Branch;
        parentRequired = false;
      }
    }
   
    switch (type) {
      case Root:
        if (parent != null) throw new RuntimeException("Cannot add root nodes to type: " + parent);
        break;
       
      case Branch:
        if (parent == null && parentRequired) throw new RuntimeException("No parent for a branch node: " + child);
        if (parent != null) this.addChild(parent, child);
        break;
       
      case Leaf:
        if (parent == null) throw new RuntimeException("No parent for a leaf node: " + child);
        this.addChild(parent, child);
        break;
       
      case Dynamic:
        throw new RuntimeException("Dynamic is not a valid type: " + child);
    }
   
    if (parent != null) this.setParent(child, parent);
  }
 
  protected void setParent (Object child, Object parent) {
    ClassMethod property = this.getParentSetter(child.getClass());
    if (property == null) return;

    property.invoke(child, parent);
  }

  protected void addChild (Object parent, Object child) {
    ClassMethod method = this.getChildAggregator(parent.getClass());
    if (method == null) return;
   
    method.invoke(parent, child);
  }
 
  protected ClassMethod getParentSetter (Class clazz) {
    if (!this.setParent.containsKey(clazz)) {
      this.setParent.put(clazz, ClassCache.getFor(clazz).getMethod(Parent.class));
    }
    return this.setParent.get(clazz);
  }

  protected ClassMethod getChildAggregator (Class clazz) {
    if (!this.addChild.containsKey(clazz)) {
      this.addChild.put(clazz, ClassCache.getFor(clazz).getMethod(AddChildNode.class));
    }
    return this.addChild.get(clazz);
  }

  protected ClassMethod getTypeIndicator (Class clazz) {
    if (!this.nodeType.containsKey(clazz)) {
      this.nodeType.put(clazz, ClassCache.getFor(clazz).getMethod(Node.class));
    }
    return this.nodeType.get(clazz);
  }
 
}
TOP

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

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.