Author: robertdzeigler Date: Tue Oct 25 13:42:33 2011 New Revision: 1188655
URL: http://svn.apache.org/viewvc?rev=1188655&view=rev Log: TAP5-1663: The @BindParameter annotation should support inherited parameters Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/BindParameterWorker.java tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/CoreBehaviorsTests.java tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/BindParameterDemo.java tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry5/integration/app1/pages/BindParameterDemo.tml Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/BindParameterWorker.java URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/BindParameterWorker.java?rev=1188655&r1=1188654&r2=1188655&view=diff ============================================================================== --- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/BindParameterWorker.java (original) +++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/BindParameterWorker.java Tue Oct 25 13:42:33 2011 @@ -1,4 +1,4 @@ -// Copyright 2009, 2010 The Apache Software Foundation +// Copyright 2009, 2010, 2011 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. @@ -26,6 +26,7 @@ import org.apache.tapestry5.ioc.services import org.apache.tapestry5.ioc.util.AvailableValues; import org.apache.tapestry5.ioc.util.UnknownValueException; import org.apache.tapestry5.model.ComponentModel; +import org.apache.tapestry5.model.EmbeddedComponentModel; import org.apache.tapestry5.model.MutableComponentModel; import org.apache.tapestry5.plastic.*; import org.apache.tapestry5.services.transform.ComponentClassTransformWorker2; @@ -71,7 +72,12 @@ public class BindParameterWorker impleme { if (conduit == null) { - conduit = containerResources.getParameterConduit(containerParameterName); + // if the parameter is not a formal parameter then it must be a published parameter + if (containerResources.getComponentModel().isFormalParameter(containerParameterName)) + conduit = containerResources.getParameterConduit(containerParameterName); + else + conduit = getEmbeddedComponentResourcesForPublishedParameter(containerResources, containerParameterName) + .getParameterConduit(containerParameterName); } return conduit; @@ -184,9 +190,12 @@ public class BindParameterWorker impleme { if (model.isFormalParameter(name)) return name; + + if(isPublishedParameter(model, name)) + return name; } - - String message = String.format("Containing component %s does not contain a formal parameter %s %s.", + + String message = String.format("Containing component %s does not contain a formal parameter or a published parameter %s %s.", model.getComponentClassName(), @@ -194,7 +203,78 @@ public class BindParameterWorker impleme InternalUtils.joinSorted(guesses)); - throw new UnknownValueException(message, new AvailableValues("Formal parameters", model - .getDeclaredParameterNames())); + List<String> formalAndPublishedParameters = CollectionFactory.newList(model.getParameterNames()); + formalAndPublishedParameters.addAll(getPublishedParameters(model)); + + throw new UnknownValueException(message, new AvailableValues("Formal and published parameters", formalAndPublishedParameters)); + } + + /** + * Returns true if the parameter with the given parameterName is a published parameter + * of any of the embedded components for the component with the given model. + */ + private boolean isPublishedParameter(ComponentModel model, String parameterName) + { + for (String embeddedComponentId : model.getEmbeddedComponentIds()) + { + EmbeddedComponentModel embeddedComponentModel = model + .getEmbeddedComponentModel(embeddedComponentId); + if (embeddedComponentModel.getPublishedParameters().contains(parameterName)) return true; + } + + return false; + } + + private List<String> getPublishedParameters(ComponentModel model) + { + List<String> publishedParameters = CollectionFactory.newList(); + for (String embeddedComponentId : model.getEmbeddedComponentIds()) + { + EmbeddedComponentModel embeddedComponentModel = model.getEmbeddedComponentModel(embeddedComponentId); + publishedParameters.addAll(embeddedComponentModel.getPublishedParameters()); + } + return publishedParameters; } + + /** + * Returns the {@link InternalComponentResources} of an embeddedComponent that contains the published parameter + * publishedParameterName. This is basically a recursive search for published parameters. + */ + private InternalComponentResources getEmbeddedComponentResourcesForPublishedParameter(InternalComponentResources containerResources, + String publishedParameterName) + { + List<InternalComponentResources> embeddedComponentResourcesList = CollectionFactory.newList(); + + embeddedComponentResourcesList.add(containerResources); + + while(!embeddedComponentResourcesList.isEmpty()) + { + InternalComponentResources resources = embeddedComponentResourcesList.remove(0); + + ComponentModel containerComponentModel = resources.getComponentModel(); + + for(String embeddedComponentId : containerComponentModel.getEmbeddedComponentIds()) + { + EmbeddedComponentModel embeddedComponentModel = containerComponentModel + .getEmbeddedComponentModel(embeddedComponentId); + + InternalComponentResources embeddedComponentResources = (InternalComponentResources) resources + .getEmbeddedComponent(embeddedComponentId).getComponentResources(); + /** + * If the parameter is not a formal parameter, then the parameter must be a published parameter + * of an embeddedComponent of the component we are currently examining. + */ + if(embeddedComponentModel.getPublishedParameters().contains(publishedParameterName) + && embeddedComponentResources.getComponentModel().isFormalParameter(publishedParameterName)) + { + return embeddedComponentResources; + } + + embeddedComponentResourcesList.add(embeddedComponentResources); + } + } + + return null; + } } + Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/CoreBehaviorsTests.java URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/CoreBehaviorsTests.java?rev=1188655&r1=1188654&r2=1188655&view=diff ============================================================================== --- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/CoreBehaviorsTests.java (original) +++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/CoreBehaviorsTests.java Tue Oct 25 13:42:33 2011 @@ -1261,6 +1261,12 @@ public class CoreBehaviorsTests extends // load invocation order) assertEchoMixins("defaultbinding", "goodbye", 0, -1, -1, 1, false); assertText("mypropertyoutput5", "goodbye"); + + // binding to a published parameter + assertText("publishedparameter_before", "publishedvalue-before"); + assertText("p3-value", "publishedvaluetemporaryvalue"); + assertText("publishedparameter_after", "publishedvalue-after"); + assertText("mypropertyoutput6", "publishedvalue"); } /** @@ -1429,7 +1435,7 @@ public class CoreBehaviorsTests extends "Failure binding parameter field 'boundParameter' of mixin BindParameterNoSuchParameter:throwexception$echovalue2 (type org.apache.tapestry5.integration.app1.mixins.EchoValue2)", - "Containing component org.apache.tapestry5.corelib.components.Any does not contain a formal parameter matching any of boundParameter, value."); + "Containing component org.apache.tapestry5.corelib.components.Any does not contain a formal parameter or a published parameter matching any of boundParameter, value."); } @Test Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/BindParameterDemo.java URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/BindParameterDemo.java?rev=1188655&r1=1188654&r2=1188655&view=diff ============================================================================== --- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/BindParameterDemo.java (original) +++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/BindParameterDemo.java Tue Oct 25 13:42:33 2011 @@ -38,6 +38,9 @@ public class BindParameterDemo @Property private String myproperty5; + @Property + private String myproperty6; + @SetupRender void initMyprop() { @@ -46,5 +49,6 @@ public class BindParameterDemo myproperty3="hello"; myproperty4="supervalue"; myproperty5="goodbye"; + myproperty6="publishedvalue"; } } Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry5/integration/app1/pages/BindParameterDemo.tml URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry5/integration/app1/pages/BindParameterDemo.tml?rev=1188655&r1=1188654&r2=1188655&view=diff ============================================================================== --- tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry5/integration/app1/pages/BindParameterDemo.tml (original) +++ tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry5/integration/app1/pages/BindParameterDemo.tml Tue Oct 25 13:42:33 2011 @@ -22,6 +22,7 @@ <t:textfield t:id="testmixin3" value="myproperty3" t:mixins="echovalue3"/> <t:textfield t:id="multimixins" value="myproperty4" t:mixins="echovalue::before:*, echovalue2::before:echovalue3, echovalue3"/> <t:textonlyondisabledtextfield t:id="defaultbinding" value="myproperty5" disabled="true" t:mixins="echovalue"/> + <t:publish1 value="prop:myproperty6" t:mixins="echoValueWithId" id="literal:publishedparameter"/> </t:form> <div id="mypropertyoutput">${myproperty}</div> @@ -29,4 +30,5 @@ <div id="mypropertyoutput3">${myproperty3}</div> <div id="mypropertyoutput4">${myproperty4}</div> <div id="mypropertyoutput5">${myproperty5}</div> + <div id="mypropertyoutput6">${myproperty6}</div> </html>