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 2011/08/16 00:34:19 UTC

svn commit: r1158047 - in /myfaces/core/branches/2.0.x/impl/src: main/java/org/apache/myfaces/view/facelets/ main/java/org/apache/myfaces/view/facelets/tag/composite/ main/java/org/apache/myfaces/view/facelets/tag/jsf/ test/java/org/apache/myfaces/view...

Author: lu4242
Date: Mon Aug 15 22:34:19 2011
New Revision: 1158047

URL: http://svn.apache.org/viewvc?rev=1158047&view=rev
Log:
MYFACES-3281 cc:attribute "targets" and cc attached object "targets" should follow strictly the spec

Added:
    myfaces/core/branches/2.0.x/impl/src/test/java/org/apache/myfaces/view/facelets/tag/composite/CompositeComponentConditionalButtonTestCase.java
    myfaces/core/branches/2.0.x/impl/src/test/resources/org/apache/myfaces/view/facelets/tag/composite/resources/testComposite/simpleConditionalButtonTargets.xhtml
    myfaces/core/branches/2.0.x/impl/src/test/resources/org/apache/myfaces/view/facelets/tag/composite/testConditionalButtonTargets.xhtml
Modified:
    myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/view/facelets/FaceletViewDeclarationLanguage.java
    myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/view/facelets/tag/composite/AttachedObjectTargetImpl.java
    myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/view/facelets/tag/jsf/ComponentSupport.java

Modified: myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/view/facelets/FaceletViewDeclarationLanguage.java
URL: http://svn.apache.org/viewvc/myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/view/facelets/FaceletViewDeclarationLanguage.java?rev=1158047&r1=1158046&r2=1158047&view=diff
==============================================================================
--- myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/view/facelets/FaceletViewDeclarationLanguage.java (original)
+++ myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/view/facelets/FaceletViewDeclarationLanguage.java Mon Aug 15 22:34:19 2011
@@ -113,6 +113,7 @@ import org.apache.myfaces.view.facelets.
 import org.apache.myfaces.view.facelets.tag.composite.ClientBehaviorRedirectEventComponentWrapper;
 import org.apache.myfaces.view.facelets.tag.composite.CompositeLibrary;
 import org.apache.myfaces.view.facelets.tag.composite.CompositeResourceLibrary;
+import org.apache.myfaces.view.facelets.tag.jsf.ComponentSupport;
 import org.apache.myfaces.view.facelets.tag.jsf.core.AjaxHandler;
 import org.apache.myfaces.view.facelets.tag.jsf.core.CoreLibrary;
 import org.apache.myfaces.view.facelets.tag.jsf.html.HtmlLibrary;
@@ -973,10 +974,12 @@ public class FaceletViewDeclarationLangu
                             }
                             // Otherwise keep the current ValueExpression, because it will be used chain other value expressions
                         }
+                        
+                        UIComponent topLevelComponentBase = topLevelComponent.getFacet(UIComponent.COMPOSITE_FACET_NAME);
 
                         for (String target : targetsArray)
                         {
-                            UIComponent innerComponent = topLevelComponent.findComponent(target);
+                            UIComponent innerComponent = ComponentSupport.findComponentChildOrFacetFrom(context, topLevelComponentBase, target);
                             
                             if (innerComponent == null)
                             {
@@ -1122,9 +1125,11 @@ public class FaceletViewDeclarationLangu
                         
                         methodExpression = reWrapMethodExpression(methodExpression, attributeNameValueExpression);
     
+                        UIComponent topLevelComponentBase = topLevelComponent.getFacet(UIComponent.COMPOSITE_FACET_NAME);
+                        
                         for (String target : targetsArray)
                         {
-                            UIComponent innerComponent = topLevelComponent.findComponent(target);
+                            UIComponent innerComponent = ComponentSupport.findComponentChildOrFacetFrom(context, topLevelComponentBase, target);
                             
                             if (innerComponent == null)
                             {

Modified: myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/view/facelets/tag/composite/AttachedObjectTargetImpl.java
URL: http://svn.apache.org/viewvc/myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/view/facelets/tag/composite/AttachedObjectTargetImpl.java?rev=1158047&r1=1158046&r2=1158047&view=diff
==============================================================================
--- myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/view/facelets/tag/composite/AttachedObjectTargetImpl.java (original)
+++ myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/view/facelets/tag/composite/AttachedObjectTargetImpl.java Mon Aug 15 22:34:19 2011
@@ -25,10 +25,12 @@ import java.util.List;
 
 import javax.el.ValueExpression;
 import javax.faces.component.UIComponent;
+import javax.faces.component.UINamingContainer;
 import javax.faces.context.FacesContext;
 import javax.faces.view.AttachedObjectTarget;
 
 import org.apache.myfaces.shared.util.StringUtils;
+import org.apache.myfaces.view.facelets.tag.jsf.ComponentSupport;
 
 /**
  * 
@@ -67,9 +69,24 @@ public class AttachedObjectTargetImpl im
         if (targetsArray.length > 0)
         {
             List<UIComponent> targetsList = new ArrayList<UIComponent>(targetsArray.length);
+            final char separatorChar = UINamingContainer.getSeparatorChar(facesContext);
+            UIComponent facetBase = topLevelComponent.getFacet(UIComponent.COMPOSITE_FACET_NAME);
             for (String target : targetsArray)
             {
-                UIComponent innerComponent = topLevelComponent.findComponent(target);
+                //UIComponent innerComponent = topLevelComponent.findComponent(
+                //        topLevelComponent.getId() + UINamingContainer.getSeparatorChar(facesContext) + target);
+                int separator = target.indexOf(separatorChar);
+                UIComponent innerComponent = null;
+                if (separator == -1)
+                {
+                    innerComponent = ComponentSupport.findComponentChildOrFacetFrom(
+                            facetBase, target, null);
+                }
+                else
+                {
+                    innerComponent = ComponentSupport.findComponentChildOrFacetFrom(
+                            facetBase, target.substring(0,separator), target);
+                }
                 
                 if (innerComponent != null)
                 {
@@ -87,7 +104,11 @@ public class AttachedObjectTargetImpl im
             String name = getName();
             if (name != null)
             {
-                UIComponent innerComponent = topLevelComponent.findComponent(getName());
+                //UIComponent innerComponent = topLevelComponent.findComponent(
+                //        topLevelComponent.getId() + UINamingContainer.getSeparatorChar(facesContext) + getName());
+                UIComponent innerComponent = ComponentSupport.findComponentChildOrFacetFrom(
+                        topLevelComponent.getFacet(UIComponent.COMPOSITE_FACET_NAME),
+                        name, null);
                 if (innerComponent != null)
                 {
                     List<UIComponent> targetsList = new ArrayList<UIComponent>(1);

Modified: myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/view/facelets/tag/jsf/ComponentSupport.java
URL: http://svn.apache.org/viewvc/myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/view/facelets/tag/jsf/ComponentSupport.java?rev=1158047&r1=1158046&r2=1158047&view=diff
==============================================================================
--- myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/view/facelets/tag/jsf/ComponentSupport.java (original)
+++ myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/view/facelets/tag/jsf/ComponentSupport.java Mon Aug 15 22:34:19 2011
@@ -25,7 +25,9 @@ import java.util.Locale;
 import java.util.Map;
 
 import javax.faces.FacesException;
+import javax.faces.component.NamingContainer;
 import javax.faces.component.UIComponent;
+import javax.faces.component.UINamingContainer;
 import javax.faces.component.UIPanel;
 import javax.faces.component.UIViewRoot;
 import javax.faces.context.FacesContext;
@@ -109,10 +111,12 @@ public final class ComponentSupport
      */
     public static UIComponent findChild(UIComponent parent, String id)
     {
-        if (parent.getChildCount() > 0)
+        int childCount = parent.getChildCount();
+        if (childCount > 0)
         {
-            for (UIComponent child : parent.getChildren())
+            for (int i = 0; i < childCount; i++)
             {
+                UIComponent child = parent.getChildren().get(i);
                 if (id.equals(child.getId()))
                 {
                     return child;
@@ -286,8 +290,9 @@ public final class ComponentSupport
             }
             else if (toRender.getChildCount() > 0)
             {
-                for (UIComponent child : toRender.getChildren())
+                for (int i = 0, childCount = toRender.getChildCount(); i < childCount; i++)
                 {
+                    UIComponent child = toRender.getChildren().get(i);
                     encodeRecursive(context, child);
                 }
             }
@@ -427,4 +432,84 @@ public final class ComponentSupport
             FaceletViewDeclarationLanguage.cleanTransientBuildOnRestore(context);
         }
     }
+    
+    public static UIComponent findComponentChildOrFacetFrom(FacesContext facesContext, UIComponent parent, String expr)
+    {
+        final char separatorChar = UINamingContainer.getSeparatorChar(facesContext);
+        int separator = expr.indexOf(separatorChar);
+        if (separator == -1)
+        {
+            return ComponentSupport.findComponentChildOrFacetFrom(
+                    parent, expr, null);
+        }
+        else
+        {
+            return ComponentSupport.findComponentChildOrFacetFrom(
+                    parent, expr.substring(0,separator), expr);
+        }
+    }
+    
+    public static UIComponent findComponentChildOrFacetFrom(UIComponent parent, String id, String innerExpr)
+    {
+        if (parent.getFacetCount() > 0)
+        {
+            for (UIComponent facet : parent.getFacets().values())
+            {
+                if (id.equals(facet.getId()))
+                {
+                    if (innerExpr == null)
+                    {
+                        return facet;
+                    }
+                    else if (facet instanceof NamingContainer)
+                    {
+                        UIComponent find = facet.findComponent(innerExpr);
+                        if (find != null)
+                        {
+                            return find;
+                        }
+                    }
+                }
+                else if (!(facet instanceof NamingContainer))
+                {
+                    UIComponent find = findComponentChildOrFacetFrom(facet, id, innerExpr);
+                    if (find != null)
+                    {
+                        return find;
+                    }
+                }
+            }
+        }
+        if (parent.getChildCount() > 0)
+        {
+            for (int i = 0, childCount = parent.getChildCount(); i < childCount; i++)
+            {
+                UIComponent child = parent.getChildren().get(i);
+                if (id.equals(child.getId()))
+                {
+                    if (innerExpr == null)
+                    {
+                        return child;
+                    }
+                    else if (child instanceof NamingContainer)
+                    {
+                        UIComponent find = child.findComponent(innerExpr);
+                        if (find != null)
+                        {
+                            return find;
+                        }
+                    }
+                }
+                else if (!(child instanceof NamingContainer))
+                {
+                    UIComponent find = findComponentChildOrFacetFrom(child, id, innerExpr);
+                    if (find != null)
+                    {
+                        return find;
+                    }
+                }
+            }
+        }
+        return null;
+    }
 }

Added: myfaces/core/branches/2.0.x/impl/src/test/java/org/apache/myfaces/view/facelets/tag/composite/CompositeComponentConditionalButtonTestCase.java
URL: http://svn.apache.org/viewvc/myfaces/core/branches/2.0.x/impl/src/test/java/org/apache/myfaces/view/facelets/tag/composite/CompositeComponentConditionalButtonTestCase.java?rev=1158047&view=auto
==============================================================================
--- myfaces/core/branches/2.0.x/impl/src/test/java/org/apache/myfaces/view/facelets/tag/composite/CompositeComponentConditionalButtonTestCase.java (added)
+++ myfaces/core/branches/2.0.x/impl/src/test/java/org/apache/myfaces/view/facelets/tag/composite/CompositeComponentConditionalButtonTestCase.java Mon Aug 15 22:34:19 2011
@@ -0,0 +1,101 @@
+/*
+ * 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.view.facelets.tag.composite;
+
+import javax.faces.component.UICommand;
+import javax.faces.component.UIComponent;
+import javax.faces.component.UINamingContainer;
+import javax.faces.component.UIViewRoot;
+import javax.faces.event.ActionEvent;
+
+import org.apache.myfaces.config.RuntimeConfig;
+import org.apache.myfaces.test.mock.MockExternalContext;
+import org.apache.myfaces.view.facelets.FaceletTestCase;
+import org.apache.myfaces.view.facelets.bean.HelloWorld;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class CompositeComponentConditionalButtonTestCase extends FaceletTestCase
+{
+
+    @Override
+    protected void setupComponents() throws Exception
+    {
+        super.setupComponents();
+    }
+    
+    @Override
+    protected void setUpExternalContext() throws Exception
+    {
+        externalContext =
+            new MockExternalContext(servletContext, request, response);
+        
+        //RuntimeConfig.getCurrentInstance(externalContext).setPropertyResolver(
+        //        new PropertyResolverImpl());
+        //RuntimeConfig.getCurrentInstance(externalContext).setVariableResolver(
+        //        new VariableResolverImpl());
+        // For this test we need the a real one, because the Mock does not
+        // handle VariableMapper stuff properly and ui:param logic will not work
+        RuntimeConfig.getCurrentInstance(externalContext).setExpressionFactory(
+                new org.apache.el.ExpressionFactoryImpl());
+    }
+
+    @Test
+    public void testConditionalButtonTargets() throws Exception
+    {
+        HelloWorld helloWorld = new HelloWorld(); 
+        
+        facesContext.getExternalContext().getRequestMap().put("helloWorldBean",
+                helloWorld);
+        
+        UIViewRoot root = facesContext.getViewRoot();
+        vdl.buildView(facesContext, root, "testConditionalButtonTargets.xhtml");
+
+        //The first component has a default command button
+        UIComponent form = root.findComponent("testForm1");
+        Assert.assertNotNull(form);
+        UINamingContainer compositeComponent1 = (UINamingContainer) form.findComponent("actionSource1");
+        Assert.assertNotNull(compositeComponent1);
+        UICommand button1 = (UICommand) compositeComponent1.findComponent("button");
+        Assert.assertNotNull(button1);
+        Assert.assertEquals("submit", button1.getActionExpression().invoke(facesContext.getELContext(), null));
+        
+        Assert.assertNotNull(button1.getActionListeners());
+        Assert.assertEquals(1, button1.getActionListeners().length);
+        
+        UINamingContainer compositeComponent2 = (UINamingContainer) form.findComponent("actionSource2");
+        Assert.assertNotNull(compositeComponent2);
+        UICommand button2 = (UICommand) compositeComponent2.findComponent("button");
+        Assert.assertNotNull(button2);
+        //Since the button is outside cc:implementation, by the spec it cannot be taken into account as a valid "targets" value.
+        Assert.assertEquals("fail", button2.getActionExpression().invoke(facesContext.getELContext(), null));
+        //It also cannot be target of cc:actionSource
+        Assert.assertNotNull(button2.getActionListeners());
+        Assert.assertEquals(0, button2.getActionListeners().length);
+
+        //StringWriter sw = new StringWriter();
+        //MockResponseWriter mrw = new MockResponseWriter(sw);
+        //facesContext.setResponseWriter(mrw);
+        
+        //root.encodeAll(facesContext);
+        //sw.flush();
+        //System.out.print(sw.toString());
+    }
+}

Added: myfaces/core/branches/2.0.x/impl/src/test/resources/org/apache/myfaces/view/facelets/tag/composite/resources/testComposite/simpleConditionalButtonTargets.xhtml
URL: http://svn.apache.org/viewvc/myfaces/core/branches/2.0.x/impl/src/test/resources/org/apache/myfaces/view/facelets/tag/composite/resources/testComposite/simpleConditionalButtonTargets.xhtml?rev=1158047&view=auto
==============================================================================
--- myfaces/core/branches/2.0.x/impl/src/test/resources/org/apache/myfaces/view/facelets/tag/composite/resources/testComposite/simpleConditionalButtonTargets.xhtml (added)
+++ myfaces/core/branches/2.0.x/impl/src/test/resources/org/apache/myfaces/view/facelets/tag/composite/resources/testComposite/simpleConditionalButtonTargets.xhtml Mon Aug 15 22:34:19 2011
@@ -0,0 +1,38 @@
+<!--
+ 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.
+
+ $Id: defineInclude.xml 804043 2009-08-13 22:08:44Z lu4242 $
+-->
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml"
+	xmlns:h="http://java.sun.com/jsf/html"
+	xmlns:f="http://java.sun.com/jsf/core"
+	xmlns:c="http://java.sun.com/jsp/jstl/core"
+	xmlns:cc="http://java.sun.com/jsf/composite">
+<head>
+</head>
+<body>
+<cc:interface>
+    <cc:attribute name="action" targets="button" default="submit"/>
+    <cc:actionSource name="button"/>
+</cc:interface>
+<cc:implementation>
+    <c:if test="#{empty cc.facets.defaultAction}">
+        <h:commandButton id="button" action="#{cc.attrs.customMethod}"/>
+    </c:if>
+    <c:if test="#{!empty cc.facets.defaultAction}">
+        <cc:renderFacet name="defaultAction"/>
+    </c:if>
+</cc:implementation>
+</body>
+</html>

Added: myfaces/core/branches/2.0.x/impl/src/test/resources/org/apache/myfaces/view/facelets/tag/composite/testConditionalButtonTargets.xhtml
URL: http://svn.apache.org/viewvc/myfaces/core/branches/2.0.x/impl/src/test/resources/org/apache/myfaces/view/facelets/tag/composite/testConditionalButtonTargets.xhtml?rev=1158047&view=auto
==============================================================================
--- myfaces/core/branches/2.0.x/impl/src/test/resources/org/apache/myfaces/view/facelets/tag/composite/testConditionalButtonTargets.xhtml (added)
+++ myfaces/core/branches/2.0.x/impl/src/test/resources/org/apache/myfaces/view/facelets/tag/composite/testConditionalButtonTargets.xhtml Mon Aug 15 22:34:19 2011
@@ -0,0 +1,36 @@
+<!--
+ 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.
+
+ $Id: defineInclude.xml 804043 2009-08-13 22:08:44Z lu4242 $
+-->
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml"
+	xmlns:h="http://java.sun.com/jsf/html"
+	xmlns:f="http://java.sun.com/jsf/core"
+	xmlns:testComposite="http://java.sun.com/jsf/composite/testComposite">
+<head>
+</head>
+<body>
+<h:form id="testForm1">
+<testComposite:simpleConditionalButtonTargets id="actionSource1">
+    <f:actionListener for="button" binding="#{helloWorldBean.actionListener}"/>
+</testComposite:simpleConditionalButtonTargets>
+<testComposite:simpleConditionalButtonTargets id="actionSource2">
+    <f:actionListener for="button" binding="#{helloWorldBean.actionListener}"/>
+    <f:facet name="defaultAction">
+        <h:commandButton id="button" action="fail"/>
+    </f:facet>
+</testComposite:simpleConditionalButtonTargets>
+</h:form>
+</body>
+</html>