protected FieldDescriptorImpl createFieldDesc(final Class javaClass,
final FieldMapping fieldMap) throws MappingException {
// If not an SQL field, return a stock field descriptor.
Sql sql = fieldMap.getSql();
if (sql == null) {
return super.createFieldDesc(javaClass, fieldMap);
}
String fieldName = fieldMap.getName();
// If the field type is supplied, grab it and use it to locate the
// field/accessor.
Class fieldType = null;
if (fieldMap.getType() != null) {
fieldType = resolveType(fieldMap.getType());
}
// If the field is declared as a collection, grab the collection type as
// well and use it to locate the field/accessor.
CollectionHandler colHandler = null;
if (fieldMap.getCollection() != null) {
Class colType = CollectionHandlers.getCollectionType(
fieldMap.getCollection().toString());
colHandler = CollectionHandlers.getHandler(colType);
if (colType.getName().equals("java.util.Iterator") && fieldMap.getLazy()) {
String err = "Lazy loading not supported for collection type 'iterator'";
throw new MappingException(err);
}
if (colType.getName().equals("java.util.Enumeration") && fieldMap.getLazy()) {
String err = "Lazy loading not supported for collection type 'enumerate'";
throw new MappingException(err);
}
}
TypeInfo typeInfo = getTypeInfo(fieldType, colHandler, fieldMap);
ExtendedFieldHandler exfHandler = null;
FieldHandler handler = null;
//-- check for user supplied FieldHandler
if (fieldMap.getHandler() != null) {
Class handlerClass = resolveType(fieldMap.getHandler());
if (!FieldHandler.class.isAssignableFrom(handlerClass)) {
String err = "The class '" + fieldMap.getHandler()
+ "' must implement " + FieldHandler.class.getName();
throw new MappingException(err);
}
//-- get default constructor to invoke. We can't use the
//-- newInstance method unfortunately becaue FieldHandler
//-- overloads this method
Constructor constructor = null;
try {
constructor = handlerClass.getConstructor(new Class[0]);
handler = (FieldHandler)
constructor.newInstance(new Object[0]);
} catch (Exception except) {
String err = "The class '" + handlerClass.getName()
+ "' must have a default public constructor.";
throw new MappingException(err);
}
//-- ExtendedFieldHandler?
if (handler instanceof ExtendedFieldHandler) {
exfHandler = (ExtendedFieldHandler) handler;
}
//-- Fix for Castor JDO from Steve Vaughan, Castor JDO
//-- requires FieldHandlerImpl or a ClassCastException
//-- will be thrown... [KV 20030131 - also make sure this new handler
//-- doesn't use it's own CollectionHandler otherwise
//-- it'll cause unwanted calls to the getValue method during
//-- unmarshalling]
colHandler = typeInfo.getCollectionHandler();
typeInfo.setCollectionHandler(null);
handler = new FieldHandlerImpl(handler, typeInfo);
typeInfo.setCollectionHandler(colHandler);
//-- End Castor JDO fix
}
boolean generalized = (exfHandler instanceof GeneralizedFieldHandler);
//-- if generalized we need to change the fieldType to whatever
//-- is specified in the GeneralizedFieldHandler so that the
//-- correct getter/setter methods can be found
FieldHandler custom = handler;
if (generalized) {
fieldType = ((GeneralizedFieldHandler) exfHandler).getFieldType();
}
if (generalized || (handler == null)) {
//-- create TypeInfoRef to get new TypeInfo from call
//-- to createFieldHandler
TypeInfoReference typeInfoRef = new TypeInfoReference();
typeInfoRef.typeInfo = typeInfo;
handler = createFieldHandler(javaClass, fieldType, fieldMap, typeInfoRef);
if (custom != null) {
((GeneralizedFieldHandler) exfHandler).setFieldHandler(handler);
handler = custom;
} else {
typeInfo = typeInfoRef.typeInfo;
}
}
String[] sqlName = sql.getName();
String[] sqlTypes = getSqlTypes(fieldMap);
int[] sqlTypeNum;
if (sqlTypes.length > 0) {
sqlTypeNum = new int[sqlTypes.length];
for (int i = 0; i < sqlTypes.length; i++) {
String sqlTypeString = definition2type(sqlTypes[i]);
Class sqlType = SQLTypeInfos.sqlTypeName2javaType(sqlTypeString);
if (_factory != null) { sqlType = _factory.adjustSqlType(sqlType); }
sqlTypeNum[i] = SQLTypeInfos.javaType2sqlTypeNum(sqlType);
}
} else {
Class sqlType = typeInfo.getFieldType();
if (_factory != null) { sqlType = _factory.adjustSqlType(sqlType); }
sqlTypeNum = new int[] {SQLTypeInfos.javaType2sqlTypeNum(sqlType)};
}
// create FieldDescriptor(Impl) instance, and apply JDO nature
FieldDescriptorImpl fieldDescriptor =
new FieldDescriptorImpl(fieldName, typeInfo, handler, fieldMap.getTransient());
fieldDescriptor.addNature(FieldDescriptorJDONature.class.getName());
fieldDescriptor.setRequired(fieldMap.getRequired());
// If we're using an ExtendedFieldHandler we need to set the FieldDescriptor
if (exfHandler != null) {
((FieldHandlerFriend) exfHandler).setFieldDescriptor(fieldDescriptor);
}
// if SQL mapping declares transient
if (sql.getTransient()) {
fieldDescriptor.setTransient(true);
}
FieldDescriptorJDONature fieldJdoNature =
new FieldDescriptorJDONature(fieldDescriptor);
fieldJdoNature.setTypeConvertor(typeInfo.getConvertorFrom());
if (sqlName.length > 0) {
fieldJdoNature.setSQLName(sqlName);
}
fieldJdoNature.setSQLType(sqlTypeNum);
fieldJdoNature.setManyTable(sql.getManyTable());
if (sql.getManyKey().length > 0) {
fieldJdoNature.setManyKey(sql.getManyKey());
}
fieldJdoNature.setDirtyCheck(!SqlDirtyType.IGNORE.equals(sql.getDirty()));
fieldJdoNature.setReadOnly(sql.getReadOnly());
return fieldDescriptor;
}