Class<? extends Convertable<?>> convertableCls = null;
ApiParameter containerContent = null;
if( apiParameterType == null )
{
throw( new TypeConversionException( "Cannot create ApiParameter description without type!" ) );
}
if (apiParameterClass == null)
{
apiParameterClass = getClassFromType( apiParameterType );
}
//try a std mapping
Type xmlRpcType = StandardXmlRpcTypeConverter.mapJavaTypeToXmlRpcType( apiParameterClass );
boolean isXmlRpcCompatible = false;
if (xmlRpcType != null || Object.class.equals( apiParameterClass ) )
{
isXmlRpcCompatible = true;
}
if (xmlRpcType == null && apiParameterClass.isArray())
{
isXmlRpcCompatible = true;
xmlRpcType = Type.ARRAY;
}
// let's see what the annotations tell us
//first: parameter annotations / types with nested content information maps, collections, arrays
//Contains containsAnno = AnnotationUtils.getAnnotation( parameterAnnotations, Contains.class );
java.lang.reflect.Type contentType = getContentType( apiParameterType );
if (/*containsAnno != null ||*/ contentType != null && xmlRpcType != Type.BASE64 )
{
containerContent = createFrom( new Annotation[0], contentType, getClassFromType( contentType ) );
}
XmlRpcBean xmlRpcBeanAnno = AnnotationUtils.getAnnotationForClass( apiParameterClass, XmlRpcBean.class );
if (xmlRpcBeanAnno != null)
{
try
{
xmlRpcType = Type.STRUCT;
ParameterConverter<?,?> c = new XmlRpcBeanConverter( apiParameterClass );
//register a converter for especially for this bean type
ParameterConverterRegistry.setParameterConverterForClass( apiParameterClass, c );
ParameterConverterRegistry.readParameterConverterMappingsFromApiClass( apiParameterClass );
}
catch( Exception e )
{
throw( new TypeConversionException( "Error creating bean converter:", e ) );
}
}
//second: annotations for used types
XmlRpc xmlRpcAnno = AnnotationUtils.getAnnotationForClass( apiParameterClass, XmlRpc.class );
if( xmlRpcAnno != null )
{
xmlRpcType = xmlRpcAnno.type();
convertableCls = xmlRpcAnno.concrete();
separateConverterCls = xmlRpcAnno.converter();
//usesConvertable = a concete class != parameter class does conversion
boolean usesConvertable = !convertableCls.equals( NoParameterBoundConverter.class );
//usesConverter = a seperate converter does conversion
boolean usesConverter = !separateConverterCls.equals( NoSeparateParameterConverter.class );
//isConvertable = the parameter does the work itself
boolean isConvertable = !usesConvertable && !usesConverter;
if (usesConvertable && usesConverter)
{
throw( new AnnotationException( "Parameter can only be either a convertable or use a parameter converter, not both at a time!" ) );
}
if (isConvertable)
{
convertableCls = validateConvertableClass( apiParameterClass, xmlRpcType );
}
else if (usesConvertable)
{
validateConvertableClass( convertableCls, xmlRpcType );
}
else if (usesConverter)
{
checkParameterConverter( separateConverterCls, xmlRpcType );
}
}
ParameterConverter<?,?> converter = ParameterConverterRegistry.getParameterConverterByClass( separateConverterCls );
if (converter == null)
{
//maybe a mapping
converter = ParameterConverterRegistry.getParameterConverterForClass( apiParameterClass );
}
if( converter != null )
{
xmlRpcType = converter.getXmlRpcRepresentationType();
}
if( xmlRpcType == null && !isXmlRpcCompatible
&& de.dfki.util.xmlrpc.XmlRpc.treatUnknownTypesAsBeans() )
{
//the last chance: treat this type as a bean
log().info( "Found XML-RPC unaware type '" + apiParameterClass.getName() + "' treating it as XmlRpcBean!" );
converter = new XmlRpcBeanConverter( apiParameterClass );
xmlRpcType = converter.getXmlRpcRepresentationType();
ParameterConverterRegistry.setParameterConverterForClass( apiParameterClass, converter );
log().info( "XmlRpcBeanConverter registered for " + apiParameterClass );
}
if( xmlRpcType == null && !isXmlRpcCompatible )
{
throw ( new TypeConversionException( "Cannot find a XML-RPC compliant type conversion for class "
+ apiParameterClass.getName() + ". Maybe missing annotation?" ) );
}
ApiParameter param = new ApiParameter( xmlRpcType, apiParameterClass, converter, convertableCls, isXmlRpcCompatible, containerContent );
return( param );