You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by lu...@apache.org on 2009/11/27 01:56:56 UTC
svn commit: r884731 - in
/myfaces/core/trunk/api/src/main/java/javax/faces/component:
_SelectItemsIterator.java _SharedRendererUtils.java
Author: lu4242
Date: Fri Nov 27 00:56:56 2009
New Revision: 884731
URL: http://svn.apache.org/viewvc?rev=884731&view=rev
Log:
MYFACES-2418 Implement h:selectManyXXX collectionType and hideNoSelectionOption (thanks to Jakob Korherr for this patch)
Modified:
myfaces/core/trunk/api/src/main/java/javax/faces/component/_SelectItemsIterator.java
myfaces/core/trunk/api/src/main/java/javax/faces/component/_SharedRendererUtils.java
Modified: myfaces/core/trunk/api/src/main/java/javax/faces/component/_SelectItemsIterator.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/api/src/main/java/javax/faces/component/_SelectItemsIterator.java?rev=884731&r1=884730&r2=884731&view=diff
==============================================================================
--- myfaces/core/trunk/api/src/main/java/javax/faces/component/_SelectItemsIterator.java (original)
+++ myfaces/core/trunk/api/src/main/java/javax/faces/component/_SelectItemsIterator.java Fri Nov 27 00:56:56 2009
@@ -53,7 +53,6 @@
private final Iterator<UIComponent> _children;
private Iterator<? extends Object> _nestedItems;
private SelectItem _nextItem;
- private String _collectionLabel;
private UISelectItems _currentUISelectItems;
private FacesContext _facesContext;
@@ -152,22 +151,12 @@
items.add(Array.get(value, i));
}
_nestedItems = items.iterator();
- _collectionLabel = "Array";
return hasNext();
}
else if (value instanceof Iterable)
{
// value is Iterable --> Collection, DataModel,...
_nestedItems = ((Iterable<?>) value).iterator();
- // For better understanding ask if value is a Collection
- if (value instanceof Collection)
- {
- _collectionLabel = "Collection";
- }
- else
- {
- _collectionLabel = "Iterable";
- }
return hasNext();
}
else if (value instanceof Map)
@@ -180,7 +169,6 @@
}
_nestedItems = items.iterator();
- _collectionLabel = "Map";
return hasNext();
}
else
@@ -232,66 +220,57 @@
oldRequestMapVarValue = _facesContext.getExternalContext().getRequestMap().put(var, item);
wroteRequestMapVarValue = true;
}
- try
+
+ // check the itemValue attribute
+ Object itemValue = attributeMap.get(ITEM_VALUE_ATTR);
+ if (itemValue == null)
+ {
+ // the itemValue attribute was not provided
+ // --> use the current item as the itemValue
+ itemValue = item;
+ }
+
+ // Spec: When iterating over the select items, toString()
+ // must be called on the string rendered attribute values
+ Object itemLabel = attributeMap.get(ITEM_LABEL_ATTR);
+ if (itemLabel == null)
+ {
+ itemLabel = itemValue.toString();
+ }
+ else
{
- Object itemValue = attributeMap.get(ITEM_VALUE_ATTR);
- if(itemValue != null)
+ itemLabel = itemLabel.toString();
+ }
+ Object itemDescription = attributeMap.get(ITEM_DESCRIPTION_ATTR);
+ if (itemDescription != null)
+ {
+ itemDescription = itemDescription.toString();
+ }
+ Boolean itemDisabled = getBooleanAttribute(_currentUISelectItems, ITEM_DISABLED_ATTR, false);
+ Boolean itemLabelEscaped = getBooleanAttribute(_currentUISelectItems, ITEM_LABEL_ESCAPED_ATTR, true);
+ Object noSelectionValue = attributeMap.get(NO_SELECTION_VALUE_ATTR);
+ item = new SelectItem(itemValue,
+ (String) itemLabel,
+ (String) itemDescription,
+ itemDisabled,
+ itemLabelEscaped,
+ itemValue.equals(noSelectionValue));
+
+ // remove the value with the key from var from the request map, if previously written
+ if(wroteRequestMapVarValue)
+ {
+ // If there was a previous value stored with the key from var in the request map, restore it
+ if (oldRequestMapVarValue != null)
{
- // Spec: When iterating over the select items, toString()
- // must be called on the string rendered attribute values
- Object itemLabel = attributeMap.get(ITEM_LABEL_ATTR);
- if (itemLabel == null)
- {
- itemLabel = itemValue.toString();
- }
- else
- {
- itemLabel = itemLabel.toString();
- }
- Object itemDescription = attributeMap.get(ITEM_DESCRIPTION_ATTR);
- if (itemDescription != null)
- {
- itemDescription.toString();
- }
- Boolean itemDisabled = getBooleanAttribute(_currentUISelectItems, ITEM_DISABLED_ATTR, false);
- Boolean itemLabelEscaped = getBooleanAttribute(_currentUISelectItems, ITEM_LABEL_ESCAPED_ATTR, true);
- Object noSelectionValue = attributeMap.get(NO_SELECTION_VALUE_ATTR);
- item = new SelectItem(itemValue,
- (String) itemLabel,
- (String) itemDescription,
- itemDisabled,
- itemLabelEscaped,
- itemValue.equals(noSelectionValue));
+ _facesContext.getExternalContext()
+ .getRequestMap().put(var, oldRequestMapVarValue);
}
- else
+ else
{
- ValueExpression expression = _currentUISelectItems.getValueExpression("value");
- throw new IllegalArgumentException(
- _collectionLabel + " referenced by UISelectItems with ValueExpression '"
- + expression.getExpressionString()
- + "' and Component-Path : " + getPathToComponent(_currentUISelectItems)
- + " does not contain Objects of type SelectItem"
- + " or does not provide the attribute itemValue");
+ _facesContext.getExternalContext()
+ .getRequestMap().remove(var);
}
- }
- finally
- {
- // remove the value with the key from var from the request map, if previously written
- if(wroteRequestMapVarValue)
- {
- // If there was a previous value stored with the key from var in the request map, restore it
- if (oldRequestMapVarValue != null)
- {
- _facesContext.getExternalContext()
- .getRequestMap().put(var, oldRequestMapVarValue);
- }
- else
- {
- _facesContext.getExternalContext()
- .getRequestMap().remove(var);
- }
- }
- }
+ }
}
return (SelectItem) item;
}
Modified: myfaces/core/trunk/api/src/main/java/javax/faces/component/_SharedRendererUtils.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/api/src/main/java/javax/faces/component/_SharedRendererUtils.java?rev=884731&r1=884730&r2=884731&view=diff
==============================================================================
--- myfaces/core/trunk/api/src/main/java/javax/faces/component/_SharedRendererUtils.java (original)
+++ myfaces/core/trunk/api/src/main/java/javax/faces/component/_SharedRendererUtils.java Fri Nov 27 00:56:56 2009
@@ -21,8 +21,10 @@
import java.lang.reflect.Array;
import java.lang.reflect.Method;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
+import java.util.Iterator;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Set;
@@ -34,6 +36,8 @@
import javax.faces.context.FacesContext;
import javax.faces.convert.Converter;
import javax.faces.convert.ConverterException;
+import javax.faces.model.SelectItem;
+import javax.faces.model.SelectItemGroup;
/**
* The util methods in this class are shared between the javax.faces.component package and the
@@ -137,136 +141,159 @@
targetForConvertedValues = Array.newInstance(componentType,
submittedValue.length);
}
- else if (Collection.class.isAssignableFrom(modelType))
+ else if (Collection.class.isAssignableFrom(modelType) || Object.class.equals(modelType))
{
- // the target should be a Collection
- Object collectionTypeAttr = component.getAttributes().get(
- COLLECTION_TYPE_KEY);
- if (collectionTypeAttr != null)
+ if (converter == 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 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)
{
- try
+ 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
- .forName((String) collectionTypeAttr);
+ collectionType = (Class<?>) collectionTypeAttr;
}
- catch (ClassNotFoundException cnfe)
+ else
{
throw new FacesException(
- "Unable to find class "
- + collectionTypeAttr
- + " on the classpath.", cnfe);
+ "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.");
}
-
- }
- // ... 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
+ // 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
{
- Method cloneMethod = componentValue.getClass()
- .getMethod("clone");
- Collection<?> clone = (Collection<?>) cloneMethod
- .invoke(componentValue);
- clone.clear();
- targetForConvertedValues = clone;
+ targetForConvertedValues = collectionType.newInstance();
}
catch (Exception e)
{
- log(facesContext, "Could not clone "
- + componentValue.getClass().getName(), e);
+ throw new FacesException("The Collection "
+ + collectionType.getName()
+ + "can not be instantiated.", e);
}
}
-
- // if clone did not work
- if (targetForConvertedValues == null)
+ else
{
- // try to create the (concrete) collection from modelType
- // or with the class object of componentValue (if any)
- try
+ // component.getValue() will implement Collection at this point
+ Collection<?> componentValue = (Collection<?>) component
+ .getValue();
+ // can we clone the Collection
+ if (componentValue instanceof Cloneable)
{
- 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))
+ // clone method of Object is protected --> use reflection
+ try
{
- targetForConvertedValues = new TreeSet();
+ Method cloneMethod = componentValue.getClass()
+ .getMethod("clone");
+ Collection<?> clone = (Collection<?>) cloneMethod
+ .invoke(componentValue);
+ clone.clear();
+ targetForConvertedValues = clone;
}
- else if (Queue.class.isAssignableFrom(modelType))
+ catch (Exception e)
{
- targetForConvertedValues = new LinkedList();
+ log(facesContext, "Could not clone "
+ + componentValue.getClass().getName(), e);
}
- else if (Set.class.isAssignableFrom(modelType))
+ }
+
+ // 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 = new HashSet(
- submittedValue.length);
+ targetForConvertedValues = (componentValue != null ? componentValue
+ .getClass()
+ : modelType).newInstance();
}
- else
+ catch (Exception e)
{
- targetForConvertedValues = new ArrayList(
- submittedValue.length);
+ // 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
{
@@ -309,6 +336,51 @@
return targetForConvertedValues;
}
+
+ /**
+ * Iterates through the SelectItems with the given Iterator and tries to obtain
+ * a by-class-converter based on the Class of SelectItem.getValue().
+ * @param iterator
+ * @param facesContext
+ * @return The first suitable Converter for the given SelectItems or null.
+ */
+ static Converter getSelectItemsValueConverter(Iterator<SelectItem> iterator, FacesContext facesContext)
+ {
+ // Attention!
+ // This code is duplicated in jsfapi component package.
+ // If you change something here please do the same in the other class!
+
+ Converter converter = null;
+ while (converter == null && iterator.hasNext())
+ {
+ SelectItem item = iterator.next();
+ if (item instanceof SelectItemGroup)
+ {
+ Iterator<SelectItem> groupIterator = Arrays.asList(((SelectItemGroup) item).getSelectItems()).iterator();
+ converter = getSelectItemsValueConverter(groupIterator, facesContext);
+ }
+ else
+ {
+ Class<?> selectItemsType = item.getValue().getClass();
+
+ // optimization: no conversion for String values
+ if (String.class.equals(selectItemsType))
+ {
+ return null;
+ }
+
+ try
+ {
+ converter = facesContext.getApplication().createConverter(selectItemsType);
+ }
+ catch (FacesException e)
+ {
+ // nothing - try again
+ }
+ }
+ }
+ return converter;
+ }
/**
* This method is different in the two versions of _SharedRendererUtils.