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 | 52 | this( FactoryAnnotationProvisionType.CONSTRUCTOR, constructor, null, parameterPosition, null, |
57 | |
provisionAnnotation, annotations, typeLiteral, null ); |
58 | 52 | } |
59 | |
|
60 | |
public FactoryAnnotationProvisionImpl( final Method method, int parameterPosition, final A provisionAnnotation, |
61 | |
final Annotation[] annotations, final TypeLiteral<T> typeLiteral ) |
62 | |
{ |
63 | |
|
64 | 32 | this( FactoryAnnotationProvisionType.METHOD, null, method, parameterPosition, null, provisionAnnotation, |
65 | |
annotations, typeLiteral, null ); |
66 | 32 | } |
67 | |
|
68 | |
public FactoryAnnotationProvisionImpl( final Field field, final A provisionAnnotation, |
69 | |
final Annotation[] annotations, final TypeLiteral<T> typeLiteral ) |
70 | |
{ |
71 | |
|
72 | 196 | this( FactoryAnnotationProvisionType.FIELD, null, null, -1, field, provisionAnnotation, annotations, |
73 | |
typeLiteral, null ); |
74 | 196 | } |
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 | 436 | { |
81 | |
|
82 | 436 | this.provisionType = provisionType; |
83 | 436 | this.constructor = constructor; |
84 | 436 | this.method = method; |
85 | 436 | this.field = field; |
86 | 436 | this.provisionAnnotation = provisionAnnotation; |
87 | 436 | this.target = target; |
88 | 436 | this.parameterPosition = parameterPosition; |
89 | |
|
90 | 436 | this.annotations = new Annotation[annotations.length]; |
91 | 436 | System.arraycopy( annotations, 0, this.annotations, 0, annotations.length ); |
92 | 436 | } |
93 | |
|
94 | |
public FactoryAnnotationProvisionType getProvisionType() |
95 | |
{ |
96 | 156 | return provisionType; |
97 | |
} |
98 | |
|
99 | |
public Constructor<T> getConstructor() |
100 | |
{ |
101 | 156 | return constructor; |
102 | |
} |
103 | |
|
104 | |
public Method getMethod() |
105 | |
{ |
106 | 156 | return method; |
107 | |
} |
108 | |
|
109 | |
public Field getField() |
110 | |
{ |
111 | 156 | return field; |
112 | |
} |
113 | |
|
114 | |
public T getTarget() |
115 | |
{ |
116 | 0 | return target; |
117 | |
} |
118 | |
|
119 | |
public A getProvisionAnnotation() |
120 | |
{ |
121 | 156 | return provisionAnnotation; |
122 | |
} |
123 | |
|
124 | |
public Annotation[] getAnnotations() |
125 | |
{ |
126 | 156 | final Annotation[] temp = new Annotation[annotations.length]; |
127 | 156 | System.arraycopy( annotations, 0, temp, 0, annotations.length ); |
128 | 156 | return annotations; |
129 | |
} |
130 | |
|
131 | |
public int getParameterPosition() |
132 | |
{ |
133 | 220 | return parameterPosition; |
134 | |
} |
135 | |
|
136 | |
public TypeLiteral<T> getElementTypeLiteral() |
137 | |
{ |
138 | 156 | return null; |
139 | |
} |
140 | |
|
141 | |
@Override |
142 | |
public int hashCode() |
143 | |
{ |
144 | 0 | final int prime = 31; |
145 | 0 | int result = 1; |
146 | 0 | result = prime * result + Arrays.hashCode( annotations ); |
147 | 0 | result = prime * result + ( ( constructor == null ) ? 0 : constructor.hashCode() ); |
148 | 0 | result = prime * result + ( ( field == null ) ? 0 : field.hashCode() ); |
149 | 0 | result = prime * result + ( ( method == null ) ? 0 : method.hashCode() ); |
150 | 0 | result = prime * result + parameterPosition; |
151 | 0 | result = prime * result + ( ( provisionAnnotation == null ) ? 0 : provisionAnnotation.hashCode() ); |
152 | 0 | result = prime * result + ( ( provisionType == null ) ? 0 : provisionType.hashCode() ); |
153 | 0 | result = prime * result + ( ( target == null ) ? 0 : target.hashCode() ); |
154 | 0 | return result; |
155 | |
} |
156 | |
|
157 | |
@Override |
158 | |
public boolean equals( Object obj ) |
159 | |
{ |
160 | 0 | if ( this == obj ) |
161 | 0 | return true; |
162 | 0 | if ( obj == null ) |
163 | 0 | return false; |
164 | 0 | if ( getClass() != obj.getClass() ) |
165 | 0 | return false; |
166 | 0 | FactoryAnnotationProvisionImpl<?, ?> other = (FactoryAnnotationProvisionImpl<?, ?>) obj; |
167 | 0 | if ( !Arrays.equals( annotations, other.annotations ) ) |
168 | 0 | return false; |
169 | 0 | if ( constructor == null ) |
170 | |
{ |
171 | 0 | if ( other.constructor != null ) |
172 | 0 | return false; |
173 | |
} |
174 | 0 | else if ( !constructor.equals( other.constructor ) ) |
175 | 0 | return false; |
176 | 0 | if ( field == null ) |
177 | |
{ |
178 | 0 | if ( other.field != null ) |
179 | 0 | return false; |
180 | |
} |
181 | 0 | else if ( !field.equals( other.field ) ) |
182 | 0 | return false; |
183 | 0 | if ( method == null ) |
184 | |
{ |
185 | 0 | if ( other.method != null ) |
186 | 0 | return false; |
187 | |
} |
188 | 0 | else if ( !method.equals( other.method ) ) |
189 | 0 | return false; |
190 | 0 | if ( parameterPosition != other.parameterPosition ) |
191 | 0 | return false; |
192 | 0 | if ( provisionAnnotation == null ) |
193 | |
{ |
194 | 0 | if ( other.provisionAnnotation != null ) |
195 | 0 | return false; |
196 | |
} |
197 | 0 | else if ( !provisionAnnotation.equals( other.provisionAnnotation ) ) |
198 | 0 | return false; |
199 | 0 | if ( provisionType != other.provisionType ) |
200 | 0 | return false; |
201 | 0 | if ( target == null ) |
202 | |
{ |
203 | 0 | if ( other.target != null ) |
204 | 0 | return false; |
205 | |
} |
206 | 0 | else if ( !target.equals( other.target ) ) |
207 | 0 | return false; |
208 | 0 | return true; |
209 | |
} |
210 | |
|
211 | |
@Override |
212 | |
public String toString() |
213 | |
{ |
214 | 0 | 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 | 124 | if ( injectionPoint.getMember() instanceof Field ) |
225 | |
{ |
226 | 40 | final Field field = (Field) injectionPoint.getMember(); |
227 | |
|
228 | 40 | return new FactoryAnnotationProvisionImpl<T, A>( field, annotation, field.getAnnotations(), |
229 | |
(TypeLiteral<T>) buildTypeLiteral( field.getType() ) ); |
230 | |
|
231 | |
} |
232 | 84 | else if ( injectionPoint.getMember() instanceof Method ) |
233 | |
{ |
234 | 32 | final Method method = (Method) injectionPoint.getMember(); |
235 | 32 | final Annotation[][] parameterAnnotations = method.getParameterAnnotations(); |
236 | |
|
237 | 40 | for ( int i = 0; i < method.getParameterTypes().length; i++ ) |
238 | |
{ |
239 | 40 | final Annotation[] annotations = parameterAnnotations[i]; |
240 | |
|
241 | 48 | for ( int o = 0; o < annotations.length; o++ ) |
242 | |
{ |
243 | 40 | if ( annotation.equals( annotations[o] ) ) |
244 | |
{ |
245 | 32 | 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 | 0 | } |
256 | 52 | else if ( injectionPoint.getMember() instanceof Constructor ) |
257 | |
{ |
258 | 52 | final Constructor<T> constructor = (Constructor<T>) injectionPoint.getMember(); |
259 | |
|
260 | 52 | final Annotation[][] parameterAnnotations = constructor.getParameterAnnotations(); |
261 | |
|
262 | 96 | for ( int i = 0; i < constructor.getParameterTypes().length; i++ ) |
263 | |
{ |
264 | 96 | final Annotation[] annotations = parameterAnnotations[i]; |
265 | |
|
266 | 140 | for ( int o = 0; o < annotations.length; o++ ) |
267 | |
{ |
268 | 96 | if ( annotation.equals( annotations[o] ) ) |
269 | |
{ |
270 | 52 | 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 | 0 | 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 | 156 | 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 | 124 | return TypeLiteral.get( clazz ); |
301 | |
} |
302 | |
|
303 | |
} |