Package jfun.yan

Source Code of jfun.yan.Components$TypedComponent

/*****************************************************************************
* 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 Feb 28, 2005
*
* Author Ben Yu
* ZBS
*/
package jfun.yan;

import java.beans.IntrospectionException;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Set;


import jfun.util.Misc;
import jfun.util.StringUtils;
import jfun.util.beans.Bean;
import jfun.util.beans.BeanType;
import jfun.util.beans.NoSuchPropertyException;
import jfun.yan.element.ElementStore;
import jfun.yan.element.ListStore;
import jfun.yan.element.MapStore;
import jfun.yan.element.SetStore;
import jfun.yan.factory.Factory;
import jfun.yan.factory.Pool;
import jfun.yan.function.Function;
import jfun.yan.function.Property2Signature;
import jfun.yan.function.Signature;
import jfun.yan.util.Predicate;
import jfun.yan.util.ReflectionUtil;

/**
* This class provides implementations of some basic components
* as well as most of the commonly used combiniators
* for Component.
* A combinator is a function that will combine one or more Component objects
* and create a more complex Component object.
* <p>
* Codehaus.org.
*
* @author Ben Yu
*
*/
public final class Components {
  /**
   * To adapt a Creator object to a Component object.
   * if the object is already a Component, itself is returned.
   * @param c the creator object.
   * @return the Component object.
   */
  public static <T> Component<T> adapt(Creator<T> c){
    if(c instanceof Component){
      return (Component<T>)c;
    }
    else return new Creator2Component<T>(c);
  }
  /**
   * Create a Component object that uses a Function to create instance.
   * @param fun the Function object.
   * @return the Component object.
   */
  public static <T> Component<T> fun(Function<T> fun){
    //do not label it because this extra frame does not bring
    //much useful information.
    return new FunctionComponent<T>(fun).guard();
  }
  /**
   * Create a Component object that uses the constructor of a class
   * to create instance of that class.
   * This class should have one and only one public constructor.
   * <br>
   * Array type is given a special constructor so that the constructor of
   * array type T has one parameter of type int
   * and calls new T[size] when invoked.
   * @param c the class.
   * @return the Component object.
   * @throws IllegalArgumentException
   * if the class is not public or has no public constructor
   * or has more than one public constructor.
   */
  public static <T> Component<T> ctor(Class<T> c)
  throws IllegalArgumentException{
    return fun(Functions.ctor(c));
  }
  /**
   * Create a Component that uses one constructor of a class
   * to create instance of that class.
   * The constructor to invoke is determined by the parameter types specified.
   * <br>
   * Array type is given a special constructor so that the constructor of
   * array type T has one parameter of type int
   * and calls new T[size] when invoked.
   * @param c the class.
   * @param param_types the parameter types of the constructor to use.
   * null indicates the default constructor.
   * @return the Component object.
   * @throws IllegalArgumentException
   * if the type is not public or the public constructor cannot be found.
   */
  public static <T> Component<T> ctor(Class<T> c, Class[] param_types)
  throws IllegalArgumentException{
    return fun(Functions.ctor(c, param_types));
  }
  /**
   * Create a Component object that invokes a static method to create instance.
   * This class should have one and only one public static method of this name.
   * @param c the class where the static method belongs.
   * @param name the static method name.
   * @return the Component object.
   * @throws IllegalArgumentException
   * thrown if any of the following conditions is true: <br>
   * 1. this method is not public. <br>
   * 2. this method is not static. <br>
   * 3. more than one public static method with the specified name. <br>
   * 4. no public static method with the specified name. <br>
   */
  public static Component static_method(Class c, String name)
  throws IllegalArgumentException{
    return fun(Functions.static_method(c, name));
  }
  /**
   * Create a Component object that invokes a static method to create instance.
   * The static method to invoke is determined by the method name
   * and the parameter types.
   * @param c the class where the static method belongs.
   * @param name the static method name.
   * @param param_types the parameter types.
   * null indicates a parameter-less method.
   * @return the Component object.
   * @throws IllegalArgumentException
   * thrown if any of the following conditions is true: <br>
   * 1. this method is not public. <br>
   * 2. this method is not static. <br>
   * 3. no public static method with the specified name and the parameter types. <br>
   */
  public static Component static_method(
      Class c, String name, Class[] param_types){
    return fun(
        Functions.static_method(c, name, param_types));
  }
  /**
   * Create a Component object that invokes a method against a given object
   * to create component instance.
   * The class of the object
   * should have one and only one public method of this name.
   * @param obj the object to run the method against. It cannot be null.
   * @param name the method name.
   * @return the Component object.
   * @throws IllegalArgumentException
   * thrown if any of the following conditions is true: <br>
   * 1. this method is not public. <br>
   * 2. more than one public method with the specified name. <br>
   * 3. no public method with the specified name. <br>
   */
  public static Component method(Object obj, String name){
    return fun(Functions.method(obj, name));
  }
  /**
   * Create a Component object that invokes a method against a given object
   * to create component instance.
   * The class of the object
   * should have one and only one public static method of this name.
   * @param type the Class object to look up method.
   * This parameter can be used when we only want to look up in
   * a super type rather than obj.getClass().
   * @param obj the object to run the method against.
   * It can be null if the method is static.
   * @param name the method name.
   * @return the Component object.
   * @throws IllegalArgumentException
   * thrown if any of the following conditions is true: <br>
   * 1. this method is not public. <br>
   * 2. more than one public method with the specified name. <br>
   * 3. no public method with the specified name. <br>
   */
  public static Component method(Class type, Object obj, String name){
    return fun(Functions.method(type, obj, name));
  }
  /**
   * Create a Component object that invokes a method against a given object
   * to create component instance.
   * The method to invoke is determined by the method name
   * and the parameter types.
   * @param obj the object to run the method against.
   * It cannot be null.
   * @param name the method name.
   * @param param_types the parameter types.
   * null indicates a parameter-less method.
   * @return the Component object.
   * @throws IllegalArgumentException
   * thrown if any of the following conditions is true: <br>
   * 1. this method is not public. <br>
   * 2. no public method with the specified name and the parameter types. <br>
   */
  public static Component method(
      Object obj, String name, Class[] param_types){
    return fun(
        Functions.method(obj, name, param_types));
  }
  /**
   * Create a Component object that invokes a method against a given object
   * to create component instance.
   * The method to invoke is determined by the method name
   * and the parameter types.
   * @param type the Class object to look up method.
   * This parameter can be used when we only want to look up in
   * a super type rather than obj.getClass().
   * @param obj the object to run the method against.
   * It can be null if the method is static.
   * @param name the method name.
   * @param param_types the parameter types.
   * null indicates a parameter-less method.
   * @return the Component object.
   * @throws IllegalArgumentException
   * thrown if any of the following conditions is true: <br>
   * 1. this method is not public. <br>
   * 2. no public method with the specified name and the parameter types. <br>
   */
  public static Component method(Class type,
      Object obj, String name, Class[] param_types){
    return fun(
        Functions.method(type, obj, name, param_types));
  }
  /**
   * Create a Component object that reads a static field to create instance.
   * @param c the class where the static instance belongs.
   * @param name the static instance name.
   * @return the Component object.
   * @throws IllegalArgumentException
   * thrown if any of the following conditions is true: <br>
   * 1. field not found. <br>
   * 2. field is not static. <br>
   */
  public static Component static_field(Class c, String name)
  throws IllegalArgumentException{
    return fun(Functions.static_field(c, name));
  }
  /**
   * Create a Component object that reads a field from a given object
   * to create component instance.
   * @param type the Class object to look up field.
   * This parameter can be used when we only want to look up in
   * a super type rather than obj.getClass().
   * @param obj the object to read field from.
   * It can be null if the field is static.
   * @param name the field name.
   * @return the Component object.
   * @throws IllegalArgumentException
   * thrown if any of the following conditions is true: <br>
   * 1. field is not found.
   */
  public static Component field(Class type, Object obj, String name){
    return fun(Functions.field(type, obj, name));
  }
  /**
   * Create a Component object that reads a field from a given object
   * to create component instance.
   * @param obj the object to read the field from. It cannot be null.
   * @param name the field name.
   * @return the Component object.
   * @throws IllegalArgumentException
   * thrown if any of the following conditions is true: <br>
   * 1. field not found.
   */
  public static Component field(Object obj, String name){
    return fun(Functions.field(obj, name));
 
  /**
   * Create a Component that calls a property getter of an object.
   * @param type the type to introspect.
   * @param obj the object to run the getter against.
   * @param prop the property name.
   * @return the Component object.
   * @throws IntrospectionException if introspection fails.
   * @throws NoSuchPropertyException if the property does not exist.
   * @throws NonReadablePropertyException if the property is not rreadable.
   */
  public static Component getter(Class type, Object obj, String prop)
  throws IntrospectionException, NoSuchPropertyException,
  NonReadablePropertyException{
    final BeanType btype = BeanType.instance(type);
    final Method m = btype.getReader(prop);
    if(m==null)
      throw new NonReadablePropertyException(type, prop);
    return fun(Functions.getter(Bean.instance(type, obj), prop));
  }
  /**
   * Create a Component that calls a property setter against an object.
   *
   * @param type the type to introspect.
   * @param obj the object.
   * @param prop the property name.
   * @return the Component object.
   * @throws IntrospectionException if introspection fails.
   * @throws NoSuchPropertyException if the the property cannot be found.
   * @throws NonWritablePropertyException if the property is not writable.
   */
  public static <T> Component<T> setter(Class type, T obj, String prop)
  throws IntrospectionException, NoSuchPropertyException,
  NonWritablePropertyException{
    final BeanType btype = BeanType.instance(type);
    if(btype.getWriter(prop)==null && btype.getIndexedWriter(prop)==null)
      throw new NonWritablePropertyException(type, prop);
    return fun(Functions.setter(Bean.instance(type, obj), prop));
  }
  /**
   * Create a Component that calls an indexed property getter of an object.
   * @param type the type to introspect.
   * @param obj the object to run the getter against.
   * @param prop the property name.
   * @param ind the index.
   * @return the Component object.
   * @throws IntrospectionException if introspection fails.
   * @throws NoSuchPropertyException if the property does not exist.
   * @throws NonReadablePropertyException
   * if the property is not rreadable or if the property is not indexed.
   */ 
  public static Component indexed_getter(Class type, Object obj, String prop, int ind)
  throws IntrospectionException, NoSuchPropertyException,
  NonReadablePropertyException{
    final BeanType btype = BeanType.instance(type);
    final Method m = btype.getIndexedReader(prop);
    if(m==null)
      throw new NonReadablePropertyException(type, prop);
    return fun(Functions.indexed_getter(Bean.instance(type, obj), prop, ind));
  }
  /**
   * Create a Component that calls an indexed property setter against an object.
   *
   * @param type the type to introspect.
   * @param obj the object.
   * @param prop the property name.
   * @param ind the index.
   * @return the Component object.
   * @throws IntrospectionException if introspection fails.
   * @throws NoSuchPropertyException if the the property cannot be found.
   * @throws NonWritablePropertyException
   * if the property is not writable or not indexed.
   */
  public static <T> Component<T> indexed_setter(Class type, T obj, String prop, int ind)
  throws IntrospectionException, NoSuchPropertyException,
  NonWritablePropertyException{
    final BeanType btype = BeanType.instance(type);
    final Method m = btype.getIndexedWriter(prop);
    if(m==null)
      throw new NonWritablePropertyException(type, prop);
    return fun(Functions.indexed_setter(Bean.instance(type, obj), prop, ind));
  }

  /**
   * Create a Component that calls a property getter of an object.
   * @param obj the object to run the getter against.
   * @param prop the property name.
   * @return the Component object.
   * @throws IntrospectionException if introspection fails.
   * @throws NoSuchPropertyException if the property does not exist.
   * @throws NonReadablePropertyException if the property is not rreadable.
   */
  public static Component getter(Object obj, String prop)
  throws IntrospectionException, NoSuchPropertyException,
  NonReadablePropertyException{
    return getter(obj.getClass(), obj, prop);
  }
  /**
   * Create a Component that calls a property setter against an object.
   *
   * @param obj the object to run the setter against.
   * @param prop the property name.
   * @return the Component object.
   * @throws IntrospectionException if introspection fails.
   * @throws NoSuchPropertyException if the the property cannot be found.
   * @throws NonWritablePropertyException if the property is not writable.
   */
  public static <T> Component<T> setter(T obj, String prop)
  throws IntrospectionException, NoSuchPropertyException,
  NonWritablePropertyException{
    return setter(obj.getClass(), obj, prop);
  }
  /**
   * Create a Component that calls an indexed property getter of an object.
   * @param obj the object to run the getter against.
   * @param prop the property name.
   * @param ind the index.
   * @return the Component object.
   * @throws IntrospectionException if introspection fails.
   * @throws NoSuchPropertyException if the property does not exist.
   * @throws NonReadablePropertyException
   * if the property is not rreadable or if the property is not indexed.
   */ 
  public static Component indexed_getter(Object obj, String prop, int ind)
  throws IntrospectionException, NoSuchPropertyException,
  NonReadablePropertyException{
    return indexed_getter(obj.getClass(), obj, prop, ind);
  }
  /**
   * Create a Component that calls an indexed property setter against an object.
   *
   * @param obj the object to run the setter against.
   * @param prop the property name.
   * @param ind the index.
   * @return the Component object.
   * @throws IntrospectionException if introspection fails.
   * @throws NoSuchPropertyException if the the property cannot be found.
   * @throws NonWritablePropertyException
   * if the property is not writable or not indexed.
   */
  public static <T> Component<T> indexed_setter(T obj, String prop, int ind)
  throws IntrospectionException, NoSuchPropertyException,
  NonWritablePropertyException{
    return indexed_setter(obj.getClass(), obj, prop, ind);
  }
 
  /**
   * Create a Component object that simply return a value upon instance creation.
   * The type of the value is used as the type of the component.
   * null is permitted as a value too.
   * void.class is used as the type of the component if the value is null.
   * @param val the value.
   * @return the Component object.
   */
  public static <T> Component<T> value(final T val){
    if(val==null) return NilComponent.instance;
    return new ValueComponent<T>(val);
  }
  /**
   * Create a Component object that simply return a value upon instance creation.
   * double.class is used as the component type.
   * @param val the value.
   * @return the Component object.
   */
  public static Component<Double> value(final double val){
    return value(new Double(val)).cast(double.class);
  }
  /**
   * Create a Component object that simply return a value upon instance creation.
   * float.class is used as the component type.
   * @param val the value.
   * @return the Component object.
   */
  public static Component<Float> value(final float val){
    return value(new Float(val)).cast(float.class);
  }
  /**
   * Create a Component object that simply return a value upon instance creation.
   * long.class is used as the component type.
   * @param val the value.
   * @return the Component object.
   */
  public static Component<Long> value(final long val){
    return value(new Long(val)).cast(long.class);
  }
  /**
   * Create a Component object that simply return a value upon instance creation.
   * int.class is used as the component type.
   * @param val the value.
   * @return the Component object.
   */
  public static Component<Integer> value(final int val){
    return value(new Integer(val)).cast(int.class);
  }
  /**
   * Create a Component object that simply return a value upon instance creation.
   * short.class is used as the component type.
   * @param val the value.
   * @return the Component object.
   */
  public static Component<Short> value(final short val){
    return value(new Short(val)).cast(short.class);
  }
  /**
   * Create a Component object that simply return a value upon instance creation.
   * byte.class is used as the component type.
   * @param val the value.
   * @return the Component object.
   */
  public static Component<Byte> value(final byte val){
    return value(new Byte(val)).cast(byte.class);
  }
  /**
   * Create a Component object that simply return a value upon instance creation.
   * char.class is used as the component type.
   * @param val the value.
   * @return the Component object.
   */
  public static Component<Character> value(final char val){
    return value(new Character(val)).cast(char.class);
  }
  /**
   * Create a Component object that simply return a value upon instance creation.
   * boolean.class is used as the component type.
   * @param val the value.
   * @return the Component object.
   */
  public static Component<Boolean> value(final boolean val){
    return val?true_component:false_component;
  }

  private static Component<Boolean> return_bool(boolean b){
    return value(Boolean.valueOf(b)).cast(boolean.class);
  }
  private static final Component<Boolean> true_component = return_bool(true);
  private static final Component<Boolean> false_component = return_bool(false);
  /**
   * Create a new Component object from a base Component object
   * that calls Java Bean setters after the base Component creates the instance.
   * <br>
   * Upon instance creation, it first calls the base Component.
   * The base Component is responsible for creating the component instance.
   * The bean component then calls the java bean setters
   * for the property names specified against the component instance
   * to finish the component creation process.
   * <br>
   * The Java Bean setters used to create the component instance are
   * determined by the return value of getType() method.
   * That means, if getType() returns Type1 while the actual instance created is
   * a subtype of Type1, only the setters of Type1 are used.
   * However, if the base component is late-bound, where the getType() returns null,
   * the Java Bean setters are resolved at creation time.
   * <br>
   * It should be noted that,
   * for a singleton bean component obtained by calling singleton() method
   * against the bean component, it does not cause infinite loop
   * if any property of the component is depending on this same singleton bean componet.
   * This is because the singleton bean component caches the instance
   * before any of the properties are set. 
   * @param cc the base Component object.
   * @param props the names of the properties used.
   * @return the new Component object.
   * @throws IntrospectionException if java bean introspection fails.
   * @throws IllegalPropertyNameException if a name specified in
   * the props Set is not a valid property name.
   * @throws NonWritablePropertyException
   * if a property specified has no setter.
   */
  public static <T> Component<T> bean(final Component<T> cc, java.util.Set props)
  throws IntrospectionException,
  IllegalPropertyNameException,  NonWritablePropertyException{
    final PropertiesInjector pi =
      DefaultPropertiesInjector.instance(cc.getType(), props);
    return makeBean(cc, pi);
    /*
    return BeanBinder.instance(cc, props).guard()
    .label();
    */
  }
  /**
   * Create a Bean component that calls a PropertiesInjector to inject
   * bean properties to the bean instance.
   * @param cc the component that instantiates the bean instance.
   * @param injector the injector to inject properties.
   * @return the bean component.
   */
  public static <T> Component<T> makeBean(Component<T> cc, PropertiesInjector injector){
    return makeBean(injector.toString(), cc, injector);
  }
  /**
   * Create a Bean component that calls a PropertiesInjector to inject
   * bean properties to the bean instance.
   * @param name the name of the bean component.
   * @param cc the component that instantiates the bean instance.
   * @param injector the injector to inject properties.
   * @return the bean component.
   */
  public static <T> Component<T> makeBean(String name,
      Component<T> cc, PropertiesInjector injector){
    return Monad.followedBy(cc, new BeanBinder<T>(name, injector)).label(name);
  }
  /**
   * Create a new Component object from a base Component object
   * that calls Java Bean setters after the base Component creates the instance.
   * <br>
   * Upon instance creation, it first calls the base Component.
   * The base Component is responsible for creating the component instance.
   * The bean component then calls the java bean setters to the component instance
   * to finish the component creation process.
   * <br>
   * The Java Bean setters used to create the component instance are
   * determined by the return value of getType() method.
   * That means, if getType() returns Type1 while the actual instance created is
   * a subtype of Type1, only the setters of Type1 are used.
   * However, if the base component is late-bound, where the getType() returns null,
   * the Java Bean setters are resolved at creation time.
   * <br>
   * It should be noted that,
   * for a singleton bean component obtained by calling singleton() method
   * against the bean component, it does not cause infinite loop
   * if any property of the component is depending on this same singleton bean componet.
   * This is because the singleton bean component caches the instance
   * before any of the properties are set. 
   * @param cc the base Component object.
   * @return the new Component object.
   * @throws IntrospectionException if java bean introspection fails.
   */
  public static <T> Component<T> bean(final Component<T> cc)
  throws IntrospectionException{
    final PropertiesInjector pi = DefaultPropertiesInjector.instance(cc.getType());
    return makeBean(cc, pi);
    //return BeanBinder.instance(cc).guard().label();
  }
  /**
   * Create a Component object that uses Java Bean convention to create instance.
   * i.e. It first calls the default constructor of the class, then calls all
   * the Java Bean setters to finish the instance creation.
   * <br>
   * It should be noted that,
   * for a singleton bean component obtained by calling singleton() method
   * against the bean component, it does not cause infinite loop
   * if any property of the component is depending on this same singleton bean componet.
   * This is because the singleton bean component caches the instance
   * before any of the properties are set. 
   * @param type the Java Bean class.
   * @return the Component object.
   * @throws IntrospectionException if Java Bean introspection fails.
   * @throws IllegalArgumentException if the class is not public
   * or does not have public default constructor.
   */
  public static <T> Component<T> bean(final Class<T> type)
  throws IntrospectionException, IllegalArgumentException{
    return bean(ctor(type, null));
  }
  /**
   * Create a Component object that uses Java Bean convention to create instance.
   * i.e. It first calls the default constructor of the class, then calls all
   * the Java Bean setters for the properties specified to finish the instance creation.
   * <br>
   * It should be noted that,
   * for a singleton bean component obtained by calling singleton() method
   * against the bean component, it does not cause infinite loop
   * if any property of the component is depending on this same singleton bean componet.
   * This is because the singleton bean component caches the instance
   * before any of the properties are set. 
   * @param type the Java Bean class.
   * @param props the names of the properties used.
   * @return the new Component object.
   * @throws IntrospectionException if Java Bean introspection fails.
   * @throws IllegalPropertyNameException if any property name specified is not valid.
   * @throws NonWritablePropertyException if any property specified has no setter.
   */
  public static <T> Component<T> bean(final Class<T> type, java.util.Set props)
  throws IntrospectionException, IllegalPropertyNameException,
  NonWritablePropertyException{
    return Components.bean(ctor(type, null), props);
  }
  /**
   * Create a new Component object from a base Component object
   * that calls Java Bean setters after the base Component creates the instance.
   * <br>
   * Upon instance creation, it first calls the base Component.
   * The base Component is responsible for creating the component instance.
   * The bean component then calls the java bean setters
   * for the property names specified against the component instance
   * to finish the component creation process.
   * <br>
   * The Java Bean setters used to create the component instance are
   * determined by the return value of getType() method.
   * That means, if getType() returns Type1 while the actual instance created is
   * a subtype of Type1, only the setters of Type1 are used.
   * However, if the base component is late-bound, where the getType() returns null,
   * the Java Bean setters are resolved at creation time.
   * <br>
   * It should be noted that,
   * for a singleton bean component obtained by calling singleton() method
   * against the bean component, it does not cause infinite loop
   * if any property of the component is depending on this same singleton bean componet.
   * This is because the singleton bean component caches the instance
   * before any of the properties are set. 
   * @param cc the base Component object.
   * @param props the names of the properties used.
   * @return the new Component object.
   * @throws IntrospectionException if java bean introspection fails.
   * @throws IllegalPropertyNameException if a name specified in
   * the props Set is not a valid property name.
   * @throws NonWritablePropertyException
   * if a property specified has no setter.
   * @throws IllegalArgumentException if the props array has any duplicate name.
   */
  public static <T> Component<T> bean(final Component<T> cc, String... props)
  throws IntrospectionException, IllegalPropertyNameException,
  NonWritablePropertyException, IllegalArgumentException{
    return Components.bean(cc, jfun.yan.util.Utils.toSet(props, "property name"));
  }
  /**
   * Create a Component object that uses Java Bean convention to create instance.
   * i.e. It first calls the default constructor of the class, then calls all
   * the Java Bean setters for the properties specified to finish the instance creation.
   * <br>
   * It should be noted that,
   * for a singleton bean component obtained by calling singleton() method
   * against the bean component, it does not cause infinite loop
   * if any property of the component is depending on this same singleton bean componet.
   * This is because the singleton bean component caches the instance
   * before any of the properties are set. 
   * @param type the Java Bean class.
   * @param props the names of the properties used.
   * @return the new Component object.
   * @throws IntrospectionException if Java Bean introspection fails.
   * @throws IllegalPropertyNameException if any property name specified is not valid.
   * @throws NonWritablePropertyException if any property specified has no setter.
   * @throws IllegalArgumentException if the props array has any duplicate name.
   */
  public static <T> Component<T> bean(final Class<T> type, String[] props)
  throws IntrospectionException, IllegalPropertyNameException,
  NonWritablePropertyException, IllegalArgumentException{
    return bean(ctor(type, null), props);
  }
 
  /**
   * Creates a Component that will call a certain method
   * against the instance created by another Component.
   * The return value of the method is used as the result of the
   * created Component.
   * @param cc the Component to create the instance.
   * @param mtd the methdo to call against the instance.
   * @return the new Component object.
   */
  public static Component bindMethod(final Component cc, final Method mtd){
    return Monad.bind(autowired(cc), new MethodBinder(mtd)).label(""+cc+".<"+mtd+">")
    .guard();
  }
  /**
   * Creates a Component that will call a certain method
   * against the instance created by another Component.
   * The return value of the method is used as the result of the
   * created Component.
   * <br>
   * If the type of the first component is statically known (getType()!=null),
   * The method is statically resolved when bindMethod() is called.
   * Otherwise, it is resolved when the actual component instantiation happens.
   * @param cc the Component to create the instance.
   * @param name the method name.
   * @param suppress_security whether access to non-public method is allowed.
   * @return the new Component object.
   * @throws IllegalArgumentException if the static resolution of the method
   * fails.
   */
  public static Component bindMethod(final Component cc, final String name,
      boolean suppress_security)
  throws IllegalArgumentException{
    final String lbl = ""+cc+"."+name + "( ... )";
    final Class type = cc.getType();
    return Monad.bind(autowired(cc), invokingMethod(type, name, suppress_security))
    .label(lbl).guard();
  }
  /**
   * Creates a Component that will call a certain method
   * against the instance created by another Component.
   * The return value of the method is used as the result of the
   * created Component.
   * <br>
   * If the type of the first component is statically known (getType()!=null),
   * The method is statically resolved when bindMethod() is called.
   * Otherwise, it is resolved when the actual component instantiation happens.
   * @param cc the Component to create the instance.
   * @param name the method name.
   * @param param_count the number of formal parameters.
   * @param suppress_security whether access to non-public method is allowed.
   * @return the new Component object.
   * @throws IllegalArgumentException if the static resolution of the method
   * fails.
   */
  public static Component bindMethod(final Component cc,
      final String name, final int param_count,
      boolean suppress_security)
  throws IllegalArgumentException{
    final String lbl = ReflectionUtil.toMethodString(name, param_count);
    final Class type = cc.getType();
    return Monad.bind(autowired(cc), invokingMethod(type, name, param_count, suppress_security))
    .label(lbl).guard();
  }
  /**
   * Creates a Component that will read a certain field
   * from the instance created by another Component.
   * The return value of the field is used as the result of the
   * created Component.
   * @param cc the Component to create the instance.
   * @param fld the methdo to read from the instance.
   * @return the new Component object.
   */
  public static Component bindField(final Component cc, final Field fld){
    return Monad.bind(autowired(cc), new FieldBinder(fld)).label(""+cc+".<"+fld+">")
    .guard();
  }

  /**
   * Creates a Component that will read a certain field
   * from the instance created by another Component.
   * The return value of the field is used as the result of the
   * created Component.
   * @param cc the Component to create the instance.
   * @param name the field name.
   * @param suppress_security whether access to non-public field is allowed.
   * @return the new Component object.
   * @throws IllegalArgumentException if the static resolution of the field
   * fails.
   */
  public static Component bindField(final Component cc, final String name,
      boolean suppress_security)
  throws IllegalArgumentException{
    final String lbl = ""+cc+"."+name;
    final Class type = cc.getType();
    return Monad.bind(autowired(cc), readingField(type, name, suppress_security))
    .label(lbl).guard();
  }
 
  /**
   * Create a ComponentBinder object that invokes a method against the
   * bound object.
   * @param type the type to search the method against. Null defers the
   * search to runtime.
   * @param name the method name.
   * @param suppress_security Are non-public methods searched at all?
   * @return the ComponentBinder object.
   */
  public static ComponentBinder invokingMethod(Class type, String name,
      final boolean suppress_security){
    if(type==null)
      return new MethodNameBinder(name,suppress_security);
    else
      return new MethodBinder(ReflectionUtil.getMethod(type, name, suppress_security));
  }
  /**
   * Create a ComponentBinder object that invokes a method against the
   * bound object.
   * @param type the type to search the method against. Null defers the
   * search to runtime.
   * @param name the method name.
   * @param param_count the number of formal parameters.
   * @param suppress_security Are non-public methods searched at all?
   * @return the ComponentBinder object.
   */
  public static ComponentBinder invokingMethod(Class type, String name,
      int param_count, final boolean suppress_security){
    if(type==null)
      return new MethodNameParamCountBinder(name,param_count,suppress_security);
    else
      return new MethodBinder(ReflectionUtil.getMethod(type, name,
          param_count, suppress_security));
  }
 
  /**
   * Create a ComponentBinder object that reads a field value from
   * the bound object.
   * @param type the type to search the field against. Null defers the search
   * to runtime.
   * @param name the field name.
   * @param suppress_security Are non-public fields searched at all?
   * @return the ComponentBinder object.
   */
  public static ComponentBinder readingField(Class type, String name,
      boolean suppress_security){
    if(type==null)
      return new FieldNameBinder(name, suppress_security);
    else
      return new FieldBinder(ReflectionUtil.getField(type, name, suppress_security));
  }
  /**
   * Creates a Component that will call a certain method
   * against the instance created by another Component.
   * The return value of the method is used as the result of the
   * created Component.
   * <br>
   * If the type of the first component is statically known (getType()!=null),
   * The method is statically resolved when bindMethod() is called.
   * Otherwise, it is resolved when the actual component instantiation happens.
   * @param cc the Component to create the instance.
   * @param name the method name.
   * @param param_types the parameter types of the method. null indicates
   * a parameter-less method.
   * @return the new Component object.
   * @throws IllegalArgumentException if the static resolution of the method
   * fails.
   */
  public static Component bindMethod(final Component cc,
      final String name, final Class[] param_types, boolean suppress_security)
  throws IllegalArgumentException{
    final String lbl =
      ""+cc+"."+name + jfun.util.StringUtils.listString("(",",",")",param_types);
    final Class type = cc.getType();
    return Monad.bind(autowired(cc),
        invokingMethod(type, name, param_types, suppress_security))
    .label(lbl).guard();
  }
  /**
   * To create a ComponentBinder object that invokes a method
   * against the bound object.
   * @param type the type to search the method against. Null defers the search
   * to runtime.
   * @param name the method name.
   * @param param_types the parameter types.
   * @param suppress_security are non-public methods considered at all?
   * @return the ComponentBinder object.
   */
  public static ComponentBinder invokingMethod(Class type, String name,
      Class[] param_types, boolean suppress_security){
    if(type==null){
      return new DynamicMethodBinder(name, param_types, suppress_security);
    }
    else
      return new MethodBinder(ReflectionUtil.getMethod(type, name, param_types,
          suppress_security));
  }
  /**
   * Create a Component that will return a bean property
   * of the instance created by another component.
   * @param cc the component to create the instance.
   * @param name the property name.
   * @return the new Component object.
   * @throws IntrospectionException if introspection fails.
   */
  public static Component bindGetter(final Component cc,
      final String name)throws IntrospectionException{
    final String lbl = ""+cc+"."+name;
    final Class type = cc.getType();
    return Monad.bind(autowired(cc), invokingGetter(type, name))
    .label(lbl).guard();
  }
  /**
   * To create a ComponentBinder object that invokes a Java Bean getter
   * against the bound object.
   * @param type the type to introspect for the property. Null defers the
   * introspection to runtime.
   * @param name the property name.
   * @return the ComponentBinder object.
   * @throws IntrospectionException when bean introspection fails.
   */
  public static ComponentBinder invokingGetter(Class type, String name)
  throws IntrospectionException{
    if(type==null){
      return new DynamicPropertyReadingBinder(name);
    }
    else
      return new PropertyReadingBinder(BeanType.instance(type), name);
  }
  /**
   * Create a Component that will set a bean property
   * of the instance created by another component.
   * <br>
   * The bean instance will still be used as the result.
   * @param cc the component to create the instance.
   * @param name the property name.
   * @return the new Component object.
   * @throws IntrospectionException if introspection fails.
   */
  public static Component bindSetter(final Component cc,
      final String name)
  throws IntrospectionException{
    final String lbl = ""+cc+"."+name+"=";
    final Class type = cc.getType();
    return Monad.bind(autowired(cc), invokingSetter(type,name))
          .label(lbl).guard();
  }
  /**
   * Create a ComponentBinder object that will invoke a Java Bean setter
   * against the bound object.
   * @param type the type to introspect for the property. Null defers the
   * introspection to runtime.
   * @param name the property name.
   * @return the ComponentBinder object
   * @throws IntrospectionException when bean introspection fails.
   */
  public static <T> ComponentBinder<T,T> invokingSetter(Class<T> type, String name)
  throws IntrospectionException{
    if(type==null){
      return new DynamicPropertyWritingBinder<T>(name);
    }
    else
      return new PropertyWritingBinder(BeanType.instance(type), name);
  }
  /**
   * Create a Component that will get an indexed property
   * of the Java Bean instance created by another component.
   * @param cc the component to create the instance.
   * @param name the property name.
   * @param ind the index.
   * @return the new Component object.
   * @throws IntrospectionException if introspection fails.
   */
  public static Component bindGetter(final Component cc,
      final String name, final int ind)throws IntrospectionException{
    final String lbl = ""+cc+"."+name+"["+ind+"]";
    final Class type = cc.getType();
    return Monad.bind(autowired(cc), getterBinder(type, name, ind))
    .label(lbl).guard();
  }
  private static ComponentBinder getterBinder(Class type,
      final String name, final int ind)
  throws IntrospectionException{
    if(type==null){
      return new DynamicIndexedPropertyReadingBinder(name, ind);
    }
    else
      return new IndexedPropertyReadingBinder(BeanType.instance(type), name, ind);
  }
  /**
   * Create a Component that will set an indexed property
   * of the Java Bean instance created by another component.
   * <br>
   * The bean instance will still be used as the result.
   * @param cc the component to create the instance.
   * @param name the property name.
   * @param ind the index.
   * @return the new Component object.
   * @throws IntrospectionException if introspection fails.
   */
  public static <T> Component<T> bindSetter(final Component<T> cc,
      final String name, final int ind)throws IntrospectionException{
    final String lbl = ""+cc+"."+name+"["+ind+"]=";
    final Class type = cc.getType();
    return Monad.bind(autowired(cc), setterBinder(type, name, ind))
    .label(lbl).guard();
  }
  private static <T> ComponentBinder<T,T> setterBinder(Class<T> type,
      String name, int ind)
  throws IntrospectionException{
    if(type==null){
      return new DynamicIndexedPropertyWritingBinder<T>(name, ind);
    }
    else
      return new IndexedPropertyWritingBinder(BeanType.instance(type), name, ind);
  }
  /**
   * Create a new Component object that utilizes singleton pattern.
   * The component instance is cached the first time when the create()
   * method is called, and the same instance is returned for subsequent calls.
   * @param cc the Component object to create the component instance.
   * @return the new Component object.
   */
  public static <T> Component<T> singleton(Component<T> cc){
    if(cc.isSingleton()) return cc;
    return new SingletonComponent(cc);
  }
  /**
   * Create a new Component object that utilizes singleton pattern
   * within the scope of the provided Pool object.
   * The component instance is cached the first time when the create()
   * method is called, and the same instance is returned for subsequent calls.
   * @param cc the Component object to create the component instance.
   * @param scope the Pool object to specify the scope of the singleton pattern.
   * @return the new Component object.
   */
  public static <T> Component<T> singleton(Component<T> cc, Pool<T> scope){
    return new PooledComponent(cc, scope);
  }
  /**
   * Create a Component that instantiates a factory interface.
   * All factory method in this factory interface will delegate
   * to the component of the product to create the product.
   * @param cc the product creator.
   * @param factory_class the factory interface class.
   * @param loader the class loader to load the proxy class.
   * @param toString the string returned by the toString() method of the proxy.
   * @return the factory component.
   */
  public static <F> Component<F> factory(Creator cc, Class<F> factory_class,
      ClassLoader loader, String toString){
    final Component<F> r =
      new FactoryComponent<F>(cc, factory_class, loader, toString).label(toString);
    if(cc.isSingleton()){
      return r.singleton();
    }
    else return r;
  }
  /**
   * Create a Component that instantiates a factory interface.
   * All factory methods in this factory interface will delegate
   * to the component of the product to create the product.
   * @param cc the product creator.
   * @param factory_class the factory interface class.
   * @param toString the string returned by the toString() method of the factory object.
   * @return the factory component.
   */
  public static <F> Component<F> factory(Creator cc, Class<F> factory_class,
      String toString){
    if(Factory.class.equals(factory_class)){
      return factory(cc, toString);
    }
    return factory(cc, factory_class, factory_class.getClassLoader(),
        toString);
  }
  /**
   * Create a Component that instantiates the {@link Factory} interface.
   * The {@link Factory#create()} method delegates
   * to the component of the product to create the product.
   * @param cc the component responsible for instantiation.
   * @param toString the string returned by the toString() method of the factory.
   * @return the factory component.
   */
  public static <T> Component<Factory<T>> factory(Creator<T> cc, String toString){
    return new TheFactoryComponent<T>(cc, toString).label(toString);
  }
  static <T> Component<T> ensureComponent(Component<T> cc, Object key){
    if(cc==null)
      throw new UnresolvedComponentException(key);
    return cc;
  }
  /**
   * Adapt a LazyComponent object to Component.
   *
   * @param lcc the LazyComponent object.
   * @param key the name of the to-be-resolved component.
   * @return the new Component object.
   */
  public static <T> Component<T> fromLazy(final LazyComponent<T> lcc, final Object key){
    return new LazyComponent2Component<T>(lcc, key).guard();
  }
  /**
   * Create a Component object that delegates to another component
   * identified by a key in a container.
   * <br>
   * When create() method is called,
   * the getComponent() method is called against the target container to resolve the component.
   * <br>
   * This is a late-bound component because its type is resolved when create()
   * method is called.
   * @param cmap the container in which to resolve the component.
   * @param key the key of the component to delegate to.
   * @return the new Component object.
   */
  public static Component useKey(
      final ComponentMap cmap, final Object key){
    return fromLazy(new LazyComponent(){
      public Component eval(){
        return cmap.getComponent(key);
      }
      public Class getType(){return null;}
      public String toString(){return "useKey <"+key+">";}
    }, key).label();
  }
 
  /**
   * Create a component that uses a particular property value
   * of the parent component as its instance.
   * <br>
   * If a component is being instantiated as a property or parameter
   * of another component, then that other component is the parent
   * component in this context.
   * @param component_type the type of the component.
   * @param key the property key.
   * @param type the property type.
   * @return the Component object.
   */
  public static <T> Component<T> useProperty(
      final Class component_type, final Object key, final Class<T> type){
    return new UsePropertyComponent<T>(component_type, key, type).guard().label();
  }
  /**
   * Create a component that uses a particular argument value
   * of the parent component as its instance.
   * <br>
   * If a component is being instantiated as a property or parameter
   * of another component, then that other component is the parent
   * component in this context.
   * @param src the function requesting the argument.
   * @param pos the ordinal position of the argument.
   * @param type the parameter type.
   * @return the Component object.
   */
  public static <T> Component<T> useArgument(
      final Signature src, final int pos, final Class<T> type){
    return new UseArgumentComponent<T>(src, pos, type).guard().label();
  }
  /**
   * Create a Part object that redirects the resolution of a typed
   * parameter/property to another container.
   * @param cmap the container.
   * @return the Part object.
   */
  public static Part useContainer(final ComponentMap cmap){
    return new Part(){
      public Object create(Class type, Dependency dependency){
        return ensureComponent(cmap.getComponentOfType(type), type)
        .create(cmap.getDependencyOfType(type, cmap));
      }
      public Class verify(Class type, Dependency dependency){
        return ensureComponent(cmap.getComponentOfType(type), type)
        .verify(cmap.getDependencyOfType(type, cmap));
      }
    };
  }
  /**
   * Create a Component object that returns the container object.
   */
  public static Component<ComponentMap> thisContainer(){
    return ThisContainerComponent.instance();
  }
  /**
   * Create a Component object that delegates to another component in a container.
   * <br>
   * When create() method is called,
   * the getComponentOfType() method is called against the target container
   * to resolve the component.
   * <br>
   * This is a late-bound component because its type is resolved when create()
   * method is called.
   * @param cmap the container in which to resolve the component.
   * @param type the component type to look for.
   * @return the new Component object.
   */
  public static <T> Component<T> useType(
      final ComponentMap cmap, final Class<T> type){
    return fromLazy(new LazyComponent<T>(){
      public Component<T> eval(){
        return cmap.getComponentOfType(type);
      }
      public Class<T> getType(){return null;}
      public String toString(){
        return "useType <"+Misc.getTypeName(type) +">";
      }
    }, type).guard().label();
  }
  /**
   * Create a Component object that creates a java.util.List.
   * <br>
   * When create() method is called,
   * the getComponentsOfType() method is called against the target container
   * to resolve the components. The components found are invoked one by one
   * to create component instances.
   * Finally these instances are stored in a java.util.List object and returned
   * as the return value.
   * <br>
   * @param cmap the container in which to resolve the components.
   * @param type the component type to look for.
   * @return the new Component object.
   */
  public static <T> Component<ArrayList<T>> useAll(
      final ComponentMap cmap, final Class<T> type){
    return fromLazy(new LazyComponent<ArrayList<T>>(){
      public Component<ArrayList<T>> eval(){
        return list(cmap.getComponentsOfType(type));
      }
      public Class getType(){
        return java.util.ArrayList.class;
      }
      public String toString(){
        return "useAll <"+Misc.getTypeName(type)+">";
      }
    }, type).label();
  }
  /**
   * Create a Component object that creates a java.util.List. <br>
   * When method create() is called, it looks up in the target container
   * for all the components with a state value that satisfies the given predicate.
   * It then invokes these components one by one to create instances.
   * These instances are finally stored in a java.util.List and returned
   * as the return value.
   * @param cmap the target container.
   * @param pred the predicate to filter state value.
   * @return the Component object.
   */
  public static Component useState(
      final ComponentMap cmap, final Predicate pred){
    return fromLazy(new LazyComponent(){
      public Component eval(){
        return list(findComponents(cmap, pred));
      }
      public Class getType(){
        return java.util.ArrayList.class;
      }
      public String toString(){
        return "useState <"+pred+">";
      }
    }, pred).guard().label();
  }
  /**
   * Label the frame for a Component so that whenever a YanException is thrown,
   * the provided label will be populated in the resolution trace.
   * @param cc the component to label.
   * @param lbl the label.
   * @return the new Component object.
   */
  public static <T> Component<T> label(final Component<T> cc, final Object lbl){
    return new ClosureableComponent(cc){
      public Class verify(Dependency dp){
        try{
          return cc.verify(dp);
        }
        catch(YanException e){
          e.push(lbl);
          throw e;
        }
      }
      public Object create(Dependency dp){
        try{
          return cc.create(dp);
        }
        catch(YanException e){
          e.push(lbl);
          throw e;
        }
      }
      //label on a label immediately will ignore the previous label.
      public Component label(Object lbl){
        return cc.label(lbl);//Components.label(cc, lbl);
      }
      protected Component decorate(Component c){
        return Components.label(c, lbl);
      }
      public String toString(){
        return ""+lbl;
      }
    };
  }
  /**
   * Create a Component object that delegates to another component
   * identified by a key in the current container.
   * <br>
   * When create() method is called,
   * the getComponent() method is called against the current container to resolve the component.
   * <br>
   * This is a late-bound component because its type is resolved when create()
   * method is called.
   * @param key the key of the component to delegate to.
   * @return the new Component object.
   */

  public static Component useKey(final Object key){
    return new UseKeyComponent(key).guard().label();
  }
  /**
   * Create a Component object that delegates to another component
   * in the current container.
   * <br>
   * When create() method is called,
   * the getComponentOfType() method is called against the current container
   * to resolve the component.
   * <br>
   * This is a late-bound component because its type is resolved when create()
   * method is called.
   * @param type the component type to look for.
   * @return the new Component object.
   */
  public static <T> Component<T> useType(final Class<T> type){
    return new UseTypeComponent<T>(type).guard().label();
  }
  /**
   * Create a Component object that delegates to another component
   * in the current container.
   * <p>
   * When create() method is called,
   * the getComponentsOfType() method is called against the current container
   * to resolve the component. If no component is found or more than one are found,
   * it tries to search component using the alternative keys sequentially until
   * a Component is found.
   * </p>
   * <p>
   * UnresolvedComponentException is thrown if no Component is found at last.
   * </p>
   * This is a late-bound component because its type is resolved when create()
   * method is called.
   * @param type the component type to look for.
   * @param alternative_keys the alternative keys to try when search by type failed.
   * @return the new Component object.
   */
  public static <T> Component<T> autodetect(final Class<T> type, final Object[] alternative_keys){
    return new AutoDetectingComponent<T>(type, alternative_keys).guard().label();
  }
  /**
   * Create a Component object that creates a java.util.List.
   * <br>
   * When create() method is called,
   * the getComponentsOfType() method is called against the current container
   * to resolve the components. The components found are invoked one by one
   * to create component instances.
   * Finally these instances are stored in a java.util.List object and returned
   * as the return value.
   * <br>
   * @param type the component type to look for.
   * @return the new Component object.
   */
  public static <T> Component<List<T>> useAll(final Class<T> type){
    return new Component<List<T>>(){
      public Class verify(Dependency dependency){
        return list(findComponents(dependency.getComponentMap(), type))
        .verify(dependency);
      }
      public List<T> create(Dependency dependency){
        return list(findComponents(dependency.getComponentMap(), type))
        .create(dependency);
      }
      private java.util.List<Component<T>> findComponents(ComponentMap cmap,
          final Class<T> type){
        return cmap.getComponentsOfType(type);       
      }
      public Class getType(){
        return java.util.ArrayList.class;
      }
      public boolean isConcrete(){
        return true;
      }
      public String toString(){
        return "useAll <" + Misc.getTypeName(type)+">";
      }
      public boolean isSingleton(){
        return false;
      }
    }.guard().label();
  }
  private static java.util.List<Component> findComponents(ComponentMap cmap,
      final Predicate pred){
    final java.util.Collection all = cmap.getComponents();
    final java.util.ArrayList<Component> ret = new java.util.ArrayList<Component>();
    for(java.util.Iterator it=all.iterator();it.hasNext();){
      final Component c = (Component)it.next();
      if(pred.isObject(c.getState())){
        ret.add(c);
      }
    }
    return ret;
  }
  /**
   * Creates a Component that throws {@link jfun.yan.DefaultingException}.
   * This exception will be caught later and a default action is taken
   * according to the context. <br>
   * For example, Component expecting a mandatory parameter
   * will use null for default value; bean component will ignore
   * setting the property; withDefaultArgument or withDefaultProperty
   * will provide a default value.
   * @return the new Component object.
   */
  public static Component useDefault(){
    return UseDefaultComponent.instance();
  }
  /**
   * Create a Component object that creates a java.util.List. <br>
   * When method create() is called, it looks up in the current container
   * for all the components with a state value that satisfies the given predicate.
   * It then invokes these components one by one to create instances.
   * These instances are finally stored in a java.util.List and returned
   * as the return value.
   * @param pred the predicate to filter state value.
   * @return the Component object.
   */
  public static Component useState(final Predicate pred){
    return new Component(){
      public Class verify(Dependency dependency){
        final ComponentMap cmap = dependency.getComponentMap();
        return list(findComponents(cmap, pred)).verify(dependency);
      }
      public Object create(Dependency dependency){
        final ComponentMap cmap = dependency.getComponentMap();
        return list(findComponents(cmap, pred)).create(dependency);
      }
      public Class getType(){
        return java.util.ArrayList.class;
      }
      public boolean isConcrete(){
        return true;
      }
      public String toString(){
        return "useState <" + pred +">";
      }
      public boolean isSingleton(){
        return false;
      }
    }.guard().label();
  }
  /**
   * Create a Component object that returns the state of a Stateful object
   * as its component instance.
   * @param st the Stateful object.
   * @return the Component object.
   */
  public static Component returnState(final Stateful st){
    return new ReturnStateComponent(st).label();
  }
  /**
   * Create a Component object that returns the type of a Typeful object
   * as its component instance.
   * @param t the Typeful object.
   * @return the Component object.
   */
  public static Component returnType(final Typeful t){
    return new ReturnTypeComponent(t).guard().label();
  }
  /**
   * Create a Component object that verifies the Verifiable object
   * and returns the result type as return value.
   * @param veri the Verifiable object.
   * @return the Component object.
   */
  public static Component returnVerification(final Verifiable veri){
    return new ReturnVerificationComponent(veri).guard()
    .label();
  }
  /*
  private static Dependency setArguments(
      final Dependency dependency,
      final Creator[] factories){
    return new DelegatingDependency(dependency){
      public Object getArgument(int i, Class type){
        if(i<factories.length){
          final Object r = factories[i].create(dependency);
          Utils.checkArg(getComponentKey(), i, type, r);
          return r;
        }
        else return dependency.getArgument(i, type);
      }
      public Class verifyArgument(int i, Class type){
        if(i<factories.length){
          final Creator factory = factories[i];
          final Class r = factory.verify(dependency);
          Utils.checkType(getComponentKey(), i, type, r);
          return r;
        }
        else return dependency.verifyArgument(i, type);
      }
    };
  }
  private static Dependency setProperties(
      final Dependency dependency, final java.util.Map props){
    return new DelegatingDependency(dependency){
      public Object getProperty(Object k, Class type){
        final Creator cr = (Creator)props.get(k);
        if(cr != null){
          final Object r = cr.create(dependency);
          Utils.checkArg(getComponentKey(), k, type, r);
          return r;
        }
        else return dependency.getProperty(k, type);
      }
      public Class verifyProperty(Object k, Class type){
        final Creator cr = (Creator)props.get(k);
        if(cr != null){
          final Class r = cr.verify(dependency);
          Utils.checkType(getComponentKey(), k, type, r);
          return r;
        }
        else return dependency.verifyProperty(k, type);
      }
    };
  }
  private static Dependency setArgument(
      final Dependency dependency,
      final int k, final Creator factory){
    return new DelegatingDependency(dependency){
      public Object getArgument(int i, Class type){
        if(i==k){
          final Object r = factory.create(dependency);
          Utils.checkArg(getComponentKey(), i, type, r);
          return r;
        }
        else return dependency.getArgument(i, type);
      }
      public Class verifyArgument(int i, Class type){
        if(i==k){
          final Class r = factory.verify(dependency);
          Utils.checkType(getComponentKey(), i, type, r);
          return r;
        }
        else return dependency.verifyArgument(i, type);
      }
    };
  }*/
  private static Dependency setArguments(
      final Dependency dependency,
      final Part part){
    return new DelegatingDependency(dependency){
      public Object getArgument(Signature src, int i, Class type){
        final Object r = part.create(type, dependency);
        Utils.checkArg(src, getComponentKey(), i, type, r);
        return r;
      }
      public Class verifyArgument(Signature src, int i, Class type){
        final Class r = part.verify(type, dependency);
        Utils.checkType(src, getComponentKey(), i, type, r);
        return r;
      }
      public Dependency seal(){
        return setArguments(dependency.seal(), part);
      }
    };
  }
  private static Dependency setProperties(
      final Dependency dependency, final Part part){
    return new DelegatingDependency(dependency){
      public Object getProperty(Class component_type, Object k, Class type){
        final Object r = part.create(type, dependency);
        Utils.checkArg(component_type, getComponentKey(), k, type, r);
        return r;
      }
      public Class verifyProperty(Class component_type, Object k, Class type){
        final Class r = part.verify(type, dependency);
        Utils.checkType(component_type, getComponentKey(), k, type, r);
        return r;
      }
      public Dependency seal(){
        return setProperties(dependency.seal(), part);
      }
    };
  }
  /**
   * Create a ParameterBinder object using an array of Creator object
   * that will be used to create arguments.
   * @param args the creators for the arguments.
   * @return the ParameterBinder object.
   */
  static ParameterBinder getParameterBinder(final Creator[] args){
    return new ParameterBinder(){
      public Creator bind(final Signature src, int k, Class type){
        if(k>=0 && k < args.length){
          return args[k];
        }
        else return useArgument(src, k, type);
      }
    };
  }
  /**
   * Create a PropertyBinder object using Creator objects
   * stored in a java.util.Map object.
   * These creator objects will be used to create property values.
   * @param props the creators for the properties and their keys.
   * @return the PropertyBinder object.
   */
  static PropertyBinder getPropertyBinder(final java.util.Map props){
    return new PropertyBinder(){
      public Creator bind(Class component_type, Object k, Class type){
        final Creator r = (Creator)props.get(k);
        if(r==null) return useProperty(component_type, k, type);
        else return r;
      }
    };
  }
  /**
   * Customizes a Component's parameters with an array of Creator objects.
   * For parameter i,
   * creators[i] is used to create it if i is between 0 and factories.length.
   * the default creation strategy is used otherwise.
   * @param cc the Component to customize.
   * @param creators the creator objects for creating arguments.
   * @return the new Component object.
   */
  public static Component withArguments(
      final Component cc, final Creator... creators){
    return bindArguments(cc, getParameterBinder(creators));
    /*
    return new DecoratingComponent(cc){
      public  Object create(Dependency dependency){
        return cc.create(Components.setArguments(dependency, factories),
            ctxt);
      }
      public Class verify(Dependency dependency){
        return cc.verify(Components.setArguments(dependency, factories),
            ctxt);
      }
      protected Component decorate(Component cc){
        return Components.withArguments(cc, factories);
      }
    };*/
  }
  /**
   * Create a sealed component.
   * A sealed component assumes responsibility to
   * resolve its own dependencies.
   * It does not attempt to look up the container
   * to resolve any unresolved dependency.
   * <br>
   * seal can be used to disable auto-wiring at component level.
   * @param cc the component to seal.
   * @return the new Component object.
   */
  public static Component seal(final Component cc){
    return new ClosureableComponent(cc){
      public  Object create(Dependency dependency){
        return cc.create(dependency.seal());
      }
      public Class verify(Dependency dependency){
        return cc.verify(dependency.seal());
      }
      public String toString(){
        return "seal <" + cc + ">";
      }
      protected Component decorate(Component cc){
        return Components.seal(cc);
      }
      public Component seal(){
        return this;
      }
    }.label();
  }
 
  /**
   * To create a Component that ignores all subsequent
   * customizations to the parameters or properties.
   * @param c the Component to decorate.
   * @return the new Component that's guaranteed to auto-wire.
   */
  public static Component autowired(final Component c){
    return new ClosureableComponent(c){
      public  Object create(Dependency dependency){
        return c.create(dependency.getOriginal());
      }
      public Class verify(Dependency dependency){
        return c.verify(dependency.getOriginal());
      }
      public String toString(){
        return "autowired <" + c + ">";
      }
      protected Component decorate(Component cc){
        return Components.autowired(cc);
      }
    }.label();
  }
  /**
   * Customize the arguments of a component with a
   * {@link jfun.yan.ParameterBinder} object.
   * @param cc the component.
   * @param binder the ParameterBinder object.
   * @return the new Component.
   */
  public static Component bindArguments(
      final Component cc, final ParameterBinder binder){
    return new DecoratingComponent(cc){
      public  Object create(Dependency dependency){
        return cc.create(Components.bindArguments(dependency, binder));
      }
      public Class verify(Dependency dependency){
        return cc.verify(Components.bindArguments(dependency, binder));
      }
      //additionally cache the result at the top level to avoid creation of Dependency objects.
      public Component singleton(){
        return new SingletonComponent(super.singleton());
      }
      //additionally cache the result at the top level to avoid creation of Dependency objects.
      public Component singleton(Pool scope){
        return new PooledComponent(super.singleton(scope), scope);
      }
      protected Component decorate(Component cc){
        return cc.bindArguments(binder);
      }
    };
  }
  /**
   * Customize one argument of a component with a
   * {@link jfun.yan.ParameterBinder} object.
   * @param cc the component.
   * @param k the ordinal position of the parameter.
   * @param binder the ParameterBinder object.
   * @return the new Component.
   */
  public static Component bindArgument(
      final Component cc, final int k, final ParameterBinder binder){
    return bindArguments(cc, new ParameterBinder(){
      public Creator bind(final Signature src, int i, Class type){
        if(i==k){
          return binder.bind(src, i, type);
        }
        else return useArgument(src, i, type);
      }
    });
  }
  /**
   * Customizes a Component's properties with provided Creator objects
   * stored in a java.util.Map object.
   * @param cc the Component object to customize.
   * @param props the map that contains mappings between property keys
   * and Creator objects that creates the property value.
   * This Map object is not modified within this method.
   * It is allowed to subsequently change the Map object
   * after this method is called.
   * The new change will be picked up by the component
   * when creating instances.
   * If a property's key is not contained in the Map object,
   * the creation strategy is not changed for this property.
   * @return the new Component object.
   */
  public static Component withProperties(
      final Component cc, final java.util.Map props){
    return bindProperties(cc, getPropertyBinder(props));
    /*
    return new DecoratingComponent(cc){
      public  Object create(Dependency dependency){
        return cc.create(Components.setProperties(dependency, props));
      }
      public Class verify(Dependency dependency){
        return cc.verify(Components.setProperties(dependency, props));
      }
      public Component decorate(Component c){
        return Components.withProperties(c, props);
      }
    };*/
   
  }
  /**
   * Customize the properties of a component with a
   * {@link jfun.yan.PropertyBinder} object.
   * @param cc the component.
   * @param binder the PropertyBinder object.
   * @return the new Component.
   */
  public static Component bindProperties(
      final Component cc, final PropertyBinder binder){
    return new ClosureableComponent(cc){
      public  Object create(Dependency dependency){
        return cc.create(Components.bindProperties(dependency, binder));
      }
      public Class verify(Dependency dependency){
        return cc.verify(Components.bindProperties(dependency, binder));
      }
      //additionally cache the result at the top level to avoid creation of Dependency objects.
      public Component singleton(){
        return new SingletonComponent(super.singleton());
      }
      //additionally cache the result at the top level to avoid creation of Dependency objects.
      public Component singleton(Pool scope){
        return new PooledComponent(super.singleton(scope), scope);
      }
      public Component decorate(Component c){
        return c.bindProperties(binder);
      }
    };
  }
  /**
   * Customize the properties of a component with a
   * {@link jfun.yan.PropertyBinder} object.
   * @param cc the component.
   * @param k the property key.
   * @param binder the PropertyBinder object.
   * @return the new Component.
   */
  public static Component bindProperty(final Component cc,
      final Object k, final PropertyBinder binder){
    return bindProperties(cc, new PropertyBinder(){
      public Creator bind(Class component_type, Object i, Class type){
        if(i.equals(k)){
          return binder.bind(component_type, i,type);
        }
        else return useProperty(component_type, i, type);
      }
    });
  }
 
  /**
   * Customizes a Component's properties with the provided Creator objects.
   * For property identified by keys[i], creators[i] is used for creating value.
   * The keys array and creators array has to be the same length.
   * @param cc the Component object to customize.
   * @param names the property keys. Duplicate key is not allowed in this array.
   * Names are case-sensitive.
   * @param creators the creators for creating property values.
   * @return the new Component object.
   */
  public static Component withProperties(
      final Component cc, final String[] names, final Creator[] creators){
    return withProperties(cc, Utils.hashmap(names, creators));
  }

  /**
   * Redirects resolution of properties to arguments.
   * So that a property-based component (such as bean)
   * can be used as if it were a parameter-based on,
   * for which withArgument, withArguments can be used to customize.
   * <br>
   * It is useful when applying a property-based component to an algorithm
   * that relies on argument-based component.
   * The factory() combinator, for example, relies on parameter-based component.
   * @param cc the component to be redirected.
   * @param keys the property keys to redirect.
   * The ordinal position of each key indicates the position of the parameter.
   * @return the redirected Component object.
   */
  public static Component fromArguments(
      final Component cc, final Object... keys){
    return bindProperties(cc, new PropertyBinder(){
      public Creator bind(Class component_type, Object key, Class type){
        final int ind = findKey(key);
        if(ind < 0) return useProperty(component_type, key, type);
        else{
          final Signature sig = new Property2Signature(component_type, key, type);
          return useArgument(sig, ind, type);
        }
      }
      private int findKey(Object k){
        for(int i=0; i<keys.length;i++){
          if(Utils.eq(k, keys[i])) return i;
        }
        return -1;
      }
    });
  }
  /**
   * Redirects resolution of arguments to properties.
   * So that a parameter-based component (such as ctor or method)
   * can be used as if it were a bean component,
   * for which withProperty, withProperties can be used to customize.
   * <br>
   * It is useful when applying a parameter-based component to an algorithm
   * that relies on property-based component.
   * @param cc the component to be redirected.
   * @param keys the property keys for parameters.
   * The ordinal position of each key indicates the position of the parameter.
   * @return the redirected Component object.
   */
  public static Component fromProperties(
      final Component cc, final Object... keys){
    return bindArguments(cc, new ParameterBinder(){
      public Creator bind(final Signature src, int k, Class type){
        if(k<0 || k>=keys.length){
          return useArgument(src, k, type);
        }
        else return useProperty(src.getReturnType(), keys[k], type);
      }
    });
  }
  /**
   * Customizes a Component with a Part object to create all its parameters.
   * @param cc the Component object to customize.
   * @param part the Part object.
   * @return the new Component object.
   */
  public static Component withArguments(
      final Component cc, final Part part){
    return new ClosureableComponent(cc){
      public  Object create(Dependency dependency){
        return cc.create(Components.setArguments(dependency, part));
      }
      public Class verify(Dependency dependency){
        return cc.verify(Components.setArguments(dependency, part));
      }
      protected Component decorate(Component cc){
        return Components.withArguments(cc, part);
      }
    };
  }
  /**
   * Customizes a Component object with a Part object to create all its property values.
   * @param cc the Component object to customize.
   * @param part the Part object.
   * @return the new Component object.
   */
  public static Component withProperties(
      final Component cc, final Part part){
    return new ClosureableComponent(cc){
      public  Object create(Dependency dependency){
        return cc.create(Components.setProperties(dependency, part));
      }
      public Class verify(Dependency dependency){
        return cc.verify(Components.setProperties(dependency, part));
      }
      public Component decorate(Component c){
        return Components.withProperties(c, part);
      }
    };
  }
  /*
  private static Dependency sealDependency(Dependency dep){
    return new DelegatingDependency(dep){
      public Object getArgument(Signature src, int i, Class type){
        throw new IrresolveableArgumentException(getComponentKey(), i, type);
      }
      public Object getProperty(Class component_type, Object local_key, Class type){
        throw new IrresolveablePropertyException(getComponentKey(), local_key, type);
      }
      public Class verifyArgument(Signature src, int i, Class type){
        throw new IrresolveableArgumentException(getComponentKey(), i, type);
      }
      public Class verifyProperty(Class component_type, Object local_key, Class type){
        throw new IrresolveablePropertyException(getComponentKey(), local_key, type);
      }
      public Dependency seal(){return this;}
    };
  }*/
  private static Dependency setParent(final Dependency dep,
      final Dependency parent){
    return new DelegatingDependency(dep){;
      public Dependency getParent(){
        return parent;
      }
      public Dependency seal(){
        return setParent(dep.seal(), parent);
      }
    };
  }
  private static Dependency ofPart(final Dependency dep, Class type){
    final ComponentMap cmap = dep.getComponentMap();
    final Dependency newdep = cmap.getDependencyOfType(type, cmap);
    return setParent(newdep, dep);
  }
  private static Dependency ofProperty(final Dependency dep, Object key, Class type){
    return ofPart(dep, type);
  }
  private static Dependency ofParameter(Dependency dep, int ind, Class type){
    return ofPart(dep, type);
  }

  /**
   * Customize a Dependency object with a ParameterBinder object.
   * @param dependency the dependency object.
   * @param binder the ParameterBinder object.
   * @return the new Dependency object.
   */
  public static Dependency bindArguments(
      final Dependency dependency,
      final ParameterBinder binder){
    return new DelegatingDependency(dependency){
      public Object getArgument(Signature src, int i, Class type){
        final Object r = binder.bind(src, i, type)
        .create(ofParameter(dependency, i, type));
        Utils.checkArg(src, getComponentKey(), i, type, r);
        return r;
      }
      public Class verifyArgument(Signature src, int i, Class type){
        final Class r = binder.bind(src, i,type)
        .verify(ofParameter(dependency, i, type));
        Utils.checkType(src, getComponentKey(), i, type, r);
        return r;
      }
      public Dependency seal(){
        return bindArguments(dependency.seal(), binder);
      }
    };
  }
  /**
   * Customize a Dependency object with a PropertyBinder object.
   * @param dependency the dependency object.
   * @param binder the PropertyBinder object.
   * @return the new Dependency object.
   */
  public static Dependency bindProperties(
      final Dependency dependency,
      final PropertyBinder binder){
    return new DelegatingDependency(dependency){
      public Object getProperty(Class component_type, Object i, Class type){
        final Object r = binder.bind(component_type, i,type)
        .create(ofProperty(dependency, i, type));
        Utils.checkArg(component_type, getComponentKey(), i, type, r);
        return r;
      }
      public Class verifyProperty(Class component_type, Object i, Class type){
        final Class r = binder.bind(component_type, i, type)
        .verify(ofProperty(dependency, i, type));
        Utils.checkType(component_type, getComponentKey(), i, type, r);
        return r;
      }
      public Dependency seal(){
        return bindProperties(dependency.seal(), binder);
      }
    };
  }
/*
  private static Dependency setProperty(
      final Dependency dependency,
      final Object k, final Creator factory){
    return new DelegatingDependency(dependency){
      public Object getProperty(Object i, Class type){
        if(i.equals(k)){
          final Object r = factory.create(dependency);
          Utils.checkArg(getComponentKey(), i, type, r);
          return r;
        }
        else return dependency.getProperty(i, type);
      }
      public Class verifyProperty(Object i, Class type){
        if(i.equals(k)){
          final Class r = factory.verify(dependency);
          Utils.checkType(getComponentKey(), i, type, r);
          return r;
        }
        else return dependency.verifyProperty(i, type);
      }
    };
  }
  private static Dependency withDefaultProperty(
      final Dependency dependency,
      final Object k, final Creator factory){
    return new DelegatingDependency(dependency){
      public Object getProperty(Object i, Class type){
        try{
          return dependency.getProperty(i, type);
        }
        catch(DefaultingException e){
          if(i.equals(k)){
            Object r = factory.create(dependency);
            Utils.checkArg(getComponentKey(), i, type, r);
            return r;
          }
          else throw e;
        }
      }
      public Class verifyProperty(Object i, Class type){
        try{
          return dependency.verifyProperty(i, type);
        }
        catch(DefaultingException e){
          if(i.equals(k)){
            final Class r = factory.verify(dependency);
            Utils.checkType(getComponentKey(), i, type, r);
            return r;
          }
          else throw e;
        }
      }
    };
  }
  private static Dependency withDefaultArgument(
      final Dependency dependency,
      final int k, final Creator factory){
    return new DelegatingDependency(dependency){
      public Object getArgument(int i, Class type){
        Object r = dependency.getArgument(i, type);
        if(r==default_value() && i == k){
          r = factory.create(dependency);
          Utils.checkArg(getComponentKey(), i, type, r);
        }
        return r;
      }
      public Class verifyArgument(int i, Class type){
        Class r = dependency.verifyArgument(i, type);
        if(default_value().getClass().equals(r) && i == k){
          r = factory.verify(dependency);
          Utils.checkType(getComponentKey(), i, type, r);
        }
        return r;
      }
    };
  }
 
  private static boolean isPropertyIgnored(Class t){
    return getDefaultValueType().equals(t);
  }
  private static Class getDefaultValueType(){
    return default_value().getClass();
  }
  private static Class tryVerify(final Dependency dep, final Object key,
      final Class type){
    try{
      return dep.verifyProperty(key, type);
    }
    catch(ComponentResolutionException e){
      return getDefaultValueType();
    }
  }
 
  private static Class tryVerify(final Dependency dep, final int i,
      Class type){
    try{
      return dep.verifyArgument(i, type);
    }
    catch(ComponentResolutionException e){
      return getDefaultValueType();
    }
  }
  private static Object defaulting(Dependency dep, Object i,
      Class type){
    if(isPropertyIgnored(tryVerify(dep,
        i, type))){
      return default_value();
    }
    else return dep.getProperty(i, type);
  }
  private static Object defaulting(Dependency dep, int i,
      Class type){
    if(isPropertyIgnored(tryVerify(dep, i, type)))
      return default_value();
    else
      return dep.getArgument(i, type);
  }
  private static Dependency optionalProperties(final Dependency dependency){
    return new DelegatingDependency(dependency){
      public Object getProperty(Object i, Class type){
        return defaulting(getDelegateTarget(), i, type);
      }
      public Class verifyProperty(Object i, Class type){
        return tryVerify(getDelegateTarget(), i, type);
      }
    };
  }
  private static Dependency optionalParameters(final Dependency dependency){
    return new DelegatingDependency(dependency){
      public Object getArgument(int i, Class type){
        return defaulting(getDelegateTarget(), i, type);
      }
      public Class verifyArgument(int i, Class type){
        return tryVerify(getDelegateTarget(), i, type);
      }
    };
  }
  private static Dependency optionalProperty(
      final Dependency dependency,
      final Object k){
    return new DelegatingDependency(dependency){
      public Object getProperty(Object i, Class type){
        if(i.equals(k)){
          return defaulting(getDelegateTarget(), i, type);
        }
        else return dependency.getProperty(i, type);
      }
      public Class verifyProperty(Object i, Class type){
        if(i.equals(k)){
          return tryVerify(getDelegateTarget(), i, type);
        }
        else return dependency.verifyProperty(i, type);
      }
    };
  }

  private static Dependency optionalParameter(
      final Dependency dependency,
      final int k){
    return new DelegatingDependency(dependency){
      public Object getArgument(int i, Class type){
        if(i == k){
          return defaulting(getDelegateTarget(), i, type);
        }
        else return dependency.getArgument(i, type);
      }
      public Class verifyArgument(int i, Class type){
        if(i==k){
          return tryVerify(getDelegateTarget(), i, type);
        }
        return dependency.verifyArgument(i, type);
      }
    };
  }
 
  private static Dependency ignoreProperty(
      final Dependency dependency,
      final Object k){
    return new DelegatingDependency(dependency){
      public Object getProperty(Object i, Class type){
        if(i.equals(k)){
          return default_value();
        }
        return dependency.getProperty(i, type);
      }
      public Class verifyProperty(Object i, Class type){
        if(i.equals(k)){
          return type;
        }
        return dependency.verifyProperty(i, type);
      }
    };
  }*/

  private static Dependency setArgument(
      final Dependency dependency,
      final int k, final Part part){
    return new DelegatingDependency(dependency){
      public Object getArgument(Signature src, int i, Class type){
        if(i==k){
          final Object r = part.create(type, dependency);
          Utils.checkArg(src, getComponentKey(), i, type, r);
          return r;
        }
        else return dependency.getArgument(src, i, type);
      }
      public Class verifyArgument(Signature src, int i, Class type){
        if(i==k){
          final Class r = part.verify(type, dependency);
          Utils.checkType(src, getComponentKey(), i, type, r);
          return r;
        }
        else return dependency.verifyArgument(src, i, type);
      }
      public Dependency seal(){
        return setArgument(dependency.seal(), k, part);
      }
    };
  }
  private static Dependency setProperty(
      final Dependency dependency,
      final Object k, final Part part){
    return new DelegatingDependency(dependency){
      public Object getProperty(Class component_type, Object i, Class type){
        if(i.equals(k)){
          final Object r = part.create(type, dependency);
          Utils.checkArg(component_type, getComponentKey(), i, type, r);
          return r;
        }
        else return dependency.getProperty(component_type, i, type);
      }
      public Class verifyProperty(Class component_type, Object i, Class type){
        if(i.equals(k)){
          final Class r = part.verify(type, dependency);
          Utils.checkType(component_type, getComponentKey(), i, type, r);
          return r;
        }
        else return dependency.verifyProperty(component_type, i, type);
      }
      public Dependency seal(){
        return setProperty(dependency.seal(), k, part);
      }
    };
  }

  /**
   * Customizes the creation of one parameter of a Component object
   * using a Creator object.
   * @param cc the Component object to customize.
   * @param k the ordinal position of the parameter.
   * @param factory the creator object for creating that argument.
   * @return the new Component object.
   */
  public static Component withArgument(
      final Component cc,
      final int k, final Creator factory){
    return bindArgument(cc, k, constParamBinder(factory));
    /*
    return new DecoratingComponent(cc){
      public  Object create(Dependency dependency){
        return cc.create(Components.setArgument(dependency, k, factory));
      }
      public Class verify(Dependency dependency){
        return cc.verify(Components.setArgument(dependency, k, factory));
      }
      public Component decorate(Component c){
        return Components.withArgument(c, k, factory);
      }
    };*/
  }
  private static ParameterBinder constParamBinder(final Creator c){
    return new ParameterBinder(){
      public Creator bind(Signature src, int k, Class type){
        return c;
      }
    };
  }
  private static PropertyBinder constPropertyBinder(final Creator c){
    return new PropertyBinder(){
      public Creator bind(Class component_type, Object k, Class type){
        return c;
      }
    };
  }
  /**
   * Customizes the creation of one property value of a Component object
   * with a Creator object.
   * @param cc the Component object to customize.
   * @param k the property key.
   * @param factory the Creator object.
   * @return the new Component object.
   */
  public static <T> Component<T> withProperty(
      final Component<T> cc,
      final Object k, final Creator factory){
    return bindProperty(cc, k, constPropertyBinder(factory));
    /*
    return new DecoratingComponent(cc){
      public  Object create(Dependency dependency){
        return cc.create(Components.setProperty(dependency, k, factory));
      }
      public Class verify(Dependency dependency){
        return cc.verify(Components.setProperty(dependency, k, factory));
      }
      public Component decorate(Component c){
        return Components.withProperty(c, k, factory);
      }
    };*/
  }
  /**
   * Customizes the creation of one parameter of a Component object
   * with a Part object.
   * @param cc the Component object to customize.
   * @param part the Part object.
   * @return the new Component object.
   */
  public static <T> Component<T> withArgument(
      final Component<T> cc,
      final int k, final Part part){
    return new ClosureableComponent(cc){
      public  Object create(Dependency dependency){
        return cc.create(Components.setArgument(dependency, k, part));
      }
      public Class verify(Dependency dependency){
        return cc.verify(Components.setArgument(dependency, k, part));
      }
      public Component decorate(Component c){
        return Components.withArgument(c, k, part);
      }
    };
  }
  /**
   * Customizes the creation of one property value of a Component object
   * with a Part object.
   * @param cc the Component object to customize.
   * @param k the property key.
   * @param part the Part object.
   * @return the new Component object.
   */
  public static <T> Component<T> withProperty(
      final Component<T> cc,
      final Object k, final Part part){
    return new ClosureableComponent(cc){
      public  Object create(Dependency dependency){
        return cc.create(Components.setProperty(dependency, k, part));
      }
      public Class verify(Dependency dependency){
        return cc.verify(Components.setProperty(dependency, k, part));
      }
      public Component decorate(Component c){
        return Components.withProperty(c, k, part);
      }
    };
  }
 
  /**
   * Creates a new Component object that makes a property identified by a key
   * optional. <br>
   * When a component sees a property is passed in with the special
   * default value indicator, it skips the property.
   * <br>
   * However, this behavior can be changed when withDefaultProperty()
   * is used. In that case, the specified alternative Creator object
   * will be used to create the default value.
   * <br>
   * Technically, when UnresolvedComponentException
   * or UnsatisfiedComponentException is caught,
   * defaulting takes place.
   * @param cc the Component object.
   * @param k the property key to make optional.
   * @return the new Component object.
   */
  public static <T> Component<T> optionalProperty(
      final Component<T> cc, final Object k){
    return bindProperty(cc, k, _optional_prop);
    /*
    return new DecoratingComponent(cc){
      public  Object create(Dependency dependency){
        return cc.create(Components.optionalProperty(dependency, k));
      }
      public Class verify(Dependency dependency){
        return cc.verify(Components.optionalProperty(dependency, k));
      }
      public Component decorate(Component c){
        return Components.optionalProperty(c, k);
      }
    };*/
  }
  /**
   * Make sure the properties of a Java bean component are optional.
   * @param cc the bean component.
   * @return the new Component.
   */
  public static <T> Component<T> optionalProperties(final Component<T> cc){
    return bindProperties(cc, _optional_prop);
    /*
    return new DecoratingComponent(cc){
      public  Object create(Dependency dependency){
        return cc.create(Components.optionalProperties(dependency));
      }
      public Class verify(Dependency dependency){
        return cc.verify(Components.optionalProperties(dependency));
      }
      public Component optionalProperties(){return this;}
      public Component decorate(Component c){
        return Components.optionalProperties(c);
      }
    };*/
  }
  private static final ParameterBinder _optional_param = new ParameterBinder(){
    public Creator bind(Signature src, int i, Class type){
      return useArgument(src, i, type).optional();
    }
  };
  private static final PropertyBinder _optional_prop = new PropertyBinder(){
    public Creator bind(Class component_type, Object k, Class type){
      return useProperty(component_type, k, type).optional();
    }
  };
  /**
   * Make sure the parameters of a component are optional.
   * @param cc the component object.
   * @return the new component object.
   */
  public static <T> Component<T> optionalParameters(final Component<T> cc){
    return bindArguments(cc, _optional_param);
    /*
    return new DecoratingComponent(cc){
      public  Object create(Dependency dependency){
        return cc.create(Components.optionalParameters(dependency));
      }
      public Class verify(Dependency dependency){
        return cc.verify(Components.optionalParameters(dependency));
      }
      public Component optionalParameters(){return this;}
      public Component decorate(Component c){
        return Components.optionalParameters(c);
      }
    };*/
  }
  /**
   * Creates a new Component object that makes a parameter
   * optional.
   * <br>
   * Technically, when UnresolvedComponentException
   * or UnsatisfiedComponentException is caught,
   * defaulting takes place.
   * <br>
   * The default value is normally null. But when
   * withDefaultArgument() is used, it uses the value returned from the default Creator object. 
   * @param cc the Component object.
   * @param k the ordinal position of the parameter.
   * @return the new Component object.
   */
  public static <T> Component<T> optionalParameter(
      final Component<T> cc, final int k){
    return bindArgument(cc, k, _optional_param);
    /*
    return new DecoratingComponent(cc){
      public  Object create(Dependency dependency){
        return cc.create(Components.optionalParameter(dependency, k));
      }
      public Class verify(Dependency dependency){
        return cc.verify(Components.optionalParameter(dependency, k));
      }
      public Component decorate(Component c){
        return Components.optionalParameter(c, k);
      }
    };*/
  }
  /**
   * Create a Component object that will use an alternative Creator object
   * when a certain property cannot be resolved or is passed in as default.
   *
   * @param cc the original Compoenent object.
   * @param k the property key.
   * @param v the alternative Creator object.
   * @return the new Component object.
   */
  public static <T> Component<T> withDefaultProperty(final Component<T> cc,
      final Object k, final Creator v){
    final Recovery def =
      Monad.onException(DefaultingException.class, v);
    return bindProperty(cc, k, new PropertyBinder(){
      public Creator bind(Class component_type, Object i, Class type){
        return
        Monad.recover(
            Monad.mplus(useProperty(component_type, i, type), v),
            def
        );
      }
    });//cc.withProperty(k))
    /*
    return new DecoratingComponent(cc){
      public  Object create(Dependency dependency){
        return cc.create(Components.withDefaultProperty(dependency, k, v));
      }
      public Class verify(Dependency dependency){
        return cc.verify(Components.withDefaultProperty(dependency, k, v));
      }
      public Component decorate(Component c){
        return Components.withDefaultProperty(c, k, v);
      }
    };*/
  }
  /**
   * Create a Component object that will use an alternative Creator object
   * when a certain parameter cannot be resolved
   * or is passed in as default.
   *
   * @param cc the original Compoenent object.
   * @param k the ordinal position of the parameter.
   * @param v the alternative Creator object.
   * @return the new Component object.
   */
  public static <T> Component<T> withDefaultArgument(final Component<T> cc,
      final int k, final Creator v){
    return bindArgument(cc, k, new ParameterBinder(){
      final Recovery def = Monad.onException(DefaultingException.class, v);
      public Creator bind(Signature src, int i, Class type){
        return Monad.recover(
            Monad.mplus(useArgument(src, i, type), v),
            def
        );
      }
    });
    /*
    return new DecoratingComponent(cc){
      public  Object create(Dependency dependency){
        return cc.create(Components.withDefaultArgument(dependency, k, v));
      }
      public Class verify(Dependency dependency){
        return cc.verify(Components.withDefaultArgument(dependency, k, v));
      }
      public Component decorate(Component c){
        return Components.withDefaultArgument(c, k, v);
      }
    };*/
  }
  /**
   * Customizes the creation of properties and parameters of a Component object
   * with a Dependency object.
   * @param cc the Component object to customize.
   * @param dependency the Dependency object.
   * @return the new Component object.
   */
  static <T> Component<T> withDependency(
      final Component<T> cc, final Dependency dep){
    return new ClosureableComponent(cc){
      public  Object create(Dependency d){
        return cc.create(dep);
      }
      public Class verify(Dependency d){
        return cc.verify(dep);
      }
      public Component decorate(Component c){
        return Components.withDependency(c, dep);
      }
    };
  }

  /**
   * To create a Component that returns an element of the array/list
   * instance returned from another Component object.
   * @param c the Component object returning array or list.
   * @param ind the subscript.
   * @return the Component object.
   */
  public static Component subscript(final Component c, final int ind){
    final Component result = c.map(new Map(){
        public Object map(Object a){
          if(a==null)
            throw new IllegalArgumentException("subscript on null pointer");
          else if(a.getClass().isArray()){
            return Array.get(a, ind);
          }
          else if(a instanceof List){
            return ((List)a).get(ind);
          }
          else
            throw new IllegalArgumentException("cannot apply subscript against "
                + Misc.getTypeName(a.getClass()));
        }
      });
    return result;
  }
 
  /**
   * To create a Component object that calls method "get" against
   * the java.util.Map object instantiated by another Component.
   * @param c the Component object that instantiates a java.util.Map.
   * @param key the key.
   * @return the Component object that returns the value corresponding to the key.
   */
  public static Component get(Component c, final Object key){
    return c.map(new Map(){
      public Object map(Object o){
        if(o==null)
          throw new IllegalArgumentException("cannot apply get against null");
        if(o instanceof java.util.Map){
          return ((java.util.Map)o).get(key);
        }
        else
          throw new IllegalArgumentException("cannot apply get against "
              + Misc.getTypeName(o.getClass()));
      }
    });
  }
  /**
   * Decorate a Component object so that
   * the new Component object guards against infinite dependency loop.
   * @return the new Component object.
   */
  public static <T> Component<T> guard(Component<T> cc){
    if(cc.isSingleton()){
      //singleton do not need guarding.
      return cc;
    }
    return new GuardedComponent<T>(cc);
  }
  /**
   * Customizes a Component object with the specified user state.
   * @param cc the Component object to customize.
   * @param obj the user state object.
   * @return the new Component object.
   */
  public static <T> Component<T> withState(Component<T> cc, Object obj){
    return new StatefulComponent(cc, obj);
  }
  /**
   * Customizes a Component object with a new component type.
   * If the component is not late-bound (where getType() returns null),
   * the given type has to be same or super type of the component being customized.
   * @param cc the Component object.
   * @param type the target type.
   * @return the new Component object.
   */
  public static <Super, T extends Super> Component<Super> subsume(final Component<T> cc, final Class<Super> type){
    final Class subtype = cc.getType();
    if(subtype!=null){
      checkType(type, subtype);
      if(type.equals(subtype)){
        return (Component<Super>)cc;
      }
    }
    return new TypedComponent(cc, type){
      protected Component decorate(Component c){
        return Components.subsume(c, type);
      }
      public String toString(){
        return "subsume <" + cc + "> as " + Misc.getTypeName(type);
      }
    }.label();
  }
  /**
   * Decorate a Factory so that the return type is guaranteed to be
   * of a certain type.
   * @param type the expected type.
   * @param f the decorated Factory object.
   * @return the new Factory object.
   */
  private static <T> Factory<T> castFactory(final Class<T> type, final Factory<?> f){
    return new Factory<T>(){
      public T create(){
        final Object obj = f.create();
        checkInstanceType(type, obj);
        return (T)obj;
      }
      public String toString(){
        return f.toString();
      }
    };
  }
  private static abstract class TypedComponent extends DecoratingComponent{
    public Class getType(){
      return type;
    }
    public boolean isConcrete(){
      return false;
    }
    //for performance, we suppress type checking for Factory.
    public Component factory(String toString){
      return getDelegateTarget().factory(toString);
    }
    public Object create(Dependency dependency){
      return checkInstanceType(this.type, super
          .create(dependency));
    }
    public Class verify(Dependency dependency){
      super.verify(dependency);
      return getType();
    }
    private final Class type;
    TypedComponent(Component cc, Class type) {
      super(cc);
      this.type = type;
    }
   
  }
  /**
   * Customizes a Component object with a new component type.
   * Unlike subsume(), this method allows "down-cast"
   * where the current component instance type is a subtype of the given type.
   * It also allows "stupid-cast" where the current
   * component instance type has no is-a relationship with the target type.
   * <p>
   * cast forces type checks to be made on this type, regardless of the concrete type.
   * </p>
   * <p>
   * However, when the component's type is concrete, it forwards to subsume.
   * </p>
   * @param type the target type.
   * @return the new Component object.
   */

  public static <T> Component<T> cast(final Component<?> cc, final Class<T> type){
    final Class suptype = cc.getType();
    if(type == suptype) return (Component<T>)cc;
    if(type!=null && cc.isConcrete())
      return subsume((Component)cc, type);
    if(type != null && suptype != null && type.equals(suptype)){
      return (Component<T>)cc;
    }

    return new TypedComponent(cc, type){
      protected Component decorate(Component c){
        return Components.cast(c,getType());
      }
      public String toString(){
        return "cast <" + cc +"> as " + Misc.getTypeName(getType());
      }
    }.label();
  }
  /**
   * Customizes a Component object so that the new Component object
   * will return a dynamic proxy and hide the real component instance.
   * @param cc the Component object to customize.
   * @param itfs the interfaces to proxy to.
   * @return the new Component object.
   */
  public static Component proxy(final Component cc, final Class... itfs){
    if(itfs.length==0) //Do nothing for Object.
      return cc;
    return proxy(cc, itfs, itfs[0].getClassLoader());
  }
  /**
   * Customizes a Component object so that the new Component object
   * will return a dynamic proxy and hide the real component instance.
   * @param cc the Component object to customize.
   * @param itfs the interfaces to proxy to.
   * @param loader the ClassLoader object used to create the proxy.
   * @return the new Component object.
   */
  public static Component proxy(final Component cc,
      final Class[] itfs, final ClassLoader loader){
    if(itfs.length==0) //Do nothing for Object.
      return cc;
    final Class type = cc.getType();
    if(type!=null)
      checkTypes(itfs, type);
    //final Class proxyType = InstanceProxy.getProxyClass(cl, itfs);
    return new ProxyComponent(cc, itfs, loader).label();
  }
  /**
   * Customizes a Component object so that the new Component object
   * will return a dynamic proxy and hide the real component instance.
   * @param cc the Component object to customize.
   * @param itf the interface to proxy to.
   * @return the new Component object.
   */
  public static <I> Component<I> proxy(final Component<?> cc, Class<I> itf){
    return proxy(cc, toInterfaces(itf));
  }
  /**
   * Customizes a Component object so that the new Component object
   * will return a dynamic proxy and hide the real component instance.
   * The dynamic proxy will implement all the public interfaces
   * implemented by the type of the component being customized.
   * @param cc the Component object to customize.
   * @return the new Component object.
   */
  public static Component proxy(final Component cc){
    final Class ctype = cc.getType();
    if(ctype == null) return cc;
    return proxy(cc, ctype);
  }
  /**
   * Create a Component object that creates an array as instance.
   * Upon instance creation, it first invokes the Component objects provided
   * one by one and stores the result instances into an array.
   * The array is finally returned as the component instance.
   * @param ccs the Component objects.
   * @param etype the target array element type.
   * @return the new Component object.
   * @throws IllegalArgumentException if any component in the ccs array
   * has an incompatible type with the target array element type.
   */
  public static <T> Component<T[]> array(final Component<T>[] ccs,
      final Class<T> etype)
  throws IllegalArgumentException{
    final Class target_type = Misc.getArrayType(etype);
    final Component<T[]> step1 = new SimpleComponent<T[]>(target_type){
      public T[] create(){
        return (T[])Array.newInstance(etype, ccs.length);
      }
      public String toString(){
        return "array "+StringUtils.listArray("[",",","]",ccs)
          + ":"+Misc.getTypeName(target_type);
      }
    };
    return storeArray(step1, ccs);
    /*
    final Component[] cpy = new Component[ccs.length];
    for(int i=0; i<ccs.length; i++){
      final Component cc = ccs[i];
      final Class ctype = cc.getType();
      if(ctype!=null && !ReflectionUtil.isAssignableFrom(etype, ctype)){
        throw new IllegalArgumentException("type mismatch: the #"
            +i+" element is a component of "+Misc.getTypeName(ctype)
            +", while the expected type is "+Misc.getTypeName(etype));
      }
      cpy[i] = ccs[i];
    }
    return new ArrayComponent(cpy, target_type).guard().label();*/
  }
  public static <T> Component<T[]> storeArray(Component<T[]> component_returning_array,
      Creator<T>... creators){
    final Class type = component_returning_array.getType();
    final Class etype = type==null?null:type.getComponentType();
    return component_returning_array
      .followedBy(new ArrayStoreBinder<T>(creators, etype))
      .label();
  }
  /**
   * Create a Component object that creates an array as instance.
   * Upon instance creation, it first invokes the Component objects provided
   * one by one and stores the result instances into an array.
   * The array is finally returned as the component instance.
   * <br>
   * The element type of the result array is determined by the types
   * of the Component objects in the ccs array.
   * The algorithm is as following:
   * if any type is a common super type of all other component types,
   * that type is used as the element type,
   * Object.class is used otherwise.
   * Note, this algorithm does not attempt to analyze the least common
   * super type. So if type 1 is Integer, type 2 is Short,
   * Object is used as the element type rather than Number.
   *
   * @param ccs the Component objects.
   * @return the new Component object.
   */
  public static <T> Component<T[]> array(final Component<T>... ccs){
    return array(ccs, Utils.getCommonRootType(ccs));
    /*
    return new ArrayComponent(copy(ccs),
        Misc.getArrayType(Utils.getCommonRootType(ccs)))
    .guard().label();*/
  }
 
  /**
   * Create a Component object that creates java.util.ArrayList.
   * Upon instance creation, it first invokes the Creator objects provided
   * one by one and stores the result instances into a java.util.ArrayList object.
   * The list is finally returned as the component instance.
   *
   * @param ccs the Creator objects.
   * @return the new Component object.
   */
  public static <T> Component<ArrayList<T>> list(final Creator<T>... ccs){
    //return new ListComponent(ccs).guard().label();
    final Component<ArrayList<T>> step1 = new SimpleComponent<ArrayList<T>>(ArrayList.class){
      public ArrayList<T> create(){
        return new ArrayList<T>(ccs.length);
      }
      public String toString(){
        return "list "+StringUtils.listArray("[",",","]",ccs);
      }
    };
    return storeList(step1, ccs);
  }
  /**
   * Create a Component object that sequentially execute an array of components
   * and collect the result into a java.util.List object.
   * @param component_returning_list the Component object that returns a java.util.List.
   * @param creators the components to be executed sequentially.
   * @return the new Component object.
   */
  public static <T,L extends List<T>> Component<L> storeList(final Component<L> component_returning_list,
      final Creator<T>... creators){
    return component_returning_list.followedBy(new StoreBinder<T,L>(creators){
      public ElementStore<T> toStore(L v){
        if(v instanceof List){
          return new ListStore<T>(v);
        }
        throw new ClassCastException("java.util.List expected, "
            +Utils.getObjTypeName(v)+" encountered");
      }
    }).label();
   
  }
  /**
   * Create a Component object that creates java.util.HashSet.
   * Upon instance creation, it first invokes the Creator objects provided
   * one by one and stores the result instances into a java.util.HashSet object.
   * The set is finally returned as the component instance.
   *
   * @param ccs the Creator objects.
   * @return the new Component object.
   */
  public static <T> Component<HashSet<T>> hashset(final Creator<T>... ccs){
    //return new ListComponent(ccs).guard().label();
    final Component<HashSet<T>> step1 = new SimpleComponent<HashSet<T>>(HashSet.class){
      public HashSet<T> create(){
        return new HashSet<T>(ccs.length);
      }
      public String toString(){
        return "hashset "+StringUtils.listArray("[",",","]",ccs);
      }
    };
    return storeSet(step1, ccs);
  }
  /**
   * Create a Component object that sequentially execute an array of components
   * and collect the result into a java.util.Set object.
   * @param component_returning_set the Component object that returns a java.util.Set.
   * @param creators the components to be executed sequentially.
   * @return the new Component object.
   */
  public static <T, S extends Set<T>> Component<S> storeSet(final Component<S> component_returning_set,
      final Creator<T>... creators){
    return component_returning_set.followedBy(new StoreBinder<T,S>(creators){
      public ElementStore<T> toStore(S v){
        if(v instanceof Set){
          return new SetStore<T>(v);
        }
        throw new ClassCastException("java.util.Set expected, "
            +Utils.getObjTypeName(v)+" encountered");
      }
    }).label();
  }
  /**
   * Create a Component object that creates java.util.ArrayList.
   * Upon instance creation, it first invokes the Creator objects provided
   * one by one and stores the result instances into a java.util.List object.
   * The list is finally returned as the component instance.
   *
   * @param ccs the Creator objects.
   * @return the new Component object.
   */
  public static <T, C extends Creator<T>> Component<ArrayList<T>> list(final java.util.List<C> ccs){
    final Creator<T>[] crs = new Creator[ccs.size()];
    ccs.toArray(crs);
    return list(crs);
  }

  /**
   * Create a Component object that creates a java.util.LinkedHashMap object.
   * <br>
   * Upon instance creation, it first invokes the Creator objects stored
   * in the parameter creators one by one.
   * The created instances along with
   * the corresponding keys stored in the parameter keys
   * are saved in a new java.util.LinkedHashMap object.
   * This new java.util.LinkedHashMap object is finally returned as the component
   * instance of this component.
   * <br>
   * The instances are populated into the java.util.LinkedHashMap object
   * in the same order as keys, so that keys[0] is the first element in the
   * java.util.LinkedHashMap object.
   * @param keys the keys for each instance.
   * @param creators the Creator objects for each instance.
   * @return the Component object.
   * @throws IllegalArgumentException if keys.length != creators.length
   * or any duplicate key is found in the keys array.
   */
  public static <K,T> Component<java.util.LinkedHashMap<K, T>> hashmap(final K[] keys, final Creator<T>[] creators)
  throws IllegalArgumentException{
    //return hashmap(Utils.lhashmap(keys, creators));
    if(keys.length != creators.length){
      throw new IllegalArgumentException("keys.length=="+keys.length
          + ", vals.length=="+creators.length);
    }
    final Component<LinkedHashMap<K,T>> step1 = new SimpleComponent<LinkedHashMap<K,T>>(LinkedHashMap.class){
      public LinkedHashMap<K,T> create(){
        return new LinkedHashMap<K,T>(keys.length);
      }
    };
    return storeMap(step1, keys, creators);
  }
 
  /**
   * Create a Component that sequentially execute an array of Component object,
   * and collect the results in a java.util.Map object.
   * @param component_return_map the Component that creates the java.util.Map object.
   * @param keys the keys to use.
   * @param vals the components to be sequentially executed.
   * @return the new Component object.
   */
  public static <K,T,M extends java.util.Map<K,T>> Component<M> storeMap(final Component<M> component_return_map,
      final K[] keys, Creator<T>[] vals){
    return component_return_map.followedBy(new StoreBinder<T,M>(vals){
      public ElementStore<T> toStore(M v){
        if(v instanceof java.util.Map){
          return new MapStore<K,T>(keys, v);
        }
        else{
          throw new ClassCastException("java.util.Map expected, "+
              Utils.getObjTypeName(v)+" encountered.");
        }
      }
    }).label();
   
  }
  /**
   * By default, all components depended by a component
   * will be verified when the component is verified.
   * incomplete() creates a new Component object that
   * suppresses the verification of dependency.
   * <br>
   * This customization cannot be applied to a late-bound component
   * whose getType() returns null.
   * In order to suppress verification, first use subsume() or cast()
   * to give it a type.
   * @param cc the Component to suppress verification for its parameters/properties.
   * @return the new Component object.
   * @throws UnknownComponentTypeException if the Component is a late-bound
   * component whose getType() returns null.
   */
  public static <T> Component<T> incomplete(final Component<T> cc)
  throws UnknownComponentTypeException{
    final Class ctype = cc.getType();
    if(ctype ==null){
      throw new UnknownComponentTypeException("immature component " + cc +
          " cannot be made incomplete");
    }
    return new ClosureableComponent(cc){
      public Class verify(Dependency dependency){
        return ctype;
      }
      protected Component decorate(Component c){
        return Components.incomplete(c);
      }
      public String toString(){
        return "incomplete <" + cc + ">";
      }
    }.label();
  }
 
 
  /**
   * Customizes a Component object so that upon creation,
   * the new Component object mutates the result component instance before it is returned.
   * @param cc the Component object to mutate.
   * @param m the Mutation object encapsulating the mutation logic.
   * @return the new Component object.
   */
  public static <T> Component<T> mutate(final Component<T> cc, final Mutation<T> m){
    //return new MutateComponent(cc, m).label();
    return cc.followedBy(new Mutation2Binder<T>(m));
  }
 
  /**
   * Create a Component that repeatedly call another Component for
   * certain amount of times.
   * @param cc the component to repeated call.
   * @param times the number of times to repeat.
   * @return the new Component object.
   */
  public static <T> Component<T> repeat(final Creator<T> cc, final int times){
    if(times<0)
      throw new IllegalArgumentException("negative repeat times: "+times);
    if(times==0)
      return value(null);
    if(times==1)
      return adapt(cc);
    return new RepeatComponent<T>(cc, times).label();
  }
 
  /**
   * Create a Component that the "create()" method is put in a
   * synchronized block to ensure thread safety.
   * @param cc the Component object.
   * @return the Component object that is "synchronized".
   */
  public static <T> Component<T> synchronizedComponent(final Component<T> cc){
    return new SynchronizedComponent(cc);
  }
  static Class[] toInterfaces(Class type){
    if(type.isInterface()){
      return new Class[]{type};
    }
    else return type.getInterfaces();
  }
  private static void checkType(final Class itf, final Class type){
    if(!ReflectionUtil.isAssignableFrom(itf, type)){
      throw new IllegalArgumentException(
          Misc.getTypeName(type) + " is not a subtype of "
          + Misc.getTypeName(itf));
    }
  }
  private static void checkTypes(final Class[] itfs, final Class type){
    for(int i=0; i<itfs.length; i++){
      final Class itf = itfs[i];
      checkType(itf, type);
    }
  }
  /*
  private static final class DefaultValue implements java.io.Serializable{
    public String toString(){
      return "default_value";
    }
  }
  private static final Object default_value = new DefaultValue();
*/
  private static Object checkInstanceType(final Class type, final Object r) {
    if(type != null && !ReflectionUtil.isInstance(type, r)){
      throw new TypeMismatchException(type, r==null?null:r.getClass(),
          Misc.getTypeName(type)
          +" expected, while " + Misc.getTypeName(Utils.getObjType(r))
          +" encountered.");
    }
    return r;
  }
}
TOP

Related Classes of jfun.yan.Components$TypedComponent

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.