Fields Summary |
---|
public static final int | GROUP_DEFAULT |
public static final int | GROUP_NONE |
public static final int | PROP_IN_CONCURRENCY_CHECKThis field is used for concurrency check |
public static final int | PROP_LOG_ON_UPDATEUpdate before image when this field is updated. This property is always set |
public static final int | PROP_READ_ONLYThis field is read only |
public static final int | PROP_RECORD_ON_UPDATERecord updates on this field to DB. This property is always set for primitive fields. |
public static final int | PROP_REF_INTEGRITY_UPDATESRelationship updates are processed from the side containing this field. |
public static final int | PROP_PRIMARY_TRACKED_FIELDThis field is the primary tracked field.
Primitive fields track each other if they are mapped to same columns.
One of them is made the primary tracked field as per precedence rules
on the field types. This field is used to bind values to columns while
updating the database.
RESOLVE:
Investigate the runtime behaviour for relationship fields marked primary. |
public static final int | PROP_SECONDARY_TRACKED_FIELDThis field is a secondary tracked field.
Seconday tracked primitive fields are not used for updates to the database
or for concurrency checking.
RESOLVE:
Investigate the runtime behaviour for secondary tracked relationship fields. |
public static final int | PROP_TRACK_RELATIONSHIP_FIELDThis field tracks a relationship field.
Only primitive fields can have this property set. |
public static final int | PROP_PRIMARY_KEY_FIELDThis field is part of a primary key. |
public static final int | PROP_VERSION_FIELDThis field is used for version consistency validation. |
public static final int | PROP_FOREIGN_KEY_FIELDThis field is part of a foreign key. |
private static final BigDecimal | LONG_MIN_VALUE |
private static final BigDecimal | LONG_MAX_VALUE |
public int | absoluteID |
public int | fetchGroup |
public int | concurrencyGroup |
public int | sqlProperties |
private Field | field |
private Class | fieldType |
private int | enumFieldTypeContains a translation from the field type class to int constants.
These constants can be used in switch statements on the field type. |
private String | fieldName |
private Class | declaringClass |
private Class | componentType |
private ArrayList | trackedFields |
protected final ClassDesc | classDescBack pointer to declaring class descriptor. |
protected static final com.sun.jdo.spi.persistence.utility.logging.Logger | loggerThe logger. |
protected static final ResourceBundle | messagesI18N message handler. |
Methods Summary |
---|
protected void | addTrackedField(com.sun.jdo.spi.persistence.support.sqlstore.model.FieldDesc f)
if (trackedFields == null)
trackedFields = new ArrayList();
if (logger.isLoggable(Logger.FINEST)) {
Object[] items = new Object[] {f.getName(),getName()};
logger.finest("sqlstore.model.fielddesc.addingfield",items); // NOI18N
}
trackedFields.add(f);
|
private void | assertIsValid(java.lang.Number number, double min_value, double max_value)
double x = number.doubleValue();
if (x < min_value)
throw new JDOUserException(I18NHelper.getMessage(messages,
"core.fielddesc.minvalue", // NOI18N
new Object[]{number, String.valueOf(min_value), fieldType.getName()}));
if (x > max_value)
throw new JDOUserException(I18NHelper.getMessage(messages,
"core.fielddesc.maxvalue", // NOI18N
new Object[]{number, String.valueOf(max_value), fieldType.getName()}));
|
private void | assertIsValidLong(java.lang.Number number)
BigDecimal bd = null;
if (number instanceof BigDecimal) {
bd = (BigDecimal) number;
} else {
bd = new BigDecimal(number.toString());
}
if (bd.compareTo(LONG_MIN_VALUE) < 0) {
throw new JDOUserException(I18NHelper.getMessage(messages,
"core.fielddesc.minvalue", // NOI18N
new Object[]{number, String.valueOf(Long.MIN_VALUE),
fieldType.getName()}));
} else if (bd.compareTo(LONG_MAX_VALUE) > 0) {
throw new JDOUserException(I18NHelper.getMessage(messages,
"core.fielddesc.maxvalue", // NOI18N
new Object[]{number, String.valueOf(Long.MAX_VALUE),
fieldType.getName()}));
}
|
static boolean | compareColumns(com.sun.jdo.spi.persistence.support.sqlstore.model.FieldDesc f1, com.sun.jdo.spi.persistence.support.sqlstore.model.FieldDesc f2)This method compares the column lists between to fields to see if they match.
If f1 and f2 are both primitive fields, we do an exact match.
If f1 is primitve and f2 is a relationship field, we do an at-least-one match.
If both f1 and f2 are relationship fields, we do an exact match.
ArrayList columnList1 = null;
ArrayList columnList2 = null;
ArrayList columnList3 = null;
ArrayList columnList4 = null;
boolean exactMatch = false;
// For LocalFieldDesc, we use columnDescs for comparison.
// Otherwise, we use localColumns for comparison.
if (f1 instanceof LocalFieldDesc) {
columnList1 = ((LocalFieldDesc) f1).columnDescs;
if (f2 instanceof LocalFieldDesc) {
columnList2 = ((LocalFieldDesc) f2).columnDescs;
// Not sure yet whether we need to a exact match
// here yet.
exactMatch = true;
} else {
// We are comparing LocalFieldDesc and ForeignFieldDesc.
// We do not need an exact match. The relationship must change,
// if one of the LocalFieldDesc's columns is changed.
columnList2 = ((ForeignFieldDesc) f2).localColumns;
}
} else {
if (f2 instanceof LocalFieldDesc) {
return false;
} else {
ForeignFieldDesc ff1 = (ForeignFieldDesc) f1;
ForeignFieldDesc ff2 = (ForeignFieldDesc) f2;
if (ff1.useJoinTable() && ff2.useJoinTable()) {
columnList1 = ff1.assocLocalColumns;
columnList2 = ff2.assocLocalColumns;
columnList3 = ff1.assocForeignColumns;
columnList4 = ff2.assocForeignColumns;
} else if (!ff1.useJoinTable() && !ff2.useJoinTable()) {
columnList1 = ff1.localColumns;
columnList2 = ff2.localColumns;
columnList3 = ff1.foreignColumns;
columnList4 = ff2.foreignColumns;
} else {
return false;
}
exactMatch = true;
}
}
boolean found = false;
for (int k = 0; k < 2; k++) {
if (k == 1) {
if (columnList3 != null) {
columnList1 = columnList3;
columnList2 = columnList4;
} else {
break;
}
}
int size1 = columnList1.size();
int size2 = columnList2.size();
if (exactMatch && (size1 != size2)) {
return false;
}
for (int i = 0; i < size1; i++) {
found = false;
ColumnElement c1 = (ColumnElement) columnList1.get(i);
// Find if any column of columnList2 matches with c1.
for (int j = 0; j < size2; j++) {
ColumnElement c2 = (ColumnElement) columnList2.get(j);
if (c1.getName().getFullName().equals(c2.getName().getFullName())) {
found = true;
}
}
// If we are doing an exact match, and no match is found,
// we return false.
if (exactMatch && !found) {
return false;
}
// If we are not doing an exact match and a match is found,
// we return true;
if (!exactMatch && found) {
return true;
}
}
}
// If found is true, that means we got here because the two column lists match
// exactly. Otherwise, the two column lists don't match at all.
return found;
|
abstract void | computeTrackedRelationshipFields()
|
private java.lang.Object | convertToDateFieldType(java.lang.Object value, StateManager sm)Converts value to the type given by enumFieldType .
Creates a new SCO instance if the PersistenceManager settings require SCO
creation.
if (value instanceof SCO) {
((SCO) value).unsetOwner();
}
Object retVal = createSCO(value, sm);
if (retVal == null) {
// We didn't create a SCO. This might be because we're running
// in a managed environment where we don't need to manage mutable
// objects as SCO. Simply convert value to the field type for
// this field.
retVal = convertToDateFieldType(value);
}
return retVal;
|
private java.lang.Object | convertToDateFieldType(java.lang.Object value)Returns an unmanaged Date instance. Converts value
to the field type for this field according to enumFieldType .
Object retVal = value;
if (!fieldType.equals(value.getClass())) {
// Convert to the new fieldType only.
if (value instanceof Date) {
switch (enumFieldType) {
case FieldTypeEnumeration.UTIL_DATE:
retVal = new java.util.Date(((Date) value).getTime());
break;
case FieldTypeEnumeration.SQL_DATE:
retVal = new java.sql.Date(((Date) value).getTime());
break;
case FieldTypeEnumeration.SQL_TIME:
retVal = new java.sql.Time(((Date) value).getTime());
break;
case FieldTypeEnumeration.SQL_TIMESTAMP:
retVal = new java.sql.Timestamp(((Date) value).getTime());
// Adjust nano second information for Timestamps.
// NOTE: The constructor java.sql.Timestamp(long) calculates nano
// seconds. If the old and new instance both represent Timestamps,
// the calculation truncates nano second information from the
// original object, see java.sql.Timestamp#getTime().
if (value instanceof java.sql.Timestamp) {
// Overwrite nano second information with the original value.
((java.sql.Timestamp) retVal).setNanos(((java.sql.Timestamp) value).getNanos());
}
break;
default:
}
}
}
return retVal;
|
public java.lang.Object | convertValue(java.lang.Object value, StateManager sm)
boolean debug = logger.isLoggable(Logger.FINEST);
if (value == null) {
if (debug)
logger.finest("sqlstore.model.fielddesc.convertvalue"); // NOI18N
return value;
}
if (absoluteID < 0) {
// Hidden field nothing to convert
if (debug)
logger.finest("sqlstore.model.fielddesc.convertvalue.hidden",new Integer(absoluteID)); // NOI18N
return value;
}
if (debug) {
Object[] items = new Object[] {value,value.getClass().getName(),fieldType};
logger.finest("sqlstore.model.fielddesc.convertvalue.from_to",items); // NOI18N
}
// Here, we'll try our best to convert the given value to the
// proper type before setting the value using reflection.
if (value instanceof Number) {
Number number = (Number) value;
switch (enumFieldType) {
case FieldTypeEnumeration.BOOLEAN_PRIMITIVE:
case FieldTypeEnumeration.BOOLEAN:
// Well, boolean in java is not really a number,
// but we'll try to convert it anyway. The algorithm is
// if the number is 0, set the field to false, otherwise
// set it to true.
// The easiest way to do this is to convert the number to
// a double before comparing it to 0.
if (number.doubleValue() == 0) {
value = new Boolean(false);
} else {
value = new Boolean(true);
}
break;
case FieldTypeEnumeration.BYTE_PRIMITIVE:
case FieldTypeEnumeration.BYTE:
if (!(value instanceof Byte)) {
assertIsValid(number, Byte.MIN_VALUE, Byte.MAX_VALUE);
value = new Byte(number.byteValue());
}
break;
case FieldTypeEnumeration.SHORT_PRIMITIVE:
case FieldTypeEnumeration.SHORT:
if (!(value instanceof Short)) {
assertIsValid(number, Short.MIN_VALUE, Short.MAX_VALUE);
value = new Short(number.shortValue());
}
break;
case FieldTypeEnumeration.INTEGER_PRIMITIVE:
case FieldTypeEnumeration.INTEGER:
if (!(value instanceof Integer)) {
assertIsValid(number, Integer.MIN_VALUE, Integer.MAX_VALUE);
value = new Integer(number.intValue());
}
break;
case FieldTypeEnumeration.LONG_PRIMITIVE:
case FieldTypeEnumeration.LONG:
if (!(value instanceof Long)) {
assertIsValidLong(number);
value = new Long(number.longValue());
}
break;
case FieldTypeEnumeration.FLOAT_PRIMITIVE:
case FieldTypeEnumeration.FLOAT:
if (!(value instanceof Float))
value = new Float(number.floatValue());
break;
case FieldTypeEnumeration.DOUBLE_PRIMITIVE:
case FieldTypeEnumeration.DOUBLE:
if (!(value instanceof Double)) {
// FIX FOR CONVERT FROM FLOAT.
if (value instanceof Float)
value = new Double(number.toString());
else
value = new Double(number.doubleValue());
}
break;
case FieldTypeEnumeration.BIGDECIMAL:
if (!(value instanceof BigDecimal)) {
if (value instanceof Double)
value = new BigDecimal(number.doubleValue());
else if (value instanceof BigInteger)
value = new BigDecimal((java.math.BigInteger) value);
else
value = new BigDecimal(number.toString());
}
break;
case FieldTypeEnumeration.BIGINTEGER:
if (!(value instanceof BigInteger)) {
if (value instanceof BigDecimal)
value = ((BigDecimal) value).toBigInteger();
else
value = new BigInteger(number.toString());
}
break;
}
} else {
switch (enumFieldType) {
case FieldTypeEnumeration.STRING:
// If the value is not a String, we take the string representation
// of the value.
if (!(value instanceof String)) {
value = value.toString();
}
break;
case FieldTypeEnumeration.UTIL_DATE:
case FieldTypeEnumeration.SQL_DATE:
case FieldTypeEnumeration.SQL_TIME:
case FieldTypeEnumeration.SQL_TIMESTAMP:
value = convertToDateFieldType(value, sm);
break;
case FieldTypeEnumeration.CHARACTER_PRIMITIVE:
case FieldTypeEnumeration.CHARACTER:
// If the value is not a character, we take the first character
// of the string representation.
if (!(value instanceof Character)) {
String str = value.toString();
value = getCharFromString(str);
}
break;
case FieldTypeEnumeration.BOOLEAN_PRIMITIVE:
case FieldTypeEnumeration.BOOLEAN:
// If the value is not a boolean, we construct a boolean
// using its string value.
if (!(value instanceof Boolean)) {
if ((value instanceof String) &&
(value).equals("1")) // NOI18N
value = "true"; // NOI18N
value = new Boolean(value.toString());
}
break;
}
}
return value;
|
public java.lang.Object | createSCO(java.lang.Object value, StateManager sm)Creates a new SCO instance. Therefore checks if PersistenceManager
settings require SCO creation. SCOs will typically be created
in a non managed environment.
Object retVal = null;
PersistenceManager pm = null;
if (sm != null) {
pm = (PersistenceManager) sm.getPersistenceManagerInternal();
}
if (pm != null && pm.getRequireTrackedSCO()) {
// Create a SCO instance and set values.
retVal = pm.newSCOInstanceInternal(fieldType,
sm.getPersistent(),
getName());
initializeSCO(retVal, value);
}
return retVal;
|
public static java.lang.Character | getCharFromString(java.lang.String str)
Character retVal = null;
if (str.length() == 0) {
retVal = new Character('\0");
} else {
retVal = new Character(str.charAt(0));
}
return retVal;
|
public java.lang.Class | getComponentType()
return componentType;
|
public java.lang.Class | getDeclaringClass()
return declaringClass;
|
public int | getEnumType()
return enumFieldType;
|
public java.lang.String | getName()
if (fieldName == null)
fieldName = "hidden" + -absoluteID; // NOI18N
return fieldName;
|
public java.util.ArrayList | getTrackedFields()
return trackedFields;
|
public java.lang.Class | getType()
if (fieldType != null) return fieldType;
return Object.class;
|
public java.lang.Object | getValue(StateManager sm)
if (sm == null) return null;
if (absoluteID >= 0) {
return ((PersistenceCapable) sm.getPersistent()).jdoGetField(absoluteID);
} else {
return sm.getHiddenValue(absoluteID);
}
|
private void | initializeSCO(java.lang.Object scoVal, java.lang.Object value)Initializes the SCO instance scoVal corresponding
to value . Currently only used for dates.
switch(enumFieldType) {
case FieldTypeEnumeration.UTIL_DATE:
case FieldTypeEnumeration.SQL_DATE:
case FieldTypeEnumeration.SQL_TIME:
case FieldTypeEnumeration.SQL_TIMESTAMP:
// Initializing SCODate
if (value instanceof Date) {
// Set milliseconds information
((SCODate) scoVal).setTimeInternal(((Date) value).getTime());
// Adjust nano second information for Timestamps.
// NOTE: java.sql.Timestamp#setTime(long) recalculates nano
// seconds. If old and new instance both represent Timestamps,
// the recalculation truncates nano second information from the
// original object, see java.sql.Timestamp#getTime().
if (enumFieldType == FieldTypeEnumeration.SQL_TIMESTAMP
&& value instanceof java.sql.Timestamp) {
// Overwrite nano second information with original value
((SqlTimestamp) scoVal).setNanosInternal(((java.sql.Timestamp) value).getNanos());
}
}
break;
default:
}
|
public boolean | isForeignKeyField()Returns true if this field is a foreign key field.
return ((sqlProperties & PROP_FOREIGN_KEY_FIELD) > 0);
|
public boolean | isKeyField()Returns true if this field is a primary key field.
return ((sqlProperties & PROP_PRIMARY_KEY_FIELD) > 0);
|
public boolean | isRelationshipField()Returns true if this field is a relationship field.
return false;
|
void | setComponentType(java.lang.Class type)
this.componentType = type;
|
public void | setValue(StateManager sm, java.lang.Object value)
boolean debug = logger.isLoggable(Logger.FINEST);
if (sm == null) return;
if (absoluteID >= 0) {
if (debug) {
if ((value != null) &&
((value instanceof com.sun.jdo.api.persistence.support.PersistenceCapable) ||
(value instanceof java.util.Collection))) {
Object[] items = new Object[] {field.getName(),value.getClass()};
logger.finest("sqlstore.model.fielddesc.fieldname",items); // NOI18N
} else {
Object[] items = new Object[] {field.getName(),value};
logger.finest("sqlstore.model.fielddesc.fieldname",items); // NOI18N
}
}
// If the given value is null, and the field type is primitive
// scalar, we need to convert it to some default value. The following
// table shows the mapping:
// primitive number types (int, long, etc) --> 0
// boolean --> false
// char --> '\0'
if (value == null) {
switch (enumFieldType) {
case FieldTypeEnumeration.BOOLEAN_PRIMITIVE:
value = new Boolean(false);
break;
case FieldTypeEnumeration.CHARACTER_PRIMITIVE:
value = new Character('\0");
break;
case FieldTypeEnumeration.BYTE_PRIMITIVE:
case FieldTypeEnumeration.SHORT_PRIMITIVE:
case FieldTypeEnumeration.INTEGER_PRIMITIVE:
case FieldTypeEnumeration.LONG_PRIMITIVE:
case FieldTypeEnumeration.FLOAT_PRIMITIVE:
case FieldTypeEnumeration.DOUBLE_PRIMITIVE:
// Replace value type if necessary
value = convertValue(new Integer(0), sm);
break;
}
}
// We've tried our best to convert the value to the proper type.
// (convertValue() was called outside this class if necessary)
// Here is where we actually set the value. Anything that didn't
// get converted will get a ClassCastException.
((PersistenceCapable) sm.getPersistent()).jdoSetField(absoluteID, value);
} else {
if (debug) {
Object[] items = new Object[] {getName(),value};
logger.finest("sqlstore.model.fielddesc.fieldname",items); // NOI18N
}
sm.setHiddenValue(absoluteID, value);
}
|
void | setupDesc(java.lang.Class classType, java.lang.String name)
Field f = (Field) java.security.AccessController.doPrivileged(
new java.security.PrivilegedAction() {
public Object run() {
try {
return classType.getDeclaredField(name);
} catch (NoSuchFieldException e) {
throw new JDOFatalUserException(I18NHelper.getMessage(messages,
"core.configuration.loadfailed.field", // NOI18N
name, classType.getName()), e);
}
}
});
setupDesc(f);
|
protected void | setupDesc(java.lang.reflect.Field f)
field = f;
fieldName = f.getName();
declaringClass = field.getDeclaringClass();
fieldType = field.getType();
enumFieldType = translateToEnumType(fieldType);
if (logger.isLoggable(Logger.FINEST)) {
Object[] items= new Object[] {fieldName,fieldType};
logger.finest("sqlstore.model.fielddesc.setupdesc",items); // NOI18N
}
|
public java.lang.String | toString()
return classDesc.getName() + "." + getName(); // NOI18N
|
private static int | translateToEnumType(java.lang.Class fldType)
int retVal = FieldTypeEnumeration.NOT_ENUMERATED;
if(fldType == Boolean.TYPE ) retVal = FieldTypeEnumeration.BOOLEAN_PRIMITIVE;
else if(fldType == Character.TYPE ) retVal = FieldTypeEnumeration.CHARACTER_PRIMITIVE;
else if(fldType == Byte.TYPE ) retVal = FieldTypeEnumeration.BYTE_PRIMITIVE;
else if(fldType == Short.TYPE ) retVal = FieldTypeEnumeration.SHORT_PRIMITIVE;
else if(fldType == Integer.TYPE ) retVal = FieldTypeEnumeration.INTEGER_PRIMITIVE;
else if(fldType == Long.TYPE ) retVal = FieldTypeEnumeration.LONG_PRIMITIVE ;
else if(fldType == Float.TYPE ) retVal = FieldTypeEnumeration.FLOAT_PRIMITIVE;
else if(fldType == Double.TYPE ) retVal = FieldTypeEnumeration.DOUBLE_PRIMITIVE;
else if(fldType == Boolean.class ) retVal = FieldTypeEnumeration.BOOLEAN;
else if(fldType == Character.class ) retVal = FieldTypeEnumeration.CHARACTER;
else if(fldType == Byte.class ) retVal = FieldTypeEnumeration.BYTE;
else if(fldType == Short.class ) retVal = FieldTypeEnumeration.SHORT;
else if(fldType == Integer.class ) retVal = FieldTypeEnumeration.INTEGER;
else if(fldType == Long.class ) retVal = FieldTypeEnumeration.LONG;
else if(fldType == Float.class ) retVal = FieldTypeEnumeration.FLOAT;
else if(fldType == Double.class ) retVal = FieldTypeEnumeration.DOUBLE;
else if(fldType == java.math.BigDecimal.class) retVal = FieldTypeEnumeration.BIGDECIMAL;
else if(fldType == java.math.BigInteger.class) retVal = FieldTypeEnumeration.BIGINTEGER;
else if(fldType == String.class ) retVal = FieldTypeEnumeration.STRING;
else if(fldType == java.util.Date.class ) retVal = FieldTypeEnumeration.UTIL_DATE;
else if(fldType == java.sql.Date.class ) retVal = FieldTypeEnumeration.SQL_DATE;
else if(fldType == java.sql.Time.class ) retVal = FieldTypeEnumeration.SQL_TIME;
else if(fldType == java.sql.Timestamp.class ) retVal = FieldTypeEnumeration.SQL_TIMESTAMP;
else if(fldType.isArray()) {
if(fldType.getComponentType() == Byte.TYPE) {
retVal = FieldTypeEnumeration.ARRAY_BYTE_PRIMITIVE;
}
}
return retVal;
|