colRequireGetSet = CollectionHandlers.isGetSetCollection(colType);
if (colType == Object[].class) {
if (fldType == null) {
String msg = "'type' is a required attribute for field that are "
+ "array collections: " + fieldName;
throw new MappingException(msg);
}
Object obj = Array.newInstance(fldType, 0);
colType = obj.getClass();
}
}
FieldHandlerImpl handler = null;
// If get/set methods not specified, use field names to determine them.
if (fldMap.getDirect()) {
// No accessor, map field directly.
Field field = findField(javaClass, fieldName, (colType == null ? fldType : colType));
if (field == null) {
throw new MappingException(
"mapping.fieldNotAccessible", fieldName, javaClass.getName());
}
if (fldType == null) {
fldType = field.getType();
}
typeInfoRef.typeInfo = getTypeInfo(fldType, colHandler, fldMap);
handler = new FieldHandlerImpl(field, typeInfoRef.typeInfo);
} else if ((fldMap.getGetMethod() == null) && (fldMap.getSetMethod() == null)) {
// If both methods (get/set) are not specified, determine them automatically
if (fieldName == null) {
throw new MappingException(
"mapping.missingFieldName", javaClass.getName());
}
List getSequence = new ArrayList();
List setSequence = new ArrayList();
Method getMethod = null;
Method setMethod = null;
// Get method normally starts with "get", but may start with "is"
// if it's a boolean.
try {
// Handle nested fields
while (true) {
int point = fieldName.indexOf('.');
if (point < 0) { break; }
String parentField = fieldName.substring(0, point);
// Getter method for parent field
String methodName = GET_METHOD_PREFIX + capitalize(parentField);
Method method = javaClass.getMethod(methodName, (Class[]) null);
if (isAbstractOrStatic(method)) {
throw new MappingException("mapping.accessorNotAccessible",
methodName, javaClass.getName());
}
getSequence.add(method);
Class nextClass = method.getReturnType();
// Setter method for parent field
try {
methodName = SET_METHOD_PREFIX + capitalize(parentField);
Class[] types = new Class[] {nextClass};
method = javaClass.getMethod(methodName, types);
if (isAbstractOrStatic(method)) { method = null; }
} catch (Exception ex) {
method = null;
}
setSequence.add(method);
javaClass = nextClass;
fieldName = fieldName.substring(point + 1);
}
// Find getter method for actual field
String methodName = GET_METHOD_PREFIX + capitalize( fieldName );
Class returnType = (colType == null) ? fldType : colType;
getMethod = findAccessor(javaClass, methodName, returnType, true);
// If getMethod is null, check for boolean type method prefix
if (getMethod == null) {
if ((fldType == Boolean.class) || (fldType == Boolean.TYPE)) {
methodName = IS_METHOD_PREFIX + capitalize(fieldName);
getMethod = findAccessor(javaClass, methodName, returnType, true);
}
}
} catch (MappingException ex) {
throw ex;
} catch (Exception ex) {
// LOG.warn("Unexpected exception", ex);
}
if (getMethod == null) {
String getAccessor = GET_METHOD_PREFIX + capitalize(fieldName);
String isAccessor = IS_METHOD_PREFIX + capitalize(fieldName);
throw new MappingException("mapping.accessorNotFound",
getAccessor + "/" + isAccessor,
(colType == null ? fldType : colType),
javaClass.getName());
}
if ((fldType == null) && (colType == null)) {
fldType = getMethod.getReturnType();
}
// We try to locate a set method anyway but complain only if we need one
String methodName = SET_METHOD_PREFIX + capitalize(fieldName);
setMethod = findAccessor(javaClass, methodName,
(colType == null ? fldType : colType), false);
// If we have a collection that need both set and get but we don't have a
// set method, we fail
if ((setMethod == null) && (colType != null) && colRequireGetSet) {
throw new MappingException("mapping.accessorNotFound", methodName,
(colType == null ? fldType : colType), javaClass.getName());
}
typeInfoRef.typeInfo = getTypeInfo(fldType, colHandler, fldMap);
fieldName = fldMap.getName();
if (fieldName == null) {
if (getMethod == null) {
fieldName = setMethod.getName();
} else {
fieldName = getMethod.getName();
}
}
// Convert method call sequence for nested fields to arrays
Method[] getArray = null;
Method[] setArray = null;
if (getSequence.size() > 0) {
getArray = new Method[getSequence.size()];
getArray = (Method[]) getSequence.toArray(getArray);
setArray = new Method[setSequence.size()];
setArray = (Method[]) setSequence.toArray(setArray);
}
// Create handler
handler = new FieldHandlerImpl(fieldName, getArray, setArray,
getMethod, setMethod, typeInfoRef.typeInfo);
if (setMethod != null) {
if (setMethod.getName().startsWith(ADD_METHOD_PREFIX)) {
handler.setAddMethod(setMethod);
}
}
} else {
Method getMethod = null;
Method setMethod = null;
// First look up the get accessors
if (fldMap.getGetMethod() != null) {
Class rtype = fldType;
if (colType != null) {
String methodName = fldMap.getGetMethod();
if (methodName.startsWith(ENUM_METHOD_PREFIX)) {
// An enumeration method must really return a enumeration.
rtype = Enumeration.class;
} else if (methodName.startsWith(ITER_METHOD_PREFIX)) {
// An iterator method must really return a iterator.
rtype = Iterator.class;
} else {
rtype = colType;
}
}
getMethod = findAccessor(javaClass, fldMap.getGetMethod(), rtype, true);
if (getMethod == null) {
throw new MappingException("mapping.accessorNotFound",
fldMap.getGetMethod(), rtype, javaClass.getName());
}
if ((fldType == null) && (colType == null)) {
fldType = getMethod.getReturnType();
}
}
// Second look up the set/add accessor
if (fldMap.getSetMethod() != null) {
String methodName = fldMap.getSetMethod();
Class type = fldType;
if (colType != null) {
if (!methodName.startsWith(ADD_METHOD_PREFIX)) {
type = colType;
}
}
// Set via constructor?
if (methodName.startsWith("%")) {
// Validate index value
int index = 0;
String temp = methodName.substring(1);
try {
index = Integer.parseInt(temp);
} catch(NumberFormatException ex) {
throw new MappingException("mapping.invalidParameterIndex", temp);
}
if ((index < 1) || (index > 9)) {
throw new MappingException("mapping.invalidParameterIndex", temp);
}
} else {
setMethod = findAccessor(javaClass, methodName, type , false);
if (setMethod == null) {
throw new MappingException("mapping.accessorNotFound",
methodName, type, javaClass.getName());
}
if (fldType == null) {
fldType = setMethod.getParameterTypes()[0];
}
}
}
typeInfoRef.typeInfo = getTypeInfo(fldType, colHandler, fldMap);
fieldName = fldMap.getName();
if (fieldName == null) {
if (getMethod == null) {
fieldName = setMethod.getName();
} else {
fieldName = getMethod.getName();
}
}
// Create handler
handler = new FieldHandlerImpl(fieldName, null, null,
getMethod, setMethod, typeInfoRef.typeInfo);
if (setMethod != null) {
if (setMethod.getName().startsWith(ADD_METHOD_PREFIX)) {
handler.setAddMethod(setMethod);
}
}
}
// If there is a create method, add it to the field handler
String methodName = fldMap.getCreateMethod();
if (methodName != null) {
try {
Method method = javaClass.getMethod(methodName, (Class[]) null);
handler.setCreateMethod(method);
} catch (Exception ex) {
throw new MappingException("mapping.createMethodNotFound",
methodName, javaClass.getName());
}
} else if ((fieldName != null) && !Types.isSimpleType(fldType)) {
try {
methodName = CREATE_METHOD_PREFIX + capitalize(fieldName);