FileDocCategorySizeDatePackage
MappingGenerator.javaAPI DocGlassfish v2 API26877Fri May 04 22:34:42 BST 2007com.sun.jdo.api.persistence.mapping.ejb

MappingGenerator

public class MappingGenerator extends Object

Fields Summary
private static final String
CLASS_SUFFIX
private static final String
FAKE_NAME
private final EJBInfoHelper
infoHelper
private final com.sun.jdo.api.persistence.model.Model
model
private final AbstractNameMapper
nameMapper
private final ClassLoader
loader
private final ConversionHelper
ddHelper
private boolean
skipGeneratedFields
a boolean indicating whether the jdo model and mapping model should contain generated fields
private List
strongRefs
Constructors Summary
public MappingGenerator(EJBInfoHelper infoHelper, ClassLoader loader, boolean skipGeneratedFields)
Constructor

param
infoHelper an instance of an EJBInfoHelper
param
model a model containing mapping class and persistence class information
param
loader a class loader
param
skipGeneratedFields a boolean indicating to remove generated fields from jdo model and mapping model


                                                    
       
                
        this.infoHelper = infoHelper;
        this.model = infoHelper.getModel();
        this.loader = loader;
        this.nameMapper = infoHelper.getNameMapper();
        this.ddHelper = infoHelper.createConversionHelper();
        this.skipGeneratedFields = skipGeneratedFields;
    
Methods Summary
public voidcleanup()
Clean up strong reference. It should be called by end of deployment or deploytool.

        // Remove the strong references to MappingClassElements
        // needed during deployment. The mapping class cache
        // can now be cleaned up by the garbage collector.
        strongRefs.clear();
    
public DatabaseGenerator.ResultsgenerateMappingClasses(java.lang.String dbName, java.lang.String uniqueTableNames, java.util.Properties userPolicy, java.lang.String inputFilesPath)
Create mapping classes and schema based on database vendor name.

param
dbName a string for database vendor name
param
uniqueTableNames a string to determin if use unique table names during database generation
param
userPolicy a property object holding user overrides
param
inputFilesPath a directory where sun-cmp-mappings.xml is located
throws
IOException
throws
Schema2BeansException
throws
ModelException
throws
DBException
throws
ConversionException


        // generate mapping classes and dbschema in memory
        SunCmpMappings sunCmpMappings = null;

        // sun-cmp-mappings.xml does not exist, use DatabaseGenerator
        // to generate sun-cmp-mappings.xml, *.dbschema

        List pcClasses = new ArrayList();
        sunCmpMappings = getPartialSunCmpMappings(
                pcClasses, 
                Boolean.valueOf(uniqueTableNames).booleanValue());

        // load real jdo model and fake mapping model in memory
        ddHelper.setEnsureValidation(false);

        // create fake schema for partial mapping
        SchemaElement fakeSchema = new SchemaElement(new SchemaElementImpl());
        fakeSchema.setName(DBIdentifier.create(FAKE_NAME));

        // add newly created fake schema to SchemaElement cache
        SchemaElement.addToCache(fakeSchema);

        // pass null as class loader in order for MappingFile to load schema
        // from cache not from disk.
        loadMappingClasses(sunCmpMappings, null);

        DatabaseGenerator.Results results = generateSchema(pcClasses,
                dbName, uniqueTableNames, userPolicy);

        SchemaElement schema = results.getSchema();
        Set mappingClasses = results.getMappingClasses();

        // remove fake schema from cache since the correct schema is generated.
        SchemaElement.removeFromCache(FAKE_NAME);

        // clean up old version of schema in SchemaElement cache
        // if there is one
        SchemaElement.removeFromCache(schema.getName().getName());

        // add newly created schema to SchemaElement cache
        SchemaElement.addToCache(schema);

        // update mapping classes
        updateMappingClasses(mappingClasses);

        // If skipGeneratedFields is set to true, the generated fields should 
        // not be kept in jdo model and mapping model. 
        // Remove generated fields from jdo model and mapping 
        // model before returning the result.
        if (skipGeneratedFields) {
            Iterator iter = mappingClasses.iterator();
            while (iter.hasNext()) {
                MappingClassElement mapClassElt = (MappingClassElement)iter.next();
                if (mapClassElt != null) {
                    String className = mapClassElt.getName();
                    String ejbName = nameMapper.getEjbNameForPersistenceClass(
                        className);

                    PersistenceClassElement pce = (PersistenceClassElement)
                            model.getPersistenceClass(className);
                    PersistenceFieldElement[] allFields = pce.getFields();
                    if (allFields != null) {
                        List generatedFieldList = new ArrayList();

                        // In order to avoid concurrentmod exception,
                        // loop through all persistence fields to put generated
                        // fields in a list, loop though the list to remove
                        // the generated fields from the model.
                        for (int i = 0; i < allFields.length; i++) { 
                            PersistenceFieldElement pfe = allFields[i];
                            if (pfe != null) { 
                                String pFieldName = pfe.getName();
                                String ejbFieldName = nameMapper.
                                    getEjbFieldForPersistenceField(className, 
                                    pFieldName);
                                if (nameMapper.isGeneratedField(ejbName, 
                                    ejbFieldName)) {
                                    generatedFieldList.add(pfe);
                                }
                            }
                        }

                        // If the field is a version field, don't remove it 
                        // from the model even though it is generated because 
                        // it is needed to hold the version column information.
                        Iterator iterator = generatedFieldList.iterator();
                        while (iterator.hasNext()) {
                            PersistenceFieldElement pfe = 
                                (PersistenceFieldElement)iterator.next();
                            MappingFieldElement mfe = mapClassElt.
                                 getField(pfe.getName());
                            if (mfe != null && (!mfe.isVersion())) {
                                model.removeFieldElement(pfe);
                                mapClassElt.removeField(mfe);
                            }
                        }
                    }
                }
            }
        }

        return results;
    
private DatabaseGenerator.ResultsgenerateSchema(java.util.List pcClasses, java.lang.String dbName, java.lang.String useUniqueTableNames, java.util.Properties userPolicy)
Call DatabaseGenerator to generate database model and mapping model

param
pcClasses a list of DatabaseGenerator.GeneratorNameTuple objects
param
dbVendorName the string of database name
param
useUniqueTableNames the string to determine use of unique table names for database generation
param
userPolicy the property having user defined mappings between class field and jdbc type
return
DatabaseGenerator.Results contains mapping classes and schema
throws
IOException
throws
DBException
throws
ModelException


        MappingPolicy mappingPolicy = MappingPolicy.getMappingPolicy(dbName);
        mappingPolicy.setUserPolicy(userPolicy);

        if (isPropertyDefined(useUniqueTableNames)) {
            // It was explicitly set.
            mappingPolicy.setUniqueTableName(
                Boolean.valueOf(useUniqueTableNames).booleanValue());
        }

       return DatabaseGenerator.generate(
                model, pcClasses, mappingPolicy, 
                infoHelper.getSchemaNameToGenerate(), CLASS_SUFFIX, true);
    
protected java.lang.ClassLoadergetClassLoader()

        return loader;
    
protected ConversionHelpergetConversionHelper()

        return ddHelper;
    
protected EJBInfoHelpergetInfoHelper()

        return infoHelper;
    
protected AbstractNameMappergetNameMapper()

        return nameMapper;
    
private SunCmpMappingsgetPartialSunCmpMappings(java.util.List pcClasses, boolean useUniqueTableNames)
Generates partial sun-cmp-mapping (contains fake table name and fake column name) for MappingFile.intoMappings()

param
pcClasses a list of DatabaseGenerator.NameTuple objects
param
useUniqueTableNames a boolean to determine whether to use unique table names during database generation
return
a SunCmpMappings object
throws
Schema2BeansException


       // Create a new name mapper with perisistence class name differing
        // from bean name if useUniqueTableName flag is true. 
        // So persistence class name can be used for unique table name.
        AbstractNameMapper nameMapper2 = (useUniqueTableNames) ? 
                infoHelper.createUniqueNameMapper() : nameMapper;

        SunCmpMappings mappings = null;
        mappings = new SunCmpMappings();
        SunCmpMapping mapping = new SunCmpMapping();
        mapping.setSchema(FAKE_NAME);

        Iterator iter = infoHelper.getEjbNames().iterator();
        while (iter.hasNext()) {
            String ejbName = (String)iter.next();
            String pcClass = ddHelper.getMappedClassName(ejbName);
            String hashClassName = JavaTypeHelper.getShortClassName(pcClass);

            // Make sure hash class name differs from ejb name 
            // if useUniqueTableName flag is true.
            // if useUniqueTableName flag is false, ejb name is used for 
            // table name and hash class name is ignored. 
            if (useUniqueTableNames & hashClassName.equals(ejbName)) {
                hashClassName = JavaTypeHelper.getShortClassName(
                       nameMapper2.getPersistenceClassForEjbName(ejbName));
                pcClasses.add(new DatabaseGenerator.NameTuple(
                       pcClass, ejbName, hashClassName));
            }
            else {
                pcClasses.add(new DatabaseGenerator.NameTuple(
                       pcClass, ejbName));
            }

            EntityMapping entity = new EntityMapping();
            entity.setEjbName(ejbName);
            entity.setTableName(FAKE_NAME);
            Collection fields = infoHelper.getFieldsForEjb(ejbName);
            Collection rels = infoHelper.getRelationshipsForEjb(ejbName);
            fields.removeAll(rels);
            // cmp field
            Iterator fIter = fields.iterator();
            while (fIter.hasNext()) {
                String fieldName = (String)fIter.next();
                CmpFieldMapping cmpField = new CmpFieldMapping();
                cmpField.setFieldName(fieldName);
                cmpField.addColumnName(FAKE_NAME);
                entity.addCmpFieldMapping(cmpField);
            } 
            // cmr field
            fIter = rels.iterator();
            while (fIter.hasNext()) {
                String fieldName = (String)fIter.next();
                CmrFieldMapping cmrField = new CmrFieldMapping();
                cmrField.setCmrFieldName(fieldName);
                ColumnPair columnPair = new ColumnPair();
                columnPair.addColumnName(FAKE_NAME);
                columnPair.addColumnName(FAKE_NAME);
                cmrField.addColumnPair(columnPair);
                entity.addCmrFieldMapping(cmrField);
            }
            mapping.addEntityMapping(entity);
        }

        mappings.addSunCmpMapping(mapping);

        return mappings;
    
protected booleanisPropertyDefined(java.lang.String propertyValue)
Returns true if the specified propertyValue represents a defined value, false otherwise. This implementation returns true if the value is not empty, but subclasses may override this method to compare to a constant which represents an undefined value.

param
propertyValue the value to be tested for defined
return
true if the specified propertyValue represents a defined value, false otherwise

        return !StringHelper.isEmpty(propertyValue);
    
protected java.util.MaploadMappingClasses(SunCmpMappings sunMapping, java.lang.ClassLoader classLoader)
load mapping classes from SunCmpMappings object

param
sunMapping a SunCmpMappings object representing sun-cmp-mappings.xml in memory
param
classLoader a class loader object
return
a map object containing ejb names and mapping classes
throws
DBException
throws
ModelException
throws
ConversionException

        MappingFile mapFile = new MappingFile(classLoader);

        Map allMappings = mapFile.intoMappingClasses(sunMapping, ddHelper);

        updateMappingClasses(allMappings.values());

        return allMappings;
    
public static voidupdateColumn(ColumnElement column, int jdbcType, java.lang.Integer length, java.lang.Integer scale, java.lang.Integer precision)
Update column in the SchemaElement with jdbc type and its length, scale and precision.

param
column a ColumnElement to be updated
param
jdbcType jdbc type from java.sql.Types
param
length an Integer for length or null if it does not apply
param
scale an Integer for scale or null if it does not apply
param
precision an Integer for precision or null if it does not apply


        column.setType(jdbcType);
        column.setLength(length);
        column.setScale(scale);
        column.setPrecision(precision);
    
private voidupdateMappingClasses(java.util.Collection mappingClasses)
Puts mapping classes into model's cache

param
mappingClasses a collection of mapping classes

        Iterator iter = mappingClasses.iterator();
        while (iter.hasNext()) {
            MappingClassElement mapClassElt = (MappingClassElement)iter.next();
            //put it in the models' cache
            model.updateKeyForClass(mapClassElt, null);
            //keep a strong ref
            strongRefs.add(mapClassElt);
        }
    
public static voidupdateProperties(java.util.Properties prop, java.lang.String className, java.lang.String fieldName, int jdbcType, java.lang.Integer length, java.lang.Integer scale, java.lang.Integer precision)
This method updates properties which stores user override policy.

param
prop the property for user override
param
className a string for bean class
param
fieldName a string for field
param
jdbcType jdbc type from java.sql.Types
param
length an Integer for length or null if it does not apply
param
scale an Integer for scale or null if it does not apply
param
precision an Integer for precision or null if it does not apply


        prop.setProperty(
                MappingPolicy.getOverrideForType(className, fieldName),
                MappingPolicy.getJdbcTypeName(jdbcType));

        updateProperty(prop, MappingPolicy.getOverrideForLength(
                className, fieldName), length);

        updateProperty(prop, MappingPolicy.getOverrideForScale(
                className, fieldName), scale);

        updateProperty(prop, MappingPolicy.getOverrideForPrecision(
                className, fieldName), precision);
    
private static voidupdateProperty(java.util.Properties prop, java.lang.String key, java.lang.Integer value)
This method updates property. If the value is not null, update the property. If the value is null, remove the property.

param
prop a property object which needs to be updated
param
key a key for the property
param
value a value for the propety

        if (value != null) {
            prop.setProperty(key, value.toString());
        }
        else {
           prop.remove(key);
        }