if (!Object.class.equals(componentType))
{
// target is not an Object array
// and not a String array (checked some lines above)
// and we do not have a Converter
throw new ConverterException(
"Could not obtain a Converter for "
+ componentType.getName());
}
}
}
// instantiate the array
targetForConvertedValues = Array.newInstance(componentType,
submittedValue.length);
}
else if (Collection.class.isAssignableFrom(modelType) || Object.class.equals(modelType))
{
if (converter == null)
{
// try to get the by-type-converter from the type of the SelectItems
_SelectItemsIterator iterator = new _SelectItemsIterator(component, facesContext);
converter = getSelectItemsValueConverter(iterator, facesContext);
}
if (Collection.class.isAssignableFrom(modelType))
{
// the target should be a Collection
Object collectionTypeAttr = component.getAttributes().get(
COLLECTION_TYPE_KEY);
if (collectionTypeAttr != null)
{
Class<?> collectionType = null;
// if there is a value, it must be a ...
// ... a ValueExpression that evaluates to a String or a Class
if (collectionTypeAttr instanceof ValueExpression)
{
// get the value of the ValueExpression
collectionTypeAttr = ((ValueExpression) collectionTypeAttr)
.getValue(facesContext.getELContext());
}
// ... String that is a fully qualified Java class name
if (collectionTypeAttr instanceof String)
{
try
{
collectionType = Class
.forName((String) collectionTypeAttr);
}
catch (ClassNotFoundException cnfe)
{
throw new FacesException(
"Unable to find class "
+ collectionTypeAttr
+ " on the classpath.", cnfe);
}
}
// ... a Class object
else if (collectionTypeAttr instanceof Class)
{
collectionType = (Class<?>) collectionTypeAttr;
}
else
{
throw new FacesException(
"The attribute "
+ COLLECTION_TYPE_KEY
+ " of component "
+ component.getClientId()
+ " does not evaluate to a "
+ "String, a Class object or a ValueExpression pointing "
+ "to a String or a Class object.");
}
// now we have a collectionType --> but is it really some kind of Collection
if (!Collection.class.isAssignableFrom(collectionType))
{
throw new FacesException("The attribute "
+ COLLECTION_TYPE_KEY + " of component "
+ component.getClientId()
+ " does not point to a valid type of Collection.");
}
// now we have a real collectionType --> try to instantiate it
try
{
targetForConvertedValues = collectionType.newInstance();
}
catch (Exception e)
{
throw new FacesException("The Collection "
+ collectionType.getName()
+ "can not be instantiated.", e);
}
}
else
{
// component.getValue() will implement Collection at this point
Collection<?> componentValue = (Collection<?>) component
.getValue();
// can we clone the Collection
if (componentValue instanceof Cloneable)
{
// clone method of Object is protected --> use reflection
try
{
Method cloneMethod = componentValue.getClass()
.getMethod("clone");
Collection<?> clone = (Collection<?>) cloneMethod
.invoke(componentValue);
clone.clear();
targetForConvertedValues = clone;
}
catch (Exception e)
{
log(facesContext, "Could not clone "
+ componentValue.getClass().getName(), e);
}
}
// if clone did not work
if (targetForConvertedValues == null)
{
// try to create the (concrete) collection from modelType
// or with the class object of componentValue (if any)
try
{
targetForConvertedValues = (componentValue != null ? componentValue
.getClass()
: modelType).newInstance();
}
catch (Exception e)
{
// this did not work either
// use the standard concrete type
if (SortedSet.class.isAssignableFrom(modelType))
{
targetForConvertedValues = new TreeSet();
}
else if (Queue.class.isAssignableFrom(modelType))
{
targetForConvertedValues = new LinkedList();
}
else if (Set.class.isAssignableFrom(modelType))
{
targetForConvertedValues = new HashSet(
submittedValue.length);
}
else
{
targetForConvertedValues = new ArrayList(
submittedValue.length);
}
}
}
}
}
else /* if (Object.class.equals(modelType)) */
{
// a modelType of Object is also permitted, in order to support
// managed bean properties of type Object
// optimization: if we don't have a converter, we can return the submittedValue
if (converter == null)
{
return submittedValue;
}
targetForConvertedValues = new Object[submittedValue.length];
}
}
else
{
// the expression does neither point to an array nor to a collection
throw new ConverterException(
"ValueExpression for UISelectMany must be of type Collection or Array.");
}
}
else
{