FileDocCategorySizeDatePackage
ClassAccessor.javaAPI DocGlassfish v2 API62794Tue May 22 16:54:26 BST 2007oracle.toplink.essentials.internal.ejb.cmp3.metadata.accessors

ClassAccessor

public class ClassAccessor extends NonRelationshipAccessor
A class accessor.
author
Guy Pelletier
since
TopLink EJB 3.0 Reference Implementation

Fields Summary
protected Class
m_inheritanceParentClass
protected Boolean
m_isInheritanceSubclass
protected List
m_mappedSuperclasses
Constructors Summary
public ClassAccessor(MetadataAccessibleObject accessibleObject, MetadataProcessor processor, MetadataDescriptor descriptor)
INTERNAL:

        super(accessibleObject, processor, descriptor);
    
Methods Summary
protected voidaddMultipleTableKeyFields(oracle.toplink.essentials.internal.ejb.cmp3.metadata.columns.MetadataPrimaryKeyJoinColumns primaryKeyJoinColumns, java.lang.String PK_CTX, java.lang.String FK_CTX)
INTERNAL: Add multiple fields to the descriptor. Called from either @Inheritance or @SecondaryTable context.

        // ProcessPrimaryKeyJoinColumns will validate the primary key join
        // columns passed in and will return a list of 
        // MetadataPrimaryKeyJoinColumn.
        for (MetadataPrimaryKeyJoinColumn primaryKeyJoinColumn : processPrimaryKeyJoinColumns(primaryKeyJoinColumns)) {
            // In an inheritance case this call will return the pk field on the
            // root class of the inheritance hierarchy. Otherwise in a secondary
            // table case it's the primary key field name off our own descriptor.
            String defaultPKFieldName = m_descriptor.getPrimaryKeyFieldName();

            DatabaseField pkField = primaryKeyJoinColumn.getPrimaryKeyField();
            pkField.setName(getName(pkField, defaultPKFieldName, PK_CTX));

            DatabaseField fkField = primaryKeyJoinColumn.getForeignKeyField();
            fkField.setName(getName(fkField, pkField.getName(), FK_CTX));
        
            if (fkField.getName().equals(pkField.getName())) {
                // Add a multiple table primary key to the descriptor.
                m_descriptor.addMultipleTablePrimaryKeyField(pkField, fkField);
            } else {
                // Add a multiple table foreign key to the descriptor.
                m_descriptor.addMultipleTableForeignKeyField(pkField, fkField);
            }
        }
    
protected oracle.toplink.essentials.internal.ejb.cmp3.metadata.accessors.MetadataAccessorbuildAccessor(oracle.toplink.essentials.internal.ejb.cmp3.metadata.accessors.objects.MetadataAccessibleObject accessibleObject)
INTERNAL: Create and return the appropriate accessor based on the accessible object given. Order of checking is important, careful when modifying or adding, check what the isXyz call does to determine if the accessor is of type xyz.

        MetadataAccessor accessor = m_descriptor.getAccessorFor(accessibleObject.getAttributeName());
        
        if (accessor == null) {
            if (MetadataHelper.isBasic(accessibleObject, m_descriptor)) {
                return new BasicAccessor(accessibleObject, this);
            } else if (MetadataHelper.isEmbedded(accessibleObject, m_descriptor)) {
                return new EmbeddedAccessor(accessibleObject, this);
            } else if (MetadataHelper.isEmbeddedId(accessibleObject, m_descriptor)) {
                return new EmbeddedIdAccessor(accessibleObject, this);
            } else if (MetadataHelper.isManyToMany(accessibleObject, m_descriptor)) {
                return new ManyToManyAccessor(accessibleObject, this);
            } else if (MetadataHelper.isManyToOne(accessibleObject, m_descriptor)) {
                return new ManyToOneAccessor(accessibleObject, this);
            } else if (MetadataHelper.isOneToMany(accessibleObject, m_descriptor)) {
                // A OneToMany can currently default, that is, doesn't require
                // an annotation to be present.
                return new OneToManyAccessor(accessibleObject, this);
            } else if (MetadataHelper.isOneToOne(accessibleObject, m_descriptor)) {
                // A OneToOne can currently default, that is, doesn't require
                // an annotation to be present.
                return new OneToOneAccessor(accessibleObject, this);
            } else {
                // Default case (everything else currently falls into this)
                return new BasicAccessor(accessibleObject, this);
            }
        } else {
            return accessor;
        }
    
public voidclearMappedSuperclasses()
INTERNAL: Clear the mapped supeclasses. Do this after the class loader has changed. The list of mapped superclasses is lazily initialized.

        m_mappedSuperclasses = null;     
    
protected java.lang.StringgetDiscriminatorValue()
INTERNAL: (Overridden in XMLClassAccessor) Return the discriminator value for this accessor.

        DiscriminatorValue discriminatorValue = getAnnotation(DiscriminatorValue.class);
        
        if (discriminatorValue == null) {
            return null;
        } else {
            return discriminatorValue.value();
        }
    
protected java.lang.StringgetEntityName()
INTERNAL: (Overridden in XMLClassAccessor) Return the name of this entity class.

        Entity entity = getAnnotation(Entity.class);
        return (entity == null) ? "" : entity.name();
    
public java.lang.ClassgetInheritanceParentClass()
INTERNAL: This method returns the first parnt entity in an inheritance hierarchy that defines the inheritance strategy. That is, has an @Inheritance or inheritance xml element.

        if (m_inheritanceParentClass == null) {
            Class lastParent = null;
            Class parent = getJavaClass().getSuperclass();
        
            while (parent != Object.class) {
                if (hasInheritance(parent) || m_project.containsDescriptor(parent)) {
                    if (lastParent == null) {
                        // Set the immediate parent class on the descriptor.
                        m_descriptor.setParentClass(parent);
                    }
                    
                    lastParent = parent;
                    
                    if (hasInheritance(parent)) {
                        break; // stop looking.
                    }
                } 
                
                parent = parent.getSuperclass();
            }
        
            // Finally set whatever we found as the inheritance parent class. 
            // Which may be null.
            m_inheritanceParentClass = lastParent;
        }
  
        return m_inheritanceParentClass;
    
public oracle.toplink.essentials.internal.ejb.cmp3.metadata.MetadataDescriptorgetInheritanceParentDescriptor()
INTERNAL: Store the descriptor metadata for the root of our inheritance hierarchy.

        return m_project.getDescriptor(getInheritanceParentClass());
    
protected java.lang.StringgetInheritanceStrategy()
INTERNAL: (Overridden in XMLClassAccessor) Return the inheritance strategy. This method should only be called on the root of the inheritance hierarchy.

        Inheritance inheritance = getAnnotation(Inheritance.class);
        
        if (inheritance == null) {
            return "";
        } else {
            return inheritance.strategy().name();   
        }
    
public java.lang.ClassgetJavaClass()
INTERNAL: (OVERRIDE) Return the java class that defines this accessor. It may be an entity, embeddable or mapped superclass.

        return (Class) getAnnotatedElement();
    
public java.util.ListgetMappedSuperclasses()
INTERNAL: Build a list of classes that are decorated with a @MappedSuperclass.

        if (m_mappedSuperclasses == null) {
            m_mappedSuperclasses = new ArrayList<ClassAccessor>();
            
            Class parent = getJavaClass().getSuperclass();
        
            while (parent != Object.class) {
                if (isInheritanceSubclass() && hasEntity(parent)) {
                    // In an inheritance case we don't want to keep looking
                    // for mapped superclasses if they are not directly above
                    // us before the next entity in the hierarchy.
                    break;
                } else if (m_project.hasMappedSuperclass(parent)) {
                    Node node = m_project.getMappedSuperclassNode(parent);
                    XMLHelper helper = m_project.getMappedSuperclassHelper(parent);                    
                    m_mappedSuperclasses.add(new XMLMappedSuperclassAccessor(new MetadataClass(parent), node, helper, m_processor, m_descriptor));
                } else if (isAnnotationPresent(MappedSuperclass.class, parent)) {
                    m_mappedSuperclasses.add(new MappedSuperclassAccessor(new MetadataClass(parent), m_processor, m_descriptor));
                }
                
                parent = parent.getSuperclass();
            }
        }
        
        return m_mappedSuperclasses;
    
protected booleanhasEntity(java.lang.Class cls)
INTERNAL: (Overridden in XMLClassAccessor) Return true if the class has an @Entity.

        return isAnnotationPresent(Entity.class, cls);
    
protected booleanhasInheritance()
INTERNAL: Return true if this class accessor has an inheritance specifications.

        return hasInheritance(getJavaClass());
    
protected booleanhasInheritance(java.lang.Class entityClass)
INTERNAL: (Overridden in XMLClassAccessor) Return true if the class has an @Inheritance.

        return isAnnotationPresent(Inheritance.class, entityClass);
    
public booleanisClass()
INTERNAL:

     	return true;
     
public booleanisInheritanceSubclass()
INTERNAL:

        if (m_isInheritanceSubclass == null) {
            m_isInheritanceSubclass = new Boolean(getInheritanceParentClass() != null);
        }
        
        return m_isInheritanceSubclass;
    
protected booleanisTransient(java.lang.reflect.AnnotatedElement annotatedElement, int modifier)
INTERNAL:

        if (isAnnotationPresent(Transient.class, annotatedElement)) {
            if (MetadataHelper.getDeclaredAnnotationsCount(annotatedElement, m_descriptor) > 1) {
                m_validator.throwMappingAnnotationsAppliedToTransientAttribute(annotatedElement);
            }
            
            return true;
        } else if (Modifier.isTransient(modifier)) {
            if (MetadataHelper.getDeclaredAnnotationsCount(annotatedElement, m_descriptor) > 0) {
                m_validator.throwMappingAnnotationsAppliedToTransientAttribute(annotatedElement);
            }
            
            return true;
        }
        
        return false;
    
protected booleanisValidPersistenceElement(java.lang.reflect.AnnotatedElement annotatedElement, int modifiers)
INTERNAL: Return true is this annotated element is not marked transient, static or abstract.

        return ! (isTransient(annotatedElement, modifiers) || Modifier.isStatic(modifiers) || Modifier.isAbstract(modifiers));
    
protected booleanisValidPersistenceField(java.lang.reflect.Field field)
INTERNAL: Check to see if this is a valid field to process for persistence. It is valid if it is not static, transient or has a @Transient specified.

        return (isValidPersistenceElement(field, field.getModifiers()));
    
protected booleanisValidPersistenceMethod(java.lang.reflect.Method method)
INTERNAL: Check to see if this is a valid method to process for persistence. It is valid if it is not static, transient or has a @Transient specified.

        // Ignore methods marked transient, static or abstract.
        if (isValidPersistenceElement(method, method.getModifiers())) {
            // Look for methods that begin with "get" or "is", ignore all others.
            String methodName = method.getName();
            if (MetadataHelper.isValidPersistenceMethodName(methodName)) {
                // Ignore get methods with parameters.
                if (method.getParameterTypes().length > 0) {
                    return false;
                }
            
                Method setMethod = MetadataHelper.getSetMethod(method, getJavaClass());
            
                if (setMethod == null) {
                    if (MetadataHelper.getDeclaredAnnotationsCount(method, m_descriptor) > 0) {
                        // We decorated the property with annotations, but have 
                        // no corresponding setter property.
                        m_validator.throwNoCorrespondingSetterMethodDefined(getJavaClass(), method);
                    }
                } else {
                    return true;
                }
            }
        }
        
        return false;
    
public voidprocess()
INTERNAL: Process the items of interest on an entity or embeddable class. The order of processing is important, care must be taken if changes must be made.

        
        if (hasEntity(getJavaClass())) {
            // This accessor represents an @Entity class.
            // Set the ignore flags for items that are already defined.
            m_descriptor.setIgnoreFlags();
            
            // Process the @Entity.
            processEntity();
            
            // Process the @Table and @Inheritance.
            processTableAndInheritance();
            
            // Process the common class level attributes that an entity or
            // mapped superclass may define. This should be done before the
            // processMappedSuperclasses call since it will call this method 
            // also. We want to be able to grab the metadata off the actual 
            // entity class first because it needs to override any settings 
            // from the mapped superclass and may need to log a warning.
            processClassMetadata();
                
            // Process the @MappedSuperclass(es).
            processMappedSuperclasses();
                    
            // Process the accessors on this entity.
            processAccessors();
            
            // Validate we found a primary key.
            validatePrimaryKey();
                    
            // Process the @SecondaryTable(s).
            processSecondaryTables();
        } else {
            // This accessor represents an @Embeddable class
            m_descriptor.setIsEmbeddable();
            
            // Process the accessors on this embeddable.
            processAccessors();
        }
    
protected voidprocessAccessor(oracle.toplink.essentials.internal.ejb.cmp3.metadata.accessors.MetadataAccessor accessor)
INTERNAL: Process an accessor method or field. Relationship accessors will be stored for later processing.

        if (! accessor.isProcessed()) {
            // Store the accessor for later retrieval.
            m_descriptor.addAccessor(accessor);
            
            if (accessor.isRelationship()) {
                // Store the relationship accessors for later processing.
                m_project.addRelationshipDescriptor(m_descriptor);
            } else {
                accessor.process();
                accessor.setIsProcessed();
            }
        }
    
protected voidprocessAccessorFields()
INTERNAL: Create mappings from the fields directly.

        for (Field field : MetadataHelper.getFields(getJavaClass())) {
            if (isValidPersistenceField(field)) {
                processAccessor(buildAccessor(new MetadataField(field)));
            }
        }
    
protected voidprocessAccessorMethods()
INTERNAL: Create mappings via the class properties.

        for (Method method : MetadataHelper.getDeclaredMethods(getJavaClass())) {
            if (isValidPersistenceMethod(method)) {
                processAccessor(buildAccessor(new MetadataMethod(method)));
            }
        }
    
protected voidprocessAccessors()
INTERNAL: Process the accessors for the given class.

        // Process the fields or methods on the class.
        if (m_descriptor.usesPropertyAccess()) {
            processAccessorMethods();
        } else {
            processAccessorFields();
        }
    
protected voidprocessAssociationOverride(java.lang.String attributeName, oracle.toplink.essentials.internal.ejb.cmp3.metadata.columns.MetadataJoinColumns joinColumns)
INTERNAL: Process an @AssociationOverride for an Entity (or MappedSuperclass) that inherits from a MappedSuperclass.

        // Add association overrides from XML as we find them.
        if (joinColumns.loadedFromXML()) {
            m_descriptor.addAssociationOverride(attributeName, joinColumns);
        } else {
            // Association override from annotations should not override those 
            // loaded from XML.
            MetadataJoinColumns existingJoinColumns = m_descriptor.getAssociationOverrideFor(attributeName);
            
            if (existingJoinColumns == null || ! existingJoinColumns.loadedFromXML()) {
                m_descriptor.addAssociationOverride(attributeName, joinColumns);
            } else {
                // WIP should log a warning.
            }
        }
    
protected voidprocessAssociationOverrides()
INTERNAL: (Overriden in XMLClassAccessor) Process an @AssociationOverrides for an Entity (or MappedSuperclass) that inherits from a MappedSuperclass. It will also look for an @AssociationOverride.

        // Look for an @AssociationOverrides.
        AssociationOverrides associationOverrides = getAnnotation(AssociationOverrides.class);
        if (associationOverrides != null) {
            for (AssociationOverride associationOverride : associationOverrides.value()) {
                processAssociationOverride(associationOverride.name(), new MetadataJoinColumns(associationOverride.joinColumns()));
            }
        }
        
        // Look for an @AssociationOverride.
        AssociationOverride associationOverride = getAnnotation(AssociationOverride.class);
        if (associationOverride != null) {
            processAssociationOverride(associationOverride.name(), new MetadataJoinColumns(associationOverride.joinColumns()));
        }
    
protected voidprocessAttributeOverride(oracle.toplink.essentials.internal.ejb.cmp3.metadata.columns.MetadataColumn column)
INTERNAL: Process the @AttributeOverrides and @AttributeOverride for an Entity (or MappedSuperclass) that inherits from a MappedSuperclass.

        String attributeName = column.getAttributeName();
        
        // Add attribute overrides from XML as we find them.
        if (column.loadedFromXML()) {
            m_descriptor.addAttributeOverride(column);
        } else {
            // Attribute overrides from annotations should not override
            // those loaded from XML.
            MetadataColumn existingColumn = m_descriptor.getAttributeOverrideFor(attributeName);
            
            if (existingColumn == null || ! existingColumn.loadedFromXML()) {
                m_descriptor.addAttributeOverride(column);
            } else {
                // WIP should log a warning.
            }
        }
    
protected voidprocessAttributeOverrides()
INTERNAL: (Overridden in XMLClassAccessor) Process the @AttributeOverrides and @AttributeOverride for an Entity (or MappedSuperclass) that inherits from a MappedSuperclass.

        // Look for an @AttributeOverrides.
        AttributeOverrides attributeOverrides = getAnnotation(AttributeOverrides.class);	
        if (attributeOverrides != null) {
            for (AttributeOverride attributeOverride : attributeOverrides.value()) {
                processAttributeOverride(new MetadataColumn(attributeOverride, getAnnotatedElement()));
            }
        }
        
        // Look for an @AttributeOverride.
        AttributeOverride attributeOverride = getAnnotation(AttributeOverride.class);
        if (attributeOverride != null) {
            processAttributeOverride(new MetadataColumn(attributeOverride, getAnnotatedElement()));
        }
    
protected voidprocessCallbackMethods(java.lang.reflect.Method[] candidateMethods, oracle.toplink.essentials.internal.ejb.cmp3.metadata.listeners.MetadataEntityListener listener)
INTERNAL: Process the array of methods for lifecyle callback events and set them on the given event listener.

        for (Method method : candidateMethods) {
            if (isAnnotationPresent(PostLoad.class, method)) {
                setPostLoad(method, listener);
            }
            
            if (isAnnotationPresent(PostPersist.class, method)) {
                setPostPersist(method, listener);
            }
            
            if (isAnnotationPresent(PostRemove.class, method)) {
                setPostRemove(method, listener);
            }
            
            if (isAnnotationPresent(PostUpdate.class, method)) {
                setPostUpdate(method, listener);
            }
            
            if (isAnnotationPresent(PrePersist.class, method)) {
                setPrePersist(method, listener);
            }
            
            if (isAnnotationPresent(PreRemove.class, method)) {
                setPreRemove(method, listener);
            }
            
            if (isAnnotationPresent(PreUpdate.class, method)) {
                setPreUpdate(method, listener);
            }
        }
    
protected voidprocessClassMetadata()
INTERNAL: Process the items of interest on an entity or mapped superclass class.

        // Process the @AttributeOverrides and @AttributeOverride.
        processAttributeOverrides();
                    
        // Process the @AssociationOverrides and @AssociationOverride.
        processAssociationOverrides();
        
        // Process the @NamedQueries and @NamedQuery.
        processNamedQueries();
                    
        // Process the @NamedNativeQueries and @NamedNativeQuery.
        processNamedNativeQueries();
                    
        // Process the @SqlRessultSetMapping.
        processSqlResultSetMappings();
                    
        // Process the @TableGenerator.
        processTableGenerator();
            
        // Process the @SequenceGenerator
        processSequenceGenerator();
                    
        // Process the @IdClass (pkClass).
        processIdClass();
        
        // Process the @ExcludeDefaultListeners.
        processExcludeDefaultListeners();
        
        // Process the @ExcludeSuperclassListeners.
        processExcludeSuperclassListeners();
    
protected voidprocessDefaultListeners(java.lang.ClassLoader loader)
INTERNAL: Process the default listeners defined in XML. This method will process the class for additional lifecycle callback methods that are decorated with annotations. NOTE: We add the default listeners regardless if the exclude default listeners flag is set. This allows the user to change the exlcude flag at runtime and have the default listeners available to them.

        Map<XMLHelper, NodeList> defaultListeners = m_project.getDefaultListeners();
        
        for (XMLHelper helper : defaultListeners.keySet()) {
            // Update the class loader.
            helper.setLoader(loader);
            NodeList nodes = defaultListeners.get(helper);
            
            for (int i = 0; i < nodes.getLength(); i++) {
                Node node = nodes.item(i);
                
                // Build an xml entity listener.
                XMLEntityListener listener = new XMLEntityListener(helper.getClassForNode(node), getJavaClass());
                
                // Process the lifecycle callback events from XML.
                Method[] candidateMethods = MetadataHelper.getCandidateCallbackMethodsForDefaultListener(listener);
                processLifecycleEvents(listener, node, helper, candidateMethods);
                
                // Process the candidate callback methods on this listener for
                // additional callback methods decorated with annotations.
                processCallbackMethods(candidateMethods, listener);
        
                // Add the listener to the descriptor.
                m_descriptor.addDefaultEventListener(listener);
            }
		}
    
protected voidprocessDiscriminatorColumn()
INTERNAL: Process a @DiscriminatorColumn (if there is one, otherwise default) to set this classes indication field name for inheritance.

        DiscriminatorColumn discriminatorColumn = getAnnotation(DiscriminatorColumn.class);
        processDiscriminatorColumn(new MetadataDiscriminatorColumn(discriminatorColumn));
    
protected voidprocessDiscriminatorColumn(oracle.toplink.essentials.internal.ejb.cmp3.metadata.columns.MetadataDiscriminatorColumn discriminatorColumn)
INTERNAL: Process a discriminator column to set this class indicatior field name for inheritance.

        DatabaseField field = new DatabaseField();

        field.setName(getName(discriminatorColumn.getName(), MetadataDiscriminatorColumn.DEFAULT_NAME, m_logger.DISCRIMINATOR_COLUMN));
        field.setLength(discriminatorColumn.getLength());
        field.setTableName(m_descriptor.getPrimaryTableName());
        field.setColumnDefinition(discriminatorColumn.getColumnDefinition());
        field.setType(MetadataHelper.getDiscriminatorType(discriminatorColumn.getDiscriminatorType()));
        
        // Set the class indicator field on the inheritance policy.
        m_descriptor.setClassIndicatorField(field);
    
protected voidprocessDiscriminatorValue()
INTERNAL: Process a discriminator value to set the class indicator on the root descriptor of the inheritance hierarchy. If there is no discriminator value, the class indicator defaults to the class name.

        if (! Modifier.isAbstract(getJavaClass().getModifiers())) {
            // Add the indicator to the inheritance root class' descriptor. The
            // default is the short class name.
            String discriminatorValue = getDiscriminatorValue();
            
            if (discriminatorValue == null) {
                m_descriptor.addClassIndicator(getJavaClass(), Helper.getShortClassName(getJavaClassName()));    
            } else {
                m_descriptor.addClassIndicator(getJavaClass(), discriminatorValue);    
            }
        }
    
protected voidprocessEntity()
INTERNAL: Process an entity.

        // Don't override existing alias.
        if (m_descriptor.getAlias().equals("")) {
            String alias = getEntityName();
            
            if (alias.equals("")) {
                alias = Helper.getShortClassName(getJavaClassName());
                m_logger.logConfigMessage(m_logger.ALIAS, m_descriptor, alias);
            }

            // Verify that the alias is not a duplicate.
            ClassDescriptor existingDescriptor = getProject().getSession().getProject().getDescriptorForAlias(alias);
            if (existingDescriptor != null) {
                m_validator.throwNonUniqueEntityName(existingDescriptor.getJavaClassName(), m_descriptor.getJavaClassName(), alias);
            }

            // Set the alias on the descriptor and add it to the project.
            m_descriptor.setAlias(alias);
            getProject().getSession().getProject().addAlias(alias, m_descriptor.getClassDescriptor());
        }
	
public oracle.toplink.essentials.internal.ejb.cmp3.metadata.listeners.MetadataEntityListenerprocessEntityEventListener(java.lang.ClassLoader loader)
INTERNAL: (Overridden in XMLCLassAccessor) Process the entity class for lifecycle callback event methods.

        MetadataEntityClassListener listener = new MetadataEntityClassListener(getJavaClass());
            
        // Check the entity class for lifecycle callback annotations.
        processCallbackMethods(MetadataHelper.getCandidateCallbackMethodsForEntityClass(getJavaClass()), listener);
        
        return listener;
    
public voidprocessEntityListeners(java.lang.Class entityClass, java.lang.ClassLoader loader)
INTERNAL: (Overridden in XMLClassAccessor) Process the @EntityListeners for this class accessor.

        EntityListeners entityListeners = getAnnotation(EntityListeners.class);
        
        if (entityListeners != null) {
            for (Class entityListener : entityListeners.value()) {
                MetadataEntityListener listener = new MetadataEntityListener(entityListener, entityClass);
                
                // Process the candidate callback methods for this listener ...
                processCallbackMethods(MetadataHelper.getCandidateCallbackMethodsForEntityListener(listener), listener);
                
                // Add the entity listener to the descriptor event manager.    
                m_descriptor.addEntityListenerEventListener(listener);
            }
        }
    
protected voidprocessExcludeDefaultListeners()
INTERNAL: (Overridden in XMLClassAccessor) Process the @ExcludeDefaultListeners if one is specified (taking metadata-complete into consideration).

        // Don't overrite a true flag that could be set from a subclass
        // that already exlcuded them.
        if (isAnnotationPresent(ExcludeDefaultListeners.class)) {
            m_descriptor.setExcludeDefaultListeners(true);
        }
    
protected voidprocessExcludeSuperclassListeners()
INTERNAL: (Overridden in XMLClassAccessor) Process the @ExcludeSuperclassListeners if one is specified (taking metadata-complete into consideration).

        // Don't overrite a true flag that could be set from a subclass
        // that already exlcuded them.
        if (isAnnotationPresent(ExcludeSuperclassListeners.class)) {
            m_descriptor.setExcludeSuperclassListeners(true);
        }
    
protected voidprocessIdClass()
INTERNAL: (Overridden in XMLClassAccessor) Process an @IdClass.

        IdClass idClass = getAnnotation(IdClass.class);
        
        if (idClass != null) {
            processIdClass(idClass.value(), m_logger.IGNORE_ID_CLASS_ANNOTATION);
        }
    
protected voidprocessIdClass(java.lang.Class idClass, java.lang.String ignoreCtx)
INTERNAL: Process an @IdClass or id-class element. It is used to specify composite primary keys. The primary keys will be processed and stored from the PK class so that they may be validated against the fields or properties of the entity bean. The access type of a primary key class is determined by the access type of the entity for which it is the primary key. NOTE: the class passed in may be a mapped-superclass or entity.

        if (m_descriptor.ignoreIDs()) {
            m_logger.logWarningMessage(ignoreCtx, m_descriptor, idClass);
        } else {
            m_descriptor.setPKClass(idClass);
                
            if (m_descriptor.usesPropertyAccess()) {
                for (Method method : MetadataHelper.getDeclaredMethods(idClass)) {
                    String methodName = method.getName();
                
                    if (MetadataHelper.isValidPersistenceMethodName(methodName)) {
                        m_descriptor.addPKClassId(MetadataHelper.getAttributeNameFromMethodName(methodName), MetadataHelper.getGenericReturnType(method));
                    }
                }
            } else {
                for (Field field : MetadataHelper.getFields(idClass)) {
                    m_descriptor.addPKClassId(field.getName(), MetadataHelper.getGenericType(field));
                }
            }   
        }
    
protected voidprocessInheritance()
INTERNAL: Process the @Inheritance or inheritance tag metadata for a parent of an inheritance hierarchy. One may or may not be specified for the entity class that is the root of the entity class hierarchy, so we need to default in this case.

        if (m_descriptor.ignoreInheritance()) {
            m_logger.logWarningMessage(m_logger.IGNORE_INHERITANCE, m_descriptor);
        } else {
            // Get the inheritance strategy and store it on the descriptor.
            String inheritanceStrategy = getInheritanceStrategy();
            if (inheritanceStrategy.equals("")) {
                inheritanceStrategy = InheritanceType.SINGLE_TABLE.name();
            }

            m_descriptor.setInheritanceStrategy(inheritanceStrategy);
                
            // Process the discriminator column metadata.
            processDiscriminatorColumn();
                
            // Process the discriminator value metadata.
            processDiscriminatorValue();
        }
    
protected voidprocessInheritanceSubclass(oracle.toplink.essentials.internal.ejb.cmp3.metadata.MetadataDescriptor parentDescriptor)
INTERNAL: Process the inheritance metadata for an inheritance subclass. The parent descriptor must be provided.

        // Ignore any project.xml settings.
        if (m_descriptor.ignoreInheritance()) {
            // Log a warning that we are ignoring the inheritance metadata.
            m_logger.logWarningMessage(m_logger.IGNORE_INHERITANCE, m_descriptor);
        } else {
            // Inheritance.stategy() = SINGLE_TABLE, set the flag. Unless this
            // descriptor has its own inheritance.
            if (parentDescriptor.usesSingleTableInheritanceStrategy() && ! hasInheritance()) {
                m_descriptor.setSingleTableInheritanceStrategy();
            } else {
                // Inheritance.stategy() = JOINED, look for primary key join 
                // column(s) and add multiple table key fields.
                MetadataPrimaryKeyJoinColumns primaryKeyJoinColumns = getPrimaryKeyJoinColumns(m_descriptor.getPrimaryKeyTableName(), m_descriptor.getPrimaryTableName());
                addMultipleTableKeyFields(primaryKeyJoinColumns, m_logger.INHERITANCE_PK_COLUMN, m_logger.INHERITANCE_FK_COLUMN);
            }    
            
            // Process the discriminator value, unless this descriptor has
            // its own inheritance.
            if (! hasInheritance()) {
                processDiscriminatorValue();
            }
            
            // If the root descriptor has an id class, we need to set the same 
            // id class on our descriptor.
            if (parentDescriptor.hasCompositePrimaryKey()) {
                m_descriptor.setPKClass(parentDescriptor.getPKClassName());
            }
        }
    
protected java.util.ListprocessJoinColumns(javax.persistence.JoinColumn[] joinColumns)
INTERNAL: Process and array of @JoinColumn into a list of metadata join column.

        ArrayList<MetadataJoinColumn> list = new ArrayList<MetadataJoinColumn>();
        
        for (JoinColumn joinColumn : joinColumns) {
            list.add(new MetadataJoinColumn(joinColumn));
        }
        
        return list;
    
protected voidprocessLifecycleEvent(oracle.toplink.essentials.internal.ejb.cmp3.metadata.listeners.MetadataEntityListener listener, org.w3c.dom.Node node, java.lang.String event, oracle.toplink.essentials.internal.ejb.cmp3.xml.XMLHelper helper, java.lang.reflect.Method[] candidateMethods)
INTERNAL: Process the XML lifecycle event for the given listener.

        Node eventNode = helper.getNode(node, event);
        
        if (eventNode != null) {
            String methodName = helper.getNodeValue(eventNode, XMLConstants.ATT_METHOD_NAME);
            Method method = MetadataHelper.getMethodForName(candidateMethods, methodName);

            if (method == null) {
                m_validator.throwInvalidCallbackMethod(listener.getListenerClass(), methodName);
            } else if (event.equals(XMLConstants.PRE_PERSIST)) {
                setPrePersist(method, listener);
            } else if (event.equals(XMLConstants.POST_PERSIST)) {
                setPostPersist(method, listener);
            } else if (event.equals(XMLConstants.PRE_REMOVE)) {
                setPreRemove(method, listener);
            } else if (event.equals(XMLConstants.POST_REMOVE)) {
                setPostRemove(method, listener);
            } else if (event.equals(XMLConstants.PRE_UPDATE)) {
                setPreUpdate(method, listener);
            } else if (event.equals(XMLConstants.POST_UPDATE)) {
                setPostUpdate(method, listener);
            } else if (event.equals(XMLConstants.POST_LOAD)) {
                setPostLoad(method, listener);
            }
        }
    
protected voidprocessLifecycleEvents(oracle.toplink.essentials.internal.ejb.cmp3.metadata.listeners.MetadataEntityListener listener, org.w3c.dom.Node node, oracle.toplink.essentials.internal.ejb.cmp3.xml.XMLHelper helper, java.lang.reflect.Method[] candidateMethods)
INTERNAL: Process the XML lifecycle events for the given listener.

        processLifecycleEvent(listener, node, XMLConstants.PRE_PERSIST, helper, candidateMethods);
        processLifecycleEvent(listener, node, XMLConstants.POST_PERSIST, helper, candidateMethods);
        processLifecycleEvent(listener, node, XMLConstants.PRE_REMOVE, helper, candidateMethods);
        processLifecycleEvent(listener, node, XMLConstants.POST_REMOVE, helper, candidateMethods);
        processLifecycleEvent(listener, node, XMLConstants.PRE_UPDATE, helper, candidateMethods);
        processLifecycleEvent(listener, node, XMLConstants.POST_UPDATE, helper, candidateMethods);
        processLifecycleEvent(listener, node, XMLConstants.POST_LOAD, helper, candidateMethods);
    
public voidprocessListeners(java.lang.ClassLoader loader)
INTERNAL: Process the listeners for this class.

        // Step 1 - process the default listeners.
        processDefaultListeners(loader);

        // Step 2 - process the entity listeners that are defined on the entity 
        // class and mapped superclasses (taking metadata-complete into 
        // consideration). Go through the mapped superclasses first, top -> down 
        // only if the exclude superclass listeners flag is not set.    
        if (! m_descriptor.excludeSuperclassListeners()) {
            List<ClassAccessor> mappedSuperclasses = getMappedSuperclasses();
            int mappedSuperclassesSize = mappedSuperclasses.size();
            
            for (int i = mappedSuperclassesSize - 1; i >= 0; i--) {
                mappedSuperclasses.get(i).processEntityListeners(getJavaClass(), loader);
            }
        }
        
        processEntityListeners(getJavaClass(), loader); 
                
        // Step 3 - process the entity class for lifecycle callback methods. Go
        // through the mapped superclasses as well.
        MetadataEntityListener listener = processEntityEventListener(loader);
        
        if (! m_descriptor.excludeSuperclassListeners()) {
            for (ClassAccessor mappedSuperclass : getMappedSuperclasses()) {
                mappedSuperclass.processMappedSuperclassEventListener(listener, getJavaClass(), loader);
            }
        }
        
        // Add the listener only if we actually found callback methods.
        if (listener.hasCallbackMethods()) {
            m_descriptor.setEntityEventListener(listener);
        }
    
protected voidprocessMappedSuperclass()
INTERNAL: Process the @MappedSuperclass(es) if there are any. There may be several MappedSuperclasses for any given Entity.

        // Process the common class level attributes that an entity or
        // mapped superclass may define.
        processClassMetadata();
            
        // Process the accessors from the mapped superclass.
        processAccessors();
    
public voidprocessMappedSuperclassEventListener(oracle.toplink.essentials.internal.ejb.cmp3.metadata.listeners.MetadataEntityListener listener, java.lang.Class entityClass, java.lang.ClassLoader loader)
INTERNAL: (Overridden in XMLCLassAccessor) Process the mapped superclass class for lifecycle callback event methods.

        // Check the mapped superclass for lifecycle callback annotations.
        processCallbackMethods(MetadataHelper.getCandidateCallbackMethodsForMappedSuperclass(getJavaClass(), entityClass), listener);
    
protected voidprocessMappedSuperclasses()
INTERNAL: Process the @MappedSuperclass(es) if there are any. There may be several MappedSuperclasses for any given Entity.

        for (ClassAccessor mappedSuperclass : getMappedSuperclasses()) {
            mappedSuperclass.process();
        }
    
protected voidprocessNamedNativeQueries()
INTERNAL: (Overridden in XMLClassAccessor) Process a @NamedNativeQueries. The method will also look for a @NamedNativeQuery. This method currently only stores the queries if there are some. The actually query processing isn't done till addNamedQueriesToSession is called.

        // Look for a @NamedNativeQueries.
        NamedNativeQueries namedNativeQueries = getAnnotation(NamedNativeQueries.class);
        if (namedNativeQueries != null) {
            for (NamedNativeQuery namedNativeQuery : namedNativeQueries.value()) {
                processNamedNativeQuery(new MetadataNamedNativeQuery(namedNativeQuery, getJavaClass()));
            }
        }
        
        // Look for a @NamedNativeQuery.
        NamedNativeQuery namedNativeQuery = getAnnotation(NamedNativeQuery.class);
        if (namedNativeQuery != null) {
            processNamedNativeQuery(new MetadataNamedNativeQuery(namedNativeQuery, getJavaClass()));
        }
    
protected voidprocessNamedNativeQuery(oracle.toplink.essentials.internal.ejb.cmp3.metadata.queries.MetadataNamedNativeQuery namedNativeQuery)
INTERNAL: Process a MetadataNamedNativeQuery. The actually query processing isn't done till addNamedQueriesToSession is called.

        if (m_project.hasNamedNativeQuery(namedNativeQuery.getName())) {
            MetadataNamedNativeQuery existingNamedNativeQuery = m_project.getNamedNativeQuery(namedNativeQuery.getName());
            
            if (existingNamedNativeQuery.loadedFromAnnotations() && namedNativeQuery.loadedFromXML()) {
                // Override the existing query.
                m_project.addNamedNativeQuery(namedNativeQuery);
            } else {
                // Ignore the query and log a message.
                m_logger.logWarningMessage(namedNativeQuery.getIgnoreLogMessageContext(), namedNativeQuery.getLocation(), namedNativeQuery.getName());
            }
        } else {
            m_project.addNamedNativeQuery(namedNativeQuery);
        }
    
protected voidprocessNamedQueries()
INTERNAL: (Overridden in XMLClassAccessor) Process a @NamedQueries. The method will also look for a @NamedQuery. This method currently only stores the queries if there are some. The actually query processing isn't done till addNamedQueriesToSession is called.

        // Look for a @NamedQueries.
        NamedQueries namedQueries = getAnnotation(NamedQueries.class);
        
        if (namedQueries != null) {
            for (NamedQuery namedQuery : namedQueries.value()) {
                processNamedQuery(new MetadataNamedQuery(namedQuery, getJavaClass()));
            }
        }
        
        // Look for a @NamedQuery.
        NamedQuery namedQuery = getAnnotation(NamedQuery.class);
        
        if (namedQuery != null) {
            processNamedQuery(new MetadataNamedQuery(namedQuery, getJavaClass()));
        }
    
protected voidprocessNamedQuery(oracle.toplink.essentials.internal.ejb.cmp3.metadata.queries.MetadataNamedQuery namedQuery)
INTERNAL: Add a metadata named query to the project. The actually query processing isn't done till addNamedQueriesToSession is called.

        if (m_project.hasNamedQuery(namedQuery.getName())) {
            MetadataNamedQuery existingNamedQuery = m_project.getNamedQuery(namedQuery.getName());
            
            if (existingNamedQuery.loadedFromAnnotations() && namedQuery.loadedFromXML()) {
                // Override the existing query.
                m_project.addNamedQuery(namedQuery);
            } else {
                // Ignore the query and log a message.
                m_logger.logWarningMessage(namedQuery.getIgnoreLogMessageContext(), namedQuery.getLocation(), namedQuery.getName());
            }
        } else {
            m_project.addNamedQuery(namedQuery);
        }
    
protected voidprocessSecondaryTable(oracle.toplink.essentials.internal.ejb.cmp3.metadata.tables.MetadataSecondaryTable secondaryTable)
INTERNAL: Process a MetadataSecondaryTable. Do all the table name defaulting and set the correct, fully qualified name on the TopLink DatabaseTable.

        // Process any table defaults and log warning messages.
        processTable(secondaryTable, secondaryTable.getName());
        
        // Add the table to the descriptor.
        m_descriptor.addTable(secondaryTable.getDatabaseTable());
        
        // Get the primary key join column(s) and add the multiple table key fields.
        MetadataPrimaryKeyJoinColumns primaryKeyJoinColumns = secondaryTable.getPrimaryKeyJoinColumns(m_descriptor.getPrimaryTableName());
        addMultipleTableKeyFields(primaryKeyJoinColumns, m_logger.SECONDARY_TABLE_PK_COLUMN, m_logger.SECONDARY_TABLE_FK_COLUMN);
    
protected voidprocessSecondaryTables()
INTERNAL: (Overridden in XMLClassAccessor) Process a @SecondaryTables. If one isn't found, try a @SecondaryTable. WIP - If the @SecondaryTable does not define the pkJoinColumns(), we could look for PrimaryKeyJoinColumns on the class itself. This is not mandatory through.

        // Look for a SecondaryTables annotation.
        SecondaryTables secondaryTables = getAnnotation(SecondaryTables.class);
        if (secondaryTables != null) {
            if (m_descriptor.ignoreTables()) {
                m_logger.logWarningMessage(m_logger.IGNORE_SECONDARY_TABLE_ANNOTATION, getJavaClass());        
            } else {
                for (SecondaryTable secondaryTable : secondaryTables.value()) {
                    processSecondaryTable(new MetadataSecondaryTable(secondaryTable, m_logger));
                }
            }
        } else {
            // Look for a SecondaryTable annotation
            SecondaryTable secondaryTable = getAnnotation(SecondaryTable.class);
            if (secondaryTable != null) {
                if (m_descriptor.ignoreTables()) {
                    m_logger.logWarningMessage(m_logger.IGNORE_SECONDARY_TABLE_ANNOTATION, getJavaClass());        
                } else {    
                    processSecondaryTable(new MetadataSecondaryTable(secondaryTable, m_logger));
                }
            }
        }
    
protected voidprocessSqlResultSetMapping(oracle.toplink.essentials.internal.ejb.cmp3.metadata.queries.MetadataSQLResultSetMapping sqlResultSetMapping)
INTERNAL: Process an sql result set mapping metadata into a TopLink SqlResultSetMapping and store it on the session.

        
        // Initialize a new SqlResultSetMapping (with the metadata name)
        oracle.toplink.essentials.queryframework.SQLResultSetMapping mapping = new oracle.toplink.essentials.queryframework.SQLResultSetMapping(sqlResultSetMapping.getName());
        
        // Process the entity results.
        for (MetadataEntityResult eResult : sqlResultSetMapping.getEntityResults()) {
            EntityResult entityResult = new EntityResult(eResult.getEntityClass().getName());
        
            // Process the field results.
            for (MetadataFieldResult fResult : eResult.getFieldResults()) {
                entityResult.addFieldResult(new FieldResult(fResult.getName(), fResult.getColumn()));
            }
        
            // Process the discriminator value;
            entityResult.setDiscriminatorColumn(eResult.getDiscriminatorColumn());
        
            // Add the result to the SqlResultSetMapping.
            mapping.addResult(entityResult);
        }
        
        // Process the column results.
        for (String columnResult : sqlResultSetMapping.getColumnResults()) {
            mapping.addResult(new ColumnResult(columnResult));
        }
            
        getProject().getSession().getProject().addSQLResultSetMapping(mapping);
    
protected voidprocessSqlResultSetMappings()
INTERNAL: Process a @SqlResultSetMappings.

        // Look for a @SqlResultSetMappings.
        SqlResultSetMappings sqlResultSetMappings = getAnnotation(SqlResultSetMappings.class);

        if (sqlResultSetMappings != null) {
            for (SqlResultSetMapping sqlResultSetMapping : sqlResultSetMappings.value()) {
                processSqlResultSetMapping(new MetadataSQLResultSetMapping(sqlResultSetMapping));
            }
        } else {
            // Look for a @SqlResultSetMapping.
            SqlResultSetMapping sqlResultSetMapping = getAnnotation(SqlResultSetMapping.class);
            
            if (sqlResultSetMapping != null) {
                processSqlResultSetMapping(new MetadataSQLResultSetMapping(sqlResultSetMapping));
            }
        }
    
protected voidprocessTable()
INTERNAL: (Overridden in XMLClassAccessor) Process a @Table annotation.

        if (m_descriptor.ignoreTables()) {
            m_logger.logWarningMessage(m_logger.IGNORE_TABLE_ANNOTATION, getJavaClass());
        } else {
            Table table = getAnnotation(Table.class);
            processTable(new MetadataTable(table, m_logger));
        }
    
protected voidprocessTable(oracle.toplink.essentials.internal.ejb.cmp3.metadata.tables.MetadataTable table)
INTERNAL: Process a MetadataTable. Do all the table name defaulting and set the correct, fully qualified name on the TopLink DatabaseTable.

        // Process any table defaults and log warning messages.
        processTable(table, m_descriptor.getDefaultTableName());

        // Set the table on the descriptor.
        m_descriptor.setPrimaryTable(table.getDatabaseTable());
    
protected voidprocessTableAndInheritance()
INTERNAL: Process any inheritance specifics. This method will fast track any parent inheritance processing, be it specified or defaulted.

        // If we are an inheritance subclass, ensure our parent is processed 
        // first since it has information its subclasses depend on.
		if (isInheritanceSubclass()) {
            MetadataDescriptor parentDescriptor = getInheritanceParentDescriptor();
            
            // Process the parent class accesor if it hasn't already been done.
            ClassAccessor parentAccessor = parentDescriptor.getClassAccessor();
            if (parentAccessor == null) {
                parentAccessor = processAccessor(parentDescriptor);
            }
            
            // A parent, who didn't know they were a parent (a root class of an 
            // inheritance hierarchy that does not have an  @Inheritance 
            // annotation or XML tag) must process and default the inheritance 
            // parent metadata.
            if (! parentDescriptor.hasInheritance()) {
                parentAccessor.processInheritance();
            }
                
            // If this entity has inheritance metadata as well, then the 
            // inheritance stragety is mixed and we need to process the 
            // inheritance parent metadata for this entity's subclasses to 
            // process correctly.
            // WIP - check that that strategies are indeed changing ....
            if (hasInheritance()) {
                // Process the table metadata if there is one, otherwise default.
                processTable();
                
                // Process the parent inheritance specifics.
                processInheritance();
                
                // Process the inheritance subclass metadata.
                processInheritanceSubclass(parentDescriptor);
            } else {
                // Process the table information for this descriptor (for a 
                // joined strategy), if there is one specified. Must be called
                // before processing the inheritance metadata.
                if (parentDescriptor.usesJoinedInheritanceStrategy()) {
                    processTable();
                }
                
                // Process the inheritance subclass metadata.
                processInheritanceSubclass(parentDescriptor);
            }
		} else {
            // Process the table metadata if there is one, otherwise default.
            processTable();
            
            // If we have inheritance metadata, then process it now. If we are 
            // an inheritance root class that doesn't know it, a subclass will 
            // force this processing to occur.
            if (hasInheritance()) {
                processInheritance();
            }
        }
    
protected voidsetPostLoad(java.lang.reflect.Method method, oracle.toplink.essentials.internal.ejb.cmp3.metadata.listeners.MetadataEntityListener listener)
INTERNAL: Set the post load event method on the listener.

        listener.setPostBuildMethod(method);
        listener.setPostCloneMethod(method);
        listener.setPostRefreshMethod(method);
    
protected voidsetPostPersist(java.lang.reflect.Method method, oracle.toplink.essentials.internal.ejb.cmp3.metadata.listeners.MetadataEntityListener listener)
INTERNAL: Set the post persist event method on the listener.

        listener.setPostInsertMethod(method); 
    
protected voidsetPostRemove(java.lang.reflect.Method method, oracle.toplink.essentials.internal.ejb.cmp3.metadata.listeners.MetadataEntityListener listener)
INTERNAL: Set the post remove event method on the listener.

        listener.setPostDeleteMethod(method);
    
protected voidsetPostUpdate(java.lang.reflect.Method method, oracle.toplink.essentials.internal.ejb.cmp3.metadata.listeners.MetadataEntityListener listener)
INTERNAL: * Set the post update event method on the listener.

        listener.setPostUpdateMethod(method);
    
protected voidsetPrePersist(java.lang.reflect.Method method, oracle.toplink.essentials.internal.ejb.cmp3.metadata.listeners.MetadataEntityListener listener)
INTERNAL: Set the pre persist event method on the listener.

        listener.setPrePersistMethod(method);
    
protected voidsetPreRemove(java.lang.reflect.Method method, oracle.toplink.essentials.internal.ejb.cmp3.metadata.listeners.MetadataEntityListener listener)
INTERNAL: Set the pre remove event method on the listener.

        listener.setPreRemoveMethod(method);
    
protected voidsetPreUpdate(java.lang.reflect.Method method, oracle.toplink.essentials.internal.ejb.cmp3.metadata.listeners.MetadataEntityListener listener)
INTERNAL: Set the pre update event method on the listener.

        listener.setPreUpdateWithChangesMethod(method);
    
protected voidvalidatePrimaryKey()
INTERNAL: Call this method after a primary key should have been found.

        // If this descriptor has a composite primary key, check that all 
        // our composite primary key attributes were validated. 
        if (m_descriptor.hasCompositePrimaryKey()) {
            if (m_descriptor.pkClassWasNotValidated()) {
                m_validator.throwInvalidCompositePKSpecification(getJavaClass(), m_descriptor.getPKClassName());
            }
        } else {
            // Descriptor has a single primary key. Validate an id 
            // attribute was found, unless we are an inheritance subclass
            // or an aggregate descriptor.
            if (! m_descriptor.hasPrimaryKeyFields() && ! isInheritanceSubclass()) {
                m_validator.throwNoPrimaryKeyAnnotationsFound(getJavaClass());
            }
        }