You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by gp...@apache.org on 2009/03/01 22:57:03 UTC

svn commit: r749124 - in /myfaces/extensions/validator/branches/branch_for_jsf_1_1: core/src/main/java/org/apache/myfaces/extensions/validator/core/el/ validation-modules/property-validation/src/test/java/org/apache/myfaces/extensions/validator/test/el/

Author: gpetracek
Date: Sun Mar  1 21:57:03 2009
New Revision: 749124

URL: http://svn.apache.org/viewvc?rev=749124&view=rev
Log:
EXTVAL-37: support for dynamic map el-syntax with custom facelets components

Added:
    myfaces/extensions/validator/branches/branch_for_jsf_1_1/validation-modules/property-validation/src/test/java/org/apache/myfaces/extensions/validator/test/el/
    myfaces/extensions/validator/branches/branch_for_jsf_1_1/validation-modules/property-validation/src/test/java/org/apache/myfaces/extensions/validator/test/el/ValueBindingExpressionTestCase.java
Modified:
    myfaces/extensions/validator/branches/branch_for_jsf_1_1/core/src/main/java/org/apache/myfaces/extensions/validator/core/el/DefaultELHelper.java
    myfaces/extensions/validator/branches/branch_for_jsf_1_1/core/src/main/java/org/apache/myfaces/extensions/validator/core/el/FaceletsTaglibExpressionHelper.java
    myfaces/extensions/validator/branches/branch_for_jsf_1_1/core/src/main/java/org/apache/myfaces/extensions/validator/core/el/ValueBindingExpression.java

Modified: myfaces/extensions/validator/branches/branch_for_jsf_1_1/core/src/main/java/org/apache/myfaces/extensions/validator/core/el/DefaultELHelper.java
URL: http://svn.apache.org/viewvc/myfaces/extensions/validator/branches/branch_for_jsf_1_1/core/src/main/java/org/apache/myfaces/extensions/validator/core/el/DefaultELHelper.java?rev=749124&r1=749123&r2=749124&view=diff
==============================================================================
--- myfaces/extensions/validator/branches/branch_for_jsf_1_1/core/src/main/java/org/apache/myfaces/extensions/validator/core/el/DefaultELHelper.java (original)
+++ myfaces/extensions/validator/branches/branch_for_jsf_1_1/core/src/main/java/org/apache/myfaces/extensions/validator/core/el/DefaultELHelper.java Sun Mar  1 21:57:03 2009
@@ -20,7 +20,10 @@
 
 import org.apache.myfaces.extensions.validator.internal.UsageInformation;
 import org.apache.myfaces.extensions.validator.internal.UsageCategory;
+import org.apache.myfaces.extensions.validator.internal.ToDo;
+import org.apache.myfaces.extensions.validator.internal.Priority;
 import org.apache.myfaces.extensions.validator.util.ExtValUtils;
+import org.apache.myfaces.extensions.validator.util.ReflectionUtils;
 import org.apache.myfaces.extensions.validator.core.property.PropertyDetails;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
@@ -29,6 +32,8 @@
 import javax.faces.context.FacesContext;
 import javax.faces.el.ValueBinding;
 import java.io.Externalizable;
+import java.lang.reflect.Method;
+import java.util.Map;
 
 /**
  * in order to centralize the jsf version dependency within the core
@@ -133,8 +138,10 @@
         return new ValueBindingExpression(valueBindingExpression);
     }
 
+    //keep in sync with DefaultELHelper#getPropertyDetailsViaReflectionFallback of trunk!!!
     public PropertyDetails getPropertyDetailsOfValueBinding(UIComponent uiComponent)
     {
+        FacesContext facesContext = FacesContext.getCurrentInstance();
         ValueBindingExpression valueBindingExpression = getValueBindingExpression(uiComponent, false);
         ValueBindingExpression currentValueBindingExpression =
             new ValueBindingExpression(valueBindingExpression.getExpressionString());
@@ -145,11 +152,11 @@
         {
             if(path == null)
             {
-                path = currentValueBindingExpression.getProperty();
+                path = getPropertyName(currentValueBindingExpression);
             }
             else
             {
-                path = currentValueBindingExpression.getProperty() + "." + path;
+                path = getPropertyName(currentValueBindingExpression) + "." + path;
             }
 
             currentValueBindingExpression = currentValueBindingExpression.getBaseExpression();
@@ -157,9 +164,67 @@
 
         path = currentValueBindingExpression.getProperty() + "." + path;
 
-        Object baseObject = getValueOfExpression(
-                FacesContext.getCurrentInstance(), valueBindingExpression.getBaseExpression());
-        return new PropertyDetails(path, baseObject, valueBindingExpression.getProperty());
+        Object baseObject = getValueOfExpression(facesContext, valueBindingExpression.getBaseExpression());
+
+        //in case of e.g.: #{bean[bean.passwordRepeatedPropertyName]}
+        //-> bean.passwordRepeatedPropertyName is not the final property name
+        return new PropertyDetails(path, baseObject, getPropertyName(valueBindingExpression));
+    }
+
+    private String getPropertyName(ValueBindingExpression valueBindingExpression)
+    {
+        String propertyName = valueBindingExpression.getProperty();
+
+        if(propertyName.contains("."))
+        {
+            propertyName = extractPropertyNameOfPropertyPath(propertyName);
+        }
+
+        return propertyName;
+    }
+
+    @ToDo(value = Priority.MEDIUM, description = "support for more dynamic bindings - details see inline")
+    private String extractPropertyNameOfPropertyPath(String propertyChain)
+    {
+        String[] properties = propertyChain.split("\\.");
+
+        Object currentPropertyValue = ExtValUtils.getELHelper().getBean(properties[0]);
+
+        Method currentMethod;
+        String currentPropertyName;
+        for(int i = 1; i < properties.length; i++)
+        {
+            currentPropertyName = properties[i];
+            currentMethod = ReflectionUtils.tryToGetMethod(currentPropertyValue.getClass(),
+                "get" + currentPropertyName.substring(0, 1).toUpperCase() + currentPropertyName.substring(1));
+
+            if(currentMethod == null && currentPropertyValue instanceof Map)
+            {
+                //it's ok for the simple map case - but not for e.g.:
+                //#{bean1[bean2.propertyNameProvider[ bean3.index]]}
+                //or every other complex replacement for bean3.index
+                //it might also require an adjustment at FaceletsTaglibExpressionHelper#tryToTransformToRealBinding
+                ((Map)currentPropertyValue).get(currentPropertyName);
+            }
+            else
+            {
+                currentPropertyValue = ReflectionUtils.tryToInvokeMethod(currentPropertyValue, currentMethod);
+            }
+        }
+
+        if(currentPropertyValue instanceof String)
+        {
+            return (String)currentPropertyValue;
+        }
+        else
+        {
+            if(this.logger.isErrorEnabled())
+            {
+                this.logger.error("unexpected value within map syntax: " + propertyChain +
+                        " last property name: " + currentPropertyValue);
+            }
+            return null;
+        }
     }
 
     static String getOriginalValueBindingExpression(UIComponent uiComponent)

Modified: myfaces/extensions/validator/branches/branch_for_jsf_1_1/core/src/main/java/org/apache/myfaces/extensions/validator/core/el/FaceletsTaglibExpressionHelper.java
URL: http://svn.apache.org/viewvc/myfaces/extensions/validator/branches/branch_for_jsf_1_1/core/src/main/java/org/apache/myfaces/extensions/validator/core/el/FaceletsTaglibExpressionHelper.java?rev=749124&r1=749123&r2=749124&view=diff
==============================================================================
--- myfaces/extensions/validator/branches/branch_for_jsf_1_1/core/src/main/java/org/apache/myfaces/extensions/validator/core/el/FaceletsTaglibExpressionHelper.java (original)
+++ myfaces/extensions/validator/branches/branch_for_jsf_1_1/core/src/main/java/org/apache/myfaces/extensions/validator/core/el/FaceletsTaglibExpressionHelper.java Sun Mar  1 21:57:03 2009
@@ -135,10 +135,11 @@
         String originalBinding = addedVirtualNames.get("value");
         originalBinding = originalBinding.substring(originalBinding.indexOf("{") + 1, originalBinding.indexOf("}"));
         addedVirtualNames.remove("value");
-        return tryToTransformToRealBinding(originalBinding, addedVirtualNames);
+        return tryToTransformToRealBinding(originalBinding, addedVirtualNames, virtualVars);
     }
 
-    private static String tryToTransformToRealBinding(String originalBinding, Map<String, String> addedVirtualNames)
+    private static String tryToTransformToRealBinding(
+            String originalBinding, Map<String, String> addedVirtualNames, Map<String, String> virtualVars)
     {
         originalBinding = "#{" + originalBinding + "}";
         Iterator nameIterator = addedVirtualNames.keySet().iterator();
@@ -148,12 +149,44 @@
         while(nameIterator.hasNext())
         {
             currentKey = (String) nameIterator.next();
-            currentValue = addedVirtualNames.get(currentKey);
 
+            currentValue = addedVirtualNames.get(currentKey);
             currentValue = currentValue.substring(currentValue.indexOf("{") + 1, currentValue.indexOf("}"));
+
             originalBinding = originalBinding.replace("{" + currentKey + ".", "{" + currentValue + ".");
+            //dynamic base and property
+            originalBinding = originalBinding.replace("{" + currentKey + "[", "{" + currentValue + "[");
+
             originalBinding = originalBinding.replace("." + currentKey + ".", "." + currentValue + ".");
-            originalBinding = originalBinding.replace("[" + currentKey + "]", "[" + currentValue + "]");
+            //dynamic base and property
+            originalBinding = originalBinding.replace("." + currentKey + "[", "." + currentValue + "[");
+
+            originalBinding = originalBinding.replace("[" + currentKey + "]", "['" + currentValue + "']");
+            //dynamic base and property
+            originalBinding = originalBinding.replace("[" + currentKey + "[", "[" + currentValue + "[");
+            originalBinding = originalBinding.replace("[" + currentKey + ".", "[" + currentValue + ".");
+        }
+
+        nameIterator = virtualVars.keySet().iterator();
+
+        while(nameIterator.hasNext())
+        {
+            currentKey = (String) nameIterator.next();
+
+            currentValue = virtualVars.get(currentKey);
+
+            originalBinding = originalBinding.replace("{" + currentKey + ".", "{" + currentValue + ".");
+            //dynamic base and property
+            originalBinding = originalBinding.replace("{" + currentKey + "[", "{" + currentValue + "[");
+
+            originalBinding = originalBinding.replace("." + currentKey + ".", "." + currentValue + ".");
+            //dynamic base and property
+            originalBinding = originalBinding.replace("." + currentKey + "[", "." + currentValue + "[");
+
+            originalBinding = originalBinding.replace("[" + currentKey + "]", "['" + currentValue + "']");
+            //dynamic base and property
+            originalBinding = originalBinding.replace("[" + currentKey + "[", "[" + currentValue + "[");
+            originalBinding = originalBinding.replace("[" + currentKey + ".", "[" + currentValue + ".");
         }
 
         return originalBinding.substring(2, originalBinding.length() - 1);

Modified: myfaces/extensions/validator/branches/branch_for_jsf_1_1/core/src/main/java/org/apache/myfaces/extensions/validator/core/el/ValueBindingExpression.java
URL: http://svn.apache.org/viewvc/myfaces/extensions/validator/branches/branch_for_jsf_1_1/core/src/main/java/org/apache/myfaces/extensions/validator/core/el/ValueBindingExpression.java?rev=749124&r1=749123&r2=749124&view=diff
==============================================================================
--- myfaces/extensions/validator/branches/branch_for_jsf_1_1/core/src/main/java/org/apache/myfaces/extensions/validator/core/el/ValueBindingExpression.java (original)
+++ myfaces/extensions/validator/branches/branch_for_jsf_1_1/core/src/main/java/org/apache/myfaces/extensions/validator/core/el/ValueBindingExpression.java Sun Mar  1 21:57:03 2009
@@ -53,6 +53,7 @@
     public static ValueBindingExpression replaceProperty(ValueBindingExpression valueBindingExpression,
                                                          String newProperty)
     {
+        //TODO adjustments for isDynamicBaseAndProperty
         if(valueBindingExpression.getProperty().endsWith("']"))
         {
             valueBindingExpression = valueBindingExpression.getBaseExpression();
@@ -73,6 +74,7 @@
         String sourceExpression = valueBindingExpression.getExpressionString();
         String result = sourceExpression.substring(0, sourceExpression.length() - 1);
 
+        //TODO adjustments for isDynamicBaseAndProperty
         if(newProperty.startsWith("['"))
         {
             return new ValueBindingExpression(result + newProperty + "}");
@@ -90,7 +92,8 @@
             throw new IllegalStateException(expression + " is no valid el-expression");
         }
 
-        int index1 = expression.lastIndexOf("']");
+        boolean isDynamicBaseAndProperty = expression.lastIndexOf("']") == -1;
+        int index1 = isDynamicBaseAndProperty ? expression.lastIndexOf("]") : expression.lastIndexOf("']");
         int index2 = expression.lastIndexOf(".");
 
         if(index1 > index2)
@@ -98,9 +101,18 @@
             expression = expression.substring(0, index1);
 
             int index3 = findIndexOfStartingBracket(expression);
-            this.value = expression.substring(index3 + 2, index1);
+            if(isDynamicBaseAndProperty)
+            {
+                this.value = expression.substring(index3 + 1, index1);
+
+            }
+            else
+            {
+                this.value = expression.substring(index3 + 2, index1);
+            }
+
             this.base = new ValueBindingExpression(expression.substring(0, index3) + "}");
-            this.token = "['";
+            this.token = isDynamicBaseAndProperty ? "[" : "['";
         }
         else if( index2 > index1)
         {
@@ -125,7 +137,7 @@
             {
                 return this.value.substring(1, this.value.length() - 1);
             }
-            return this.base.value + this.token + this.value.substring(0, this.value.length()) + "']";
+            //return this.base.value + this.token + this.value.substring(0, this.value.length()) + "']";
         }
         return value;
     }
@@ -145,6 +157,10 @@
             {
                 return baseExpression.substring(0, baseExpression.length() - 1) + this.token + this.value + "']}";
             }
+            else if("[".equals(this.token))
+            {
+                return baseExpression.substring(0, baseExpression.length() - 1) + this.token + this.value + "]}";
+            }
             return baseExpression.substring(0, baseExpression.length() - 1) + this.token + this.value + "}";
         }
         else

Added: myfaces/extensions/validator/branches/branch_for_jsf_1_1/validation-modules/property-validation/src/test/java/org/apache/myfaces/extensions/validator/test/el/ValueBindingExpressionTestCase.java
URL: http://svn.apache.org/viewvc/myfaces/extensions/validator/branches/branch_for_jsf_1_1/validation-modules/property-validation/src/test/java/org/apache/myfaces/extensions/validator/test/el/ValueBindingExpressionTestCase.java?rev=749124&view=auto
==============================================================================
--- myfaces/extensions/validator/branches/branch_for_jsf_1_1/validation-modules/property-validation/src/test/java/org/apache/myfaces/extensions/validator/test/el/ValueBindingExpressionTestCase.java (added)
+++ myfaces/extensions/validator/branches/branch_for_jsf_1_1/validation-modules/property-validation/src/test/java/org/apache/myfaces/extensions/validator/test/el/ValueBindingExpressionTestCase.java Sun Mar  1 21:57:03 2009
@@ -0,0 +1,165 @@
+/*
+ * 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 org.apache.myfaces.extensions.validator.test.el;
+
+import org.apache.myfaces.extensions.validator.test.AbstractExValViewControllerTestCase;
+import org.apache.myfaces.extensions.validator.core.el.ValueBindingExpression;
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+/**
+ * @author Gerhard Petracek
+ * @since 1.x.2
+ */
+public class ValueBindingExpressionTestCase extends AbstractExValViewControllerTestCase
+{
+    public ValueBindingExpressionTestCase(String name)
+    {
+        super(name);
+    }
+
+    public static Test suite()
+    {
+        return new TestSuite(ValueBindingExpressionTestCase.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception
+    {
+        super.setUp();
+    }
+
+    @Override
+    protected void tearDown() throws Exception
+    {
+        super.tearDown();
+    }
+
+    public void testStandardSyntax() throws Exception
+    {
+        ValueBindingExpression valueBindingExpression = new ValueBindingExpression("#{bean1.property1}");
+
+        assertEquals(valueBindingExpression.getExpressionString(), "#{bean1.property1}");
+        assertEquals(valueBindingExpression.getBaseExpression().getExpressionString(), "#{bean1}");
+        assertEquals(valueBindingExpression.getProperty(), "property1");
+
+        valueBindingExpression = new ValueBindingExpression("#{bean1['property1']}");
+
+        assertEquals(valueBindingExpression.getExpressionString(), "#{bean1['property1']}");
+        assertEquals(valueBindingExpression.getBaseExpression().getExpressionString(), "#{bean1}");
+        assertEquals(valueBindingExpression.getProperty(), "property1");
+
+        valueBindingExpression = new ValueBindingExpression("#{bean1['bean2'].property1}");
+
+        assertEquals(valueBindingExpression.getExpressionString(), "#{bean1['bean2'].property1}");
+        assertEquals(valueBindingExpression.getBaseExpression().getExpressionString(), "#{bean1['bean2']}");
+        assertEquals(valueBindingExpression.getBaseExpression().getBaseExpression().getExpressionString(), "#{bean1}");
+        assertEquals(valueBindingExpression.getProperty(), "property1");
+    }
+
+    public void testStandardSyntaxReplaceProperty() throws Exception
+    {
+        ValueBindingExpression valueBindingExpression = new ValueBindingExpression("#{bean1.property1}");
+
+        valueBindingExpression = ValueBindingExpression.replaceProperty(valueBindingExpression, "property2");
+
+        assertEquals(valueBindingExpression.getExpressionString(), "#{bean1.property2}");
+        assertEquals(valueBindingExpression.getBaseExpression().getExpressionString(), "#{bean1}");
+        assertEquals(valueBindingExpression.getProperty(), "property2");
+
+        valueBindingExpression = new ValueBindingExpression("#{bean1['property1']}");
+
+        valueBindingExpression = ValueBindingExpression.replaceProperty(valueBindingExpression, "property2");
+
+        //TODO restore original syntax
+        assertEquals(valueBindingExpression.getExpressionString(), "#{bean1.property2}");
+        assertEquals(valueBindingExpression.getBaseExpression().getExpressionString(), "#{bean1}");
+        assertEquals(valueBindingExpression.getProperty(), "property2");
+
+        valueBindingExpression = new ValueBindingExpression("#{bean1['bean2'].property1}");
+
+        valueBindingExpression = ValueBindingExpression.replaceProperty(valueBindingExpression, "property2");
+
+        assertEquals(valueBindingExpression.getExpressionString(), "#{bean1['bean2'].property2}");
+        assertEquals(valueBindingExpression.getBaseExpression().getExpressionString(), "#{bean1['bean2']}");
+        assertEquals(valueBindingExpression.getBaseExpression().getBaseExpression().getExpressionString(), "#{bean1}");
+        assertEquals(valueBindingExpression.getProperty(), "property2");
+    }
+
+    public void testStandardSyntaxAddProperty() throws Exception
+    {
+        ValueBindingExpression valueBindingExpression = new ValueBindingExpression("#{bean1.bean2}");
+
+        valueBindingExpression = ValueBindingExpression.addProperty(valueBindingExpression, "property1");
+
+        assertEquals(valueBindingExpression.getExpressionString(), "#{bean1.bean2.property1}");
+        assertEquals(valueBindingExpression.getBaseExpression().getExpressionString(), "#{bean1.bean2}");
+        assertEquals(valueBindingExpression.getProperty(), "property1");
+
+        valueBindingExpression = new ValueBindingExpression("#{bean1['bean2']}");
+
+        valueBindingExpression = ValueBindingExpression.addProperty(valueBindingExpression, "property1");
+
+        assertEquals(valueBindingExpression.getExpressionString(), "#{bean1['bean2'].property1}");
+        assertEquals(valueBindingExpression.getBaseExpression().getExpressionString(), "#{bean1['bean2']}");
+        assertEquals(valueBindingExpression.getProperty(), "property1");
+
+        valueBindingExpression = new ValueBindingExpression("#{bean1['bean2'].bean3}");
+
+        valueBindingExpression = ValueBindingExpression.addProperty(valueBindingExpression, "property1");
+
+        assertEquals(valueBindingExpression.getExpressionString(), "#{bean1['bean2'].bean3.property1}");
+        assertEquals(valueBindingExpression.getBaseExpression().getExpressionString(), "#{bean1['bean2'].bean3}");
+        assertEquals(valueBindingExpression
+                .getBaseExpression().getBaseExpression().getExpressionString(), "#{bean1['bean2']}");
+        assertEquals(valueBindingExpression.getProperty(), "property1");
+    }
+
+    public void testFaceletsCustomComponentSyntax() throws Exception
+    {
+        ValueBindingExpression valueBindingExpression = new ValueBindingExpression("#{entity[fieldName]}");
+
+        assertEquals(valueBindingExpression.getExpressionString(), "#{entity[fieldName]}");
+        assertEquals(valueBindingExpression.getBaseExpression().getExpressionString(), "#{entity}");
+        assertEquals(valueBindingExpression.getProperty(), "fieldName");
+    }
+
+    public void testFaceletsCustomComponentSyntaxReplaceProperty() throws Exception
+    {
+        ValueBindingExpression valueBindingExpression = new ValueBindingExpression("#{entity[fieldName]}");
+
+        valueBindingExpression = ValueBindingExpression.replaceProperty(valueBindingExpression, "newFieldName");
+
+        //TODO restore original syntax
+        assertEquals(valueBindingExpression.getExpressionString(), "#{entity.newFieldName}");
+        assertEquals(valueBindingExpression.getBaseExpression().getExpressionString(), "#{entity}");
+        assertEquals(valueBindingExpression.getProperty(), "newFieldName");
+    }
+
+    public void testComplexMapSyntax() throws Exception
+    {
+        ValueBindingExpression valueBindingExpression
+                = new ValueBindingExpression("#{bean1[bean2[bean3['key1']]].property1}");
+
+        //TODO
+        //assertEquals(valueBindingExpression.getExpressionString(), "#{bean1[bean2[bean3['key1']]].property1}");
+        assertEquals(valueBindingExpression.getProperty(), "property1");
+    }
+
+}