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/04 20:58:14 UTC
svn commit: r832865 - in /myfaces:
core/trunk/api/src/main/java/javax/faces/component/
core/trunk/api/src/test/java/javax/faces/component/
shared/trunk_4.0.x/core/src/main/java/org/apache/myfaces/shared/renderkit/
shared/trunk_4.0.x/core/src/main/java/...
Author: lu4242
Date: Wed Nov 4 19:58:13 2009
New Revision: 832865
URL: http://svn.apache.org/viewvc?rev=832865&view=rev
Log:
MYFACES-2309 Add new attributes to f:selectItems (Thanks to Jakob Korherr for this patch)
Modified:
myfaces/core/trunk/api/src/main/java/javax/faces/component/UISelectMany.java
myfaces/core/trunk/api/src/main/java/javax/faces/component/UISelectOne.java
myfaces/core/trunk/api/src/main/java/javax/faces/component/_SelectItemsIterator.java
myfaces/core/trunk/api/src/main/java/javax/faces/component/_UISelectItems.java
myfaces/core/trunk/api/src/test/java/javax/faces/component/UISelectItemsTest.java
myfaces/shared/trunk_4.0.x/core/src/main/java/org/apache/myfaces/shared/renderkit/JSFAttr.java
myfaces/shared/trunk_4.0.x/core/src/main/java/org/apache/myfaces/shared/renderkit/RendererUtils.java
myfaces/shared/trunk_4.0.x/core/src/main/java/org/apache/myfaces/shared/renderkit/html/HtmlCheckboxRendererBase.java
myfaces/shared/trunk_4.0.x/core/src/main/java/org/apache/myfaces/shared/renderkit/html/HtmlRadioRendererBase.java
myfaces/shared/trunk_4.0.x/core/src/main/java/org/apache/myfaces/shared/renderkit/html/HtmlRendererUtils.java
myfaces/shared/trunk_4.0.x/core/src/main/java/org/apache/myfaces/shared/util/SelectItemsIterator.java
Modified: myfaces/core/trunk/api/src/main/java/javax/faces/component/UISelectMany.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/api/src/main/java/javax/faces/component/UISelectMany.java?rev=832865&r1=832864&r2=832865&view=diff
==============================================================================
--- myfaces/core/trunk/api/src/main/java/javax/faces/component/UISelectMany.java (original)
+++ myfaces/core/trunk/api/src/main/java/javax/faces/component/UISelectMany.java Wed Nov 4 19:58:13 2009
@@ -373,7 +373,7 @@
};
Collection<SelectItem> items = new ArrayList<SelectItem>();
- for (Iterator<SelectItem> iter = new _SelectItemsIterator(this); iter.hasNext();)
+ for (Iterator<SelectItem> iter = new _SelectItemsIterator(this, context); iter.hasNext();)
{
items.add(iter.next());
}
Modified: myfaces/core/trunk/api/src/main/java/javax/faces/component/UISelectOne.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/api/src/main/java/javax/faces/component/UISelectOne.java?rev=832865&r1=832864&r2=832865&view=diff
==============================================================================
--- myfaces/core/trunk/api/src/main/java/javax/faces/component/UISelectOne.java (original)
+++ myfaces/core/trunk/api/src/main/java/javax/faces/component/UISelectOne.java Wed Nov 4 19:58:13 2009
@@ -87,10 +87,10 @@
// selected value must match to one of the available options
// and if required is true it must not match an option with noSelectionOption set to true (since 2.0)
- if (!(_SelectItemsUtil.matchValue(context, value, new _SelectItemsIterator(this), converter)
+ if (!(_SelectItemsUtil.matchValue(context, value, new _SelectItemsIterator(this, context), converter)
&& (!this.isRequired()
|| (this.isRequired()
- && !_SelectItemsUtil.isNoSelectionOption(context, value, new _SelectItemsIterator(this), converter)))))
+ && !_SelectItemsUtil.isNoSelectionOption(context, value, new _SelectItemsIterator(this, context), converter)))))
{
_MessageUtils.addErrorMessage(context, this, INVALID_MESSAGE_ID, new Object[] { _MessageUtils.getLabel(
context, this) });
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=832865&r1=832864&r2=832865&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 Wed Nov 4 19:58:13 2009
@@ -18,28 +18,49 @@
*/
package javax.faces.component;
-import java.util.*;
+import java.lang.reflect.Array;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.NoSuchElementException;
import javax.el.ValueExpression;
import javax.faces.context.FacesContext;
-import javax.faces.el.ValueBinding;
import javax.faces.model.SelectItem;
+// ATTENTION
+// This class is associated with org.apache.myfaces.shared.util.SelectItemsIterator.
+// Changes here should also be applied to this class.
+
/**
* @author Mathias Broekelmann (latest modification by $Author$)
+ * @author Jakob Korherr (jsf 2.0)
* @version $Revision$ $Date$
*/
class _SelectItemsIterator implements Iterator<SelectItem>
{
- private final Iterator<UIComponent> _childs;
- private Iterator<SelectItem> _nestedItems;
+
+ // org.apache.myfaces.shared.util.SelectItemsIterator uses JSFAttr
+ private static final String VAR_ATTR = "var";
+ private static final String ITEM_VALUE_ATTR = "itemValue";
+ private static final String ITEM_LABEL_ATTR = "itemLabel";
+ private static final String ITEM_DESCRIPTION_ATTR = "itemDescription";
+ private static final String ITEM_DISABLED_ATTR = "itemDisabled";
+ private static final String ITEM_LABEL_ESCAPED_ATTR = "itemLabelEscaped";
+ private static final String NO_SELECTION_VALUE_ATTR = "noSelectionValue";
+
+ private final Iterator<UIComponent> _children;
+ private Iterator<? extends Object> _nestedItems;
private SelectItem _nextItem;
private String _collectionLabel;
private UISelectItems _currentUISelectItems;
+ private FacesContext _facesContext;
- public _SelectItemsIterator(UIComponent selectItemsParent)
+ public _SelectItemsIterator(UIComponent selectItemsParent, FacesContext facesContext)
{
- _childs = selectItemsParent.getChildren().iterator();
+ _children = selectItemsParent.getChildren().iterator();
+ _facesContext = facesContext;
}
@SuppressWarnings("unchecked")
@@ -55,17 +76,11 @@
{
return true;
}
- // remove the last value from the request map
- if(_currentUISelectItems.getVar() != null && !"".equals(_currentUISelectItems.getVar()))
- {
- FacesContext.getCurrentInstance().getExternalContext()
- .getRequestMap().remove(_currentUISelectItems.getVar());
- }
_nestedItems = null;
}
- if (_childs.hasNext())
+ if (_children.hasNext())
{
- UIComponent child = _childs.next();
+ UIComponent child = _children.next();
// When there is other components nested that does
// not extends from UISelectItem or UISelectItems
// the behavior for this iterator is just skip this
@@ -75,10 +90,10 @@
while (!(child instanceof UISelectItem) && !(child instanceof UISelectItems))
{
// Try to skip it
- if (_childs.hasNext())
+ if (_children.hasNext())
{
// Skip and do the same check
- child = _childs.next();
+ child = _children.next();
}
else
{
@@ -93,24 +108,27 @@
Object item = uiSelectItem.getValue();
if (item == null)
{
- Object itemValue = ((UISelectItem) child).getItemValue();
- String label = ((UISelectItem) child).getItemLabel();
- String description = ((UISelectItem) child).getItemDescription();
- boolean disabled = ((UISelectItem) child).isItemDisabled();
+ // no value attribute --> create the SelectItem out of the other attributes
+ Object itemValue = uiSelectItem.getItemValue();
+ String label = uiSelectItem.getItemLabel();
+ String description = uiSelectItem.getItemDescription();
+ boolean disabled = uiSelectItem.isItemDisabled();
+ boolean escape = uiSelectItem.isItemEscaped();
+ boolean noSelectionOption = uiSelectItem.isNoSelectionOption();
if (label == null)
{
label = itemValue.toString();
}
- item = new SelectItem(itemValue, label, description, disabled);
+ item = new SelectItem(itemValue, label, description, disabled, escape, noSelectionOption);
}
else if (!(item instanceof SelectItem))
{
- ValueBinding binding = ((UISelectItem) child).getValueBinding("value");
- throw new IllegalArgumentException("Value binding '"
- + (binding == null ? null : binding.getExpressionString()) + "' of UISelectItem : "
+ ValueExpression expression = uiSelectItem.getValueExpression("value");
+ throw new IllegalArgumentException("ValueExpression '"
+ + (expression == null ? null : expression.getExpressionString()) + "' of UISelectItem : "
+ getPathToComponent(child) + " does not reference an Object of type SelectItem");
}
- _nextItem = (SelectItem)item;
+ _nextItem = (SelectItem) item;
return true;
}
else if (child instanceof UISelectItems)
@@ -120,19 +138,36 @@
if (value instanceof SelectItem)
{
- _nextItem = (SelectItem)value;
+ _nextItem = (SelectItem) value;
return true;
}
- else if (value instanceof SelectItem[])
+ else if (value != null && value.getClass().isArray())
{
- _nestedItems = Arrays.asList((SelectItem[]) value).iterator();
+ // value is any kind of array (primitive or non-primitive)
+ // --> we have to use class Array to get the values
+ final int length = Array.getLength(value);
+ Collection<Object> items = new ArrayList<Object>(length);
+ for (int i = 0; i < length; i++)
+ {
+ items.add(Array.get(value, i));
+ }
+ _nestedItems = items.iterator();
_collectionLabel = "Array";
return hasNext();
}
- else if (value instanceof Collection)
+ else if (value instanceof Iterable)
{
- _nestedItems = ((Collection<SelectItem>) value).iterator();
- _collectionLabel = "Collection";
+ // 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)
@@ -150,15 +185,14 @@
}
else
{
- ValueBinding binding = _currentUISelectItems.getValueBinding("value");
-
+ ValueExpression expression = _currentUISelectItems.getValueExpression("value");
throw new IllegalArgumentException(
- "Value binding '"
- + (binding == null ? null : binding.getExpressionString())
- + "'of UISelectItems with component-path "
- + getPathToComponent(child)
- + " does not reference an Object of type SelectItem, SelectItem[], Collection or Map but of type : "
- + ((value == null) ? null : value.getClass().getName()));
+ "ValueExpression '"
+ + (expression == null ? null : expression.getExpressionString())
+ + "'of UISelectItems with component-path "
+ + getPathToComponent(child)
+ + " does not reference an Object of type SelectItem, array, Iterable or Map, but of type : "
+ + ((value == null) ? null : value.getClass().getName()));
}
}
}
@@ -181,39 +215,82 @@
{
Object item = _nestedItems.next();
- // write the current item into the request map under the key listed in var, if available
- if(_currentUISelectItems.getVar() != null && !"".equals(_currentUISelectItems.getVar()))
- {
- FacesContext.getCurrentInstance().getExternalContext()
- .getRequestMap().put(_currentUISelectItems.getVar(), item);
- }
-
if (!(item instanceof SelectItem))
{
- // check new params of SelectItems (since 2.0) itemValue, itemLabel, itemDescription,...
- Object itemValue = _currentUISelectItems.getItemValue();
- if(itemValue != null)
- {
- String itemLabel = _currentUISelectItems.getItemLabel() == null ?
- itemValue.toString() :
- _currentUISelectItems.getItemLabel();
- item = new SelectItem(itemValue,
- itemLabel,
- _currentUISelectItems.getItemDescription(),
- _currentUISelectItems.isItemDisabled(),
- _currentUISelectItems.isItemLabelEscaped(),
- itemValue.equals(_currentUISelectItems.getNoSelectionValue())
- || itemLabel.equals(_currentUISelectItems.getNoSelectionValue()));
+ // check new params of SelectItems (since 2.0): itemValue, itemLabel, itemDescription,...
+ // Note that according to the spec UISelectItems does not provide Getter and Setter
+ // methods for this values, so we have to use the attribute map
+ Map<String, Object> attributeMap = _currentUISelectItems.getAttributes();
+
+ // write the current item into the request map under the key listed in var, if available
+ boolean wroteRequestMapVarValue = false;
+ Object oldRequestMapVarValue = null;
+ final String var = (String) attributeMap.get(VAR_ATTR);
+ if(var != null && !"".equals(var))
+ {
+ // save the current value of the key listed in var from the request map
+ oldRequestMapVarValue = _facesContext.getExternalContext().getRequestMap().put(var, item);
+ wroteRequestMapVarValue = true;
}
- else
+ try
{
- ValueExpression expression = _currentUISelectItems.getValueExpression("value");
- throw new IllegalArgumentException(
- _collectionLabel + " referenced by UISelectItems with binding '"
- + expression.getExpressionString()
- + "' and Component-Path : " + getPathToComponent(_currentUISelectItems)
- + " does not contain Objects of type SelectItem"
- + " or does not provide the attribute itemValue");
+ Object itemValue = attributeMap.get(ITEM_VALUE_ATTR);
+ if(itemValue != 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));
+ }
+ 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");
+ }
+ }
+ 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;
@@ -225,6 +302,26 @@
{
throw new UnsupportedOperationException();
}
+
+ private boolean getBooleanAttribute(UIComponent component, String attrName, boolean defaultValue)
+ {
+ Object value = component.getAttributes().get(attrName);
+ if (value == null)
+ {
+ return defaultValue;
+ }
+ else if (value instanceof Boolean)
+ {
+ return (Boolean) value;
+ }
+ else
+ {
+ // If the value is a String, parse the boolean.
+ // This makes the following code work: <tag attribute="true" />,
+ // otherwise you would have to write <tag attribute="#{true}" />.
+ return Boolean.valueOf(value.toString());
+ }
+ }
private String getPathToComponent(UIComponent component)
{
Modified: myfaces/core/trunk/api/src/main/java/javax/faces/component/_UISelectItems.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/api/src/main/java/javax/faces/component/_UISelectItems.java?rev=832865&r1=832864&r2=832865&view=diff
==============================================================================
--- myfaces/core/trunk/api/src/main/java/javax/faces/component/_UISelectItems.java (original)
+++ myfaces/core/trunk/api/src/main/java/javax/faces/component/_UISelectItems.java Wed Nov 4 19:58:13 2009
@@ -19,6 +19,7 @@
package javax.faces.component;
import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFComponent;
+import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFExclude;
import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFProperty;
/**
@@ -79,8 +80,11 @@
* @since 2.0
* @return
*/
+ @JSFExclude
@JSFProperty(literalOnly = true)
- public abstract String getVar();
+ public String getVar() {
+ return null;
+ }
/**
* The value for the current item.
@@ -88,8 +92,11 @@
* @since 2.0
* @return
*/
+ @JSFExclude
@JSFProperty
- public abstract Object getItemValue();
+ public Object getItemValue() {
+ return null;
+ }
/**
* The label of the current item.
@@ -97,8 +104,11 @@
* @since 2.0
* @return
*/
+ @JSFExclude
@JSFProperty
- public abstract String getItemLabel();
+ public String getItemLabel() {
+ return null;
+ }
/**
* The description of the current item.
@@ -106,8 +116,11 @@
* @since 2.0
* @return
*/
+ @JSFExclude
@JSFProperty
- public abstract String getItemDescription();
+ public String getItemDescription() {
+ return null;
+ }
/**
* Determines if the current item is selectable or not.
@@ -115,8 +128,11 @@
* @since 2.0
* @return
*/
+ @JSFExclude
@JSFProperty(defaultValue = "false")
- public abstract boolean isItemDisabled();
+ public boolean isItemDisabled() {
+ return false;
+ }
/**
* Determines if the rendered markup for the current item receives
@@ -125,8 +141,11 @@
* @since 2.0
* @return
*/
+ @JSFExclude
@JSFProperty(defaultValue = "true")
- public abstract boolean isItemLabelEscaped();
+ public boolean isItemLabelEscaped() {
+ return true;
+ }
/**
* Is either an EL expression pointing to the element in the value collection
@@ -138,7 +157,10 @@
* @since 2.0
* @return
*/
+ @JSFExclude
@JSFProperty
- public abstract Object getNoSelectionValue();
+ public Object getNoSelectionValue() {
+ return null;
+ }
}
Modified: myfaces/core/trunk/api/src/test/java/javax/faces/component/UISelectItemsTest.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/api/src/test/java/javax/faces/component/UISelectItemsTest.java?rev=832865&r1=832864&r2=832865&view=diff
==============================================================================
--- myfaces/core/trunk/api/src/test/java/javax/faces/component/UISelectItemsTest.java (original)
+++ myfaces/core/trunk/api/src/test/java/javax/faces/component/UISelectItemsTest.java Wed Nov 4 19:58:13 2009
@@ -1,3 +1,21 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
package javax.faces.component;
import java.util.ArrayList;
@@ -8,6 +26,11 @@
import org.apache.shale.test.base.AbstractJsfTestCase;
import org.apache.shale.test.el.MockValueExpression;
+/**
+ * Tests for UISelectItems.
+ * @author Jakob Korherr (latest modification by $Author$)
+ * @version $Revision$ $Date$
+ */
public class UISelectItemsTest extends AbstractJsfTestCase
{
@@ -15,7 +38,7 @@
{
super(name);
}
-
+
public void testStringListAsValue()
{
List<String> value = new ArrayList<String>();
@@ -25,14 +48,14 @@
UISelectItems selectItems = new UISelectItems();
selectItems.setValue(value);
- selectItems.setVar("item");
+ selectItems.getAttributes().put("var", "item");
ValueExpression itemValue = new MockValueExpression("#{item}", Object.class);
selectItems.setValueExpression("itemValue" , itemValue);
UISelectOne selectOne = new UISelectOne();
selectOne.getChildren().add(selectItems);
- _SelectItemsIterator iter = new _SelectItemsIterator(selectOne);
+ _SelectItemsIterator iter = new _SelectItemsIterator(selectOne, facesContext);
List<String> options = new ArrayList<String>();
while(iter.hasNext())
{
@@ -41,4 +64,31 @@
assertEquals(value, options);
}
+
+ public void testPrimitiveArrayAsValue()
+ {
+ int[] value = new int[3];
+ value[0] = 1;
+ value[1] = 2;
+ value[2] = 3;
+
+ UISelectItems selectItems = new UISelectItems();
+ selectItems.setValue(value);
+ selectItems.getAttributes().put("var", "item");
+ ValueExpression itemValue = new MockValueExpression("#{item}", Object.class);
+ selectItems.setValueExpression("itemValue" , itemValue);
+
+ UISelectOne selectOne = new UISelectOne();
+ selectOne.getChildren().add(selectItems);
+
+ _SelectItemsIterator iter = new _SelectItemsIterator(selectOne, facesContext);
+ int[] options = new int[3];
+ for (int i = 0; i < 3; i++)
+ {
+ options[i] = (Integer) iter.next().getValue();
+
+ // test equality
+ assertEquals(value[i], options[i]);
+ }
+ }
}
Modified: myfaces/shared/trunk_4.0.x/core/src/main/java/org/apache/myfaces/shared/renderkit/JSFAttr.java
URL: http://svn.apache.org/viewvc/myfaces/shared/trunk_4.0.x/core/src/main/java/org/apache/myfaces/shared/renderkit/JSFAttr.java?rev=832865&r1=832864&r2=832865&view=diff
==============================================================================
--- myfaces/shared/trunk_4.0.x/core/src/main/java/org/apache/myfaces/shared/renderkit/JSFAttr.java (original)
+++ myfaces/shared/trunk_4.0.x/core/src/main/java/org/apache/myfaces/shared/renderkit/JSFAttr.java Wed Nov 4 19:58:13 2009
@@ -127,6 +127,11 @@
String ITEM_LABEL_ATTR = "itemLabel";
String ITEM_VALUE_ATTR = "itemValue";
String ITEM_ESCAPED_ATTR = "itemEscaped";
+ String NO_SELECTION_OPTION_ATTR = "noSelectionOption";
+
+ // UISelectItems attributes
+ String ITEM_LABEL_ESCAPED_ATTR = "itemLabelEscaped";
+ String NO_SELECTION_VALUE_ATTR = "noSelectionValue";
// UIData attributes
String ROWS_ATTR = "rows";
Modified: myfaces/shared/trunk_4.0.x/core/src/main/java/org/apache/myfaces/shared/renderkit/RendererUtils.java
URL: http://svn.apache.org/viewvc/myfaces/shared/trunk_4.0.x/core/src/main/java/org/apache/myfaces/shared/renderkit/RendererUtils.java?rev=832865&r1=832864&r2=832865&view=diff
==============================================================================
--- myfaces/shared/trunk_4.0.x/core/src/main/java/org/apache/myfaces/shared/renderkit/RendererUtils.java (original)
+++ myfaces/shared/trunk_4.0.x/core/src/main/java/org/apache/myfaces/shared/renderkit/RendererUtils.java Wed Nov 4 19:58:13 2009
@@ -441,7 +441,7 @@
// contains by looking at the SelectItem value of the first item. With generics in
// JDK 1.5, it would be much easier to determine the type.
- List selectItems = RendererUtils.internalGetSelectItemList(component);
+ List selectItems = RendererUtils.internalGetSelectItemList(component, facesContext);
if (selectItems != null && selectItems.size() > 0)
{
@@ -539,23 +539,25 @@
/**
* @param uiSelectOne
+ * @param facesContext
* @return List of SelectItem Objects
*/
- public static List getSelectItemList(UISelectOne uiSelectOne)
+ public static List getSelectItemList(UISelectOne uiSelectOne, FacesContext facesContext)
{
- return internalGetSelectItemList(uiSelectOne);
+ return internalGetSelectItemList(uiSelectOne, facesContext);
}
/**
* @param uiSelectMany
+ * @param facesContext
* @return List of SelectItem Objects
*/
- public static List getSelectItemList(UISelectMany uiSelectMany)
+ public static List getSelectItemList(UISelectMany uiSelectMany, FacesContext facesContext)
{
- return internalGetSelectItemList(uiSelectMany);
+ return internalGetSelectItemList(uiSelectMany, facesContext);
}
- private static List internalGetSelectItemList(UIComponent uiComponent)
+ private static List internalGetSelectItemList(UIComponent uiComponent, FacesContext facesContext)
{
/* TODO: Shall we cache the list in a component attribute?
ArrayList list = (ArrayList)uiComponent.getAttributes().get(SELECT_ITEM_LIST_ATTR);
@@ -567,7 +569,7 @@
List list = new ArrayList();
- for (Iterator iter = new SelectItemsIterator(uiComponent); iter.hasNext();)
+ for (Iterator iter = new SelectItemsIterator(uiComponent, facesContext); iter.hasNext();)
{
list.add(iter.next());
}
Modified: myfaces/shared/trunk_4.0.x/core/src/main/java/org/apache/myfaces/shared/renderkit/html/HtmlCheckboxRendererBase.java
URL: http://svn.apache.org/viewvc/myfaces/shared/trunk_4.0.x/core/src/main/java/org/apache/myfaces/shared/renderkit/html/HtmlCheckboxRendererBase.java?rev=832865&r1=832864&r2=832865&view=diff
==============================================================================
--- myfaces/shared/trunk_4.0.x/core/src/main/java/org/apache/myfaces/shared/renderkit/html/HtmlCheckboxRendererBase.java (original)
+++ myfaces/shared/trunk_4.0.x/core/src/main/java/org/apache/myfaces/shared/renderkit/html/HtmlCheckboxRendererBase.java Wed Nov 4 19:58:13 2009
@@ -122,7 +122,7 @@
int itemNum = 0;
- for (Iterator it = org.apache.myfaces.shared.renderkit.RendererUtils.getSelectItemList(selectMany)
+ for (Iterator it = org.apache.myfaces.shared.renderkit.RendererUtils.getSelectItemList(selectMany, facesContext)
.iterator(); it.hasNext();) {
SelectItem selectItem = (SelectItem) it.next();
Modified: myfaces/shared/trunk_4.0.x/core/src/main/java/org/apache/myfaces/shared/renderkit/html/HtmlRadioRendererBase.java
URL: http://svn.apache.org/viewvc/myfaces/shared/trunk_4.0.x/core/src/main/java/org/apache/myfaces/shared/renderkit/html/HtmlRadioRendererBase.java?rev=832865&r1=832864&r2=832865&view=diff
==============================================================================
--- myfaces/shared/trunk_4.0.x/core/src/main/java/org/apache/myfaces/shared/renderkit/html/HtmlRadioRendererBase.java (original)
+++ myfaces/shared/trunk_4.0.x/core/src/main/java/org/apache/myfaces/shared/renderkit/html/HtmlRadioRendererBase.java Wed Nov 4 19:58:13 2009
@@ -91,7 +91,7 @@
if (!pageDirectionLayout) writer.startElement(HTML.TR_ELEM, selectOne);
Converter converter;
- List selectItemList = org.apache.myfaces.shared.renderkit.RendererUtils.getSelectItemList(selectOne);
+ List selectItemList = org.apache.myfaces.shared.renderkit.RendererUtils.getSelectItemList(selectOne, facesContext);
converter = HtmlRendererUtils.findUIOutputConverterFailSafe(facesContext, selectOne);
Object currentValue = org.apache.myfaces.shared.renderkit.RendererUtils.getObjectValue(selectOne);
Modified: myfaces/shared/trunk_4.0.x/core/src/main/java/org/apache/myfaces/shared/renderkit/html/HtmlRendererUtils.java
URL: http://svn.apache.org/viewvc/myfaces/shared/trunk_4.0.x/core/src/main/java/org/apache/myfaces/shared/renderkit/html/HtmlRendererUtils.java?rev=832865&r1=832864&r2=832865&view=diff
==============================================================================
--- myfaces/shared/trunk_4.0.x/core/src/main/java/org/apache/myfaces/shared/renderkit/html/HtmlRendererUtils.java (original)
+++ myfaces/shared/trunk_4.0.x/core/src/main/java/org/apache/myfaces/shared/renderkit/html/HtmlRendererUtils.java Wed Nov 4 19:58:13 2009
@@ -394,11 +394,11 @@
if (selectMany) {
writer.writeAttribute(HTML.MULTIPLE_ATTR, HTML.MULTIPLE_ATTR, null);
selectItemList = org.apache.myfaces.shared.renderkit.RendererUtils
- .getSelectItemList((UISelectMany) uiComponent);
+ .getSelectItemList((UISelectMany) uiComponent, facesContext);
converter = findUISelectManyConverterFailsafe(facesContext, uiComponent);
} else {
selectItemList = RendererUtils
- .getSelectItemList((UISelectOne) uiComponent);
+ .getSelectItemList((UISelectOne) uiComponent, facesContext);
converter = findUIOutputConverterFailSafe(facesContext, uiComponent);
}
@@ -811,12 +811,12 @@
if (uiComponent instanceof UISelectMany) {
isSelectOne = false;
selectItemList = RendererUtils
- .getSelectItemList((UISelectMany) uiComponent);
+ .getSelectItemList((UISelectMany) uiComponent, facesContext);
converter = findUISelectManyConverterFailsafe(facesContext, uiComponent);
} else if(uiComponent instanceof UISelectOne){
isSelectOne = true;
selectItemList = RendererUtils
- .getSelectItemList((UISelectOne) uiComponent);
+ .getSelectItemList((UISelectOne) uiComponent, facesContext);
converter = findUIOutputConverterFailSafe(facesContext, uiComponent);
}
Modified: myfaces/shared/trunk_4.0.x/core/src/main/java/org/apache/myfaces/shared/util/SelectItemsIterator.java
URL: http://svn.apache.org/viewvc/myfaces/shared/trunk_4.0.x/core/src/main/java/org/apache/myfaces/shared/util/SelectItemsIterator.java?rev=832865&r1=832864&r2=832865&view=diff
==============================================================================
--- myfaces/shared/trunk_4.0.x/core/src/main/java/org/apache/myfaces/shared/util/SelectItemsIterator.java (original)
+++ myfaces/shared/trunk_4.0.x/core/src/main/java/org/apache/myfaces/shared/util/SelectItemsIterator.java Wed Nov 4 19:58:13 2009
@@ -18,8 +18,8 @@
*/
package org.apache.myfaces.shared.util;
+import java.lang.reflect.Array;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
@@ -30,70 +30,80 @@
import javax.faces.component.UISelectItem;
import javax.faces.component.UISelectItems;
import javax.faces.context.FacesContext;
-import javax.faces.el.ValueBinding;
import javax.faces.model.SelectItem;
+import org.apache.myfaces.shared.renderkit.JSFAttr;
import org.apache.myfaces.shared.renderkit.RendererUtils;
+// ATTENTION
+// This class is associated with javax.faces.component._SelectItemsIterator.
+// Changes here should also be applied to this class.
+
/**
* @author Mathias Broekelmann (latest modification by $Author$)
+ * @author Jakob Korherr (jsf 2.0)
* @version $Revision$ $Date$
*/
-public class SelectItemsIterator implements Iterator
+public class SelectItemsIterator implements Iterator<SelectItem>
{
- private final Iterator _childs;
- private Iterator _nestedItems;
- private Object _nextItem;
+
+ private static final String VAR_ATTR = JSFAttr.VAR_ATTR;
+ private static final String ITEM_VALUE_ATTR = JSFAttr.ITEM_VALUE_ATTR;
+ private static final String ITEM_LABEL_ATTR = JSFAttr.ITEM_LABEL_ATTR;
+ private static final String ITEM_DESCRIPTION_ATTR = JSFAttr.ITEM_DESCRIPTION_ATTR;
+ private static final String ITEM_DISABLED_ATTR = JSFAttr.ITEM_DISABLED_ATTR;
+ private static final String ITEM_LABEL_ESCAPED_ATTR = JSFAttr.ITEM_LABEL_ESCAPED_ATTR;
+ private static final String NO_SELECTION_VALUE_ATTR = JSFAttr.NO_SELECTION_VALUE_ATTR;
+
+ private final Iterator<UIComponent> _children;
+ private Iterator<? extends Object> _nestedItems;
+ private SelectItem _nextItem;
private String _collectionLabel;
private UISelectItems _currentUISelectItems;
+ private FacesContext _facesContext;
- public SelectItemsIterator(UIComponent selectItemsParent)
+ public SelectItemsIterator(UIComponent selectItemsParent, FacesContext facesContext)
{
- _childs = selectItemsParent.getChildren().iterator();
+ _children = selectItemsParent.getChildren().iterator();
+ _facesContext = facesContext;
}
+ @SuppressWarnings("unchecked")
public boolean hasNext()
{
- if(_nextItem != null)
+ if (_nextItem != null)
{
return true;
}
- if(_nestedItems != null)
+ if (_nestedItems != null)
{
- if(_nestedItems.hasNext())
+ if (_nestedItems.hasNext())
{
return true;
}
- // remove the last value from the request map
- if(_currentUISelectItems.getVar() != null && !"".equals(_currentUISelectItems.getVar()))
- {
- FacesContext.getCurrentInstance().getExternalContext()
- .getRequestMap().remove(_currentUISelectItems.getVar());
- }
_nestedItems = null;
- }
- if (_childs.hasNext())
+ }
+ if (_children.hasNext())
{
- UIComponent child = (UIComponent) _childs.next();
+ UIComponent child = _children.next();
// When there is other components nested that does
// not extends from UISelectItem or UISelectItems
// the behavior for this iterator is just skip this
// element(s) until an element that extends from these
// classes are found. If there is no more elements
// that conform this condition, just return false.
- while (!(child instanceof UISelectItem)
- && !(child instanceof UISelectItems))
+ while (!(child instanceof UISelectItem) && !(child instanceof UISelectItems))
{
- //Try to skip it
- if (_childs.hasNext())
+ // Try to skip it
+ if (_children.hasNext())
{
- //Skip and do the same check
- child = (UIComponent) _childs.next();
+ // Skip and do the same check
+ child = _children.next();
}
else
{
- //End loop, so the final result is return false,
- //since there are no more components to iterate.
+ // End loop, so the final result is return false,
+ // since there are no more components to iterate.
return false;
}
}
@@ -103,31 +113,27 @@
Object item = uiSelectItem.getValue();
if (item == null)
{
- Object itemValue = ((UISelectItem) child).getItemValue();
- String label = ((UISelectItem) child).getItemLabel();
- String description = ((UISelectItem) child)
- .getItemDescription();
- boolean disabled = ((UISelectItem) child).isItemDisabled();
- boolean escaped = ((UISelectItem) child).isItemEscaped();
+ // no value attribute --> create the SelectItem out of the other attributes
+ Object itemValue = uiSelectItem.getItemValue();
+ String label = uiSelectItem.getItemLabel();
+ String description = uiSelectItem.getItemDescription();
+ boolean disabled = uiSelectItem.isItemDisabled();
+ boolean escape = uiSelectItem.isItemEscaped();
+ boolean noSelectionOption = uiSelectItem.isNoSelectionOption();
if (label == null)
{
label = itemValue.toString();
}
- item = new SelectItem(itemValue, label, description,
- disabled, escaped);
+ item = new SelectItem(itemValue, label, description, disabled, escape, noSelectionOption);
}
else if (!(item instanceof SelectItem))
{
- ValueBinding binding = ((UISelectItem) child)
- .getValueBinding("value");
- throw new IllegalArgumentException(
- "Value binding '"
- + (binding == null ? null : binding.getExpressionString())
- + "' of UISelectItem : "
- + RendererUtils.getPathToComponent(child)
- + " does not reference an Object of type SelectItem");
+ ValueExpression expression = uiSelectItem.getValueExpression("value");
+ throw new IllegalArgumentException("ValueExpression '"
+ + (expression == null ? null : expression.getExpressionString()) + "' of UISelectItem : "
+ + RendererUtils.getPathToComponent(child) + " does not reference an Object of type SelectItem");
}
- _nextItem = item;
+ _nextItem = (SelectItem) item;
return true;
}
else if (child instanceof UISelectItems)
@@ -137,109 +143,162 @@
if (value instanceof SelectItem)
{
- _nextItem = value;
+ _nextItem = (SelectItem) value;
return true;
}
- else if (value instanceof SelectItem[])
+ else if (value != null && value.getClass().isArray())
{
- _nestedItems = Arrays.asList((SelectItem[]) value)
- .iterator();
+ // value is any kind of array (primitive or non-primitive)
+ // --> we have to use class Array to get the values
+ final int length = Array.getLength(value);
+ Collection<Object> items = new ArrayList<Object>(length);
+ for (int i = 0; i < length; i++)
+ {
+ items.add(Array.get(value, i));
+ }
+ _nestedItems = items.iterator();
_collectionLabel = "Array";
return hasNext();
}
- else if (value instanceof Collection)
+ else if (value instanceof Iterable)
{
- _nestedItems = ((Collection)value).iterator();
- _collectionLabel = "Collection";
+ // 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)
{
- Map map = ((Map) value);
- Collection items = new ArrayList(map.size());
- for (Iterator it = map.entrySet().iterator(); it
- .hasNext();)
- {
- Map.Entry entry = (Map.Entry) it.next();
- items.add(new SelectItem(entry.getValue(), entry
- .getKey().toString()));
+ Map<Object, Object> map = ((Map<Object, Object>) value);
+ Collection<SelectItem> items = new ArrayList<SelectItem>(map.size());
+ for (Map.Entry<Object, Object> entry : map.entrySet())
+ {
+ items.add(new SelectItem(entry.getValue(), entry.getKey().toString()));
}
+
_nestedItems = items.iterator();
_collectionLabel = "Map";
return hasNext();
}
else
{
- ValueBinding binding = _currentUISelectItems.getValueBinding("value");
-
+ ValueExpression expression = _currentUISelectItems.getValueExpression("value");
throw new IllegalArgumentException(
- "Value binding '"
- + (binding == null ? null : binding
- .getExpressionString())
- + "'of UISelectItems with component-path "
- + RendererUtils.getPathToComponent(child)
- + " does not reference an Object of type SelectItem, SelectItem[], Collection or Map but of type : "
- + ((value == null) ? null : value
- .getClass()
- .getName()));
+ "ValueExpression '"
+ + (expression == null ? null : expression.getExpressionString())
+ + "'of UISelectItems with component-path "
+ + RendererUtils.getPathToComponent(child)
+ + " does not reference an Object of type SelectItem, array, Iterable or Map, but of type : "
+ + ((value == null) ? null : value.getClass().getName()));
}
}
}
return false;
}
- public Object next()
+ public SelectItem next()
{
if (!hasNext())
{
throw new NoSuchElementException();
}
- if(_nextItem != null)
+ if (_nextItem != null)
{
- Object value = _nextItem;
+ SelectItem value = _nextItem;
_nextItem = null;
return value;
- }
+ }
if (_nestedItems != null)
{
Object item = _nestedItems.next();
- // write the current item into the request map under the key listed in var, if available
- if(_currentUISelectItems.getVar() != null && !"".equals(_currentUISelectItems.getVar()))
- {
- FacesContext.getCurrentInstance().getExternalContext()
- .getRequestMap().put(_currentUISelectItems.getVar(), item);
- }
-
if (!(item instanceof SelectItem))
{
- // check new params of SelectItems (since 2.0) itemValue, itemLabel,...
- Object itemValue = _currentUISelectItems.getItemValue();
- if(itemValue != null)
- {
- String itemLabel = _currentUISelectItems.getItemLabel() == null ?
- itemValue.toString() :
- _currentUISelectItems.getItemLabel();
- item = new SelectItem(itemValue,
- itemLabel,
- _currentUISelectItems.getItemDescription(),
- _currentUISelectItems.isItemDisabled(),
- _currentUISelectItems.isItemLabelEscaped(),
- itemValue.equals(_currentUISelectItems.getNoSelectionValue())
- || itemLabel.equals(_currentUISelectItems.getNoSelectionValue()));
+ // check new params of SelectItems (since 2.0): itemValue, itemLabel, itemDescription,...
+ // Note that according to the spec UISelectItems does not provide Getter and Setter
+ // methods for this values, so we have to use the attribute map
+ Map<String, Object> attributeMap = _currentUISelectItems.getAttributes();
+
+ // write the current item into the request map under the key listed in var, if available
+ boolean wroteRequestMapVarValue = false;
+ Object oldRequestMapVarValue = null;
+ final String var = (String) attributeMap.get(VAR_ATTR);
+ if(var != null && !"".equals(var))
+ {
+ // save the current value of the key listed in var from the request map
+ oldRequestMapVarValue = _facesContext.getExternalContext().getRequestMap().put(var, item);
+ wroteRequestMapVarValue = true;
}
- else
+ try
{
- ValueExpression expression = _currentUISelectItems.getValueExpression("value");
- throw new IllegalArgumentException(
- _collectionLabel + " referenced by UISelectItems with binding '"
- + expression.getExpressionString()
- + "' and Component-Path : " + RendererUtils.getPathToComponent(_currentUISelectItems)
- + " does not contain Objects of type SelectItem"
- + " or does not provide the attribute itemValue");
+ Object itemValue = attributeMap.get(ITEM_VALUE_ATTR);
+ if(itemValue != 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));
+ }
+ else
+ {
+ ValueExpression expression = _currentUISelectItems.getValueExpression("value");
+ throw new IllegalArgumentException(
+ _collectionLabel + " referenced by UISelectItems with ValueExpression '"
+ + expression.getExpressionString()
+ + "' and Component-Path : " + RendererUtils.getPathToComponent(_currentUISelectItems)
+ + " does not contain Objects of type SelectItem"
+ + " or does not provide the attribute itemValue");
+ }
+ }
+ 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 item;
+ return (SelectItem) item;
}
throw new NoSuchElementException();
}
@@ -248,4 +307,25 @@
{
throw new UnsupportedOperationException();
}
+
+ private boolean getBooleanAttribute(UIComponent component, String attrName, boolean defaultValue)
+ {
+ Object value = component.getAttributes().get(attrName);
+ if (value == null)
+ {
+ return defaultValue;
+ }
+ else if (value instanceof Boolean)
+ {
+ return (Boolean) value;
+ }
+ else
+ {
+ // If the value is a String, parse the boolean.
+ // This makes the following code work: <tag attribute="true" />,
+ // otherwise you would have to write <tag attribute="#{true}" />.
+ return Boolean.valueOf(value.toString());
+ }
+ }
+
}