KickJava   Java API By Example, From Geeks To Geeks.

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


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 Rodrigo Westrupp
28  */

29
30 package com.caucho.amber.cfg;
31
32 import com.caucho.amber.entity.Listener;
33
34 import com.caucho.amber.field.*;
35 import com.caucho.amber.idgen.IdGenerator;
36 import com.caucho.amber.manager.AmberPersistenceUnit;
37 import com.caucho.amber.table.Column;
38 import com.caucho.amber.table.ForeignColumn;
39 import com.caucho.amber.table.LinkColumns;
40 import com.caucho.amber.table.Table;
41 import com.caucho.amber.type.*;
42 import com.caucho.bytecode.*;
43 import com.caucho.config.ConfigException;
44 import com.caucho.jdbc.JdbcMetaData;
45 import com.caucho.util.L10N;
46
47 import javax.persistence.*;
48 import java.sql.SQLException JavaDoc;
49 import java.util.ArrayList JavaDoc;
50 import java.util.HashMap JavaDoc;
51 import java.util.logging.Level JavaDoc;
52 import java.util.logging.Logger JavaDoc;
53
54
55 /**
56  * Base concrete introspector for orm.xml and annotations.
57  */

58 public class BaseConfigIntrospector extends AbstractConfigIntrospector {
59   private static final Logger JavaDoc log
60     = Logger.getLogger(BaseConfigIntrospector.class.getName());
61   private static final L10N L = new L10N(BaseConfigIntrospector.class);
62
63   AmberPersistenceUnit _persistenceUnit;
64
65   ArrayList JavaDoc<Completion> _linkCompletions = new ArrayList JavaDoc<Completion>();
66   ArrayList JavaDoc<Completion> _depCompletions = new ArrayList JavaDoc<Completion>();
67
68   HashMap JavaDoc<RelatedType, ArrayList JavaDoc<OneToOneCompletion>> _oneToOneCompletions
69     = new HashMap JavaDoc<RelatedType, ArrayList JavaDoc<OneToOneCompletion>>();
70
71   HashMap JavaDoc<String JavaDoc, EmbeddableConfig> _embeddableConfigMap
72     = new HashMap JavaDoc<String JavaDoc, EmbeddableConfig>();
73
74   HashMap JavaDoc<String JavaDoc, EntityConfig> _entityConfigMap
75     = new HashMap JavaDoc<String JavaDoc, EntityConfig>();
76
77   HashMap JavaDoc<String JavaDoc, MappedSuperclassConfig> _mappedSuperclassConfigMap
78     = new HashMap JavaDoc<String JavaDoc, MappedSuperclassConfig>();
79
80   /**
81    * Creates the introspector.
82    */

83   public BaseConfigIntrospector()
84   {
85   }
86
87   /**
88    * Creates the introspector.
89    */

90   public BaseConfigIntrospector(AmberPersistenceUnit persistenceUnit)
91   {
92     _persistenceUnit = persistenceUnit;
93   }
94
95   /**
96    * Sets the entity config map.
97    */

98   public void setEntityConfigMap(HashMap JavaDoc<String JavaDoc, EntityConfig> entityConfigMap)
99   {
100     _entityConfigMap = entityConfigMap;
101   }
102
103   /**
104    * Sets the mapped superclass config map.
105    */

106   public void setMappedSuperclassConfigMap(HashMap JavaDoc<String JavaDoc, MappedSuperclassConfig>
107                                            mappedSuperclassConfigMap)
108   {
109     _mappedSuperclassConfigMap = mappedSuperclassConfigMap;
110   }
111
112   /**
113    * Initializes the persistence unit meta data:
114    * default listeners and so on.
115    */

116   public void initMetaData(EntityMappingsConfig entityMappings,
117                            AmberPersistenceUnit persistenceUnit)
118     throws ConfigException
119   {
120     PersistenceUnitMetaDataConfig metaData;
121     metaData = entityMappings.getPersistenceUnitMetaData();
122
123     if (metaData == null)
124       return;
125
126     PersistenceUnitDefaultsConfig defaults;
127
128     defaults = metaData.getPersistenceUnitDefaults();
129
130     if (defaults == null)
131       return;
132
133     EntityListenersConfig entityListeners;
134     entityListeners = defaults.getEntityListeners();
135
136     if (entityListeners == null)
137       return;
138
139     ArrayList JavaDoc<EntityListenerConfig> listeners;
140     listeners = entityListeners.getEntityListeners();
141
142     for (EntityListenerConfig listener : listeners)
143       introspectDefaultListener(listener, persistenceUnit);
144   }
145
146   public void introspectDefaultListener(EntityListenerConfig listener,
147                                         AmberPersistenceUnit persistenceUnit)
148     throws ConfigException
149   {
150     JClassLoader loader = persistenceUnit.getJClassLoader();
151
152     String JavaDoc className = listener.getClassName();
153
154     JClass type = loader.forName(className);
155
156     if (type == null)
157       throw new ConfigException(L.l("'{0}' is an unknown type for <entity-listener> in orm.xml",
158                                     className));
159
160     ListenerType listenerType = persistenceUnit.addDefaultListener(type);
161
162     introspectListener(type, listenerType);
163   }
164
165   public void introspectEntityListeners(JClass type,
166                                         RelatedType relatedType,
167                                         AmberPersistenceUnit persistenceUnit)
168     throws ConfigException
169   {
170     getInternalEntityListenersConfig(type);
171     JAnnotation entityListenersAnn = _annotationCfg.getAnnotation();
172     EntityListenersConfig entityListenersCfg
173       = _annotationCfg.getEntityListenersConfig();
174
175     Object JavaDoc listeners[] = null;
176
177     // XML mapping takes higher priority than annotations.
178
if (entityListenersCfg != null)
179       listeners = entityListenersCfg.getEntityListeners().toArray();
180     else if (entityListenersAnn != null)
181       listeners = (Object JavaDoc []) entityListenersAnn.get("value");
182     else
183       return;
184
185     String JavaDoc relatedTypeName = relatedType.getBeanClass().getName();
186
187     for (int i=0; i < listeners.length; i++) {
188
189       JClass cl;
190
191       // Introspects annotation or xml.
192
if (listeners[i] instanceof JClass)
193         cl = (JClass) listeners[i];
194       else {
195         JClassLoader loader = persistenceUnit.getJClassLoader();
196
197         EntityListenerConfig listenerConfig
198           = (EntityListenerConfig) listeners[i];
199
200         String JavaDoc className = listenerConfig.getClassName();
201
202         cl = loader.forName(className);
203
204         if (cl == null)
205           throw new ConfigException(L.l("'{0}' is an unknown type for <entity-listener> in orm.xml",
206                                         className));
207       }
208
209       if (persistenceUnit.getDefaultListener(cl.getName()) != null)
210         continue;
211
212       introspectEntityListener(cl,
213                                persistenceUnit,
214                                relatedType,
215                                relatedTypeName);
216     }
217   }
218
219   public void introspectEntityListener(JClass type,
220                                        AmberPersistenceUnit persistenceUnit,
221                                        RelatedType sourceType,
222                                        String JavaDoc sourceClassName)
223     throws ConfigException
224   {
225     if (type == null) {
226       throw new ConfigException(L.l("'{0}' is an unknown type for @EntityListeners annotated at class '{1}'",
227                                     type.getName(),
228                                     sourceClassName));
229     }
230
231     JClass parentClass = type.getSuperClass();
232
233     if (parentClass == null) {
234       // java.lang.Object
235
return;
236     }
237     else {
238       // XXX: entity listener super-classes in a hierarchy might
239
// not be annotated as entity listeners but they might have
240
// @PreXxx or @PostXxx annotated methods. On the other hand,
241
// needs to filter regular classes out.
242

243       introspectEntityListener(parentClass, persistenceUnit,
244                                sourceType, sourceClassName);
245     }
246
247     // jpa/0r42
248

249     ListenerType listenerType
250       = persistenceUnit.getEntityListener(type.getName());
251
252     ListenerType newListenerType
253       = persistenceUnit.addEntityListener(sourceClassName, type);
254
255     if (listenerType == null) {
256       listenerType = newListenerType;
257       introspectListener(type, listenerType);
258     }
259
260     sourceType.addListener(listenerType);
261   }
262
263   public void introspectListener(JClass type,
264                                  ListenerType listenerType)
265     throws ConfigException
266   {
267     listenerType.setInstanceClassName(listenerType.getName() + "__ResinExt");
268
269     for (JMethod method : type.getMethods()) {
270       introspectCallbacks(listenerType, method);
271     }
272   }
273
274   /**
275    * Introspects the callbacks.
276    */

277   public void introspectCallbacks(JClass type,
278                                   EntityType entityType)
279     throws ConfigException
280   {
281     getInternalExcludeDefaultListenersConfig(type);
282
283     if (! _annotationCfg.isNull())
284       entityType.setExcludeDefaultListeners(true);
285
286     getInternalExcludeSuperclassListenersConfig(type);
287
288     if (! _annotationCfg.isNull())
289       entityType.setExcludeSuperclassListeners(true);
290
291     for (JMethod method : type.getMethods()) {
292       introspectCallbacks(entityType, method);
293     }
294   }
295
296   /**
297    * Introspects the callbacks.
298    */

299   public void introspectCallbacks(AbstractEnhancedType type,
300                                   JMethod method)
301     throws ConfigException
302   {
303     JClass []param = method.getParameterTypes();
304
305     String JavaDoc methodName = method.getName();
306     JClass jClass = type.getBeanClass();
307
308     boolean isListener = type instanceof ListenerType;
309
310     int n = ListenerType.CALLBACK_CLASS.length;
311
312     for (int i=1; i < n; i++) {
313       getInternalCallbackConfig(i, jClass, method, methodName);
314
315       if (! _annotationCfg.isNull()) {
316         validateCallback(ListenerType.CALLBACK_CLASS[i].getName(),
317                          method, isListener);
318
319         type.addCallback(i, method);
320       }
321     }
322   }
323
324   /**
325    * Introspects named queries.
326    */

327   void introspectNamedQueries(JClass type, String JavaDoc typeName)
328   {
329     // jpa/0y0-
330

331     getInternalNamedQueryConfig(type);
332     JAnnotation namedQueryAnn = _annotationCfg.getAnnotation();
333     NamedQueryConfig namedQueryConfig = _annotationCfg.getNamedQueryConfig();
334
335     // getInternalNamedQueriesConfig(type);
336
JAnnotation namedQueriesAnn = type.getAnnotation(NamedQueries.class);
337     // NamedQueriesConfig namedQueriesConfig = _annotationCfg.getNamedQueriesConfig();
338

339     if ((namedQueryAnn == null) && (namedQueriesAnn == null))
340       return;
341
342     Object JavaDoc namedQueryArray[];
343
344     if ((namedQueryAnn != null) && (namedQueriesAnn != null)) {
345       throw new ConfigException(L.l("{0} may not have both @NamedQuery and @NamedQueries",
346                                     typeName));
347     }
348     else if (namedQueriesAnn != null) {
349       namedQueryArray = (Object JavaDoc []) namedQueriesAnn.get("value");
350     }
351     else {
352       namedQueryArray = new Object JavaDoc[] { namedQueryAnn };
353     }
354
355     for (int i=0; i < namedQueryArray.length; i++) {
356       namedQueryAnn = (JAnnotation) namedQueryArray[i];
357       _persistenceUnit.addNamedQuery(namedQueryAnn.getString("name"),
358                                      namedQueryAnn.getString("query"));
359     }
360   }
361
362   /**
363    * Introspects named native queries.
364    */

365   void introspectNamedNativeQueries(JClass type, String JavaDoc typeName)
366   {
367     // jpa/0y2-
368

369     getInternalNamedNativeQueryConfig(type);
370     JAnnotation namedNativeQueryAnn = _annotationCfg.getAnnotation();
371     NamedNativeQueryConfig namedNativeQueryConfig = _annotationCfg.getNamedNativeQueryConfig();
372
373     JAnnotation namedNativeQueriesAnn = type.getAnnotation(NamedNativeQueries.class);
374
375     if ((namedNativeQueryAnn == null) && (namedNativeQueriesAnn == null))
376       return;
377
378     Object JavaDoc namedNativeQueryArray[];
379
380     if ((namedNativeQueryAnn != null) && (namedNativeQueriesAnn != null)) {
381       throw new ConfigException(L.l("{0} may not have both @NamedNativeQuery and @NamedNativeQueries",
382                                     typeName));
383     }
384     else if (namedNativeQueriesAnn != null) {
385       namedNativeQueryArray = (Object JavaDoc []) namedNativeQueriesAnn.get("value");
386     }
387     else {
388       namedNativeQueryArray = new Object JavaDoc[] { namedNativeQueryAnn };
389     }
390
391     for (int i=0; i < namedNativeQueryArray.length; i++) {
392       namedNativeQueryAnn = (JAnnotation) namedNativeQueryArray[i];
393
394       NamedNativeQueryConfig nativeQueryConfig = new NamedNativeQueryConfig();
395
396       nativeQueryConfig.setQuery(namedNativeQueryAnn.getString("query"));
397       nativeQueryConfig.setResultClass(namedNativeQueryAnn.getClass("resultClass").getName());
398       nativeQueryConfig.setResultSetMapping(namedNativeQueryAnn.getString("resultSetMapping"));
399
400       _persistenceUnit.addNamedNativeQuery(namedNativeQueryAnn.getString("name"),
401                                            nativeQueryConfig);
402     }
403   }
404
405   /**
406    * Introspects sql result set mappings.
407    */

408   void introspectSqlResultSetMappings(JClass type,
409                                       RelatedType relatedType,
410                                       String JavaDoc typeName)
411   {
412     // jpa/0y1-
413

414     getInternalSqlResultSetMappingConfig(type);
415     JAnnotation sqlResultSetMappingAnn = _annotationCfg.getAnnotation();
416     SqlResultSetMappingConfig sqlResultSetMappingConfig
417       = _annotationCfg.getSqlResultSetMappingConfig();
418
419     JAnnotation sqlResultSetMappingsAnn = type.getAnnotation(SqlResultSetMappings.class);
420
421     if ((sqlResultSetMappingAnn == null) && (sqlResultSetMappingsAnn == null))
422       return;
423
424     Object JavaDoc sqlResultSetMappingArray[];
425
426     if ((sqlResultSetMappingAnn != null) && (sqlResultSetMappingsAnn != null)) {
427       throw new ConfigException(L.l("{0} may not have both @SqlResultSetMapping and @SqlResultSetMappings",
428                                     typeName));
429     }
430     else if (sqlResultSetMappingsAnn != null) {
431       sqlResultSetMappingArray = (Object JavaDoc []) sqlResultSetMappingsAnn.get("value");
432     }
433     else {
434       sqlResultSetMappingArray = new Object JavaDoc[] { sqlResultSetMappingAnn };
435     }
436
437     if (sqlResultSetMappingConfig != null) {
438       _persistenceUnit.addSqlResultSetMapping(sqlResultSetMappingConfig.getName(),
439                                               sqlResultSetMappingConfig);
440       return;
441     }
442
443     for (int i=0; i < sqlResultSetMappingArray.length; i++) {
444       sqlResultSetMappingAnn = (JAnnotation) sqlResultSetMappingArray[i];
445
446       String JavaDoc name = sqlResultSetMappingAnn.getString("name");
447       Object JavaDoc entities[] = (Object JavaDoc []) sqlResultSetMappingAnn.get("entities");
448       Object JavaDoc columns[] = (Object JavaDoc []) sqlResultSetMappingAnn.get("columns");
449
450       SqlResultSetMappingCompletion completion
451         = new SqlResultSetMappingCompletion(relatedType, name,
452                                             entities, columns);
453
454       _depCompletions.add(completion);
455     }
456   }
457
458   /**
459    * Completion callback for sql result set mappings.
460    */

461   void addSqlResultSetMapping(String JavaDoc resultSetName,
462                               Object JavaDoc entities[],
463                               Object JavaDoc columns[])
464     throws ConfigException
465   {
466     // jpa/0y1-
467

468     SqlResultSetMappingConfig sqlResultSetMapping
469       = new SqlResultSetMappingConfig();
470
471     // Adds @EntityResult.
472
for (int i=0; i < entities.length; i++) {
473       JAnnotation entityResult = (JAnnotation) entities[i];
474
475       String JavaDoc className = entityResult.getClass("entityClass").getName();
476
477       EntityType resultType = _persistenceUnit.getEntity(className);
478
479       if (resultType == null)
480         throw new ConfigException(L.l("entityClass '{0}' is not an @Entity bean for @SqlResultSetMapping '{1}'. The entityClass of an @EntityResult must be an @Entity bean.",
481                                       className,
482                                       resultSetName));
483
484       EntityResultConfig entityResultConfig = new EntityResultConfig();
485
486       entityResultConfig.setEntityClass(className);
487
488       // @FieldResult annotations.
489
Object JavaDoc fields[] = (Object JavaDoc []) entityResult.get("fields");
490
491       for (int j=0; j < fields.length; j++) {
492         JAnnotation fieldResult = (JAnnotation) fields[j];
493
494         String JavaDoc fieldName = fieldResult.getString("name");
495
496         AmberField field = resultType.getField(fieldName);
497
498         if (field == null)
499           throw new ConfigException(L.l("@FieldResult with field name '{0}' is not a field for @EntityResult bean '{1}' in @SqlResultSetMapping '{2}'",
500                                         fieldName,
501                                         className,
502                                         resultSetName));
503
504         String JavaDoc columnName = fieldResult.getString("column");
505
506         if (columnName == null || columnName.length() == 0)
507           throw new ConfigException(L.l("@FieldResult must have a column name defined and it must not be empty for '{0}' in @EntityResult '{1}' @SqlResultSetMapping '{2}'",
508                                         fieldName,
509                                         className,
510                                         resultSetName));
511
512         FieldResultConfig fieldResultConfig = new FieldResultConfig();
513
514         fieldResultConfig.setName(fieldName);
515         fieldResultConfig.setColumn(columnName);
516
517         entityResultConfig.addFieldResult(fieldResultConfig);
518       }
519
520       sqlResultSetMapping.addEntityResult(entityResultConfig);
521     }
522
523     // Adds @ColumnResult.
524
for (int i=0; i < columns.length; i++) {
525       JAnnotation columnResult = (JAnnotation) columns[i];
526
527       String JavaDoc columnName = columnResult.getString("name");
528
529       if (columnName == null || columnName.length() == 0)
530         throw new ConfigException(L.l("@ColumnResult must have a column name defined and it must not be empty in @SqlResultSetMapping '{0}'",
531                                       resultSetName));
532
533       ColumnResultConfig columnResultConfig = new ColumnResultConfig();
534
535       columnResultConfig.setName(columnName);
536
537       sqlResultSetMapping.addColumnResult(columnResultConfig);
538     }
539
540     // Adds a global sql result set mapping to the persistence unit.
541
_persistenceUnit.addSqlResultSetMapping(resultSetName,
542                                             sqlResultSetMapping);
543   }
544
545   /**
546    * Completes all partial bean introspection.
547    */

548   public void configure()
549     throws ConfigException
550   {
551     ConfigException exn = null;
552
553     while (_depCompletions.size() > 0 || _linkCompletions.size() > 0) {
554       while (_linkCompletions.size() > 0) {
555         Completion completion = _linkCompletions.remove(0);
556
557         try {
558           completion.complete();
559         } catch (Exception JavaDoc e) {
560           completion.getRelatedType().setConfigException(e);
561
562           if (exn == null)
563             exn = new ConfigException(e);
564           else
565             log.log(Level.WARNING, e.toString(), e);
566         }
567       }
568
569       if (_depCompletions.size() > 0) {
570         Completion completion = _depCompletions.remove(0);
571
572
573         try {
574           completion.complete();
575         } catch (Exception JavaDoc e) {
576           completion.getRelatedType().setConfigException(e);
577
578           log.log(Level.WARNING, e.toString(), e);
579
580           if (exn == null)
581             exn = new ConfigException(e);
582           else
583             log.log(Level.WARNING, e.toString(), e);
584         }
585       }
586     }
587
588     if (exn != null)
589       throw exn;
590   }
591
592   /**
593    * Introspects the Inheritance
594    */

595   void introspectInheritance(AmberPersistenceUnit persistenceUnit,
596                              RelatedType entityType,
597                              JClass type,
598                              JAnnotation inheritanceAnn,
599                              InheritanceConfig inheritanceConfig)
600     throws ConfigException, SQLException JavaDoc
601   {
602     InheritanceType strategy;
603
604     if (inheritanceAnn != null)
605       strategy = (InheritanceType) inheritanceAnn.get("strategy");
606     else
607       strategy = inheritanceConfig.getStrategy();
608
609     JAnnotation discValueAnn = type.getAnnotation(DiscriminatorValue.class);
610
611     String JavaDoc discriminatorValue = null;
612
613     if (discValueAnn != null)
614       discriminatorValue = discValueAnn.getString("value");
615
616     if (discriminatorValue == null || discriminatorValue.equals("")) {
617       String JavaDoc name = entityType.getBeanClass().getName();
618       int p = name.lastIndexOf('.');
619       if (p > 0)
620         name = name.substring(p + 1);
621
622       discriminatorValue = name;
623     }
624
625     entityType.setDiscriminatorValue(discriminatorValue);
626
627     if (entityType instanceof SubEntityType) {
628       SubEntityType subType = (SubEntityType) entityType;
629
630       subType.getParentType().addSubClass(subType);
631
632       getInternalPrimaryKeyJoinColumnConfig(type);
633       JAnnotation joinAnn = _annotationCfg.getAnnotation();
634       PrimaryKeyJoinColumnConfig primaryKeyJoinColumnConfig = _annotationCfg.getPrimaryKeyJoinColumnConfig();
635
636       // if (subType.isJoinedSubClass()) {
637
if (strategy == InheritanceType.JOINED) {
638         linkInheritanceTable(subType.getRootType().getTable(),
639                              subType.getTable(),
640                              joinAnn,
641                              primaryKeyJoinColumnConfig);
642
643         subType.setId(new SubId(subType, subType.getRootType()));
644       }
645
646       return;
647     }
648
649     switch (strategy) {
650     case JOINED:
651       entityType.setJoinedSubClass(true);
652       break;
653     }
654
655     getInternalDiscriminatorColumnConfig(type);
656     JAnnotation discriminatorAnn = _annotationCfg.getAnnotation();
657     DiscriminatorColumnConfig discriminatorConfig = _annotationCfg.getDiscriminatorColumnConfig();
658
659     String JavaDoc columnName = null;
660
661     if (discriminatorAnn != null)
662       columnName = discriminatorAnn.getString("name");
663
664     if (columnName == null || columnName.equals(""))
665       columnName = "DTYPE";
666
667     Type columnType = null;
668     DiscriminatorType discType = DiscriminatorType.STRING;
669
670     if (discriminatorAnn != null)
671       discType = (DiscriminatorType) discriminatorAnn.get("discriminatorType");
672
673     switch (discType) {
674     case STRING:
675       columnType = StringType.create();
676       break;
677     case CHAR:
678       columnType = PrimitiveCharType.create();
679       break;
680     case INTEGER:
681       columnType = PrimitiveIntType.create();
682       break;
683     default:
684       throw new IllegalStateException JavaDoc();
685     }
686
687     Column column = entityType.getTable().createColumn(columnName,
688                                                        columnType);
689
690     if (discriminatorAnn != null) {
691       column.setNotNull(! discriminatorAnn.getBoolean("nullable"));
692
693       column.setLength(discriminatorAnn.getInt("length"));
694
695       if (! "".equals(discriminatorAnn.get("columnDefinition")))
696         column.setSQLType(discriminatorAnn.getString("columnDefinition"));
697     }
698     else {
699       column.setNotNull(true);
700       column.setLength(10);
701     }
702
703     entityType.setDiscriminator(column);
704   }
705
706   /**
707    * Introspects the fields.
708    */

709   void introspectIdMethod(AmberPersistenceUnit persistenceUnit,
710                           RelatedType entityType,
711                           RelatedType parentType,
712                           JClass type,
713                           JClass idClass,
714                           EntityConfig entityConfig)
715     throws ConfigException, SQLException JavaDoc
716   {
717     ArrayList JavaDoc<IdField> keys = new ArrayList JavaDoc<IdField>();
718
719     IdField idField = null;
720
721     AttributesConfig attributesConfig = null;
722
723     if (entityConfig != null)
724       attributesConfig = entityConfig.getAttributes();
725
726     for (JMethod method : type.getMethods()) {
727       String JavaDoc methodName = method.getName();
728       JClass []paramTypes = method.getParameterTypes();
729
730       if (method.getDeclaringClass().getName().equals("java.lang.Object"))
731         continue;
732
733       if (! methodName.startsWith("get") || paramTypes.length != 0) {
734         continue;
735       }
736
737       String JavaDoc fieldName = toFieldName(methodName.substring(3));
738
739       if (containsFieldOrCompletion(parentType, fieldName))
740         continue;
741
742       getInternalIdConfig(type, method, fieldName);
743       JAnnotation id = _annotationCfg.getAnnotation();
744       IdConfig idConfig = _annotationCfg.getIdConfig();
745
746       if (! _annotationCfg.isNull()) {
747         idField = introspectId(persistenceUnit,
748                                entityType,
749                                method,
750                                fieldName,
751                                method.getReturnType(),
752                                idConfig);
753
754         if (idField != null)
755           keys.add(idField);
756       }
757       else {
758         getInternalEmbeddedIdConfig(type, method, fieldName);
759         JAnnotation embeddedId = _annotationCfg.getAnnotation();
760         EmbeddedIdConfig embeddedIdConfig = _annotationCfg.getEmbeddedIdConfig();
761
762         if (! _annotationCfg.isNull()) {
763           idField = introspectEmbeddedId(persistenceUnit,
764                                          entityType,
765                                          method,
766                                          fieldName,
767                                          method.getReturnType());
768           break;
769         }
770         else {
771           continue;
772         }
773       }
774     }
775
776     if (keys.size() == 0) {
777       if (idField != null) {
778         // @EmbeddedId was used.
779
CompositeId id = new CompositeId(entityType, (EmbeddedIdField) idField);
780         entityType.setId(id);
781       }
782     }
783     else if (keys.size() == 1)
784       entityType.setId(new com.caucho.amber.field.Id(entityType, keys));
785     else if (idClass == null) {
786       throw new ConfigException(L.l("{0} has multiple @Id methods, but no @IdClass. Compound primary keys require either an @IdClass or exactly one @EmbeddedId field or property.",
787                                     entityType.getName()));
788     }
789     else {
790       CompositeId id = new CompositeId(entityType, keys);
791       id.setKeyClass(idClass);
792
793       entityType.setId(id);
794     }
795   }
796
797   /**
798    * Introspects the fields.
799    */

800   void introspectIdField(AmberPersistenceUnit persistenceUnit,
801                          RelatedType entityType,
802                          RelatedType parentType,
803                          JClass type,
804                          JClass idClass,
805                          EntityConfig entityConfig)
806     throws ConfigException, SQLException JavaDoc
807   {
808     ArrayList JavaDoc<IdField> keys = new ArrayList JavaDoc<IdField>();
809
810     AttributesConfig attributesConfig = null;
811
812     if (entityConfig != null)
813       attributesConfig = entityConfig.getAttributes();
814
815     for (JField field : type.getFields()) {
816       String JavaDoc fieldName = field.getName();
817
818       if (containsFieldOrCompletion(parentType, fieldName))
819         continue;
820
821       getInternalIdConfig(type, field, fieldName);
822       JAnnotation id = _annotationCfg.getAnnotation();
823       IdConfig idConfig = _annotationCfg.getIdConfig();
824
825       boolean hasId = ! _annotationCfg.isNull();
826
827       getInternalEmbeddedIdConfig(type, field, fieldName);
828       JAnnotation embeddedId = _annotationCfg.getAnnotation();
829       EmbeddedIdConfig embeddedIdConfig = _annotationCfg.getEmbeddedIdConfig();
830
831       boolean hasEmbeddedId = ! _annotationCfg.isNull();
832
833       if (! (hasId || hasEmbeddedId))
834         continue;
835
836       IdField idField = introspectId(persistenceUnit,
837                                      entityType,
838                                      field,
839                                      fieldName,
840                                      field.getType(),
841                                      idConfig);
842
843       if (idField != null)
844         keys.add(idField);
845     }
846
847     if (keys.size() == 0) {
848     }
849     else if (keys.size() == 1)
850       entityType.setId(new com.caucho.amber.field.Id(entityType, keys));
851     else if (idClass == null) {
852       throw new ConfigException(L.l("{0} has multiple @Id fields, but no @IdClass. Compound primary keys require an @IdClass.",
853                                     entityType.getName()));
854     }
855     else {
856       CompositeId id = new CompositeId(entityType, keys);
857       id.setKeyClass(idClass);
858
859       entityType.setId(id);
860     }
861   }
862
863   /**
864    * Check if it's field
865    */

866   boolean isField(JClass type,
867                   AbstractEnhancedConfig typeConfig,
868                   boolean isEmbeddable)
869     throws ConfigException
870   {
871     if (type == null)
872       return false;
873
874     if (isEmbeddable) {
875
876       for (JMethod method : type.getDeclaredMethods()) {
877
878         JAnnotation ann[] = method.getDeclaredAnnotations();
879
880         if ((ann != null) && (ann.length > 0))
881           return false;
882       }
883
884       // jpa/0gh0
885
for (JField field : type.getDeclaredFields()) {
886
887         if ((! field.isTransient()) && field.isPrivate())
888           return false;
889       }
890
891       return true;
892     }
893
894     if (typeConfig != null) {
895
896       String JavaDoc access = typeConfig.getAccess();
897
898       if (access != null)
899         return access.equals("FIELD");
900
901       JClass parentClass = type.getSuperClass();
902
903       if (parentClass == null)
904         return false;
905       else {
906         getInternalEntityConfig(parentClass);
907         EntityConfig superEntityConfig = _annotationCfg.getEntityConfig();
908
909         if (superEntityConfig == null)
910           return false;
911
912         return isField(parentClass, superEntityConfig, false);
913       }
914     }
915
916     for (JField field : type.getDeclaredFields()) {
917
918       JAnnotation id = field.getAnnotation(javax.persistence.Id.class);
919
920       if (id != null)
921         return true;
922
923       id = field.getAnnotation(EmbeddedId.class);
924
925       if (id != null)
926         return true;
927     }
928
929     return isField(type.getSuperClass(), null, false);
930   }
931
932   private IdField introspectId(AmberPersistenceUnit persistenceUnit,
933                                RelatedType entityType,
934                                JAccessibleObject field,
935                                String JavaDoc fieldName,
936                                JClass fieldType,
937                                IdConfig idConfig)
938     throws ConfigException, SQLException JavaDoc
939   {
940     JAnnotation id = field.getAnnotation(javax.persistence.Id.class);
941     JAnnotation column = field.getAnnotation(javax.persistence.Column.class);
942
943     ColumnConfig columnConfig = null;
944     GeneratedValueConfig generatedValueConfig = null;
945
946     if (idConfig != null) {
947       columnConfig = idConfig.getColumn();
948       generatedValueConfig = idConfig.getGeneratedValue();
949     }
950
951     JAnnotation gen = field.getAnnotation(GeneratedValue.class);
952
953     Type amberType = persistenceUnit.createType(fieldType);
954
955     Column keyColumn = createColumn(entityType,
956                                     field,
957                                     fieldName,
958                                     column,
959                                     amberType,
960                                     columnConfig);
961
962     KeyPropertyField idField;
963     idField = new KeyPropertyField(entityType, fieldName, keyColumn);
964
965     if (gen == null) {
966     }
967     else {
968       JdbcMetaData metaData = null;
969
970       try {
971         metaData = persistenceUnit.getMetaData();
972       } catch (Exception JavaDoc e) {
973         throw new ConfigException(L.l("Unable to get meta data for database. Meta data is needed for generated values."));
974       }
975
976       if (GenerationType.IDENTITY.equals(gen.get("strategy"))) {
977         if (! metaData.supportsIdentity())
978           throw new ConfigException(L.l("'{0}' does not support identity.",
979                                         metaData.getDatabaseName()));
980
981         keyColumn.setGeneratorType("identity");
982         idField.setGenerator("identity");
983       }
984       else if (GenerationType.SEQUENCE.equals(gen.get("strategy"))) {
985         if (! metaData.supportsSequences())
986           throw new ConfigException(L.l("'{0}' does not support sequence.",
987                                         metaData.getDatabaseName()));
988
989         addSequenceIdGenerator(persistenceUnit, idField, gen);
990       }
991       else if (GenerationType.TABLE.equals(gen.get("strategy"))) {
992         addTableIdGenerator(persistenceUnit, idField, id);
993       }
994       else if (GenerationType.AUTO.equals(gen.get("strategy"))) {
995         if (metaData.supportsIdentity()) {
996           keyColumn.setGeneratorType("identity");
997           idField.setGenerator("identity");
998         }
999         else if (metaData.supportsSequences()) {
1000          addSequenceIdGenerator(persistenceUnit, idField, gen);
1001        }
1002        else {
1003          addTableIdGenerator(persistenceUnit, idField, id);
1004        }
1005      }
1006    }
1007
1008    return idField;
1009  }
1010
1011  private IdField introspectEmbeddedId(AmberPersistenceUnit persistenceUnit,
1012                                       RelatedType entityType,
1013                                       JAccessibleObject field,
1014                                       String JavaDoc fieldName,
1015                                       JClass fieldType)
1016    throws ConfigException, SQLException JavaDoc
1017  {
1018    IdField idField;
1019
1020    idField = new EmbeddedIdField(entityType, fieldName);
1021
1022    return idField;
1023  }
1024
1025  void addSequenceIdGenerator(AmberPersistenceUnit persistenceUnit,
1026                              KeyPropertyField idField,
1027                              JAnnotation genAnn)
1028    throws ConfigException
1029  {
1030    idField.setGenerator("sequence");
1031    idField.getColumn().setGeneratorType("sequence");
1032
1033    String JavaDoc name = genAnn.getString("generator");
1034
1035    if (name == null || "".equals(name))
1036      name = idField.getEntitySourceType().getTable().getName() + "_cseq";
1037
1038    IdGenerator gen = persistenceUnit.createSequenceGenerator(name, 1);
1039
1040    idField.getEntitySourceType().setGenerator(idField.getName(), gen);
1041  }
1042
1043  void addTableIdGenerator(AmberPersistenceUnit persistenceUnit,
1044                           KeyPropertyField idField,
1045                           JAnnotation idAnn)
1046    throws ConfigException
1047  {
1048    idField.setGenerator("table");
1049    idField.getColumn().setGeneratorType("table");
1050
1051    String JavaDoc name = idAnn.getString("generator");
1052    if (name == null || "".equals(name))
1053      name = "caucho";
1054
1055    IdGenerator gen = persistenceUnit.getTableGenerator(name);
1056
1057    if (gen == null) {
1058      String JavaDoc genName = "GEN_TABLE";
1059
1060      GeneratorTableType genTable;
1061      genTable = persistenceUnit.createGeneratorTable(genName);
1062
1063      gen = genTable.createGenerator(name);
1064
1065      persistenceUnit.putTableGenerator(name, gen);
1066    }
1067
1068    idField.getEntitySourceType().setGenerator(idField.getName(), gen);
1069  }
1070
1071  /**
1072   * Links a secondary table.
1073   */

1074  void linkSecondaryTable(Table primaryTable,
1075                          Table secondaryTable,
1076                          JAnnotation []joinColumnsAnn)
1077    throws ConfigException
1078  {
1079    ArrayList JavaDoc<ForeignColumn> linkColumns = new ArrayList JavaDoc<ForeignColumn>();
1080    for (Column column : primaryTable.getIdColumns()) {
1081      ForeignColumn linkColumn;
1082
1083      JAnnotation joinAnn = getJoinColumn(joinColumnsAnn, column.getName());
1084      String JavaDoc name;
1085
1086      if (joinAnn == null)
1087        name = column.getName();
1088      else
1089        name = joinAnn.getString("name");
1090
1091      linkColumn = secondaryTable.createForeignColumn(name, column);
1092      linkColumn.setPrimaryKey(true);
1093
1094      secondaryTable.addIdColumn(linkColumn);
1095
1096      linkColumns.add(linkColumn);
1097    }
1098
1099    LinkColumns link = new LinkColumns(secondaryTable,
1100                                       primaryTable,
1101                                       linkColumns);
1102
1103    link.setSourceCascadeDelete(true);
1104
1105    secondaryTable.setDependentIdLink(link);
1106  }
1107
1108  /**
1109   * Links a secondary table.
1110   */

1111  void linkInheritanceTable(Table primaryTable,
1112                            Table secondaryTable,
1113                            JAnnotation joinAnn,
1114                            PrimaryKeyJoinColumnConfig pkJoinColumnCfg)
1115    throws ConfigException
1116  {
1117    JAnnotation joinAnns[] = null;
1118
1119    if (joinAnn != null)
1120      joinAnns = new JAnnotation[] { joinAnn };
1121
1122    linkInheritanceTable(primaryTable,
1123                         secondaryTable,
1124                         joinAnns,
1125                         pkJoinColumnCfg);
1126  }
1127
1128  /**
1129   * Links a secondary table.
1130   */

1131  void linkInheritanceTable(Table primaryTable,
1132                            Table secondaryTable,
1133                            JAnnotation []joinColumnsAnn,
1134                            PrimaryKeyJoinColumnConfig pkJoinColumnCfg)
1135    throws ConfigException
1136  {
1137    ArrayList JavaDoc<ForeignColumn> linkColumns = new ArrayList JavaDoc<ForeignColumn>();
1138    for (Column column : primaryTable.getIdColumns()) {
1139      ForeignColumn linkColumn;
1140
1141      String JavaDoc name;
1142
1143      if (joinColumnsAnn == null) {
1144
1145        if (pkJoinColumnCfg == null)
1146          name = column.getName();
1147        else
1148          name = pkJoinColumnCfg.getName();
1149      }
1150      else {
1151        JAnnotation join;
1152
1153        join = getJoinColumn(joinColumnsAnn, column.getName());
1154
1155        if (join == null)
1156          name = column.getName();
1157        else
1158          name = join.getString("name");
1159      }
1160
1161      linkColumn = secondaryTable.createForeignColumn(name, column);
1162      linkColumn.setPrimaryKey(true);
1163
1164      secondaryTable.addIdColumn(linkColumn);
1165
1166      linkColumns.add(linkColumn);
1167    }
1168
1169    LinkColumns link = new LinkColumns(secondaryTable,
1170                                       primaryTable,
1171                                       linkColumns);
1172
1173    link.setSourceCascadeDelete(true);
1174
1175    secondaryTable.setDependentIdLink(link);
1176
1177    // jpa/0l48
1178
// link = new LinkColumns(primaryTable,
1179
// secondaryTable,
1180
// linkColumns);
1181
//
1182
// link.setSourceCascadeDelete(true);
1183
//
1184
// primaryTable.setDependentIdLink(link);
1185
}
1186
1187  /**
1188   * Introspects the methods.
1189   */

1190  void introspectMethods(AmberPersistenceUnit persistenceUnit,
1191                         AbstractStatefulType entityType,
1192                         AbstractStatefulType parentType,
1193                         JClass type,
1194                         AbstractEnhancedConfig typeConfig)
1195    throws ConfigException
1196  {
1197    for (JMethod method : type.getMethods()) {
1198      String JavaDoc methodName = method.getName();
1199      JClass []paramTypes = method.getParameterTypes();
1200
1201      if (method.getDeclaringClass().getName().equals("java.lang.Object"))
1202        continue;
1203
1204      // jpa/0r38
1205
// Callbacks are introspected in the main introspect() block.
1206
// introspectCallbacks(entityType, method);
1207

1208      String JavaDoc propName;
1209
1210      if (paramTypes.length != 0) {
1211        validateNonGetter(method);
1212        continue;
1213      }
1214      else if (methodName.startsWith("get")) {
1215        propName = methodName.substring(3);
1216      }
1217      else if (methodName.startsWith("is") &&
1218               (method.getReturnType().getName().equals("boolean") ||
1219                method.getReturnType().getName().equals("java.lang.Boolean"))) {
1220        propName = methodName.substring(2);
1221      }
1222      else {
1223        validateNonGetter(method);
1224        continue;
1225      }
1226
1227      getInternalVersionConfig(type, method, propName);
1228      JAnnotation versionAnn = _annotationCfg.getAnnotation();
1229      VersionConfig versionConfig = _annotationCfg.getVersionConfig();
1230
1231      if (! _annotationCfg.isNull()) {
1232        validateNonGetter(method);
1233      }
1234      else {
1235
1236        JMethod setter = type.getMethod("set" + propName,
1237                                        new JClass[] { method.getReturnType() });
1238        if (method.isPrivate() ||
1239            (setter == null) || setter.isPrivate()) {
1240
1241          JAnnotation ann = isAnnotatedMethod(method);
1242
1243          if (ann == null) {
1244            if (setter != null)
1245              ann = isAnnotatedMethod(setter);
1246          }
1247          else if (ann.getType().equals("javax.persistence.Transient"))
1248            continue;
1249
1250          if (ann != null) {
1251            throw new ConfigException(L.l("'{0}' is not a valid annotation for {1}. Only public persistent property getters with matching setters may have property annotations.",
1252                                          ann.getType(), method.getFullName()));
1253          }
1254
1255          continue;
1256        }
1257
1258        // ejb/0g03 for private
1259
if (method.isStatic()) { // || ! method.isPublic()) {
1260
validateNonGetter(method);
1261          continue;
1262        }
1263      }
1264
1265      String JavaDoc fieldName = toFieldName(propName);
1266
1267      if (containsFieldOrCompletion(parentType, fieldName))
1268        continue;
1269
1270      JClass fieldType = method.getReturnType();
1271
1272      introspectField(persistenceUnit, entityType, method,
1273                      fieldName, fieldType, typeConfig);
1274    }
1275  }
1276
1277  /**
1278   * Introspects the fields.
1279   */

1280  void introspectFields(AmberPersistenceUnit persistenceUnit,
1281                        AbstractStatefulType entityType,
1282                        AbstractStatefulType parentType,
1283                        JClass type,
1284                        AbstractEnhancedConfig typeConfig,
1285                        boolean isEmbeddable)
1286    throws ConfigException
1287  {
1288    if (! isEmbeddable)
1289      if (((RelatedType) entityType).getId() == null)
1290        throw new IllegalStateException JavaDoc(L.l("{0} has no key", entityType));
1291
1292    for (JField field : type.getFields()) {
1293      String JavaDoc fieldName = field.getName();
1294
1295      if (containsFieldOrCompletion(parentType, fieldName))
1296        continue;
1297
1298      if (field.isStatic() || field.isTransient())
1299        continue;
1300
1301      JClass fieldType = field.getType();
1302
1303      introspectField(persistenceUnit, entityType, field,
1304                      fieldName, fieldType, typeConfig);
1305    }
1306  }
1307
1308  void introspectField(AmberPersistenceUnit persistenceUnit,
1309                       AbstractStatefulType sourceType,
1310                       JAccessibleObject field,
1311                       String JavaDoc fieldName,
1312                       JClass fieldType,
1313                       AbstractEnhancedConfig typeConfig)
1314    throws ConfigException
1315  {
1316    EmbeddableConfig embeddableConfig = null;
1317    EntityConfig entityConfig = null;
1318    MappedSuperclassConfig mappedSuperConfig = null;
1319
1320    if (typeConfig instanceof EmbeddableConfig)
1321      embeddableConfig = (EmbeddableConfig) typeConfig;
1322    else if (typeConfig instanceof EntityConfig)
1323      entityConfig = (EntityConfig) typeConfig;
1324    else if (typeConfig instanceof MappedSuperclassConfig)
1325      mappedSuperConfig = (MappedSuperclassConfig) typeConfig;
1326
1327    // jpa/0r37: interface fields must not be considered.
1328

1329    JClass jClass = field.getDeclaringClass();
1330
1331    if (jClass.isInterface())
1332      return;
1333
1334    // jpa/0r37: fields declared in non-entity superclasses
1335
// must not be considered.
1336

1337    AbstractStatefulType declaringType;
1338
1339    declaringType = _persistenceUnit.getEntity(jClass.getName());
1340
1341    if (declaringType == null)
1342      declaringType = _persistenceUnit.getEmbeddable(jClass.getName());
1343
1344    if (declaringType == null)
1345      return;
1346
1347    AttributesConfig attributesConfig = null;
1348    IdConfig idConfig = null;
1349    BasicConfig basicConfig = null;
1350    OneToOneConfig oneToOneConfig = null;
1351    OneToManyConfig oneToManyConfig = null;
1352    ManyToOneConfig manyToOneConfig = null;
1353    ManyToManyConfig manyToManyConfig = null;
1354    VersionConfig versionConfig = null;
1355
1356    if (entityConfig != null) {
1357      attributesConfig = entityConfig.getAttributes();
1358
1359      if (attributesConfig != null) {
1360        idConfig = attributesConfig.getId(fieldName);
1361
1362        basicConfig = attributesConfig.getBasic(fieldName);
1363
1364        oneToOneConfig = attributesConfig.getOneToOne(fieldName);
1365
1366        oneToManyConfig = attributesConfig.getOneToMany(fieldName);
1367
1368        manyToOneConfig = attributesConfig.getManyToOne(fieldName);
1369
1370        manyToManyConfig = attributesConfig.getManyToMany(fieldName);
1371
1372        versionConfig = attributesConfig.getVersion(fieldName);
1373      }
1374    }
1375
1376    if ((idConfig != null) ||
1377        field.isAnnotationPresent(javax.persistence.Id.class)) {
1378      validateAnnotations(field, _idAnnotations);
1379
1380      if (! _idTypes.contains(fieldType.getName())) {
1381        throw error(field, L.l("{0} is an invalid @Id type for {1}.",
1382                               fieldType.getName(), field.getName()));
1383      }
1384    }
1385    else if ((basicConfig != null) ||
1386             field.isAnnotationPresent(javax.persistence.Basic.class)) {
1387      validateAnnotations(field, _basicAnnotations);
1388
1389      addBasic(sourceType, field, fieldName, fieldType, basicConfig);
1390    }
1391    else if ((versionConfig != null) ||
1392             field.isAnnotationPresent(javax.persistence.Version.class)) {
1393      validateAnnotations(field, _versionAnnotations);
1394
1395      addVersion((RelatedType) sourceType, field,
1396                 fieldName, fieldType, versionConfig);
1397    }
1398    else if ((manyToOneConfig != null) ||
1399             field.isAnnotationPresent(javax.persistence.ManyToOne.class)) {
1400      validateAnnotations(field, _manyToOneAnnotations);
1401
1402      JAnnotation ann = field.getAnnotation(ManyToOne.class);
1403
1404      JClass targetEntity = null;
1405
1406      if (ann != null)
1407        targetEntity = ann.getClass("targetEntity");
1408      else {
1409
1410        String JavaDoc s = manyToOneConfig.getTargetEntity();
1411
1412        if ((s != null) && (s.length() > 0))
1413          targetEntity = _persistenceUnit.getJClassLoader().forName(s);
1414      }
1415
1416      if (targetEntity == null ||
1417          targetEntity.getName().equals("void")) {
1418        targetEntity = fieldType;
1419      }
1420
1421      getInternalEntityConfig(targetEntity);
1422      JAnnotation targetEntityAnn = _annotationCfg.getAnnotation();
1423      EntityConfig targetEntityConfig = _annotationCfg.getEntityConfig();
1424
1425      if (_annotationCfg.isNull()) {
1426        throw error(field, L.l("'{0}' is an illegal targetEntity for {1}. @ManyToOne relations must target a valid @Entity.",
1427                               targetEntity.getName(), field.getName()));
1428      }
1429
1430      if (! fieldType.isAssignableFrom(targetEntity)) {
1431        throw error(field, L.l("'{0}' is an illegal targetEntity for {1}. @ManyToOne targetEntity must be assignable to the field type '{2}'.",
1432                               targetEntity.getName(),
1433                               field.getName(),
1434                               fieldType.getName()));
1435      }
1436
1437      RelatedType relatedType = (RelatedType) sourceType;
1438
1439      relatedType.setHasDependent(true);
1440
1441      _linkCompletions.add(new ManyToOneCompletion(relatedType,
1442                                                   field,
1443                                                   fieldName,
1444                                                   fieldType));
1445    }
1446    else if ((oneToManyConfig != null) ||
1447             field.isAnnotationPresent(javax.persistence.OneToMany.class)) {
1448      validateAnnotations(field, _oneToManyAnnotations);
1449
1450      if (field.isAnnotationPresent(javax.persistence.MapKey.class)) {
1451        if (!fieldType.getName().equals("java.util.Map")) {
1452          throw error(field, L.l("'{0}' is an illegal @OneToMany/@MapKey type for {1}. @MapKey must be a java.util.Map",
1453                                 fieldType.getName(),
1454                                 field.getName()));
1455        }
1456      }
1457      else if (! _oneToManyTypes.contains(fieldType.getName())) {
1458        throw error(field, L.l("'{0}' is an illegal @OneToMany type for {1}. @OneToMany must be a java.util.Collection, java.util.List or java.util.Map",
1459                               fieldType.getName(),
1460                               field.getName()));
1461      }
1462
1463      RelatedType relatedType = (RelatedType) sourceType;
1464
1465      _depCompletions.add(new OneToManyCompletion(relatedType,
1466                                                  field,
1467                                                  fieldName,
1468                                                  fieldType,
1469                                                  oneToManyConfig));
1470    }
1471    else if ((oneToOneConfig != null) ||
1472             field.isAnnotationPresent(javax.persistence.OneToOne.class)) {
1473      validateAnnotations(field, _oneToOneAnnotations);
1474
1475      RelatedType relatedType = (RelatedType) sourceType;
1476
1477      relatedType.setHasDependent(true);
1478
1479      OneToOneCompletion oneToOne = new OneToOneCompletion(relatedType,
1480                                                           field,
1481                                                           fieldName,
1482                                                           fieldType);
1483
1484      // jpa/0o03 and jpa/0o06 (check also jpa/0o07 with no mappedBy at all)
1485
// @OneToOne with mappedBy should be completed first
1486
String JavaDoc mappedBy;
1487
1488      if (oneToOneConfig != null)
1489        mappedBy = oneToOneConfig.getMappedBy();
1490      else {
1491        JAnnotation oneToOneAnn = field.getAnnotation(OneToOne.class);
1492        mappedBy = oneToOneAnn.getString("mappedBy");
1493      }
1494
1495      boolean isOwner = (mappedBy == null || mappedBy.equals(""));
1496
1497      if (isOwner)
1498        _depCompletions.add(oneToOne);
1499      else
1500        _depCompletions.add(0, oneToOne);
1501
1502      ArrayList JavaDoc<OneToOneCompletion> oneToOneList
1503        = _oneToOneCompletions.get(relatedType);
1504
1505      if (oneToOneList == null) {
1506        oneToOneList = new ArrayList JavaDoc<OneToOneCompletion>();
1507        _oneToOneCompletions.put(relatedType, oneToOneList);
1508      }
1509
1510      oneToOneList.add(oneToOne);
1511    }
1512    else if ((manyToManyConfig != null) ||
1513             field.isAnnotationPresent(javax.persistence.ManyToMany.class)) {
1514
1515      if (field.isAnnotationPresent(javax.persistence.MapKey.class)) {
1516        if (! fieldType.getName().equals("java.util.Map")) {
1517          throw error(field, L.l("'{0}' is an illegal @ManyToMany/@MapKey type for {1}. @MapKey must be a java.util.Map",
1518                                 fieldType.getName(),
1519                                 field.getName()));
1520        }
1521      }
1522
1523      RelatedType relatedType = (RelatedType) sourceType;
1524
1525      Completion completion = new ManyToManyCompletion(relatedType,
1526                                                       field,
1527                                                       fieldName,
1528                                                       fieldType);
1529
1530      JAnnotation ann = field.getAnnotation(ManyToMany.class);
1531
1532      String JavaDoc mappedBy;
1533
1534      if (ann != null)
1535        mappedBy = ann.getString("mappedBy");
1536      else
1537        mappedBy = manyToManyConfig.getMappedBy();
1538
1539      if ("".equals(mappedBy))
1540        _linkCompletions.add(completion);
1541      else
1542        _depCompletions.add(completion);
1543    }
1544    else if (field.isAnnotationPresent(javax.persistence.Embedded.class)) {
1545      validateAnnotations(field, _embeddedAnnotations);
1546
1547      RelatedType relatedType = (RelatedType) sourceType;
1548
1549      relatedType.setHasDependent(true);
1550
1551      _depCompletions.add(new EmbeddedCompletion(relatedType,
1552                                                 field,
1553                                                 fieldName,
1554                                                 fieldType,
1555                                                 false));
1556    }
1557    else if (field.isAnnotationPresent(javax.persistence.EmbeddedId.class)) {
1558      validateAnnotations(field, _embeddedIdAnnotations);
1559
1560      _depCompletions.add(new EmbeddedCompletion((RelatedType) sourceType,
1561                                                 field,
1562                                                 fieldName,
1563                                                 fieldType,
1564                                                 true));
1565    }
1566    else if (field.isAnnotationPresent(javax.persistence.Transient.class)) {
1567    }
1568    else {
1569      addBasic(sourceType, field, fieldName, fieldType, basicConfig);
1570    }
1571  }
1572
1573  void addBasic(AbstractStatefulType sourceType,
1574                JAccessibleObject field,
1575                String JavaDoc fieldName,
1576                JClass fieldType,
1577                BasicConfig basicConfig)
1578    throws ConfigException
1579  {
1580    AmberPersistenceUnit persistenceUnit = sourceType.getPersistenceUnit();
1581
1582    JAnnotation basicAnn = field.getAnnotation(Basic.class);
1583    JAnnotation columnAnn = field.getAnnotation(javax.persistence.Column.class);
1584    JAnnotation enumeratedAnn = field.getAnnotation(Enumerated.class);
1585
1586    ColumnConfig columnConfig = null;
1587
1588    if (basicConfig != null)
1589      columnConfig = basicConfig.getColumn();
1590
1591    if (_basicTypes.contains(fieldType.getName())) {
1592    }
1593    else if (fieldType.isAssignableTo(java.io.Serializable JavaDoc.class)) {
1594    }
1595    else
1596      throw error(field, L.l("{0} is an invalid @Basic type for {1}.",
1597                             fieldType.getName(), field.getName()));
1598
1599    Type amberType;
1600
1601    if (enumeratedAnn == null)
1602      amberType = persistenceUnit.createType(fieldType);
1603    else {
1604      com.caucho.amber.type.EnumType enumType;
1605
1606      enumType = persistenceUnit.createEnum(fieldType.getName(),
1607                                            fieldType);
1608
1609      enumType.setOrdinal(enumeratedAnn.get("value") ==
1610                          javax.persistence.EnumType.ORDINAL);
1611
1612      amberType = enumType;
1613    }
1614
1615    Column fieldColumn = null;
1616
1617    if (sourceType instanceof RelatedType)
1618      fieldColumn = createColumn((RelatedType) sourceType, field, fieldName,
1619                                 columnAnn, amberType, columnConfig);
1620
1621    PropertyField property = new PropertyField(sourceType, fieldName);
1622    property.setColumn(fieldColumn);
1623
1624    // jpa/0w24
1625
property.setType(amberType);
1626
1627    if (basicAnn != null)
1628      property.setLazy(basicAnn.get("fetch") == FetchType.LAZY);
1629    else if (basicConfig != null)
1630      property.setLazy(basicConfig.getFetch() == FetchType.LAZY);
1631    else
1632      property.setLazy(false);
1633
1634    /*
1635      field.setInsertable(insertable);
1636      field.setUpdateable(updateable);
1637    */

1638
1639    sourceType.addField(property);
1640  }
1641
1642  void addVersion(RelatedType sourceType,
1643                  JAccessibleObject field,
1644                  String JavaDoc fieldName,
1645                  JClass fieldType,
1646                  VersionConfig versionConfig)
1647    throws ConfigException
1648  {
1649    AmberPersistenceUnit persistenceUnit = sourceType.getPersistenceUnit();
1650
1651    JAnnotation columnAnn = field.getAnnotation(javax.persistence.Column.class);
1652
1653    ColumnConfig columnConfig = null;
1654
1655    if (versionConfig != null)
1656      columnConfig = versionConfig.getColumn();
1657
1658    if (! _versionTypes.contains(fieldType.getName())) {
1659      throw error(field, L.l("{0} is an invalid @Version type for {1}.",
1660                             fieldType.getName(), field.getName()));
1661    }
1662
1663    Type amberType = persistenceUnit.createType(fieldType);
1664
1665    Column fieldColumn = createColumn(sourceType, field, fieldName,
1666                                      columnAnn, amberType, columnConfig);
1667
1668    VersionField version = new VersionField(sourceType, fieldName);
1669    version.setColumn(fieldColumn);
1670
1671    sourceType.setVersionField(version);
1672  }
1673
1674  private Column createColumn(RelatedType entityType,
1675                              JAccessibleObject field,
1676                              String JavaDoc fieldName,
1677                              JAnnotation columnAnn,
1678                              Type amberType,
1679                              ColumnConfig columnConfig)
1680    throws ConfigException
1681  {
1682    String JavaDoc name;
1683
1684    if (columnAnn != null && ! columnAnn.get("name").equals(""))
1685      name = (String JavaDoc) columnAnn.get("name");
1686    else if (columnConfig != null && ! columnConfig.getName().equals(""))
1687      name = columnConfig.getName();
1688    else
1689      name = toSqlName(fieldName);
1690
1691    Column column = null;
1692
1693    if (columnAnn != null && ! columnAnn.get("table").equals("")) {
1694      String JavaDoc tableName = columnAnn.getString("table");
1695      Table table;
1696
1697      table = entityType.getSecondaryTable(tableName);
1698
1699      if (table == null)
1700        throw error(field, L.l("{0} @Column(table='{1}') is an unknown secondary table.",
1701                               fieldName,
1702                               tableName));
1703
1704      column = table.createColumn(name, amberType);
1705    }
1706    else
1707      column = entityType.getTable().createColumn(name, amberType);
1708
1709    if ((column != null) && (columnAnn != null)) {
1710      // primaryKey = column.primaryKey();
1711
column.setUnique(columnAnn.getBoolean("unique"));
1712      column.setNotNull(! columnAnn.getBoolean("nullable"));
1713      //insertable = column.insertable();
1714
//updateable = column.updatable();
1715
if (! "".equals(columnAnn.getString("columnDefinition")))
1716        column.setSQLType(columnAnn.getString("columnDefinition"));
1717      column.setLength(columnAnn.getInt("length"));
1718      int precision = columnAnn.getInt("precision");
1719      if (precision < 0) {
1720        throw error(field, L.l("{0} @Column precision cannot be less than 0.",
1721                               fieldName));
1722      }
1723
1724      int scale = columnAnn.getInt("scale");
1725      if (scale < 0) {
1726        throw error(field, L.l("{0} @Column scale cannot be less than 0.",
1727                               fieldName));
1728      }
1729
1730      // this test implicitly works for case where
1731
// precision is not set explicitly (ie: set to 0 by default)
1732
// and scale is set
1733
if (scale > precision) {
1734        throw error(field, L.l("{0} @Column scale cannot be greater than precision. Must set precision to a non-zero value before setting scale.",
1735                               fieldName));
1736      }
1737
1738      if (precision > 0) {
1739        column.setPrecision(precision);
1740        column.setScale(scale);
1741      }
1742    }
1743
1744    return column;
1745  }
1746
1747  void addManyToOne(RelatedType sourceType,
1748                    JAccessibleObject field,
1749                    String JavaDoc fieldName,
1750                    JClass fieldType)
1751    throws ConfigException
1752  {
1753    AmberPersistenceUnit persistenceUnit = sourceType.getPersistenceUnit();
1754
1755    getInternalManyToOneConfig(sourceType.getBeanClass(), field, fieldName);
1756    JAnnotation manyToOneAnn = _annotationCfg.getAnnotation();
1757    Object JavaDoc manyToOneConfig = _annotationCfg.getManyToOneConfig();
1758    HashMap JavaDoc<String JavaDoc, JoinColumnConfig> joinColumnMap = null;
1759    CascadeType cascadeTypes[] = null;
1760
1761    JClass parentClass = sourceType.getBeanClass();
1762
1763    do {
1764      getInternalEntityConfig(parentClass);
1765      JAnnotation parentEntity = _annotationCfg.getAnnotation();
1766      EntityConfig superEntityConfig = _annotationCfg.getEntityConfig();
1767
1768      if (superEntityConfig != null) {
1769        AttributesConfig attributesConfig = superEntityConfig.getAttributes();
1770
1771        if (attributesConfig != null) {
1772          if (manyToOneConfig == null)
1773            manyToOneConfig = attributesConfig.getManyToOne(fieldName);
1774        }
1775      }
1776
1777      parentClass = parentClass.getSuperClass();
1778    }
1779    while ((parentClass != null) && (manyToOneConfig == null));
1780
1781    FetchType fetchType = FetchType.EAGER;
1782    JClass targetClass = null;
1783
1784    if ((manyToOneAnn == null) && (manyToOneConfig == null)) {
1785      // jpa/0o03
1786

1787      getInternalOneToOneConfig(sourceType.getBeanClass(), field, fieldName);
1788      manyToOneAnn = _annotationCfg.getAnnotation();
1789      manyToOneConfig = _annotationCfg.getOneToOneConfig();
1790
1791      if (manyToOneConfig != null) {
1792        fetchType = ((OneToOneConfig) manyToOneConfig).getFetch();
1793        joinColumnMap = ((OneToOneConfig) manyToOneConfig).getJoinColumnMap();
1794
1795        String JavaDoc s = ((OneToOneConfig) manyToOneConfig).getTargetEntity();
1796        if (s != null)
1797          targetClass = _persistenceUnit.getJClassLoader().forName(s);
1798      }
1799    }
1800    else {
1801      if (manyToOneConfig != null) {
1802        fetchType = ((ManyToOneConfig) manyToOneConfig).getFetch();
1803        joinColumnMap = ((ManyToOneConfig) manyToOneConfig).getJoinColumnMap();
1804        CascadeConfig cascade = ((ManyToOneConfig) manyToOneConfig).getCascade();
1805
1806        if (cascade != null) {
1807          cascadeTypes = cascade.getCascadeTypes();
1808        }
1809
1810        String JavaDoc s = ((ManyToOneConfig) manyToOneConfig).getTargetEntity();
1811        if (s != null)
1812          targetClass = _persistenceUnit.getJClassLoader().forName(s);
1813      }
1814    }
1815
1816    if (manyToOneAnn != null) {
1817      fetchType = (FetchType) manyToOneAnn.get("fetch");
1818
1819      targetClass = manyToOneAnn.getClass("targetEntity");
1820
1821      // XXX: runtime does not cast this
1822
// cascadeType = (CascadeType []) manyToOneAnn.get("cascade");
1823
Object JavaDoc cascade[] = (Object JavaDoc []) manyToOneAnn.get("cascade");
1824
1825      cascadeTypes = new CascadeType[cascade.length];
1826
1827      for (int i=0; i < cascade.length; i++)
1828        cascadeTypes[i] = (CascadeType) cascade[i];
1829    }
1830
1831    if (fetchType == FetchType.EAGER) {
1832      if (sourceType.getBeanClass().getName().equals(fieldType.getName())) {
1833        throw error(field, L.l("'{0}': '{1}' is an illegal recursive type for @OneToOne/@ManyToOne with EAGER fetching. You should specify FetchType.LAZY for this relationship.",
1834                               field.getName(),
1835                               fieldType.getName()));
1836      }
1837    }
1838
1839    JAnnotation joinColumns = field.getAnnotation(JoinColumns.class);
1840
1841    Object JavaDoc []joinColumnsAnn = null;
1842
1843    if (joinColumns != null)
1844      joinColumnsAnn = (Object JavaDoc []) joinColumns.get("value");
1845
1846    JAnnotation joinColumnAnn = field.getAnnotation(JoinColumn.class);
1847
1848    if (joinColumnsAnn != null && joinColumnAnn != null) {
1849      throw error(field, L.l("{0} may not have both @JoinColumn and @JoinColumns",
1850                             field.getName()));
1851    }
1852
1853    if (joinColumnAnn != null)
1854      joinColumnsAnn = new Object JavaDoc[] { joinColumnAnn };
1855
1856    String JavaDoc targetName = "";
1857    if (targetClass != null)
1858      targetName = targetClass.getName();
1859
1860    if (targetName.equals("") || targetName.equals("void"))
1861      targetName = fieldType.getName();
1862
1863    EntityManyToOneField manyToOneField;
1864    manyToOneField = new EntityManyToOneField(sourceType, fieldName, cascadeTypes);
1865
1866    EntityType targetType = persistenceUnit.createEntity(targetName, fieldType);
1867
1868    manyToOneField.setType(targetType);
1869
1870    manyToOneField.setLazy(fetchType == FetchType.LAZY);
1871
1872    sourceType.addField(manyToOneField);
1873
1874    Table sourceTable = sourceType.getTable();
1875
1876    validateJoinColumns(field, joinColumnsAnn, joinColumnMap, targetType);
1877
1878    int n = 0;
1879
1880    if (joinColumnMap != null)
1881      n = joinColumnMap.size();
1882
1883    ArrayList JavaDoc<ForeignColumn> foreignColumns = new ArrayList JavaDoc<ForeignColumn>();
1884
1885    RelatedType parentType = targetType;
1886
1887    ArrayList JavaDoc<Column> targetIdColumns = targetType.getId().getColumns();
1888
1889    while (targetIdColumns.size() == 0) {
1890
1891      parentType = parentType.getParentType();
1892
1893      if (parentType == null)
1894        break;
1895
1896      targetIdColumns = parentType.getId().getColumns();
1897    }
1898
1899    for (Column keyColumn : targetIdColumns) {
1900
1901      String JavaDoc columnName = fieldName.toUpperCase() + '_' + keyColumn.getName();
1902      boolean nullable = true;
1903      boolean unique = false;
1904
1905      if (n > 0) {
1906
1907        JoinColumnConfig joinColumn;
1908
1909        if (n == 1) {
1910          joinColumn = (JoinColumnConfig) joinColumnMap.values().toArray()[0];
1911        } else
1912          joinColumn = joinColumnMap.get(keyColumn.getName());
1913
1914        if (joinColumn != null) {
1915          columnName = joinColumn.getName();
1916
1917          nullable = joinColumn.getNullable();
1918          unique = joinColumn.getUnique();
1919        }
1920      }
1921      else {
1922        JAnnotation joinAnn = getJoinColumn(joinColumnsAnn, keyColumn.getName());
1923
1924        if (joinAnn != null) {
1925          columnName = joinAnn.getString("name");
1926
1927          nullable = joinAnn.getBoolean("nullable");
1928          unique = joinAnn.getBoolean("unique");
1929        }
1930      }
1931
1932      ForeignColumn foreignColumn;
1933
1934      foreignColumn = sourceTable.createForeignColumn(columnName, keyColumn);
1935
1936      foreignColumn.setNotNull(! nullable);
1937      foreignColumn.setUnique(unique);
1938
1939      foreignColumns.add(foreignColumn);
1940    }
1941
1942    LinkColumns linkColumns = new LinkColumns(sourceType.getTable(),
1943                                              targetType.getTable(),
1944                                              foreignColumns);
1945
1946    manyToOneField.setLinkColumns(linkColumns);
1947
1948    manyToOneField.init();
1949  }
1950
1951  private JAnnotation getJoinColumn(JAnnotation joinColumns,
1952                                    String JavaDoc keyName)
1953  {
1954    if (joinColumns == null)
1955      return null;
1956
1957    return getJoinColumn((Object JavaDoc []) joinColumns.get("value"), keyName);
1958  }
1959
1960  void validateJoinColumns(JAccessibleObject field,
1961                           Object JavaDoc []columnsAnn,
1962                           HashMap JavaDoc<String JavaDoc, JoinColumnConfig> joinColumnMap,
1963                           RelatedType targetType)
1964    throws ConfigException
1965  {
1966    if ((joinColumnMap == null) && (columnsAnn == null))
1967      return;
1968
1969    com.caucho.amber.field.Id id = targetType.getId();
1970
1971    int size;
1972    Object JavaDoc joinColumnCfg[] = null;
1973
1974    if (columnsAnn != null)
1975      size = columnsAnn.length;
1976    else {
1977      size = joinColumnMap.size();
1978      joinColumnCfg = joinColumnMap.values().toArray();
1979    }
1980
1981    if (id.getColumns().size() != size) {
1982      throw error(field, L.l("Number of @JoinColumns for '{1}' ({0}) does not match the number of primary key columns for '{3}' ({2}).",
1983                             "" + size,
1984                             field.getName(),
1985                             id.getColumns().size(),
1986                             targetType.getName()));
1987    }
1988
1989    for (int i = 0; i < size; i++) {
1990      String JavaDoc ref;
1991
1992      if (joinColumnCfg != null) {
1993        ref = ((JoinColumnConfig) joinColumnCfg[i]).getReferencedColumnName();
1994      }
1995      else {
1996        JAnnotation ann = (JAnnotation) columnsAnn[i];
1997
1998        ref = ann.getString("referencedColumnName");
1999      }
2000
2001      if (((ref == null) || ref.equals("")) && size > 1)
2002        throw error(field, L.l("referencedColumnName is required when more than one @JoinColumn is specified."));
2003
2004      Column column = findColumn(id.getColumns(), ref);
2005
2006      if (column == null)
2007        throw error(field, L.l("referencedColumnName '{0}' does not match any key column in '{1}'.",
2008                               ref, targetType.getName()));
2009    }
2010  }
2011
2012  private Column findColumn(ArrayList JavaDoc<Column> columns, String JavaDoc ref)
2013  {
2014    if (((ref == null) || ref.equals("")) && columns.size() == 1)
2015      return columns.get(0);
2016
2017    for (Column column : columns) {
2018      if (column.getName().equals(ref))
2019        return column;
2020    }
2021
2022    return null;
2023  }
2024
2025  JAnnotation getJoinColumn(Object JavaDoc []columnsAnn, String JavaDoc keyName)
2026  {
2027    if (columnsAnn == null || columnsAnn.length == 0)
2028      return null;
2029
2030    for (int i = 0; i < columnsAnn.length; i++) {
2031      JAnnotation ann = (JAnnotation) columnsAnn[i];
2032
2033      String JavaDoc ref = ann.getString("referencedColumnName");
2034
2035      if (ref.equals("") || ref.equals(keyName))
2036        return ann;
2037    }
2038
2039    return null;
2040  }
2041
2042  void addManyToMany(RelatedType sourceType,
2043                     JAccessibleObject field,
2044                     String JavaDoc fieldName,
2045                     JClass fieldType)
2046    throws ConfigException
2047  {
2048    getInternalManyToManyConfig(sourceType.getBeanClass(), field, fieldName);
2049    JAnnotation manyToManyAnn = _annotationCfg.getAnnotation();
2050    ManyToManyConfig manyToManyConfig = _annotationCfg.getManyToManyConfig();
2051
2052    JType retType;
2053
2054    if (field instanceof JField)
2055      retType = ((JField) field).getGenericType();
2056    else
2057      retType = ((JMethod) field).getGenericReturnType();
2058
2059    JType []typeArgs = retType.getActualTypeArguments();
2060
2061    String JavaDoc targetName = "";
2062
2063    if (manyToManyAnn != null) {
2064      JClass targetEntity = manyToManyAnn.getClass("targetEntity");
2065
2066      if (targetEntity != null)
2067        targetName = targetEntity.getName();
2068    }
2069    else
2070      targetName = manyToManyConfig.getTargetEntity();
2071
2072    if (! targetName.equals("") && ! targetName.equals("void")) {
2073    }
2074    else if (typeArgs.length > 0)
2075      targetName = typeArgs[0].getName();
2076    else
2077      throw error(field, L.l("Can't determine targetEntity for {0}. @OneToMany properties must target @Entity beans.",
2078                             field.getName()));
2079
2080    EntityType targetType = _persistenceUnit.getEntity(targetName);
2081
2082    if (targetType == null)
2083      throw error(field,
2084                  L.l("targetEntity '{0}' is not an @Entity bean for {1}. The targetEntity of a @ManyToMany collection must be an @Entity bean.",
2085                      targetName,
2086                      field.getName()));
2087
2088    // XXX: introspect cascade types
2089
CascadeType[] cascadeTypes = null;
2090
2091    String JavaDoc mappedBy;
2092
2093    if (manyToManyAnn != null) {
2094      mappedBy = manyToManyAnn.getString("mappedBy");
2095
2096      // XXX: runtime does not cast this
2097
// cascadeType = (CascadeType []) manyToManyAnn.get("cascade");
2098
Object JavaDoc cascade[] = (Object JavaDoc []) manyToManyAnn.get("cascade");
2099
2100      cascadeTypes = new CascadeType[cascade.length];
2101
2102      for (int i=0; i < cascade.length; i++)
2103        cascadeTypes[i] = (CascadeType) cascade[i];
2104    }
2105    else {
2106      mappedBy = manyToManyConfig.getMappedBy();
2107
2108      CascadeConfig cascade = ((ManyToManyConfig) manyToManyConfig).getCascade();
2109
2110      if (cascade != null) {
2111        cascadeTypes = cascade.getCascadeTypes();
2112      }
2113    }
2114
2115    if (! ((mappedBy == null) || "".equals(mappedBy))) {
2116      EntityManyToManyField sourceField
2117        = (EntityManyToManyField) targetType.getField(mappedBy);
2118
2119      EntityManyToManyField manyToManyField;
2120
2121      if (sourceField == null)
2122        throw error(field,
2123                    L.l("Unable to find the associated field in '{0}' for a @ManyToMany relationship from '{1}'",
2124                        targetName,
2125                        field.getName()));
2126
2127      manyToManyField = new EntityManyToManyField(sourceType,
2128                                                  fieldName,
2129                                                  sourceField,
2130                                                  cascadeTypes);
2131      manyToManyField.setType(targetType);
2132      sourceType.addField(manyToManyField);
2133
2134      // jpa/0i5-
2135
// Update column names for bidirectional many-to-many
2136

2137      if (! sourceField.hasJoinColumns()) {
2138        LinkColumns sourceLink = sourceField.getSourceLink();
2139        ArrayList JavaDoc<ForeignColumn> columns = sourceLink.getColumns();
2140        for (ForeignColumn column : columns) {
2141          String JavaDoc columnName = column.getName();
2142          columnName = columnName.substring(columnName.indexOf('_'));
2143          columnName = manyToManyField.getName().toUpperCase() + columnName;
2144          column.setName(columnName);
2145        }
2146      }
2147
2148      if (! sourceField.hasInverseJoinColumns()) {
2149        LinkColumns targetLink = sourceField.getTargetLink();
2150        ArrayList JavaDoc<ForeignColumn> columns = targetLink.getColumns();
2151        for (ForeignColumn column : columns) {
2152          String JavaDoc columnName = column.getName();
2153          columnName = columnName.substring(columnName.indexOf('_'));
2154          columnName = sourceField.getName().toUpperCase() + columnName;
2155          column.setName(columnName);
2156        }
2157      }
2158
2159      return;
2160    }
2161
2162    EntityManyToManyField manyToManyField;
2163
2164    manyToManyField = new EntityManyToManyField(sourceType, fieldName, cascadeTypes);
2165    manyToManyField.setType(targetType);
2166
2167    String JavaDoc sqlTable = sourceType.getTable().getName() + "_" +
2168      targetType.getTable().getName();
2169
2170    JAnnotation joinTableAnn = field.getAnnotation(javax.persistence.JoinTable.class);
2171
2172    JoinTableConfig joinTableConfig = null;
2173
2174    if (manyToManyConfig != null)
2175      joinTableConfig = manyToManyConfig.getJoinTable();
2176
2177    Table mapTable = null;
2178
2179    ArrayList JavaDoc<ForeignColumn> sourceColumns = null;
2180    ArrayList JavaDoc<ForeignColumn> targetColumns = null;
2181
2182    if ((joinTableAnn != null) || (joinTableConfig != null)) {
2183
2184      Object JavaDoc joinColumns[] = null;
2185      Object JavaDoc inverseJoinColumns[] = null;
2186
2187      HashMap JavaDoc<String JavaDoc, JoinColumnConfig> joinColumnsConfig = null;
2188      HashMap JavaDoc<String JavaDoc, JoinColumnConfig> inverseJoinColumnsConfig = null;
2189
2190      String JavaDoc joinTableName;
2191
2192      if (joinTableAnn != null) {
2193        joinTableName = joinTableAnn.getString("name");
2194        joinColumns = (Object JavaDoc []) joinTableAnn.get("joinColumns");
2195        inverseJoinColumns = (Object JavaDoc []) joinTableAnn.get("inverseJoinColumns");
2196
2197        if ((joinColumns != null) &&
2198            (joinColumns.length > 0))
2199          manyToManyField.setJoinColumns(true);
2200
2201        if ((inverseJoinColumns != null) &&
2202            (inverseJoinColumns.length > 0))
2203          manyToManyField.setInverseJoinColumns(true);
2204      }
2205      else {
2206        joinTableName = joinTableConfig.getName();
2207        joinColumnsConfig = joinTableConfig.getJoinColumnMap();
2208        inverseJoinColumnsConfig = joinTableConfig.getInverseJoinColumnMap();
2209
2210        if ((joinColumnsConfig != null) &&
2211            (joinColumnsConfig.size() > 0))
2212          manyToManyField.setJoinColumns(true);
2213
2214        if ((inverseJoinColumnsConfig != null) &&
2215            (inverseJoinColumnsConfig.size() > 0))
2216          manyToManyField.setInverseJoinColumns(true);
2217      }
2218
2219      if (! joinTableName.equals(""))
2220        sqlTable = joinTableName;
2221
2222      mapTable = _persistenceUnit.createTable(sqlTable);
2223
2224      sourceColumns = AbstractConfigIntrospector.calculateColumns(field,
2225                                                                  mapTable,
2226                                                                  sourceType.getTable().getName() + "_",
2227                                                                  sourceType,
2228                                                                  joinColumns,
2229                                                                  joinColumnsConfig);
2230
2231      targetColumns = AbstractConfigIntrospector.calculateColumns(field,
2232                                                                  mapTable,
2233                                                                  targetType.getTable().getName() + "_",
2234                                                                  targetType,
2235                                                                  inverseJoinColumns,
2236                                                                  inverseJoinColumnsConfig);
2237    }
2238    else {
2239      mapTable = _persistenceUnit.createTable(sqlTable);
2240
2241      sourceColumns = AbstractConfigIntrospector.calculateColumns(mapTable,
2242                                                                  sourceType.getTable().getName() + "_",
2243                                                                  sourceType);
2244
2245      targetColumns = AbstractConfigIntrospector.calculateColumns(mapTable,
2246                                                                  targetType.getTable().getName() + "_",
2247                                                                  targetType);
2248    }
2249
2250    manyToManyField.setAssociationTable(mapTable);
2251    manyToManyField.setTable(sqlTable);
2252
2253    manyToManyField.setSourceLink(new LinkColumns(mapTable,
2254                                                  sourceType.getTable(),
2255                                                  sourceColumns));
2256
2257    manyToManyField.setTargetLink(new LinkColumns(mapTable,
2258                                                  targetType.getTable(),
2259                                                  targetColumns));
2260
2261    getInternalMapKeyConfig(sourceType.getBeanClass(), field, fieldName);
2262    JAnnotation mapKeyAnn = _annotationCfg.getAnnotation();
2263    MapKeyConfig mapKeyConfig = _annotationCfg.getMapKeyConfig();
2264
2265    if (! _annotationCfg.isNull()) {
2266
2267      String JavaDoc key;
2268
2269      if (mapKeyAnn != null)
2270        key = mapKeyAnn.getString("name");
2271      else
2272        key = mapKeyConfig.getName();
2273
2274      String JavaDoc getter = "get" +
2275        Character.toUpperCase(key.charAt(0)) + key.substring(1);
2276
2277      JMethod method = targetType.getGetter(getter);
2278
2279      if (method == null) {
2280        throw error(field,
2281                    L.l("targetEntity '{0}' has no getter for field named '{1}'. Either the @MapKey name or the @ManyToMany targetEntity is incorrect.",
2282                        targetName, key));
2283      }
2284
2285      manyToManyField.setMapKey(key);
2286    }
2287
2288    sourceType.addField(manyToManyField);
2289  }
2290
2291  EntityManyToOneField getSourceField(RelatedType targetType,
2292                                      String JavaDoc mappedBy,
2293                                      RelatedType sourceType)
2294  {
2295    ArrayList JavaDoc<AmberField> fields = targetType.getFields();
2296
2297    for (AmberField field : fields) {
2298      // jpa/0o07: there is no mappedBy at all on any sides.
2299
if ("".equals(mappedBy) || mappedBy == null) {
2300        if (field.getJavaType().isAssignableFrom(sourceType.getBeanClass()))
2301          return (EntityManyToOneField) field;
2302      }
2303      else if (field.getName().equals(mappedBy))
2304        return (EntityManyToOneField) field;
2305    }
2306
2307    return null;
2308  }
2309
2310  OneToOneCompletion getSourceCompletion(RelatedType targetType,
2311                                         String JavaDoc mappedBy)
2312  {
2313    ArrayList JavaDoc<OneToOneCompletion> sourceCompletions
2314      = _oneToOneCompletions.get(targetType);
2315
2316    if (sourceCompletions == null)
2317      return null;
2318
2319    // jpa/0o07
2320
if (sourceCompletions.size() == 1)
2321      return sourceCompletions.get(0);
2322
2323    for (OneToOneCompletion oneToOne : sourceCompletions) {
2324
2325      if (oneToOne.getFieldName().equals(mappedBy)) {
2326        return oneToOne;
2327      }
2328    }
2329
2330    return null;
2331  }
2332
2333  /**
2334   * completes for dependent
2335   */

2336  class Completion {
2337    protected RelatedType _relatedType;
2338
2339    protected Completion(RelatedType relatedType,
2340                         String JavaDoc fieldName)
2341    {
2342      _relatedType = relatedType;
2343      _relatedType.addCompletionField(fieldName);
2344    }
2345
2346    protected Completion(RelatedType relatedType)
2347    {
2348      _relatedType = relatedType;
2349    }
2350
2351    RelatedType getRelatedType()
2352    {
2353      return _relatedType;
2354    }
2355
2356    void complete()
2357      throws ConfigException
2358    {
2359    }
2360  }
2361
2362  /**
2363   * completes for dependent
2364   */

2365  class OneToManyCompletion extends Completion {
2366    private JAccessibleObject _field;
2367    private String JavaDoc _fieldName;
2368    private JClass _fieldType;
2369    private OneToManyConfig _oneToManyConfig;
2370
2371    OneToManyCompletion(RelatedType type,
2372                        JAccessibleObject field,
2373                        String JavaDoc fieldName,
2374                        JClass fieldType,
2375                        OneToManyConfig oneToManyConfig)
2376    {
2377      super(type, fieldName);
2378
2379      _field = field;
2380      _fieldName = fieldName;
2381      _fieldType = fieldType;
2382      _oneToManyConfig = oneToManyConfig;
2383    }
2384
2385    void complete()
2386      throws ConfigException
2387    {
2388      getInternalOneToManyConfig(_relatedType.getBeanClass(), _field, _fieldName);
2389      JAnnotation oneToManyAnn = _annotationCfg.getAnnotation();
2390      OneToManyConfig oneToManyConfig = _annotationCfg.getOneToManyConfig();
2391
2392      AmberPersistenceUnit persistenceUnit = _relatedType.getPersistenceUnit();
2393
2394      JType retType;
2395
2396      if (_field instanceof JField)
2397        retType = ((JField) _field).getGenericType();
2398      else
2399        retType = ((JMethod) _field).getGenericReturnType();
2400
2401      JType []typeArgs = retType.getActualTypeArguments();
2402
2403      JClass targetEntity = null;
2404
2405      if (oneToManyAnn != null)
2406        targetEntity = oneToManyAnn.getClass("targetEntity");
2407      else {
2408        String JavaDoc s = oneToManyConfig.getTargetEntity();
2409
2410        if (s != null)
2411          targetEntity = _persistenceUnit.getJClassLoader().forName(s);
2412      }
2413
2414      String JavaDoc targetName = "";
2415
2416      if (targetEntity != null)
2417        targetName = targetEntity.getName();
2418
2419      if (! targetName.equals("") && ! targetName.equals("void")) {
2420      }
2421      else if (typeArgs.length > 0)
2422        targetName = typeArgs[typeArgs.length-1].getName();
2423      else
2424        throw error(_field, L.l("Can't determine targetEntity for {0}. @OneToMany properties must target @Entity beans.",
2425                                _field.getName()));
2426
2427      EntityType targetType = persistenceUnit.getEntity(targetName);
2428      if (targetType == null) {
2429
2430        EntityConfig entityConfig = null;
2431
2432        if (_entityConfigMap != null) {
2433          entityConfig = _entityConfigMap.get(targetName);
2434        }
2435
2436        if (entityConfig == null)
2437          throw error(_field,
2438                      L.l("targetEntity '{0}' is not an @Entity bean for {1}. The targetEntity of a @OneToMany collection must be an @Entity bean.",
2439                          targetName,
2440                          _field.getName()));
2441      }
2442
2443      CascadeType[] cascadeTypes = null;
2444
2445      String JavaDoc mappedBy;
2446
2447      if (oneToManyAnn != null) {
2448        mappedBy = oneToManyAnn.getString("mappedBy");
2449
2450        // XXX: runtime does not cast this
2451
// cascadeType = (CascadeType []) oneToManyAnn.get("cascade");
2452
Object JavaDoc cascade[] = (Object JavaDoc []) oneToManyAnn.get("cascade");
2453
2454        cascadeTypes = new CascadeType[cascade.length];
2455
2456        for (int i=0; i < cascade.length; i++)
2457          cascadeTypes[i] = (CascadeType) cascade[i];
2458      }
2459      else {
2460        mappedBy = oneToManyConfig.getMappedBy();
2461
2462        CascadeConfig cascade = ((OneToManyConfig) oneToManyConfig).getCascade();
2463
2464        if (cascade != null) {
2465          cascadeTypes = cascade.getCascadeTypes();
2466        }
2467      }
2468
2469      if (mappedBy != null && ! mappedBy.equals("")) {
2470        oneToManyBidirectional(targetType, targetName, mappedBy, cascadeTypes);
2471      }
2472      else {
2473        oneToManyUnidirectional(targetType, targetName, cascadeTypes);
2474      }
2475    }
2476
2477    private void oneToManyBidirectional(RelatedType targetType,
2478                                        String JavaDoc targetName,
2479                                        String JavaDoc mappedBy,
2480                                        CascadeType[] cascadeTypes)
2481      throws ConfigException
2482    {
2483      JAnnotation joinTableAnn = _field.getAnnotation(javax.persistence.JoinTable.class);
2484
2485      JoinTableConfig joinTableConfig = null;
2486
2487      if (_oneToManyConfig != null)
2488        joinTableConfig = _oneToManyConfig.getJoinTable();
2489
2490      if ((joinTableAnn != null) || (joinTableConfig != null)) {
2491        throw error(_field,
2492                    L.l("Bidirectional @ManyToOne property {0} may not have a @JoinTable annotation.",
2493                        _field.getName()));
2494      }
2495
2496      EntityManyToOneField sourceField = getSourceField(targetType,
2497                                                        mappedBy,
2498                                                        null);
2499
2500      if (sourceField == null)
2501        throw error(_field, L.l("'{0}' does not have matching field for @ManyToOne(mappedBy={1}).",
2502                                targetType.getName(),
2503                                mappedBy));
2504
2505      JAnnotation orderByAnn = _field.getAnnotation(javax.persistence.OrderBy.class);
2506
2507      String JavaDoc orderBy = null;
2508      ArrayList JavaDoc<String JavaDoc> orderByFields = null;
2509      ArrayList JavaDoc<Boolean JavaDoc> orderByAscending = null;
2510
2511      if (orderByAnn != null) {
2512        orderBy = (String JavaDoc) orderByAnn.get("value");
2513
2514        if (orderBy == null)
2515          orderBy = "";
2516
2517        if ("".equals(orderBy)) {
2518          if (targetType instanceof RelatedType) {
2519            RelatedType targetRelatedType = (RelatedType) targetType;
2520            orderBy = targetRelatedType.getId().generateJavaSelect(null);
2521          }
2522        }
2523
2524        orderByFields = new ArrayList JavaDoc<String JavaDoc>();
2525        orderByAscending = new ArrayList JavaDoc<Boolean JavaDoc>();
2526
2527        int len = orderBy.length();
2528
2529        int i = 0;
2530
2531        while (i < len) {
2532
2533          int index = orderBy.indexOf(",", i);
2534
2535          if (index < 0)
2536            index = len;
2537
2538          String JavaDoc orderByField = orderBy.substring(i, index);
2539
2540          i += index;
2541
2542          // ASC or DESC
2543
index = orderByField.toUpperCase().lastIndexOf("SC");
2544
2545          Boolean JavaDoc asc = Boolean.TRUE;
2546
2547          if (index > 1) {
2548            if (orderByField.charAt(index - 1) != 'E') {
2549              // field ASC or default
2550
if (orderByField.charAt(index - 1) == 'A' &&
2551                  Character.isSpaceChar(orderByField.charAt(index - 2))) {
2552                index -= 2;
2553              }
2554            }
2555            else if (index > 2 &&
2556                     orderByField.charAt(index - 2) == 'D' &&
2557                     Character.isSpaceChar(orderByField.charAt(index - 3))) {
2558
2559                asc = Boolean.FALSE;
2560                index -= 3;
2561            }
2562          }
2563
2564          if (index > 0)
2565            orderByField = orderByField.substring(0, index).trim();
2566
2567          AmberField amberField = targetType.getField(orderByField);
2568
2569          if (amberField == null)
2570            throw error(_field, L.l("'{0}' has no field named '{1}' in @OrderBy",
2571                                    targetType.getName(),
2572                                    orderByField));
2573
2574          /*
2575          if (amberField instanceof PropertyField) {
2576            PropertyField property = (PropertyField) amberField;
2577            orderByField = property.getColumn().getName();
2578          }
2579          */

2580
2581          orderByFields.add(orderByField);
2582          orderByAscending.add(asc);
2583        }
2584      }
2585
2586      EntityOneToManyField oneToMany;
2587
2588      oneToMany = new EntityOneToManyField(_relatedType, _fieldName, cascadeTypes);
2589      oneToMany.setSourceField(sourceField);
2590      oneToMany.setOrderBy(orderByFields, orderByAscending);
2591
2592      getInternalMapKeyConfig(_relatedType.getBeanClass(), _field, _fieldName);
2593      JAnnotation mapKeyAnn = _annotationCfg.getAnnotation();
2594      MapKeyConfig mapKeyConfig = _annotationCfg.getMapKeyConfig();
2595
2596      if (! _annotationCfg.isNull()) {
2597
2598        String JavaDoc key = mapKeyAnn.getString("name");
2599
2600        String JavaDoc getter = "get" +
2601          Character.toUpperCase(key.charAt(0)) + key.substring(1);
2602
2603        JMethod method = targetType.getGetter(getter);
2604
2605        if (method == null) {
2606          throw error(_field,
2607                      L.l("targetEntity '{0}' has no getter for field named '{1}'. Either the @MapKey name or the @OneToMany targetEntity is incorrect.",
2608                          targetName, key));
2609        }
2610
2611        oneToMany.setMapKey(key);
2612      }
2613
2614      _relatedType.addField(oneToMany);
2615    }
2616
2617    private void oneToManyUnidirectional(RelatedType targetType,
2618                                         String JavaDoc targetName,
2619                                         CascadeType[] cascadeTypes)
2620      throws ConfigException
2621    {
2622      EntityManyToManyField manyToManyField;
2623
2624      manyToManyField = new EntityManyToManyField(_relatedType, _fieldName, cascadeTypes);
2625      manyToManyField.setType(targetType);
2626
2627      String JavaDoc sqlTable = _relatedType.getTable().getName() + "_" + targetType.getTable().getName();
2628
2629      JAnnotation joinTableAnn = _field.getAnnotation(javax.persistence.JoinTable.class);
2630
2631      JoinTableConfig joinTableConfig = null;
2632
2633      if (_oneToManyConfig != null)
2634        joinTableConfig = _oneToManyConfig.getJoinTable();
2635
2636      Table mapTable = null;
2637
2638      ArrayList JavaDoc<ForeignColumn> sourceColumns = null;
2639      ArrayList JavaDoc<ForeignColumn> targetColumns = null;
2640
2641      if ((joinTableAnn != null) || (joinTableConfig != null)) {
2642
2643        Object JavaDoc joinColumns[] = null;
2644        Object JavaDoc inverseJoinColumns[] = null;
2645
2646        HashMap JavaDoc<String JavaDoc, JoinColumnConfig> joinColumnsConfig = null;
2647        HashMap JavaDoc<String JavaDoc, JoinColumnConfig> inverseJoinColumnsConfig = null;
2648
2649        if (joinTableAnn != null) {
2650          if (! joinTableAnn.getString("name").equals(""))
2651            sqlTable = joinTableAnn.getString("name");
2652          joinColumns = (Object JavaDoc []) joinTableAnn.get("joinColumns");
2653          inverseJoinColumns = (Object JavaDoc []) joinTableAnn.get("inverseJoinColumns");
2654        }
2655        else {
2656          if (! joinTableConfig.getName().equals(""))
2657            sqlTable = joinTableConfig.getName();
2658          joinColumnsConfig = joinTableConfig.getJoinColumnMap();
2659          inverseJoinColumnsConfig = joinTableConfig.getInverseJoinColumnMap();
2660        }
2661
2662        mapTable = _persistenceUnit.createTable(sqlTable);
2663
2664        sourceColumns = AbstractConfigIntrospector.calculateColumns(_field,
2665                                                                    mapTable,
2666                                                                    _relatedType.getTable().getName() + "_",
2667                                                                    _relatedType,
2668                                                                    joinColumns,
2669                                                                    joinColumnsConfig);
2670
2671        targetColumns = AbstractConfigIntrospector.calculateColumns(_field,
2672                                                                    mapTable,
2673                                                                    targetType.getTable().getName() + "_",
2674                                                                    targetType,
2675                                                                    inverseJoinColumns,
2676                                                                    inverseJoinColumnsConfig);
2677      }
2678      else {
2679        mapTable = _persistenceUnit.createTable(sqlTable);
2680
2681        sourceColumns = AbstractConfigIntrospector.calculateColumns(mapTable,
2682                                                                    _relatedType.getTable().getName() + "_",
2683                                                                    _relatedType);
2684
2685        targetColumns = AbstractConfigIntrospector.calculateColumns(mapTable,
2686                                                                    // jpa/0j40
2687
_fieldName.toUpperCase() + "_",
2688                                                                    targetType);
2689      }
2690
2691      manyToManyField.setAssociationTable(mapTable);
2692      manyToManyField.setTable(sqlTable);
2693
2694      manyToManyField.setSourceLink(new LinkColumns(mapTable,
2695                                                    _relatedType.getTable(),
2696                                                    sourceColumns));
2697
2698      manyToManyField.setTargetLink(new LinkColumns(mapTable,
2699                                                    targetType.getTable(),
2700                                                    targetColumns));
2701
2702      getInternalMapKeyConfig(_relatedType.getBeanClass(), _field, _field.getName());
2703      JAnnotation mapKeyAnn = _annotationCfg.getAnnotation();
2704      MapKeyConfig mapKeyConfig = _annotationCfg.getMapKeyConfig();
2705
2706      if (! _annotationCfg.isNull()) {
2707
2708        String JavaDoc key;
2709
2710        if (mapKeyAnn != null)
2711          key = mapKeyAnn.getString("name");
2712        else
2713          key = mapKeyConfig.getName();
2714
2715        String JavaDoc getter = "get" +
2716          Character.toUpperCase(key.charAt(0)) + key.substring(1);
2717
2718        JMethod method = targetType.getGetter(getter);
2719
2720        if (method == null) {
2721          throw error(_field,
2722                      L.l("targetEntity '{0}' has no getter for field named '{1}'. Either the @MapKey name or the @ManyToMany targetEntity is incorrect.",
2723                          targetName, key));
2724        }
2725
2726        manyToManyField.setMapKey(key);
2727      }
2728
2729      _relatedType.addField(manyToManyField);
2730    }
2731  }
2732
2733  /**
2734   * completes for dependent
2735   */

2736  class OneToOneCompletion extends Completion {
2737    private JAccessibleObject _field;
2738    private String JavaDoc _fieldName;
2739    private JClass _fieldType;
2740
2741    OneToOneCompletion(RelatedType type,
2742                       JAccessibleObject field,
2743                       String JavaDoc fieldName,
2744                       JClass fieldType)
2745    {
2746      super(type, fieldName);
2747
2748      _field = field;
2749      _fieldName = fieldName;
2750      _fieldType = fieldType;
2751    }
2752
2753    String JavaDoc getFieldName()
2754    {
2755      return _fieldName;
2756    }
2757
2758    void complete()
2759      throws ConfigException
2760    {
2761      getInternalOneToOneConfig(_relatedType.getBeanClass(), _field, _fieldName);
2762      JAnnotation oneToOneAnn = _annotationCfg.getAnnotation();
2763      OneToOneConfig oneToOneConfig = _annotationCfg.getOneToOneConfig();
2764
2765      boolean isLazy;
2766
2767      if (oneToOneAnn != null)
2768        isLazy = oneToOneAnn.get("fetch") == FetchType.LAZY;
2769      else
2770        isLazy = oneToOneConfig.getFetch() == FetchType.LAZY;
2771
2772      if (! isLazy) {
2773        if (_relatedType.getBeanClass().getName().equals(_fieldType.getName())) {
2774          throw error(_field, L.l("'{0}': '{1}' is an illegal recursive type for @OneToOne with EAGER fetching. You should specify FetchType.LAZY for this relationship.",
2775                                  _field.getName(),
2776                                  _fieldType.getName()));
2777        }
2778      }
2779
2780      AmberPersistenceUnit persistenceUnit = _relatedType.getPersistenceUnit();
2781
2782      JClass targetEntity = null;
2783      String JavaDoc targetName = "";
2784
2785      if (oneToOneAnn != null) {
2786        targetEntity = oneToOneAnn.getClass("targetEntity");
2787
2788        if (targetEntity != null)
2789          targetEntity.getName();
2790      }
2791      else {
2792        targetName = oneToOneConfig.getTargetEntity();
2793
2794        if (! ((targetName == null) || "".equals(targetName)))
2795          targetEntity = _persistenceUnit.getJClassLoader().forName(targetName);
2796      }
2797
2798      if (targetEntity == null || targetEntity.getName().equals("void"))
2799        targetEntity = _fieldType;
2800
2801      getInternalEntityConfig(targetEntity);
2802      JAnnotation targetEntityAnn = _annotationCfg.getAnnotation();
2803      EntityConfig targetEntityConfig = _annotationCfg.getEntityConfig();
2804
2805      if (_annotationCfg.isNull()) {
2806        throw error(_field, L.l("'{0}' is an illegal targetEntity for {1}. @OneToOne relations must target a valid @Entity.",
2807                                targetEntity.getName(), _field.getName()));
2808      }
2809
2810      if (! _fieldType.isAssignableFrom(targetEntity)) {
2811        throw error(_field, L.l("'{0}' is an illegal targetEntity for {1}. @OneToOne targetEntity must be assignable to the field type '{2}'.",
2812                                targetEntity.getName(),
2813                                _field.getName(),
2814                                _fieldType.getName()));
2815      }
2816
2817      String JavaDoc mappedBy;
2818
2819      if (oneToOneAnn != null)
2820        mappedBy = oneToOneAnn.getString("mappedBy");
2821      else
2822        mappedBy = oneToOneConfig.getMappedBy();
2823
2824      RelatedType targetType = null;
2825
2826      if (targetName != null && ! targetName.equals("")) {
2827        targetType = persistenceUnit.getEntity(targetName);
2828
2829        if (targetType == null)
2830          throw new ConfigException(L.l("{0}: '{1}' is an unknown entity for '{2}'.",
2831                                        _field.getDeclaringClass().getName(),
2832                                        targetName,
2833                                        _field.getName()));
2834      }
2835      else {
2836        targetType = persistenceUnit.getEntity(_field.getReturnType().getName());
2837
2838        if (targetType == null)
2839          throw new ConfigException(L.l("{0} can't determine target name for '{1}'",
2840                                        _field.getDeclaringClass().getName(),
2841                                        _field.getName()));
2842      }
2843
2844      // jpa/0o00, jpa/0o03, jpa/0o06, jpa/0o07, jpa/10ca, jpa/0s2d
2845

2846      // jpa/0o06
2847
boolean isManyToOne = (mappedBy == null) || "".equals(mappedBy);
2848
2849      // jpa/0o07
2850
if (isManyToOne) {
2851
2852        getInternalJoinColumnConfig(_relatedType.getBeanClass(), _field, _fieldName);
2853        JAnnotation joinColumnAnn = _annotationCfg.getAnnotation();
2854        JoinColumnConfig joinColumnConfig = _annotationCfg.getJoinColumnConfig();
2855
2856        if (! _annotationCfg.isNull()) {
2857          // jpa/0o07: DstBean.getParent()
2858
// OK: isManyToOne = true;
2859
}
2860        else {
2861          // jpa/10ca
2862
OneToOneCompletion otherSide
2863            = getSourceCompletion(targetType, mappedBy);
2864
2865          if (otherSide != null) {
2866            getInternalJoinColumnConfig(targetType.getBeanClass(),
2867                                        otherSide._field,
2868                                        otherSide._fieldName);
2869            // jpa/0o07, jpa/0s2d
2870
if (! _annotationCfg.isNull())
2871              isManyToOne = false;
2872          }
2873        }
2874      }
2875
2876      if (isManyToOne) {
2877
2878        addManyToOne(_relatedType, _field, _fieldName, _field.getReturnType());
2879
2880        // XXX: set unique
2881
}
2882      else {
2883
2884        if (! (mappedBy == null || "".equals(mappedBy))) {
2885
2886          // jpa/0o06
2887

2888          OneToOneCompletion otherSide
2889            = getSourceCompletion(targetType, mappedBy);
2890
2891          if (otherSide != null) {
2892            // jpa/0o00
2893
if (_depCompletions.remove(otherSide)) {
2894              otherSide.complete();
2895            }
2896          }
2897        }
2898
2899        // Owner
2900
EntityManyToOneField sourceField
2901          = getSourceField(targetType, mappedBy, _relatedType);
2902
2903        if (sourceField == null)
2904          throw new ConfigException(L.l("{0}: OneToOne target '{1}' does not have a matching ManyToOne relation.",
2905                                        _field.getDeclaringClass().getName(),
2906                                        targetType.getName()));
2907
2908        DependentEntityOneToOneField oneToOne;
2909
2910        oneToOne = new DependentEntityOneToOneField(_relatedType, _fieldName);
2911        oneToOne.setTargetField(sourceField);
2912        sourceField.setTargetField(oneToOne);
2913        oneToOne.setLazy(isLazy);
2914
2915        _relatedType.addField(oneToOne);
2916      }
2917    }
2918  }
2919
2920  /**
2921   * completes for dependent
2922   */

2923  class ManyToManyCompletion extends Completion {
2924    private JAccessibleObject _field;
2925    private String JavaDoc _fieldName;
2926    private JClass _fieldType;
2927
2928    ManyToManyCompletion(RelatedType type,
2929                         JAccessibleObject field,
2930                         String JavaDoc fieldName,
2931                         JClass fieldType)
2932    {
2933      super(type, fieldName);
2934
2935      _field = field;
2936      _fieldName = fieldName;
2937      _fieldType = fieldType;
2938    }
2939
2940    void complete()
2941      throws ConfigException
2942    {
2943      addManyToMany(_relatedType, _field, _fieldName, _fieldType);
2944    }
2945  }
2946
2947  /**
2948   * completes for link
2949   */

2950  class ManyToOneCompletion extends Completion {
2951    private JAccessibleObject _field;
2952    private String JavaDoc _fieldName;
2953    private JClass _fieldType;
2954
2955    ManyToOneCompletion(RelatedType type,
2956                        JAccessibleObject field,
2957                        String JavaDoc fieldName,
2958                        JClass fieldType)
2959    {
2960      super(type, fieldName);
2961
2962      _field = field;
2963      _fieldName = fieldName;
2964      _fieldType = fieldType;
2965    }
2966
2967    void complete()
2968      throws ConfigException
2969    {
2970      addManyToOne(_relatedType, _field, _fieldName, _fieldType);
2971    }
2972  }
2973
2974  /**
2975   * completes for dependent
2976   */

2977  class EmbeddedCompletion extends Completion {
2978    private JAccessibleObject _field;
2979    private String JavaDoc _fieldName;
2980    private JClass _fieldType;
2981    // The same completion is used for both:
2982
// @Embedded or @EmbeddedId
2983
private boolean _embeddedId;
2984
2985    EmbeddedCompletion(RelatedType type,
2986                       JAccessibleObject field,
2987                       String JavaDoc fieldName,
2988                       JClass fieldType,
2989                       boolean embeddedId)
2990    {
2991      super(type, fieldName);
2992
2993      _field = field;
2994      _fieldName = fieldName;
2995      _fieldType = fieldType;
2996      _embeddedId = embeddedId;
2997    }
2998
2999    void complete()
3000      throws ConfigException
3001    {
3002      getInternalAttributeOverrideConfig(_relatedType.getBeanClass(), _field, _fieldName);
3003      JAnnotation attributeOverrideAnn = _annotationCfg.getAnnotation();
3004      AttributeOverrideConfig attributeOverrideConfig = _annotationCfg.getAttributeOverrideConfig();
3005
3006      boolean hasAttributeOverride = ! _annotationCfg.isNull();
3007
3008      JAnnotation attributeOverridesAnn = _field.getAnnotation(AttributeOverrides.class);
3009
3010      boolean hasAttributeOverrides = (attributeOverridesAnn != null);
3011
3012      if (hasAttributeOverride && hasAttributeOverrides) {
3013        throw error(_field, L.l("{0} may not have both @AttributeOverride and @AttributeOverrides",
3014                                _field.getName()));
3015      }
3016
3017      Object JavaDoc attOverridesAnn[] = null;
3018
3019      if (attributeOverrideAnn != null) {
3020        attOverridesAnn = new Object JavaDoc[] { attributeOverrideAnn };
3021      }
3022      else if (attributeOverridesAnn != null) {
3023        attOverridesAnn = (Object JavaDoc []) attributeOverridesAnn.get("value");
3024      }
3025
3026      EntityEmbeddedField embeddedField;
3027
3028      if (_embeddedId) {
3029        embeddedField = _relatedType.getId().getEmbeddedIdField();
3030      } else {
3031        embeddedField = new EntityEmbeddedField(_relatedType, _fieldName);
3032      }
3033
3034      embeddedField.setEmbeddedId(_embeddedId);
3035
3036      embeddedField.setLazy(false);
3037
3038      AmberPersistenceUnit persistenceUnit = _relatedType.getPersistenceUnit();
3039
3040      EmbeddableType type = persistenceUnit.createEmbeddable(_fieldType.getName(), _fieldType);
3041
3042      embeddedField.setType(type);
3043
3044      _relatedType.addField(embeddedField);
3045
3046      // XXX: todo ...
3047
// validateAttributeOverrides(_field, attributeOverridesAnn, type);
3048

3049      Table sourceTable = _relatedType.getTable();
3050
3051      HashMap JavaDoc<String JavaDoc, Column> embeddedColumns = new HashMap JavaDoc<String JavaDoc, Column>();
3052      HashMap JavaDoc<String JavaDoc, String JavaDoc> fieldNameByColumn = new HashMap JavaDoc<String JavaDoc, String JavaDoc>();
3053
3054      ArrayList JavaDoc<AmberField> fields = type.getFields();
3055
3056      for (int i=0; i < fields.size(); i++) {
3057
3058        String JavaDoc embeddedFieldName = fields.get(i).getName();
3059
3060        String JavaDoc columnName = toSqlName(embeddedFieldName);
3061        boolean notNull = false;
3062        boolean unique = false;
3063
3064        if (attOverridesAnn != null) {
3065          for (int j=0; j<attOverridesAnn.length; j++) {
3066
3067            if (embeddedFieldName.equals(((JAnnotation) attOverridesAnn[j]).getString("name"))) {
3068
3069              JAnnotation columnAnn = ((JAnnotation) attOverridesAnn[j]).getAnnotation("column");
3070
3071              if (columnAnn != null) {
3072                columnName = columnAnn.getString("name");
3073                notNull = ! columnAnn.getBoolean("nullable");
3074                unique = columnAnn.getBoolean("unique");
3075              }
3076            }
3077          }
3078        }
3079
3080        Type amberType = _persistenceUnit.createType(fields.get(i).getJavaType().getName());
3081
3082        Column column = sourceTable.createColumn(columnName, amberType);
3083
3084        column.setNotNull(notNull);
3085        column.setUnique(unique);
3086
3087        embeddedColumns.put(columnName, column);
3088        fieldNameByColumn.put(columnName, embeddedFieldName);
3089      }
3090
3091      embeddedField.setEmbeddedColumns(embeddedColumns);
3092      embeddedField.setFieldNameByColumn(fieldNameByColumn);
3093
3094      embeddedField.init();
3095    }
3096  }
3097
3098  /**
3099   * completes for dependent
3100   */

3101  class SqlResultSetMappingCompletion extends Completion {
3102    private String JavaDoc _name;
3103    private Object JavaDoc _entities[];
3104    private Object JavaDoc _columns[];
3105
3106    SqlResultSetMappingCompletion(RelatedType type,
3107                                  String JavaDoc name,
3108                                  Object JavaDoc entities[],
3109                                  Object JavaDoc columns[])
3110    {
3111      super(type);
3112
3113      _name = name;
3114      _entities = entities;
3115      _columns = columns;
3116    }
3117
3118    void complete()
3119      throws ConfigException
3120    {
3121      addSqlResultSetMapping(_name,
3122                             _entities,
3123                             _columns);
3124    }
3125  }
3126
3127  void getInternalEmbeddableConfig(JClass type)
3128  {
3129    _annotationCfg.reset(type, Embeddable.class);
3130
3131    EmbeddableConfig embeddableConfig = null;
3132
3133    if (_embeddableConfigMap != null)
3134      embeddableConfig = _embeddableConfigMap.get(type.getName());
3135
3136    _annotationCfg.setConfig(embeddableConfig);
3137  }
3138
3139  void getInternalEntityConfig(JClass type)
3140  {
3141    _annotationCfg.reset(type, Entity.class);
3142
3143    EntityConfig entityConfig = null;
3144
3145    if (_entityConfigMap != null)
3146      entityConfig = _entityConfigMap.get(type.getName());
3147
3148    _annotationCfg.setConfig(entityConfig);
3149  }
3150
3151  void getInternalMappedSuperclassConfig(JClass type)
3152  {
3153    _annotationCfg.reset(type, MappedSuperclass.class);
3154
3155    if (_mappedSuperclassConfigMap == null)
3156      return;
3157
3158    MappedSuperclassConfig mappedSuperConfig = null;
3159
3160    mappedSuperConfig = _mappedSuperclassConfigMap.get(type.getName());
3161
3162    _annotationCfg.setConfig(mappedSuperConfig);
3163  }
3164
3165  void getInternalEntityListenersConfig(JClass type)
3166  {
3167    _annotationCfg.reset(type, EntityListeners.class);
3168
3169    if (_entityConfigMap == null)
3170      return;
3171
3172    EntityConfig entityConfig;
3173
3174    entityConfig = _entityConfigMap.get(type.getName());
3175
3176    if (entityConfig == null)
3177      return;
3178
3179    _annotationCfg.setConfig(entityConfig.getEntityListeners());
3180  }
3181
3182  void getInternalExcludeDefaultListenersConfig(JClass type)
3183  {
3184    _annotationCfg.reset(type, ExcludeDefaultListeners.class);
3185
3186    if (_entityConfigMap == null)
3187      return;
3188
3189    EntityConfig entityConfig;
3190
3191    entityConfig = _entityConfigMap.get(type.getName());
3192
3193    if (entityConfig == null)
3194      return;
3195
3196    if (entityConfig.getExcludeDefaultListeners())
3197      _annotationCfg.setConfig(entityConfig.getExcludeDefaultListeners());
3198  }
3199
3200  void getInternalExcludeSuperclassListenersConfig(JClass type)
3201  {
3202    _annotationCfg.reset(type, ExcludeSuperclassListeners.class);
3203
3204    if (_entityConfigMap == null)
3205      return;
3206
3207    EntityConfig entityConfig;
3208
3209    entityConfig = _entityConfigMap.get(type.getName());
3210
3211    if (entityConfig == null)
3212      return;
3213
3214    if (entityConfig.getExcludeSuperclassListeners())
3215      _annotationCfg.setConfig(entityConfig.getExcludeSuperclassListeners());
3216  }
3217
3218  void getInternalInheritanceConfig(JClass type)
3219  {
3220    _annotationCfg.reset(type, Inheritance.class);
3221
3222    EntityConfig entityConfig = null;
3223
3224    if (_entityConfigMap != null)
3225      entityConfig = _entityConfigMap.get(type.getName());
3226
3227    if (entityConfig != null) {
3228      _annotationCfg.setConfig(entityConfig.getInheritance());
3229    }
3230  }
3231
3232  void getInternalNamedQueryConfig(JClass type)
3233  {
3234    _annotationCfg.reset(type, NamedQuery.class);
3235
3236    EntityConfig entityConfig = null;
3237
3238    if (_entityConfigMap != null)
3239      entityConfig = _entityConfigMap.get(type.getName());
3240
3241    if (entityConfig != null) {
3242      _annotationCfg.setConfig(entityConfig.getNamedQuery());
3243    }
3244  }
3245
3246  void getInternalNamedNativeQueryConfig(JClass type)
3247  {
3248    _annotationCfg.reset(type, NamedNativeQuery.class);
3249
3250    EntityConfig entityConfig = null;
3251
3252    if (_entityConfigMap != null)
3253      entityConfig = _entityConfigMap.get(type.getName());
3254
3255    if (entityConfig != null) {
3256      _annotationCfg.setConfig(entityConfig.getNamedNativeQuery());
3257    }
3258  }
3259
3260  void getInternalSqlResultSetMappingConfig(JClass type)
3261  {
3262    _annotationCfg.reset(type, SqlResultSetMapping.class);
3263
3264    EntityConfig entityConfig = null;
3265
3266    if (_entityConfigMap != null)
3267      entityConfig = _entityConfigMap.get(type.getName());
3268
3269    if (entityConfig != null) {
3270      _annotationCfg.setConfig(entityConfig.getSqlResultSetMapping());
3271    }
3272  }
3273
3274  void getInternalTableConfig(JClass type)
3275  {
3276    _annotationCfg.reset(type, javax.persistence.Table.class);
3277
3278    EntityConfig entityConfig = null;
3279
3280    if (_entityConfigMap != null)
3281      entityConfig = _entityConfigMap.get(type.getName());
3282
3283    if (entityConfig != null) {
3284      _annotationCfg.setConfig(entityConfig.getTable());
3285    }
3286  }
3287
3288  void getInternalSecondaryTableConfig(JClass type)
3289  {
3290    _annotationCfg.reset(type, SecondaryTable.class);
3291
3292    EntityConfig entityConfig = null;
3293
3294    if (_entityConfigMap != null)
3295      entityConfig = _entityConfigMap.get(type.getName());
3296
3297    if (entityConfig != null) {
3298      _annotationCfg.setConfig(entityConfig.getSecondaryTable());
3299    }
3300  }
3301
3302  void getInternalIdClassConfig(JClass type)
3303  {
3304    _annotationCfg.reset(type, IdClass.class);
3305
3306    EntityConfig entityConfig = null;
3307
3308    if (_entityConfigMap != null)
3309      entityConfig = _entityConfigMap.get(type.getName());
3310
3311    if (entityConfig != null) {
3312      _annotationCfg.setConfig(entityConfig.getIdClass());
3313    }
3314  }
3315
3316  void getInternalPrimaryKeyJoinColumnConfig(JClass type)
3317  {
3318    _annotationCfg.reset(type, PrimaryKeyJoinColumn.class);
3319
3320    EntityConfig entityConfig = null;
3321
3322    if (_entityConfigMap != null)
3323      entityConfig = _entityConfigMap.get(type.getName());
3324
3325    if (entityConfig != null) {
3326      _annotationCfg.setConfig(entityConfig.getPrimaryKeyJoinColumn());
3327    }
3328  }
3329
3330  void getInternalDiscriminatorColumnConfig(JClass type)
3331  {
3332    _annotationCfg.reset(type, DiscriminatorColumn.class);
3333
3334    EntityConfig entityConfig = null;
3335
3336    if (_entityConfigMap != null)
3337      entityConfig = _entityConfigMap.get(type.getName());
3338
3339    if (entityConfig != null) {
3340      _annotationCfg.setConfig(entityConfig.getDiscriminatorColumn());
3341    }
3342  }
3343
3344  void getInternalOneToOneConfig(JClass type,
3345                                 JAccessibleObject field,
3346                                 String JavaDoc fieldName)
3347  {
3348    _annotationCfg.reset(field, OneToOne.class);
3349
3350    EntityConfig entityConfig = null;
3351
3352    if (_entityConfigMap != null)
3353      entityConfig = _entityConfigMap.get(type.getName());
3354
3355    if (entityConfig != null) {
3356
3357      AttributesConfig attributes = entityConfig.getAttributes();
3358
3359      if (attributes != null) {
3360        OneToOneConfig oneToOne = attributes.getOneToOne(fieldName);
3361
3362        _annotationCfg.setConfig(oneToOne);
3363      }
3364    }
3365  }
3366
3367  void getInternalOneToManyConfig(JClass type,
3368                                  JAccessibleObject field,
3369                                  String JavaDoc fieldName)
3370  {
3371    _annotationCfg.reset(field, OneToMany.class);
3372
3373    EntityConfig entityConfig = null;
3374
3375    if (_entityConfigMap != null)
3376      entityConfig = _entityConfigMap.get(type.getName());
3377
3378    if (entityConfig != null) {
3379
3380      AttributesConfig attributes = entityConfig.getAttributes();
3381
3382      if (attributes != null) {
3383        OneToManyConfig oneToMany = attributes.getOneToMany(fieldName);
3384
3385        _annotationCfg.setConfig(oneToMany);
3386      }
3387    }
3388  }
3389
3390  void getInternalManyToOneConfig(JClass type,
3391                                  JAccessibleObject field,
3392                                  String JavaDoc fieldName)
3393  {
3394    _annotationCfg.reset(field, ManyToOne.class);
3395
3396    EntityConfig entityConfig = null;
3397
3398    if (_entityConfigMap != null)
3399      entityConfig = _entityConfigMap.get(type.getName());
3400
3401    if (entityConfig != null) {
3402
3403      AttributesConfig attributes = entityConfig.getAttributes();
3404
3405      if (attributes != null) {
3406        ManyToOneConfig manyToOne = attributes.getManyToOne(fieldName);
3407
3408        _annotationCfg.setConfig(manyToOne);
3409      }
3410    }
3411  }
3412
3413  void getInternalManyToManyConfig(JClass type,
3414                                   JAccessibleObject field,
3415                                   String JavaDoc fieldName)
3416  {
3417    _annotationCfg.reset(field, ManyToMany.class);
3418
3419    EntityConfig entityConfig = null;
3420
3421    if (_entityConfigMap != null)
3422      entityConfig = _entityConfigMap.get(type.getName());
3423
3424    if (entityConfig != null) {
3425
3426      AttributesConfig attributes = entityConfig.getAttributes();
3427
3428      if (attributes != null) {
3429        ManyToManyConfig manyToMany = attributes.getManyToMany(fieldName);
3430
3431        _annotationCfg.setConfig(manyToMany);
3432      }
3433    }
3434  }
3435
3436  void getInternalIdConfig(JClass type,
3437                           JAccessibleObject method,
3438                           String JavaDoc fieldName)
3439  {
3440    _annotationCfg.reset(method, javax.persistence.Id.class);
3441
3442    EntityConfig entityConfig = null;
3443
3444    if (_entityConfigMap != null)
3445      entityConfig = _entityConfigMap.get(type.getName());
3446
3447    if (entityConfig != null) {
3448
3449      AttributesConfig attributes = entityConfig.getAttributes();
3450
3451      if (attributes != null) {
3452        IdConfig id = attributes.getId(fieldName);
3453
3454        _annotationCfg.setConfig(id);
3455      }
3456    }
3457  }
3458
3459  void getInternalCallbackConfig(int callback,
3460                                 JClass type,
3461                                 JAccessibleObject method,
3462                                 String JavaDoc fieldName)
3463  {
3464    _annotationCfg.reset(method, ListenerType.CALLBACK_CLASS[callback]);
3465
3466    if (_entityConfigMap == null)
3467      return;
3468
3469    EntityConfig entityConfig;
3470
3471    entityConfig = _entityConfigMap.get(type.getName());
3472
3473    if (entityConfig == null)
3474      return;
3475
3476    AbstractListenerConfig callbackConfig;
3477
3478    switch (callback) {
3479    case Listener.PRE_PERSIST:
3480      callbackConfig = entityConfig.getPrePersist();
3481      break;
3482    case Listener.POST_PERSIST:
3483      callbackConfig = entityConfig.getPostPersist();
3484      break;
3485    case Listener.PRE_REMOVE:
3486      callbackConfig = entityConfig.getPreRemove();
3487      break;
3488    case Listener.POST_REMOVE:
3489      callbackConfig = entityConfig.getPostRemove();
3490      break;
3491    case Listener.PRE_UPDATE:
3492      callbackConfig = entityConfig.getPreUpdate();
3493      break;
3494    case Listener.POST_UPDATE:
3495      callbackConfig = entityConfig.getPostUpdate();
3496      break;
3497    case Listener.POST_LOAD:
3498      callbackConfig = entityConfig.getPostLoad();
3499      break;
3500    default:
3501      return;
3502    }
3503
3504    if (callbackConfig == null)
3505      return;
3506
3507    if (callbackConfig.getMethodName().equals(method.getName()))
3508      _annotationCfg.setConfig(callbackConfig);
3509  }
3510
3511  void getInternalEmbeddedIdConfig(JClass type,
3512                                   JAccessibleObject method,
3513                                   String JavaDoc fieldName)
3514  {
3515    _annotationCfg.reset(method, EmbeddedId.class);
3516  }
3517
3518  void getInternalVersionConfig(JClass type,
3519                                JAccessibleObject method,
3520                                String JavaDoc fieldName)
3521  {
3522    _annotationCfg.reset(method, Version.class);
3523  }
3524
3525  void getInternalJoinColumnConfig(JClass type,
3526                                   JAccessibleObject field,
3527                                   String JavaDoc fieldName)
3528  {
3529    _annotationCfg.reset(field, JoinColumn.class);
3530  }
3531
3532  void getInternalJoinTableConfig(JClass type,
3533                                  JAccessibleObject field,
3534                                  String JavaDoc fieldName)
3535  {
3536    _annotationCfg.reset(field, JoinTable.class);
3537  }
3538
3539  void getInternalMapKeyConfig(JClass type,
3540                               JAccessibleObject field,
3541                               String JavaDoc fieldName)
3542  {
3543    _annotationCfg.reset(field, MapKey.class);
3544  }
3545
3546  void getInternalAttributeOverrideConfig(JClass type,
3547                                          JAccessibleObject field,
3548                                          String JavaDoc fieldName)
3549  {
3550    _annotationCfg.reset(field, AttributeOverride.class);
3551  }
3552
3553  void getInternalAttributeOverrideConfig(JClass type)
3554  {
3555    _annotationCfg.reset(type, AttributeOverride.class);
3556  }
3557}
3558
Popular Tags