FileDocCategorySizeDatePackage
CMP3Policy.javaAPI DocGlassfish v2 API27694Tue May 22 16:54:24 BST 2007oracle.toplink.essentials.internal.ejb.cmp3.base

CMP3Policy

public class CMP3Policy extends CMPPolicy
Description: Defines primary key extraction coce, and differentiates CMP3 from CMP1/2.
since
TopLink 10.1.3

Fields Summary
protected KeyElementAccessor[]
keyClassFields
Stores the fields for this classes compound primary key class if required.
protected String
pkClassName
protected Class
pkClass
Constructors Summary
public CMP3Policy()

        super();
    
Methods Summary
public voidconvertClassNamesToClasses(java.lang.ClassLoader classLoader)
INTERNAL: Convert all the class-name-based settings in this object to actual class-based settings. This method is used when converting a project that has been built with class names to a project with classes.

param
classLoader

        if(getPKClassName() != null){
            try{
                Class pkClass = null;
                if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()){
                    try {
                        pkClass = (Class)AccessController.doPrivileged(new PrivilegedClassForName(getPKClassName(), true, classLoader));
                    } catch (PrivilegedActionException exception) {
                        throw new IllegalArgumentException(ExceptionLocalization.buildMessage("pk_class_not_found", new Object[] {this.pkClassName}), exception.getException());
                        
                    }
                } else {
                    pkClass = oracle.toplink.essentials.internal.security.PrivilegedAccessHelper.getClassForName(getPKClassName(), true, classLoader);
                }
                setPKClass(pkClass);
            } catch (ClassNotFoundException exc){
                throw new IllegalArgumentException(ExceptionLocalization.buildMessage("pk_class_not_found", new Object[] {this.pkClassName}), exc);
            }
        }
    
protected java.lang.ObjectcreateBeanUsingKey(java.lang.Object key, oracle.toplink.essentials.internal.sessions.AbstractSession session)
INTERNAL: Use the key to create a bean and initialize its primary key fields. Note: If is a compound PK then a primary key object is being used. This method should only be used for 'templates' when executing queries. The bean built will not be given an EntityContext and should not be used as an actual entity bean.

param
key Object the primary key to use for initializing the bean's corresponding pk fields
return
TopLinkCmpEntity

        try {
            Object bean = this.getDescriptor().getInstantiationPolicy().buildNewInstance();
            KeyElementAccessor[] keyElements = this.getKeyClassFields(key.getClass());
            for (int index = 0; index < keyElements.length; ++index) {
                Object toWriteInto = bean;
                Object keyFieldValue = keyElements[index].getValue(key);
                DatabaseField field = keyElements[index].getDatabaseField();
                DatabaseMapping mapping = this.getDescriptor().getObjectBuilder().getMappingForAttributeName(keyElements[index].getAttributeName());
                if (mapping == null) {// must be aggregate
                    mapping = this.getDescriptor().getObjectBuilder().getMappingForField(field);
                }
                while (mapping.isAggregateObjectMapping()) {
                    Object aggregate = mapping.getRealAttributeValueFromObject(toWriteInto, session);
                    if (aggregate == null) {
                        aggregate = mapping.getReferenceDescriptor().getJavaClass().newInstance();
                        mapping.setRealAttributeValueInObject(toWriteInto, aggregate);
                    }
                    mapping = mapping.getReferenceDescriptor().getObjectBuilder().getMappingForAttributeName(keyElements[index].getAttributeName());
                    if (mapping == null) {// must be aggregate
                        mapping = this.getDescriptor().getObjectBuilder().getMappingForField(field);
                    }

                    //change the object to write into to the aggregate for the next stage of the 
                    // loop or for when we exit the loop.
                    toWriteInto = aggregate;
                }
                mapping.setRealAttributeValueInObject(toWriteInto, keyFieldValue);
            }
            return bean;
        } catch (Exception e) {
            throw DescriptorException.errorUsingPrimaryKey(key, this.getDescriptor(), e);
        }
    
public java.util.VectorcreatePkVectorFromKey(java.lang.Object key, oracle.toplink.essentials.internal.sessions.AbstractSession session)
INTERNAL: Use the key to create a TopLink primary key Vector. If the key is simple (direct mapped) then just add it to a vector, otherwise must go through the inefficient process of copying the key into the bean and extracting the key from the bean.

param
key Object the primary key to use for creating the vector
return
Vector

        // If the descriptor primary key is mapped through direct-to-field mappings,
        // then no elaborate conversion is required.
        // If key is compound, add each value to the vector.
        KeyElementAccessor[] pkElementArray = this.getKeyClassFields(key.getClass());
        Vector pkVector = new Vector(pkElementArray.length);
        for (int index = 0; index < pkElementArray.length; index++) {
            DatabaseMapping mapping = this.getDescriptor().getObjectBuilder().getMappingForAttributeName(pkElementArray[index].getAttributeName());
            if (mapping == null) {
                mapping = this.getDescriptor().getObjectBuilder().getMappingForField(pkElementArray[index].getDatabaseField());
            }
            while (mapping.isAggregateObjectMapping()) {
                mapping = mapping.getReferenceDescriptor().getObjectBuilder().getMappingForAttributeName(pkElementArray[index].getAttributeName());
                if (mapping == null) {// must be aggregate
                    mapping = this.getDescriptor().getObjectBuilder().getMappingForField(pkElementArray[index].getDatabaseField());
                }
            }
            Object fieldValue = null;
            if (mapping.isDirectToFieldMapping()) {
                fieldValue = ((AbstractDirectMapping)mapping).getFieldValue(pkElementArray[index].getValue(key), (oracle.toplink.essentials.internal.sessions.AbstractSession)session);
            } else {
                fieldValue = pkElementArray[index].getValue(key);
            }
            pkVector.add(fieldValue);
        }
        return pkVector;
    
public java.lang.ObjectcreatePrimaryKeyInstance(java.lang.Object key, oracle.toplink.essentials.internal.sessions.AbstractSession session)
INTERNAL: Create an instance of the composite primary key class for the key object.

        Object keyInstance = getPKClassInstance();
        ObjectBuilder builder = getDescriptor().getObjectBuilder();
        KeyElementAccessor[] pkElementArray = this.getKeyClassFields(getPKClass());
                
        for (int index = 0; index < pkElementArray.length; index++) {
            KeyElementAccessor accessor = pkElementArray[index];
            DatabaseMapping mapping = builder.getMappingForAttributeName(accessor.getAttributeName());
            // With session validation, the mapping shouldn't be null at this 
            // point, don't bother checking.
            
            while (mapping.isAggregateObjectMapping()) {
                mapping = mapping.getReferenceDescriptor().getObjectBuilder().getMappingForAttributeName(pkElementArray[index].getAttributeName());
            
                if (mapping == null) { // must be aggregate
                    mapping = builder.getMappingForField(accessor.getDatabaseField());
                }
            }
            
            Object fieldValue = mapping.getRealAttributeValueFromObject(key, (oracle.toplink.essentials.internal.sessions.AbstractSession) session);
            accessor.setValue(keyInstance, fieldValue);
        }
        
        return keyInstance;
    
protected oracle.toplink.essentials.internal.ejb.cmp3.base.CMP3Policy$KeyElementAccessor[]getKeyClassFields(java.lang.Class clazz)
INTERNAL:

return
Returns the keyClassFields.

        if (this.keyClassFields == null){
            this.keyClassFields = initializePrimaryKeyFields(this.pkClass == null? clazz : this.pkClass);
        }
        return this.keyClassFields;
    
public java.lang.ClassgetPKClass()
INTERNAL:

        if(this.pkClass == null && getPKClassName() == null) {
            initializePrimaryKeyFields(null);
        }
        return this.pkClass;
    
public java.lang.ObjectgetPKClassInstance()
INTERNAL:

        try {
            return getPKClass().newInstance();
        } catch (Exception ex) {
            return null;
            // WIP - this should throw an exception
        }
    
public java.lang.StringgetPKClassName()
INTERNAL:

        return pkClassName;
    
protected oracle.toplink.essentials.internal.ejb.cmp3.base.CMP3Policy$KeyElementAccessor[]initializePrimaryKeyFields(java.lang.Class keyClass)
INTERNAL: Cache the bean's primary key fields so speed up creating of primary key objects and initialization of beans. Note, we have to re-look up the fields for the bean class since these fields may have been loaded with the wrong loader (thank you Kirk). If the key is compound, we also have to look up the fields for the key.

        KeyElementAccessor[] pkAttributes = null;
        ClassDescriptor descriptor = this.getDescriptor();

        pkAttributes = new KeyElementAccessor[descriptor.getObjectBuilder().getPrimaryKeyMappings().size()];

        Iterator attributesIter = descriptor.getPrimaryKeyFields().iterator();

        // Used fields in case it is an embedded class
        for (int i = 0; attributesIter.hasNext(); i++) {
            DatabaseField field = (DatabaseField)attributesIter.next();

            // This next section looks strange but we need to check all mappings
            // for this field, not just the writable one and instead of having 
            // multiple sections of duplicate code I will just add the writable 
            // mapping to the list.
            Vector allMappings = descriptor.getObjectBuilder().getReadOnlyMappingsForField(field);
            if (allMappings == null) {
                allMappings = new Vector(1);
            } 
            allMappings.add(descriptor.getObjectBuilder().getMappingForField(field));
            
            Exception elementIsFound = null; // use exception existence to detemine if element was found, so we can throw exception later
            for (int index = (allMappings.size() - 1); index >= 0; --index) { // start with the writable first
                DatabaseMapping mapping = (DatabaseMapping) allMappings.get(index);
                
                if (mapping.isForeignReferenceMapping()) {
                    // In EJB3 this should be a direct to field mapping (either
                    // on the entity directly or on an embeddable (aggregate).
                    continue;
                } else if (mapping.isAggregateMapping()) { // in the case of aggregates drill down.
                    ObjectBuilder builder = mapping.getReferenceDescriptor().getObjectBuilder();
                    
                    Vector aggregateMappings = builder.getReadOnlyMappingsForField(field);
                    if ((aggregateMappings != null) && (!aggregateMappings.isEmpty())) {
                        // Add all the mappings from the aggregate to be
                        // processed.
                        allMappings.addAll(aggregateMappings);
                    }
                                        
                    DatabaseMapping writableMapping = builder.getMappingForField(field);
                    
                    if (writableMapping != null) {
                        // Since it may be another aggregate mapping, add it to 
                        // the allMappings list so we can drill down on it as 
                        // well.
                        allMappings.add(writableMapping);
                    }
                    
                    // Since we added the mappings from this aggregate mapping, 
                    // we should remove this aggregate mapping from the
                    // allMappings list. Otherwise, if the mapping for the 
                    // primary key field is not found in the aggregate (or 
                    // nested aggregate) then we will hit an infinite loop when
                    // searching the aggregate and its mappings.
                    // Note: This is cautionary, since in reality, this 'should'
                    // never happen, but if it does we certainly would rather
                    // throw an exception instead of causing an infinite loop.
                    allMappings.remove(mapping);
                    
                    // Update the index to parse the next mapping.
                    index = allMappings.size();
                        
                    // We modified the allMappings list, start over!
                    continue; // for loop.
                }
                
                String fieldName = mapping.getAttributeName();
                if (keyClass == null){
                    // must be a primitive
                    pkAttributes[i] = new KeyIsElementAccessor(mapping.getAttributeName(), field);
                    setPKClass(ConversionManager.getObjectClass(mapping.getAttributeClassification()));
                    elementIsFound = null;
                } else {
                    try {
                        Field keyField = null;
                        if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()){
                            try {
                                keyField = (Field)AccessController.doPrivileged(new PrivilegedGetField(keyClass, fieldName, true));
                            } catch (PrivilegedActionException exception) {
                                throw (NoSuchFieldException)exception.getException();
                            }
                        } else {
                            keyField = PrivilegedAccessHelper.getField(keyClass, fieldName, true);
                        }
                        pkAttributes[i] = new FieldAccessor(keyField, fieldName, field);
                        elementIsFound = null;
                    } catch (NoSuchFieldException ex) {
                        //must be a property
                        StringBuffer buffer = new StringBuffer();
                        buffer.append("get");
                        buffer.append(fieldName.substring(0, 1).toUpperCase());
                        buffer.append(fieldName.substring(1));
                        try {
                            Method method = null;
                            if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()){
                                try {
                                    method = (Method)AccessController.doPrivileged(new PrivilegedGetMethod(keyClass, buffer.toString(), new Class[] {  }, true));
                                } catch (PrivilegedActionException exception) {
                                    throw (NoSuchMethodException)exception.getException();
                                }
                            } else {
                                method = PrivilegedAccessHelper.getMethod(keyClass, buffer.toString(), new Class[] {  }, true);
                            }
                            pkAttributes[i] = new PropertyAccessor(method, fieldName, field);
                            elementIsFound = null;
                        } catch (NoSuchMethodException exs) {
                            // not a field not a method 
                            if (descriptor.getObjectBuilder().getPrimaryKeyMappings().size() == 1) {
                                //must be a primitive
                                pkAttributes[i] = new KeyIsElementAccessor(mapping.getAttributeName(), field);
                                setPKClass(ConversionManager.getObjectClass(mapping.getAttributeClassification()));
                                elementIsFound = null;
                            } else {
                                elementIsFound = exs;
                            }
                        }
                    }
                }
                
                if (elementIsFound == null) {
                    break;// break out of the loop we do not need to look for any more
                }
            }
            if (elementIsFound != null) {
                throw DescriptorException.errorUsingPrimaryKey(keyClass, getDescriptor(), elementIsFound);
            }
        }
        return pkAttributes;
    
public booleanisCMP3Policy()
INTERNAL: Return if this policy is for CMP3.

        return true;
    
public voidsetPKClass(java.lang.Class pkClass)
ADVANCED:

        this.pkClass = pkClass;
    
public voidsetPrimaryKeyClassName(java.lang.String pkClassName)
INTERNAL:

        this.pkClassName = pkClassName;