KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > versant > core > metadata > EJBAnnotationProcessor


1
2 /*
3  * Copyright (c) 1998 - 2005 Versant Corporation
4  * All rights reserved. This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License v1.0
6  * which accompanies this distribution, and is available at
7  * http://www.eclipse.org/legal/epl-v10.html
8  *
9  * Contributors:
10  * Versant Corporation - initial API and implementation
11  */

12 package com.versant.core.metadata;
13
14 import com.versant.core.metadata.parser.*;
15 import com.versant.core.util.classhelper.ClassHelper;
16 import com.versant.core.common.BindingSupportImpl;
17
18 import javax.persistence.*;
19 import java.lang.reflect.*;
20 import java.lang.annotation.Annotation JavaDoc;
21 import java.util.Map JavaDoc;
22 import java.util.HashMap JavaDoc;
23 import java.io.Serializable JavaDoc;
24
25 /**
26  * MetaData PreProcessor for ejb jdbc metadata. The preprocessor looks for annotations
27  * and set the equivalent jdo metadata. If no annotations is present then the ejb defaults
28  * will be applied.
29  */

30 public class EJBAnnotationProcessor implements JdoExtensionKeys, MetaDataPreProcessor {
31     private ClassLoader JavaDoc loader;
32     private MetaDataUtils mdutils;
33     private final Class JavaDoc[] EMPTY_CLASS_ARRAY;
34
35     public EJBAnnotationProcessor(ClassLoader JavaDoc loader, MetaDataUtils mdutils) {
36         this.loader = loader;
37         this.mdutils = mdutils;
38         EMPTY_CLASS_ARRAY = new Class JavaDoc[] {};
39     }
40
41     public void process(JdoClass jdoClass) {
42         Class JavaDoc cls;
43         try {
44             cls = loadClass(jdoClass.getQName());
45         } catch (ClassNotFoundException JavaDoc e) {
46             throw new RuntimeException JavaDoc(e);
47         }
48
49         if (!cls.isAnnotationPresent(javax.persistence.Entity.class)) return;
50         javax.persistence.Entity ea = (Entity) cls.getAnnotation(javax.persistence.Entity.class);
51
52         //change to appid
53
jdoClass.identityType = MDStatics.IDENTITY_TYPE_APPLICATION;
54         jdoClass.objectIdClasssRequired = false;
55
56         //update table name
57
if (cls.isAnnotationPresent(javax.persistence.Table.class)) {
58             javax.persistence.Table ta = (Table) cls.getAnnotation(javax.persistence.Table.class);
59             JdoExtension ext = JdoExtension.find(JDBC_TABLE_NAME, jdoClass.elements);
60             if (ext == null) {
61                 ext = new JdoExtension();
62                 ext.key = JDBC_TABLE_NAME;
63                 ext.value = ta.name();
64                 jdoClass.addElement(ext);
65             }
66         }
67
68         //calculate pc super
69
doPCSuperClass(jdoClass, cls);
70
71         //create a map for jdoField name to jdoField instance.
72
Map JavaDoc jdoFieldMap = createFieldMap(jdoClass);
73
74         final AccessibleMember accessibleMember = new AccessibleMember();
75         if (ea.access() == AccessType.FIELD) {
76             Field[] fields = cls.getDeclaredFields();
77             for (int i = 0; i < fields.length; i++) {
78                 accessibleMember.init(fields[i], null);
79                 bla(jdoFieldMap, jdoClass, accessibleMember);
80             }
81         } else {
82             Field[] fields = cls.getDeclaredFields();
83             for (int i = 0; i < fields.length; i++) {
84                 String JavaDoc s = fields[i].getName();
85                 char[] ca = s.toCharArray();
86                 ca[0] = Character.toUpperCase(ca[0]);
87                 Method m = null;
88                 try {
89                     m = cls.getDeclaredMethod("get" + String.valueOf(ca), EMPTY_CLASS_ARRAY);
90                 } catch (NoSuchMethodException JavaDoc e) {
91 // System.out.println("method 'get" + String.valueOf(ca) + "' not found");
92
try {
93                         m = cls.getDeclaredMethod("is" + String.valueOf(ca), EMPTY_CLASS_ARRAY);
94 // System.out.println("method 'is" + String.valueOf(ca) + "' not found");
95
} catch (NoSuchMethodException JavaDoc e1) {
96                     }
97                 }
98                 //only proceed if the method is found.
99
if (m == null) {
100 // System.out.println("Accessor method not found for field '" + fields[i].getName() + "'");
101
continue;
102                 }
103                 accessibleMember.init(fields[i], m);
104                 bla(jdoFieldMap, jdoClass, accessibleMember);
105             }
106         }
107     }
108
109     private void bla(Map JavaDoc jdoFieldMap, JdoClass jdoClass, AccessibleMember property) {
110         //ignore certain fields
111
if (property.isSynthetic()) return;
112         if (Modifier.isStatic(property.getModifiers())) return;
113         if (mdutils.isEnhancerAddedField(property.getName())) return;
114         //check if there is a field for the property
115

116         JdoField jdoField = getJdoField(jdoFieldMap, property, jdoClass);
117
118         if (jdoField.persistenceModifier == 0
119                 && property.isAnnotationPresent(Transient.class)) {
120             jdoField.persistenceModifier = MDStatics.PERSISTENCE_MODIFIER_NONE;
121             return;
122         }
123
124         processId(property, jdoField, jdoClass);
125
126         if (property.isAnnotationPresent(javax.persistence.Column.class)) {
127             javax.persistence.Column ca = property.getAnnotation(javax.persistence.Column.class);
128             if (isValid(ca.name())) {
129                 jdoField.findCreate(JDBC_COLUMN, null, false).
130                         findCreate(JDBC_COLUMN_NAME, ca.name(), false);
131             }
132             if (ca.scale() != 0) {
133                 jdoField.findCreate(JDBC_COLUMN, null, false).
134                         findCreate(JDBC_SCALE, "" + ca.scale(), false);
135             }
136             if (ca.length() != 255) {
137                 jdoField.findCreate(JDBC_COLUMN, null, false).
138                         findCreate(JDBC_LENGTH, "" + ca.length(), false);
139             }
140
141             if (ca.primaryKey()) jdoField.primaryKey = true;
142         }
143
144         if (property.isAnnotationPresent(Basic.class)) {
145             Basic basic = property.getAnnotation(Basic.class);
146             jdoField.defaultFetchGroup = (basic.fetch() == FetchType.EAGER) ? MDStatics.TRUE : MDStatics.FALSE;
147         } else if (property.isAnnotationPresent(OneToOne.class)) {
148             OneToOne oto = property.getAnnotation(OneToOne.class);
149             if (oto.cascade() != null) {
150                 setCascadeType(oto.cascade(), jdoField);
151             }
152             if (!oto.optional()) jdoField.nullValue = MDStatics.NULL_VALUE_EXCEPTION;
153             jdoField.defaultFetchGroup = (oto.fetch() == FetchType.EAGER) ? MDStatics.TRUE : MDStatics.FALSE;
154         } else if (property.isAnnotationPresent(OneToMany.class)) {
155             OneToMany oto = property.getAnnotation(OneToMany.class);
156             if (oto.cascade() != null) {
157                 setCascadeType(oto.cascade(), jdoField);
158             }
159             jdoField.defaultFetchGroup = (oto.fetch() == FetchType.EAGER) ? MDStatics.TRUE : MDStatics.FALSE;
160
161             JdoCollection col = jdoField.collection;
162             if (col == null) {
163                 col = jdoField.collection = new JdoCollection();
164                 jdoField.collection.parent = jdoField;
165             }
166
167             if (!isValid(col.elementType) && isValid(oto.targetEntity())) {
168                 col.elementType = oto.targetEntity();
169             }
170
171             //inverse field
172
if (isValid(oto.mappedBy())) {
173                 col.findCreate(INVERSE, oto.mappedBy(), false);
174             }
175         } else if (property.isAnnotationPresent(ManyToMany.class)) {
176             ManyToMany oto = property.getAnnotation(ManyToMany.class);
177             if (oto.cascade() != null) {
178                 setCascadeType(oto.cascade(), jdoField);
179             }
180             jdoField.defaultFetchGroup = (oto.fetch() == FetchType.EAGER) ? MDStatics.TRUE : MDStatics.FALSE;
181
182         } else if (property.isAnnotationPresent(ManyToOne.class)) {
183             ManyToOne oto = property.getAnnotation(ManyToOne.class);
184             if (oto.cascade() != null) {
185                 setCascadeType(oto.cascade(), jdoField);
186             }
187             jdoField.defaultFetchGroup = (oto.fetch() == FetchType.EAGER) ? MDStatics.TRUE : MDStatics.FALSE;
188
189         } else if (property.isAnnotationPresent(Serialized.class)) {
190             Serialized oto = property.getAnnotation(Serialized.class);
191             jdoField.defaultFetchGroup = (oto.fetch() == FetchType.EAGER) ? MDStatics.TRUE : MDStatics.FALSE;
192             jdoField.findCreate(EXTERNALIZER, "SERIALIZED", false);
193         } else if (property.isAnnotationPresent(Embedded.class)) {
194             jdoField.embedded = MDStatics.TRUE;
195             jdoField.defaultFetchGroup = MDStatics.FALSE;
196         } else if (property.isAnnotationPresent(Lob.class)) {
197             Lob lob = property.getAnnotation(Lob.class);
198             jdoField.defaultFetchGroup = (lob.fetch() == FetchType.EAGER) ? MDStatics.TRUE : MDStatics.FALSE;
199         } else if (property.isAnnotationPresent(Version.class)) {
200             jdoField.findCreate(JDBC_OPTIMISTIC_LOCKING, "version", false);
201         } else {
202             if (!mdutils.isPersistentModifiers(property.getModifiers())) {
203                 jdoField.persistenceModifier = MDStatics.PERSISTENCE_MODIFIER_NONE;
204             } else if (mdutils.isBasicType(property.getType())) {
205                 jdoField.defaultFetchGroup = MDStatics.TRUE;
206             } else if (property.getType().isAnnotationPresent(javax.persistence.Embeddable.class)) {
207                 jdoField.embedded = MDStatics.TRUE;
208                 jdoField.defaultFetchGroup = MDStatics.TRUE;
209             } else if (Serializable JavaDoc.class.isAssignableFrom(property.getType())) {
210                 jdoField.findCreate(EXTERNALIZER, "SERIALIZED", false);
211                 jdoField.defaultFetchGroup = MDStatics.TRUE;
212             } else if (java.sql.Blob JavaDoc.class.equals(property.getType())
213                     || java.sql.Clob JavaDoc.class.equals(property.getType())) {
214                 jdoField.defaultFetchGroup = MDStatics.FALSE;
215             }
216         }
217     }
218
219     private void processId(AccessibleMember property, JdoField jdoField, JdoClass jdoClass) {
220         /**
221          * TODO
222          * composite pk?
223          *
224          */

225         if (property.isAnnotationPresent(Id.class)) {
226             jdoField.primaryKey = true;
227
228             Id idAno = (Id) property.getAnnotation(Id.class);
229             //the current keygenExt as per jdo metadata
230
JdoExtension keygenExt = JdoExtension.find(JDBC_KEY_GENERATOR, jdoClass.elements);
231
232             String JavaDoc generator = idAno.generator();
233             if (idAno.generate() == GeneratorType.NONE) {
234                 if (keygenExt != null) {
235                     //removing it by setting the key to -1
236
keygenExt.key = -1;
237                 }
238             } else if (idAno.generate() == GeneratorType.SEQUENCE ||
239                     idAno.generate() == GeneratorType.IDENTITY) {
240                 keygenExt = createKeyGen(jdoClass, keygenExt);
241                 keygenExt.value = "AUTOINC";
242                 if (generator != null && generator.length() > 0) {
243                     keygenExt.value = generator;
244                 }
245             } else if (idAno.generate() == GeneratorType.AUTO) {
246                 throw new RuntimeException JavaDoc("NotImplemented");
247             } else if (idAno.generate() == GeneratorType.TABLE) {
248                 keygenExt = createKeyGen(jdoClass, keygenExt);
249                 if (generator != null && generator.length() > 0) {
250                     keygenExt.value = generator;
251                 } else {
252                     throw new RuntimeException JavaDoc("Must ' '" + idAno.generate() + "'");
253                 }
254             } else {
255                 throw new RuntimeException JavaDoc("Unsupported GeneratorType '" + idAno.generate() + "'");
256             }
257         }
258     }
259
260     private JdoField getJdoField(Map JavaDoc jdoFieldMap, Member field, JdoClass jdoClass) {
261         JdoField jdoField = (JdoField)jdoFieldMap.get(field.getName());
262         if (jdoField == null) {
263             jdoField = new JdoField();
264             jdoField.name = field.getName();
265             jdoField.parent = jdoClass;
266             jdoClass.addElement(jdoField);
267             jdoFieldMap.put(jdoField.name, jdoField);
268         }
269         return jdoField;
270     }
271
272     private Map JavaDoc createFieldMap(JdoClass jdoClass) {
273         Map JavaDoc jdoFieldMap = new HashMap JavaDoc();
274         if (jdoClass.elements != null) {
275             JdoElement[] elements = jdoClass.elements;
276             for (int i = 0; i < elements.length; i++) {
277                 JdoElement element = elements[i];
278                 if (element instanceof JdoField) {
279                     jdoFieldMap.put(((JdoField)element).name, element);
280                 }
281             }
282         }
283         return jdoFieldMap;
284     }
285
286     private boolean isValid(String JavaDoc value) {
287         if (value == null || value.length() == 0) return false;
288         return true;
289     }
290
291     private void setCascadeType(CascadeType[] cct, JdoField jdoField) {
292         for (int j = 0; j < cct.length; j++) {
293             CascadeType cascadeType = cct[j];
294             switch (cascadeType) {
295                 case ALL:
296                     jdoField.cascadeType = MDStatics.CASCADE_ALL;
297                     break;
298                 case MERGE:
299                     jdoField.cascadeType += MDStatics.CASCADE_MERGE;
300                     break;
301                 case PERSIST:
302                     jdoField.cascadeType += MDStatics.CASCADE_PERSIST;
303                     break;
304                 case REFRESH:
305                     jdoField.cascadeType += MDStatics.CASCADE_REFRESH;
306                     break;
307                 case REMOVE:
308                     jdoField.cascadeType += MDStatics.CASCADE_REMOVE;
309                     break;
310                 default:
311                     throw BindingSupportImpl.getInstance().internal("unhandled CascadeType '" + cascadeType + "'");
312             }
313         }
314     }
315
316     private JdoExtension createKeyGen(JdoClass jdoCls, JdoExtension keygenExt) {
317         if (keygenExt == null) {
318             keygenExt = new JdoExtension();
319             keygenExt.key = JDBC_KEY_GENERATOR;
320             jdoCls.addElement(keygenExt);
321         }
322         return keygenExt;
323     }
324
325     private void doPCSuperClass(JdoClass jdoClass, Class JavaDoc subClass) {
326         Class JavaDoc superClass = subClass.getSuperclass();
327         if (superClass == null) return;
328
329         String JavaDoc superClassName = jdoClass.getPCSuperClassQName();
330         if (superClassName == null && superClass.isAnnotationPresent(javax.persistence.Entity.class)) {
331             jdoClass.pcSuperclass = superClass.getName();
332         }
333     }
334
335     /**
336      * Load class name using our loader.
337      */

338     private Class JavaDoc loadClass(String JavaDoc name) throws ClassNotFoundException JavaDoc {
339         return ClassHelper.get().classForName(name, false, loader);
340     }
341
342     /**
343      * Structure to provide info for a field and/or method.
344      */

345     private class AccessibleMember extends AccessibleObject implements Member {
346         private Field field;
347         private Method method;
348
349         public void init(Field field, Method method) {
350             this.field = field;
351             this.method = method;
352         }
353
354         public Class JavaDoc getDeclaringClass() {
355             return field.getDeclaringClass();
356         }
357
358         public int getModifiers() {
359             return field.getModifiers();
360         }
361
362         public String JavaDoc getName() {
363             return field.getName();
364         }
365
366         public boolean isSynthetic() {
367             return field.isSynthetic();
368         }
369
370         public <T extends Annotation JavaDoc> T getAnnotation(Class JavaDoc<T> annotationClass) {
371             if (method == null) {
372                 return field.getAnnotation(annotationClass);
373             } else {
374                 return method.getAnnotation(annotationClass);
375             }
376         }
377
378         public Annotation JavaDoc[] getAnnotations() {
379             if (method == null) {
380                 return field.getAnnotations();
381             } else {
382                 return method.getAnnotations();
383             }
384         }
385
386         public Annotation JavaDoc[] getDeclaredAnnotations() {
387             if (method == null) {
388                 return field.getDeclaredAnnotations();
389             } else {
390                 return method.getDeclaredAnnotations();
391             }
392         }
393
394
395         public boolean isAccessible() {
396             if (method == null) {
397                 return field.isAccessible();
398             } else {
399                 return method.isAccessible();
400             }
401         }
402
403         public boolean isAnnotationPresent(Class JavaDoc<? extends Annotation JavaDoc> annotationClass) {
404             if (method == null) {
405                 return field.isAnnotationPresent(annotationClass);
406             } else {
407                 return method.isAnnotationPresent(annotationClass);
408             }
409         }
410
411         public void setAccessible(boolean flag) throws SecurityException JavaDoc {
412             if (method == null) {
413                 field.setAccessible(flag);
414             } else {
415                 method.setAccessible(flag);
416             }
417         }
418
419         public Class JavaDoc getType() {
420             return field.getType();
421         }
422
423     }
424 }
425
Popular Tags