KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > jfun > yan > Components


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

8 /*
9  * Created on Feb 28, 2005
10  *
11  * Author Ben Yu
12  * ZBS
13  */

14 package jfun.yan;
15
16 import java.beans.IntrospectionException JavaDoc;
17 import java.lang.reflect.Array JavaDoc;
18 import java.lang.reflect.Field JavaDoc;
19 import java.lang.reflect.Method JavaDoc;
20 import java.util.ArrayList JavaDoc;
21 import java.util.HashSet JavaDoc;
22 import java.util.LinkedHashMap JavaDoc;
23 import java.util.List JavaDoc;
24 import java.util.Set JavaDoc;
25
26
27 import jfun.util.Misc;
28 import jfun.util.StringUtils;
29 import jfun.util.beans.Bean;
30 import jfun.util.beans.BeanType;
31 import jfun.util.beans.NoSuchPropertyException;
32 import jfun.yan.element.ElementStore;
33 import jfun.yan.element.ListStore;
34 import jfun.yan.element.MapStore;
35 import jfun.yan.element.SetStore;
36 import jfun.yan.factory.Factory;
37 import jfun.yan.factory.Pool;
38 import jfun.yan.function.Function;
39 import jfun.yan.function.Property2Signature;
40 import jfun.yan.function.Signature;
41 import jfun.yan.util.Predicate;
42 import jfun.yan.util.ReflectionUtil;
43
44 /**
45  * This class provides implementations of some basic components
46  * as well as most of the commonly used combiniators
47  * for Component.
48  * A combinator is a function that will combine one or more Component objects
49  * and create a more complex Component object.
50  *
51  * <p>
52  * Codehaus.org.
53  *
54  * @author Ben Yu
55  *
56  */

57 public final class Components {
58   /**
59    * To adapt a Creator object to a Component object.
60    * if the object is already a Component, itself is returned.
61    * @param c the creator object.
62    * @return the Component object.
63    */

64   public static <T> Component<T> adapt(Creator<T> c){
65     if(c instanceof Component){
66       return (Component<T>)c;
67     }
68     else return new Creator2Component<T>(c);
69   }
70   /**
71    * Create a Component object that uses a Function to create instance.
72    * @param fun the Function object.
73    * @return the Component object.
74    */

75   public static <T> Component<T> fun(Function<T> fun){
76     //do not label it because this extra frame does not bring
77
//much useful information.
78
return new FunctionComponent<T>(fun).guard();
79   }
80   /**
81    * Create a Component object that uses the constructor of a class
82    * to create instance of that class.
83    * This class should have one and only one public constructor.
84    * <br>
85    * Array type is given a special constructor so that the constructor of
86    * array type T has one parameter of type int
87    * and calls new T[size] when invoked.
88    * @param c the class.
89    * @return the Component object.
90    * @throws IllegalArgumentException
91    * if the class is not public or has no public constructor
92    * or has more than one public constructor.
93    */

94   public static <T> Component<T> ctor(Class JavaDoc<T> c)
95   throws IllegalArgumentException JavaDoc{
96     return fun(Functions.ctor(c));
97   }
98   /**
99    * Create a Component that uses one constructor of a class
100    * to create instance of that class.
101    * The constructor to invoke is determined by the parameter types specified.
102    * <br>
103    * Array type is given a special constructor so that the constructor of
104    * array type T has one parameter of type int
105    * and calls new T[size] when invoked.
106    * @param c the class.
107    * @param param_types the parameter types of the constructor to use.
108    * null indicates the default constructor.
109    * @return the Component object.
110    * @throws IllegalArgumentException
111    * if the type is not public or the public constructor cannot be found.
112    */

113   public static <T> Component<T> ctor(Class JavaDoc<T> c, Class JavaDoc[] param_types)
114   throws IllegalArgumentException JavaDoc{
115     return fun(Functions.ctor(c, param_types));
116   }
117   /**
118    * Create a Component object that invokes a static method to create instance.
119    * This class should have one and only one public static method of this name.
120    * @param c the class where the static method belongs.
121    * @param name the static method name.
122    * @return the Component object.
123    * @throws IllegalArgumentException
124    * thrown if any of the following conditions is true: <br>
125    * 1. this method is not public. <br>
126    * 2. this method is not static. <br>
127    * 3. more than one public static method with the specified name. <br>
128    * 4. no public static method with the specified name. <br>
129    */

130   public static Component static_method(Class JavaDoc c, String JavaDoc name)
131   throws IllegalArgumentException JavaDoc{
132     return fun(Functions.static_method(c, name));
133   }
134   /**
135    * Create a Component object that invokes a static method to create instance.
136    * The static method to invoke is determined by the method name
137    * and the parameter types.
138    * @param c the class where the static method belongs.
139    * @param name the static method name.
140    * @param param_types the parameter types.
141    * null indicates a parameter-less method.
142    * @return the Component object.
143    * @throws IllegalArgumentException
144    * thrown if any of the following conditions is true: <br>
145    * 1. this method is not public. <br>
146    * 2. this method is not static. <br>
147    * 3. no public static method with the specified name and the parameter types. <br>
148    */

149   public static Component static_method(
150       Class JavaDoc c, String JavaDoc name, Class JavaDoc[] param_types){
151     return fun(
152         Functions.static_method(c, name, param_types));
153   }
154   /**
155    * Create a Component object that invokes a method against a given object
156    * to create component instance.
157    * The class of the object
158    * should have one and only one public method of this name.
159    * @param obj the object to run the method against. It cannot be null.
160    * @param name the method name.
161    * @return the Component object.
162    * @throws IllegalArgumentException
163    * thrown if any of the following conditions is true: <br>
164    * 1. this method is not public. <br>
165    * 2. more than one public method with the specified name. <br>
166    * 3. no public method with the specified name. <br>
167    */

168   public static Component method(Object JavaDoc obj, String JavaDoc name){
169     return fun(Functions.method(obj, name));
170   }
171   /**
172    * Create a Component object that invokes a method against a given object
173    * to create component instance.
174    * The class of the object
175    * should have one and only one public static method of this name.
176    * @param type the Class object to look up method.
177    * This parameter can be used when we only want to look up in
178    * a super type rather than obj.getClass().
179    * @param obj the object to run the method against.
180    * It can be null if the method is static.
181    * @param name the method name.
182    * @return the Component object.
183    * @throws IllegalArgumentException
184    * thrown if any of the following conditions is true: <br>
185    * 1. this method is not public. <br>
186    * 2. more than one public method with the specified name. <br>
187    * 3. no public method with the specified name. <br>
188    */

189   public static Component method(Class JavaDoc type, Object JavaDoc obj, String JavaDoc name){
190     return fun(Functions.method(type, obj, name));
191   }
192   /**
193    * Create a Component object that invokes a method against a given object
194    * to create component instance.
195    * The method to invoke is determined by the method name
196    * and the parameter types.
197    * @param obj the object to run the method against.
198    * It cannot be null.
199    * @param name the method name.
200    * @param param_types the parameter types.
201    * null indicates a parameter-less method.
202    * @return the Component object.
203    * @throws IllegalArgumentException
204    * thrown if any of the following conditions is true: <br>
205    * 1. this method is not public. <br>
206    * 2. no public method with the specified name and the parameter types. <br>
207    */

208   public static Component method(
209       Object JavaDoc obj, String JavaDoc name, Class JavaDoc[] param_types){
210     return fun(
211         Functions.method(obj, name, param_types));
212   }
213   /**
214    * Create a Component object that invokes a method against a given object
215    * to create component instance.
216    * The method to invoke is determined by the method name
217    * and the parameter types.
218    * @param type the Class object to look up method.
219    * This parameter can be used when we only want to look up in
220    * a super type rather than obj.getClass().
221    * @param obj the object to run the method against.
222    * It can be null if the method is static.
223    * @param name the method name.
224    * @param param_types the parameter types.
225    * null indicates a parameter-less method.
226    * @return the Component object.
227    * @throws IllegalArgumentException
228    * thrown if any of the following conditions is true: <br>
229    * 1. this method is not public. <br>
230    * 2. no public method with the specified name and the parameter types. <br>
231    */

232   public static Component method(Class JavaDoc type,
233       Object JavaDoc obj, String JavaDoc name, Class JavaDoc[] param_types){
234     return fun(
235         Functions.method(type, obj, name, param_types));
236   }
237   /**
238    * Create a Component object that reads a static field to create instance.
239    * @param c the class where the static instance belongs.
240    * @param name the static instance name.
241    * @return the Component object.
242    * @throws IllegalArgumentException
243    * thrown if any of the following conditions is true: <br>
244    * 1. field not found. <br>
245    * 2. field is not static. <br>
246    */

247   public static Component static_field(Class JavaDoc c, String JavaDoc name)
248   throws IllegalArgumentException JavaDoc{
249     return fun(Functions.static_field(c, name));
250   }
251   /**
252    * Create a Component object that reads a field from a given object
253    * to create component instance.
254    * @param type the Class object to look up field.
255    * This parameter can be used when we only want to look up in
256    * a super type rather than obj.getClass().
257    * @param obj the object to read field from.
258    * It can be null if the field is static.
259    * @param name the field name.
260    * @return the Component object.
261    * @throws IllegalArgumentException
262    * thrown if any of the following conditions is true: <br>
263    * 1. field is not found.
264    */

265   public static Component field(Class JavaDoc type, Object JavaDoc obj, String JavaDoc name){
266     return fun(Functions.field(type, obj, name));
267   }
268   /**
269    * Create a Component object that reads a field from a given object
270    * to create component instance.
271    * @param obj the object to read the field from. It cannot be null.
272    * @param name the field name.
273    * @return the Component object.
274    * @throws IllegalArgumentException
275    * thrown if any of the following conditions is true: <br>
276    * 1. field not found.
277    */

278   public static Component field(Object JavaDoc obj, String JavaDoc name){
279     return fun(Functions.field(obj, name));
280   }
281   /**
282    * Create a Component that calls a property getter of an object.
283    * @param type the type to introspect.
284    * @param obj the object to run the getter against.
285    * @param prop the property name.
286    * @return the Component object.
287    * @throws IntrospectionException if introspection fails.
288    * @throws NoSuchPropertyException if the property does not exist.
289    * @throws NonReadablePropertyException if the property is not rreadable.
290    */

291   public static Component getter(Class JavaDoc type, Object JavaDoc obj, String JavaDoc prop)
292   throws IntrospectionException JavaDoc, NoSuchPropertyException,
293   NonReadablePropertyException{
294     final BeanType btype = BeanType.instance(type);
295     final Method JavaDoc m = btype.getReader(prop);
296     if(m==null)
297       throw new NonReadablePropertyException(type, prop);
298     return fun(Functions.getter(Bean.instance(type, obj), prop));
299   }
300   /**
301    * Create a Component that calls a property setter against an object.
302    *
303    * @param type the type to introspect.
304    * @param obj the object.
305    * @param prop the property name.
306    * @return the Component object.
307    * @throws IntrospectionException if introspection fails.
308    * @throws NoSuchPropertyException if the the property cannot be found.
309    * @throws NonWritablePropertyException if the property is not writable.
310    */

311   public static <T> Component<T> setter(Class JavaDoc type, T obj, String JavaDoc prop)
312   throws IntrospectionException JavaDoc, NoSuchPropertyException,
313   NonWritablePropertyException{
314     final BeanType btype = BeanType.instance(type);
315     if(btype.getWriter(prop)==null && btype.getIndexedWriter(prop)==null)
316       throw new NonWritablePropertyException(type, prop);
317     return fun(Functions.setter(Bean.instance(type, obj), prop));
318   }
319   /**
320    * Create a Component that calls an indexed property getter of an object.
321    * @param type the type to introspect.
322    * @param obj the object to run the getter against.
323    * @param prop the property name.
324    * @param ind the index.
325    * @return the Component object.
326    * @throws IntrospectionException if introspection fails.
327    * @throws NoSuchPropertyException if the property does not exist.
328    * @throws NonReadablePropertyException
329    * if the property is not rreadable or if the property is not indexed.
330    */

331   public static Component indexed_getter(Class JavaDoc type, Object JavaDoc obj, String JavaDoc prop, int ind)
332   throws IntrospectionException JavaDoc, NoSuchPropertyException,
333   NonReadablePropertyException{
334     final BeanType btype = BeanType.instance(type);
335     final Method JavaDoc m = btype.getIndexedReader(prop);
336     if(m==null)
337       throw new NonReadablePropertyException(type, prop);
338     return fun(Functions.indexed_getter(Bean.instance(type, obj), prop, ind));
339   }
340   /**
341    * Create a Component that calls an indexed property setter against an object.
342    *
343    * @param type the type to introspect.
344    * @param obj the object.
345    * @param prop the property name.
346    * @param ind the index.
347    * @return the Component object.
348    * @throws IntrospectionException if introspection fails.
349    * @throws NoSuchPropertyException if the the property cannot be found.
350    * @throws NonWritablePropertyException
351    * if the property is not writable or not indexed.
352    */

353   public static <T> Component<T> indexed_setter(Class JavaDoc type, T obj, String JavaDoc prop, int ind)
354   throws IntrospectionException JavaDoc, NoSuchPropertyException,
355   NonWritablePropertyException{
356     final BeanType btype = BeanType.instance(type);
357     final Method JavaDoc m = btype.getIndexedWriter(prop);
358     if(m==null)
359       throw new NonWritablePropertyException(type, prop);
360     return fun(Functions.indexed_setter(Bean.instance(type, obj), prop, ind));
361   }
362
363   /**
364    * Create a Component that calls a property getter of an object.
365    * @param obj the object to run the getter against.
366    * @param prop the property name.
367    * @return the Component object.
368    * @throws IntrospectionException if introspection fails.
369    * @throws NoSuchPropertyException if the property does not exist.
370    * @throws NonReadablePropertyException if the property is not rreadable.
371    */

372   public static Component getter(Object JavaDoc obj, String JavaDoc prop)
373   throws IntrospectionException JavaDoc, NoSuchPropertyException,
374   NonReadablePropertyException{
375     return getter(obj.getClass(), obj, prop);
376   }
377   /**
378    * Create a Component that calls a property setter against an object.
379    *
380    * @param obj the object to run the setter against.
381    * @param prop the property name.
382    * @return the Component object.
383    * @throws IntrospectionException if introspection fails.
384    * @throws NoSuchPropertyException if the the property cannot be found.
385    * @throws NonWritablePropertyException if the property is not writable.
386    */

387   public static <T> Component<T> setter(T obj, String JavaDoc prop)
388   throws IntrospectionException JavaDoc, NoSuchPropertyException,
389   NonWritablePropertyException{
390     return setter(obj.getClass(), obj, prop);
391   }
392   /**
393    * Create a Component that calls an indexed property getter of an object.
394    * @param obj the object to run the getter against.
395    * @param prop the property name.
396    * @param ind the index.
397    * @return the Component object.
398    * @throws IntrospectionException if introspection fails.
399    * @throws NoSuchPropertyException if the property does not exist.
400    * @throws NonReadablePropertyException
401    * if the property is not rreadable or if the property is not indexed.
402    */

403   public static Component indexed_getter(Object JavaDoc obj, String JavaDoc prop, int ind)
404   throws IntrospectionException JavaDoc, NoSuchPropertyException,
405   NonReadablePropertyException{
406     return indexed_getter(obj.getClass(), obj, prop, ind);
407   }
408   /**
409    * Create a Component that calls an indexed property setter against an object.
410    *
411    * @param obj the object to run the setter against.
412    * @param prop the property name.
413    * @param ind the index.
414    * @return the Component object.
415    * @throws IntrospectionException if introspection fails.
416    * @throws NoSuchPropertyException if the the property cannot be found.
417    * @throws NonWritablePropertyException
418    * if the property is not writable or not indexed.
419    */

420   public static <T> Component<T> indexed_setter(T obj, String JavaDoc prop, int ind)
421   throws IntrospectionException JavaDoc, NoSuchPropertyException,
422   NonWritablePropertyException{
423     return indexed_setter(obj.getClass(), obj, prop, ind);
424   }
425   
426   /**
427    * Create a Component object that simply return a value upon instance creation.
428    * The type of the value is used as the type of the component.
429    * null is permitted as a value too.
430    * void.class is used as the type of the component if the value is null.
431    * @param val the value.
432    * @return the Component object.
433    */

434   public static <T> Component<T> value(final T val){
435     if(val==null) return NilComponent.instance;
436     return new ValueComponent<T>(val);
437   }
438   /**
439    * Create a Component object that simply return a value upon instance creation.
440    * double.class is used as the component type.
441    * @param val the value.
442    * @return the Component object.
443    */

444   public static Component<Double JavaDoc> value(final double val){
445     return value(new Double JavaDoc(val)).cast(double.class);
446   }
447   /**
448    * Create a Component object that simply return a value upon instance creation.
449    * float.class is used as the component type.
450    * @param val the value.
451    * @return the Component object.
452    */

453   public static Component<Float JavaDoc> value(final float val){
454     return value(new Float JavaDoc(val)).cast(float.class);
455   }
456   /**
457    * Create a Component object that simply return a value upon instance creation.
458    * long.class is used as the component type.
459    * @param val the value.
460    * @return the Component object.
461    */

462   public static Component<Long JavaDoc> value(final long val){
463     return value(new Long JavaDoc(val)).cast(long.class);
464   }
465   /**
466    * Create a Component object that simply return a value upon instance creation.
467    * int.class is used as the component type.
468    * @param val the value.
469    * @return the Component object.
470    */

471   public static Component<Integer JavaDoc> value(final int val){
472     return value(new Integer JavaDoc(val)).cast(int.class);
473   }
474   /**
475    * Create a Component object that simply return a value upon instance creation.
476    * short.class is used as the component type.
477    * @param val the value.
478    * @return the Component object.
479    */

480   public static Component<Short JavaDoc> value(final short val){
481     return value(new Short JavaDoc(val)).cast(short.class);
482   }
483   /**
484    * Create a Component object that simply return a value upon instance creation.
485    * byte.class is used as the component type.
486    * @param val the value.
487    * @return the Component object.
488    */

489   public static Component<Byte JavaDoc> value(final byte val){
490     return value(new Byte JavaDoc(val)).cast(byte.class);
491   }
492   /**
493    * Create a Component object that simply return a value upon instance creation.
494    * char.class is used as the component type.
495    * @param val the value.
496    * @return the Component object.
497    */

498   public static Component<Character JavaDoc> value(final char val){
499     return value(new Character JavaDoc(val)).cast(char.class);
500   }
501   /**
502    * Create a Component object that simply return a value upon instance creation.
503    * boolean.class is used as the component type.
504    * @param val the value.
505    * @return the Component object.
506    */

507   public static Component<Boolean JavaDoc> value(final boolean val){
508     return val?true_component:false_component;
509   }
510
511   private static Component<Boolean JavaDoc> return_bool(boolean b){
512     return value(Boolean.valueOf(b)).cast(boolean.class);
513   }
514   private static final Component<Boolean JavaDoc> true_component = return_bool(true);
515   private static final Component<Boolean JavaDoc> false_component = return_bool(false);
516   /**
517    * Create a new Component object from a base Component object
518    * that calls Java Bean setters after the base Component creates the instance.
519    * <br>
520    * Upon instance creation, it first calls the base Component.
521    * The base Component is responsible for creating the component instance.
522    * The bean component then calls the java bean setters
523    * for the property names specified against the component instance
524    * to finish the component creation process.
525    * <br>
526    * The Java Bean setters used to create the component instance are
527    * determined by the return value of getType() method.
528    * That means, if getType() returns Type1 while the actual instance created is
529    * a subtype of Type1, only the setters of Type1 are used.
530    * However, if the base component is late-bound, where the getType() returns null,
531    * the Java Bean setters are resolved at creation time.
532    * <br>
533    * It should be noted that,
534    * for a singleton bean component obtained by calling singleton() method
535    * against the bean component, it does not cause infinite loop
536    * if any property of the component is depending on this same singleton bean componet.
537    * This is because the singleton bean component caches the instance
538    * before any of the properties are set.
539    * @param cc the base Component object.
540    * @param props the names of the properties used.
541    * @return the new Component object.
542    * @throws IntrospectionException if java bean introspection fails.
543    * @throws IllegalPropertyNameException if a name specified in
544    * the props Set is not a valid property name.
545    * @throws NonWritablePropertyException
546    * if a property specified has no setter.
547    */

548   public static <T> Component<T> bean(final Component<T> cc, java.util.Set JavaDoc props)
549   throws IntrospectionException JavaDoc,
550   IllegalPropertyNameException, NonWritablePropertyException{
551     final PropertiesInjector pi =
552       DefaultPropertiesInjector.instance(cc.getType(), props);
553     return makeBean(cc, pi);
554     /*
555     return BeanBinder.instance(cc, props).guard()
556     .label();
557     */

558   }
559   /**
560    * Create a Bean component that calls a PropertiesInjector to inject
561    * bean properties to the bean instance.
562    * @param cc the component that instantiates the bean instance.
563    * @param injector the injector to inject properties.
564    * @return the bean component.
565    */

566   public static <T> Component<T> makeBean(Component<T> cc, PropertiesInjector injector){
567     return makeBean(injector.toString(), cc, injector);
568   }
569   /**
570    * Create a Bean component that calls a PropertiesInjector to inject
571    * bean properties to the bean instance.
572    * @param name the name of the bean component.
573    * @param cc the component that instantiates the bean instance.
574    * @param injector the injector to inject properties.
575    * @return the bean component.
576    */

577   public static <T> Component<T> makeBean(String JavaDoc name,
578       Component<T> cc, PropertiesInjector injector){
579     return Monad.followedBy(cc, new BeanBinder<T>(name, injector)).label(name);
580   }
581   /**
582    * Create a new Component object from a base Component object
583    * that calls Java Bean setters after the base Component creates the instance.
584    * <br>
585    * Upon instance creation, it first calls the base Component.
586    * The base Component is responsible for creating the component instance.
587    * The bean component then calls the java bean setters to the component instance
588    * to finish the component creation process.
589    * <br>
590    * The Java Bean setters used to create the component instance are
591    * determined by the return value of getType() method.
592    * That means, if getType() returns Type1 while the actual instance created is
593    * a subtype of Type1, only the setters of Type1 are used.
594    * However, if the base component is late-bound, where the getType() returns null,
595    * the Java Bean setters are resolved at creation time.
596    * <br>
597    * It should be noted that,
598    * for a singleton bean component obtained by calling singleton() method
599    * against the bean component, it does not cause infinite loop
600    * if any property of the component is depending on this same singleton bean componet.
601    * This is because the singleton bean component caches the instance
602    * before any of the properties are set.
603    * @param cc the base Component object.
604    * @return the new Component object.
605    * @throws IntrospectionException if java bean introspection fails.
606    */

607   public static <T> Component<T> bean(final Component<T> cc)
608   throws IntrospectionException JavaDoc{
609     final PropertiesInjector pi = DefaultPropertiesInjector.instance(cc.getType());
610     return makeBean(cc, pi);
611     //return BeanBinder.instance(cc).guard().label();
612
}
613   /**
614    * Create a Component object that uses Java Bean convention to create instance.
615    * i.e. It first calls the default constructor of the class, then calls all
616    * the Java Bean setters to finish the instance creation.
617    * <br>
618    * It should be noted that,
619    * for a singleton bean component obtained by calling singleton() method
620    * against the bean component, it does not cause infinite loop
621    * if any property of the component is depending on this same singleton bean componet.
622    * This is because the singleton bean component caches the instance
623    * before any of the properties are set.
624    * @param type the Java Bean class.
625    * @return the Component object.
626    * @throws IntrospectionException if Java Bean introspection fails.
627    * @throws IllegalArgumentException if the class is not public
628    * or does not have public default constructor.
629    */

630   public static <T> Component<T> bean(final Class JavaDoc<T> type)
631   throws IntrospectionException JavaDoc, IllegalArgumentException JavaDoc{
632     return bean(ctor(type, null));
633   }
634   /**
635    * Create a Component object that uses Java Bean convention to create instance.
636    * i.e. It first calls the default constructor of the class, then calls all
637    * the Java Bean setters for the properties specified to finish the instance creation.
638    * <br>
639    * It should be noted that,
640    * for a singleton bean component obtained by calling singleton() method
641    * against the bean component, it does not cause infinite loop
642    * if any property of the component is depending on this same singleton bean componet.
643    * This is because the singleton bean component caches the instance
644    * before any of the properties are set.
645    * @param type the Java Bean class.
646    * @param props the names of the properties used.
647    * @return the new Component object.
648    * @throws IntrospectionException if Java Bean introspection fails.
649    * @throws IllegalPropertyNameException if any property name specified is not valid.
650    * @throws NonWritablePropertyException if any property specified has no setter.
651    */

652   public static <T> Component<T> bean(final Class JavaDoc<T> type, java.util.Set JavaDoc props)
653   throws IntrospectionException JavaDoc, IllegalPropertyNameException,
654   NonWritablePropertyException{
655     return Components.bean(ctor(type, null), props);
656   }
657   /**
658    * Create a new Component object from a base Component object
659    * that calls Java Bean setters after the base Component creates the instance.
660    * <br>
661    * Upon instance creation, it first calls the base Component.
662    * The base Component is responsible for creating the component instance.
663    * The bean component then calls the java bean setters
664    * for the property names specified against the component instance
665    * to finish the component creation process.
666    * <br>
667    * The Java Bean setters used to create the component instance are
668    * determined by the return value of getType() method.
669    * That means, if getType() returns Type1 while the actual instance created is
670    * a subtype of Type1, only the setters of Type1 are used.
671    * However, if the base component is late-bound, where the getType() returns null,
672    * the Java Bean setters are resolved at creation time.
673    * <br>
674    * It should be noted that,
675    * for a singleton bean component obtained by calling singleton() method
676    * against the bean component, it does not cause infinite loop
677    * if any property of the component is depending on this same singleton bean componet.
678    * This is because the singleton bean component caches the instance
679    * before any of the properties are set.
680    * @param cc the base Component object.
681    * @param props the names of the properties used.
682    * @return the new Component object.
683    * @throws IntrospectionException if java bean introspection fails.
684    * @throws IllegalPropertyNameException if a name specified in
685    * the props Set is not a valid property name.
686    * @throws NonWritablePropertyException
687    * if a property specified has no setter.
688    * @throws IllegalArgumentException if the props array has any duplicate name.
689    */

690   public static <T> Component<T> bean(final Component<T> cc, String JavaDoc... props)
691   throws IntrospectionException JavaDoc, IllegalPropertyNameException,
692   NonWritablePropertyException, IllegalArgumentException JavaDoc{
693     return Components.bean(cc, jfun.yan.util.Utils.toSet(props, "property name"));
694   }
695   /**
696    * Create a Component object that uses Java Bean convention to create instance.
697    * i.e. It first calls the default constructor of the class, then calls all
698    * the Java Bean setters for the properties specified to finish the instance creation.
699    * <br>
700    * It should be noted that,
701    * for a singleton bean component obtained by calling singleton() method
702    * against the bean component, it does not cause infinite loop
703    * if any property of the component is depending on this same singleton bean componet.
704    * This is because the singleton bean component caches the instance
705    * before any of the properties are set.
706    * @param type the Java Bean class.
707    * @param props the names of the properties used.
708    * @return the new Component object.
709    * @throws IntrospectionException if Java Bean introspection fails.
710    * @throws IllegalPropertyNameException if any property name specified is not valid.
711    * @throws NonWritablePropertyException if any property specified has no setter.
712    * @throws IllegalArgumentException if the props array has any duplicate name.
713    */

714   public static <T> Component<T> bean(final Class JavaDoc<T> type, String JavaDoc[] props)
715   throws IntrospectionException JavaDoc, IllegalPropertyNameException,
716   NonWritablePropertyException, IllegalArgumentException JavaDoc{
717     return bean(ctor(type, null), props);
718   }
719   
720   /**
721    * Creates a Component that will call a certain method
722    * against the instance created by another Component.
723    * The return value of the method is used as the result of the
724    * created Component.
725    * @param cc the Component to create the instance.
726    * @param mtd the methdo to call against the instance.
727    * @return the new Component object.
728    */

729   public static Component bindMethod(final Component cc, final Method JavaDoc mtd){
730     return Monad.bind(autowired(cc), new MethodBinder(mtd)).label(""+cc+".<"+mtd+">")
731     .guard();
732   }
733   /**
734    * Creates a Component that will call a certain method
735    * against the instance created by another Component.
736    * The return value of the method is used as the result of the
737    * created Component.
738    * <br>
739    * If the type of the first component is statically known (getType()!=null),
740    * The method is statically resolved when bindMethod() is called.
741    * Otherwise, it is resolved when the actual component instantiation happens.
742    * @param cc the Component to create the instance.
743    * @param name the method name.
744    * @param suppress_security whether access to non-public method is allowed.
745    * @return the new Component object.
746    * @throws IllegalArgumentException if the static resolution of the method
747    * fails.
748    */

749   public static Component bindMethod(final Component cc, final String JavaDoc name,
750       boolean suppress_security)
751   throws IllegalArgumentException JavaDoc{
752     final String JavaDoc lbl = ""+cc+"."+name + "( ... )";
753     final Class JavaDoc type = cc.getType();
754     return Monad.bind(autowired(cc), invokingMethod(type, name, suppress_security))
755     .label(lbl).guard();
756   }
757   /**
758    * Creates a Component that will call a certain method
759    * against the instance created by another Component.
760    * The return value of the method is used as the result of the
761    * created Component.
762    * <br>
763    * If the type of the first component is statically known (getType()!=null),
764    * The method is statically resolved when bindMethod() is called.
765    * Otherwise, it is resolved when the actual component instantiation happens.
766    * @param cc the Component to create the instance.
767    * @param name the method name.
768    * @param param_count the number of formal parameters.
769    * @param suppress_security whether access to non-public method is allowed.
770    * @return the new Component object.
771    * @throws IllegalArgumentException if the static resolution of the method
772    * fails.
773    */

774   public static Component bindMethod(final Component cc,
775       final String JavaDoc name, final int param_count,
776       boolean suppress_security)
777   throws IllegalArgumentException JavaDoc{
778     final String JavaDoc lbl = ReflectionUtil.toMethodString(name, param_count);
779     final Class JavaDoc type = cc.getType();
780     return Monad.bind(autowired(cc), invokingMethod(type, name, param_count, suppress_security))
781     .label(lbl).guard();
782   }
783   /**
784    * Creates a Component that will read a certain field
785    * from the instance created by another Component.
786    * The return value of the field is used as the result of the
787    * created Component.
788    * @param cc the Component to create the instance.
789    * @param fld the methdo to read from the instance.
790    * @return the new Component object.
791    */

792   public static Component bindField(final Component cc, final Field JavaDoc fld){
793     return Monad.bind(autowired(cc), new FieldBinder(fld)).label(""+cc+".<"+fld+">")
794     .guard();
795   }
796
797   /**
798    * Creates a Component that will read a certain field
799    * from the instance created by another Component.
800    * The return value of the field is used as the result of the
801    * created Component.
802    * @param cc the Component to create the instance.
803    * @param name the field name.
804    * @param suppress_security whether access to non-public field is allowed.
805    * @return the new Component object.
806    * @throws IllegalArgumentException if the static resolution of the field
807    * fails.
808    */

809   public static Component bindField(final Component cc, final String JavaDoc name,
810       boolean suppress_security)
811   throws IllegalArgumentException JavaDoc{
812     final String JavaDoc lbl = ""+cc+"."+name;
813     final Class JavaDoc type = cc.getType();
814     return Monad.bind(autowired(cc), readingField(type, name, suppress_security))
815     .label(lbl).guard();
816   }
817   
818   /**
819    * Create a ComponentBinder object that invokes a method against the
820    * bound object.
821    * @param type the type to search the method against. Null defers the
822    * search to runtime.
823    * @param name the method name.
824    * @param suppress_security Are non-public methods searched at all?
825    * @return the ComponentBinder object.
826    */

827   public static ComponentBinder invokingMethod(Class JavaDoc type, String JavaDoc name,
828       final boolean suppress_security){
829     if(type==null)
830       return new MethodNameBinder(name,suppress_security);
831     else
832       return new MethodBinder(ReflectionUtil.getMethod(type, name, suppress_security));
833   }
834   /**
835    * Create a ComponentBinder object that invokes a method against the
836    * bound object.
837    * @param type the type to search the method against. Null defers the
838    * search to runtime.
839    * @param name the method name.
840    * @param param_count the number of formal parameters.
841    * @param suppress_security Are non-public methods searched at all?
842    * @return the ComponentBinder object.
843    */

844   public static ComponentBinder invokingMethod(Class JavaDoc type, String JavaDoc name,
845       int param_count, final boolean suppress_security){
846     if(type==null)
847       return new MethodNameParamCountBinder(name,param_count,suppress_security);
848     else
849       return new MethodBinder(ReflectionUtil.getMethod(type, name,
850           param_count, suppress_security));
851   }
852   
853   /**
854    * Create a ComponentBinder object that reads a field value from
855    * the bound object.
856    * @param type the type to search the field against. Null defers the search
857    * to runtime.
858    * @param name the field name.
859    * @param suppress_security Are non-public fields searched at all?
860    * @return the ComponentBinder object.
861    */

862   public static ComponentBinder readingField(Class JavaDoc type, String JavaDoc name,
863       boolean suppress_security){
864     if(type==null)
865       return new FieldNameBinder(name, suppress_security);
866     else
867       return new FieldBinder(ReflectionUtil.getField(type, name, suppress_security));
868   }
869   /**
870    * Creates a Component that will call a certain method
871    * against the instance created by another Component.
872    * The return value of the method is used as the result of the
873    * created Component.
874    * <br>
875    * If the type of the first component is statically known (getType()!=null),
876    * The method is statically resolved when bindMethod() is called.
877    * Otherwise, it is resolved when the actual component instantiation happens.
878    * @param cc the Component to create the instance.
879    * @param name the method name.
880    * @param param_types the parameter types of the method. null indicates
881    * a parameter-less method.
882    * @return the new Component object.
883    * @throws IllegalArgumentException if the static resolution of the method
884    * fails.
885    */

886   public static Component bindMethod(final Component cc,
887       final String JavaDoc name, final Class JavaDoc[] param_types, boolean suppress_security)
888   throws IllegalArgumentException JavaDoc{
889     final String JavaDoc lbl =
890       ""+cc+"."+name + jfun.util.StringUtils.listString("(",",",")",param_types);
891     final Class JavaDoc type = cc.getType();
892     return Monad.bind(autowired(cc),
893         invokingMethod(type, name, param_types, suppress_security))
894     .label(lbl).guard();
895   }
896   /**
897    * To create a ComponentBinder object that invokes a method
898    * against the bound object.
899    * @param type the type to search the method against. Null defers the search
900    * to runtime.
901    * @param name the method name.
902    * @param param_types the parameter types.
903    * @param suppress_security are non-public methods considered at all?
904    * @return the ComponentBinder object.
905    */

906   public static ComponentBinder invokingMethod(Class JavaDoc type, String JavaDoc name,
907       Class JavaDoc[] param_types, boolean suppress_security){
908     if(type==null){
909       return new DynamicMethodBinder(name, param_types, suppress_security);
910     }
911     else
912       return new MethodBinder(ReflectionUtil.getMethod(type, name, param_types,
913           suppress_security));
914   }
915   /**
916    * Create a Component that will return a bean property
917    * of the instance created by another component.
918    * @param cc the component to create the instance.
919    * @param name the property name.
920    * @return the new Component object.
921    * @throws IntrospectionException if introspection fails.
922    */

923   public static Component bindGetter(final Component cc,
924       final String JavaDoc name)throws IntrospectionException JavaDoc{
925     final String JavaDoc lbl = ""+cc+"."+name;
926     final Class JavaDoc type = cc.getType();
927     return Monad.bind(autowired(cc), invokingGetter(type, name))
928     .label(lbl).guard();
929   }
930   /**
931    * To create a ComponentBinder object that invokes a Java Bean getter
932    * against the bound object.
933    * @param type the type to introspect for the property. Null defers the
934    * introspection to runtime.
935    * @param name the property name.
936    * @return the ComponentBinder object.
937    * @throws IntrospectionException when bean introspection fails.
938    */

939   public static ComponentBinder invokingGetter(Class JavaDoc type, String JavaDoc name)
940   throws IntrospectionException JavaDoc{
941     if(type==null){
942       return new DynamicPropertyReadingBinder(name);
943     }
944     else
945       return new PropertyReadingBinder(BeanType.instance(type), name);
946   }
947   /**
948    * Create a Component that will set a bean property
949    * of the instance created by another component.
950    * <br>
951    * The bean instance will still be used as the result.
952    * @param cc the component to create the instance.
953    * @param name the property name.
954    * @return the new Component object.
955    * @throws IntrospectionException if introspection fails.
956    */

957   public static Component bindSetter(final Component cc,
958       final String JavaDoc name)
959   throws IntrospectionException JavaDoc{
960     final String JavaDoc lbl = ""+cc+"."+name+"=";
961     final Class JavaDoc type = cc.getType();
962     return Monad.bind(autowired(cc), invokingSetter(type,name))
963           .label(lbl).guard();
964   }
965   /**
966    * Create a ComponentBinder object that will invoke a Java Bean setter
967    * against the bound object.
968    * @param type the type to introspect for the property. Null defers the
969    * introspection to runtime.
970    * @param name the property name.
971    * @return the ComponentBinder object
972    * @throws IntrospectionException when bean introspection fails.
973    */

974   public static <T> ComponentBinder<T,T> invokingSetter(Class JavaDoc<T> type, String JavaDoc name)
975   throws IntrospectionException JavaDoc{
976     if(type==null){
977       return new DynamicPropertyWritingBinder<T>(name);
978     }
979     else
980       return new PropertyWritingBinder(BeanType.instance(type), name);
981   }
982   /**
983    * Create a Component that will get an indexed property
984    * of the Java Bean instance created by another component.
985    * @param cc the component to create the instance.
986    * @param name the property name.
987    * @param ind the index.
988    * @return the new Component object.
989    * @throws IntrospectionException if introspection fails.
990    */

991   public static Component bindGetter(final Component cc,
992       final String JavaDoc name, final int ind)throws IntrospectionException JavaDoc{
993     final String JavaDoc lbl = ""+cc+"."+name+"["+ind+"]";
994     final Class JavaDoc type = cc.getType();
995     return Monad.bind(autowired(cc), getterBinder(type, name, ind))
996     .label(lbl).guard();
997   }
998   private static ComponentBinder getterBinder(Class JavaDoc type,
999       final String JavaDoc name, final int ind)
1000  throws IntrospectionException JavaDoc{
1001    if(type==null){
1002      return new DynamicIndexedPropertyReadingBinder(name, ind);
1003    }
1004    else
1005      return new IndexedPropertyReadingBinder(BeanType.instance(type), name, ind);
1006  }
1007  /**
1008   * Create a Component that will set an indexed property
1009   * of the Java Bean instance created by another component.
1010   * <br>
1011   * The bean instance will still be used as the result.
1012   * @param cc the component to create the instance.
1013   * @param name the property name.
1014   * @param ind the index.
1015   * @return the new Component object.
1016   * @throws IntrospectionException if introspection fails.
1017   */

1018  public static <T> Component<T> bindSetter(final Component<T> cc,
1019      final String JavaDoc name, final int ind)throws IntrospectionException JavaDoc{
1020    final String JavaDoc lbl = ""+cc+"."+name+"["+ind+"]=";
1021    final Class JavaDoc type = cc.getType();
1022    return Monad.bind(autowired(cc), setterBinder(type, name, ind))
1023    .label(lbl).guard();
1024  }
1025  private static <T> ComponentBinder<T,T> setterBinder(Class JavaDoc<T> type,
1026      String JavaDoc name, int ind)
1027  throws IntrospectionException JavaDoc{
1028    if(type==null){
1029      return new DynamicIndexedPropertyWritingBinder<T>(name, ind);
1030    }
1031    else
1032      return new IndexedPropertyWritingBinder(BeanType.instance(type), name, ind);
1033  }
1034  /**
1035   * Create a new Component object that utilizes singleton pattern.
1036   * The component instance is cached the first time when the create()
1037   * method is called, and the same instance is returned for subsequent calls.
1038   * @param cc the Component object to create the component instance.
1039   * @return the new Component object.
1040   */

1041  public static <T> Component<T> singleton(Component<T> cc){
1042    if(cc.isSingleton()) return cc;
1043    return new SingletonComponent(cc);
1044  }
1045  /**
1046   * Create a new Component object that utilizes singleton pattern
1047   * within the scope of the provided Pool object.
1048   * The component instance is cached the first time when the create()
1049   * method is called, and the same instance is returned for subsequent calls.
1050   * @param cc the Component object to create the component instance.
1051   * @param scope the Pool object to specify the scope of the singleton pattern.
1052   * @return the new Component object.
1053   */

1054  public static <T> Component<T> singleton(Component<T> cc, Pool<T> scope){
1055    return new PooledComponent(cc, scope);
1056  }
1057  /**
1058   * Create a Component that instantiates a factory interface.
1059   * All factory method in this factory interface will delegate
1060   * to the component of the product to create the product.
1061   * @param cc the product creator.
1062   * @param factory_class the factory interface class.
1063   * @param loader the class loader to load the proxy class.
1064   * @param toString the string returned by the toString() method of the proxy.
1065   * @return the factory component.
1066   */

1067  public static <F> Component<F> factory(Creator cc, Class JavaDoc<F> factory_class,
1068      ClassLoader JavaDoc loader, String JavaDoc toString){
1069    final Component<F> r =
1070      new FactoryComponent<F>(cc, factory_class, loader, toString).label(toString);
1071    if(cc.isSingleton()){
1072      return r.singleton();
1073    }
1074    else return r;
1075  }
1076  /**
1077   * Create a Component that instantiates a factory interface.
1078   * All factory methods in this factory interface will delegate
1079   * to the component of the product to create the product.
1080   * @param cc the product creator.
1081   * @param factory_class the factory interface class.
1082   * @param toString the string returned by the toString() method of the factory object.
1083   * @return the factory component.
1084   */

1085  public static <F> Component<F> factory(Creator cc, Class JavaDoc<F> factory_class,
1086      String JavaDoc toString){
1087    if(Factory.class.equals(factory_class)){
1088      return factory(cc, toString);
1089    }
1090    return factory(cc, factory_class, factory_class.getClassLoader(),
1091        toString);
1092  }
1093  /**
1094   * Create a Component that instantiates the {@link Factory} interface.
1095   * The {@link Factory#create()} method delegates
1096   * to the component of the product to create the product.
1097   * @param cc the component responsible for instantiation.
1098   * @param toString the string returned by the toString() method of the factory.
1099   * @return the factory component.
1100   */

1101  public static <T> Component<Factory<T>> factory(Creator<T> cc, String JavaDoc toString){
1102    return new TheFactoryComponent<T>(cc, toString).label(toString);
1103  }
1104  static <T> Component<T> ensureComponent(Component<T> cc, Object JavaDoc key){
1105    if(cc==null)
1106      throw new UnresolvedComponentException(key);
1107    return cc;
1108  }
1109  /**
1110   * Adapt a LazyComponent object to Component.
1111   *
1112   * @param lcc the LazyComponent object.
1113   * @param key the name of the to-be-resolved component.
1114   * @return the new Component object.
1115   */

1116  public static <T> Component<T> fromLazy(final LazyComponent<T> lcc, final Object JavaDoc key){
1117    return new LazyComponent2Component<T>(lcc, key).guard();
1118  }
1119  /**
1120   * Create a Component object that delegates to another component
1121   * identified by a key in a container.
1122   * <br>
1123   * When create() method is called,
1124   * the getComponent() method is called against the target container to resolve the component.
1125   * <br>
1126   * This is a late-bound component because its type is resolved when create()
1127   * method is called.
1128   * @param cmap the container in which to resolve the component.
1129   * @param key the key of the component to delegate to.
1130   * @return the new Component object.
1131   */

1132  public static Component useKey(
1133      final ComponentMap cmap, final Object JavaDoc key){
1134    return fromLazy(new LazyComponent(){
1135      public Component eval(){
1136        return cmap.getComponent(key);
1137      }
1138      public Class JavaDoc getType(){return null;}
1139      public String JavaDoc toString(){return "useKey <"+key+">";}
1140    }, key).label();
1141  }
1142  
1143  /**
1144   * Create a component that uses a particular property value
1145   * of the parent component as its instance.
1146   * <br>
1147   * If a component is being instantiated as a property or parameter
1148   * of another component, then that other component is the parent
1149   * component in this context.
1150   * @param component_type the type of the component.
1151   * @param key the property key.
1152   * @param type the property type.
1153   * @return the Component object.
1154   */

1155  public static <T> Component<T> useProperty(
1156      final Class JavaDoc component_type, final Object JavaDoc key, final Class JavaDoc<T> type){
1157    return new UsePropertyComponent<T>(component_type, key, type).guard().label();
1158  }
1159  /**
1160   * Create a component that uses a particular argument value
1161   * of the parent component as its instance.
1162   * <br>
1163   * If a component is being instantiated as a property or parameter
1164   * of another component, then that other component is the parent
1165   * component in this context.
1166   * @param src the function requesting the argument.
1167   * @param pos the ordinal position of the argument.
1168   * @param type the parameter type.
1169   * @return the Component object.
1170   */

1171  public static <T> Component<T> useArgument(
1172      final Signature src, final int pos, final Class JavaDoc<T> type){
1173    return new UseArgumentComponent<T>(src, pos, type).guard().label();
1174  }
1175  /**
1176   * Create a Part object that redirects the resolution of a typed
1177   * parameter/property to another container.
1178   * @param cmap the container.
1179   * @return the Part object.
1180   */

1181  public static Part useContainer(final ComponentMap cmap){
1182    return new Part(){
1183      public Object JavaDoc create(Class JavaDoc type, Dependency dependency){
1184        return ensureComponent(cmap.getComponentOfType(type), type)
1185        .create(cmap.getDependencyOfType(type, cmap));
1186      }
1187      public Class JavaDoc verify(Class JavaDoc type, Dependency dependency){
1188        return ensureComponent(cmap.getComponentOfType(type), type)
1189        .verify(cmap.getDependencyOfType(type, cmap));
1190      }
1191    };
1192  }
1193  /**
1194   * Create a Component object that returns the container object.
1195   */

1196  public static Component<ComponentMap> thisContainer(){
1197    return ThisContainerComponent.instance();
1198  }
1199  /**
1200   * Create a Component object that delegates to another component in a container.
1201   * <br>
1202   * When create() method is called,
1203   * the getComponentOfType() method is called against the target container
1204   * to resolve the component.
1205   * <br>
1206   * This is a late-bound component because its type is resolved when create()
1207   * method is called.
1208   * @param cmap the container in which to resolve the component.
1209   * @param type the component type to look for.
1210   * @return the new Component object.
1211   */

1212  public static <T> Component<T> useType(
1213      final ComponentMap cmap, final Class JavaDoc<T> type){
1214    return fromLazy(new LazyComponent<T>(){
1215      public Component<T> eval(){
1216        return cmap.getComponentOfType(type);
1217      }
1218      public Class JavaDoc<T> getType(){return null;}
1219      public String JavaDoc toString(){
1220        return "useType <"+Misc.getTypeName(type) +">";
1221      }
1222    }, type).guard().label();
1223  }
1224  /**
1225   * Create a Component object that creates a java.util.List.
1226   * <br>
1227   * When create() method is called,
1228   * the getComponentsOfType() method is called against the target container
1229   * to resolve the components. The components found are invoked one by one
1230   * to create component instances.
1231   * Finally these instances are stored in a java.util.List object and returned
1232   * as the return value.
1233   * <br>
1234   * @param cmap the container in which to resolve the components.
1235   * @param type the component type to look for.
1236   * @return the new Component object.
1237   */

1238  public static <T> Component<ArrayList JavaDoc<T>> useAll(
1239      final ComponentMap cmap, final Class JavaDoc<T> type){
1240    return fromLazy(new LazyComponent<ArrayList JavaDoc<T>>(){
1241      public Component<ArrayList JavaDoc<T>> eval(){
1242        return list(cmap.getComponentsOfType(type));
1243      }
1244      public Class JavaDoc getType(){
1245        return java.util.ArrayList JavaDoc.class;
1246      }
1247      public String JavaDoc toString(){
1248        return "useAll <"+Misc.getTypeName(type)+">";
1249      }
1250    }, type).label();
1251  }
1252  /**
1253   * Create a Component object that creates a java.util.List. <br>
1254   * When method create() is called, it looks up in the target container
1255   * for all the components with a state value that satisfies the given predicate.
1256   * It then invokes these components one by one to create instances.
1257   * These instances are finally stored in a java.util.List and returned
1258   * as the return value.
1259   * @param cmap the target container.
1260   * @param pred the predicate to filter state value.
1261   * @return the Component object.
1262   */

1263  public static Component useState(
1264      final ComponentMap cmap, final Predicate pred){
1265    return fromLazy(new LazyComponent(){
1266      public Component eval(){
1267        return list(findComponents(cmap, pred));
1268      }
1269      public Class JavaDoc getType(){
1270        return java.util.ArrayList JavaDoc.class;
1271      }
1272      public String JavaDoc toString(){
1273        return "useState <"+pred+">";
1274      }
1275    }, pred).guard().label();
1276  }
1277  /**
1278   * Label the frame for a Component so that whenever a YanException is thrown,
1279   * the provided label will be populated in the resolution trace.
1280   * @param cc the component to label.
1281   * @param lbl the label.
1282   * @return the new Component object.
1283   */

1284  public static <T> Component<T> label(final Component<T> cc, final Object JavaDoc lbl){
1285    return new ClosureableComponent(cc){
1286      public Class JavaDoc verify(Dependency dp){
1287        try{
1288          return cc.verify(dp);
1289        }
1290        catch(YanException e){
1291          e.push(lbl);
1292          throw e;
1293        }
1294      }
1295      public Object JavaDoc create(Dependency dp){
1296        try{
1297          return cc.create(dp);
1298        }
1299        catch(YanException e){
1300          e.push(lbl);
1301          throw e;
1302        }
1303      }
1304      //label on a label immediately will ignore the previous label.
1305
public Component label(Object JavaDoc lbl){
1306        return cc.label(lbl);//Components.label(cc, lbl);
1307
}
1308      protected Component decorate(Component c){
1309        return Components.label(c, lbl);
1310      }
1311      public String JavaDoc toString(){
1312        return ""+lbl;
1313      }
1314    };
1315  }
1316  /**
1317   * Create a Component object that delegates to another component
1318   * identified by a key in the current container.
1319   * <br>
1320   * When create() method is called,
1321   * the getComponent() method is called against the current container to resolve the component.
1322   * <br>
1323   * This is a late-bound component because its type is resolved when create()
1324   * method is called.
1325   * @param key the key of the component to delegate to.
1326   * @return the new Component object.
1327   */

1328
1329  public static Component useKey(final Object JavaDoc key){
1330    return new UseKeyComponent(key).guard().label();
1331  }
1332  /**
1333   * Create a Component object that delegates to another component
1334   * in the current container.
1335   * <br>
1336   * When create() method is called,
1337   * the getComponentOfType() method is called against the current container
1338   * to resolve the component.
1339   * <br>
1340   * This is a late-bound component because its type is resolved when create()
1341   * method is called.
1342   * @param type the component type to look for.
1343   * @return the new Component object.
1344   */

1345  public static <T> Component<T> useType(final Class JavaDoc<T> type){
1346    return new UseTypeComponent<T>(type).guard().label();
1347  }
1348  /**
1349   * Create a Component object that delegates to another component
1350   * in the current container.
1351   * <p>
1352   * When create() method is called,
1353   * the getComponentsOfType() method is called against the current container
1354   * to resolve the component. If no component is found or more than one are found,
1355   * it tries to search component using the alternative keys sequentially until
1356   * a Component is found.
1357   * </p>
1358   * <p>
1359   * UnresolvedComponentException is thrown if no Component is found at last.
1360   * </p>
1361   * This is a late-bound component because its type is resolved when create()
1362   * method is called.
1363   * @param type the component type to look for.
1364   * @param alternative_keys the alternative keys to try when search by type failed.
1365   * @return the new Component object.
1366   */

1367  public static <T> Component<T> autodetect(final Class JavaDoc<T> type, final Object JavaDoc[] alternative_keys){
1368    return new AutoDetectingComponent<T>(type, alternative_keys).guard().label();
1369  }
1370  /**
1371   * Create a Component object that creates a java.util.List.
1372   * <br>
1373   * When create() method is called,
1374   * the getComponentsOfType() method is called against the current container
1375   * to resolve the components. The components found are invoked one by one
1376   * to create component instances.
1377   * Finally these instances are stored in a java.util.List object and returned
1378   * as the return value.
1379   * <br>
1380   * @param type the component type to look for.
1381   * @return the new Component object.
1382   */

1383  public static <T> Component<List JavaDoc<T>> useAll(final Class JavaDoc<T> type){
1384    return new Component<List JavaDoc<T>>(){
1385      public Class JavaDoc verify(Dependency dependency){
1386        return list(findComponents(dependency.getComponentMap(), type))
1387        .verify(dependency);
1388      }
1389      public List JavaDoc<T> create(Dependency dependency){
1390        return list(findComponents(dependency.getComponentMap(), type))
1391        .create(dependency);
1392      }
1393      private java.util.List JavaDoc<Component<T>> findComponents(ComponentMap cmap,
1394          final Class JavaDoc<T> type){
1395        return cmap.getComponentsOfType(type);
1396      }
1397      public Class JavaDoc getType(){
1398        return java.util.ArrayList JavaDoc.class;
1399      }
1400      public boolean isConcrete(){
1401        return true;
1402      }
1403      public String JavaDoc toString(){
1404        return "useAll <" + Misc.getTypeName(type)+">";
1405      }
1406      public boolean isSingleton(){
1407        return false;
1408      }
1409    }.guard().label();
1410  }
1411  private static java.util.List JavaDoc<Component> findComponents(ComponentMap cmap,
1412      final Predicate pred){
1413    final java.util.Collection JavaDoc all = cmap.getComponents();
1414    final java.util.ArrayList JavaDoc<Component> ret = new java.util.ArrayList JavaDoc<Component>();
1415    for(java.util.Iterator JavaDoc it=all.iterator();it.hasNext();){
1416      final Component c = (Component)it.next();
1417      if(pred.isObject(c.getState())){
1418        ret.add(c);
1419      }
1420    }
1421    return ret;
1422  }
1423  /**
1424   * Creates a Component that throws {@link jfun.yan.DefaultingException}.
1425   * This exception will be caught later and a default action is taken
1426   * according to the context. <br>
1427   * For example, Component expecting a mandatory parameter
1428   * will use null for default value; bean component will ignore
1429   * setting the property; withDefaultArgument or withDefaultProperty
1430   * will provide a default value.
1431   * @return the new Component object.
1432   */

1433  public static Component useDefault(){
1434    return UseDefaultComponent.instance();
1435  }
1436  /**
1437   * Create a Component object that creates a java.util.List. <br>
1438   * When method create() is called, it looks up in the current container
1439   * for all the components with a state value that satisfies the given predicate.
1440   * It then invokes these components one by one to create instances.
1441   * These instances are finally stored in a java.util.List and returned
1442   * as the return value.
1443   * @param pred the predicate to filter state value.
1444   * @return the Component object.
1445   */

1446  public static Component useState(final Predicate pred){
1447    return new Component(){
1448      public Class JavaDoc verify(Dependency dependency){
1449        final ComponentMap cmap = dependency.getComponentMap();
1450        return list(findComponents(cmap, pred)).verify(dependency);
1451      }
1452      public Object JavaDoc create(Dependency dependency){
1453        final ComponentMap cmap = dependency.getComponentMap();
1454        return list(findComponents(cmap, pred)).create(dependency);
1455      }
1456      public Class JavaDoc getType(){
1457        return java.util.ArrayList JavaDoc.class;
1458      }
1459      public boolean isConcrete(){
1460        return true;
1461      }
1462      public String JavaDoc toString(){
1463        return "useState <" + pred +">";
1464      }
1465      public boolean isSingleton(){
1466        return false;
1467      }
1468    }.guard().label();
1469  }
1470  /**
1471   * Create a Component object that returns the state of a Stateful object
1472   * as its component instance.
1473   * @param st the Stateful object.
1474   * @return the Component object.
1475   */

1476  public static Component returnState(final Stateful st){
1477    return new ReturnStateComponent(st).label();
1478  }
1479  /**
1480   * Create a Component object that returns the type of a Typeful object
1481   * as its component instance.
1482   * @param t the Typeful object.
1483   * @return the Component object.
1484   */

1485  public static Component returnType(final Typeful t){
1486    return new ReturnTypeComponent(t).guard().label();
1487  }
1488  /**
1489   * Create a Component object that verifies the Verifiable object
1490   * and returns the result type as return value.
1491   * @param veri the Verifiable object.
1492   * @return the Component object.
1493   */

1494  public static Component returnVerification(final Verifiable veri){
1495    return new ReturnVerificationComponent(veri).guard()
1496    .label();
1497  }
1498  /*
1499  private static Dependency setArguments(
1500      final Dependency dependency,
1501      final Creator[] factories){
1502    return new DelegatingDependency(dependency){
1503      public Object getArgument(int i, Class type){
1504        if(i<factories.length){
1505          final Object r = factories[i].create(dependency);
1506          Utils.checkArg(getComponentKey(), i, type, r);
1507          return r;
1508        }
1509        else return dependency.getArgument(i, type);
1510      }
1511      public Class verifyArgument(int i, Class type){
1512        if(i<factories.length){
1513          final Creator factory = factories[i];
1514          final Class r = factory.verify(dependency);
1515          Utils.checkType(getComponentKey(), i, type, r);
1516          return r;
1517        }
1518        else return dependency.verifyArgument(i, type);
1519      }
1520    };
1521  }
1522  private static Dependency setProperties(
1523      final Dependency dependency, final java.util.Map props){
1524    return new DelegatingDependency(dependency){
1525      public Object getProperty(Object k, Class type){
1526        final Creator cr = (Creator)props.get(k);
1527        if(cr != null){
1528          final Object r = cr.create(dependency);
1529          Utils.checkArg(getComponentKey(), k, type, r);
1530          return r;
1531        }
1532        else return dependency.getProperty(k, type);
1533      }
1534      public Class verifyProperty(Object k, Class type){
1535        final Creator cr = (Creator)props.get(k);
1536        if(cr != null){
1537          final Class r = cr.verify(dependency);
1538          Utils.checkType(getComponentKey(), k, type, r);
1539          return r;
1540        }
1541        else return dependency.verifyProperty(k, type);
1542      }
1543    };
1544  }
1545  private static Dependency setArgument(
1546      final Dependency dependency,
1547      final int k, final Creator factory){
1548    return new DelegatingDependency(dependency){
1549      public Object getArgument(int i, Class type){
1550        if(i==k){
1551          final Object r = factory.create(dependency);
1552          Utils.checkArg(getComponentKey(), i, type, r);
1553          return r;
1554        }
1555        else return dependency.getArgument(i, type);
1556      }
1557      public Class verifyArgument(int i, Class type){
1558        if(i==k){
1559          final Class r = factory.verify(dependency);
1560          Utils.checkType(getComponentKey(), i, type, r);
1561          return r;
1562        }
1563        else return dependency.verifyArgument(i, type);
1564      }
1565    };
1566  }*/

1567  private static Dependency setArguments(
1568      final Dependency dependency,
1569      final Part part){
1570    return new DelegatingDependency(dependency){
1571      public Object JavaDoc getArgument(Signature src, int i, Class JavaDoc type){
1572        final Object JavaDoc r = part.create(type, dependency);
1573        Utils.checkArg(src, getComponentKey(), i, type, r);
1574        return r;
1575      }
1576      public Class JavaDoc verifyArgument(Signature src, int i, Class JavaDoc type){
1577        final Class JavaDoc r = part.verify(type, dependency);
1578        Utils.checkType(src, getComponentKey(), i, type, r);
1579        return r;
1580      }
1581      public Dependency seal(){
1582        return setArguments(dependency.seal(), part);
1583      }
1584    };
1585  }
1586  private static Dependency setProperties(
1587      final Dependency dependency, final Part part){
1588    return new DelegatingDependency(dependency){
1589      public Object JavaDoc getProperty(Class JavaDoc component_type, Object JavaDoc k, Class JavaDoc type){
1590        final Object JavaDoc r = part.create(type, dependency);
1591        Utils.checkArg(component_type, getComponentKey(), k, type, r);
1592        return r;
1593      }
1594      public Class JavaDoc verifyProperty(Class JavaDoc component_type, Object JavaDoc k, Class JavaDoc type){
1595        final Class JavaDoc r = part.verify(type, dependency);
1596        Utils.checkType(component_type, getComponentKey(), k, type, r);
1597        return r;
1598      }
1599      public Dependency seal(){
1600        return setProperties(dependency.seal(), part);
1601      }
1602    };
1603  }
1604  /**
1605   * Create a ParameterBinder object using an array of Creator object
1606   * that will be used to create arguments.
1607   * @param args the creators for the arguments.
1608   * @return the ParameterBinder object.
1609   */

1610  static ParameterBinder getParameterBinder(final Creator[] args){
1611    return new ParameterBinder(){
1612      public Creator bind(final Signature src, int k, Class JavaDoc type){
1613        if(k>=0 && k < args.length){
1614          return args[k];
1615        }
1616        else return useArgument(src, k, type);
1617      }
1618    };
1619  }
1620  /**
1621   * Create a PropertyBinder object using Creator objects
1622   * stored in a java.util.Map object.
1623   * These creator objects will be used to create property values.
1624   * @param props the creators for the properties and their keys.
1625   * @return the PropertyBinder object.
1626   */

1627  static PropertyBinder getPropertyBinder(final java.util.Map JavaDoc props){
1628    return new PropertyBinder(){
1629      public Creator bind(Class JavaDoc component_type, Object JavaDoc k, Class JavaDoc type){
1630        final Creator r = (Creator)props.get(k);
1631        if(r==null) return useProperty(component_type, k, type);
1632        else return r;
1633      }
1634    };
1635  }
1636  /**
1637   * Customizes a Component's parameters with an array of Creator objects.
1638   * For parameter i,
1639   * creators[i] is used to create it if i is between 0 and factories.length.
1640   * the default creation strategy is used otherwise.
1641   * @param cc the Component to customize.
1642   * @param creators the creator objects for creating arguments.
1643   * @return the new Component object.
1644   */

1645  public static Component withArguments(
1646      final Component cc, final Creator... creators){
1647    return bindArguments(cc, getParameterBinder(creators));
1648    /*
1649    return new DecoratingComponent(cc){
1650      public Object create(Dependency dependency){
1651        return cc.create(Components.setArguments(dependency, factories),
1652            ctxt);
1653      }
1654      public Class verify(Dependency dependency){
1655        return cc.verify(Components.setArguments(dependency, factories),
1656            ctxt);
1657      }
1658      protected Component decorate(Component cc){
1659        return Components.withArguments(cc, factories);
1660      }
1661    };*/

1662  }
1663  /**
1664   * Create a sealed component.
1665   * A sealed component assumes responsibility to
1666   * resolve its own dependencies.
1667   * It does not attempt to look up the container
1668   * to resolve any unresolved dependency.
1669   * <br>
1670   * seal can be used to disable auto-wiring at component level.
1671   * @param cc the component to seal.
1672   * @return the new Component object.
1673   */

1674  public static Component seal(final Component cc){
1675    return new ClosureableComponent(cc){
1676      public Object JavaDoc create(Dependency dependency){
1677        return cc.create(dependency.seal());
1678      }
1679      public Class JavaDoc verify(Dependency dependency){
1680        return cc.verify(dependency.seal());
1681      }
1682      public String JavaDoc toString(){
1683        return "seal <" + cc + ">";
1684      }
1685      protected Component decorate(Component cc){
1686        return Components.seal(cc);
1687      }
1688      public Component seal(){
1689        return this;
1690      }
1691    }.label();
1692  }
1693  
1694  /**
1695   * To create a Component that ignores all subsequent
1696   * customizations to the parameters or properties.
1697   * @param c the Component to decorate.
1698   * @return the new Component that's guaranteed to auto-wire.
1699   */

1700  public static Component autowired(final Component c){
1701    return new ClosureableComponent(c){
1702      public Object JavaDoc create(Dependency dependency){
1703        return c.create(dependency.getOriginal());
1704      }
1705      public Class JavaDoc verify(Dependency dependency){
1706        return c.verify(dependency.getOriginal());
1707      }
1708      public String JavaDoc toString(){
1709        return "autowired <" + c + ">";
1710      }
1711      protected Component decorate(Component cc){
1712        return Components.autowired(cc);
1713      }
1714    }.label();
1715  }
1716  /**
1717   * Customize the arguments of a component with a
1718   * {@link jfun.yan.ParameterBinder} object.
1719   * @param cc the component.
1720   * @param binder the ParameterBinder object.
1721   * @return the new Component.
1722   */

1723  public static Component bindArguments(
1724      final Component cc, final ParameterBinder binder){
1725    return new DecoratingComponent(cc){
1726      public Object JavaDoc create(Dependency dependency){
1727        return cc.create(Components.bindArguments(dependency, binder));
1728      }
1729      public Class JavaDoc verify(Dependency dependency){
1730        return cc.verify(Components.bindArguments(dependency, binder));
1731      }
1732      //additionally cache the result at the top level to avoid creation of Dependency objects.
1733
public Component singleton(){
1734        return new SingletonComponent(super.singleton());
1735      }
1736      //additionally cache the result at the top level to avoid creation of Dependency objects.
1737
public Component singleton(Pool scope){
1738        return new PooledComponent(super.singleton(scope), scope);
1739      }
1740      protected Component decorate(Component cc){
1741        return cc.bindArguments(binder);
1742      }
1743    };
1744  }
1745  /**
1746   * Customize one argument of a component with a
1747   * {@link jfun.yan.ParameterBinder} object.
1748   * @param cc the component.
1749   * @param k the ordinal position of the parameter.
1750   * @param binder the ParameterBinder object.
1751   * @return the new Component.
1752   */

1753  public static Component bindArgument(
1754      final Component cc, final int k, final ParameterBinder binder){
1755    return bindArguments(cc, new ParameterBinder(){
1756      public Creator bind(final Signature src, int i, Class JavaDoc type){
1757        if(i==k){
1758          return binder.bind(src, i, type);
1759        }
1760        else return useArgument(src, i, type);
1761      }
1762    });
1763  }
1764  /**
1765   * Customizes a Component's properties with provided Creator objects
1766   * stored in a java.util.Map object.
1767   * @param cc the Component object to customize.
1768   * @param props the map that contains mappings between property keys
1769   * and Creator objects that creates the property value.
1770   * This Map object is not modified within this method.
1771   * It is allowed to subsequently change the Map object
1772   * after this method is called.
1773   * The new change will be picked up by the component
1774   * when creating instances.
1775   * If a property's key is not contained in the Map object,
1776   * the creation strategy is not changed for this property.
1777   * @return the new Component object.
1778   */

1779  public static Component withProperties(
1780      final Component cc, final java.util.Map JavaDoc props){
1781    return bindProperties(cc, getPropertyBinder(props));
1782    /*
1783    return new DecoratingComponent(cc){
1784      public Object create(Dependency dependency){
1785        return cc.create(Components.setProperties(dependency, props));
1786      }
1787      public Class verify(Dependency dependency){
1788        return cc.verify(Components.setProperties(dependency, props));
1789      }
1790      public Component decorate(Component c){
1791        return Components.withProperties(c, props);
1792      }
1793    };*/

1794    
1795  }
1796  /**
1797   * Customize the properties of a component with a
1798   * {@link jfun.yan.PropertyBinder} object.
1799   * @param cc the component.
1800   * @param binder the PropertyBinder object.
1801   * @return the new Component.
1802   */

1803  public static Component bindProperties(
1804      final Component cc, final PropertyBinder binder){
1805    return new ClosureableComponent(cc){
1806      public Object JavaDoc create(Dependency dependency){
1807        return cc.create(Components.bindProperties(dependency, binder));
1808      }
1809      public Class JavaDoc verify(Dependency dependency){
1810        return cc.verify(Components.bindProperties(dependency, binder));
1811      }
1812      //additionally cache the result at the top level to avoid creation of Dependency objects.
1813
public Component singleton(){
1814        return new SingletonComponent(super.singleton());
1815      }
1816      //additionally cache the result at the top level to avoid creation of Dependency objects.
1817
public Component singleton(Pool scope){
1818        return new PooledComponent(super.singleton(scope), scope);
1819      }
1820      public Component decorate(Component c){
1821        return c.bindProperties(binder);
1822      }
1823    };
1824  }
1825  /**
1826   * Customize the properties of a component with a
1827   * {@link jfun.yan.PropertyBinder} object.
1828   * @param cc the component.
1829   * @param k the property key.
1830   * @param binder the PropertyBinder object.
1831   * @return the new Component.
1832   */

1833  public static Component bindProperty(final Component cc,
1834      final Object JavaDoc k, final PropertyBinder binder){
1835    return bindProperties(cc, new PropertyBinder(){
1836      public Creator bind(Class JavaDoc component_type, Object JavaDoc i, Class JavaDoc type){
1837        if(i.equals(k)){
1838          return binder.bind(component_type, i,type);
1839        }
1840        else return useProperty(component_type, i, type);
1841      }
1842    });
1843  }
1844  
1845  /**
1846   * Customizes a Component's properties with the provided Creator objects.
1847   * For property identified by keys[i], creators[i] is used for creating value.
1848   * The keys array and creators array has to be the same length.
1849   * @param cc the Component object to customize.
1850   * @param names the property keys. Duplicate key is not allowed in this array.
1851   * Names are case-sensitive.
1852   * @param creators the creators for creating property values.
1853   * @return the new Component object.
1854   */

1855  public static Component withProperties(
1856      final Component cc, final String JavaDoc[] names, final Creator[] creators){
1857    return withProperties(cc, Utils.hashmap(names, creators));
1858  }
1859
1860  /**
1861   * Redirects resolution of properties to arguments.
1862   * So that a property-based component (such as bean)
1863   * can be used as if it were a parameter-based on,
1864   * for which withArgument, withArguments can be used to customize.
1865   * <br>
1866   * It is useful when applying a property-based component to an algorithm
1867   * that relies on argument-based component.
1868   * The factory() combinator, for example, relies on parameter-based component.
1869   * @param cc the component to be redirected.
1870   * @param keys the property keys to redirect.
1871   * The ordinal position of each key indicates the position of the parameter.
1872   * @return the redirected Component object.
1873   */

1874  public static Component fromArguments(
1875      final Component cc, final Object JavaDoc... keys){
1876    return bindProperties(cc, new PropertyBinder(){
1877      public Creator bind(Class JavaDoc component_type, Object JavaDoc key, Class JavaDoc type){
1878        final int ind = findKey(key);
1879        if(ind < 0) return useProperty(component_type, key, type);
1880        else{
1881          final Signature sig = new Property2Signature(component_type, key, type);
1882          return useArgument(sig, ind, type);
1883        }
1884      }
1885      private int findKey(Object JavaDoc k){
1886        for(int i=0; i<keys.length;i++){
1887          if(Utils.eq(k, keys[i])) return i;
1888        }
1889        return -1;
1890      }
1891    });
1892  }
1893  /**
1894   * Redirects resolution of arguments to properties.
1895   * So that a parameter-based component (such as ctor or method)
1896   * can be used as if it were a bean component,
1897   * for which withProperty, withProperties can be used to customize.
1898   * <br>
1899   * It is useful when applying a parameter-based component to an algorithm
1900   * that relies on property-based component.
1901   * @param cc the component to be redirected.
1902   * @param keys the property keys for parameters.
1903   * The ordinal position of each key indicates the position of the parameter.
1904   * @return the redirected Component object.
1905   */

1906  public static Component fromProperties(
1907      final Component cc, final Object JavaDoc... keys){
1908    return bindArguments(cc, new ParameterBinder(){
1909      public Creator bind(final Signature src, int k, Class JavaDoc type){
1910        if(k<0 || k>=keys.length){
1911          return useArgument(src, k, type);
1912        }
1913        else return useProperty(src.getReturnType(), keys[k], type);
1914      }
1915    });
1916  }
1917  /**
1918   * Customizes a Component with a Part object to create all its parameters.
1919   * @param cc the Component object to customize.
1920   * @param part the Part object.
1921   * @return the new Component object.
1922   */

1923  public static Component withArguments(
1924      final Component cc, final Part part){
1925    return new ClosureableComponent(cc){
1926      public Object JavaDoc create(Dependency dependency){
1927        return cc.create(Components.setArguments(dependency, part));
1928      }
1929      public Class JavaDoc verify(Dependency dependency){
1930        return cc.verify(Components.setArguments(dependency, part));
1931      }
1932      protected Component decorate(Component cc){
1933        return Components.withArguments(cc, part);
1934      }
1935    };
1936  }
1937  /**
1938   * Customizes a Component object with a Part object to create all its property values.
1939   * @param cc the Component object to customize.
1940   * @param part the Part object.
1941   * @return the new Component object.
1942   */

1943  public static Component withProperties(
1944      final Component cc, final Part part){
1945    return new ClosureableComponent(cc){
1946      public Object JavaDoc create(Dependency dependency){
1947        return cc.create(Components.setProperties(dependency, part));
1948      }
1949      public Class JavaDoc verify(Dependency dependency){
1950        return cc.verify(Components.setProperties(dependency, part));
1951      }
1952      public Component decorate(Component c){
1953        return Components.withProperties(c, part);
1954      }
1955    };
1956  }
1957  /*
1958  private static Dependency sealDependency(Dependency dep){
1959    return new DelegatingDependency(dep){
1960      public Object getArgument(Signature src, int i, Class type){
1961        throw new IrresolveableArgumentException(getComponentKey(), i, type);
1962      }
1963      public Object getProperty(Class component_type, Object local_key, Class type){
1964        throw new IrresolveablePropertyException(getComponentKey(), local_key, type);
1965      }
1966      public Class verifyArgument(Signature src, int i, Class type){
1967        throw new IrresolveableArgumentException(getComponentKey(), i, type);
1968      }
1969      public Class verifyProperty(Class component_type, Object local_key, Class type){
1970        throw new IrresolveablePropertyException(getComponentKey(), local_key, type);
1971      }
1972      public Dependency seal(){return this;}
1973    };
1974  }*/

1975  private static Dependency setParent(final Dependency dep,
1976      final Dependency parent){
1977    return new DelegatingDependency(dep){;
1978      public Dependency getParent(){
1979        return parent;
1980      }
1981      public Dependency seal(){
1982        return setParent(dep.seal(), parent);
1983      }
1984    };
1985  }
1986  private static Dependency ofPart(final Dependency dep, Class JavaDoc type){
1987    final ComponentMap cmap = dep.getComponentMap();
1988    final Dependency newdep = cmap.getDependencyOfType(type, cmap);
1989    return setParent(newdep, dep);
1990  }
1991  private static Dependency ofProperty(final Dependency dep, Object JavaDoc key, Class JavaDoc type){
1992    return ofPart(dep, type);
1993  }
1994  private static Dependency ofParameter(Dependency dep, int ind, Class JavaDoc type){
1995    return ofPart(dep, type);
1996  }
1997
1998  /**
1999   * Customize a Dependency object with a ParameterBinder object.
2000   * @param dependency the dependency object.
2001   * @param binder the ParameterBinder object.
2002   * @return the new Dependency object.
2003   */

2004  public static Dependency bindArguments(
2005      final Dependency dependency,
2006      final ParameterBinder binder){
2007    return new DelegatingDependency(dependency){
2008      public Object JavaDoc getArgument(Signature src, int i, Class JavaDoc type){
2009        final Object JavaDoc r = binder.bind(src, i, type)
2010        .create(ofParameter(dependency, i, type));
2011        Utils.checkArg(src, getComponentKey(), i, type, r);
2012        return r;
2013      }
2014      public Class JavaDoc verifyArgument(Signature src, int i, Class JavaDoc type){
2015        final Class JavaDoc r = binder.bind(src, i,type)
2016        .verify(ofParameter(dependency, i, type));
2017        Utils.checkType(src, getComponentKey(), i, type, r);
2018        return r;
2019      }
2020      public Dependency seal(){
2021        return bindArguments(dependency.seal(), binder);
2022      }
2023    };
2024  }
2025  /**
2026   * Customize a Dependency object with a PropertyBinder object.
2027   * @param dependency the dependency object.
2028   * @param binder the PropertyBinder object.
2029   * @return the new Dependency object.
2030   */

2031  public static Dependency bindProperties(
2032      final Dependency dependency,
2033      final PropertyBinder binder){
2034    return new DelegatingDependency(dependency){
2035      public Object JavaDoc getProperty(Class JavaDoc component_type, Object JavaDoc i, Class JavaDoc type){
2036        final Object JavaDoc r = binder.bind(component_type, i,type)
2037        .create(ofProperty(dependency, i, type));
2038        Utils.checkArg(component_type, getComponentKey(), i, type, r);
2039        return r;
2040      }
2041      public Class JavaDoc verifyProperty(Class JavaDoc component_type, Object JavaDoc i, Class JavaDoc type){
2042        final Class JavaDoc r = binder.bind(component_type, i, type)
2043        .verify(ofProperty(dependency, i, type));
2044        Utils.checkType(component_type, getComponentKey(), i, type, r);
2045        return r;
2046      }
2047      public Dependency seal(){
2048        return bindProperties(dependency.seal(), binder);
2049      }
2050    };
2051  }
2052/*
2053  private static Dependency setProperty(
2054      final Dependency dependency,
2055      final Object k, final Creator factory){
2056    return new DelegatingDependency(dependency){
2057      public Object getProperty(Object i, Class type){
2058        if(i.equals(k)){
2059          final Object r = factory.create(dependency);
2060          Utils.checkArg(getComponentKey(), i, type, r);
2061          return r;
2062        }
2063        else return dependency.getProperty(i, type);
2064      }
2065      public Class verifyProperty(Object i, Class type){
2066        if(i.equals(k)){
2067          final Class r = factory.verify(dependency);
2068          Utils.checkType(getComponentKey(), i, type, r);
2069          return r;
2070        }
2071        else return dependency.verifyProperty(i, type);
2072      }
2073    };
2074  }
2075  private static Dependency withDefaultProperty(
2076      final Dependency dependency,
2077      final Object k, final Creator factory){
2078    return new DelegatingDependency(dependency){
2079      public Object getProperty(Object i, Class type){
2080        try{
2081          return dependency.getProperty(i, type);
2082        }
2083        catch(DefaultingException e){
2084          if(i.equals(k)){
2085            Object r = factory.create(dependency);
2086            Utils.checkArg(getComponentKey(), i, type, r);
2087            return r;
2088          }
2089          else throw e;
2090        }
2091      }
2092      public Class verifyProperty(Object i, Class type){
2093        try{
2094          return dependency.verifyProperty(i, type);
2095        }
2096        catch(DefaultingException e){
2097          if(i.equals(k)){
2098            final Class r = factory.verify(dependency);
2099            Utils.checkType(getComponentKey(), i, type, r);
2100            return r;
2101          }
2102          else throw e;
2103        }
2104      }
2105    };
2106  }
2107  private static Dependency withDefaultArgument(
2108      final Dependency dependency,
2109      final int k, final Creator factory){
2110    return new DelegatingDependency(dependency){
2111      public Object getArgument(int i, Class type){
2112        Object r = dependency.getArgument(i, type);
2113        if(r==default_value() && i == k){
2114          r = factory.create(dependency);
2115          Utils.checkArg(getComponentKey(), i, type, r);
2116        }
2117        return r;
2118      }
2119      public Class verifyArgument(int i, Class type){
2120        Class r = dependency.verifyArgument(i, type);
2121        if(default_value().getClass().equals(r) && i == k){
2122          r = factory.verify(dependency);
2123          Utils.checkType(getComponentKey(), i, type, r);
2124        }
2125        return r;
2126      }
2127    };
2128  }
2129  
2130  private static boolean isPropertyIgnored(Class t){
2131    return getDefaultValueType().equals(t);
2132  }
2133  private static Class getDefaultValueType(){
2134    return default_value().getClass();
2135  }
2136  private static Class tryVerify(final Dependency dep, final Object key,
2137      final Class type){
2138    try{
2139      return dep.verifyProperty(key, type);
2140    }
2141    catch(ComponentResolutionException e){
2142      return getDefaultValueType();
2143    }
2144  }
2145  
2146  private static Class tryVerify(final Dependency dep, final int i,
2147      Class type){
2148    try{
2149      return dep.verifyArgument(i, type);
2150    }
2151    catch(ComponentResolutionException e){
2152      return getDefaultValueType();
2153    }
2154  }
2155  private static Object defaulting(Dependency dep, Object i,
2156      Class type){
2157    if(isPropertyIgnored(tryVerify(dep,
2158        i, type))){
2159      return default_value();
2160    }
2161    else return dep.getProperty(i, type);
2162  }
2163  private static Object defaulting(Dependency dep, int i,
2164      Class type){
2165    if(isPropertyIgnored(tryVerify(dep, i, type)))
2166      return default_value();
2167    else
2168      return dep.getArgument(i, type);
2169  }
2170  private static Dependency optionalProperties(final Dependency dependency){
2171    return new DelegatingDependency(dependency){
2172      public Object getProperty(Object i, Class type){
2173        return defaulting(getDelegateTarget(), i, type);
2174      }
2175      public Class verifyProperty(Object i, Class type){
2176        return tryVerify(getDelegateTarget(), i, type);
2177      }
2178    };
2179  }
2180  private static Dependency optionalParameters(final Dependency dependency){
2181    return new DelegatingDependency(dependency){
2182      public Object getArgument(int i, Class type){
2183        return defaulting(getDelegateTarget(), i, type);
2184      }
2185      public Class verifyArgument(int i, Class type){
2186        return tryVerify(getDelegateTarget(), i, type);
2187      }
2188    };
2189  }
2190  private static Dependency optionalProperty(
2191      final Dependency dependency,
2192      final Object k){
2193    return new DelegatingDependency(dependency){
2194      public Object getProperty(Object i, Class type){
2195        if(i.equals(k)){
2196          return defaulting(getDelegateTarget(), i, type);
2197        }
2198        else return dependency.getProperty(i, type);
2199      }
2200      public Class verifyProperty(Object i, Class type){
2201        if(i.equals(k)){
2202          return tryVerify(getDelegateTarget(), i, type);
2203        }
2204        else return dependency.verifyProperty(i, type);
2205      }
2206    };
2207  }
2208
2209  private static Dependency optionalParameter(
2210      final Dependency dependency,
2211      final int k){
2212    return new DelegatingDependency(dependency){
2213      public Object getArgument(int i, Class type){
2214        if(i == k){
2215          return defaulting(getDelegateTarget(), i, type);
2216        }
2217        else return dependency.getArgument(i, type);
2218      }
2219      public Class verifyArgument(int i, Class type){
2220        if(i==k){
2221          return tryVerify(getDelegateTarget(), i, type);
2222        }
2223        return dependency.verifyArgument(i, type);
2224      }
2225    };
2226  }
2227  
2228  private static Dependency ignoreProperty(
2229      final Dependency dependency,
2230      final Object k){
2231    return new DelegatingDependency(dependency){
2232      public Object getProperty(Object i, Class type){
2233        if(i.equals(k)){
2234          return default_value();
2235        }
2236        return dependency.getProperty(i, type);
2237      }
2238      public Class verifyProperty(Object i, Class type){
2239        if(i.equals(k)){
2240          return type;
2241        }
2242        return dependency.verifyProperty(i, type);
2243      }
2244    };
2245  }*/

2246
2247  private static Dependency setArgument(
2248      final Dependency dependency,
2249      final int k, final Part part){
2250    return new DelegatingDependency(dependency){
2251      public Object JavaDoc getArgument(Signature src, int i, Class JavaDoc type){
2252        if(i==k){
2253          final Object JavaDoc r = part.create(type, dependency);
2254          Utils.checkArg(src, getComponentKey(), i, type, r);
2255          return r;
2256        }
2257        else return dependency.getArgument(src, i, type);
2258      }
2259      public Class JavaDoc verifyArgument(Signature src, int i, Class JavaDoc type){
2260        if(i==k){
2261          final Class JavaDoc r = part.verify(type, dependency);
2262          Utils.checkType(src, getComponentKey(), i, type, r);
2263          return r;
2264        }
2265        else return dependency.verifyArgument(src, i, type);
2266      }
2267      public Dependency seal(){
2268        return setArgument(dependency.seal(), k, part);
2269      }
2270    };
2271  }
2272  private static Dependency setProperty(
2273      final Dependency dependency,
2274      final Object JavaDoc k, final Part part){
2275    return new DelegatingDependency(dependency){
2276      public Object JavaDoc getProperty(Class JavaDoc component_type, Object JavaDoc i, Class JavaDoc type){
2277        if(i.equals(k)){
2278          final Object JavaDoc r = part.create(type, dependency);
2279          Utils.checkArg(component_type, getComponentKey(), i, type, r);
2280          return r;
2281        }
2282        else return dependency.getProperty(component_type, i, type);
2283      }
2284      public Class JavaDoc verifyProperty(Class JavaDoc component_type, Object JavaDoc i, Class JavaDoc type){
2285        if(i.equals(k)){
2286          final Class JavaDoc r = part.verify(type, dependency);
2287          Utils.checkType(component_type, getComponentKey(), i, type, r);
2288          return r;
2289        }
2290        else return dependency.verifyProperty(component_type, i, type);
2291      }
2292      public Dependency seal(){
2293        return setProperty(dependency.seal(), k, part);
2294      }
2295    };
2296  }
2297
2298  /**
2299   * Customizes the creation of one parameter of a Component object
2300   * using a Creator object.
2301   * @param cc the Component object to customize.
2302   * @param k the ordinal position of the parameter.
2303   * @param factory the creator object for creating that argument.
2304   * @return the new Component object.
2305   */

2306  public static Component withArgument(
2307      final Component cc,
2308      final int k, final Creator factory){
2309    return bindArgument(cc, k, constParamBinder(factory));
2310    /*
2311    return new DecoratingComponent(cc){
2312      public Object create(Dependency dependency){
2313        return cc.create(Components.setArgument(dependency, k, factory));
2314      }
2315      public Class verify(Dependency dependency){
2316        return cc.verify(Components.setArgument(dependency, k, factory));
2317      }
2318      public Component decorate(Component c){
2319        return Components.withArgument(c, k, factory);
2320      }
2321    };*/

2322  }
2323  private static ParameterBinder constParamBinder(final Creator c){
2324    return new ParameterBinder(){
2325      public Creator bind(Signature src, int k, Class JavaDoc type){
2326        return c;
2327      }
2328    };
2329  }
2330  private static PropertyBinder constPropertyBinder(final Creator c){
2331    return new PropertyBinder(){
2332      public Creator bind(Class JavaDoc component_type, Object JavaDoc k, Class JavaDoc type){
2333        return c;
2334      }
2335    };
2336  }
2337  /**
2338   * Customizes the creation of one property value of a Component object
2339   * with a Creator object.
2340   * @param cc the Component object to customize.
2341   * @param k the property key.
2342   * @param factory the Creator object.
2343   * @return the new Component object.
2344   */

2345  public static <T> Component<T> withProperty(
2346      final Component<T> cc,
2347      final Object JavaDoc k, final Creator factory){
2348    return bindProperty(cc, k, constPropertyBinder(factory));
2349    /*
2350    return new DecoratingComponent(cc){
2351      public Object create(Dependency dependency){
2352        return cc.create(Components.setProperty(dependency, k, factory));
2353      }
2354      public Class verify(Dependency dependency){
2355        return cc.verify(Components.setProperty(dependency, k, factory));
2356      }
2357      public Component decorate(Component c){
2358        return Components.withProperty(c, k, factory);
2359      }
2360    };*/

2361  }
2362  /**
2363   * Customizes the creation of one parameter of a Component object
2364   * with a Part object.
2365   * @param cc the Component object to customize.
2366   * @param part the Part object.
2367   * @return the new Component object.
2368   */

2369  public static <T> Component<T> withArgument(
2370      final Component<T> cc,
2371      final int k, final Part part){
2372    return new ClosureableComponent(cc){
2373      public Object JavaDoc create(Dependency dependency){
2374        return cc.create(Components.setArgument(dependency, k, part));
2375      }
2376      public Class JavaDoc verify(Dependency dependency){
2377        return cc.verify(Components.setArgument(dependency, k, part));
2378      }
2379      public Component decorate(Component c){
2380        return Components.withArgument(c, k, part);
2381      }
2382    };
2383  }
2384  /**
2385   * Customizes the creation of one property value of a Component object
2386   * with a Part object.
2387   * @param cc the Component object to customize.
2388   * @param k the property key.
2389   * @param part the Part object.
2390   * @return the new Component object.
2391   */

2392  public static <T> Component<T> withProperty(
2393      final Component<T> cc,
2394      final Object JavaDoc k, final Part part){
2395    return new ClosureableComponent(cc){
2396      public Object JavaDoc create(Dependency dependency){
2397        return cc.create(Components.setProperty(dependency, k, part));
2398      }
2399      public Class JavaDoc verify(Dependency dependency){
2400        return cc.verify(Components.setProperty(dependency, k, part));
2401      }
2402      public Component decorate(Component c){
2403        return Components.withProperty(c, k, part);
2404      }
2405    };
2406  }
2407  
2408  /**
2409   * Creates a new Component object that makes a property identified by a key
2410   * optional. <br>
2411   * When a component sees a property is passed in with the special
2412   * default value indicator, it skips the property.
2413   * <br>
2414   * However, this behavior can be changed when withDefaultProperty()
2415   * is used. In that case, the specified alternative Creator object
2416   * will be used to create the default value.
2417   * <br>
2418   * Technically, when UnresolvedComponentException
2419   * or UnsatisfiedComponentException is caught,
2420   * defaulting takes place.
2421   * @param cc the Component object.
2422   * @param k the property key to make optional.
2423   * @return the new Component object.
2424   */

2425  public static <T> Component<T> optionalProperty(
2426      final Component<T> cc, final Object JavaDoc k){
2427    return bindProperty(cc, k, _optional_prop);
2428    /*
2429    return new DecoratingComponent(cc){
2430      public Object create(Dependency dependency){
2431        return cc.create(Components.optionalProperty(dependency, k));
2432      }
2433      public Class verify(Dependency dependency){
2434        return cc.verify(Components.optionalProperty(dependency, k));
2435      }
2436      public Component decorate(Component c){
2437        return Components.optionalProperty(c, k);
2438      }
2439    };*/

2440  }
2441  /**
2442   * Make sure the properties of a Java bean component are optional.
2443   * @param cc the bean component.
2444   * @return the new Component.
2445   */

2446  public static <T> Component<T> optionalProperties(final Component<T> cc){
2447    return bindProperties(cc, _optional_prop);
2448    /*
2449    return new DecoratingComponent(cc){
2450      public Object create(Dependency dependency){
2451        return cc.create(Components.optionalProperties(dependency));
2452      }
2453      public Class verify(Dependency dependency){
2454        return cc.verify(Components.optionalProperties(dependency));
2455      }
2456      public Component optionalProperties(){return this;}
2457      public Component decorate(Component c){
2458        return Components.optionalProperties(c);
2459      }
2460    };*/

2461  }
2462  private static final ParameterBinder _optional_param = new ParameterBinder(){
2463    public Creator bind(Signature src, int i, Class JavaDoc type){
2464      return useArgument(src, i, type).optional();
2465    }
2466  };
2467  private static final PropertyBinder _optional_prop = new PropertyBinder(){
2468    public Creator bind(Class JavaDoc component_type, Object JavaDoc k, Class JavaDoc type){
2469      return useProperty(component_type, k, type).optional();
2470    }
2471  };
2472  /**
2473   * Make sure the parameters of a component are optional.
2474   * @param cc the component object.
2475   * @return the new component object.
2476   */

2477  public static <T> Component<T> optionalParameters(final Component<T> cc){
2478    return bindArguments(cc, _optional_param);
2479    /*
2480    return new DecoratingComponent(cc){
2481      public Object create(Dependency dependency){
2482        return cc.create(Components.optionalParameters(dependency));
2483      }
2484      public Class verify(Dependency dependency){
2485        return cc.verify(Components.optionalParameters(dependency));
2486      }
2487      public Component optionalParameters(){return this;}
2488      public Component decorate(Component c){
2489        return Components.optionalParameters(c);
2490      }
2491    };*/

2492  }
2493  /**
2494   * Creates a new Component object that makes a parameter
2495   * optional.
2496   * <br>
2497   * Technically, when UnresolvedComponentException
2498   * or UnsatisfiedComponentException is caught,
2499   * defaulting takes place.
2500   * <br>
2501   * The default value is normally null. But when
2502   * withDefaultArgument() is used, it uses the value returned from the default Creator object.
2503   * @param cc the Component object.
2504   * @param k the ordinal position of the parameter.
2505   * @return the new Component object.
2506   */

2507  public static <T> Component<T> optionalParameter(
2508      final Component<T> cc, final int k){
2509    return bindArgument(cc, k, _optional_param);
2510    /*
2511    return new DecoratingComponent(cc){
2512      public Object create(Dependency dependency){
2513        return cc.create(Components.optionalParameter(dependency, k));
2514      }
2515      public Class verify(Dependency dependency){
2516        return cc.verify(Components.optionalParameter(dependency, k));
2517      }
2518      public Component decorate(Component c){
2519        return Components.optionalParameter(c, k);
2520      }
2521    };*/

2522  }
2523  /**
2524   * Create a Component object that will use an alternative Creator object
2525   * when a certain property cannot be resolved or is passed in as default.
2526   *
2527   * @param cc the original Compoenent object.
2528   * @param k the property key.
2529   * @param v the alternative Creator object.
2530   * @return the new Component object.
2531   */

2532  public static <T> Component<T> withDefaultProperty(final Component<T> cc,
2533      final Object JavaDoc k, final Creator v){
2534    final Recovery def =
2535      Monad.onException(DefaultingException.class, v);
2536    return bindProperty(cc, k, new PropertyBinder(){
2537      public Creator bind(Class JavaDoc component_type, Object JavaDoc i, Class JavaDoc type){
2538        return
2539        Monad.recover(
2540            Monad.mplus(useProperty(component_type, i, type), v),
2541            def
2542        );
2543      }
2544    });//cc.withProperty(k))
2545
/*
2546    return new DecoratingComponent(cc){
2547      public Object create(Dependency dependency){
2548        return cc.create(Components.withDefaultProperty(dependency, k, v));
2549      }
2550      public Class verify(Dependency dependency){
2551        return cc.verify(Components.withDefaultProperty(dependency, k, v));
2552      }
2553      public Component decorate(Component c){
2554        return Components.withDefaultProperty(c, k, v);
2555      }
2556    };*/

2557  }
2558  /**
2559   * Create a Component object that will use an alternative Creator object
2560   * when a certain parameter cannot be resolved
2561   * or is passed in as default.
2562   *
2563   * @param cc the original Compoenent object.
2564   * @param k the ordinal position of the parameter.
2565   * @param v the alternative Creator object.
2566   * @return the new Component object.
2567   */

2568  public static <T> Component<T> withDefaultArgument(final Component<T> cc,
2569      final int k, final Creator v){
2570    return bindArgument(cc, k, new ParameterBinder(){
2571      final Recovery def = Monad.onException(DefaultingException.class, v);
2572      public Creator bind(Signature src, int i, Class JavaDoc type){
2573        return Monad.recover(
2574            Monad.mplus(useArgument(src, i, type), v),
2575            def
2576        );
2577      }
2578    });
2579    /*
2580    return new DecoratingComponent(cc){
2581      public Object create(Dependency dependency){
2582        return cc.create(Components.withDefaultArgument(dependency, k, v));
2583      }
2584      public Class verify(Dependency dependency){
2585        return cc.verify(Components.withDefaultArgument(dependency, k, v));
2586      }
2587      public Component decorate(Component c){
2588        return Components.withDefaultArgument(c, k, v);
2589      }
2590    };*/

2591  }
2592  /**
2593   * Customizes the creation of properties and parameters of a Component object
2594   * with a Dependency object.
2595   * @param cc the Component object to customize.
2596   * @param dependency the Dependency object.
2597   * @return the new Component object.
2598   */

2599  static <T> Component<T> withDependency(
2600      final Component<T> cc, final Dependency dep){
2601    return new ClosureableComponent(cc){
2602      public Object JavaDoc create(Dependency d){
2603        return cc.create(dep);
2604      }
2605      public Class JavaDoc verify(Dependency d){
2606        return cc.verify(dep);
2607      }
2608      public Component decorate(Component c){
2609        return Components.withDependency(c, dep);
2610      }
2611    };
2612  }
2613
2614  /**
2615   * To create a Component that returns an element of the array/list
2616   * instance returned from another Component object.
2617   * @param c the Component object returning array or list.
2618   * @param ind the subscript.
2619   * @return the Component object.
2620   */

2621  public static Component subscript(final Component c, final int ind){
2622    final Component result = c.map(new Map(){
2623        public Object JavaDoc map(Object JavaDoc a){
2624          if(a==null)
2625            throw new IllegalArgumentException JavaDoc("subscript on null pointer");
2626          else if(a.getClass().isArray()){
2627            return Array.get(a, ind);
2628          }
2629          else if(a instanceof List JavaDoc){
2630            return ((List JavaDoc)a).get(ind);
2631          }
2632          else
2633            throw new IllegalArgumentException JavaDoc("cannot apply subscript against "
2634                + Misc.getTypeName(a.getClass()));
2635        }
2636      });
2637    return result;
2638  }
2639  
2640  /**
2641   * To create a Component object that calls method "get" against
2642   * the java.util.Map object instantiated by another Component.
2643   * @param c the Component object that instantiates a java.util.Map.
2644   * @param key the key.
2645   * @return the Component object that returns the value corresponding to the key.
2646   */

2647  public static Component get(Component c, final Object JavaDoc key){
2648    return c.map(new Map(){
2649      public Object JavaDoc map(Object JavaDoc o){
2650        if(o==null)
2651          throw new IllegalArgumentException JavaDoc("cannot apply get against null");
2652        if(o instanceof java.util.Map JavaDoc){
2653          return ((java.util.Map JavaDoc)o).get(key);
2654        }
2655        else
2656          throw new IllegalArgumentException JavaDoc("cannot apply get against "
2657              + Misc.getTypeName(o.getClass()));
2658      }
2659    });
2660  }
2661  /**
2662   * Decorate a Component object so that
2663   * the new Component object guards against infinite dependency loop.
2664   * @return the new Component object.
2665   */

2666  public static <T> Component<T> guard(Component<T> cc){
2667    if(cc.isSingleton()){
2668      //singleton do not need guarding.
2669
return cc;
2670    }
2671    return new GuardedComponent<T>(cc);
2672  }
2673  /**
2674   * Customizes a Component object with the specified user state.
2675   * @param cc the Component object to customize.
2676   * @param obj the user state object.
2677   * @return the new Component object.
2678   */

2679  public static <T> Component<T> withState(Component<T> cc, Object JavaDoc obj){
2680    return new StatefulComponent(cc, obj);
2681  }
2682  /**
2683   * Customizes a Component object with a new component type.
2684   * If the component is not late-bound (where getType() returns null),
2685   * the given type has to be same or super type of the component being customized.
2686   * @param cc the Component object.
2687   * @param type the target type.
2688   * @return the new Component object.
2689   */

2690  public static <Super, T extends Super> Component<Super> subsume(final Component<T> cc, final Class JavaDoc<Super> type){
2691    final Class JavaDoc subtype = cc.getType();
2692    if(subtype!=null){
2693      checkType(type, subtype);
2694      if(type.equals(subtype)){
2695        return (Component<Super>)cc;
2696      }
2697    }
2698    return new TypedComponent(cc, type){
2699      protected Component decorate(Component c){
2700        return Components.subsume(c, type);
2701      }
2702      public String JavaDoc toString(){
2703        return "subsume <" + cc + "> as " + Misc.getTypeName(type);
2704      }
2705    }.label();
2706  }
2707  /**
2708   * Decorate a Factory so that the return type is guaranteed to be
2709   * of a certain type.
2710   * @param type the expected type.
2711   * @param f the decorated Factory object.
2712   * @return the new Factory object.
2713   */

2714  private static <T> Factory<T> castFactory(final Class JavaDoc<T> type, final Factory<?> f){
2715    return new Factory<T>(){
2716      public T create(){
2717        final Object JavaDoc obj = f.create();
2718        checkInstanceType(type, obj);
2719        return (T)obj;
2720      }
2721      public String JavaDoc toString(){
2722        return f.toString();
2723      }
2724    };
2725  }
2726  private static abstract class TypedComponent extends DecoratingComponent{
2727    public Class JavaDoc getType(){
2728      return type;
2729    }
2730    public boolean isConcrete(){
2731      return false;
2732    }
2733    //for performance, we suppress type checking for Factory.
2734
public Component factory(String JavaDoc toString){
2735      return getDelegateTarget().factory(toString);
2736    }
2737    public Object JavaDoc create(Dependency dependency){
2738      return checkInstanceType(this.type, super
2739          .create(dependency));
2740    }
2741    public Class JavaDoc verify(Dependency dependency){
2742      super.verify(dependency);
2743      return getType();
2744    }
2745    private final Class JavaDoc type;
2746    TypedComponent(Component cc, Class JavaDoc type) {
2747      super(cc);
2748      this.type = type;
2749    }
2750    
2751  }
2752  /**
2753   * Customizes a Component object with a new component type.
2754   * Unlike subsume(), this method allows "down-cast"
2755   * where the current component instance type is a subtype of the given type.
2756   * It also allows "stupid-cast" where the current
2757   * component instance type has no is-a relationship with the target type.
2758   * <p>
2759   * cast forces type checks to be made on this type, regardless of the concrete type.
2760   * </p>
2761   * <p>
2762   * However, when the component's type is concrete, it forwards to subsume.
2763   * </p>
2764   * @param type the target type.
2765   * @return the new Component object.
2766   */

2767
2768  public static <T> Component<T> cast(final Component<?> cc, final Class JavaDoc<T> type){
2769    final Class JavaDoc suptype = cc.getType();
2770    if(type == suptype) return (Component<T>)cc;
2771    if(type!=null && cc.isConcrete())
2772      return subsume((Component)cc, type);
2773    if(type != null && suptype != null && type.equals(suptype)){
2774      return (Component<T>)cc;
2775    }
2776
2777    return new TypedComponent(cc, type){
2778      protected Component decorate(Component c){
2779        return Components.cast(c,getType());
2780      }
2781      public String JavaDoc toString(){
2782        return "cast <" + cc +"> as " + Misc.getTypeName(getType());
2783      }
2784    }.label();
2785  }
2786  /**
2787   * Customizes a Component object so that the new Component object
2788   * will return a dynamic proxy and hide the real component instance.
2789   * @param cc the Component object to customize.
2790   * @param itfs the interfaces to proxy to.
2791   * @return the new Component object.
2792   */

2793  public static Component proxy(final Component cc, final Class JavaDoc... itfs){
2794    if(itfs.length==0) //Do nothing for Object.
2795
return cc;
2796    return proxy(cc, itfs, itfs[0].getClassLoader());
2797  }
2798  /**
2799   * Customizes a Component object so that the new Component object
2800   * will return a dynamic proxy and hide the real component instance.
2801   * @param cc the Component object to customize.
2802   * @param itfs the interfaces to proxy to.
2803   * @param loader the ClassLoader object used to create the proxy.
2804   * @return the new Component object.
2805   */

2806  public static Component proxy(final Component cc,
2807      final Class JavaDoc[] itfs, final ClassLoader JavaDoc loader){
2808    if(itfs.length==0) //Do nothing for Object.
2809
return cc;
2810    final Class JavaDoc type = cc.getType();
2811    if(type!=null)
2812      checkTypes(itfs, type);
2813    //final Class proxyType = InstanceProxy.getProxyClass(cl, itfs);
2814
return new ProxyComponent(cc, itfs, loader).label();
2815  }
2816  /**
2817   * Customizes a Component object so that the new Component object
2818   * will return a dynamic proxy and hide the real component instance.
2819   * @param cc the Component object to customize.
2820   * @param itf the interface to proxy to.
2821   * @return the new Component object.
2822   */

2823  public static <I> Component<I> proxy(final Component<?> cc, Class JavaDoc<I> itf){
2824    return proxy(cc, toInterfaces(itf));
2825  }
2826  /**
2827   * Customizes a Component object so that the new Component object
2828   * will return a dynamic proxy and hide the real component instance.
2829   * The dynamic proxy will implement all the public interfaces
2830   * implemented by the type of the component being customized.
2831   * @param cc the Component object to customize.
2832   * @return the new Component object.
2833   */

2834  public static Component proxy(final Component cc){
2835    final Class JavaDoc ctype = cc.getType();
2836    if(ctype == null) return cc;
2837    return proxy(cc, ctype);
2838  }
2839  /**
2840   * Create a Component object that creates an array as instance.
2841   * Upon instance creation, it first invokes the Component objects provided
2842   * one by one and stores the result instances into an array.
2843   * The array is finally returned as the component instance.
2844   * @param ccs the Component objects.
2845   * @param etype the target array element type.
2846   * @return the new Component object.
2847   * @throws IllegalArgumentException if any component in the ccs array
2848   * has an incompatible type with the target array element type.
2849   */

2850  public static <T> Component<T[]> array(final Component<T>[] ccs,
2851      final Class JavaDoc<T> etype)
2852  throws IllegalArgumentException JavaDoc{
2853    final Class JavaDoc target_type = Misc.getArrayType(etype);
2854    final Component<T[]> step1 = new SimpleComponent<T[]>(target_type){
2855      public T[] create(){
2856        return (T[])Array.newInstance(etype, ccs.length);
2857      }
2858      public String JavaDoc toString(){
2859        return "array "+StringUtils.listArray("[",",","]",ccs)
2860          + ":"+Misc.getTypeName(target_type);
2861      }
2862    };
2863    return storeArray(step1, ccs);
2864    /*
2865    final Component[] cpy = new Component[ccs.length];
2866    for(int i=0; i<ccs.length; i++){
2867      final Component cc = ccs[i];
2868      final Class ctype = cc.getType();
2869      if(ctype!=null && !ReflectionUtil.isAssignableFrom(etype, ctype)){
2870        throw new IllegalArgumentException("type mismatch: the #"
2871            +i+" element is a component of "+Misc.getTypeName(ctype)
2872            +", while the expected type is "+Misc.getTypeName(etype));
2873      }
2874      cpy[i] = ccs[i];
2875    }
2876    return new ArrayComponent(cpy, target_type).guard().label();*/

2877  }
2878  public static <T> Component<T[]> storeArray(Component<T[]> component_returning_array,
2879      Creator<T>... creators){
2880    final Class JavaDoc type = component_returning_array.getType();
2881    final Class JavaDoc etype = type==null?null:type.getComponentType();
2882    return component_returning_array
2883      .followedBy(new ArrayStoreBinder<T>(creators, etype))
2884      .label();
2885  }
2886  /**
2887   * Create a Component object that creates an array as instance.
2888   * Upon instance creation, it first invokes the Component objects provided
2889   * one by one and stores the result instances into an array.
2890   * The array is finally returned as the component instance.
2891   * <br>
2892   * The element type of the result array is determined by the types
2893   * of the Component objects in the ccs array.
2894   * The algorithm is as following:
2895   * if any type is a common super type of all other component types,
2896   * that type is used as the element type,
2897   * Object.class is used otherwise.
2898   * Note, this algorithm does not attempt to analyze the least common
2899   * super type. So if type 1 is Integer, type 2 is Short,
2900   * Object is used as the element type rather than Number.
2901   *
2902   * @param ccs the Component objects.
2903   * @return the new Component object.
2904   */

2905  public static <T> Component<T[]> array(final Component<T>... ccs){
2906    return array(ccs, Utils.getCommonRootType(ccs));
2907    /*
2908    return new ArrayComponent(copy(ccs),
2909        Misc.getArrayType(Utils.getCommonRootType(ccs)))
2910    .guard().label();*/

2911  }
2912  
2913  /**
2914   * Create a Component object that creates java.util.ArrayList.
2915   * Upon instance creation, it first invokes the Creator objects provided
2916   * one by one and stores the result instances into a java.util.ArrayList object.
2917   * The list is finally returned as the component instance.
2918   *
2919   * @param ccs the Creator objects.
2920   * @return the new Component object.
2921   */

2922  public static <T> Component<ArrayList JavaDoc<T>> list(final Creator<T>... ccs){
2923    //return new ListComponent(ccs).guard().label();
2924
final Component<ArrayList JavaDoc<T>> step1 = new SimpleComponent<ArrayList JavaDoc<T>>(ArrayList JavaDoc.class){
2925      public ArrayList JavaDoc<T> create(){
2926        return new ArrayList JavaDoc<T>(ccs.length);
2927      }
2928      public String JavaDoc toString(){
2929        return "list "+StringUtils.listArray("[",",","]",ccs);
2930      }
2931    };
2932    return storeList(step1, ccs);
2933  }
2934  /**
2935   * Create a Component object that sequentially execute an array of components
2936   * and collect the result into a java.util.List object.
2937   * @param component_returning_list the Component object that returns a java.util.List.
2938   * @param creators the components to be executed sequentially.
2939   * @return the new Component object.
2940   */

2941  public static <T,L extends List JavaDoc<T>> Component<L> storeList(final Component<L> component_returning_list,
2942      final Creator<T>... creators){
2943    return component_returning_list.followedBy(new StoreBinder<T,L>(creators){
2944      public ElementStore<T> toStore(L v){
2945        if(v instanceof List JavaDoc){
2946          return new ListStore<T>(v);
2947        }
2948        throw new ClassCastException JavaDoc("java.util.List expected, "
2949            +Utils.getObjTypeName(v)+" encountered");
2950      }
2951    }).label();
2952    
2953  }
2954  /**
2955   * Create a Component object that creates java.util.HashSet.
2956   * Upon instance creation, it first invokes the Creator objects provided
2957   * one by one and stores the result instances into a java.util.HashSet object.
2958   * The set is finally returned as the component instance.
2959   *
2960   * @param ccs the Creator objects.
2961   * @return the new Component object.
2962   */

2963  public static <T> Component<HashSet JavaDoc<T>> hashset(final Creator<T>... ccs){
2964    //return new ListComponent(ccs).guard().label();
2965
final Component<HashSet JavaDoc<T>> step1 = new SimpleComponent<HashSet JavaDoc<T>>(HashSet JavaDoc.class){
2966      public HashSet JavaDoc<T> create(){
2967        return new HashSet JavaDoc<T>(ccs.length);
2968      }
2969      public String JavaDoc toString(){
2970        return "hashset "+StringUtils.listArray("[",",","]",ccs);
2971      }
2972    };
2973    return storeSet(step1, ccs);
2974  }
2975  /**
2976   * Create a Component object that sequentially execute an array of components
2977   * and collect the result into a java.util.Set object.
2978   * @param component_returning_set the Component object that returns a java.util.Set.
2979   * @param creators the components to be executed sequentially.
2980   * @return the new Component object.
2981   */

2982  public static <T, S extends Set JavaDoc<T>> Component<S> storeSet(final Component<S> component_returning_set,
2983      final Creator<T>... creators){
2984    return component_returning_set.followedBy(new StoreBinder<T,S>(creators){
2985      public ElementStore<T> toStore(S v){
2986        if(v instanceof Set JavaDoc){
2987          return new SetStore<T>(v);
2988        }
2989        throw new ClassCastException JavaDoc("java.util.Set expected, "
2990            +Utils.getObjTypeName(v)+" encountered");
2991      }
2992    }).label();
2993  }
2994  /**
2995   * Create a Component object that creates java.util.ArrayList.
2996   * Upon instance creation, it first invokes the Creator objects provided
2997   * one by one and stores the result instances into a java.util.List object.
2998   * The list is finally returned as the component instance.
2999   *
3000   * @param ccs the Creator objects.
3001   * @return the new Component object.
3002   */

3003  public static <T, C extends Creator<T>> Component<ArrayList JavaDoc<T>> list(final java.util.List JavaDoc<C> ccs){
3004    final Creator<T>[] crs = new Creator[ccs.size()];
3005    ccs.toArray(crs);
3006    return list(crs);
3007  }
3008
3009  /**
3010   * Create a Component object that creates a java.util.LinkedHashMap object.
3011   * <br>
3012   * Upon instance creation, it first invokes the Creator objects stored
3013   * in the parameter creators one by one.
3014   * The created instances along with
3015   * the corresponding keys stored in the parameter keys
3016   * are saved in a new java.util.LinkedHashMap object.
3017   * This new java.util.LinkedHashMap object is finally returned as the component
3018   * instance of this component.
3019   * <br>
3020   * The instances are populated into the java.util.LinkedHashMap object
3021   * in the same order as keys, so that keys[0] is the first element in the
3022   * java.util.LinkedHashMap object.
3023   * @param keys the keys for each instance.
3024   * @param creators the Creator objects for each instance.
3025   * @return the Component object.
3026   * @throws IllegalArgumentException if keys.length != creators.length
3027   * or any duplicate key is found in the keys array.
3028   */

3029  public static <K,T> Component<java.util.LinkedHashMap JavaDoc<K, T>> hashmap(final K[] keys, final Creator<T>[] creators)
3030  throws IllegalArgumentException JavaDoc{
3031    //return hashmap(Utils.lhashmap(keys, creators));
3032
if(keys.length != creators.length){
3033      throw new IllegalArgumentException JavaDoc("keys.length=="+keys.length
3034          + ", vals.length=="+creators.length);
3035    }
3036    final Component<LinkedHashMap JavaDoc<K,T>> step1 = new SimpleComponent<LinkedHashMap JavaDoc<K,T>>(LinkedHashMap JavaDoc.class){
3037      public LinkedHashMap JavaDoc<K,T> create(){
3038        return new LinkedHashMap JavaDoc<K,T>(keys.length);
3039      }
3040    };
3041    return storeMap(step1, keys, creators);
3042  }
3043  
3044  /**
3045   * Create a Component that sequentially execute an array of Component object,
3046   * and collect the results in a java.util.Map object.
3047   * @param component_return_map the Component that creates the java.util.Map object.
3048   * @param keys the keys to use.
3049   * @param vals the components to be sequentially executed.
3050   * @return the new Component object.
3051   */

3052  public static <K,T,M extends java.util.Map JavaDoc<K,T>> Component<M> storeMap(final Component<M> component_return_map,
3053      final K[] keys, Creator<T>[] vals){
3054    return component_return_map.followedBy(new StoreBinder<T,M>(vals){
3055      public ElementStore<T> toStore(M v){
3056        if(v instanceof java.util.Map JavaDoc){
3057          return new MapStore<K,T>(keys, v);
3058        }
3059        else{
3060          throw new ClassCastException JavaDoc("java.util.Map expected, "+
3061              Utils.getObjTypeName(v)+" encountered.");
3062        }
3063      }
3064    }).label();
3065    
3066  }
3067  /**
3068   * By default, all components depended by a component
3069   * will be verified when the component is verified.
3070   * incomplete() creates a new Component object that
3071   * suppresses the verification of dependency.
3072   * <br>
3073   * This customization cannot be applied to a late-bound component
3074   * whose getType() returns null.
3075   * In order to suppress verification, first use subsume() or cast()
3076   * to give it a type.
3077   * @param cc the Component to suppress verification for its parameters/properties.
3078   * @return the new Component object.
3079   * @throws UnknownComponentTypeException if the Component is a late-bound
3080   * component whose getType() returns null.
3081   */

3082  public static <T> Component<T> incomplete(final Component<T> cc)
3083  throws UnknownComponentTypeException{
3084    final Class JavaDoc ctype = cc.getType();
3085    if(ctype ==null){
3086      throw new UnknownComponentTypeException("immature component " + cc +
3087          " cannot be made incomplete");
3088    }
3089    return new ClosureableComponent(cc){
3090      public Class JavaDoc verify(Dependency dependency){
3091        return ctype;
3092      }
3093      protected Component decorate(Component c){
3094        return Components.incomplete(c);
3095      }
3096      public String JavaDoc toString(){
3097        return "incomplete <" + cc + ">";
3098      }
3099    }.label();
3100  }
3101  
3102  
3103  /**
3104   * Customizes a Component object so that upon creation,
3105   * the new Component object mutates the result component instance before it is returned.
3106   * @param cc the Component object to mutate.
3107   * @param m the Mutation object encapsulating the mutation logic.
3108   * @return the new Component object.
3109   */

3110  public static <T> Component<T> mutate(final Component<T> cc, final Mutation<T> m){
3111    //return new MutateComponent(cc, m).label();
3112
return cc.followedBy(new Mutation2Binder<T>(m));
3113  }
3114  
3115  /**
3116   * Create a Component that repeatedly call another Component for
3117   * certain amount of times.
3118   * @param cc the component to repeated call.
3119   * @param times the number of times to repeat.
3120   * @return the new Component object.
3121   */

3122  public static <T> Component<T> repeat(final Creator<T> cc, final int times){
3123    if(times<0)
3124      throw new IllegalArgumentException JavaDoc("negative repeat times: "+times);
3125    if(times==0)
3126      return value(null);
3127    if(times==1)
3128      return adapt(cc);
3129    return new RepeatComponent<T>(cc, times).label();
3130  }
3131  
3132  /**
3133   * Create a Component that the "create()" method is put in a
3134   * synchronized block to ensure thread safety.
3135   * @param cc the Component object.
3136   * @return the Component object that is "synchronized".
3137   */

3138  public static <T> Component<T> synchronizedComponent(final Component<T> cc){
3139    return new SynchronizedComponent(cc);
3140  }
3141  static Class JavaDoc[] toInterfaces(Class JavaDoc type){
3142    if(type.isInterface()){
3143      return new Class JavaDoc[]{type};
3144    }
3145    else return type.getInterfaces();
3146  }
3147  private static void checkType(final Class JavaDoc itf, final Class JavaDoc type){
3148    if(!ReflectionUtil.isAssignableFrom(itf, type)){
3149      throw new IllegalArgumentException JavaDoc(
3150          Misc.getTypeName(type) + " is not a subtype of "
3151          + Misc.getTypeName(itf));
3152    }
3153  }
3154  private static void checkTypes(final Class JavaDoc[] itfs, final Class JavaDoc type){
3155    for(int i=0; i<itfs.length; i++){
3156      final Class JavaDoc itf = itfs[i];
3157      checkType(itf, type);
3158    }
3159  }
3160  /*
3161  private static final class DefaultValue implements java.io.Serializable{
3162    public String toString(){
3163      return "default_value";
3164    }
3165  }
3166  private static final Object default_value = new DefaultValue();
3167*/

3168  private static Object JavaDoc checkInstanceType(final Class JavaDoc type, final Object JavaDoc r) {
3169    if(type != null && !ReflectionUtil.isInstance(type, r)){
3170      throw new TypeMismatchException(type, r==null?null:r.getClass(),
3171          Misc.getTypeName(type)
3172          +" expected, while " + Misc.getTypeName(Utils.getObjType(r))
3173          +" encountered.");
3174    }
3175    return r;
3176  }
3177}
3178
Popular Tags