You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by mb...@apache.org on 2005/09/02 14:49:26 UTC

svn commit: r267196 - in /myfaces: api/trunk/src/java/javax/faces/component/UISelectOne.java share/trunk/src/java/org/apache/myfaces/renderkit/RendererUtils.java share/trunk/src/java/org/apache/myfaces/util/SelectItemsIterator.java

Author: mbr
Date: Fri Sep  2 05:49:18 2005
New Revision: 267196

URL: http://svn.apache.org/viewcvs?rev=267196&view=rev
Log:
fix for MYFACES-465

Added:
    myfaces/share/trunk/src/java/org/apache/myfaces/util/SelectItemsIterator.java
Modified:
    myfaces/api/trunk/src/java/javax/faces/component/UISelectOne.java
    myfaces/share/trunk/src/java/org/apache/myfaces/renderkit/RendererUtils.java

Modified: myfaces/api/trunk/src/java/javax/faces/component/UISelectOne.java
URL: http://svn.apache.org/viewcvs/myfaces/api/trunk/src/java/javax/faces/component/UISelectOne.java?rev=267196&r1=267195&r2=267196&view=diff
==============================================================================
--- myfaces/api/trunk/src/java/javax/faces/component/UISelectOne.java (original)
+++ myfaces/api/trunk/src/java/javax/faces/component/UISelectOne.java Fri Sep  2 05:49:18 2005
@@ -15,8 +15,14 @@
  */
 package javax.faces.component;
 
+import java.util.Arrays;
+import java.util.Iterator;
+
 import javax.faces.context.FacesContext;
+import javax.faces.model.SelectItem;
+import javax.faces.model.SelectItemGroup;
 
+import org.apache.myfaces.util.SelectItemsIterator;
 
 /**
  * see Javadoc of JSF Specification
@@ -24,18 +30,62 @@
  * @author Manfred Geiler (latest modification by $Author$)
  * @version $Revision$ $Date$
  */
-public class UISelectOne
-        extends UIInput
+public class UISelectOne extends UIInput
 {
     public static final String INVALID_MESSAGE_ID = "javax.faces.component.UISelectOne.INVALID";
 
-    public void validate(FacesContext context)
+    /**
+     * @see javax.faces.component.UIInput#validateValue(javax.faces.context.FacesContext, java.lang.Object)
+     */
+    protected void validateValue(FacesContext context, Object value)
     {
-        super.validate(context);
-        //TODO: see javadoc: iterate through UISelectItem and UISelectItems and check
-        //current value against these items
+        super.validateValue(context, value);
+
+        if (!isValid() || value == null)
+        {
+            return;
+        }
+
+        // selected value must match to one of the available options
+        if (!matchValue(context, value, new SelectItemsIterator(this)))
+        {
+            _MessageUtils.addErrorMessage(context, this, INVALID_MESSAGE_ID,
+                            new Object[] {getId()});
+            setValid(false);
+        }
     }
 
+    /**
+     * @param context
+     * @param value 
+     * @param iterator
+     * @return
+     */
+    private boolean matchValue(FacesContext context, Object value,
+                    Iterator selectItemsIter)
+    {
+        while (selectItemsIter.hasNext())
+        {
+            SelectItem item = (SelectItem) selectItemsIter.next();
+            if (value.equals(item.getValue()))
+            {
+                return true;
+            }
+            if (item instanceof SelectItemGroup)
+            {
+                SelectItemGroup itemgroup = (SelectItemGroup) item;
+                SelectItem[] selectItems = itemgroup.getSelectItems();
+                if (selectItems != null
+                                && selectItems.length > 0
+                                && matchValue(context, value, Arrays.asList(
+                                                selectItems).iterator()))
+                {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
 
     //------------------ GENERATED CODE BEGIN (do not modify!) --------------------
 
@@ -43,7 +93,6 @@
     public static final String COMPONENT_FAMILY = "javax.faces.SelectOne";
     private static final String DEFAULT_RENDERER_TYPE = "javax.faces.Menu";
 
-
     public UISelectOne()
     {
         setRendererType(DEFAULT_RENDERER_TYPE);
@@ -53,7 +102,6 @@
     {
         return COMPONENT_FAMILY;
     }
-
 
     //------------------ GENERATED CODE END ---------------------------------------
 }

Modified: myfaces/share/trunk/src/java/org/apache/myfaces/renderkit/RendererUtils.java
URL: http://svn.apache.org/viewcvs/myfaces/share/trunk/src/java/org/apache/myfaces/renderkit/RendererUtils.java?rev=267196&r1=267195&r2=267196&view=diff
==============================================================================
--- myfaces/share/trunk/src/java/org/apache/myfaces/renderkit/RendererUtils.java (original)
+++ myfaces/share/trunk/src/java/org/apache/myfaces/renderkit/RendererUtils.java Fri Sep  2 05:49:18 2005
@@ -52,6 +52,7 @@
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.myfaces.util.HashMapUtils;
+import org.apache.myfaces.util.SelectItemsIterator;
 
 /**
  * @author Manfred Geiler (latest modification by $Author$)
@@ -478,95 +479,13 @@
             return list;
         }
          */
-
-        List list = new ArrayList(uiComponent.getChildCount());
-        for (Iterator children = uiComponent.getChildren().iterator(); children.hasNext(); )
+        
+        List list = new ArrayList();
+        
+        for (Iterator iter = new SelectItemsIterator(uiComponent); iter.hasNext();)
         {
-            UIComponent child = (UIComponent)children.next();
-            if (child instanceof UISelectItem)
-            {
-                Object value = ((UISelectItem) child).getValue();
-                if (value != null)
-                {
-                    //get SelectItem from model via value binding
-                    if (!(value instanceof SelectItem))
-                    {
-                        ValueBinding binding = ((UISelectItem) child).getValueBinding("value");
-                        throw new IllegalArgumentException("Value binding '"+(binding==null?null:binding.getExpressionString())
-                                +"' of UISelectItem : " + getPathToComponent(child) + " does not reference an Object of type SelectItem");
-                    }
-                    list.add(value);
-                }
-                else
-                {
-                    Object itemValue = ((UISelectItem)child).getItemValue();
-                    String label = ((UISelectItem)child).getItemLabel();
-                    String description = ((UISelectItem)child).getItemDescription();
-                    boolean disabled = ((UISelectItem)child).isItemDisabled();
-                    if (label == null)
-                    {
-                        list.add(new SelectItem(itemValue, itemValue.toString(), description, disabled));
-                    }
-                    else
-                    {
-                        list.add(new SelectItem(itemValue, label, description, disabled));
-                    }
-                }
-            }
-            else if (child instanceof UISelectItems)
-            {
-                UISelectItems items = ((UISelectItems) child);
-
-                Object value = items.getValue(); // TODO : Check here for getSubmittedValue.
-
-                if (value instanceof SelectItem)
-                {
-                    list.add(value);
-                }
-                else if (value instanceof SelectItem[])
-                {
-                    for (int i = 0; i < ((SelectItem[])value).length; i++)
-                    {
-                        list.add(((SelectItem[])value)[i]);
-                    }
-                }
-                else if (value instanceof Collection)
-                {
-                    for (Iterator it = ((Collection)value).iterator(); it.hasNext();)
-                    {
-                        Object item = it.next();
-                        if (!(item instanceof SelectItem))
-                        {
-                            ValueBinding binding = items.getValueBinding("value");
-                            throw new IllegalArgumentException("Collection referenced by UISelectItems with binding '"+
-                                    binding.getExpressionString()+"' and Component-Path : " + getPathToComponent(child) + " does not contain Objects of type SelectItem");
-                        }
-                        list.add(item);
-                    }
-                }
-                else if (value instanceof Map)
-                {
-                    for (Iterator it = ((Map)value).entrySet().iterator(); it.hasNext();)
-                    {
-                        Map.Entry entry = (Map.Entry)it.next();
-                        list.add(new SelectItem(entry.getValue(), entry.getKey().toString()));
-                    }
-                }
-                else
-                {
-                    ValueBinding binding = items.getValueBinding("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()));
-                }
-            }
-            else
-            {
-                //todo: may other objects than selectItems be nested or not?
-                //log.error("Invalid component : " + getPathToComponent(child) + " : must be UISelectItem or UISelectItems, is of type : "+((child==null)?"null":child.getClass().getName()));
-            }
-        }
-
+            list.add(iter.next());            
+        }        
         return list;
     }
 

Added: myfaces/share/trunk/src/java/org/apache/myfaces/util/SelectItemsIterator.java
URL: http://svn.apache.org/viewcvs/myfaces/share/trunk/src/java/org/apache/myfaces/util/SelectItemsIterator.java?rev=267196&view=auto
==============================================================================
--- myfaces/share/trunk/src/java/org/apache/myfaces/util/SelectItemsIterator.java (added)
+++ myfaces/share/trunk/src/java/org/apache/myfaces/util/SelectItemsIterator.java Fri Sep  2 05:49:18 2005
@@ -0,0 +1,187 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ *
+ * Licensed 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 org.apache.myfaces.util;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.NoSuchElementException;
+
+import javax.faces.component.UIComponent;
+import javax.faces.component.UISelectItem;
+import javax.faces.component.UISelectItems;
+import javax.faces.el.ValueBinding;
+import javax.faces.model.SelectItem;
+
+import org.apache.myfaces.renderkit.RendererUtils;
+
+/**
+ * @author Mathias Broekelmann (latest modification by $Author$)
+ * @version $Revision$ $Date$
+ */
+public class SelectItemsIterator implements Iterator
+{
+    private final Iterator _childs;
+    private Iterator _nestedItems;
+    private UISelectItems _currentUISelectItems;
+    private String _collectionLabel;
+
+    public SelectItemsIterator(UIComponent selectItemsParent)
+    {
+        _childs = selectItemsParent.getChildren().iterator();
+    }
+
+    public boolean hasNext()
+    {
+        if (_nestedItems != null)
+        {
+            if (_nestedItems.hasNext())
+            {
+                return true;
+            }
+            _nestedItems = null;
+            _currentUISelectItems = null;
+        }
+        return _childs.hasNext();
+    }
+
+    public Object next()
+    {
+        if (!hasNext())
+        {
+            throw new NoSuchElementException();
+        }
+        if (_nestedItems != null)
+        {
+            Object item = _nestedItems.next();
+            if (!(item instanceof SelectItem))
+            {
+                ValueBinding binding = _currentUISelectItems
+                                .getValueBinding("value");
+                throw new IllegalArgumentException(
+                _collectionLabel + " referenced by UISelectItems with binding '"
+                + binding.getExpressionString()
+                + "' and Component-Path : " + RendererUtils.getPathToComponent(_currentUISelectItems)
+                + " does not contain Objects of type SelectItem");
+            }
+            return _nestedItems.next();
+        }
+        else if (_childs.hasNext())
+        {
+            UIComponent child = (UIComponent) _childs.next();
+            if (child instanceof UISelectItem)
+            {
+                UISelectItem uiSelectItem = (UISelectItem) child;
+                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();
+                    if (label == null)
+                    {
+                        return new SelectItem(itemValue, itemValue.toString(),
+                                        description, disabled);
+                    }
+                    return new SelectItem(itemValue, label, description,
+                                    disabled);
+                }
+                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");
+                }
+                return item;
+            }
+            else if (child instanceof UISelectItems)
+            {
+                _currentUISelectItems = ((UISelectItems) child);
+
+                Object value = _currentUISelectItems.getValue();
+
+                if (value instanceof SelectItem)
+                {
+                    return value;
+                }
+                else if (value instanceof SelectItem[])
+                {
+                    _nestedItems = Arrays.asList((SelectItem[]) value)
+                                    .iterator();
+                    _collectionLabel = "Array";
+                    return next();
+                }
+                else if (value instanceof Collection)
+                {
+                    _nestedItems = ((Collection)value).iterator();
+                    _collectionLabel = "Collection";
+                    return next();
+                }
+                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()));
+                    }
+                    _nestedItems = items.iterator();
+                    _collectionLabel = null;
+                    return next();
+                }
+                else
+                {
+                    ValueBinding binding = _currentUISelectItems.getValueBinding("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()));
+                }
+            }
+            else
+            {
+                //todo: may other objects than selectItems be nested or not?
+                //log.error("Invalid component : " + getPathToComponent(child) + " : must be UISelectItem or UISelectItems, is of type : "+((child==null)?"null":child.getClass().getName()));
+            }
+        }
+        return null;
+    }
+
+    public void remove()
+    {
+        throw new UnsupportedOperationException();
+    }
+
+}