Package jfun.yan.etc

Source Code of jfun.yan.etc.Beans

/*****************************************************************************
* Copyright (C) Codehaus.org. All rights reserved.            *
* ------------------------------------------------------------------------- *
* The software in this package is published under the terms of the BSD      *
* style license a copy of which has been included with this distribution in *
* the LICENSE.txt file.                                                     *
*****************************************************************************/

/*
* Created on Apr 7, 2005
*
* Author Michelle Lei
* ZBS
*/
package jfun.yan.etc;

import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.util.HashMap;
import jfun.yan.Component;
import jfun.yan.Components;
import jfun.yan.Creator;
import jfun.yan.PropertyBinder;

/**
* Helper functions for bean component including customizations
* of bean property resolution strategy.
* The default strategy is byType.
* byName, byDisplayName and byQualifiedName are provided in this class directly.
* More flexible policies can be implemented by
* using the {@link Beans#resolveBy(jfun.yan.Component, FromProperty)} method.
* <p>
* Codehaus.org.
*
* @author Michelle Lei
*
*/
public class Beans {
  private static PropertyDescriptor[] getBeanProperties(Class c){
    try{
      return Introspector.getBeanInfo(c).getPropertyDescriptors();
    }
    catch(IntrospectionException e){
      throw new IllegalArgumentException(e.getMessage());
    }
  }
  /**
   * Customize the resolution mechanism for java bean properties
   * using the result from a FromProperty object.
   *
   * @param cc the component.
   * @param type the type of the java bean.
   * @param pn the FromProperty object.
   * @return the new Component.
   */
  public static Component resolveBy(final Component cc, final Class type,
      final FromProperty pn){
    final PropertyDescriptor[] props = getBeanProperties(type);
    //Component r = cc;
    final java.util.HashMap hmap = new java.util.HashMap();
    for(int i=0; i<props.length; i++){
      final PropertyDescriptor prop = props[i];
      if(prop.getWriteMethod() == null) continue;
      final String name = prop.getName();
      hmap.put(name, Components.useKey(pn.fromProperty(type, prop)));
      //r = r.withProperty(name, Components.useKey(pn.fromProperty(type, prop)))
       
        //;
    }
    return cc.withProperties(hmap);
    //return r;
  }
  /**
   * Customize the resolution mechanism for java bean properties
   * using the result from a FromProperty object.
   *
   * @param cc the component.
   * @param pn the FromProperty object.
   * @return the new Component.
   */
  public static Component resolveBy(final Component cc, final FromProperty pn){
    final Class type = cc.getType();
    if(type==null || !cc.isConcrete()){
      return cc.bind(new jfun.yan.Binder(){
        public Creator bind(Object obj)
        throws Exception{
          if(obj==null) return Components.value(null);
          else return resolveBy(Components.value(obj), obj.getClass(), pn);
        }
      });
    }
    else{
      return resolveBy(cc, type, pn);
    }
  }
  /**
   * resolve java bean properties by name instead of the default "byType"
   * policy.
   *
   * @param cc the component.
   * @return the new Component.
   */
  public static Component byName(final Component cc){
    /*return resolveBy(cc, new FromProperty(){
      public Object fromProperty(Class c, PropertyDescriptor prop){
        return prop.getName();
      }
    });*/
    //we use withProperties because it is easier.
    //and we get more testing coverage.
    return cc.bindProperties(new jfun.yan.PropertyBinder(){
      public Creator bind(Class component_type, Object key, Class type){
        return Components.useKey(key);
      }
    });
  }
  /**
   * resolve java bean properties by type.
   *
   * @param cc the component.
   * @return the new Component.
   */
  public static Component byType(final Component cc){
    return cc.bindProperties(new jfun.yan.PropertyBinder(){
      public Creator bind(Class component_type, Object key, Class type){
        return Components.useType(type);
      }
    });
  }
  /**
   * resolve java bean properties by display name instead of the default "byType"
   * policy.
   *
   * @param cc the component.
   * @return the new Component.
   */
  public static Component byDisplayName(final Component cc){
    return resolveBy(cc, new FromProperty(){
      public Object fromProperty(Class c, PropertyDescriptor prop){
        return prop.getDisplayName();
      }
    });
  }
  /**
   * resolve java bean properties by fully qualified name
   * (class_name.property_name) instead of the default "byType"
   * policy.
   *
   * @param cc the component.
   * @return the new Component.
   */
  public static Component byQualifiedName(final Component cc){
    return resolveBy(cc, new FromProperty(){
      public Object fromProperty(Class c, PropertyDescriptor prop){
        return jfun.util.Misc.getTypeName(c)+'.'+prop.getName();
      }
    });
  }
 
  /**
   * Create a Component that makes the parameters mandatory properties
   * and all java bean setters optional.
   * <br>
   * For a class whose constructor has two parameters,
   * the two parameters will be made two mandatory properties under the provided
   * property names; all the java bean setters will be made optional properties.
   * <br>
   * This way, mandatory properties can be expressed as parameters and optional
   * properties can be represented as bean properties.
   * Yet, configuration consistently uses named properties, avoiding confusion
   * caused by position based parameters.
   * @param cc the component that expects some mandatory parameters
   * (such as a constructor or a static factory method)
   * @param mandatory_params the property names to name the parameters.
   * @return the new Component object that expects mandatory properties for the
   * parameters and optioinal properties for the java bean properties.
   * @throws IntrospectionException
   * When Java Bean Introspection fails.
   */
  public static Component beanComponent(final Component cc,
      final String[] mandatory_params)
  throws IntrospectionException{
    if(mandatory_params==null || mandatory_params.length==0)
      return cc.bean().optionalProperties();
    final HashMap params = new HashMap();
    for(int i=0;i<mandatory_params.length;i++){
      final String name = mandatory_params[i];
      params.put(name, name);
    }
    return cc.fromProperties(mandatory_params).bean()
      .bindProperties(new PropertyBinder(){
        public Creator bind(Class component_type, Object key, Class type){
          final Component p = Components.useProperty(component_type, key, type);
          if(params.containsKey(key)){
            return p;
          }
          else return p.optional();
        }
      });
  }
 

}
TOP

Related Classes of jfun.yan.etc.Beans

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.