KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > hibernate > cfg > PropertyInferredData


1 //$Id: PropertyInferredData.java,v 1.3 2005/07/11 16:23:29 epbernard Exp $
2
package org.hibernate.cfg;
3
4 import java.beans.Introspector JavaDoc;
5 import java.lang.reflect.AnnotatedElement JavaDoc;
6 import java.lang.reflect.Field JavaDoc;
7 import java.lang.reflect.Member JavaDoc;
8 import java.lang.reflect.Method JavaDoc;
9 import java.lang.reflect.Modifier JavaDoc;
10 import java.lang.reflect.ParameterizedType JavaDoc;
11 import java.lang.reflect.Type JavaDoc;
12
13 import org.hibernate.MappingException;
14
15 /**
16  * Retrieve all inferred data from an annnoted element
17  * Currently support field and getter processing.
18  * An exception is thrown when the annoted element does not fit.
19  * The calculation is lazied until the first access to a public getter.
20  * This prevent useless reflection.
21  *
22  * @author Emmanuel Bernard
23  */

24 public class PropertyInferredData {
25     private String JavaDoc defaultAccess;
26     private String JavaDoc propertyName;
27     private Class JavaDoc returnedClassOrElement;
28     private Class JavaDoc returnedClass;
29     private Class JavaDoc collectionType;
30     private String JavaDoc returnedClassOrElementName;
31     private String JavaDoc returnedClassName;
32     private final AnnotatedElement JavaDoc annotedElt;
33     private boolean processed;
34     private boolean annotable;
35     private boolean skip;
36     private boolean isArray;
37
38     public PropertyInferredData(String JavaDoc defaultAccess, String JavaDoc propertyName, Class JavaDoc returnedClass) {
39         this.defaultAccess = defaultAccess;
40         this.processed = true;
41         this.propertyName = propertyName;
42         this.returnedClass = returnedClass;
43         this.returnedClassOrElement = returnedClass;
44         this.returnedClassName = returnedClass == null ? null : returnedClass.getName();
45         this.returnedClassOrElementName = returnedClassName;
46         annotedElt = null;
47         annotable = true;
48         skip = false;
49         isArray = false;
50     }
51
52     public boolean skip() {
53         execute(false);
54         return skip;
55     }
56
57     private static final String JavaDoc EXCEPTION_MESSAGE =
58         "The annoted inferred element should be a field or a getter";
59
60     /**
61      * Take the annoted element for lazy process
62      *
63      * @param annotedElt element to process
64      */

65     public PropertyInferredData(AnnotatedElement JavaDoc annotedElt) {
66         this.annotedElt = annotedElt;
67     }
68     
69     /**
70      * Process an annoted element and give a final
71      * structure.
72      * The annoted element must be either field or getter
73      *
74      * @throws MappingException No getter or field found or wrong JavaBean spec usage
75      */

76     private void execute(boolean throwException) throws MappingException {
77         if (! processed) {
78             /*
79              * guess access from annoted element type
80              * retrieve property name.
81              */

82             skip = false;
83             annotable = true;
84             if ( ! (annotedElt instanceof Member JavaDoc) ) {
85                 throw new MappingException(EXCEPTION_MESSAGE);
86             }
87             propertyName = retrievePropertyNameFromMember( (Member JavaDoc) annotedElt, throwException );
88             if (annotedElt instanceof Field JavaDoc) {
89                 Field JavaDoc field = (Field JavaDoc) annotedElt;
90                 defaultAccess = "field";
91                 returnedClass = field.getType();
92                 collectionType = findCollectionType(field);
93                 //TODO check whether synthetic shoud be excluded or not?
94
if ( field.isSynthetic() ||
95                      Modifier.isStatic( field.getModifiers() )
96                 ) {
97                     skip = true;
98                 }
99             }
100             else if (annotedElt instanceof Method JavaDoc) {
101                 Method JavaDoc method = (Method JavaDoc) annotedElt;
102                 defaultAccess = "property";
103                 returnedClass = method.getReturnType();
104                 collectionType = findCollectionType(method);
105                 //TODO check whether synthetic shoud be excluded or not?
106
if ( method.isSynthetic() ||
107                      method.isBridge() ||
108                      Modifier.isStatic( method.getModifiers() ) ||
109                      method.getParameterTypes().length != 0 || //not a getter
110
void.class.equals( method.getReturnType() ) //not a getter
111
) {
112                     skip = true;
113                 }
114             }
115             else {
116                 throw new MappingException(EXCEPTION_MESSAGE);
117             }
118             if ( returnedClass.isArray() ) {
119                 isArray = true;
120                 returnedClassOrElement = returnedClass.getComponentType();
121                 collectionType = returnedClassOrElement;
122             }
123             else {
124                 returnedClassOrElement = returnedClass;
125             }
126             returnedClassName = returnedClass.getName();
127             returnedClassOrElementName = returnedClassOrElement.getName();
128             if (annotable == false) skip = true;
129             processed = true;
130         }
131     }
132     
133     private Class JavaDoc findCollectionType(Method JavaDoc method) {
134         Type JavaDoc t = method.getGenericReturnType();
135         return extractType(t);
136     }
137     
138     private Class JavaDoc findCollectionType(Field JavaDoc field) {
139         Type JavaDoc t = field.getGenericType();
140         return extractType(t);
141     }
142     
143     private Class JavaDoc extractType(Type JavaDoc t) {
144         if (t != null && t instanceof ParameterizedType JavaDoc) {
145             ParameterizedType JavaDoc pt = (ParameterizedType JavaDoc) t;
146             Type JavaDoc[] genTypes = pt.getActualTypeArguments();
147             if (genTypes.length == 1 && genTypes[0] instanceof Class JavaDoc) {
148                 return (Class JavaDoc) genTypes[0];
149             }
150             else if (genTypes.length == 2 && genTypes[1] instanceof Class JavaDoc) {
151                 //TODO we might want to store the index type at some point
152
return (Class JavaDoc) genTypes[1];
153             }
154         }
155         return null;
156     }
157     
158     /**
159      * Build the property name from the Member one using JavaBean conventions
160      *
161      * @param member member used to build
162      * @return property name
163      *
164      * @throws MappingException annoted part not on a getter method
165      */

166     private String JavaDoc retrievePropertyNameFromMember(Member JavaDoc member, boolean throwException) throws MappingException {
167         
168         if (member instanceof Field JavaDoc) {
169             return member.getName();
170         }
171         else if (member instanceof Method JavaDoc) {
172             final String JavaDoc methName = member.getName();
173             if ( methName.startsWith( "get" ) ) {
174
175                 return Introspector.decapitalize( methName.substring( "get".length() ) );
176             }
177             else if ( methName.startsWith("is") ) {
178                 return Introspector.decapitalize( methName.substring( "is".length() ) );
179             }
180             else {
181                 annotable = false;
182                 if (throwException) {
183                     throw new MappingException("Annotated Method is not a proper getter: " + methName);
184                 }
185                 else {
186                     return methName;
187                 }
188             }
189         }
190         else {
191             throw new MappingException(EXCEPTION_MESSAGE);
192         }
193     }
194     
195     
196
197     /**
198      * @return default member access (whether field or property)
199      * @throws MappingException No getter or field found or wrong JavaBean spec usage
200      */

201     public String JavaDoc getDefaultAccess() throws MappingException {
202         execute(true);
203         return defaultAccess;
204     }
205
206     /**
207      * @return property name
208      * @throws MappingException No getter or field found or wrong JavaBean spec usage
209      */

210     public String JavaDoc getPropertyName() throws MappingException {
211         execute(true);
212         return propertyName;
213     }
214
215     /**
216      * Returns the returned class itself or the element type if an array
217      */

218     public Class JavaDoc getReturnedClassOrElement() throws MappingException {
219         execute(true);
220         return returnedClassOrElement;
221     }
222
223     /**
224      * Return the class itself
225      */

226     public Class JavaDoc getReturnedClass() throws MappingException {
227         execute(true);
228         return returnedClass;
229     }
230
231     /**
232      * Returns the returned class name itself or the element type if an array
233      */

234     public String JavaDoc getReturnedClassOrElementName() throws MappingException {
235         execute(true);
236         return returnedClassOrElementName;
237     }
238
239     /**
240      * Returns the returned class name itself
241      */

242     public String JavaDoc getReturnedClassName() throws MappingException {
243         execute(true);
244         return returnedClassName;
245     }
246
247     /**
248      * @return collection type if any, or null otherwise
249      */

250     public Class JavaDoc getCollectionType() {
251         return collectionType;
252     }
253
254     public boolean isArray() {
255         return isArray;
256     }
257 }
258
Popular Tags