KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > oracle > toplink > essentials > internal > ejb > cmp3 > metadata > accessors > ClassAccessor


1 /*
2  * The contents of this file are subject to the terms
3  * of the Common Development and Distribution License
4  * (the "License"). You may not use this file except
5  * in compliance with the License.
6  *
7  * You can obtain a copy of the license at
8  * glassfish/bootstrap/legal/CDDLv1.0.txt or
9  * https://glassfish.dev.java.net/public/CDDLv1.0.html.
10  * See the License for the specific language governing
11  * permissions and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL
14  * HEADER in each file and include the License file at
15  * glassfish/bootstrap/legal/CDDLv1.0.txt. If applicable,
16  * add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your
18  * own identifying information: Portions Copyright [yyyy]
19  * [name of copyright owner]
20  */

21 // Copyright (c) 1998, 2006, Oracle. All rights reserved.
22
package oracle.toplink.essentials.internal.ejb.cmp3.metadata.accessors;
23
24 import java.lang.reflect.AnnotatedElement JavaDoc;
25 import java.lang.reflect.Field JavaDoc;
26 import java.lang.reflect.Method JavaDoc;
27 import java.lang.reflect.Modifier JavaDoc;
28
29 import java.util.ArrayList JavaDoc;
30 import java.util.List JavaDoc;
31 import java.util.Map JavaDoc;
32
33 import javax.persistence.AssociationOverride;
34 import javax.persistence.AssociationOverrides;
35 import javax.persistence.AttributeOverride;
36 import javax.persistence.AttributeOverrides;
37 import javax.persistence.DiscriminatorColumn;
38 import javax.persistence.DiscriminatorValue;
39 import javax.persistence.Entity;
40 import javax.persistence.EntityListeners;
41 import javax.persistence.ExcludeDefaultListeners;
42 import javax.persistence.ExcludeSuperclassListeners;
43 import javax.persistence.IdClass;
44 import javax.persistence.Inheritance;
45 import javax.persistence.InheritanceType;
46 import javax.persistence.JoinColumn;
47 import javax.persistence.MappedSuperclass;
48 import javax.persistence.NamedNativeQueries;
49 import javax.persistence.NamedNativeQuery;
50 import javax.persistence.NamedQueries;
51 import javax.persistence.NamedQuery;
52 import javax.persistence.PostLoad;
53 import javax.persistence.PostPersist;
54 import javax.persistence.PostRemove;
55 import javax.persistence.PostUpdate;
56 import javax.persistence.PrePersist;
57 import javax.persistence.PreRemove;
58 import javax.persistence.PreUpdate;
59 import javax.persistence.SecondaryTable;
60 import javax.persistence.SecondaryTables;
61 import javax.persistence.SqlResultSetMapping;
62 import javax.persistence.SqlResultSetMappings;
63 import javax.persistence.Table;
64 import javax.persistence.Transient;
65
66 import oracle.toplink.essentials.descriptors.ClassDescriptor;
67
68 // WIP shouldn't be here
69
import oracle.toplink.essentials.exceptions.ValidationException;
70
71 import oracle.toplink.essentials.internal.ejb.cmp3.metadata.accessors.MetadataAccessor;
72
73 import oracle.toplink.essentials.internal.ejb.cmp3.metadata.accessors.objects.MetadataAccessibleObject;
74 import oracle.toplink.essentials.internal.ejb.cmp3.metadata.accessors.objects.MetadataClass;
75 import oracle.toplink.essentials.internal.ejb.cmp3.metadata.accessors.objects.MetadataField;
76 import oracle.toplink.essentials.internal.ejb.cmp3.metadata.accessors.objects.MetadataMethod;
77
78 import oracle.toplink.essentials.internal.ejb.cmp3.metadata.columns.MetadataColumn;
79 import oracle.toplink.essentials.internal.ejb.cmp3.metadata.columns.MetadataDiscriminatorColumn;
80 import oracle.toplink.essentials.internal.ejb.cmp3.metadata.columns.MetadataJoinColumn;
81 import oracle.toplink.essentials.internal.ejb.cmp3.metadata.columns.MetadataJoinColumns;
82 import oracle.toplink.essentials.internal.ejb.cmp3.metadata.columns.MetadataPrimaryKeyJoinColumn;
83 import oracle.toplink.essentials.internal.ejb.cmp3.metadata.columns.MetadataPrimaryKeyJoinColumns;
84
85 import oracle.toplink.essentials.internal.ejb.cmp3.metadata.listeners.MetadataEntityClassListener;
86 import oracle.toplink.essentials.internal.ejb.cmp3.metadata.listeners.MetadataEntityListener;
87
88 import oracle.toplink.essentials.internal.ejb.cmp3.metadata.MetadataHelper;
89 import oracle.toplink.essentials.internal.ejb.cmp3.metadata.MetadataConstants;
90 import oracle.toplink.essentials.internal.ejb.cmp3.metadata.MetadataProcessor;
91 import oracle.toplink.essentials.internal.ejb.cmp3.metadata.MetadataDescriptor;
92
93 import oracle.toplink.essentials.internal.ejb.cmp3.metadata.queries.MetadataEntityResult;
94 import oracle.toplink.essentials.internal.ejb.cmp3.metadata.queries.MetadataFieldResult;
95 import oracle.toplink.essentials.internal.ejb.cmp3.metadata.queries.MetadataNamedNativeQuery;
96 import oracle.toplink.essentials.internal.ejb.cmp3.metadata.queries.MetadataNamedQuery;
97 import oracle.toplink.essentials.internal.ejb.cmp3.metadata.queries.MetadataSQLResultSetMapping;
98
99 import oracle.toplink.essentials.internal.ejb.cmp3.metadata.tables.MetadataSecondaryTable;
100 import oracle.toplink.essentials.internal.ejb.cmp3.metadata.tables.MetadataTable;
101
102 import oracle.toplink.essentials.internal.ejb.cmp3.xml.accessors.XMLMappedSuperclassAccessor;
103 import oracle.toplink.essentials.internal.ejb.cmp3.xml.listeners.XMLEntityListener;
104 import oracle.toplink.essentials.internal.ejb.cmp3.xml.XMLConstants;
105 import oracle.toplink.essentials.internal.ejb.cmp3.xml.XMLHelper;
106
107 import oracle.toplink.essentials.internal.helper.DatabaseField;
108 import oracle.toplink.essentials.internal.helper.DatabaseTable;
109 import oracle.toplink.essentials.internal.helper.Helper;
110
111 import oracle.toplink.essentials.queryframework.ColumnResult;
112 import oracle.toplink.essentials.queryframework.EntityResult;
113 import oracle.toplink.essentials.queryframework.FieldResult;
114
115 import org.w3c.dom.Node JavaDoc;
116 import org.w3c.dom.NodeList JavaDoc;
117
118 /**
119  * A class accessor.
120  *
121  * @author Guy Pelletier
122  * @since TopLink EJB 3.0 Reference Implementation
123  */

124 public class ClassAccessor extends NonRelationshipAccessor {
125     protected Class JavaDoc m_inheritanceRootClass;
126     protected Boolean JavaDoc m_isInheritanceSubclass;
127     protected List JavaDoc<ClassAccessor> m_mappedSuperclasses;
128     
129     /**
130      * INTERNAL:
131      */

132     public ClassAccessor(MetadataAccessibleObject accessibleObject, MetadataProcessor processor, MetadataDescriptor descriptor) {
133         super(accessibleObject, processor, descriptor);
134     }
135     
136     /**
137      * INTERNAL:
138      * Add multiple fields to the descriptor. Called from either @Inheritance
139      * or @SecondaryTable context.
140      */

141     protected void addMultipleTableKeyFields(MetadataPrimaryKeyJoinColumns primaryKeyJoinColumns, String JavaDoc PK_CTX, String JavaDoc FK_CTX) {
142         // ProcessPrimaryKeyJoinColumns will validate the primary key join
143
// columns passed in and will return a list of
144
// MetadataPrimaryKeyJoinColumn.
145
for (MetadataPrimaryKeyJoinColumn primaryKeyJoinColumn : processPrimaryKeyJoinColumns(primaryKeyJoinColumns)) {
146             // In an inheritance case this call will return the pk field on the
147
// root class of the inheritance hierarchy. Otherwise in a secondary
148
// table case it's the primary key field name off our own descriptor.
149
String JavaDoc defaultPKFieldName = m_descriptor.getPrimaryKeyFieldName();
150
151             DatabaseField pkField = primaryKeyJoinColumn.getPrimaryKeyField();
152             pkField.setName(getName(pkField, defaultPKFieldName, PK_CTX));
153
154             DatabaseField fkField = primaryKeyJoinColumn.getForeignKeyField();
155             fkField.setName(getName(fkField, pkField.getName(), FK_CTX));
156         
157             if (fkField.getName().equals(pkField.getName())) {
158                 // Add a multiple table primary key to the descriptor.
159
m_descriptor.addMultipleTablePrimaryKeyField(pkField, fkField);
160             } else {
161                 // Add a multiple table foreign key to the descriptor.
162
m_descriptor.addMultipleTableForeignKeyField(pkField, fkField);
163             }
164         }
165     }
166     
167     /**
168      * INTERNAL:
169      * Create and return the appropriate accessor based on the accessible
170      * object given.
171      */

172     protected MetadataAccessor buildAccessor(MetadataAccessibleObject accessibleObject) {
173         MetadataAccessor accessor = m_descriptor.getAccessorFor(accessibleObject.getAttributeName());
174         
175         if (accessor == null) {
176             if (MetadataHelper.isEmbeddedId(accessibleObject, m_descriptor)) {
177                 return new EmbeddedAccessor(accessibleObject, this, true);
178             } else if (MetadataHelper.isEmbedded(accessibleObject, m_descriptor)) {
179                 return new EmbeddedAccessor(accessibleObject, this, false);
180             } else if (MetadataHelper.isManyToMany(accessibleObject, m_descriptor)) {
181                 return new ManyToManyAccessor(accessibleObject, this);
182             } else if (MetadataHelper.isManyToOne(accessibleObject, m_descriptor)) {
183                 return new ManyToOneAccessor(accessibleObject, this);
184             } else if (MetadataHelper.isOneToMany(accessibleObject, m_logger, m_descriptor)) {
185                 return new OneToManyAccessor(accessibleObject, this);
186             } else if (MetadataHelper.isOneToOne(accessibleObject, m_project, m_logger, m_descriptor)) {
187                 return new OneToOneAccessor(accessibleObject, this);
188             } else {
189                 // Default case (everything else currently falls into this)
190
return new BasicAccessor(accessibleObject, this);
191             }
192         } else {
193             return accessor;
194         }
195     }
196     
197     /**
198      * INTERNAL:
199      * Clear the mapped supeclasses. Do this after the class loader has changed.
200      * The list of mapped superclasses is lazily initialized.
201      */

202     public void clearMappedSuperclasses() {
203         m_mappedSuperclasses = null;
204     }
205     
206     /**
207      * INTERNAL: (Overridden in XMLClassAccessor)
208      * Return the discriminator value for this accessor.
209      */

210     public String JavaDoc getDiscriminatorValue() {
211         DiscriminatorValue discriminatorValue = getAnnotation(DiscriminatorValue.class);
212         
213         if (discriminatorValue == null) {
214             return null;
215         } else {
216             return discriminatorValue.value();
217         }
218     }
219     
220     /**
221      * INTERNAL: (Overridden in XMLClassAccessor)
222      * Return the name of this entity class.
223      */

224     public String JavaDoc getEntityName() {
225         Entity entity = getAnnotation(Entity.class);
226         return (entity == null) ? "" : entity.name();
227     }
228     
229     /**
230      * INTERNAL: (Overridden in XMLClassAccessor)
231      */

232     protected Class JavaDoc getIdClass() {
233         IdClass idClass = getAnnotation(IdClass.class);
234         return (idClass == null) ? null : idClass.value();
235     }
236     
237     /**
238      * INTERNAL:
239      * You should call isInheritanceSubclass before calling this method,
240      * otherwise you risk extra processing trying to figure out a root class.
241      * That is, the class traversal will be done everytime you call this method
242      * on a class that is actually not an inheritance subclass.
243      */

244     public Class JavaDoc getInheritanceRootClass() {
245         if (m_inheritanceRootClass == null) {
246             Class JavaDoc lastParent = null;
247             Class JavaDoc parent = getJavaClass().getSuperclass();
248         
249             while (parent != Object JavaDoc.class) {
250                 if (hasInheritanceTag(parent) || m_project.containsDescriptor(parent)) {
251                     lastParent = parent;
252                 }
253                 
254                 parent = parent.getSuperclass();
255             }
256         
257             // Finally set whatever we found as the inheritance root class.
258
// Which may be null.
259
m_inheritanceRootClass = lastParent;
260         }
261   
262         return m_inheritanceRootClass;
263     }
264     
265     /**
266      * INTERNAL:
267      * Store the descriptor metadata for the root of our inheritance hierarchy.
268      */

269     public MetadataDescriptor getInheritanceRootDescriptor() {
270         return m_project.getDescriptor(getInheritanceRootClass());
271     }
272     
273     /**
274      * INTERNAL: (Overridden in XMLClassAccessor)
275      * Return the inheritance strategy. This method should only be called
276      * on the root of the inheritance hierarchy.
277      */

278     protected String JavaDoc getInheritanceStrategy() {
279         Inheritance inheritance = getAnnotation(Inheritance.class);
280         
281         if (inheritance == null) {
282             return "";
283         } else {
284             return inheritance.strategy().name();
285         }
286     }
287     
288     /**
289      * INTERNAL: (OVERRIDE)
290      * Return the java class that defines this accessor. It may be an
291      * entity, embeddable or mapped superclass.
292      */

293     public Class JavaDoc getJavaClass() {
294         return (Class JavaDoc) getAnnotatedElement();
295     }
296     
297     /**
298      * INTERNAL:
299      * Build a list of classes that are decorated with a @MappedSuperclass.
300      */

301     public List JavaDoc<ClassAccessor> getMappedSuperclasses() {
302         if (m_mappedSuperclasses == null) {
303             m_mappedSuperclasses = new ArrayList JavaDoc<ClassAccessor>();
304             
305             Class JavaDoc parent = getJavaClass().getSuperclass();
306         
307             while (parent != Object JavaDoc.class) {
308                 if (m_project.hasMappedSuperclass(parent)) {
309                     Node JavaDoc node = m_project.getMappedSuperclassNode(parent);
310                     XMLHelper helper = m_project.getMappedSuperclassHelper(parent);
311                     m_mappedSuperclasses.add(new XMLMappedSuperclassAccessor(new MetadataClass(parent), node, helper, m_processor, m_descriptor));
312                 } else if (isAnnotationPresent(MappedSuperclass.class, parent)) {
313                     m_mappedSuperclasses.add(new MappedSuperclassAccessor(new MetadataClass(parent), m_processor, m_descriptor));
314                 }
315                 
316                 parent = parent.getSuperclass();
317             }
318         }
319         
320         return m_mappedSuperclasses;
321     }
322     
323     /**
324      * INTERNAL: (Overridden in XMLClassAccessor)
325      */

326     protected boolean hasEntityTag(Class JavaDoc cls) {
327         return isAnnotationPresent(Entity.class, cls);
328     }
329     
330     /**
331      * INTERNAL: (Overridden in XMLClassAccessor)
332      * Return true if this class has an @Inheritance.
333      */

334     protected boolean hasInheritanceTag(Class JavaDoc entityClass) {
335         return isAnnotationPresent(Inheritance.class, entityClass);
336     }
337     
338     /**
339      * INTERNAL:
340      */

341      public boolean isClass() {
342         return true;
343      }
344      
345     /**
346      * INTERNAL:
347      */

348     public boolean isInheritanceSubclass() {
349         if (m_isInheritanceSubclass == null) {
350             m_isInheritanceSubclass = new Boolean JavaDoc(getInheritanceRootClass() != null);
351         }
352         
353         return m_isInheritanceSubclass;
354     }
355      
356      /**
357      * INTERNAL:
358      */

359     protected boolean isTransient(AnnotatedElement JavaDoc annotatedElement, int modifier) {
360         if (isAnnotationPresent(Transient.class, annotatedElement)) {
361             if (MetadataHelper.getDeclaredAnnotationsCount(annotatedElement, m_descriptor) > 1) {
362                 m_validator.throwMappingAnnotationsAppliedToTransientAttribute(annotatedElement);
363             }
364             
365             return true;
366         } else if (Modifier.isTransient(modifier)) {
367             if (MetadataHelper.getDeclaredAnnotationsCount(annotatedElement, m_descriptor) > 0) {
368                 m_validator.throwMappingAnnotationsAppliedToTransientAttribute(annotatedElement);
369             }
370             
371             return true;
372         }
373         
374         return false;
375     }
376
377     /**
378      * INTERNAL:
379      * Return true is this annotated element is not marked transient, static or
380      * abstract.
381      */

382     protected boolean isValidPersistenceElement(AnnotatedElement JavaDoc annotatedElement, int modifiers) {
383         return ! (isTransient(annotatedElement, modifiers) || Modifier.isStatic(modifiers) || Modifier.isAbstract(modifiers));
384     }
385     
386     /**
387      * INTERNAL:
388      * Check to see if this is a valid field to process for persistence. It is
389      * valid if it is not static, transient or has a @Transient specified.
390      */

391     protected boolean isValidPersistenceField(Field JavaDoc field) {
392         return (isValidPersistenceElement(field, field.getModifiers()));
393     }
394     
395     /**
396      * INTERNAL:
397      * Check to see if this is a valid method to process for persistence. It is
398      * valid if it is not static, transient or has a @Transient specified.
399      */

400     protected boolean isValidPersistenceMethod(Method JavaDoc method) {
401         // Ignore methods marked transient, static or abstract.
402
if (isValidPersistenceElement(method, method.getModifiers())) {
403             // Look for methods that begin with "get" or "is", ignore all others.
404
String JavaDoc methodName = method.getName();
405             if (MetadataHelper.isValidPersistenceMethodName(methodName)) {
406                 // Ignore get methods with parameters.
407
if (method.getParameterTypes().length > 0) {
408                     return false;
409                 }
410             
411                 Method JavaDoc setMethod = MetadataHelper.getSetMethod(method, getJavaClass());
412             
413                 if (setMethod == null) {
414                     if (MetadataHelper.getDeclaredAnnotationsCount(method, m_descriptor) > 0) {
415                         // We decorated the property with annotations, but have
416
// no corresponding setter property.
417
m_validator.throwNoCorrespondingSetterMethodDefined(getJavaClass(), method);
418                     }
419                     
420                     // WIP
421
//m_logger.logWarningMessage(m_logger.IGNORE_GET_METHOD, m_descriptor, method);
422
} else {
423                     return true;
424                 }
425             }
426         }
427         
428         return false;
429     }
430     
431     /**
432      * INTERNAL:
433      * Process the items of interest on an entity class. The order of
434      * processing is important, care must be taken if changes must be made.
435      *
436      * Classes without an @Entity are ignored if no metadata complete flag
437      * is set.
438      */

439     public void process() {
440         if (hasEntityTag(getJavaClass())) {
441             // This accessor represents an @Entity class.
442

443             // Set the ignore flags for items that are already defined.
444
m_descriptor.setIgnoreFlags();
445             
446             // Process the @Entity.
447
processEntity();
448             
449             // Process the common class level attributes that an entity or
450
// mapped superclass may define.
451
processClass();
452             
453             // Process the @Table and @Inheritance.
454
processTableAndInheritance();
455                 
456             // Process the @MappedSuperclass(es).
457
processMappedSuperclasses();
458                     
459             // Process the accessors on this entity.
460
processAccessors();
461             
462             // Validate we found a primary key.
463
validatePrimaryKey();
464                     
465             // Process the @SecondaryTable(s).
466
processSecondaryTables();
467         } else {
468             // This accessor represents an @Embeddable class
469
m_descriptor.setDescriptorIsEmbeddable();
470             
471             // Process the accessors on this embeddable.
472
processAccessors();
473         }
474     }
475     
476     /**
477      * INTERNAL:
478      * Process an accessor method or field. Relationship accessors will be
479      * stored for later processing.
480      */

481     protected void processAccessor(MetadataAccessor accessor) {
482         if (! accessor.isProcessed()) {
483             // Store the accessor for later retrieval.
484
m_descriptor.addAccessor(accessor);
485         
486             if (accessor.isRelationship()) {
487                 // Store the relationship accessors for later processing.
488
m_project.addRelationshipDescriptor(m_descriptor);
489             } else {
490                 accessor.process();
491                 accessor.setIsProcessed();
492             }
493         }
494     }
495     
496     /**
497      * INTERNAL:
498      * Create mappings from the fields directly.
499      */

500     protected void processAccessorFields() {
501         for (Field JavaDoc field : MetadataHelper.getFields(getJavaClass())) {
502             if (isValidPersistenceField(field)) {
503                 processAccessor(buildAccessor(new MetadataField(field)));
504             }
505         }
506     }
507     
508     /**
509      * INTERNAL:
510      * Create mappings via the class properties.
511      */

512     protected void processAccessorMethods() {
513         for (Method JavaDoc method : MetadataHelper.getDeclaredMethods(getJavaClass())) {
514             if (isValidPersistenceMethod(method)) {
515                 processAccessor(buildAccessor(new MetadataMethod(method)));
516             }
517         }
518     }
519     
520     /**
521      * INTERNAL:
522      * Process the accessors for the given class.
523      */

524     protected void processAccessors() {
525         // Process the fields or methods on the class.
526
if (m_descriptor.usesPropertyAccess()) {
527             processAccessorMethods();
528         } else {
529             processAccessorFields();
530         }
531     }
532     
533     /**
534      * INTERNAL:
535      * Process an @AssociationOverride for an Entity (or MappedSuperclass)
536      * that inherits from a MappedSuperclass.
537      */

538     protected void processAssociationOverride(String JavaDoc attributeName, MetadataJoinColumns joinColumns) {
539         // Add association overrides from XML as we find them.
540
if (joinColumns.loadedFromXML()) {
541             // WIP - what about any defaulting?
542
m_descriptor.addAssociationOverride(attributeName, joinColumns);
543         } else {
544             // Association override from annotations should not override those
545
// loaded from XML.
546
MetadataJoinColumns existingJoinColumns = m_descriptor.getAssociationOverrideFor(attributeName);
547             
548             if (existingJoinColumns == null || ! existingJoinColumns.loadedFromXML()) {
549                 // WIP - what about any defaulting?
550
m_descriptor.addAssociationOverride(attributeName, joinColumns);
551             } else {
552                 // WIP should log a warning.
553
}
554         }
555     }
556     
557     /**
558      * INTERNAL: (Overriden in XMLClassAccessor)
559      * Process an @AssociationOverrides for an Entity (or MappedSuperclass)
560      * that inherits from a MappedSuperclass.
561      *
562      * It will also look for an @AssociationOverride.
563      */

564     protected void processAssociationOverrides() {
565         // Look for an @AssociationOverrides.
566
AssociationOverrides associationOverrides = getAnnotation(AssociationOverrides.class);
567         if (associationOverrides != null) {
568             for (AssociationOverride associationOverride : associationOverrides.value()) {
569                 processAssociationOverride(associationOverride.name(), new MetadataJoinColumns(associationOverride.joinColumns()));
570             }
571         }
572         
573         // Look for an @AssociationOverride.
574
AssociationOverride associationOverride = getAnnotation(AssociationOverride.class);
575         if (associationOverride != null) {
576             processAssociationOverride(associationOverride.name(), new MetadataJoinColumns(associationOverride.joinColumns()));
577         }
578     }
579     
580     /**
581      * INTERNAL:
582      * Process the @AttributeOverrides and @AttributeOverride for an Entity (or
583      * MappedSuperclass) that inherits from a MappedSuperclass.
584      */

585     protected void processAttributeOverride(MetadataColumn column) {
586         String JavaDoc attributeName = column.getAttributeName();
587         
588         // Add attribute overrides from XML as we find them.
589
if (column.loadedFromXML()) {
590             m_descriptor.addAttributeOverride(column);
591         } else {
592             // Attribute overrides from annotations should not override
593
// those loaded from XML.
594
MetadataColumn existingColumn = m_descriptor.getAttributeOverrideFor(attributeName);
595             
596             if (existingColumn == null || ! existingColumn.loadedFromXML()) {
597                 m_descriptor.addAttributeOverride(column);
598             } else {
599                 // WIP should log a warning.
600
}
601         }
602     }
603     
604     /**
605      * INTERNAL: (Overridden in XMLClassAccessor)
606      * Process the @AttributeOverrides and @AttributeOverride for an Entity (or
607      * MappedSuperclass) that inherits from a MappedSuperclass.
608      */

609     protected void processAttributeOverrides() {
610         // Look for an @AttributeOverrides.
611
AttributeOverrides attributeOverrides = getAnnotation(AttributeOverrides.class);
612         if (attributeOverrides != null) {
613             for (AttributeOverride attributeOverride : attributeOverrides.value()) {
614                 processAttributeOverride(new MetadataColumn(attributeOverride, getAnnotatedElement()));
615             }
616         }
617         
618         // Look for an @AttributeOverride.
619
AttributeOverride attributeOverride = getAnnotation(AttributeOverride.class);
620         if (attributeOverride != null) {
621             processAttributeOverride(new MetadataColumn(attributeOverride, getAnnotatedElement()));
622         }
623     }
624     
625     /**
626      * INTERNAL:
627      * Process the array of methods for lifecyle callback events and set them
628      * on the given event listener.
629      */

630     protected void processCallbackMethods(Method JavaDoc[] candidateMethods, MetadataEntityListener listener) {
631         for (Method JavaDoc method : candidateMethods) {
632             if (isAnnotationPresent(PostLoad.class, method)) {
633                 setPostLoad(method, listener);
634             }
635             
636             if (isAnnotationPresent(PostPersist.class, method)) {
637                 setPostPersist(method, listener);
638             }
639             
640             if (isAnnotationPresent(PostRemove.class, method)) {
641                 setPostRemove(method, listener);
642             }
643             
644             if (isAnnotationPresent(PostUpdate.class, method)) {
645                 setPostUpdate(method, listener);
646             }
647             
648             if (isAnnotationPresent(PrePersist.class, method)) {
649                 setPrePersist(method, listener);
650             }
651             
652             if (isAnnotationPresent(PreRemove.class, method)) {
653                 setPreRemove(method, listener);
654             }
655             
656             if (isAnnotationPresent(PreUpdate.class, method)) {
657                 setPreUpdate(method, listener);
658             }
659         }
660     }
661     
662     /**
663      * INTERNAL:
664      * Process the items of interest on an entity or mapped superclass class.
665      */

666     protected void processClass() {
667         // Process the @AttributeOverrides and @AttributeOverride.
668
processAttributeOverrides();
669                     
670         // Process the @AssociationOverrides and @AssociationOverride.
671
processAssociationOverrides();
672         
673         // Process the @NamedQueries and @NamedQuery.
674
processNamedQueries();
675                     
676         // Process the @NamedNativeQueries and @NamedNativeQuery.
677
processNamedNativeQueries();
678                     
679         // Process the @SqlRessultSetMapping.
680
processSqlResultSetMappings();
681                     
682         // Process the @TableGenerator.
683
processTableGenerator();
684             
685         // Process the @SequenceGenerator
686
processSequenceGenerator();
687                     
688         // Process the @IdClass (pkClass).
689
processIdClass();
690         
691         // Process the @ExcludeDefaultListeners.
692
processExcludeDefaultListeners();
693         
694         // Process the @ExcludeSuperclassListeners.
695
processExcludeSuperclassListeners();
696     }
697
698     /**
699      * INTERNAL:
700      * Process the default listeners defined in XML. This method will process
701      * the class for additional lifecycle callback methods that are decorated
702      * with annotations.
703      *
704      * NOTE: We add the default listeners regardless if the exclude default
705      * listeners flag is set. This allows the user to change the exlcude flag
706      * at runtime and have the default listeners available to them.
707      */

708     protected void processDefaultListeners(ClassLoader JavaDoc loader) {
709         Map JavaDoc<XMLHelper, NodeList JavaDoc> defaultListeners = m_project.getDefaultListeners();
710         
711         for (XMLHelper helper : defaultListeners.keySet()) {
712             // Update the class loader.
713
helper.setLoader(loader);
714             NodeList JavaDoc nodes = defaultListeners.get(helper);
715             
716             for (int i = 0; i < nodes.getLength(); i++) {
717                 Node JavaDoc node = nodes.item(i);
718                 
719                 // Build an xml entity listener.
720
XMLEntityListener listener = new XMLEntityListener(helper.getClassForNode(node), getJavaClass());
721                 
722                 // Process the lifecycle callback events from XML.
723
Method JavaDoc[] candidateMethods = MetadataHelper.getCandidateCallbackMethodsForDefaultListener(listener);
724                 processLifecycleEvents(listener, node, helper, candidateMethods);
725                 
726                 // Process the candidate callback methods on this listener for
727
// additional callback methods decorated with annotations.
728
processCallbackMethods(candidateMethods, listener);
729         
730                 // Add the listener to the descriptor.
731
m_descriptor.addDefaultEventListener(listener);
732             }
733         }
734     }
735     
736     /**
737      * INTERNAL:
738      * Process a @DiscriminatorColumn (if there is one, otherwise default) to
739      * set this classes indication field name for inheritance.
740      */

741     protected void processDiscriminatorColumn() {
742         DiscriminatorColumn discriminatorColumn = getAnnotation(DiscriminatorColumn.class);
743         processDiscriminatorColumn(new MetadataDiscriminatorColumn(discriminatorColumn));
744     }
745     
746     /**
747      * INTERNAL:
748      * Process a discriminator column to set this class indicatior field name
749      * for inheritance.
750      */

751     protected void processDiscriminatorColumn(MetadataDiscriminatorColumn discriminatorColumn) {
752         DatabaseField field = new DatabaseField();
753
754         field.setName(getName(discriminatorColumn.getName(), MetadataDiscriminatorColumn.DEFAULT_NAME, m_logger.DISCRIMINATOR_COLUMN));
755         field.setLength(discriminatorColumn.getLength());
756         field.setTableName(m_descriptor.getPrimaryTableName());
757         field.setColumnDefinition(discriminatorColumn.getColumnDefinition());
758         field.setType(MetadataHelper.getDiscriminatorType(discriminatorColumn.getDiscriminatorType()));
759         
760         // Set the class indicator field on the inheritance policy.
761
m_descriptor.setClassIndicatorField(field);
762     }
763     
764     /**
765      * INTERNAL:
766      * Process a discriminator value to set the class indicator on the root
767      * descriptor of the inheritance hierarchy.
768      *
769      * If there is no discriminator value, the class indicator defaults to
770      * the class name.
771      */

772     protected void processDiscriminatorValue() {
773         if (! Modifier.isAbstract(getJavaClass().getModifiers())) {
774             // Add the indicator to the inheritance root class' descriptor. The
775
// default is the short class name.
776
String JavaDoc discriminatorValue = getDiscriminatorValue();
777             
778             if (discriminatorValue == null) {
779                 // WIP - log a warning ...
780
m_descriptor.addClassIndicator(getJavaClass(), Helper.getShortClassName(getJavaClassName()));
781             } else {
782                 m_descriptor.addClassIndicator(getJavaClass(), discriminatorValue);
783             }
784         }
785     }
786     
787     /**
788      * INTERNAL:
789      * Process an entity.
790      */

791     protected void processEntity() {
792         // Don't override existing alias.
793
if (m_descriptor.getAlias().equals("")) {
794             String JavaDoc alias = getEntityName();
795             
796             if (alias.equals("")) {
797                 alias = Helper.getShortClassName(getJavaClassName());
798                 m_logger.logConfigMessage(m_logger.ALIAS, m_descriptor, alias);
799             }
800
801             // Verify that the alias is not a duplicate.
802
ClassDescriptor existingDescriptor = getProject().getSession().getProject().getDescriptorForAlias(alias);
803             if (existingDescriptor != null) {
804                 m_validator.throwNonUniqueEntityName(existingDescriptor.getJavaClassName(), m_descriptor.getJavaClassName(), alias);
805             }
806
807             // Set the alias on the descriptor and add it to the project.
808
m_descriptor.setAlias(alias);
809             getProject().getSession().getProject().addAlias(alias, m_descriptor.getDescriptor());
810         }
811     }
812     
813     /**
814      * INTERNAL: (Overridden in XMLCLassAccessor)
815      * Process the entity class for lifecycle callback event methods.
816      */

817     public MetadataEntityListener processEntityEventListener(ClassLoader JavaDoc loader) {
818         MetadataEntityClassListener listener = new MetadataEntityClassListener(getJavaClass());
819             
820         // Check the entity class for lifecycle callback annotations.
821
processCallbackMethods(MetadataHelper.getCandidateCallbackMethodsForEntityClass(getJavaClass()), listener);
822         
823         return listener;
824     }
825     
826     /**
827      * INTERNAL: (Overridden in XMLClassAccessor)
828      * Process the @EntityListeners for this class accessor.
829      */

830     public void processEntityListeners(Class JavaDoc entityClass, ClassLoader JavaDoc loader) {
831         EntityListeners entityListeners = getAnnotation(EntityListeners.class);
832         
833         if (entityListeners != null) {
834             for (Class JavaDoc entityListener : entityListeners.value()) {
835                 MetadataEntityListener listener = new MetadataEntityListener(entityListener, entityClass);
836                 
837                 // Process the candidate callback methods for this listener ...
838
processCallbackMethods(MetadataHelper.getCandidateCallbackMethodsForEntityListener(listener), listener);
839                 
840                 // Add the entity listener to the descriptor event manager.
841
m_descriptor.addEntityListenerEventListener(listener);
842             }
843         }
844     }
845     
846     /**
847      * INTERNAL: (Overridden in XMLClassAccessor)
848      * Process the @ExcludeDefaultListeners if one is specified (taking
849      * metadata-complete into consideration).
850      */

851     protected void processExcludeDefaultListeners() {
852         // Don't overrite a true flag that could be set from a subclass
853
// that already exlcuded them.
854
if (isAnnotationPresent(ExcludeDefaultListeners.class)) {
855             m_descriptor.setExcludeDefaultListeners(true);
856         }
857     }
858     
859     /**
860      * INTERNAL: (Overridden in XMLClassAccessor)
861      * Process the @ExcludeSuperclassListeners if one is specified (taking
862      * metadata-complete into consideration).
863      */

864     protected void processExcludeSuperclassListeners() {
865         // Don't overrite a true flag that could be set from a subclass
866
// that already exlcuded them.
867
if (isAnnotationPresent(ExcludeSuperclassListeners.class)) {
868             m_descriptor.setExcludeSuperclassListeners(true);
869         }
870     }
871     
872     /**
873      * INTERNAL:
874      * Process an @IdClass or id-class element. It is used to specify composite
875      * primary keys. The primary keys will be processed and stored from the PK
876      * class so that they may be validated against the fields or properties of
877      * the entity bean. The access type of a primary key class is determined by
878      * the access type of the entity for which it is the primary key.
879      *
880      * NOTE: the class passed in may be a mapped-superclass or entity.
881      */

882     protected void processIdClass() {
883         Class JavaDoc idClass = getIdClass();
884         
885         if (idClass != null) {
886             if (m_descriptor.ignoreIDs()) {
887                 m_logger.logWarningMessage(m_logger.IGNORE_ID_CLASS, m_descriptor, idClass);
888             } else {
889                 m_descriptor.setPKClass(idClass);
890                 
891                 if (m_descriptor.usesPropertyAccess()) {
892                     for (Method JavaDoc method : MetadataHelper.getDeclaredMethods(idClass)) {
893                         String JavaDoc methodName = method.getName();
894                 
895                         if (MetadataHelper.isValidPersistenceMethodName(methodName)) {
896                             m_descriptor.addPKClassId(MetadataHelper.getAttributeNameFromMethodName(methodName), MetadataHelper.getGenericReturnType(method));
897                         }
898                     }
899                 } else {
900                     for (Field JavaDoc field : MetadataHelper.getFields(idClass)) {
901                         m_descriptor.addPKClassId(field.getName(), MetadataHelper.getGenericType(field));
902                     }
903                 }
904             }
905         }
906     }
907     
908     /**
909      * INTERNAL:
910      * Process the @Inheritance or inheritance tag if there is one. One may or
911      * may not be specified for the entity class that is the root of the entity
912      * class hierarchy.
913      */

914     protected void processInheritanceRoot() {
915         if (m_descriptor.ignoreInheritance()) {
916             m_logger.logWarningMessage(m_logger.IGNORE_INHERITANCE, m_descriptor);
917         } else {
918             // Get the inheritance strategy and store it on the descriptor.
919
String JavaDoc inheritanceStrategy = getInheritanceStrategy();
920             if (inheritanceStrategy.equals("")) {
921                 // WIP - should log a message that we are defaulting ...
922
inheritanceStrategy = InheritanceType.SINGLE_TABLE.name();
923             }
924
925             m_descriptor.setInheritanceStrategy(inheritanceStrategy);
926                 
927             // Process the discriminator column metadata.
928
processDiscriminatorColumn();
929                 
930             // Process the discriminator value metadata.
931
processDiscriminatorValue();
932         }
933     }
934     
935     /**
936      * INTERNAL:
937      * Process an inheritance subclass.
938      */

939     public void processInheritanceSubclass() {
940         if (m_descriptor.ignoreInheritance()) {
941             m_logger.logWarningMessage(m_logger.IGNORE_INHERITANCE, m_descriptor);
942         } else {
943             // Log a warning if we are ignoring an entity that has an inheritance tag.
944
if (hasInheritanceTag(getJavaClass())) {
945                 m_logger.logWarningMessage(m_logger.IGNORE_INHERITANCE, m_descriptor);
946             }
947             
948             // Set the parent class on the source descriptor.
949
setInheritanceParentClass();
950                 
951             // Get the inheritance root descriptor metadata.
952
MetadataDescriptor rootDescriptor = getInheritanceRootDescriptor();
953                 
954             // Inheritance.stategy() = SINGLE_TABLE, set the flag.
955
if (rootDescriptor.usesSingleTableInheritanceStrategy()) {
956                 m_descriptor.setSingleTableInheritanceStrategy();
957             } else {
958                 // Inheritance.stategy() = JOINED, then we need to look for
959
// primary key join column(s) and add multiple table key fields.
960
MetadataPrimaryKeyJoinColumns primaryKeyJoinColumns = getPrimaryKeyJoinColumns(rootDescriptor.getPrimaryTableName(), m_descriptor.getPrimaryTableName());
961                 addMultipleTableKeyFields(primaryKeyJoinColumns, m_logger.INHERITANCE_PK_COLUMN, m_logger.INHERITANCE_FK_COLUMN);
962             }
963             
964             // Process the discriminator value.
965
processDiscriminatorValue();
966             
967             // If the root descriptor has an id class, we need to set the same
968
// id class on our descriptor.
969
if (rootDescriptor.hasCompositePrimaryKey()) {
970                 m_descriptor.setPKClass(rootDescriptor.getPKClassName());
971             }
972         }
973     }
974     
975     /**
976      * INTERNAL:
977      * Process and array of @JoinColumn into a list of metadata join column.
978      */

979     protected List JavaDoc<MetadataJoinColumn> processJoinColumns(JoinColumn[] joinColumns) {
980         ArrayList JavaDoc<MetadataJoinColumn> list = new ArrayList JavaDoc<MetadataJoinColumn>();
981         
982         for (JoinColumn joinColumn : joinColumns) {
983             list.add(new MetadataJoinColumn(joinColumn));
984         }
985         
986         return list;
987     }
988     
989     /**
990      * INTERNAL:
991      * Process the XML lifecycle event for the given listener.
992      */

993     protected void processLifecycleEvent(MetadataEntityListener listener, Node JavaDoc node, String JavaDoc event, XMLHelper helper, Method JavaDoc[] candidateMethods) {
994         Node JavaDoc eventNode = helper.getNode(node, event);
995         
996         if (eventNode != null) {
997             String JavaDoc methodName = helper.getNodeValue(eventNode, XMLConstants.ATT_METHOD_NAME);
998             Method JavaDoc method = MetadataHelper.getMethodForName(candidateMethods, methodName);
999
1000            if (method == null) {
1001                // WIP - should be on the validator.
1002
throw ValidationException.invalidCallbackMethod(listener.getListenerClass(), methodName);
1003            } else if (event.equals(XMLConstants.PRE_PERSIST)) {
1004                setPrePersist(method, listener);
1005            } else if (event.equals(XMLConstants.POST_PERSIST)) {
1006                setPostPersist(method, listener);
1007            } else if (event.equals(XMLConstants.PRE_REMOVE)) {
1008                setPreRemove(method, listener);
1009            } else if (event.equals(XMLConstants.POST_REMOVE)) {
1010                setPostRemove(method, listener);
1011            } else if (event.equals(XMLConstants.PRE_UPDATE)) {
1012                setPreUpdate(method, listener);
1013            } else if (event.equals(XMLConstants.POST_UPDATE)) {
1014                setPostUpdate(method, listener);
1015            } else if (event.equals(XMLConstants.POST_LOAD)) {
1016                setPostLoad(method, listener);
1017            }
1018        }
1019    }
1020    
1021    /**
1022     * INTERNAL:
1023     * Process the XML lifecycle events for the given listener.
1024     */

1025    protected void processLifecycleEvents(MetadataEntityListener listener, Node JavaDoc node, XMLHelper helper, Method JavaDoc[] candidateMethods) {
1026        processLifecycleEvent(listener, node, XMLConstants.PRE_PERSIST, helper, candidateMethods);
1027        processLifecycleEvent(listener, node, XMLConstants.POST_PERSIST, helper, candidateMethods);
1028        processLifecycleEvent(listener, node, XMLConstants.PRE_REMOVE, helper, candidateMethods);
1029        processLifecycleEvent(listener, node, XMLConstants.POST_REMOVE, helper, candidateMethods);
1030        processLifecycleEvent(listener, node, XMLConstants.PRE_UPDATE, helper, candidateMethods);
1031        processLifecycleEvent(listener, node, XMLConstants.POST_UPDATE, helper, candidateMethods);
1032        processLifecycleEvent(listener, node, XMLConstants.POST_LOAD, helper, candidateMethods);
1033    }
1034    
1035    /**
1036     * INTERNAL:
1037     * Process the listeners for this class.
1038     */

1039    public void processListeners(ClassLoader JavaDoc loader) {
1040        // Step 1 - process the default listeners.
1041
processDefaultListeners(loader);
1042
1043        // Step 2 - process the entity listeners that are defined on the entity
1044
// class and mapped superclasses (taking metadata-complete into
1045
// consideration). Go through the mapped superclasses first, top -> down
1046
// only if the exclude superclass listeners flag is not set.
1047
if (! m_descriptor.excludeSuperclassListeners()) {
1048            List JavaDoc<ClassAccessor> mappedSuperclasses = getMappedSuperclasses();
1049            int mappedSuperclassesSize = mappedSuperclasses.size();
1050            
1051            for (int i = mappedSuperclassesSize - 1; i >= 0; i--) {
1052                mappedSuperclasses.get(i).processEntityListeners(getJavaClass(), loader);
1053            }
1054        }
1055        
1056        processEntityListeners(getJavaClass(), loader);
1057                
1058        // Step 3 - process the entity class for lifecycle callback methods. Go
1059
// through the mapped superclasses as well.
1060
MetadataEntityListener listener = processEntityEventListener(loader);
1061        
1062        if (! m_descriptor.excludeSuperclassListeners()) {
1063            for (ClassAccessor mappedSuperclass : getMappedSuperclasses()) {
1064                mappedSuperclass.processMappedSuperclassEventListener(listener, getJavaClass(), loader);
1065            }
1066        }
1067        
1068        // Add the listener only if we actually found callback methods.
1069
if (listener.hasCallbackMethods()) {
1070            m_descriptor.setEntityEventListener(listener);
1071        }
1072    }
1073
1074    /**
1075     * INTERNAL:
1076     * Process the @MappedSuperclass(es) if there are any. There may be
1077     * several MappedSuperclasses for any given Entity.
1078     */

1079    protected void processMappedSuperclass() {
1080        // Process the common class level attributes that an entity or
1081
// mapped superclass may define.
1082
processClass();
1083            
1084        // Process the accessors from the mapped superclass.
1085
processAccessors();
1086    }
1087    
1088    /**
1089     * INTERNAL:
1090     * Process the @MappedSuperclass(es) if there are any. There may be
1091     * several MappedSuperclasses for any given Entity.
1092     */

1093    protected void processMappedSuperclasses() {
1094        for (ClassAccessor mappedSuperclass : getMappedSuperclasses()) {
1095            mappedSuperclass.process();
1096        }
1097    }
1098    
1099    /**
1100     * INTERNAL: (Overridden in XMLCLassAccessor)
1101     * Process the mapped superclass class for lifecycle callback event methods.
1102     */

1103    public void processMappedSuperclassEventListener(MetadataEntityListener listener, Class JavaDoc entityClass, ClassLoader JavaDoc loader) {
1104        // Check the mapped superclass for lifecycle callback annotations.
1105
processCallbackMethods(MetadataHelper.getCandidateCallbackMethodsForMappedSuperclass(getJavaClass(), entityClass), listener);
1106    }
1107    
1108    /**
1109     * INTERNAL:
1110     * Process a @NamedNativeQueries. The method will also look for
1111     * a @NamedNativeQuery. This method currently only stores the queries if
1112     * there are some. The actually query processing isn't done till
1113     * addNamedQueriesToSession is called.
1114     */

1115    protected void processNamedNativeQueries() {
1116        // Look for a @NamedNativeQueries.
1117
NamedNativeQueries namedNativeQueries = getAnnotation(NamedNativeQueries.class);
1118        if (namedNativeQueries != null) {
1119            for (NamedNativeQuery namedNativeQuery : namedNativeQueries.value()) {
1120                processNamedNativeQuery(new MetadataNamedNativeQuery(namedNativeQuery));
1121            }
1122        }
1123        
1124        // Look for a @NamedNativeQuery.
1125
NamedNativeQuery namedNativeQuery = getAnnotation(NamedNativeQuery.class);
1126        if (namedNativeQuery != null) {
1127            processNamedNativeQuery(new MetadataNamedNativeQuery(namedNativeQuery));
1128        }
1129    }
1130    
1131    /**
1132     * INTERNAL:
1133     * Process a MetadataNamedNativeQuery. The actually query processing isn't
1134     * done till addNamedQueriesToSession is called.
1135     */

1136    protected void processNamedNativeQuery(MetadataNamedNativeQuery namedNativeQuery) {
1137        if (m_project.hasNamedNativeQuery(namedNativeQuery.getName())) {
1138            MetadataNamedNativeQuery existingNamedNativeQuery = m_project.getNamedNativeQuery(namedNativeQuery.getName());
1139            
1140            if (existingNamedNativeQuery.loadedFromAnnotations() && namedNativeQuery.loadedFromXML()) {
1141                // Override the existing query.
1142
m_project.addNamedNativeQuery(namedNativeQuery);
1143            } else {
1144                // Ignore the query and log a message.
1145
m_logger.logWarningMessage(m_logger.IGNORE_QUERY, m_descriptor, namedNativeQuery.getName());
1146            }
1147        } else {
1148            m_project.addNamedNativeQuery(namedNativeQuery);
1149        }
1150    }
1151    
1152    /**
1153     * INTERNAL:
1154     * Process a @NamedQueries. The method will also look for a @NamedQuery.
1155     * This method currently only stores the queries if there are some. The
1156     * actually query processing isn't done till addNamedQueriesToSession is
1157     * called.
1158     */

1159    protected void processNamedQueries() {
1160        // Look for a @NamedQueries.
1161
NamedQueries namedQueries = getAnnotation(NamedQueries.class);
1162        
1163        if (namedQueries != null) {
1164            for (NamedQuery namedQuery : namedQueries.value()) {
1165                processNamedQuery(new MetadataNamedQuery(namedQuery));
1166            }
1167        }
1168        
1169        // Look for a @NamedQuery.
1170
NamedQuery namedQuery = getAnnotation(NamedQuery.class);
1171        
1172        if (namedQuery != null) {
1173            processNamedQuery(new MetadataNamedQuery(namedQuery));
1174        }
1175    }
1176    
1177    /**
1178     * INTERNAL:
1179     * Add a metadata named query to the project. The actually query processing
1180     * isn't done till addNamedQueriesToSession is called.
1181     */

1182    protected void processNamedQuery(MetadataNamedQuery namedQuery) {
1183        if (m_project.hasNamedQuery(namedQuery.getName())) {
1184            MetadataNamedQuery existingNamedQuery = m_project.getNamedQuery(namedQuery.getName());
1185            
1186            if (existingNamedQuery.loadedFromAnnotations() && namedQuery.loadedFromXML()) {
1187                // Override the existing query.
1188
m_project.addNamedQuery(namedQuery);
1189            } else {
1190                // Ignore the query and log a message.
1191
m_logger.logWarningMessage(m_logger.IGNORE_QUERY, m_descriptor, namedQuery.getName());
1192            }
1193        } else {
1194            m_project.addNamedQuery(namedQuery);
1195        }
1196    }
1197    
1198    /**
1199     * INTERNAL:
1200     * Process a MetadataSecondaryTable. Do all the table name defaulting and
1201     * set the correct, fully qualified name on the TopLink DatabaseTable.
1202     */

1203    protected void processSecondaryTable(MetadataSecondaryTable secondaryTable) {
1204        // Catalog could be "", need to check for an XML default.
1205
// WIP - build m_logger.SECONDARY_TABLE_CATALOG
1206
String JavaDoc catalog = getName(secondaryTable.getCatalog(), m_descriptor.getCatalog(), m_logger.TABLE_CATALOG);
1207        
1208        // Schema could be "", need to check for an XML default.
1209
// WIP - build m_logger.SECONDARY_TABLE_SCHEMA
1210
String JavaDoc schema = getName(secondaryTable.getSchema(), m_descriptor.getSchema(), m_logger.TABLE_SCHEMA);
1211        
1212        // Build a fully qualified name and set it on the secondary table.
1213
secondaryTable.setName(MetadataHelper.getFullyQualifiedTableName(secondaryTable.getName(), catalog, schema));
1214        
1215        // Add the table to the descriptor.
1216
m_descriptor.addTable(secondaryTable.getDatabaseTable());
1217        
1218        // Get the primary key join column(s) and add the multiple table key fields.
1219
MetadataPrimaryKeyJoinColumns primaryKeyJoinColumns = secondaryTable.getPrimaryKeyJoinColumns(m_descriptor.getPrimaryTableName());
1220        addMultipleTableKeyFields(primaryKeyJoinColumns, m_logger.SECONDARY_TABLE_PK_COLUMN, m_logger.SECONDARY_TABLE_FK_COLUMN);
1221    }
1222    
1223    /**
1224     * INTERNAL: (Overridden in XMLClassAccessor)
1225     * Process a @SecondaryTables. If one isn't found, try a @SecondaryTable.
1226     * WIP - If the @SecondaryTable does not define the pkJoinColumns(), we
1227     * could look for PrimaryKeyJoinColumns on the class itself. This is not
1228     * mandatory through.
1229     */

1230    protected void processSecondaryTables() {
1231        if (m_descriptor.ignoreTables()) {
1232            m_logger.logWarningMessage(m_logger.IGNORE_TABLE, getJavaClass());
1233        } else {
1234            // Look for a SecondaryTables annotation.
1235
SecondaryTables secondaryTables = getAnnotation(SecondaryTables.class);
1236            if (secondaryTables != null) {
1237                for (SecondaryTable secondaryTable : secondaryTables.value()) {
1238                    processSecondaryTable(new MetadataSecondaryTable(secondaryTable));
1239                }
1240            } else {
1241                // Look for a SecondaryTable annotation
1242
SecondaryTable secondaryTable = getAnnotation(SecondaryTable.class);
1243                if (secondaryTable != null) {
1244                    processSecondaryTable(new MetadataSecondaryTable(secondaryTable));
1245                }
1246            }
1247        }
1248    }
1249    
1250    /**
1251     * INTERNAL:
1252     * Process an sql result set mapping metadata into a TopLink
1253     * SqlResultSetMapping and store it on the session.
1254     */

1255    protected void processSqlResultSetMapping(MetadataSQLResultSetMapping sqlResultSetMapping) {
1256        // Initialize a new SqlResultSetMapping (with the metadata name)
1257
oracle.toplink.essentials.queryframework.SQLResultSetMapping mapping = new oracle.toplink.essentials.queryframework.SQLResultSetMapping(sqlResultSetMapping.getName());
1258        
1259        // Process the entity results.
1260
for (MetadataEntityResult eResult : sqlResultSetMapping.getEntityResults()) {
1261            EntityResult entityResult = new EntityResult(eResult.getEntityClass().getName());
1262        
1263            // Process the field results.
1264
for (MetadataFieldResult fResult : eResult.getFieldResults()) {
1265                entityResult.addFieldResult(new FieldResult(fResult.getName(), fResult.getColumn()));
1266            }
1267        
1268            // Process the discriminator value;
1269
entityResult.setDiscriminatorColumn(eResult.getDiscriminatorColumn());
1270        
1271            // Add the result to the SqlResultSetMapping.
1272
mapping.addResult(entityResult);
1273        }
1274        
1275        // Process the column results.
1276
for (String JavaDoc columnResult : sqlResultSetMapping.getColumnResults()) {
1277            mapping.addResult(new ColumnResult(columnResult));
1278        }
1279            
1280        getProject().getSession().getProject().addSQLResultSetMapping(mapping);
1281    }
1282    
1283    /**
1284     * INTERNAL:
1285     * Process a @SqlResultSetMappings.
1286     */

1287    protected void processSqlResultSetMappings() {
1288        // Look for a @SqlResultSetMappings.
1289
SqlResultSetMappings sqlResultSetMappings = getAnnotation(SqlResultSetMappings.class);
1290
1291        if (sqlResultSetMappings != null) {
1292            for (SqlResultSetMapping sqlResultSetMapping : sqlResultSetMappings.value()) {
1293                processSqlResultSetMapping(new MetadataSQLResultSetMapping(sqlResultSetMapping));
1294            }
1295        } else {
1296            // Look for a @SqlResultSetMapping.
1297
SqlResultSetMapping sqlResultSetMapping = getAnnotation(SqlResultSetMapping.class);
1298            
1299            if (sqlResultSetMapping != null) {
1300                processSqlResultSetMapping(new MetadataSQLResultSetMapping(sqlResultSetMapping));
1301            }
1302        }
1303    }
1304
1305    /**
1306     * INTERNAL: (Overridden in XMLClassAccessor)
1307     * Process a @Table annotation.
1308     */

1309    protected void processTable() {
1310        if (m_descriptor.ignoreTables()) {
1311            m_logger.logWarningMessage(m_logger.IGNORE_TABLE, getJavaClass());
1312        } else {
1313            Table table = getAnnotation(Table.class);
1314            processTable(new MetadataTable(table));
1315        }
1316    }
1317    
1318    /**
1319     * INTERNAL:
1320     * Process a MetadataTable. Do all the table name defaulting and set the
1321     * correct, fully qualified name on the TopLink DatabaseTable.
1322     */

1323    protected void processTable(MetadataTable table) {
1324        // Name could be "", need to check against the default name.
1325
String JavaDoc name = getName(table.getName(), m_descriptor.getDefaultTableName(), m_logger.TABLE_NAME);
1326
1327        // Catalog could be "", need to check for an XML default.
1328
String JavaDoc catalog = getName(table.getCatalog(), m_descriptor.getCatalog(), m_logger.TABLE_CATALOG);
1329        
1330        // Schema could be "", need to check for an XML default.
1331
String JavaDoc schema = getName(table.getSchema(), m_descriptor.getSchema(), m_logger.TABLE_SCHEMA);
1332        
1333        // Build a fully qualified name and set it on the table.
1334
table.setName(MetadataHelper.getFullyQualifiedTableName(name, catalog, schema));
1335
1336        // Set the table on the descriptor.
1337
m_descriptor.setPrimaryTable(table.getDatabaseTable());
1338    }
1339    
1340    /**
1341     * INTERNAL:
1342     * Process any inheritance specifics. This method will fast track any root
1343     * inheritance processing, be it specified or defaulted.
1344     */

1345    protected void processTableAndInheritance() {
1346        // If we are an inheritance subclass, ensure our root is processed
1347
// first since it has information its subclasses depend on.
1348
if (isInheritanceSubclass()) {
1349            MetadataDescriptor rootDescriptor = getInheritanceRootDescriptor();
1350            
1351            // Process the root class accesor if it hasn't already been done.
1352
ClassAccessor rootAccessor = rootDescriptor.getClassAccessor();
1353            if (rootAccessor == null) {
1354                rootAccessor = processAccessor(rootDescriptor);
1355            }
1356            
1357            // If the root class inheritance specifics haven't been processed
1358
// yet, then do them now.
1359
if (! rootDescriptor.hasInheritance()) {
1360                rootAccessor.processInheritanceRoot();
1361            }
1362                
1363            // Process the @Table if there is one. Must be processed before
1364
// processing the inheritance subclass metadata.
1365
if (! rootDescriptor.usesSingleTableInheritanceStrategy()) {
1366                processTable();
1367            }
1368            
1369            // Process our inheritance specifics.
1370
processInheritanceSubclass();
1371        } else {
1372            // Process the @Table if there is one.
1373
processTable();
1374        }
1375    }
1376    
1377    /**
1378     * INTERNAL:
1379     * Should only be called from those classes that are in fact part of an
1380     * inheritance hierarchy. It figures out the parent and then sets it.
1381     */

1382    protected void setInheritanceParentClass() {
1383        Class JavaDoc parent = getJavaClass().getSuperclass();
1384        
1385        while (parent != Object JavaDoc.class) {
1386            if (hasEntityTag(parent) || m_project.containsDescriptor(parent)) {
1387                break;
1388            }
1389            
1390            parent = parent.getSuperclass();
1391        }
1392        
1393        m_descriptor.setParentClass(parent);
1394    }
1395    
1396    /**
1397     * INTERNAL:
1398     * Set the post load event method on the listener.
1399     */

1400    protected void setPostLoad(Method JavaDoc method, MetadataEntityListener listener) {
1401        listener.setPostBuildMethod(method);
1402        listener.setPostCloneMethod(method);
1403        listener.setPostRefreshMethod(method);
1404    }
1405    
1406    /**
1407     * INTERNAL:
1408     * Set the post persist event method on the listener.
1409     */

1410    protected void setPostPersist(Method JavaDoc method, MetadataEntityListener listener) {
1411        listener.setPostInsertMethod(method);
1412    }
1413    
1414    /**
1415     * INTERNAL:
1416     * Set the post remove event method on the listener.
1417     */

1418    protected void setPostRemove(Method JavaDoc method, MetadataEntityListener listener) {
1419        listener.setPostDeleteMethod(method);
1420    }
1421    
1422    /**
1423     * INTERNAL:
1424     * * Set the post update event method on the listener.
1425     */

1426    protected void setPostUpdate(Method JavaDoc method, MetadataEntityListener listener) {
1427        listener.setPostUpdateMethod(method);
1428    }
1429            
1430    /**
1431     * INTERNAL:
1432     * Set the pre persist event method on the listener.
1433     */

1434    protected void setPrePersist(Method JavaDoc method, MetadataEntityListener listener) {
1435        listener.setPrePersistMethod(method);
1436    }
1437    
1438    /**
1439     * INTERNAL:
1440     * Set the pre remove event method on the listener.
1441     */

1442    protected void setPreRemove(Method JavaDoc method, MetadataEntityListener listener) {
1443        listener.setPreRemoveMethod(method);
1444    }
1445    
1446    /**
1447     * INTERNAL:
1448     * Set the pre update event method on the listener.
1449     */

1450    protected void setPreUpdate(Method JavaDoc method, MetadataEntityListener listener) {
1451        listener.setPreUpdateWithChangesMethod(method);
1452    }
1453    
1454    /**
1455     * INTERNAL:
1456     * Call this method after a primary key should have been found.
1457     */

1458    protected void validatePrimaryKey() {
1459        // If this descriptor has a composite primary key, check that all
1460
// our composite primary key attributes were validated.
1461
if (m_descriptor.hasCompositePrimaryKey()) {
1462            if (m_descriptor.pkClassWasNotValidated()) {
1463                m_validator.throwInvalidCompositePKSpecification(getJavaClass(), m_descriptor.getPKClassName());
1464            }
1465        } else {
1466            // Descriptor has a single primary key. Validate an id
1467
// attribute was found, unless we are an inheritance subclass
1468
// or an aggregate descriptor.
1469
if (! m_descriptor.hasPrimaryKeyFields() && ! isInheritanceSubclass()) {
1470                m_validator.throwNoPrimaryKeyAnnotationsFound(getJavaClass());
1471            }
1472        }
1473    }
1474}
1475
Popular Tags