View Javadoc

1   /*
2    * Copyright 2007-2008 Naoki NOSE.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package jp.liq.container.vocabulary;
17  
18  import jp.liq.container.component.ComponentMethodComponent;
19  import jp.liq.container.component.ConstructorComponent;
20  import jp.liq.container.component.InjectableComponentList;
21  import jp.liq.container.component.MappingComponent;
22  import jp.liq.container.component.ObjectComponent;
23  import jp.liq.container.component.ObjectMethodComponent;
24  import jp.liq.container.reflect.ClassMethodFinder;
25  import jp.liq.container.reflect.ConstructorWrapper;
26  import jp.liq.container.reflect.MethodWrapper;
27  import jp.liq.container.reflect.ObjectMethod;
28  import jp.liq.container.reflect.ObjectMethodFinder;
29  import jp.liq.container.vocabulary.VocabularyException.Reason;
30  
31  /**
32   * {@link jp.liq.container.Component} のインスタンスを生成します。
33   * @see jp.liq.container.ContainerVocabulary#component
34   * @author nosen
35   */
36  public class Components {
37      private final Methods methods = new Methods();
38      
39      /**
40       * MappingComponent を生成します。
41       */
42      public <T> MappingComponent<T> mapping(Class<T> type, Class<?> subtype) {
43          //TODO check if type and subtype is not null
44      	if(!type.isAssignableFrom(subtype)) {
45      		throw new VocabularyException(Reason.INVALID_MAPPING, 
46      				type, subtype);
47      	}
48          return new MappingComponent<T>(type, subtype);
49      }
50  
51      /**
52       * ObjectComponent を生成します。
53       */
54      public <T> ObjectComponent<T> instance(Class<T> type ,T obj) {
55          return new ObjectComponent<T>(type, obj);
56      }
57  
58      /**
59       * ObjectMethodComponentのリストを生成します。
60       * 
61       * @param obj
62       * @return 生成された InjectableComponentList
63       */
64      public InjectableComponentList factory(Object obj) {
65          return from(methods.of(obj).withAnnotation(Factory.class));
66      }
67  
68      public InjectableComponentList factory(Class<?> type) {
69          return from(methods.of(type).withAnnotation(Factory.class));
70      }
71  
72      /**
73       * コンストラクタを使用してコンポーネントのインスタンスを構築する、
74       * InjectableComponentのインスタンスを生成します。
75       * @param ctor コンポーネントのインスタンスを生成するコンストラクタ
76       * @return 生成された InjectableComponent
77       */
78      public <T> ConstructorComponent<T> from(ConstructorWrapper<T> ctor) {
79          Class<T> declaringClass = ctor.getConstructor().getDeclaringClass();
80  		boolean recycled = declaringClass.isAnnotationPresent(Recycle.class);
81      	return new ConstructorComponent<T>(ctor, declaringClass, recycled);
82      }
83  
84      /**
85       * オブジェクトのメソッドを使用してコンポーネントのインスタンスを構築する、
86       * Componentのインスタンスを生成します。
87       * @param finder コンポーネントを生成するメソッド
88       * @return 生成された Componentのリスト
89       */
90      public <T> InjectableComponentList from(ObjectMethodFinder finder) {
91          InjectableComponentList rv = new InjectableComponentList();
92          for(ObjectMethod m : finder) {
93              rv.add(createObjectMethodComponent(m.getMethod().getReturnType(), m));
94          }
95          return rv;
96      }
97  
98      /**
99       * 他のコンポーネントのメソッドを使用してコンポーネントのインスタンスを構築する、
100      * Componentのインスタンスを生成します。
101      * @param finder コンポーネントを生成するメソッド
102      * @return 生成された Componentのリスト
103      */
104     public InjectableComponentList from(ClassMethodFinder<?> finder) {
105         InjectableComponentList rv  = 
106             new InjectableComponentList();
107         for(MethodWrapper m : finder) {
108             rv.add(createComponentMethodComponent(m.getMethod().getReturnType(), m, 
109                     finder.getOwnerClass()));
110         }
111         return rv;
112     }
113 
114     private <T> ObjectMethodComponent<T> createObjectMethodComponent(Class<T> returnType, 
115             ObjectMethod m) {
116         return new ObjectMethodComponent<T>(returnType, m);
117     }
118 
119     private <T> ComponentMethodComponent<T> createComponentMethodComponent(Class<T> rtype, 
120             MethodWrapper m, Class<?> ctype) {
121         return new ComponentMethodComponent<T>(rtype, m, ctype);
122     }
123 }