Converter converter = customConverters.get(id);
if (converter == null) {
if (parent != null) {
return parent.getConversionExecutor(id, sourceClass, targetClass);
} else {
throw new ConversionExecutorNotFoundException(sourceClass, targetClass,
"No custom ConversionExecutor found with id '" + id + "' for converting from sourceClass ["
+ sourceClass.getName() + "] to targetClass [" + targetClass.getName() + "]");
}
}
sourceClass = convertToWrapperClassIfNecessary(sourceClass);
targetClass = convertToWrapperClassIfNecessary(targetClass);
if (sourceClass.isArray()) {
Class<?> sourceComponentType = sourceClass.getComponentType();
if (targetClass.isArray()) {
Class<?> targetComponentType = targetClass.getComponentType();
if (converter.getSourceClass().isAssignableFrom(sourceComponentType)) {
if (!converter.getTargetClass().isAssignableFrom(targetComponentType)) {
throw new ConversionExecutorNotFoundException(sourceClass, targetClass,
"Custom ConversionExecutor with id '" + id
+ "' cannot convert from an array storing elements of type ["
+ sourceComponentType.getName() + "] to an array of storing elements of type ["
+ targetComponentType.getName() + "]");
}
ConversionExecutor elementConverter = new StaticConversionExecutor(sourceComponentType,
targetComponentType, converter);
return new StaticConversionExecutor(sourceClass, targetClass, new ArrayToArray(elementConverter));
} else if (converter.getTargetClass().isAssignableFrom(sourceComponentType)
&& converter instanceof TwoWayConverter) {
TwoWayConverter twoWay = (TwoWayConverter) converter;
ConversionExecutor elementConverter = new StaticConversionExecutor(sourceComponentType,
targetComponentType, new ReverseConverter(twoWay));
return new StaticConversionExecutor(sourceClass, targetClass, new ArrayToArray(elementConverter));
} else {
throw new ConversionExecutorNotFoundException(sourceClass, targetClass,
"Custom ConversionExecutor with id '" + id
+ "' cannot convert from an array storing elements of type ["
+ sourceComponentType.getName() + "] to an array storing elements of type ["
+ targetComponentType.getName() + "]");
}
} else if (Collection.class.isAssignableFrom(targetClass)) {
if (!targetClass.isInterface() && Modifier.isAbstract(targetClass.getModifiers())) {
throw new IllegalArgumentException("Conversion target class [" + targetClass.getName()
+ "] is invalid; cannot convert to abstract collection types--"
+ "request an interface or concrete implementation instead");
}
if (converter.getSourceClass().isAssignableFrom(sourceComponentType)) {
// type erasure has prevented us from getting the concrete type, this is best we can do for now
ConversionExecutor elementConverter = new StaticConversionExecutor(sourceComponentType,
converter.getTargetClass(), converter);
return new StaticConversionExecutor(sourceClass, targetClass, new ArrayToCollection(
elementConverter));
} else if (converter.getTargetClass().isAssignableFrom(sourceComponentType)
&& converter instanceof TwoWayConverter) {
TwoWayConverter twoWay = (TwoWayConverter) converter;
ConversionExecutor elementConverter = new StaticConversionExecutor(sourceComponentType,
converter.getSourceClass(), new ReverseConverter(twoWay));
return new StaticConversionExecutor(sourceClass, targetClass, new ArrayToCollection(
elementConverter));
} else {
throw new ConversionExecutorNotFoundException(sourceClass, targetClass,
"Custom ConversionExecutor with id '" + id
+ "' cannot convert from array an storing elements type ["
+ sourceComponentType.getName() + "] to a collection of type ["
+ targetClass.getName() + "]");
}
}
}
if (targetClass.isArray()) {
Class<?> targetComponentType = targetClass.getComponentType();
if (Collection.class.isAssignableFrom(sourceClass)) {
// type erasure limits us here as well
if (converter.getTargetClass().isAssignableFrom(targetComponentType)) {
ConversionExecutor elementConverter = new StaticConversionExecutor(converter.getSourceClass(),
targetComponentType, converter);
Converter collectionToArray = new ReverseConverter(new ArrayToCollection(elementConverter));
return new StaticConversionExecutor(sourceClass, targetClass, collectionToArray);
} else if (converter.getSourceClass().isAssignableFrom(targetComponentType)
&& converter instanceof TwoWayConverter) {
TwoWayConverter twoWay = (TwoWayConverter) converter;
ConversionExecutor elementConverter = new StaticConversionExecutor(converter.getTargetClass(),
targetComponentType, new ReverseConverter(twoWay));
Converter collectionToArray = new ReverseConverter(new ArrayToCollection(elementConverter));
return new StaticConversionExecutor(sourceClass, targetClass, collectionToArray);
} else {
throw new ConversionExecutorNotFoundException(sourceClass, targetClass,
"Custom ConversionExecutor with id '" + id + "' cannot convert from collection of type ["
+ sourceClass.getName() + "] to an array storing elements of type ["
+ targetComponentType.getName() + "]");
}
} else {
if (converter.getSourceClass().isAssignableFrom(sourceClass)) {
if (!converter.getTargetClass().isAssignableFrom(targetComponentType)) {
throw new ConversionExecutorNotFoundException(sourceClass, targetClass,
"Custom ConversionExecutor with id '" + id + "' cannot convert from sourceClass ["
+ sourceClass.getName() + "] to array holding elements of type ["
+ targetComponentType.getName() + "]");
}
ConversionExecutor elementConverter = new StaticConversionExecutor(sourceClass,
targetComponentType, converter);
return new StaticConversionExecutor(sourceClass, targetClass, new ObjectToArray(elementConverter));
} else if (converter.getTargetClass().isAssignableFrom(sourceClass)
&& converter instanceof TwoWayConverter) {
if (!converter.getSourceClass().isAssignableFrom(targetComponentType)) {
throw new ConversionExecutorNotFoundException(sourceClass, targetClass,
"Custom ConversionExecutor with id '" + id + "' cannot convert from sourceClass ["
+ sourceClass.getName() + "] to array holding elements of type ["
+ targetComponentType.getName() + "]");
}
TwoWayConverter twoWay = (TwoWayConverter) converter;
ConversionExecutor elementConverter = new StaticConversionExecutor(sourceClass,
targetComponentType, new ReverseConverter(twoWay));
return new StaticConversionExecutor(sourceClass, targetClass, new ObjectToArray(elementConverter));
}
}
}
if (Collection.class.isAssignableFrom(targetClass)) {
if (Collection.class.isAssignableFrom(sourceClass)) {
ConversionExecutor elementConverter;
// type erasure forces us to do runtime checks of list elements
if (converter instanceof TwoWayConverter) {
elementConverter = new TwoWayCapableConversionExecutor(converter.getSourceClass(),
converter.getTargetClass(), (TwoWayConverter) converter);
} else {
elementConverter = new StaticConversionExecutor(converter.getSourceClass(),
converter.getTargetClass(), converter);
}
return new StaticConversionExecutor(sourceClass, targetClass, new CollectionToCollection(
elementConverter));
} else {
ConversionExecutor elementConverter;
// type erasure forces us to do runtime checks of list elements
if (converter instanceof TwoWayConverter) {
elementConverter = new TwoWayCapableConversionExecutor(sourceClass, converter.getTargetClass(),
(TwoWayConverter) converter);
} else {
elementConverter = new StaticConversionExecutor(sourceClass, converter.getTargetClass(), converter);
}
if (!Collection.class.isAssignableFrom(converter.getTargetClass())) {
elementConverter = new StaticConversionExecutor(sourceClass, targetClass, new ObjectToCollection(
elementConverter));
}
return elementConverter;
}
}
if (converter.getSourceClass().isAssignableFrom(sourceClass)) {
if (!converter.getTargetClass().isAssignableFrom(targetClass)) {
throw new ConversionExecutorNotFoundException(sourceClass, targetClass,
"Custom ConversionExecutor with id '" + id + "' cannot convert from sourceClass ["
+ sourceClass.getName() + "] to targetClass [" + targetClass.getName() + "]");
}
return new StaticConversionExecutor(sourceClass, targetClass, converter);
} else if (converter.getTargetClass().isAssignableFrom(sourceClass) && converter instanceof TwoWayConverter) {
if (!converter.getSourceClass().isAssignableFrom(targetClass)) {
throw new ConversionExecutorNotFoundException(sourceClass, targetClass,
"Custom ConversionExecutor with id '" + id + "' cannot convert from sourceClass ["
+ sourceClass.getName() + "] to targetClass [" + targetClass.getName() + "]");
}
TwoWayConverter twoWay = (TwoWayConverter) converter;
return new StaticConversionExecutor(sourceClass, targetClass, new ReverseConverter(twoWay));
} else {
throw new ConversionExecutorNotFoundException(sourceClass, targetClass,
"Custom ConversionExecutor with id '" + id + "' cannot convert from sourceClass ["
+ sourceClass.getName() + "] to targetClass [" + targetClass.getName() + "]");
}
}