KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > caucho > amber > cfg > EntityIntrospector


1 /*
2  * Copyright (c) 1998-2006 Caucho Technology -- all rights reserved
3  *
4  * This file is part of Resin(R) Open Source
5  *
6  * Each copy or derived work must preserve the copyright notice and this
7  * notice unmodified.
8  *
9  * Resin Open Source is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * Resin Open Source is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
17  * of NON-INFRINGEMENT. See the GNU General Public License for more
18  * details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with Resin Open Source; if not, write to the
22  *
23  * Free Software Foundation, Inc.
24  * 59 Temple Place, Suite 330
25  * Boston, MA 02111-1307 USA
26  *
27  * @author Scott Ferguson
28  */

29
30 package com.caucho.amber.cfg;
31
32 import com.caucho.amber.AmberTableCache;
33 import com.caucho.amber.field.AmberField;
34 import com.caucho.amber.field.Id;
35 import com.caucho.amber.field.IdField;
36 import com.caucho.amber.field.KeyPropertyField;
37 import com.caucho.amber.field.PropertyField;
38 import com.caucho.amber.manager.AmberPersistenceUnit;
39 import com.caucho.amber.table.Column;
40 import com.caucho.amber.table.Table;
41 import com.caucho.amber.type.EntityType;
42 import com.caucho.amber.type.Type;
43 import com.caucho.bytecode.JAnnotation;
44 import com.caucho.bytecode.JClass;
45 import com.caucho.bytecode.JMethod;
46 import com.caucho.config.ConfigException;
47 import com.caucho.config.types.Period;
48 import com.caucho.util.L10N;
49
50 import javax.persistence.AttributeOverrides;
51 import javax.persistence.InheritanceType;
52 import javax.persistence.MappedSuperclass;
53 import java.sql.SQLException JavaDoc;
54 import java.util.ArrayList JavaDoc;
55 import java.util.HashMap JavaDoc;
56 import java.util.logging.Logger JavaDoc;
57
58 /**
59  * Configuration for an entity bean
60  */

61 public class EntityIntrospector extends BaseConfigIntrospector {
62   private static final L10N L = new L10N(EntityIntrospector.class);
63   private static final Logger JavaDoc log
64     = Logger.getLogger(EntityIntrospector.class.getName());
65
66   HashMap JavaDoc<String JavaDoc, EntityType> _entityMap
67     = new HashMap JavaDoc<String JavaDoc, EntityType>();
68
69   /**
70    * Creates the introspector.
71    */

72   public EntityIntrospector(AmberPersistenceUnit persistenceUnit)
73   {
74     super(persistenceUnit);
75   }
76
77   /**
78    * Returns true for entity type.
79    */

80   public boolean isEntity(JClass type)
81   {
82     getInternalEntityConfig(type);
83     JAnnotation entityAnn = _annotationCfg.getAnnotation();
84     EntityConfig entityConfig = _annotationCfg.getEntityConfig();
85
86     return (! _annotationCfg.isNull());
87   }
88
89   /**
90    * Introspects.
91    */

92   public EntityType introspect(JClass type)
93     throws ConfigException, SQLException JavaDoc
94   {
95     EntityType entityType = null;
96
97     try {
98       getInternalEntityConfig(type);
99       JAnnotation entityAnn = _annotationCfg.getAnnotation();
100       EntityConfig entityConfig = _annotationCfg.getEntityConfig();
101
102       boolean isEntity = ! _annotationCfg.isNull();
103
104       String JavaDoc typeName;
105
106       if (isEntity) {
107         if (entityConfig != null)
108           typeName = entityConfig.getClassName();
109         else
110           typeName = entityAnn.getString("name");
111       }
112       else {
113         getInternalMappedSuperclassConfig(type);
114         JAnnotation mappedSuperAnn = _annotationCfg.getAnnotation();
115         MappedSuperclassConfig mappedSuperConfig = _annotationCfg.getMappedSuperclassConfig();
116
117         boolean isMappedSuperclass = ! _annotationCfg.isNull();
118
119         if (isMappedSuperclass) {
120           if (mappedSuperConfig != null)
121             typeName = mappedSuperConfig.getClassName();
122           else
123             typeName = mappedSuperAnn.getString("name");
124         }
125         else
126           throw new ConfigException(L.l("'{0}' is not an @Entity or @MappedSuperclass.",
127                                         type));
128       }
129
130       // Adds named queries, if any.
131
introspectNamedQueries(type, typeName);
132       introspectNamedNativeQueries(type, typeName);
133
134       // Validates the type
135
String JavaDoc entityName;
136       EntityType parentType = null;
137       JAnnotation inheritanceAnn = null;
138       InheritanceConfig inheritanceConfig = null;
139       JClass rootClass = type;
140       JAnnotation rootEntityAnn = null;
141       EntityConfig rootEntityConfig = null;
142
143       if (isEntity) {
144         validateType(type);
145
146         // Inheritance annotation/configuration is specified
147
// on the entity class that is the root of the entity
148
// class hierarachy.
149

150         getInternalInheritanceConfig(type);
151         inheritanceAnn = _annotationCfg.getAnnotation();
152         inheritanceConfig = _annotationCfg.getInheritanceConfig();
153
154         boolean hasInheritance = ! _annotationCfg.isNull();
155
156         for (JClass parentClass = type.getSuperClass();
157              parentClass != null;
158              parentClass = parentClass.getSuperClass()) {
159
160           getInternalEntityConfig(parentClass);
161
162           if (_annotationCfg.isNull())
163             break;
164
165           rootEntityAnn = _annotationCfg.getAnnotation();
166           rootEntityConfig = _annotationCfg.getEntityConfig();
167
168           rootClass = parentClass;
169
170           if (hasInheritance)
171             throw new ConfigException(L.l("'{0}' cannot have @Inheritance. It must be specified on the entity class that is the root of the entity class hierarchy.",
172                                           type));
173
174           getInternalInheritanceConfig(rootClass);
175           inheritanceAnn = _annotationCfg.getAnnotation();
176           inheritanceConfig = _annotationCfg.getInheritanceConfig();
177
178           hasInheritance = ! _annotationCfg.isNull();
179         }
180
181         if (hasInheritance) {
182
183           for (JClass parentClass = type.getSuperClass();
184                parentClass != null;
185                parentClass = parentClass.getSuperClass()) {
186
187             getInternalEntityConfig(parentClass);
188             JAnnotation parentEntity = _annotationCfg.getAnnotation();
189             EntityConfig superEntityConfig = _annotationCfg.getEntityConfig();
190
191             if (! _annotationCfg.isNull()) {
192               parentType = introspect(parentClass);
193               break;
194             }
195
196             // getInternalMappedSuperclassConfig(parentClass);
197
// JAnnotation superclassAnn = _annotationCfg.getAnnotation();
198
// EntityConfig superclassConfig = _annotationCfg.getMappedSuperclassConfig();
199
//
200
// if (! _annotationCfg.isNull()) {
201
// parentType = introspect(parentClass);
202
// break;
203
// }
204
}
205         }
206
207         if (entityAnn != null)
208           entityName = entityAnn.getString("name");
209         else {
210           entityName = entityConfig.getClassName();
211
212           int p = entityName.lastIndexOf('.');
213
214           if (p > 0)
215             entityName = entityName.substring(p + 1);
216         }
217       }
218       else {
219         entityName = type.getName();
220       }
221
222       if (entityName.equals("")) {
223         entityName = type.getName();
224         int p = entityName.lastIndexOf('.');
225         if (p > 0)
226           entityName = entityName.substring(p + 1);
227       }
228
229       entityType = _entityMap.get(entityName);
230
231       if (entityType != null)
232         return entityType;
233
234       entityType = _persistenceUnit.createEntity(entityName, type);
235       _entityMap.put(entityName, entityType);
236
237       // Adds entity listeners, if any.
238
introspectEntityListeners(type, entityType, _persistenceUnit);
239
240       // Adds sql result set mappings, if any.
241
introspectSqlResultSetMappings(type, entityType, typeName);
242
243       boolean isField = isField(type, entityConfig, false);
244
245       if (isField)
246         entityType.setFieldAccess(true);
247
248       entityType.setInstanceClassName(type.getName() + "__ResinExt");
249       entityType.setEnhanced(true);
250
251       Table table = null;
252
253       getInternalTableConfig(type);
254       JAnnotation tableAnn = _annotationCfg.getAnnotation();
255       TableConfig tableConfig = _annotationCfg.getTableConfig();
256
257       String JavaDoc tableName = null;
258
259       if (tableAnn != null)
260         tableName = (String JavaDoc) tableAnn.get("name");
261       else if (tableConfig != null)
262         tableName = tableConfig.getName();
263
264       if (tableName == null || tableName.equals(""))
265         tableName = entityName.toUpperCase();
266
267       if (isEntity) {
268
269         InheritanceType strategy = null;
270
271         if (inheritanceAnn != null)
272           strategy = (InheritanceType) inheritanceAnn.get("strategy");
273         else if (inheritanceConfig != null)
274           strategy = inheritanceConfig.getStrategy();
275
276         if (parentType == null)
277           entityType.setTable(_persistenceUnit.createTable(tableName));
278         else if (strategy == InheritanceType.JOINED) {
279           entityType.setTable(_persistenceUnit.createTable(tableName));
280
281           getInternalTableConfig(rootClass);
282           JAnnotation rootTableAnn = _annotationCfg.getAnnotation();
283           TableConfig rootTableConfig = _annotationCfg.getTableConfig();
284
285           String JavaDoc rootTableName = null;
286
287           if (rootTableAnn != null)
288             rootTableName = (String JavaDoc) rootTableAnn.get("name");
289           else if (rootTableConfig != null)
290             rootTableName = rootTableConfig.getName();
291
292           if (rootTableName == null || rootTableName.equals("")) {
293
294             String JavaDoc rootEntityName;
295
296             if (rootEntityAnn != null)
297               rootEntityName = rootEntityAnn.getString("name");
298             else {
299               rootEntityName = rootEntityConfig.getClassName();
300
301               int p = rootEntityName.lastIndexOf('.');
302
303               if (p > 0)
304                 rootEntityName = rootEntityName.substring(p + 1);
305             }
306
307             if (rootEntityName.equals("")) {
308               rootEntityName = rootClass.getName();
309
310               int p = rootEntityName.lastIndexOf('.');
311
312               if (p > 0)
313                 rootEntityName = rootEntityName.substring(p + 1);
314             }
315
316             rootTableName = rootEntityName.toUpperCase();
317           }
318
319           entityType.setRootTableName(rootTableName);
320         }
321         else
322           entityType.setTable(parentType.getTable());
323       }
324
325       JAnnotation tableCache = type.getAnnotation(AmberTableCache.class);
326
327       if (tableCache != null) {
328         entityType.getTable().setReadOnly(tableCache.getBoolean("readOnly"));
329
330         long cacheTimeout = Period.toPeriod(tableCache.getString("timeout"));
331         entityType.getTable().setCacheTimeout(cacheTimeout);
332       }
333
334       getInternalSecondaryTableConfig(type);
335       JAnnotation secondaryTableAnn = _annotationCfg.getAnnotation();
336       SecondaryTableConfig secondaryTableConfig = _annotationCfg.getSecondaryTableConfig();
337
338       Table secondaryTable = null;
339
340       if ((inheritanceAnn != null) || (inheritanceConfig != null))
341         introspectInheritance(_persistenceUnit, entityType, type,
342                               inheritanceAnn, inheritanceConfig);
343
344       if ((secondaryTableAnn != null) || (secondaryTableConfig != null)) {
345         String JavaDoc secondaryName;
346
347         if (secondaryTableAnn != null)
348           secondaryName = secondaryTableAnn.getString("name");
349         else
350           secondaryName = secondaryTableConfig.getName();
351
352         secondaryTable = _persistenceUnit.createTable(secondaryName);
353
354         entityType.addSecondaryTable(secondaryTable);
355
356         // XXX: pk
357
}
358
359       getInternalIdClassConfig(type);
360       JAnnotation idClassAnn = _annotationCfg.getAnnotation();
361       IdClassConfig idClassConfig = _annotationCfg.getIdClassConfig();
362
363       JClass idClass = null;
364       if (! _annotationCfg.isNull()) {
365
366         if (idClassAnn != null)
367           idClass = idClassAnn.getClass("value");
368         else {
369           String JavaDoc s = idClassConfig.getClassName();
370           idClass = _persistenceUnit.getJClassLoader().forName(s);
371         }
372
373         // XXX: temp. introspects idClass as an embeddable type.
374
_persistenceUnit.getEmbeddableIntrospector().introspect(idClass);
375       }
376
377       if (entityType.getId() != null) {
378       }
379       else if (isField)
380         introspectIdField(_persistenceUnit, entityType, parentType,
381                           type, idClass, entityConfig);
382       else
383         introspectIdMethod(_persistenceUnit, entityType, parentType,
384                            type, idClass, entityConfig);
385
386       HashMap JavaDoc<String JavaDoc, IdConfig> idMap = null;
387
388       AttributesConfig attributes = null;
389
390       if (entityConfig != null) {
391         attributes = entityConfig.getAttributes();
392
393         if (attributes != null)
394           idMap = attributes.getIdMap();
395       }
396
397       // if ((idMap == null) || (idMap.size() == 0)) {
398
// idMap = entityType.getSuperClass();
399
// }
400

401       if (isEntity && (entityType.getId() == null) && ((idMap == null) || (idMap.size() == 0)))
402         throw new ConfigException(L.l("{0} does not have any primary keys. Entities must have at least one @Id or exactly one @EmbeddedId field.",
403                                       entityType.getName()));
404
405       // Introspect overridden attributes. (jpa/0ge2)
406
introspectAttributeOverrides(type, entityType);
407
408       if (isField)
409         introspectFields(_persistenceUnit, entityType, parentType, type, entityConfig, false);
410       else
411         introspectMethods(_persistenceUnit, entityType, parentType, type, entityConfig);
412
413       if (isEntity) {
414         introspectCallbacks(type, entityType);
415
416         if (secondaryTableAnn != null) {
417           Object JavaDoc []join = (Object JavaDoc []) secondaryTableAnn.get("pkJoinColumns");
418
419           JAnnotation []joinAnn = null;
420
421           if (join != null) {
422             joinAnn = new JAnnotation[join.length];
423             System.arraycopy(join, 0, joinAnn, 0, join.length);
424           }
425
426           linkSecondaryTable(entityType.getTable(),
427                              secondaryTable,
428                              joinAnn);
429         }
430       }
431     } catch (ConfigException e) {
432       if (entityType != null)
433         entityType.setConfigException(e);
434
435       throw e;
436     } catch (SQLException JavaDoc e) {
437       if (entityType != null)
438         entityType.setConfigException(e);
439
440       throw e;
441     } catch (RuntimeException JavaDoc e) {
442       if (entityType != null)
443         entityType.setConfigException(e);
444
445       throw e;
446     }
447
448     return entityType;
449   }
450
451   private void introspectAttributeOverrides(JClass type,
452                                             EntityType entityType)
453   {
454     getInternalAttributeOverrideConfig(type);
455     JAnnotation attributeOverrideAnn = _annotationCfg.getAnnotation();
456     AttributeOverrideConfig attributeOverrideConfig
457       = _annotationCfg.getAttributeOverrideConfig();
458
459     boolean hasAttributeOverride = ! _annotationCfg.isNull();
460
461     JAnnotation attributeOverridesAnn = type.getAnnotation(AttributeOverrides.class);
462
463     boolean hasAttributeOverrides = (attributeOverridesAnn != null);
464
465     if (hasAttributeOverride && hasAttributeOverrides)
466       throw new ConfigException(L.l("{0} may not have both @AttributeOverride and @AttributeOverrides",
467                                     type));
468
469     Object JavaDoc attOverridesAnn[] = null;
470
471     if (attributeOverrideAnn != null) {
472       attOverridesAnn = new Object JavaDoc[] { attributeOverrideAnn };
473     }
474     else if (attributeOverridesAnn != null) {
475       attOverridesAnn = (Object JavaDoc []) attributeOverridesAnn.get("value");
476     }
477     else
478       return;
479
480     Table sourceTable = entityType.getTable();
481
482     for (int j=0; j < attOverridesAnn.length; j++) {
483
484       JAnnotation attOverrideAnn = (JAnnotation) attOverridesAnn[j];
485
486       String JavaDoc entityFieldName;
487       String JavaDoc columnName;
488       boolean notNull = false;
489       boolean unique = false;
490
491       Type amberType = null;
492
493       ArrayList JavaDoc<AmberField> fields = entityType.getFields();
494
495       for (int i=0; i < fields.size(); i++) {
496
497         AmberField field = fields.get(i);
498
499         // XXX: needs to handle @AttributeOverrides with
500
// fields other than PropertyField's.
501
if (! (field instanceof PropertyField))
502           continue;
503
504         entityFieldName = field.getName();
505
506         columnName = toSqlName(entityFieldName);
507
508         if (entityFieldName.equals(attOverrideAnn.getString("name"))) {
509
510           JAnnotation columnAnn = attOverrideAnn.getAnnotation("column");
511
512           if (columnAnn != null) {
513             columnName = columnAnn.getString("name");
514             notNull = ! columnAnn.getBoolean("nullable");
515             unique = columnAnn.getBoolean("unique");
516             amberType = _persistenceUnit.createType(field.getJavaType().getName());
517
518             Column column = sourceTable.createColumn(columnName, amberType);
519
520             column.setNotNull(notNull);
521             column.setUnique(unique);
522
523             ((PropertyField) field).setColumn(column);
524           }
525         }
526       }
527
528       if (entityType.getId() != null) {
529         ArrayList JavaDoc<IdField> keys = entityType.getId().getKeys();
530
531         for (int i=0; i < keys.size(); i++) {
532
533           IdField field = keys.get(i);
534
535           entityFieldName = field.getName();
536
537           columnName = toSqlName(entityFieldName);
538
539           if (entityFieldName.equals(attOverrideAnn.getString("name"))) {
540
541             JAnnotation columnAnn = attOverrideAnn.getAnnotation("column");
542
543             if (columnAnn != null) {
544               columnName = columnAnn.getString("name");
545               notNull = ! columnAnn.getBoolean("nullable");
546               unique = columnAnn.getBoolean("unique");
547               amberType = _persistenceUnit.createType(field.getJavaType().getName());
548
549               Column column = sourceTable.createColumn(columnName, amberType);
550
551               column.setNotNull(notNull);
552               column.setUnique(unique);
553
554               ArrayList JavaDoc<Column> columns = field.getColumns();
555
556               if (field instanceof KeyPropertyField) {
557                 if (columns.size() > 0) {
558                   sourceTable.removeColumn(columns.get(0));
559                   columns.remove(0);
560                 }
561
562                 columns.add(column);
563
564                 ((KeyPropertyField) field).setColumn(column);
565               }
566             }
567           }
568         }
569       }
570     }
571   }
572 }
573
Popular Tags