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 2011/10/03 23:22:19 UTC
svn commit: r1178584 - in /tapestry/tapestry5/trunk/tapestry-core/src:
main/java/org/apache/tapestry5/internal/pageload/
main/resources/org/apache/tapestry5/internal/pageload/
test/groovy/org/apache/tapestry5/integration/app1/
test/java/org/apache/tape...
Author: hlship
Date: Mon Oct 3 21:22:18 2011
New Revision: 1178584
URL: http://svn.apache.org/viewvc?rev=1178584&view=rev
Log:
TAP5-1680: A mixin with a formal parameter will prevent an informal parameter of the same name from being bound on the component
Added:
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/mixins/AltTitle.java
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/MixinVsInformalParameter.java
tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry5/integration/app1/pages/MixinVsInformalParameter.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/main/java/org/apache/tapestry5/internal/pageload/PageloadMessages.java
tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/internal/pageload/PageloadStrings.properties
tapestry/tapestry5/trunk/tapestry-core/src/test/groovy/org/apache/tapestry5/integration/app1/ParameterTests.groovy
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/Index.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=1178584&r1=1178583&r2=1178584&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 Mon Oct 3 21:22:18 2011
@@ -286,6 +286,7 @@ class ComponentAssemblerImpl implements
throw new TapestryException(
PageloadMessages.missingComponentType(), location, null);
}
+
EmbeddedComponentAssemblerImpl embedded = new EmbeddedComponentAssemblerImpl(assemblerSource,
instantiatorSource, componentClassResolver, componentClassName, getSelector(), embeddedModel,
mixins, location);
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=1178584&r1=1178583&r2=1178584&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 Mon Oct 3 21:22:18 2011
@@ -33,7 +33,9 @@ interface EmbeddedComponentAssembler ext
* 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
- * the latter case, the mixinId is validated (to ensure it exists).
+ * the latter case, the mixinId is validated (to ensure it exists). In addition, a special mixinid that matches the
+ * component's class name can be used; this is necessary to disambiguate informal parameters of the component from formal mixin parameters
+ * (where an unqualified name would be bound to the mixin's parameter).
* <p/>
* If the name of the parameter does not match a formal parameter of the component (or mixin) and the component (or
* mixin) does not support informal parameters, then null is returned.
@@ -41,8 +43,7 @@ interface EmbeddedComponentAssembler ext
* This method should only be called at page-assembly time as it requires some data that is collected during
* ComponentAssembly construction in order to handle published parameters of embedded components.
*
- * @param parameterName
- * simple or qualified parameter name
+ * @param parameterName simple or qualified parameter name
* @return object that can bind the parameter
*/
ParameterBinder createParameterBinder(String parameterName);
@@ -62,8 +63,7 @@ interface EmbeddedComponentAssembler ext
/**
* Adds mixins to the newly created embedded element.
*
- * @param newElement
- * new element requiring mixins
+ * @param newElement new element requiring mixins
*/
void addMixinsToElement(ComponentPageElement newElement);
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=1178584&r1=1178583&r2=1178584&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 Mon Oct 3 21:22:18 2011
@@ -57,24 +57,19 @@ public class EmbeddedComponentAssemblerI
private final String informalParametersMixinId;
+ private final String componentPsuedoMixinId;
+
private Map<String, Boolean> bound;
/**
* @param assemblerSource
- * @param instantiatorSource
- * used to access component models
- * @param componentClassResolver
- * used to convert mixin types to component models
- * @param componentClassName
- * class name of embedded component
- * @param selector
- * used to select template and other resources
- * @param embeddedModel
- * embedded model (may be null for components defined in the template)
- * @param templateMixins
- * list of mixins from the t:mixins element (possibly null)
- * @param location
- * location of components element in its container's template
+ * @param instantiatorSource used to access component models
+ * @param componentClassResolver used to convert mixin types to component models
+ * @param componentClassName class name of embedded component
+ * @param selector used to select template and other resources
+ * @param embeddedModel embedded model (may be null for components defined in the template)
+ * @param templateMixins list of mixins from the t:mixins element (possibly null)
+ * @param location location of components element in its container's template
*/
public EmbeddedComponentAssemblerImpl(ComponentAssemblerSource assemblerSource,
ComponentInstantiatorSource instantiatorSource, ComponentClassResolver componentClassResolver,
@@ -106,7 +101,7 @@ public class EmbeddedComponentAssemblerI
}
}
- // And the template may include a t:mixins element to define yet more mixin.
+ // And the template may include a t:mixins element to define yet more mixins.
// Template strings specified as:
for (String mixinDef : TapestryInternalUtils.splitAtCommas(templateMixins))
{
@@ -116,6 +111,12 @@ public class EmbeddedComponentAssemblerI
addMixin(className, order.getConstraints());
}
+ // Finally (new in 5.3, for TAP5-1680), the component itself can sometimes acts as a mixin;
+ // this allows for dealing with parameter name conflicts between the component and the mixin
+ // (especially where informal parameters are involved).
+
+ componentPsuedoMixinId = InternalUtils.lastTerm(componentClassName);
+
informalParametersMixinId = prescanMixins();
}
@@ -182,51 +183,116 @@ public class EmbeddedComponentAssemblerI
return assemblerSource.getAssembler(componentModel.getComponentClassName(), selector);
}
- public ParameterBinder createParameterBinder(String parameterName)
+
+ public ParameterBinder createParameterBinder(String qualifiedParameterName)
{
- int dotx = parameterName.indexOf('.');
- if (dotx >= 0)
- {
- String mixinId = parameterName.substring(0, dotx);
- if (!mixinIdToInstantiator.containsKey(mixinId))
- {
- throw new TapestryException(
- PageloadMessages.mixinidForParamnotfound(parameterName, mixinIdToInstantiator.keySet()), location,
- null);
- }
- } else
+ int dotx = qualifiedParameterName.indexOf('.');
+
+ if (dotx < 0)
{
- // Unqualified parameter name. May be a reference not to a parameter of this component, but a published
- // parameter of a component embedded in this component. The ComponentAssembler for this component
- // will know.
+ return createParameterBinderFromSimpleParameterName(qualifiedParameterName);
+ }
+
+ return createParameterBinderFromQualifiedParameterName(qualifiedParameterName, qualifiedParameterName.substring(0, dotx),
+ qualifiedParameterName.substring(dotx + 1));
+ }
- ComponentAssembler assembler = assemblerSource.getAssembler(componentModel.getComponentClassName(),
- selector);
+ private ParameterBinder createParameterBinderFromSimpleParameterName(String parameterName)
+ {
- ParameterBinder binder = assembler.getBinder(parameterName);
+ // Look for a *formal* parameter with the simple name on the component itself.
- if (binder != null)
- return binder;
+ ParameterBinder binder = getComponentAssembler().getBinder(parameterName);
+
+ if (binder != null)
+ {
+ return binder;
}
- final ParameterBinder binder = parameterNameToBinder.get(parameterName);
+ // Next see if any mixin has a formal parameter with this simple name.
+
+ binder = parameterNameToBinder.get(parameterName);
if (binder != null)
+ {
return binder;
+ }
- // Informal parameter: Is there a mixin for that?
+
+ // So, is there an mixin that's claiming all informal parameters?
if (informalParametersMixinId != null)
+ {
return new ParameterBinderImpl(informalParametersMixinId, parameterName, null);
+ }
+ // Maybe the component claims informal parameters?
if (componentModel.getSupportsInformalParameters())
return new ParameterBinderImpl(null, parameterName, null);
- // Otherwise, informal parameter and not supported by the component or any mixin.
+ // Otherwise, informal parameter are not supported by the component or any mixin.
return null;
}
+ private ParameterBinder createParameterBinderFromQualifiedParameterName(String qualifiedParameterName, String mixinId, String parameterName)
+ {
+
+ if (mixinId.equalsIgnoreCase(componentPsuedoMixinId))
+ {
+ return createParameterBinderForComponent(qualifiedParameterName, parameterName);
+ }
+
+ if (!mixinIdToInstantiator.containsKey(mixinId))
+ {
+ throw new TapestryException(
+ String.format("Mixin id for parameter '%s' not found. Attached mixins: %s.", qualifiedParameterName,
+ InternalUtils.joinSorted(mixinIdToInstantiator.keySet())), location,
+ null);
+ }
+
+ ParameterBinder binder = parameterNameToBinder.get(qualifiedParameterName);
+
+ if (binder != null)
+ {
+ return binder;
+ }
+
+ // Ok, so perhaps this is a qualified name for an informal parameter of the mixin.
+
+ Instantiator instantiator = mixinIdToInstantiator.get(mixinId);
+
+ assert instantiator != null;
+
+ return bindInformalParameter(qualifiedParameterName, mixinId, parameterName, instantiator.getModel());
+ }
+
+ private ParameterBinder bindInformalParameter(String qualifiedParameterName, String mixinId, String parameterName, ComponentModel model)
+ {
+ if (model.getSupportsInformalParameters())
+ {
+ return new ParameterBinderImpl(mixinId, parameterName, null);
+ }
+
+ // Pretty sure this was not caught as an error in 5.2.
+
+ throw new TapestryException(String.format("Binding parameter %s as an informal parameter does not make sense, as %s does not support informal parameters.",
+ qualifiedParameterName, model.getComponentClassName()), location, null);
+ }
+
+ private ParameterBinder createParameterBinderForComponent(String qualifiedParameterName, String parameterName)
+ {
+ ParameterBinder binder = getComponentAssembler().getBinder(parameterName);
+
+ if (binder != null)
+ {
+ return binder;
+ }
+
+ return bindInformalParameter(qualifiedParameterName, null, parameterName, componentModel);
+ }
+
+
public boolean isBound(String parameterName)
{
return InternalUtils.get(bound, parameterName) != null;
Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/pageload/PageloadMessages.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/pageload/PageloadMessages.java?rev=1178584&r1=1178583&r2=1178584&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/pageload/PageloadMessages.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/pageload/PageloadMessages.java Mon Oct 3 21:22:18 2011
@@ -14,17 +14,15 @@
package org.apache.tapestry5.internal.pageload;
+import org.apache.tapestry5.internal.parser.TokenType;
import org.apache.tapestry5.ioc.Messages;
import org.apache.tapestry5.ioc.Resource;
import org.apache.tapestry5.ioc.internal.util.MessagesImpl;
-import org.apache.tapestry5.ioc.internal.util.InternalUtils;
-import org.apache.tapestry5.internal.parser.TokenType;
import org.apache.tapestry5.model.ComponentModel;
-import java.util.Collection;
-
/**
* Localized exception message support for pageload-related classes.
+ *
* @since 5.2.0
*/
final class PageloadMessages
@@ -41,11 +39,6 @@ final class PageloadMessages
return MESSAGES.format("unique_mixin_required", mixinId);
}
- public static String mixinidForParamnotfound(String parameterName, Collection<String> availableMixins)
- {
- return MESSAGES.format("mixinid_for_paramnotfound", parameterName, InternalUtils.joinSorted(availableMixins));
- }
-
public static String missingComponentType()
{
return MESSAGES.get("missing_component_type");
@@ -83,12 +76,12 @@ final class PageloadMessages
public static String compositeRenderCommandMethodNotImplemented(String methodName)
{
- return MESSAGES.format("composite_render_command_method_not_implemented",methodName);
+ return MESSAGES.format("composite_render_command_method_not_implemented", methodName);
}
public static String exceptionAssemblingRootComponent(String pageName, String exceptionMessage)
{
- return MESSAGES.format("exception_assembling_root_component",pageName,exceptionMessage);
+ return MESSAGES.format("exception_assembling_root_component", pageName, exceptionMessage);
}
public static String exceptionAssemblingEmbeddedComponent(
@@ -118,7 +111,7 @@ final class PageloadMessages
}
public static String parameterAlreadyPublished(
- String publishedParameterName,
+ String publishedParameterName,
String embeddedId,
String componentClassName,
String existingEmbeddedId)
@@ -132,7 +125,7 @@ final class PageloadMessages
public static String failureCreatingEmbeddedComponent(String embeddedId, String containerClass, String exception)
{
- return MESSAGES.format("failure_creating_embedded_component",embeddedId, containerClass, exception);
+ return MESSAGES.format("failure_creating_embedded_component", embeddedId, containerClass, exception);
}
public static String publishedParameterNonexistant(String parameterName, String publishingClass, String embeddedId)
Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/internal/pageload/PageloadStrings.properties
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/internal/pageload/PageloadStrings.properties?rev=1178584&r1=1178583&r2=1178584&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/internal/pageload/PageloadStrings.properties (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/internal/pageload/PageloadStrings.properties Mon Oct 3 21:22:18 2011
@@ -15,7 +15,6 @@
#
unique_mixin_required=Mixins applied to a component must be unique. Mixin '%s' has already been applied.
-mixinid_for_paramnotfound="Mixin id for parameter '%s' not found. Attached mixins: %s."
missing_component_type=You must specify the type via t:type, the element, or @Component annotation.
no_more_tokens=No more template tokens.
could_not_find_override=Could not find an override for extension point '%s'.
Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/groovy/org/apache/tapestry5/integration/app1/ParameterTests.groovy
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/groovy/org/apache/tapestry5/integration/app1/ParameterTests.groovy?rev=1178584&r1=1178583&r2=1178584&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/groovy/org/apache/tapestry5/integration/app1/ParameterTests.groovy (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/groovy/org/apache/tapestry5/integration/app1/ParameterTests.groovy Mon Oct 3 21:22:18 2011
@@ -57,4 +57,18 @@ class ParameterTests extends TapestryCor
assertTextPresent "Parameter 'value' of component class org.apache.tapestry5.integration.app1.components.ParameterSubClass conflicts with the parameter defined by the org.apache.tapestry5.integration.app1.base.ParameterBaseClass base class."
}
+
+ /**
+ * https://issues.apache.org/jira/browse/TAP5-1680
+ */
+ @Test
+ void use_component_class_name_to_disambiguate_informal_parameter()
+ {
+ openLinks "Mixin Parameter vs. Informal Parameter"
+
+ // Why frog? I don't know.
+
+ assertAttribute "//a[@id='frog']/@alt", "Alt Title"
+ assertAttribute "//a[@id='frog']/@title", "Frog Title"
+ }
}
Added: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/mixins/AltTitle.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/mixins/AltTitle.java?rev=1178584&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/mixins/AltTitle.java (added)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/mixins/AltTitle.java Mon Oct 3 21:22:18 2011
@@ -0,0 +1,32 @@
+package org.apache.tapestry5.integration.app1.mixins;
+
+import org.apache.tapestry5.BindingConstants;
+import org.apache.tapestry5.ClientElement;
+import org.apache.tapestry5.MarkupWriter;
+import org.apache.tapestry5.annotations.InjectContainer;
+import org.apache.tapestry5.annotations.MixinAfter;
+import org.apache.tapestry5.annotations.Parameter;
+
+/**
+ * Used to test https://issues.apache.org/jira/browse/TAP5-1680.
+ */
+@MixinAfter
+public class AltTitle
+{
+ @InjectContainer
+ private ClientElement container;
+
+ @Parameter(required = true, defaultPrefix = BindingConstants.LITERAL)
+ private String title;
+
+ void afterRender()
+ {
+ container.getClientId();
+ }
+
+ void beginRender(MarkupWriter writer)
+ {
+ writer.attributes("alt", title);
+ }
+
+}
Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/Index.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/Index.java?rev=1178584&r1=1178583&r2=1178584&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/Index.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/Index.java Mon Oct 3 21:22:18 2011
@@ -56,6 +56,8 @@ public class Index
private static final List<Item> ITEMS = CollectionFactory
.newList(
+ new Item("MixinVsInformalParameter", "Mixin Parameter vs. Informal Parameter", "Informal Paramters vs. Mixin parameter of same name"),
+
new Item("inherit/childa", "TAP5-1656 Demo", "Test a reported bug in component inheritance"),
new Item("ComponentInsideBlockDemo", "Component Inside Block Demo", "Verify that a component, inside a block, is still an embedded "),
Added: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/MixinVsInformalParameter.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/MixinVsInformalParameter.java?rev=1178584&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/MixinVsInformalParameter.java (added)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/MixinVsInformalParameter.java Mon Oct 3 21:22:18 2011
@@ -0,0 +1,13 @@
+package org.apache.tapestry5.integration.app1.pages;
+
+/**
+ *
+ */
+public class MixinVsInformalParameter
+{
+ void onActionFromFrog()
+ {
+
+
+ }
+}
Added: tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry5/integration/app1/pages/MixinVsInformalParameter.tml
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry5/integration/app1/pages/MixinVsInformalParameter.tml?rev=1178584&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry5/integration/app1/pages/MixinVsInformalParameter.tml (added)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry5/integration/app1/pages/MixinVsInformalParameter.tml Mon Oct 3 21:22:18 2011
@@ -0,0 +1,10 @@
+<html t:type="Border" xmlns:t="http://tapestry.apache.org/schema/tapestry_5_3.xsd">
+
+<h1>Mixin Parameter vs. Component Informal Parameter</h1>
+
+<p>
+ <t:actionlink t:id="frog" actionlink.title="Frog Title" t:mixins="alttitle" alttitle.title="Alt Title">little frog
+ </t:actionlink>
+</p>
+
+</html>
\ No newline at end of file