You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tapestry.apache.org by hl...@apache.org on 2009/02/15 20:01:04 UTC

svn commit: r744720 - in /tapestry/tapestry5/trunk/tapestry-core/src: main/java/org/apache/tapestry5/internal/pageload/ test/app1/ test/java/org/apache/tapestry5/integration/ test/java/org/apache/tapestry5/integration/app1/components/ test/java/org/apa...

Author: hlship
Date: Sun Feb 15 19:01:03 2009
New Revision: 744720

URL: http://svn.apache.org/viewvc?rev=744720&view=rev
Log:
TAP5-487: Easier way to expose parameters of an embedded component in a containing component

Added:
    tapestry/tapestry5/trunk/tapestry-core/src/test/app1/PublishUnknownParameterDemo.tml
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/components/BadPublishUnknown.java
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/PublishUnknownParameterDemo.java
    tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry5/integration/app1/components/BadPublishUnknown.tml
Modified:
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/pageload/ComponentAssemblerImpl.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/pageload/EmbeddedComponentAssembler.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/pageload/EmbeddedComponentAssemblerImpl.java
    tapestry/tapestry5/trunk/tapestry-core/src/test/app1/Index.tml
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/IntegrationTests.java

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/pageload/ComponentAssemblerImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/pageload/ComponentAssemblerImpl.java?rev=744720&r1=744719&r2=744720&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/pageload/ComponentAssemblerImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/pageload/ComponentAssemblerImpl.java Sun Feb 15 19:01:03 2009
@@ -51,12 +51,9 @@
 
     private final IdAllocator allocator = new IdAllocator();
 
-    private final Map<String, String> publishedParameterToEmbeddedId = CollectionFactory.newCaseInsensitiveMap();
+    private Map<String, String> publishedParameterToEmbeddedId;
 
-    // Doesn't have to be case-insensitive, because the embeddedIds are always known alues from
-    // publishedParameterToEmbeddedId.
-
-    private final Map<String, String> embeddedIdToComponentClassName = CollectionFactory.newMap();
+    private Map<String, EmbeddedComponentAssembler> embeddedIdToAssembler;
 
     public ComponentAssemblerImpl(ComponentAssemblerSource assemblerSource,
                                   ComponentInstantiatorSource instantiatorSource,
@@ -263,12 +260,18 @@
                                                                                      mixins,
                                                                                      location);
 
+        if (embeddedIdToAssembler == null)
+            embeddedIdToAssembler = CollectionFactory.newMap();
+
+        embeddedIdToAssembler.put(embeddedId, embedded);
+
         if (embeddedModel != null)
         {
-            // ComponentModel embeddedComponentModel = instantiatorSource.getInstantiator(componentClassName).getModel();
-
             for (String publishedParameterName : embeddedModel.getPublishedParameters())
             {
+                if (publishedParameterToEmbeddedId == null)
+                    publishedParameterToEmbeddedId = CollectionFactory.newCaseInsensitiveMap();
+
                 String existingEmbeddedId = publishedParameterToEmbeddedId.get(publishedParameterName);
 
                 if (existingEmbeddedId != null)
@@ -283,35 +286,23 @@
                     throw new TapestryException(message, location, null);
                 }
 
-//                if (embeddedComponentModel.getParameterModel(publishedParameterName) == null)
-//                {
-//                    String message = String.format(
-//                            "Component %s does not include a parameter named '%s' to publish. Possible parameters: %s.",
-//                            componentClassName, publishedParameterName,
-//                            InternalUtils.joinSorted(embeddedComponentModel.getParameterNames()));
-//
-//                    throw new TapestryException(message, location, null);
-//                }
-
                 publishedParameterToEmbeddedId.put(publishedParameterName, embeddedId);
             }
 
         }
 
-        embeddedIdToComponentClassName.put(embeddedId, componentClassName);
-
         return embedded;
     }
 
     public ParameterBinder getBinder(final String parameterName)
     {
-        final String embeddedId = publishedParameterToEmbeddedId.get(parameterName);
+        final String embeddedId = InternalUtils.get(publishedParameterToEmbeddedId, parameterName);
 
         if (embeddedId == null) return null;
 
-        String componentClassName = embeddedIdToComponentClassName.get(embeddedId);
+        final EmbeddedComponentAssembler embededdedComponentAssembler = embeddedIdToAssembler.get(embeddedId);
 
-        final ComponentAssembler embeddedAssembler = assemblerSource.getAssembler(componentClassName, locale);
+        final ComponentAssembler embeddedAssembler = embededdedComponentAssembler.getComponentAssembler();
 
         final ParameterBinder embeddedBinder = embeddedAssembler.getBinder(parameterName);
 
@@ -336,6 +327,20 @@
             };
         }
 
+
+        final ParameterBinder innerBinder = embededdedComponentAssembler.createParameterBinder(parameterName);
+
+        if (innerBinder == null)
+        {
+            String message = String.format(
+                    "Parameter '%s' of component %s is improperly published from embedded component '%s' (where it does not exist). " +
+                            "This may be a typo in the publishParameters attribute of the @Component annotation.",
+                    parameterName,
+                    instantiator.getModel().getComponentClassName(),
+                    embeddedId);
+
+            throw new TapestryException(message, embededdedComponentAssembler.getLocation(), null);
+        }
         // The simple case, publishing a parameter of a subcomponent as if it were a parameter
         // of this component.
 
@@ -345,12 +350,12 @@
             {
                 ComponentPageElement subelement = element.getEmbeddedElement(embeddedId);
 
-                subelement.bindParameter(parameterName, binding);
+                innerBinder.bind(subelement, binding);
             }
 
             public String getDefaultBindingPrefix(String metaDefault)
             {
-                return embeddedAssembler.getModel().getParameterModel(parameterName).getDefaultBindingPrefix();
+                return innerBinder.getDefaultBindingPrefix(metaDefault);
             }
         };
     }

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/pageload/EmbeddedComponentAssembler.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/pageload/EmbeddedComponentAssembler.java?rev=744720&r1=744719&r2=744720&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/pageload/EmbeddedComponentAssembler.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/pageload/EmbeddedComponentAssembler.java Sun Feb 15 19:01:03 2009
@@ -23,6 +23,11 @@
 interface EmbeddedComponentAssembler extends Locatable
 {
     /**
+     * Returns the assembler responsible for creating instances of this embedded component.
+     */
+    ComponentAssembler getComponentAssembler();
+
+    /**
      * Creates a binder that can later be used to bind the parameter. The parameter name may be unqualified ("value") or
      * have a mixin prefix ("mymixin.value").  In the former case, the correct mixin is located (though the more typical
      * case is to bind a parameter of the component itself, not a parameter of a mixin attached to the component). In

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/pageload/EmbeddedComponentAssemblerImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/pageload/EmbeddedComponentAssemblerImpl.java?rev=744720&r1=744719&r2=744720&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/pageload/EmbeddedComponentAssemblerImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/pageload/EmbeddedComponentAssemblerImpl.java Sun Feb 15 19:01:03 2009
@@ -41,7 +41,7 @@
 
     private final Location location;
 
-    private final Map<String, ComponentModel> mixinIdToComponentModel = CollectionFactory.newCaseInsensitiveMap();
+    private final Map<String, Instantiator> mixinIdToInstantiator = CollectionFactory.newCaseInsensitiveMap();
 
     /**
      * Maps parameter names (both simple, and qualified with the mixin id) to the corresponding QualifiedParameterName.
@@ -69,7 +69,8 @@
                                           ComponentInstantiatorSource instantiatorSource,
                                           ComponentClassResolver componentClassResolver,
                                           String componentClassName,
-                                          Locale locale, EmbeddedComponentModel embeddedModel,
+                                          Locale locale,
+                                          EmbeddedComponentModel embeddedModel,
                                           String templateMixins,
                                           Location location)
     {
@@ -113,12 +114,14 @@
 
     private String prescanMixins()
     {
+        // Mixin id found to support informal parameters
+
         String supportsInformals = null;
 
-        for (Map.Entry<String, ComponentModel> entry : mixinIdToComponentModel.entrySet())
+        for (Map.Entry<String, Instantiator> entry : mixinIdToInstantiator.entrySet())
         {
             String mixinId = entry.getKey();
-            ComponentModel mixinModel = entry.getValue();
+            ComponentModel mixinModel = entry.getValue().getModel();
 
             updateParameterNameToQualified(mixinId, mixinModel);
 
@@ -151,18 +154,18 @@
 
     private void addMixin(String className)
     {
-        ComponentModel model = getModel(className);
+        Instantiator mixinInstantiator = instantiatorSource.getInstantiator(className);
 
         String mixinId = InternalUtils.lastTerm(className);
 
-        if (mixinIdToComponentModel.containsKey(mixinId))
+        if (mixinIdToInstantiator.containsKey(mixinId))
             throw new TapestryException(
                     String.format("Mixins applied to a component must be unique. Mixin '%s' has already been applied.",
                                   mixinId),
                     location, null);
 
 
-        mixinIdToComponentModel.put(mixinId, model);
+        mixinIdToInstantiator.put(mixinId, mixinInstantiator);
     }
 
     private ComponentModel getModel(String className)
@@ -170,17 +173,22 @@
         return instantiatorSource.getInstantiator(className).getModel();
     }
 
+    public ComponentAssembler getComponentAssembler()
+    {
+        return assemblerSource.getAssembler(componentModel.getComponentClassName(), locale);
+    }
+
     public ParameterBinder createParameterBinder(String parameterName)
     {
         int dotx = parameterName.indexOf('.');
         if (dotx >= 0)
         {
             String mixinId = parameterName.substring(0, dotx);
-            if (!mixinIdToComponentModel.containsKey(mixinId))
+            if (!mixinIdToInstantiator.containsKey(mixinId))
             {
                 String message = String.format("Mixin id for parameter '%s' not found. Attached mixins: %s.",
                                                parameterName,
-                                               InternalUtils.joinSorted(mixinIdToComponentModel.keySet()));
+                                               InternalUtils.joinSorted(mixinIdToInstantiator.keySet()));
 
                 throw new TapestryException(message, location, null);
             }
@@ -231,15 +239,10 @@
 
     public void addMixinsToElement(ComponentPageElement newElement)
     {
-        for (Map.Entry<String, ComponentModel> entry : mixinIdToComponentModel.entrySet())
+        for (Map.Entry<String, Instantiator> entry : mixinIdToInstantiator.entrySet())
         {
             String mixinId = entry.getKey();
-            ComponentModel model = entry.getValue();
-
-            // TODO: Change mixinIdTo... to be to Instantiator instead, so we don't have to
-            // keep asking the IS for them.
-
-            Instantiator instantiator = instantiatorSource.getInstantiator(model.getComponentClassName());
+            Instantiator instantiator = entry.getValue();
 
             newElement.addMixin(mixinId, instantiator);
         }

Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/app1/Index.tml
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/app1/Index.tml?rev=744720&r1=744719&r2=744720&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/app1/Index.tml (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/app1/Index.tml Sun Feb 15 19:01:03 2009
@@ -107,6 +107,10 @@
             </a>
             -- error checking for conflict between @Component.type and t:type.
         </li>
+        <li>
+            <a href="PublishUnknownParameterDemo">Publish Unknown Parameter Demo</a>
+            -- publishing a parameter which does not exist
+        </li>
     </ul>
 
 </html>

Added: tapestry/tapestry5/trunk/tapestry-core/src/test/app1/PublishUnknownParameterDemo.tml
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/app1/PublishUnknownParameterDemo.tml?rev=744720&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/app1/PublishUnknownParameterDemo.tml (added)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/app1/PublishUnknownParameterDemo.tml Sun Feb 15 19:01:03 2009
@@ -0,0 +1,4 @@
+<t:border xmlns:t="http://tapestry.apache.org/schema/tapestry_5_0_0.xsd"
+          xmlns:p="tapestry:parameter">
+    <t:badpublishunknown xyzzyx="whatever"/>
+</t:border>
\ No newline at end of file

Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/IntegrationTests.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/IntegrationTests.java?rev=744720&r1=744719&r2=744720&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/IntegrationTests.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/IntegrationTests.java Sun Feb 15 19:01:03 2009
@@ -2573,4 +2573,14 @@
                         "as well as in the component class ('textfield'). You should not provide a type attribute in " +
                         "the template when defining an embedded component within the component class.");
     }
+
+    public void publish_unknown_parameter()
+    {
+        start("Publish Unknown Parameter Demo");
+
+        assertTextPresent(
+                "Parameter 'xyzzyx' of component org.apache.tapestry5.integration.app1.components.BadPublishUnknown " +
+                        "is improperly published from embedded component 'publish1' (where it does not exist). " +
+                        "This may be a typo in the publishParameters attribute of the @Component annotation.");
+    }
 }
\ No newline at end of file

Added: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/components/BadPublishUnknown.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/components/BadPublishUnknown.java?rev=744720&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/components/BadPublishUnknown.java (added)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/components/BadPublishUnknown.java Sun Feb 15 19:01:03 2009
@@ -0,0 +1,23 @@
+// Copyright 2009 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.tapestry5.integration.app1.components;
+
+import org.apache.tapestry5.annotations.Component;
+
+public class BadPublishUnknown
+{
+    @Component(publishParameters = "xyzzyx")
+    private Publish1 publish1;
+}

Added: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/PublishUnknownParameterDemo.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/PublishUnknownParameterDemo.java?rev=744720&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/PublishUnknownParameterDemo.java (added)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/PublishUnknownParameterDemo.java Sun Feb 15 19:01:03 2009
@@ -0,0 +1,19 @@
+// Copyright 2009 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.tapestry5.integration.app1.pages;
+
+public class PublishUnknownParameterDemo
+{
+}

Added: tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry5/integration/app1/components/BadPublishUnknown.tml
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry5/integration/app1/components/BadPublishUnknown.tml?rev=744720&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry5/integration/app1/components/BadPublishUnknown.tml (added)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry5/integration/app1/components/BadPublishUnknown.tml Sun Feb 15 19:01:03 2009
@@ -0,0 +1,6 @@
+<t:container xmlns:t="http://tapestry.apache.org/schema/tapestry_5_0_0.xsd"
+             xmlns:p="tapestry:parameter">
+
+    <span t:id="publish1"/>
+
+</t:container>
\ No newline at end of file