View Javadoc

1   package org.apache.onami.test.reflection;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import static com.google.common.base.Preconditions.checkArgument;
23  
24  import java.lang.annotation.Annotation;
25  import java.lang.reflect.AnnotatedElement;
26  import java.util.logging.Level;
27  import java.util.logging.Logger;
28  
29  import com.google.common.collect.ArrayListMultimap;
30  import com.google.common.collect.Multimap;
31  
32  /**
33   * <p>
34   * Class visitor engine.
35   * </p>
36   * <p>
37   * Visit the input class and all super classes and invokes handler to register annotations.
38   * </p>
39   */
40  public final class ClassVisitor
41  {
42  
43      private static final String JAVA_PACKAGE = "java";
44  
45      private static final Logger LOGGER = Logger.getLogger( ClassVisitor.class.getName() );
46  
47      private final Multimap<Class<? extends Annotation>, AnnotationHandler<? extends Annotation, ? extends AnnotatedElement>> handlers =
48          ArrayListMultimap.create();
49  
50      /**
51       * Registers an annotation handler.
52       *
53       * @param <A> whatever annotation type
54       * @param annotationType the annotation class to handle
55       * @param handler the related annotation handler
56       * @return the current {@code ClassVisitor} instance
57       */
58      public <A extends Annotation> ClassVisitor registerHandler( Class<A> annotationType,
59                                                                  AnnotationHandler<A, ? extends AnnotatedElement> handler )
60      {
61          handlers.put( annotationType, handler );
62          return this;
63      }
64  
65      /**
66       * Visits all fields, methods and super classes of the input class.
67       *
68       * @param <T> any type
69       * @param type The type 
70       * @throws HandleException when an error occurs.
71       */
72      public <T> void visit( final Class<? super T> type )
73          throws HandleException
74      {
75          checkArgument( type != null, "Type to be visited cannot be null" );
76  
77          if ( LOGGER.isLoggable( Level.FINER ) )
78          {
79              LOGGER.finer( "  Visit class: " + type );
80          }
81  
82          if ( type.getPackage() != null && type.getPackage().getName().startsWith( JAVA_PACKAGE ) )
83          {
84              return;
85          }
86  
87          handle( type );
88          handle( type.getDeclaredFields() );
89          handle( type.getDeclaredMethods() );
90  
91          visit( type.getSuperclass() );
92      }
93  
94      @SuppressWarnings( "unchecked" )
95      private void handle( AnnotatedElement... elements )
96          throws HandleException
97      {
98          for ( AnnotatedElement element : elements )
99          {
100             for ( Annotation annotation : element.getAnnotations() )
101             {
102                 for ( AnnotationHandler<? extends Annotation, ? extends AnnotatedElement> handler : handlers.get( annotation.annotationType() ) )
103                 {
104                     ( (AnnotationHandler<Annotation, AnnotatedElement>) handler ).handle( annotation, element );
105                 }
106             }
107         }
108     }
109 
110 }