You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by ma...@apache.org on 2010/11/04 15:39:50 UTC

svn commit: r1031006 - in /myfaces/core/trunk/api/src: main/java/javax/faces/component/ test/java/javax/faces/component/

Author: martinkoci
Date: Thu Nov  4 14:39:49 2010
New Revision: 1031006

URL: http://svn.apache.org/viewvc?rev=1031006&view=rev
Log:
MYFACES-2920: UISelectOne/UISelectMany validateValue: Before comparing each option, coerce the option value type to the type of component's value 
https://issues.apache.org/jira/browse/MYFACES-2920

Added:
    myfaces/core/trunk/api/src/test/java/javax/faces/component/_SelectItemsUtilTest.java
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/_SelectItemsUtil.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=1031006&r1=1031005&r2=1031006&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 Thu Nov  4 14:39:49 2010
@@ -28,6 +28,7 @@ import java.util.Iterator;
 import javax.el.ValueExpression;
 import javax.faces.application.FacesMessage;
 import javax.faces.context.FacesContext;
+import javax.faces.convert.Converter;
 import javax.faces.convert.ConverterException;
 import javax.faces.el.ValueBinding;
 import javax.faces.model.SelectItem;
@@ -350,39 +351,22 @@ public class UISelectMany extends UIInpu
         {
             // all selected values must match to the values of the available options
 
-            _SelectItemsUtil._ValueConverter converter = new _SelectItemsUtil._ValueConverter()
-            {
-                public Object getConvertedValue(FacesContext context, String value)
-                {
-                    Object convertedValue = UISelectMany.this.getConvertedValue(context, new String[] { value });
-                    if (convertedValue instanceof Collection)
-                    {
-                        Iterator<?> iter = ((Collection<?>) convertedValue).iterator();
-                        if (iter.hasNext())
-                        {
-                            return iter.next();
-                        }
-                        return null;
-                    }
-                    return ((Object[]) convertedValue)[0];
-                }
-            };
-
             Collection<SelectItem> items = new ArrayList<SelectItem>();
             for (Iterator<SelectItem> iter = new _SelectItemsIterator(this, context); iter.hasNext();)
             {
                 items.add(iter.next());
             }
+            Converter converter = getConverter();
             while (itemValues.hasNext())
             {
                 Object itemValue = itemValues.next();
 
                 // 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, itemValue, items.iterator(), converter)
+                if (!_SelectItemsUtil.matchValue(context, this, itemValue, items.iterator(), converter)
                         || (
                             this.isRequired()
-                            && _SelectItemsUtil.isNoSelectionOption(context, itemValue, items.iterator(), converter)
+                            && _SelectItemsUtil.isNoSelectionOption(context, this, itemValue, items.iterator(), converter)
                         ))
                 {    
                     _MessageUtils.addErrorMessage(context, this, INVALID_MESSAGE_ID,

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=1031006&r1=1031005&r2=1031006&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 Thu Nov  4 14:39:49 2010
@@ -19,10 +19,10 @@
 package javax.faces.component;
 
 import javax.faces.context.FacesContext;
+import javax.faces.convert.Converter;
 
 import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFComponent;
 import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFJspProperty;
-import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFProperty;
 
 /**
  * Component for choosing one option out of a set of possibilities.
@@ -71,20 +71,13 @@ public class UISelectOne extends UIInput
             return;
         }
 
-        _SelectItemsUtil._ValueConverter converter = new _SelectItemsUtil._ValueConverter()
-        {
-            public Object getConvertedValue(FacesContext context, String value)
-            {
-                return UISelectOne.this.getConvertedValue(context, value);
-            }
-        };
-
         // 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, context), converter)
+        Converter converter = getConverter();
+        if (!(_SelectItemsUtil.matchValue(context, this, value, new _SelectItemsIterator(this, context), converter)
               && (!this.isRequired() 
                   || (this.isRequired() 
-                      && !_SelectItemsUtil.isNoSelectionOption(context, value, new _SelectItemsIterator(this, context), converter)))))
+                      && !_SelectItemsUtil.isNoSelectionOption(context, this, 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/_SelectItemsUtil.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/api/src/main/java/javax/faces/component/_SelectItemsUtil.java?rev=1031006&r1=1031005&r2=1031006&view=diff
==============================================================================
--- myfaces/core/trunk/api/src/main/java/javax/faces/component/_SelectItemsUtil.java (original)
+++ myfaces/core/trunk/api/src/main/java/javax/faces/component/_SelectItemsUtil.java Thu Nov  4 14:39:49 2010
@@ -22,6 +22,7 @@ import java.util.Arrays;
 import java.util.Iterator;
 
 import javax.faces.context.FacesContext;
+import javax.faces.convert.Converter;
 import javax.faces.model.SelectItem;
 import javax.faces.model.SelectItemGroup;
 
@@ -31,20 +32,18 @@ import javax.faces.model.SelectItemGroup
  */
 class _SelectItemsUtil
 {
-    static interface _ValueConverter
-    {
-        Object getConvertedValue(FacesContext context, String value);
-    }
-    
+
     /**
      * @param context the faces context
+     * @param uiComponent the component instance
      * @param value the value to check
-     * @param converter 
+     * @param converter a converter instance
      * @param iterator contains instances of SelectItem
      * @return if the value of a selectitem is equal to the given value
      */
-    public static boolean matchValue(FacesContext context, Object value,
-                    Iterator<SelectItem> selectItemsIter, _ValueConverter converter)
+    public static boolean matchValue(FacesContext context,
+            UIComponent uiComponent, Object value,
+            Iterator<SelectItem> selectItemsIter, Converter converter)
     {
         while (selectItemsIter.hasNext())
         {
@@ -54,38 +53,37 @@ class _SelectItemsUtil
                 SelectItemGroup itemgroup = (SelectItemGroup) item;
                 SelectItem[] selectItems = itemgroup.getSelectItems();
                 if (selectItems != null
-                                && selectItems.length > 0
-                                && matchValue(context, value, Arrays.asList(
-                                                selectItems).iterator(), converter))
+                        && selectItems.length > 0
+                        && matchValue(context, uiComponent, value, Arrays
+                                .asList(selectItems).iterator(), converter))
                 {
                     return true;
                 }
             }
             else
             {
-                Object itemValue = item.getValue();
-                if(converter != null && itemValue instanceof String)
-                {
-                    itemValue = converter.getConvertedValue(context, (String)itemValue);
-                }
-                if (value==itemValue || value.equals(itemValue))
+                Object itemValue = _convertOrCoerceValue(context,
+                        uiComponent, value, item, converter);
+                if (value == itemValue || value.equals(itemValue))
                 {
                     return true;
                 }
             }
         }
         return false;
-    }  
-    
+    }
+
     /**
      * @param context the faces context
+     * @param uiComponent the component instance
      * @param value the value to check
      * @param converter 
      * @param iterator contains instances of SelectItem
      * @return if the value is a SelectItem of selectItemsIter, on which noSelectionOption is true
      */
-    public static boolean isNoSelectionOption(FacesContext context, Object value,
-            Iterator<SelectItem> selectItemsIter, _ValueConverter converter)
+    public static boolean isNoSelectionOption(FacesContext context,
+            UIComponent uiComponent, Object value,
+            Iterator<SelectItem> selectItemsIter, Converter converter)
     {
         while (selectItemsIter.hasNext())
         {
@@ -95,26 +93,46 @@ class _SelectItemsUtil
                 SelectItemGroup itemgroup = (SelectItemGroup) item;
                 SelectItem[] selectItems = itemgroup.getSelectItems();
                 if (selectItems != null
-                                && selectItems.length > 0
-                                && isNoSelectionOption(context, value, Arrays.asList(
-                                                selectItems).iterator(), converter))
+                        && selectItems.length > 0
+                        && isNoSelectionOption(context, uiComponent, value,
+                                Arrays.asList(selectItems).iterator(),
+                                converter))
                 {
                     return true;
                 }
             }
-            else if(item.isNoSelectionOption())
+            else if (item.isNoSelectionOption())
             {
-                Object itemValue = item.getValue();
-                if(converter != null && itemValue instanceof String)
-                {
-                    itemValue = converter.getConvertedValue(context, (String)itemValue);
-                }
-                if (value==itemValue || value.equals(itemValue))
+                Object itemValue = _convertOrCoerceValue(context, uiComponent,
+                        value, item, converter);
+                if (value == itemValue || value.equals(itemValue))
                 {
                     return true;
                 }
             }
         }
         return false;
+    }
+
+    /**
+     * If converter is available and selectItem.value is String uses getAsObject,
+     * otherwise uses EL type coertion and return result.
+     */
+    private static Object _convertOrCoerceValue(FacesContext facesContext,
+            UIComponent uiComponent, Object value, SelectItem selectItem,
+            Converter converter)
+    {
+        Object itemValue = selectItem.getValue();
+        if (converter != null && itemValue instanceof String)
+        {
+            itemValue = converter.getAsObject(facesContext, uiComponent,
+                    (String) itemValue);
+        }
+        else
+        {
+            itemValue = _ClassUtils.convertToType(itemValue, value.getClass());
         }
+        return itemValue;
     }
+
+}

Added: myfaces/core/trunk/api/src/test/java/javax/faces/component/_SelectItemsUtilTest.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/api/src/test/java/javax/faces/component/_SelectItemsUtilTest.java?rev=1031006&view=auto
==============================================================================
--- myfaces/core/trunk/api/src/test/java/javax/faces/component/_SelectItemsUtilTest.java (added)
+++ myfaces/core/trunk/api/src/test/java/javax/faces/component/_SelectItemsUtilTest.java Thu Nov  4 14:39:49 2010
@@ -0,0 +1,136 @@
+/*
+ * 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 static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import org.apache.myfaces.test.base.junit4.AbstractJsfTestCase;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+
+/**
+ * 
+ * @author martinkoci
+ */
+public class _SelectItemsUtilTest extends AbstractJsfTestCase
+{
+
+    private static final String NO_SELECTION_ITEM_VALUE = "1.0";
+    private UISelectOne uiComponent;
+    private Float value;
+    private _SelectItemsIterator iterator;
+    private UISelectItem noSelectionOption;
+    private UISelectItem selectItem1;
+    private UISelectItem selectItem2;
+    private UISelectItem selectItem3;
+
+    @Before
+    public void setUp() throws Exception
+    {
+        super.setUp();
+        
+        uiComponent = new UISelectOne();
+        
+        value = Float.valueOf("1.2");
+
+        noSelectionOption = new UISelectItem();
+        noSelectionOption.setNoSelectionOption(true);
+        noSelectionOption.setItemValue(NO_SELECTION_ITEM_VALUE);
+        uiComponent.getChildren().add(noSelectionOption);
+        
+        selectItem1 = new UISelectItem();
+        selectItem1.setItemValue("1.1");
+        uiComponent.getChildren().add(selectItem1);
+        selectItem2 = new UISelectItem();
+        selectItem2.setItemValue("1.2");
+        uiComponent.getChildren().add(selectItem2);
+        selectItem3 = new UISelectItem();
+        selectItem3.setItemValue("1.3");
+        uiComponent.getChildren().add(selectItem3);
+        
+        iterator = new _SelectItemsIterator(uiComponent, facesContext);
+    }
+
+    @After
+    public void tearDown() throws Exception
+    {
+        super.tearDown();
+        uiComponent = null;
+        value = null;
+        iterator = null;
+        noSelectionOption = null;
+        selectItem1 = null;
+        selectItem2 = null;
+        selectItem3 = null;
+    }
+
+    @Test
+    public void testMatchValue()
+    {
+        
+        boolean matchValue = _SelectItemsUtil.matchValue(facesContext, uiComponent, value, iterator, null);
+        
+        assertTrue("Value Float 1.2 must match SelectItem.value \"1.2\" (type of String)", matchValue);
+        
+        Float valueNotInSelectItems = Float.valueOf("2.0");
+        matchValue = _SelectItemsUtil.matchValue(facesContext, uiComponent, valueNotInSelectItems, iterator, null);
+        assertFalse(matchValue);
+    }
+    
+    @Test @Ignore // TODO martinkoci remove @Ignore after myfaces-test 1.0.1 release 
+    public void testMatchValueWithEnums() throws Exception
+    {
+        noSelectionOption.setItemValue("NONE");
+        selectItem1.setItemValue("ONE");
+        selectItem2.setItemValue("TWO");
+        selectItem3.setItemValue("THREE");
+        iterator = new _SelectItemsIterator(uiComponent, facesContext);
+        
+        Object enumValue = MockEnum.THREE;
+        boolean matchValue = _SelectItemsUtil.matchValue(facesContext, uiComponent, enumValue, iterator, null);
+        
+        assertTrue("Value Enum THREE must match SelectItem.value \"THREE\" (type of String)", matchValue);
+        
+        enumValue = MockEnum.FOUR;
+        matchValue = _SelectItemsUtil.matchValue(facesContext, uiComponent, enumValue, iterator, null);
+        assertFalse(matchValue);
+    }
+    
+    
+    private static enum MockEnum {
+        NONE, ONE,TWO, THREE, FOUR
+    }
+
+    @Test
+    public void testIsNoSelectionOption()
+    {
+        Float value = Float.parseFloat(NO_SELECTION_ITEM_VALUE);
+        boolean noSelectionOption = _SelectItemsUtil.isNoSelectionOption(facesContext, uiComponent, value, iterator, null);
+        assertTrue(noSelectionOption);
+        
+        Float valueNotInSelectItems = Float.valueOf("2.0");
+        noSelectionOption = _SelectItemsUtil.isNoSelectionOption(facesContext, uiComponent, valueNotInSelectItems, iterator, null);
+        assertFalse(noSelectionOption);
+        
+    }
+
+}