1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.onami.factoryannotation;
20
21 import java.lang.annotation.Annotation;
22 import java.lang.reflect.Constructor;
23 import java.lang.reflect.Field;
24 import java.lang.reflect.Method;
25 import java.util.Arrays;
26
27 import com.google.inject.ProvisionException;
28 import com.google.inject.TypeLiteral;
29 import com.google.inject.spi.InjectionPoint;
30
31 class FactoryAnnotationProvisionImpl<T, A extends Annotation>
32 implements FactoryAnnotationProvision<T, A>
33 {
34
35 private final FactoryAnnotationProvisionType provisionType;
36
37 private final Constructor<T> constructor;
38
39 private final Method method;
40
41 private final Field field;
42
43 private final A provisionAnnotation;
44
45 private final Annotation[] annotations;
46
47 private final T target;
48
49 private final int parameterPosition;
50
51 public FactoryAnnotationProvisionImpl( final Constructor<T> constructor, int parameterPosition,
52 final A provisionAnnotation, final Annotation[] annotations,
53 final TypeLiteral<T> typeLiteral )
54 {
55
56 this( FactoryAnnotationProvisionType.CONSTRUCTOR, constructor, null, parameterPosition, null,
57 provisionAnnotation, annotations, typeLiteral, null );
58 }
59
60 public FactoryAnnotationProvisionImpl( final Method method, int parameterPosition, final A provisionAnnotation,
61 final Annotation[] annotations, final TypeLiteral<T> typeLiteral )
62 {
63
64 this( FactoryAnnotationProvisionType.METHOD, null, method, parameterPosition, null, provisionAnnotation,
65 annotations, typeLiteral, null );
66 }
67
68 public FactoryAnnotationProvisionImpl( final Field field, final A provisionAnnotation,
69 final Annotation[] annotations, final TypeLiteral<T> typeLiteral )
70 {
71
72 this( FactoryAnnotationProvisionType.FIELD, null, null, -1, field, provisionAnnotation, annotations,
73 typeLiteral, null );
74 }
75
76 FactoryAnnotationProvisionImpl( final FactoryAnnotationProvisionType provisionType,
77 final Constructor<T> constructor, final Method method, int parameterPosition,
78 final Field field, final A provisionAnnotation, final Annotation[] annotations,
79 final TypeLiteral<T> typeLiteral, final T target )
80 {
81
82 this.provisionType = provisionType;
83 this.constructor = constructor;
84 this.method = method;
85 this.field = field;
86 this.provisionAnnotation = provisionAnnotation;
87 this.target = target;
88 this.parameterPosition = parameterPosition;
89
90 this.annotations = new Annotation[annotations.length];
91 System.arraycopy( annotations, 0, this.annotations, 0, annotations.length );
92 }
93
94 public FactoryAnnotationProvisionType getProvisionType()
95 {
96 return provisionType;
97 }
98
99 public Constructor<T> getConstructor()
100 {
101 return constructor;
102 }
103
104 public Method getMethod()
105 {
106 return method;
107 }
108
109 public Field getField()
110 {
111 return field;
112 }
113
114 public T getTarget()
115 {
116 return target;
117 }
118
119 public A getProvisionAnnotation()
120 {
121 return provisionAnnotation;
122 }
123
124 public Annotation[] getAnnotations()
125 {
126 final Annotation[] temp = new Annotation[annotations.length];
127 System.arraycopy( annotations, 0, temp, 0, annotations.length );
128 return annotations;
129 }
130
131 public int getParameterPosition()
132 {
133 return parameterPosition;
134 }
135
136 public TypeLiteral<T> getElementTypeLiteral()
137 {
138 return null;
139 }
140
141 @Override
142 public int hashCode()
143 {
144 final int prime = 31;
145 int result = 1;
146 result = prime * result + Arrays.hashCode( annotations );
147 result = prime * result + ( ( constructor == null ) ? 0 : constructor.hashCode() );
148 result = prime * result + ( ( field == null ) ? 0 : field.hashCode() );
149 result = prime * result + ( ( method == null ) ? 0 : method.hashCode() );
150 result = prime * result + parameterPosition;
151 result = prime * result + ( ( provisionAnnotation == null ) ? 0 : provisionAnnotation.hashCode() );
152 result = prime * result + ( ( provisionType == null ) ? 0 : provisionType.hashCode() );
153 result = prime * result + ( ( target == null ) ? 0 : target.hashCode() );
154 return result;
155 }
156
157 @Override
158 public boolean equals( Object obj )
159 {
160 if ( this == obj )
161 return true;
162 if ( obj == null )
163 return false;
164 if ( getClass() != obj.getClass() )
165 return false;
166 FactoryAnnotationProvisionImpl<?, ?> other = (FactoryAnnotationProvisionImpl<?, ?>) obj;
167 if ( !Arrays.equals( annotations, other.annotations ) )
168 return false;
169 if ( constructor == null )
170 {
171 if ( other.constructor != null )
172 return false;
173 }
174 else if ( !constructor.equals( other.constructor ) )
175 return false;
176 if ( field == null )
177 {
178 if ( other.field != null )
179 return false;
180 }
181 else if ( !field.equals( other.field ) )
182 return false;
183 if ( method == null )
184 {
185 if ( other.method != null )
186 return false;
187 }
188 else if ( !method.equals( other.method ) )
189 return false;
190 if ( parameterPosition != other.parameterPosition )
191 return false;
192 if ( provisionAnnotation == null )
193 {
194 if ( other.provisionAnnotation != null )
195 return false;
196 }
197 else if ( !provisionAnnotation.equals( other.provisionAnnotation ) )
198 return false;
199 if ( provisionType != other.provisionType )
200 return false;
201 if ( target == null )
202 {
203 if ( other.target != null )
204 return false;
205 }
206 else if ( !target.equals( other.target ) )
207 return false;
208 return true;
209 }
210
211 @Override
212 public String toString()
213 {
214 return "IdentityProvisionImpl [provisionType=" + provisionType + ", constructor=" + constructor + ", method="
215 + method + ", field=" + field + ", provisionAnnotation=" + provisionAnnotation + ", annotations="
216 + Arrays.toString( annotations ) + ", target=" + target + ", parameterPosition=" + parameterPosition + "]";
217 }
218
219 @SuppressWarnings( "unchecked" )
220 static <T, A extends Annotation> FactoryAnnotationProvision<T, A> wrapInjectionPoint( final InjectionPoint injectionPoint,
221 final A annotation )
222 {
223
224 if ( injectionPoint.getMember() instanceof Field )
225 {
226 final Field field = (Field) injectionPoint.getMember();
227
228 return new FactoryAnnotationProvisionImpl<T, A>( field, annotation, field.getAnnotations(),
229 (TypeLiteral<T>) buildTypeLiteral( field.getType() ) );
230
231 }
232 else if ( injectionPoint.getMember() instanceof Method )
233 {
234 final Method method = (Method) injectionPoint.getMember();
235 final Annotation[][] parameterAnnotations = method.getParameterAnnotations();
236
237 for ( int i = 0; i < method.getParameterTypes().length; i++ )
238 {
239 final Annotation[] annotations = parameterAnnotations[i];
240
241 for ( int o = 0; o < annotations.length; o++ )
242 {
243 if ( annotation.equals( annotations[o] ) )
244 {
245 return new FactoryAnnotationProvisionImpl<T, A>(
246 method,
247 i,
248 annotation,
249 annotations,
250 (TypeLiteral<T>) buildTypeLiteral( method.getParameterTypes()[i] ) );
251 }
252 }
253 }
254
255 }
256 else if ( injectionPoint.getMember() instanceof Constructor )
257 {
258 final Constructor<T> constructor = (Constructor<T>) injectionPoint.getMember();
259
260 final Annotation[][] parameterAnnotations = constructor.getParameterAnnotations();
261
262 for ( int i = 0; i < constructor.getParameterTypes().length; i++ )
263 {
264 final Annotation[] annotations = parameterAnnotations[i];
265
266 for ( int o = 0; o < annotations.length; o++ )
267 {
268 if ( annotation.equals( annotations[o] ) )
269 {
270 return new FactoryAnnotationProvisionImpl<T, A>(
271 constructor,
272 i,
273 annotation,
274 annotations,
275 (TypeLiteral<T>) buildTypeLiteral( constructor.getParameterTypes()[i] ) );
276 }
277 }
278 }
279 }
280
281 throw new ProvisionException( "InjectionPoint could not be transformed to FactoryAnnotationProvision" );
282 }
283
284 static <T, A extends Annotation> FactoryAnnotationProvision<T, A> modify( final FactoryAnnotationProvision<T, A> identityProvision,
285 final T target )
286 {
287
288 return new FactoryAnnotationProvisionImpl<T, A>( identityProvision.getProvisionType(),
289 identityProvision.getConstructor(),
290 identityProvision.getMethod(),
291 identityProvision.getParameterPosition(),
292 identityProvision.getField(),
293 identityProvision.getProvisionAnnotation(),
294 identityProvision.getAnnotations(),
295 identityProvision.getElementTypeLiteral(), target );
296 }
297
298 private static <T> TypeLiteral<T> buildTypeLiteral( final Class<T> clazz )
299 {
300 return TypeLiteral.get( clazz );
301 }
302
303 }