FileDocCategorySizeDatePackage
LocalFieldDesc.javaAPI DocGlassfish v2 API18345Fri May 04 22:35:06 BST 2007com.sun.jdo.spi.persistence.support.sqlstore.model

LocalFieldDesc

public class LocalFieldDesc extends FieldDesc

Fields Summary
final ArrayList
columnDescs
Array of ColumnElement.
private Boolean
primitiveMappedToNullableColumn
Stores this special mapping information.
private final int
primaryColumnType
SQL Column type for primary column.
private static final Class[]
nonNullableNonScaledTypes
This array specifies the precedence of Java types that are mapped to non-nullable database types without scale. The primitive type long has the highest precedence and the type Float has the lowest.
private static final Class[]
nullableNonScaledTypes
This array specifies the precedence of Java types that are mapped to nullable SQL types without scale. The type BigDecimal has the highest precedence and the primitive type float has the lowest.
private static final Class[]
nonNullableScaledTypes
This array specifies the precedence of Java types that are mapped to non-nullable SQL types with scale. The primitive type double has the highest precedence and the primitive type byte has the lowest.
private static final Class[]
nullableScaledTypes
This array specifies the precedence of Java types that are mapped to non-nullable SQL types without scale. The primitive type BigDecimal has the highest precedence and the primitive type float has the lowest.
Constructors Summary
LocalFieldDesc(ClassDesc config, ArrayList columnDescs)

        super(config);
        this.columnDescs = columnDescs;

        //Initialize primary column's type.
        primaryColumnType = getPrimaryColumn().getType();

        sqlProperties |= FieldDesc.PROP_RECORD_ON_UPDATE;
    
Methods Summary
voidcleanupTrackedFields()

        ArrayList trackedFields = getTrackedFields();

        if (trackedFields != null) {
            for (int j = 1; ; j++) {
                int index = trackedFields.size() - j;

                if (index < 0) {
                    break;
                }

                FieldDesc tf = (FieldDesc) trackedFields.get(index);

                if (tf instanceof LocalFieldDesc) {
                    break;
                }

                ArrayList foreignTrackedFields = tf.getTrackedFields();

                if (foreignTrackedFields != null) {
                    trackedFields.removeAll(foreignTrackedFields);
                }
            }
        }
    
voidcomputePrimaryTrackedPrimitiveField()
Compute the primary tracked field.

        ArrayList trackedFields = null;

        // We need to skip fields that are read-only.
        if (((trackedFields = getTrackedFields()) == null) ||
                (sqlProperties & (FieldDesc.PROP_PRIMARY_TRACKED_FIELD |
                FieldDesc.PROP_SECONDARY_TRACKED_FIELD |
                FieldDesc.PROP_READ_ONLY)) > 0) {
            return;
        }

        // We don't know which field is the primary field yet, so we set this field
        // to be secondary. Once we know that this field is primary, we can unset it.
        sqlProperties |= FieldDesc.PROP_SECONDARY_TRACKED_FIELD;

        FieldDesc primaryTrackedField = null;
        int currentPrecedence = Integer.MAX_VALUE;
        int precedence = 0;

        if ((precedence = computeTypePrecedence()) < currentPrecedence) {
            primaryTrackedField = this;
            currentPrecedence = precedence;
        }

        for (int j = 0; j < trackedFields.size(); j++) {
            FieldDesc tf = (FieldDesc) trackedFields.get(j);

            // We don't need to assign primary or secondary status for ForeignFieldDesc
            // because we don't write it to the disk.
            if (tf instanceof ForeignFieldDesc) {
                continue;
            }

            // We don't know which field is the primary field yet, so we set this field
            // to be secondary. Once we know the which field is primary, we can unset it.
            tf.sqlProperties |= FieldDesc.PROP_SECONDARY_TRACKED_FIELD;

            if ((precedence = ((LocalFieldDesc) tf).computeTypePrecedence()) < currentPrecedence) {
                primaryTrackedField = tf;
                currentPrecedence = precedence;
            }
        }

        // If we didn't find any candidate for the primary tracked field,
        // we pick f as the one.
        if (primaryTrackedField == null) {
            primaryTrackedField = this;
        }

        if (logger.isLoggable(Logger.FINEST)) {
            logger.finest("sqlstore.model.classdesc.primarytrackedfield", primaryTrackedField.getName()); // NOI18N
        }

        primaryTrackedField.sqlProperties |= FieldDesc.PROP_PRIMARY_TRACKED_FIELD;
        primaryTrackedField.sqlProperties &= ~FieldDesc.PROP_SECONDARY_TRACKED_FIELD;
    
voidcomputeTrackedPrimitiveFields()

        for (int i = 0; i < classDesc.fields.size(); i++) {
            FieldDesc tf = (FieldDesc) classDesc.fields.get(i);

            if ((tf instanceof LocalFieldDesc) && (this != tf) && (compareColumns(this, tf) == true)) {
                addTrackedField(tf);
            }
        }
    
voidcomputeTrackedRelationshipFields()


        if (((sqlProperties & FieldDesc.PROP_REF_INTEGRITY_UPDATES) == 0) &&
                ((sqlProperties & FieldDesc.PROP_PRIMARY_KEY_FIELD) == 0)) {
            return;
        }

        for (int k = 0; k < classDesc.foreignFields.size(); k++) {
            ForeignFieldDesc tf = (ForeignFieldDesc) classDesc.foreignFields.get(k);

            if (compareColumns(this, tf) == true) {
                // In the case where the relationship has cardinality LWB and UPB
                // both equal to 1, it is possible for the relationship field to
                // be mapped to same column as the primary key field. We will
                // allow this relationship field to be tracked by the primary key field.
                if (((sqlProperties & FieldDesc.PROP_PRIMARY_KEY_FIELD) > 0) &&
                        ((tf.cardinalityUPB > 1) || (tf.cardinalityLWB == 0))) {
                    continue;
                }

                // If f does not track other primitive fields, we need to
                // make it the primary tracked field because it was skipped
                // in computeTrackedPrimitiveFields().
                if (getTrackedFields() == null) {
                    sqlProperties |= FieldDesc.PROP_PRIMARY_TRACKED_FIELD;
                }

                addTrackedField(tf);

                // Mark f to indicate that it is tracking a relationship field.
                sqlProperties |= FieldDesc.PROP_TRACK_RELATIONSHIP_FIELD;
            }
        }
    
private intcomputeTypePrecedence()
This method computes the type precedence for the given field f.

return
an integer value indicating the precedence. 0 indicates highest precedence and Integer.MAX_VALUE indicates lowest.

        ColumnElement c = (ColumnElement) columnDescs.get(0);
        int sqlType = c.getType();
        Class type = getType();
        boolean isNullable = c.isNullable();
        int precedence = Integer.MAX_VALUE;

        switch (sqlType) {
            case Types.TINYINT:
            case Types.SMALLINT:
            case Types.INTEGER:
            case Types.BIGINT:
                if (isNullable) {
                    precedence = lookupTypePrecedence(type, nullableNonScaledTypes);
                } else {
                    precedence = lookupTypePrecedence(type, nonNullableNonScaledTypes);
                }
                break;
            case Types.REAL:
            case Types.FLOAT:
            case Types.DOUBLE:
                if (isNullable) {
                    precedence = lookupTypePrecedence(type, nullableScaledTypes);
                }  else {
                    precedence = lookupTypePrecedence(type, nonNullableScaledTypes);
                }
                break;
            case Types.NUMERIC:
            case Types.DECIMAL:
                int scale = -1;
                if ((scale = c.getScale().intValue()) == 0) {
                    // non scaled type
                    if (isNullable) {
                        precedence = lookupTypePrecedence(type, nullableNonScaledTypes);
                    } else {
                        precedence = lookupTypePrecedence(type, nonNullableNonScaledTypes);
                    }
                } else if (scale > 0) {
                    // scaled type
                    if (isNullable) {
                        precedence = lookupTypePrecedence(type, nullableScaledTypes);
                    } else {
                        precedence = lookupTypePrecedence(type, nonNullableScaledTypes);
                    }
                }
                break;
            case Types.CHAR:
            case Types.VARCHAR:
            case Types.LONGVARCHAR:
                if (type == String.class) {
                    precedence = 0;
                }
                break;
            case Types.DATE:
            case Types.TIMESTAMP:
                if (java.util.Date.class.isAssignableFrom(type)) {
                    precedence = 0;
                }
                break;
            case Types.BIT:
                if (type == Boolean.class) {
                    if (isNullable) {
                        precedence = 0;
                    } else {
                        precedence = 1;
                    }
                } else if (type == Boolean.TYPE) {
                    if (isNullable) {
                        precedence = 1;
                    } else {
                        precedence = 0;
                    }
                }
                break;
        }

        return precedence;
    
public java.util.IteratorgetColumnElements()
Returns an iterator on the mapped column elements.

return
An iterator on the mapped column elements.

        return columnDescs.iterator();
    
public org.netbeans.modules.dbschema.ColumnElementgetPrimaryColumn()
Gets the ColumnElement for the primary column of this field.

return
The ColumnElement for the primary column of this field.

        return ((ColumnElement) columnDescs.get(0));
    
public voidincrementValue(com.sun.jdo.spi.persistence.support.sqlstore.StateManager sm)
Increments this field in the instance managed by state manager sm by one.

param
sm State manager to be modified.

        assert isVersion();

        Long val = (Long) getValue(sm);
        long value = (val != null) ? val.longValue() : 0;

        setValue(sm, new Long(++value));
    
public static booleanisCharLobType(int sqlType)
Determines if sqltype passed to this method is to be considered a character LOB type.

return
true if field is mapped to character LOB column type. false otherwise.

        //Resolve : Need to check for all supported datbases all possible LOB types
        return
            sqlType == Types.LONGVARCHAR  ||
            sqlType == Types.CLOB;
    
public static booleanisFixedCharType(int sqlType)
Determines if the sqlType passed to this method corresponds to a fixed char type.

param
sqlType The input sqlType.
return
true if field is mapped to Types.CHAR false otherwise.

        return sqlType == Types.CHAR;
    
public booleanisMappedToLob()
Determines if this field is mapped to a LOB column type. It is assumed that lob fields are mapped to only one columns and UI and model verifications enforce it.

return
true if field is mapped to LOB column type. false otherwise.

        return
            primaryColumnType == Types.BLOB             ||

            //primaryColumnType == Types.BINARY           ||
            //primaryColumnType == Types.VARBINARY        ||
            //primaryColumnType == Types.LONGVARBINARY    ||

            isCharLobType(primaryColumnType)		||
            // If none of above, check if the field is mapped to byte[].
            // We should treat any field mapped to byte[] as mapped to a LOB.
            getEnumType() == FieldTypeEnumeration.ARRAY_BYTE_PRIMITIVE;
    
public booleanisPrimitiveMappedToNullableColumn()

        if (primitiveMappedToNullableColumn == null) {
            boolean rc = getType().isPrimitive();

            for (Iterator iter = columnDescs.iterator(); iter.hasNext() && rc; ) {
                ColumnElement c = (ColumnElement) iter.next();
                rc = c.isNullable();
            }
            primitiveMappedToNullableColumn = new Boolean(rc);
        }

        return primitiveMappedToNullableColumn.booleanValue();
    
public booleanisVersion()
Returns true if this field is a version field.

        return ((sqlProperties & FieldDesc.PROP_VERSION_FIELD) > 0);
    
private static intlookupTypePrecedence(java.lang.Class type, java.lang.Class[] typePrecedence)
This method looks up the type precedence given a typePrecedence array.

param
type the class type whose precedence we want to look up
param
typePrecedence an array of types. Possible values are:
see
#nonNullableNonScaledTypes
see
#nullableNonScaledTypes
see
#nonNullableScaledTypes
see
#nullableScaledTypes
return
an integer value indicating the precedence


                                                        
           
        for (int i = 0; i < typePrecedence.length; i++) {
            if (type == typePrecedence[i]) {
                return i;
            }
        }

        return Integer.MAX_VALUE;
    
protected voidsetupDesc(java.lang.reflect.Field f)
Calls the superclass method and disables concurrency checking for certain field types.

        super.setupDesc(f);

        // Disables concurrency check for fields mapped to LOB columns.
        if (isMappedToLob() ) {
            sqlProperties = sqlProperties & ~PROP_IN_CONCURRENCY_CHECK;
        }

        // Disables the concurrency check for scaled numeric fields.
        switch (getEnumType()) {
            case FieldTypeEnumeration.FLOAT_PRIMITIVE:
            case FieldTypeEnumeration.FLOAT:
            case FieldTypeEnumeration.DOUBLE_PRIMITIVE:
            case FieldTypeEnumeration.DOUBLE:
            case FieldTypeEnumeration.BIGDECIMAL:
                sqlProperties &= ~PROP_IN_CONCURRENCY_CHECK;
        }