1 package org.apache.commons.digester3.annotations.handlers;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import static org.apache.commons.digester3.annotations.utils.AnnotationUtils.getAnnotationNamespaceURI;
23 import static org.apache.commons.digester3.annotations.utils.AnnotationUtils.getAnnotationPattern;
24 import static org.apache.commons.digester3.annotations.utils.AnnotationUtils.getAnnotationValue;
25 import static org.apache.commons.digester3.annotations.utils.AnnotationUtils.getAnnotationsArrayValue;
26 import static org.apache.commons.digester3.annotations.utils.AnnotationUtils.getFireOnBegin;
27
28 import java.lang.annotation.Annotation;
29 import java.lang.reflect.Constructor;
30 import java.lang.reflect.Method;
31 import java.lang.reflect.Modifier;
32
33 import org.apache.commons.digester3.annotations.AnnotationHandler;
34 import org.apache.commons.digester3.annotations.DigesterRule;
35 import org.apache.commons.digester3.annotations.DigesterRuleList;
36 import org.apache.commons.digester3.annotations.FromAnnotationsRuleModule;
37 import org.apache.commons.digester3.annotations.rules.CreationRule;
38 import org.apache.commons.digester3.binder.RulesBinder;
39
40
41
42
43
44
45
46
47
48 abstract class AbstractMethodHandler<A extends Annotation> implements AnnotationHandler<A, Method>
49 {
50
51
52
53
54 private static final int SUPPORTED_ARGS = 1;
55
56
57
58
59 public void handle( A annotation, Method element, RulesBinder rulesBinder )
60 {
61 if ( SUPPORTED_ARGS != element.getParameterTypes().length )
62 {
63 DigesterRule rule = annotation.annotationType().getAnnotation( DigesterRule.class );
64
65 rulesBinder.addError( "Methods annotated with digester annotation rule @%s must have just one argument",
66 rule.reflectsRule().getName() );
67 return;
68 }
69
70 Object explicitTypesObject = getAnnotationValue( annotation );
71 if ( explicitTypesObject == null || !explicitTypesObject.getClass().isArray()
72 || Class.class != explicitTypesObject.getClass().getComponentType() )
73 {
74 rulesBinder.addError( "Impossible to apply this handler, @%s.value() has to be of type 'Class<?>[]'",
75 annotation.getClass().getName() );
76 return;
77 }
78
79 Class<?>[] explicitTypes = (Class<?>[]) explicitTypesObject;
80 Class<?> paramType = element.getParameterTypes()[0];
81 boolean fireOnBegin = getFireOnBegin( annotation );
82
83 if ( explicitTypes.length > 0 )
84 {
85 for ( Class<?> explicitType : explicitTypes )
86 {
87 if ( !paramType.isAssignableFrom( explicitType ) )
88 {
89 rulesBinder.addError( "Impossible to handle annotation %s on method, %s has to be a %s",
90 annotation, element.toGenericString(), explicitType.getName(),
91 paramType.getName() );
92 return;
93 }
94
95 doHandle( annotation, element, explicitType, fireOnBegin, rulesBinder );
96 }
97 }
98 else
99 {
100 doHandle( annotation, element, paramType, fireOnBegin, rulesBinder );
101 }
102 }
103
104 private void doHandle( A methodAnnotation, Method method, Class<?> type, boolean fireOnBegin,
105 RulesBinder rulesBinder )
106 {
107 if ( type.isInterface() && Modifier.isAbstract( type.getModifiers() ) )
108 {
109 rulesBinder.addError( "Impossible to proceed analyzing %s, specified type '%s' is an interface/abstract",
110 methodAnnotation, type.getName() );
111 return;
112 }
113
114 for ( Annotation annotation : type.getAnnotations() )
115 {
116 doHandle( methodAnnotation, annotation, method, type, fireOnBegin, rulesBinder );
117 }
118
119 for ( Constructor<?> constructor : type.getConstructors() )
120 {
121 for ( Annotation annotation : constructor.getAnnotations() )
122 {
123 doHandle( methodAnnotation, annotation, method, type, fireOnBegin, rulesBinder );
124 }
125 }
126 }
127
128 private void doHandle( A methodAnnotation, Annotation annotation, Method method, final Class<?> type,
129 boolean fireOnBegin, RulesBinder rulesBinder )
130 {
131 if ( annotation.annotationType().isAnnotationPresent( DigesterRule.class )
132 && annotation.annotationType().isAnnotationPresent( CreationRule.class ) )
133 {
134 rulesBinder.install( new FromAnnotationsRuleModule()
135 {
136
137 @Override
138 protected void configureRules()
139 {
140 bindRulesFrom( type );
141 }
142
143 } );
144
145 String pattern = getAnnotationPattern( annotation );
146 String namespaceURI = getAnnotationNamespaceURI( annotation );
147 doBind( pattern, namespaceURI, method, type, fireOnBegin, rulesBinder );
148 }
149 else if ( annotation.annotationType().isAnnotationPresent( DigesterRuleList.class ) )
150 {
151
152 Annotation[] annotations = getAnnotationsArrayValue( annotation );
153 if ( annotations != null )
154 {
155
156 for ( Annotation ptr : annotations )
157 {
158 doHandle( methodAnnotation, ptr, method, type, fireOnBegin, rulesBinder );
159 }
160 }
161 }
162 }
163
164 protected abstract void doBind( String pattern, String namespaceURI, Method method, Class<?> type,
165 boolean fireOnBegin, RulesBinder rulesBinder );
166
167 }