FileDocCategorySizeDatePackage
MappingPolicy.javaAPI DocGlassfish v2 API58865Fri May 04 22:34:40 BST 2007com.sun.jdo.spi.persistence.generator.database

MappingPolicy

public class MappingPolicy extends Object implements Cloneable
Describes how Java classes and their fields are to be mapped to database tables and columns

Fields Summary
static final char
DOT
private static final String
CLASS_BASE
Base name to denote a class.
private static final String
FIELD_BASE
Base name to denote a field.
private static final String
RELATIONSHIP_BASE
Base name to denote a relationship field.
private static String
REGEXP_DOT
Represents a '.' in a regular expression
private static final String
INDICATOR_JDBC_PREFIX
Synonym for DatabaseGenerationConstants.INDICATOR_JDBC_PREFIX.
private static final String
INDICATOR_MAXIMUM_LENGTH
Base name to denote maximum length of a name in a database. We support different maximum lengths for table, column, and constraint names.
private static final String
INDICATOR_TABLE_NAME
Indicator that property is for a table name.
private static final String
INDICATOR_COLUMN_NAME
Indicator that property is for a column name.
private static final String
INDICATOR_JOIN_TABLE_NAME
Indicator that property is for a join table name.
private static final String
INDICATOR_CONSTRAINT_NAME
Indicator that property is for a constraint name.
private static final String
CLASS_PREFIX
Prefix of properties that denote classes.
private static final String
RELATIONSHIP_PREFIX
Prefix of properties that denote classes.
private static final String
DEFAULT_COLUMN_KEY
Name of property that provides default field-to-column name mapping.
private static final String
DEFAULT_JOIN_TABLE_KEY
Name of property that provides default jointable name mapping.
private static final String
DEFAULT_CONSTRAINT_KEY
Name of property that provides default constraint name mapping.
private static final String
DEFAULT_TABLE_KEY
Name of property that provides default class-to-table name mapping.
private static final String
TABLE_NAME_AS_CLASSNAME
Property value indicating table name must be same as class name.
private static final String
TABLE_NAME_UPPERCASE
Property value indicating table name must be upper case.
private static final String
TABLE_NAME_HASH_UPPERCASE
Property value indicating table name must be uppercase and unique.
private static final String
COLUMN_NAME_AS_FIELDNAME
Property value indicating colum name must be same as field name.
private static final String
COLUMN_NAME_UPPERCASE
Property value indicating column name must be uppercase.
private static final String
JOIN_TABLE_NAME_UPPERCASE
Property value indicating join table name must be uppercase.
private static final String
CONSTRAINT_NAME_UPPERCASE
Property value indicating constraint name must be uppercase.
private static final String
INDICATOR_SQL_FORMAT
Indicator that property is for formatting SQL
private static final String
STATEMENT_SEPARATOR_INDICATOR
The indicator for a statement separator.
private static final String
CREATE_TABLE_START_INDICATOR
The indicator for starting a "create table".
private static final String
CREATE_TABLE_END_INDICATOR
The indicator for ending a "create table".
private static final String
DROP_TABLE_INDICATOR
The indicator for starting a "drop table".
private static final String
ALTER_TABLE_ADD_CONSTRAINT_START_INDICATOR
The indicator for "add constraint".
private static final String
ALTER_TABLE_DROP_CONSTRAINT_INDICATOR
The indicator for "drop constraint".
private static final String
PRIMARY_KEY_CONSTRAINT_INDICATOR
The indicator for adding a primary key constraint.
private static final String
FOREIGN_KEY_CONSTRAINT_INDICATOR
The indicator for adding a foreign key constraint.
private static final String
COLUMN_NULLABILITY_INDICATOR
The indicator for verbose nullability.
private static final String
LOB_LOGGING_INDICATOR
The indicator for information used with LOB columns.
private static final String
PK_PREFIX
Prefix of column names which are primary key columns.
private static final String
FK_PREFIX
Prefix of column names which are foreign key columns.
private static final String
GLOBAL_NAMING_SPACE
Name of the "global" namespace.
public static final String
USE_UNIQUE_TABLE_NAMES
Property name which indicates unique table names should be generated.
private static final String
RESERVED_WORDS
Property name which indicates reserved words.
private static final String
RESERVED_WORD_UNRESERVER
When appended to a reserved word, causes it to be not-reserved.
private static final int
MAX_LEN_COUNTER
Maximum length of the counter used to create unique names with a numeric id. Note that this length includes a NAME_SEPARATOR, so that we allow for 3 digits total.
private static final int
MAX_LEN_RESERVED
Number of chars to change a reserved word into * unreserved.
private static final String
PROPERTY_FILE_DIR
Name of subdirectory in which db vendor - specific properties files are located.
private static final String
PROPERTY_FILE_EXT
Extension used by properties files.
private static final Properties
defaultProps
This is the set of all default properties.
private static final Map
jdbcTypes
Map from String names to the Integer-boxed values from java.sql.Types.
private static final Map
jdbcTypeNames
Maps from Integer-boxed values from java.sql.Types to String names.
private int
counter
Global counter for creating unique names in each of the namespaces. Note that a single counter is used across all namespaces.
private Map
namespaces
Map from namespaces to Set of names defined in each namespace. Used to ensure uniqueness within namespaces.
private boolean
uniqueTableName
Indicates whether or not generated table names should include a unique value as part of their names.
private final Set
reservedWords
Set of reserved words for a particular policy.
private static Set
defaultReservedWords
Set of reserved words for the default database.
private final Map
dbJdbcInfoMap
Map from the string names of the java types (e.g. "java.lang.String") to a JDBCInfo of information about the corresponding java.sql.Types type. Different for different dbvendor types, but the same instance, per dbvendor, is shared by all MappingPolicy instances.
private Map
userJdbcInfoMap
Similar to {@link #dbJdbcInfoMap}, but is reinitialized by each clone(). Contains user-provided overrides of the information in dbjdbcInfoMap.
private final Map
sqlInfo
Map from a boxed value based on fields in java.sql.Types to the String name of a SQL type.
private int
tableNameMaxLength
Maximum length of the name of a table.
private int
columnNameMaxLength
Maximum length of the name of a column.
private int
constraintNameMaxLength
Maximum length of the name of a constraint.
private String
statementSeparator
The SQL for a statement separator.
private String
createTableStart
The SQL for starting a "create table".
private String
createTableEnd
The SQL for ending a "create table".
private String
dropTable
The SQL for "drop table".
private String
alterTableAddConstraintStart
The SQL for "add constraint".
private String
alterTableDropConstraint
The SQL for "drop constraint".
private String
primaryKeyConstraint
The SQL for adding a primary key constraint.
private String
foreignKeyConstraint
The SQL for adding a foreign key constraint.
private String
columnNullability
The SQL for indicating column nullability
private String
lobLogging
The SQL for indicating LOB column logging
private final Map
namingPolicy
Map from the encoded name of a policy to its value. For example, a class name's naming policy would be encoded as ".table-name".
private static final Map
instances
Map from database vendor names to instances of MappingPolicy.
private static final com.sun.jdo.spi.persistence.utility.logging.Logger
logger
Logger for warning & error messages
private static final ResourceBundle
messages
I18N message handler
Constructors Summary
private MappingPolicy()
Create the default MappingPolicy instance.


    //
    // Initialize the JDBC String to Integer map and the default (SQL92)
    // MappingPolicy.
    //

    // XXX Why initialize the SQL policy, when there's a good chance it won't
    // ever be used?  Do we really want to support unrecognized databases?
    // See comment in getMappingPolicy.  The default properties, on the other
    // hand, *do* need to be loaded.

    // XXX We need to decide what happens when an unrecognized dbvendorname
    // is given: Error?  Warning, continue running?
     
        // Initialize jdbcType map.
        jdbcTypes.put("BIGINT", new Integer(Types.BIGINT)); // NOI18N
        jdbcTypes.put("BIT", new Integer(Types.BIT)); // NOI18N
        jdbcTypes.put("BLOB", new Integer(Types.BLOB)); // NOI18N
        jdbcTypes.put("CHAR", new Integer(Types.CHAR)); // NOI18N
        jdbcTypes.put("CLOB", new Integer(Types.CLOB)); // NOI18N
        jdbcTypes.put("DATE", new Integer(Types.DATE)); // NOI18N
        jdbcTypes.put("DECIMAL", new Integer(Types.DECIMAL)); // NOI18N
        jdbcTypes.put("DOUBLE", new Integer(Types.DOUBLE)); // NOI18N
        jdbcTypes.put("INTEGER", new Integer(Types.INTEGER)); // NOI18N
        jdbcTypes.put("LONGVARBINARY", new Integer(Types.LONGVARBINARY)); // NOI18N
        jdbcTypes.put("LONGVARCHAR", new Integer(Types.LONGVARCHAR)); // NOI18N
        jdbcTypes.put("NULL", new Integer(Types.NULL)); // NOI18N
        jdbcTypes.put("REAL", new Integer(Types.REAL)); // NOI18N
        jdbcTypes.put("SMALLINT", new Integer(Types.SMALLINT)); // NOI18N
        jdbcTypes.put("TIME", new Integer(Types.TIME)); // NOI18N
        jdbcTypes.put("TIMESTAMP", new Integer(Types.TIMESTAMP)); // NOI18N
        jdbcTypes.put("TINYINT", new Integer(Types.TINYINT)); // NOI18N
        jdbcTypes.put("VARCHAR", new Integer(Types.VARCHAR)); // NOI18N
        
        jdbcTypeNames.put(new Integer(Types.BIGINT), "BIGINT"); // NOI18N
        jdbcTypeNames.put(new Integer(Types.BIT), "BIT"); // NOI18N
        jdbcTypeNames.put(new Integer(Types.BLOB), "BLOB"); // NOI18N
        jdbcTypeNames.put(new Integer(Types.CHAR), "CHAR"); // NOI18N
        jdbcTypeNames.put(new Integer(Types.CLOB), "CLOB"); // NOI18N
        jdbcTypeNames.put(new Integer(Types.DATE), "DATE"); // NOI18N
        jdbcTypeNames.put(new Integer(Types.DECIMAL), "DECIMAL"); // NOI18N
        jdbcTypeNames.put(new Integer(Types.DOUBLE), "DOUBLE"); // NOI18N
        jdbcTypeNames.put(new Integer(Types.INTEGER), "INTEGER"); // NOI18N
        jdbcTypeNames.put(new Integer(Types.LONGVARBINARY), "LONGVARBINARY"); // NOI18N
        jdbcTypeNames.put(new Integer(Types.LONGVARCHAR), "LONGVARCHAR"); // NOI18N
        jdbcTypeNames.put(new Integer(Types.NULL), "NULL"); // NOI18N
        jdbcTypeNames.put(new Integer(Types.REAL), "REAL"); // NOI18N
        jdbcTypeNames.put(new Integer(Types.SMALLINT), "SMALLINT"); // NOI18N
        jdbcTypeNames.put(new Integer(Types.TIME), "TIME"); // NOI18N
        jdbcTypeNames.put(new Integer(Types.TIMESTAMP), "TIMESTAMP"); // NOI18N
        jdbcTypeNames.put(new Integer(Types.TINYINT), "TINYINT"); // NOI18N
        jdbcTypeNames.put(new Integer(Types.VARCHAR), "VARCHAR"); // NOI18N
        
        try {

            // Create and load the default mapping policy.
            new MappingPolicy();

        } catch (Throwable ex) {
            logger.log(Logger.SEVERE,
                       I18NHelper.getMessage(
                               messages,
                               "EXC_MappingPolicyNotFound",  //NOI18N
                               DBVendorTypeHelper.DEFAULT_DB));
        }
    
        load(getPropertyFileName(DBVendorTypeHelper.DEFAULT_DB),
             defaultProps, false);
        init(defaultProps);

        // The DEFAULT_DB has reserved words for the default database type.
        // Other databases can access those same values through the
        // defaultReservedWords set.
        defaultReservedWords = reservedWords;

        instances.put(DBVendorTypeHelper.DEFAULT_DB, this);

        if (logger.isLoggable(Logger.FINEST)) {
            logger.finest("new MappingPolicy():\n" + toString()); // NOI18N
        }
    
private MappingPolicy(String databaseType)
Create a MappingPolicy for the named database type.

param
databaseType Name of the database for which a MappingPolicy is created. The name must conform to one of the .properties files in this package.

        Properties mergedProp = new Properties(defaultProps);
        load(getPropertyFileName(databaseType), mergedProp, false);
        init(mergedProp);
        instances.put(databaseType, this);        

        if (logger.isLoggable(Logger.FINEST)) {
            logger.finest("new MappingPolicy(" // NOI18N
                + databaseType + "):\n" + toString()); // NOI18N
        }
    
Methods Summary
protected java.lang.Objectclone()
Clones the vendor-specific policy for generator session. Replace the namespaces map in the clone, so that each instance has its own.

return
clone of this MappingPolicy
throws
CloneNotSupportedException never thrown

        MappingPolicy mappingPolicyClone = (MappingPolicy) super.clone();
        mappingPolicyClone.namespaces = new HashMap();
        mappingPolicyClone.uniqueTableName = false;
        mappingPolicyClone.userJdbcInfoMap = new HashMap();
        return mappingPolicyClone;
    
java.lang.StringgetAlterTableAddConstraintStart()

return
the SQL for "add constraint".

        return alterTableAddConstraintStart;
    
java.lang.StringgetAlterTableDropConstraint()

return
the SQL for "drop constraint".

        return alterTableDropConstraint;
    
public java.lang.StringgetColumnName(java.lang.String className, java.lang.String fieldName, java.lang.String tableName)
Returns the name of a column for a given field in a given class. The column name will be unique within the table.

param
className Name of the class containing the field.
param
fieldName Name of the field for which a column name is returned.
param
tableName Name of the table in which the column name is created.
return
Name of a column that is unique within the named table.


        // Get column naming policy based on className and fieldName
        StringBuffer key = new StringBuffer(className)
            .append(DOT).append(fieldName)
            .append(DOT).append(INDICATOR_COLUMN_NAME);
        String rc = (String)namingPolicy.get(key.toString());

        if (rc == null) {
            // No fieldName specific policy, so use default for className
            key = new StringBuffer(className)
                .append(DOT).append(FIELD_BASE)
                .append(DOT).append(INDICATOR_COLUMN_NAME);
            rc = (String)namingPolicy.get(key.toString());
        }

        if (rc == null) {
            // No overriding policy, so use overall default.
            rc = (String)namingPolicy.get(DEFAULT_COLUMN_KEY);
        }

        if (rc.equals(COLUMN_NAME_UPPERCASE)) {
            rc = fieldName.toUpperCase();
        } else if (rc.equals(COLUMN_NAME_AS_FIELDNAME)) {
            rc = fieldName;
        }

        return getUniqueLocalName(rc, tableName, columnNameMaxLength);
    
java.lang.StringgetColumnNullability()

return
the SQL for indicating column nullability

        return columnNullability;
    
public java.lang.StringgetConstraintColumnName(java.lang.String tableName, java.lang.String columnName)
Returns the name of the column which represents a foreign key in the named table.

param
tableName Name of the table in which the FK column will be created.
param
columnName Name of PK column in referenced table.
return
Name of the FK column in the named table.


       return getUniqueLocalName(
               new StringBuffer(tableName)
                   .append(DatabaseConstants.NAME_SEPARATOR)
                   .append(columnName).toString(),
               tableName,
               columnNameMaxLength);
    
public java.lang.StringgetConstraintName(java.lang.String relName, java.lang.String uniqueId)
Returns the name of a constraint corresponding to the named relationship.

param
relName Name of a relationship.
param
uniqueId Id that can be appened to relName to distinguish it from other relNames in the database. Will be appended only if {@link #uniqueTableName} is true.
return
Name of a constraint.

        String rc = (String)namingPolicy.get(DEFAULT_CONSTRAINT_KEY);

        if (rc.equals(CONSTRAINT_NAME_UPPERCASE)) {
            rc = FK_PREFIX + relName.toUpperCase();
        }

        if (uniqueTableName) {
            rc += uniqueId;
        }

        rc = getUniqueGlobalName(rc, constraintNameMaxLength);

        if (logger.isLoggable(Logger.FINER)) {
            logger.finer("MappingPolicy.getConstraintName: " // NOI8N
                         + relName + " -> " + rc); // NOI18N
        }

        return rc;
    
java.lang.StringgetCreateTableEnd()

return
the SQL for ending a "create table".

        return createTableEnd;
    
java.lang.StringgetCreateTableStart()

return
the SQL for starting a "create table".

        return createTableStart;
    
java.lang.StringgetDropTable()

return
the SQL for a "drop table".

        return dropTable;
    
java.lang.StringgetForeignKeyConstraint()

return
the SQL for adding a foreign key constraint.

        return foreignKeyConstraint;
    
public JDBCInfogetJDBCInfo(java.lang.String fieldName, java.lang.String fieldType)
Returns JDBC type information corresponding to the given field name and type. If fieldName is null or there is no fieldName - specific information already existing, the default for the given fieldType is returned. Otherwise, information specific to the fieldName is returned. Note: It is possible to have a field in a class have the same name as another class; this mechanism is not robust in that case:
class Foo { }

class MyFoo {
Foo Foo = new Foo();
}
We think this obfuscation unlikely to occur.

param
fieldName Name of field for which information is needed. May be null, in which case only fieldType is used to determine returned information.
param
fieldType Name of a Java type.
return
JDBCInfo representing the field or type.

        JDBCInfo rc = null;

        if (logger.isLoggable(Logger.FINEST)) {
            logger.finest("Entering MappingPolicy.getJDBCInfo: " // NOI18N
                          + fieldName + ", " + fieldType); // NOI18N
        }

        if (null != fieldName) {

            // If fieldName is given, try to find a JDBCInfo using that name.
            // Looking up fieldName only makes sense in userJdbcInfoMap
            // which contains the user's overrides.
            rc = (JDBCInfo) userJdbcInfoMap.get(fieldName);
            if (null != rc && (! rc.isComplete())) {

                // There is an override for the field named fieldName, but
                // it is not complete, i.e., not all possible information
                // about the field was provided in the user override.
                //
                // Choose a JDBCInfo to use to complete the information in rc.
                // If the user override specifies a type and there is
                // information about that type for the database, use that.
                // Otherwise, use the given fieldType.
                JDBCInfo ji = null;
                if (rc.hasJdbcType()) {
                    ji = getdbJDBCInfo(rc.getJdbcType());
                }
                if (null == ji) {
                    ji = getdbJDBCInfo(fieldType);
                }

                // Fill in the rest of the fields in rc with values from ji.
                rc.complete(ji);
            }
        }

        if (null == rc) {

            // Either fieldName is null, or there is no JDBCInfo specific to
            // fieldName, so use fieldType.
            rc = getdbJDBCInfo(fieldType);
        }

        // If dbJdbcInfoMap has an entry for rc's jdbc type, replace rc's jdbc
        // type with the result of the mapping.  This allows, for example, a
        // user to specify that a field should be represented by a CLOB, when
        // the database and/or driver do not support that but do support
        // LONGVARCHAR (e.g. Sybase).
        JDBCInfo ji = getdbJDBCInfo(rc.getJdbcType());
        rc.override(ji);

        if (logger.isLoggable(Logger.FINEST)) {
            logger.finest("Leaving MappingPolicy.getJDBCInfo: " // NOI18N
                          + fieldName + ", " + fieldType // NOI18N
                          + " => " + rc); // NOI18N
        }

        return rc;
    
static java.lang.IntegergetJdbcType(java.lang.String jdbcTypeName)
Returns the boxed form of the java.sql.Types value corresponding to the given name.

param
jdbcStringType Name of the value to return.
return
Value from java.sql.Types, wrapped into an Integer, or null if jdbcTypeName is not that of a recognized JDBC type.

        return (Integer) jdbcTypes.get(jdbcTypeName.toUpperCase());
    
public static java.lang.StringgetJdbcTypeName(int type)
Provide the String name of a JDBC type, as per java.sql.Types.

param
type A value from java.sql.Types
return
the String name corresponding to type
throws
IllegalArgumentException if type is not recognized as being a valid member of java.sql.Types. Note that only a subset of the types in java.sql.Types are recognized.

        String rc = (String) jdbcTypeNames.get(new Integer(type));
        if (null == rc) {
            throw new IllegalArgumentException();
        }
        return rc;
    
public java.lang.StringgetJoinTableName(java.lang.String className1, java.lang.String className2)
Returns the name of a join table which joins the tables that correspond to the two named classes.

param
className1 Name of one class to join.
param
className2 Name of the other class to join.
return
Name of a join table.

        String rc = (String)namingPolicy.get(DEFAULT_JOIN_TABLE_KEY);

        if (rc.equals(JOIN_TABLE_NAME_UPPERCASE)) {
            rc = (className1 + className2).toUpperCase();
        }
        return getUniqueGlobalName(rc, tableNameMaxLength);
    
java.lang.StringgetLobLogging()

return
the SQL for indicating LOB column logging

        return lobLogging;
    
public static synchronized com.sun.jdo.spi.persistence.generator.database.MappingPolicygetMappingPolicy(java.lang.String databaseType)
Returns a vendor-specifc MappingPolicy instance. This method always returns a copy (clone) of the known MappingPolicy to allow for user-specific overrides.

param
databaseType a database vendor name as a String.
return
MappingPolicy instance corresponding to the provided database vendor name.
throws
IOException if there are problems reading the vendor- specific mappinng policy file

               
        if (logger.isLoggable(Logger.FINE)) {
            logger.fine("get MappingPolicy"+databaseType); // NOI18N
        }
        
        MappingPolicy mappingPolicy = null;
        try {
            if (databaseType == null) {
                databaseType = DBVendorTypeHelper.DEFAULT_DB;
                // XXX FIXME Need to log a warning and report to user that we
                // are *not* using databaseType given, that we are using
                // SQL92 instead, and provide list of recognized names.
            }
            mappingPolicy = (MappingPolicy) instances.get(databaseType);
            if (mappingPolicy == null) {
                mappingPolicy = new MappingPolicy(databaseType);
            }
            mappingPolicy = (MappingPolicy) mappingPolicy.clone();
        } catch (CloneNotSupportedException ec) {
            // ignore it because it will not happen
        }
        return mappingPolicy;
    
public static java.lang.StringgetOverrideForLength(java.lang.String className, java.lang.String fieldName)
Provides a String that can be recognized as a policy to override the default length of a field.

param
className name of a class
param
fieldName name of a field in that class
return
a String that can be used as the name of a length override for a field in a class.

        
        return className
            + DOT + fieldName
            + DOT + DatabaseGenerationConstants.INDICATOR_JDBC_LENGTH;
    
public static java.lang.StringgetOverrideForNullability(java.lang.String className, java.lang.String fieldName)
Provides a String that can be recognized as a policy to override the default nullability of a field.

param
className name of a class
param
fieldName name of a field in that class
return
a String that can be used as the name of a nullability override for a field in a class.

        
        return className
            + DOT + fieldName
            + DOT + DatabaseGenerationConstants.INDICATOR_JDBC_NULLABLE;
    
public static java.lang.StringgetOverrideForPrecision(java.lang.String className, java.lang.String fieldName)
Provides a String that can be recognized as a policy to override the default precision of a field.

param
className name of a class
param
fieldName name of a field in that class
return
a String that can be used as the name of a precision override for a field in a class.

        
        return className
            + DOT + fieldName
            + DOT + DatabaseGenerationConstants.INDICATOR_JDBC_PRECISION;
    
public static java.lang.StringgetOverrideForScale(java.lang.String className, java.lang.String fieldName)
Provides a String that can be recognized as a policy to override the default scale of a field.

param
className name of a class
param
fieldName name of a field in that class
return
a String that can be used as the name of a scale override for a field in a class.

        
        return className
            + DOT + fieldName
            + DOT + DatabaseGenerationConstants.INDICATOR_JDBC_SCALE;
    
public static java.lang.StringgetOverrideForType(java.lang.String className, java.lang.String fieldName)
Provides a String that can be recognized as a policy to override the default type of a field.

param
className name of a class
param
fieldName name of a field in that class
return
a String that can be used as the name of a type override for a field in a class.

        
        return className
            + DOT + fieldName
            + DOT + DatabaseGenerationConstants.INDICATOR_JDBC_TYPE;
    
java.lang.StringgetPrimaryKeyConstraint()

return
the SQL for adding a primary key constraint.

        return primaryKeyConstraint;
    
public java.lang.StringgetPrimaryKeyConstraintName(java.lang.String tableName)
Returns the name of a PK constraint, unique-ified as required.

param
tableName Name of a table on which a constraint is to be placed.
return
Name of a constraint on named table.

        return getUniqueGlobalName(PK_PREFIX + tableName, constraintNameMaxLength);
    
private static java.lang.StringgetPropertyFileName(java.lang.String databaseType)

param
databaseType Name of a type of database.
return
Name of a file containing a description of properties for named database type.

        return PROPERTY_FILE_DIR + databaseType + PROPERTY_FILE_EXT;
    
public java.lang.StringgetSQLTypeName(int jdbcType)
Returns the String name of the SQL type for a given JDBC type.

param
jdbcType One of the values from java.sql.Types.
return
Name of SQL type corresponding to given jdbcType.

        String rc = null;

        // The name is in sqlInfo if it was loaded from one of our
        // vendor-specific properties files.
        Object o = sqlInfo.get(new Integer(jdbcType));
        if (null != o) {
            rc = (String) o;
        } else {
            // Otherwise, user has overriden, e.g. java.lang.String -> CLOB.
            rc = getJdbcTypeName(jdbcType);
        }

        return rc;
    
java.lang.StringgetStatementSeparator()

return
the SQL for a statement separator.

        return statementSeparator;
    
public java.lang.StringgetTableName(java.lang.String name, java.lang.String uniqueName)
Returns the name of a table for a given class, as per current policy.

param
name Basis for what the returned table should be named, for example the unqualified name of a class.
param
uniqueName Used if the current policy is to return a unique name. Client must provide a name that is unique to them.
return
Name to be used for table. Regardless of the current policy, the name is different from other names returned during the current run of {@link DatabaseGenerator.generate}.

        StringBuffer key =
            new StringBuffer(name).append(DOT).append(INDICATOR_TABLE_NAME);
        String rc = (String)namingPolicy.get(key.toString());

        if (rc == null) {
            rc = (String)namingPolicy.get(DEFAULT_TABLE_KEY);
        }

        if (uniqueTableName) {
            rc = TABLE_NAME_HASH_UPPERCASE;
        }

        if (rc.equals(TABLE_NAME_UPPERCASE)) {
            rc = name.toUpperCase();
        } else if (rc.equals(TABLE_NAME_AS_CLASSNAME)) {
            rc = name;
        } else if (rc.equals(TABLE_NAME_HASH_UPPERCASE)) {
            rc = uniqueName.toUpperCase();
        }
        
        return getUniqueGlobalName(rc, tableNameMaxLength);
    
private java.lang.StringgetUniqueGlobalName(java.lang.String name, int maxLen)
Return a unique name for the given name. It will be "globally" unique between invocations of method {@link #resetCounter}; the first use of a MappingPolicy instance is "reset".

param
name Name for which a unique name is returned.
return
A unique name for given name.

        return getUniqueName(name, GLOBAL_NAMING_SPACE, maxLen);
    
private java.lang.StringgetUniqueLocalName(java.lang.String colName, java.lang.String tableName, int maxLen)
Return a unique name for a column. The column will be unique within the named table.

param
colName Name of the column
param
tableName Name of the table.
return
A unique name for colName within tableName.


        return getUniqueName(colName, tableName, maxLen);
    
private java.lang.StringgetUniqueName(java.lang.String name, java.lang.String namespace, int maxLen)
Return a unique name for name. It will be unique within the given namespace.

param
name Name for which a unique name is returned.
param
space Namespace in which the returned name is unique.
return
A unique name for given name.

        String rc = name;

        // Reserve MAX_LEN_COUNTER characters for unique-ifying digits.
        maxLen -= MAX_LEN_COUNTER;

        // Name cannot be more than maxLen chars long.
        if (name.length() > maxLen) {
            rc = name.substring(0, maxLen);
        }

        // Convert to upper case for uniqueing comparisons below.
        String nameUpper = rc.toUpperCase();

        // Ensure the name we create is not a reserved word by comparing
        // nameUpper against reserved words.
        if (defaultReservedWords.contains(nameUpper)
            || reservedWords.contains(nameUpper)) {

            // Append a character that is not used as the last char of any
            // existing reserved words.  Make sure we have space for this plus
            // for any uniqueing below.  Length-limit both rc and nameUpper, so
            // that the value in the namespace and the end result have the same
            // length.
            maxLen -= MAX_LEN_RESERVED;
            if (rc.length() > maxLen) {
                // Limit nameUpper as well as rc because we need to do uniqueing
                // in a case-insensitve fashion.
                nameUpper = nameUpper.substring(0, maxLen);
                rc = rc.substring(0, maxLen);
            }
            nameUpper += RESERVED_WORD_UNRESERVER;
            rc += RESERVED_WORD_UNRESERVER;
        }
        
        Set names = (Set) namespaces.get(namespace);

        if (names == null) {
            // Name is first entry in namespace, therefore already unique, no
            // need to append counter.
            names = new HashSet();
            names.add(nameUpper);
            namespaces.put(namespace, names);

        } else if (names.contains(nameUpper)) {
            // Name is already in namespace, so make a different name by
            // appending a count to given name.
            counter++;
            rc += DatabaseConstants.NAME_SEPARATOR + counter;

        } else {
            // Add new name to namespace.
            names.add(nameUpper);
        }

        return rc;
    
private JDBCInfogetdbJDBCInfo(int jdbcType)
Gets the JDBCInfo corresponding to the type in the given JDBCInfo. I.e., it maps from one JDBCInfo to another on the basis of their types.

param
ji JDBCInfo
return
a JDBCInfo
throws
IllegalArgumentException if type is not recognized as being a valid member of java.sql.Types. Note that only a subset of the types in java.sql.Types are recognized.

        String typename = getJdbcTypeName(jdbcType);
        return (JDBCInfo) dbJdbcInfoMap.get(typename);
    
private JDBCInfogetdbJDBCInfo(java.lang.String fieldType)
Gets the JDBCInfo for the given fieldType

param
fieldType Name of the type of a field
return
a JDBCInfo for the given fieldType

        JDBCInfo rc = (JDBCInfo) dbJdbcInfoMap.get(fieldType);
        
        if (null == rc) {
            
            // There is also nothing provided for the field's
            // type, so use a BLOB.
            rc = (JDBCInfo) dbJdbcInfoMap.get("BLOB"); // NOI18N
        }
        return rc;
    
private voidinit(java.util.Properties props)
Initialize this MappingPolicy as per the values in the given properties.

param
props Properties for initializing this MappingPolicy

        // Use Enumeration instead of iterator because former gets default
        // values while latter does not.
        for (Enumeration e = props.propertyNames(); e.hasMoreElements();) {
            String name = (String) e.nextElement();
            String value = props.getProperty(name);

            if (name.equals(RESERVED_WORDS)) {
                initReservedWords(value);
                continue;
            }
                
            // The indicator is the last DOT-separated substring in name.
            String indicator = null;
            StringTokenizer nameParser =
                new StringTokenizer(name, String.valueOf(DOT));
            while (nameParser.hasMoreTokens()) {
                indicator = nameParser.nextToken();
            }

            if (indicator.equals(INDICATOR_SQL_FORMAT)) {
                setSqlFormatEntry(name, value);

            } else if (indicator.startsWith(INDICATOR_JDBC_PREFIX)) {
                setJDBCInfoEntry(dbJdbcInfoMap, name, value, indicator);
                
            } else if (indicator.equals(INDICATOR_MAXIMUM_LENGTH)) {
                setLengthEntry(name, value);
                
            } else if (indicator.equals(INDICATOR_TABLE_NAME) || 
                       indicator.equals(INDICATOR_COLUMN_NAME) || 
                       indicator.equals(INDICATOR_JOIN_TABLE_NAME) || 
                       indicator.equals(INDICATOR_CONSTRAINT_NAME)) {
                setNamingEntry(name, value);

            } else {
                setSQLInfoEntry(name, value);
            }
        }
    
private voidinitReservedWords(java.lang.String res)
Initializes the reservedWords field.

param
res Comma-separated list of reserved words.

        StringTokenizer st = new StringTokenizer(res, ",");
        while (st.hasMoreTokens()) {
            reservedWords.add(st.nextToken().trim());
        }
    
private synchronized voidload(java.lang.String resourceName, java.util.Properties properties, boolean override)
Initializes the given properties from the given resourceName.

param
resourceName Name of the resource to open, expected to contain properties in text form.
param
properties Properties that are to be loaded.
param
override If true, treat resourceName as a filename from which to read; if false, treat resourceName as the name of a resource accessed via the class loader which loaded the MappingPolicy class.

 
        if (logger.isLoggable(Logger.FINE)) {
            logger.fine("load resource:" + resourceName); // NOI18N
        }

        InputStream bin = null;
        InputStream in = null;

        try {
            if (override) {
                in = new FileInputStream(resourceName);
            } else {
                final ClassLoader loader =
                        MappingPolicy.class.getClassLoader();
                in = (InputStream) AccessController.doPrivileged(
                        new PrivilegedAction() {

                            public Object run() {
                                Object rc = null;
                                if (loader != null) {
                                    rc =loader.getResourceAsStream(
                                            resourceName);
                                } else {
                                    rc =
                                        ClassLoader.getSystemResourceAsStream(
                                                resourceName);
                                }
                                return rc;
                            }
                        });
                if (in == null) {
                    throw new IOException(I18NHelper.getMessage(messages,
                        "EXC_ResourceNotFound", resourceName));// NOI18N
                }
            }

            bin = new BufferedInputStream(in);
            properties.load(bin);
            if (logger.isLoggable(Logger.FINE)) {
                logger.fine("load "+resourceName + " successfuly"); // NOI18N
            }
        } finally {
            try {
                bin.close();
                // XXX Need to close both streams in.close();
            } catch (Exception e) {
                // ignore
            }
        }
    
voidresetCounter()
Resets the namespaces and counter.

        namespaces.clear();
        userJdbcInfoMap.clear();
        counter = 0;
    
private voidsetJDBCInfoEntry(java.util.Map jdbcInfoMap, java.lang.String name, java.lang.String value, java.lang.String indicator)
Sets a JDBC property in this MappingPolicy.

param
Map into which property is set.
param
name Name of the policy property, including its indicator.
param
indicator The indicator, alone, which should start with "jdbc-".
param
value Value to be bound to that property.


        if (value != null) {

            // Get substring that is before the indicator, which is the name
            // of a type or of a particular field.
            String fieldOrType = name;
            int i = name.indexOf(DOT + indicator);
            if (i > 0) {
                fieldOrType = name.substring(0, i);
            }

            JDBCInfo ji = (JDBCInfo) jdbcInfoMap.get(fieldOrType);

            try {
                if (null != ji) {
                    ji.setValue(value, indicator);
                } else {
                    ji = new JDBCInfo();
                    ji.setValue(value, indicator);
                    jdbcInfoMap.put(fieldOrType, ji);
                }
            } catch (JDBCInfo.IllegalJDBCTypeException ex) {
                String msg = I18NHelper.getMessage(
                        messages,
                        "EXC_InvalidJDBCTypeName", // NOI18N
                        value, fieldOrType);
                logger.log(Logger.SEVERE, msg);
                throw new IllegalArgumentException(msg);
            }
        }
    
private voidsetLengthEntry(java.lang.String name, java.lang.String value)
Sets a name length attribute.

param
name Name of the attribute to set. Should be INDICATOR_TABLE_NAME, INDICATOR_COLUMN_NAME, or INDICATOR_CONSTRAINT_NAME.
param
value Value to which attribute is set.

        if (value != null) {

            int val = Integer.valueOf(value).intValue();

            if (name.startsWith(INDICATOR_TABLE_NAME)) {
                tableNameMaxLength = val;

            } else if (name.startsWith(INDICATOR_COLUMN_NAME)) {
                columnNameMaxLength = val;

            } else if (name.startsWith(INDICATOR_CONSTRAINT_NAME)) {
                constraintNameMaxLength = val;
            }
        }
    
private voidsetNamingEntry(java.lang.String name, java.lang.String value)
Set a naming property in this MappingPolicy.

param
name Name of the policy property.
param
value Value to be bound to that property.

        namingPolicy.put(name, value);
    
private voidsetSQLInfoEntry(java.lang.String name, java.lang.String value)
Sets a JDBC-to-SQL mapping property, that is, a mapping from a JDBC type to a SQL type.

param
name Name of a JDBC type (see {@link java.sql.Types}).
param
value SQL type to be used to represent given JDBC type in database.

        sqlInfo.put(getJdbcType(name), value);
    
private voidsetSqlFormatEntry(java.lang.String name, java.lang.String value)
Sets a SQL formatting property in this MappingPolicy.

param
name Name of the policy property, including its indicator.
param
indicator The indicator, alone, which should start with "sql-format".
param
value Value to be bound to that property.

        if (value != null) {
            if (name.startsWith(STATEMENT_SEPARATOR_INDICATOR)) {
                statementSeparator = value;

            } else if (name.startsWith(CREATE_TABLE_START_INDICATOR)) {
                createTableStart = value;

            } else if (name.startsWith(CREATE_TABLE_END_INDICATOR)) {
                createTableEnd = value;

            } else if (name.startsWith(DROP_TABLE_INDICATOR)) {
                dropTable = value;

            } else if (name.startsWith(ALTER_TABLE_ADD_CONSTRAINT_START_INDICATOR)) {
                alterTableAddConstraintStart = value;

            } else if (name.startsWith(ALTER_TABLE_DROP_CONSTRAINT_INDICATOR)) {
                alterTableDropConstraint = value;

            } else if (name.startsWith(PRIMARY_KEY_CONSTRAINT_INDICATOR)) {
                primaryKeyConstraint = value;

            } else if (name.startsWith(FOREIGN_KEY_CONSTRAINT_INDICATOR)) {
                foreignKeyConstraint = value;
                
            } else if (name.startsWith(COLUMN_NULLABILITY_INDICATOR)) {
                columnNullability = value;
                
            } else if (name.startsWith(LOB_LOGGING_INDICATOR)) {
                lobLogging = value;
            }
        }
    
public voidsetUniqueTableName(boolean uniqueTableName)
Sets whether or not unique table names should be generated.

param
uniqueTableName If true, tables names will be unique.

        this.uniqueTableName = uniqueTableName;
    
public voidsetUserPolicy(java.util.Properties props)
Sets user-provided policy to that provided in the given properties.

param
userProp Properties which override built in defaults.

        if (null != props) {

            // Look for and set JDBCInfo entries.  Use Enumeration instead of
            // iterator because former gets default values while latter does
            // not.
            for (Enumeration e = props.propertyNames(); e.hasMoreElements();) {
                String name = (String) e.nextElement();
                String value = props.getProperty(name);

                if (name.equals(USE_UNIQUE_TABLE_NAMES)) {
                    if (! StringHelper.isEmpty(value)) {
                        uniqueTableName =
                            Boolean.valueOf(value).booleanValue();
                    }
                    continue;
                }

                StringTokenizer nameParser =
                    new StringTokenizer(name, String.valueOf(DOT));

                // Get the last element from key which is separated by DOT.
                String indicator = null;
                while (nameParser.hasMoreTokens()) {
                    indicator = nameParser.nextToken();
                }

                if (indicator.startsWith(INDICATOR_JDBC_PREFIX)) {
                    setJDBCInfoEntry(userJdbcInfoMap, name, value, indicator);
                } else {
                    if (logger.isLoggable(Logger.INFO)) {
                        logger.info(
                                I18NHelper.getMessage(
                                        messages,
                                        "MSG_UnexpectedUserProp", // NOI18N
                                        name, value)); // NOI18N
                    }
                }
            }
        }
    
private java.lang.StringstringifyMap(java.util.Map m)
Debug support.

param
m Map whose keys & values are to be returned in a string.
return
The string form of m's keys and values, each pair separated from the next by a newline, with keys separated from values by '='.

        StringBuffer rc = new StringBuffer();
        for (Iterator i = m.entrySet().iterator(); i.hasNext();) {
            Map.Entry e = (Map.Entry) i.next();
            rc.append(e.getKey()).append("=") // NOI18N
                .append(e.getValue()).append("\n"); // NOI18N
        }
        return rc.toString();
    
private java.lang.StringstringifySet(java.util.Set s)
Debug support

param
s Set whose values are to be returned in a string
return
values from the given set, separated by spaces, up to 6 per line.

        StringBuffer rc = new StringBuffer();
        int count = 0;
        for (Iterator i = s.iterator(); i.hasNext();) {
            rc.append(i.next()).append(" "); // NOI18N
            if (count++ > 6) {
                rc.append("\n"); // NOI18N
                count = 0;
            }
        }
        return rc.toString();
    
public java.lang.StringtoString()
Debug support.

return
A description of this MappingPolicy in string form. Basically, all it's "interesting" values.

        StringBuffer rc = new StringBuffer(
            "statementSeparator=" + statementSeparator // NOI18N
            + "\ncreateTableStart=" + createTableStart // NOI18N
            + "\ncreateTableEnd=" + createTableEnd // NOI18N
            + "\ndropTable=" + dropTable // NOI18N
            + "\nalterTableAddConstraintStart=" + alterTableAddConstraintStart // NOI18N
            + "\nalterTableDropConstraint=" + alterTableDropConstraint // NOI18N
            + "\nprimaryKeyConstraint=" + primaryKeyConstraint // NOI18N
            + "\nforeignKeyConstraint=" + foreignKeyConstraint // NOI18N
            + "\ncolumnNullability=" + columnNullability // NOI18N
            + "\nlobLogging=" + lobLogging // NOI18N
            + "\ntableNameMaxLength=" + tableNameMaxLength // NOI18N
            + "\ncolumnNameMaxLength=" + columnNameMaxLength // NOI18N
            + "\nconstraintNameMaxLength=" + constraintNameMaxLength // NOI18N
            + "\nuniqueTableName=" + uniqueTableName // NOI18N
            + "\ncounter=" + counter // NOI18N
            + "\n\n"); // NOI18N
        rc.append("    dbJdbcInfoMap:\n").append(stringifyMap(dbJdbcInfoMap)); // NOI18N
        rc.append("    userJdbcInfoMap:\n").append(stringifyMap(userJdbcInfoMap)); // NOI18N
        rc.append("    sqlInfo:\n").append(stringifyMap(sqlInfo)); // NOI18N
        rc.append("    namingPolicy:\n").append(stringifyMap(namingPolicy)); // NOI18N
        rc.append("    namespaces:\n").append(stringifyMap(namespaces)); // NOI18N
        rc.append("    reservedWords:\n").append(stringifySet(reservedWords)); // NOI18N
        return rc.toString();