View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
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 }