Hi Thiago!

Nice feature! Simple but very useful. Thanks you.

Just a thought. What about multiple contributions to the ComponentReplacer
for the same page/component or mixin ?
In a next improvement, it could be very handy to allow some kind of ordered
configuration.

Nourredine.


2014-06-16 3:18 GMT+02:00 <thiag...@apache.org>:

> Repository: tapestry-5
> Updated Branches:
>   refs/heads/master 9cd156f37 -> e6a83e031
>
>
> TAP5-1611 : out-of-the-box way in Tapestry for replacing components
>
>
> Project: http://git-wip-us.apache.org/repos/asf/tapestry-5/repo
> Commit: http://git-wip-us.apache.org/repos/asf/tapestry-5/commit/e6a83e03
> Tree: http://git-wip-us.apache.org/repos/asf/tapestry-5/tree/e6a83e03
> Diff: http://git-wip-us.apache.org/repos/asf/tapestry-5/diff/e6a83e03
>
> Branch: refs/heads/master
> Commit: e6a83e031ad65eac99614f108392d06a8ff6c8f9
> Parents: 9cd156f
> Author: Thiago H. de Paula Figueiredo <thiag...@apache.org>
> Authored: Sun Jun 15 22:17:47 2014 -0300
> Committer: Thiago H. de Paula Figueiredo <thiag...@apache.org>
> Committed: Sun Jun 15 22:17:47 2014 -0300
>
> ----------------------------------------------------------------------
>  .../internal/ComponentReplacerImpl.java         | 89 ++++++++++++++++++++
>  .../tapestry5/modules/TapestryModule.java       | 32 +++++++
>  .../tapestry5/services/ComponentReplacer.java   | 51 +++++++++++
>  tapestry-core/src/test/app3/Login.tml           |  6 ++
>  tapestry-core/src/test/app3/OverridePage.tml    | 12 +++
>  .../src/test/app3/OverridePageAtComponent.tml   | 12 +++
>  tapestry-core/src/test/app3/OverridenPage.tml   |  8 ++
>  .../app3/AdditionalIntegrationTests.java        | 21 +++++
>  .../app3/components/OverrideComponent.java      | 24 ++++++
>  .../app3/components/OverridenComponent.java     | 24 ++++++
>  .../integration/app3/mixins/OverrideMixin.java  | 32 +++++++
>  .../integration/app3/mixins/OverridenMixin.java | 30 +++++++
>  .../integration/app3/pages/OverridePage.java    | 18 ++++
>  .../app3/pages/OverridePageAtComponent.java     | 35 ++++++++
>  .../integration/app3/pages/OverridenPage.java   | 18 ++++
>  .../integration/app3/services/AppModule.java    | 16 +++-
>  16 files changed, 427 insertions(+), 1 deletion(-)
> ----------------------------------------------------------------------
>
>
>
> http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/e6a83e03/tapestry-core/src/main/java/org/apache/tapestry5/internal/ComponentReplacerImpl.java
> ----------------------------------------------------------------------
> diff --git
> a/tapestry-core/src/main/java/org/apache/tapestry5/internal/ComponentReplacerImpl.java
> b/tapestry-core/src/main/java/org/apache/tapestry5/internal/ComponentReplacerImpl.java
> new file mode 100644
> index 0000000..8d7fc75
> --- /dev/null
> +++
> b/tapestry-core/src/main/java/org/apache/tapestry5/internal/ComponentReplacerImpl.java
> @@ -0,0 +1,89 @@
> +// Copyright 2014 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.internal;
> +
> +import java.util.ArrayList;
> +import java.util.Collections;
> +import java.util.HashMap;
> +import java.util.List;
> +import java.util.Map;
> +import java.util.Map.Entry;
> +import java.util.Set;
> +
> +import org.apache.tapestry5.ioc.util.CaseInsensitiveMap;
> +import org.apache.tapestry5.services.ComponentReplacer;
> +import org.slf4j.Logger;
> +
> +public class ComponentReplacerImpl implements ComponentReplacer
> +{
> +
> +    final Logger logger;
> +    final private Map<Class, Class> replacements;
> +    final private Map<String, Class> nameToClass;
> +
> +    @SuppressWarnings("rawtypes")
> +    public ComponentReplacerImpl(Map<Class, Class> contributions, Logger
> logger)
> +    {
> +
> +        this.logger = logger;
> +        this.replacements = Collections.unmodifiableMap(contributions);
> +        Map<String, Class> nameToClass = new HashMap<String, Class>();
> +
> +        int maxLength = 0;
> +
> +        for (Class<?> clasz : contributions.keySet())
> +        {
> +
> +            final String name = clasz.getName();
> +            if (name.length() > maxLength) {
> +                maxLength = name.length();
> +            }
> +            nameToClass.put(name, contributions.get(clasz));
> +
> +        }
> +
> +        this.nameToClass = Collections.unmodifiableMap(nameToClass);
> +
> +        if (replacements.size() > 0 && logger.isInfoEnabled())
> +        {
> +
> +            StringBuilder builder = new StringBuilder(1000);
> +            final String format = "%" + maxLength + "s: %s\n";
> +            builder.append("Component replacements (including components,
> pages and mixins):\n");
> +            List<String> names = new
> ArrayList<String>(nameToClass.keySet());
> +            Collections.sort(names);
> +
> +            for (String name : names) {
> +                builder.append(String.format(format, name,
> nameToClass.get(name).getName()));
> +            }
> +
> +            logger.info(builder.toString());
> +
> +        }
> +
> +    }
> +
> +    @Override
> +    public Map<Class, Class> getReplacements()
> +    {
> +        return replacements;
> +    }
> +
> +    @Override
> +    public Class getReplacement(String className)
> +    {
> +        return nameToClass.get(className);
> +    }
> +
> +}
>
>
> http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/e6a83e03/tapestry-core/src/main/java/org/apache/tapestry5/modules/TapestryModule.java
> ----------------------------------------------------------------------
> diff --git
> a/tapestry-core/src/main/java/org/apache/tapestry5/modules/TapestryModule.java
> b/tapestry-core/src/main/java/org/apache/tapestry5/modules/TapestryModule.java
> index 63c114b..1a08540 100644
> ---
> a/tapestry-core/src/main/java/org/apache/tapestry5/modules/TapestryModule.java
> +++
> b/tapestry-core/src/main/java/org/apache/tapestry5/modules/TapestryModule.java
> @@ -65,7 +65,9 @@ import org.apache.tapestry5.ioc.util.AvailableValues;
>  import org.apache.tapestry5.ioc.util.StrategyRegistry;
>  import org.apache.tapestry5.json.JSONArray;
>  import org.apache.tapestry5.json.JSONObject;
> +import org.apache.tapestry5.plastic.MethodAdvice;
>  import org.apache.tapestry5.plastic.MethodDescription;
> +import org.apache.tapestry5.plastic.MethodInvocation;
>  import org.apache.tapestry5.runtime.Component;
>  import org.apache.tapestry5.runtime.ComponentResourcesAware;
>  import org.apache.tapestry5.runtime.RenderCommand;
> @@ -95,6 +97,7 @@ import org.slf4j.Logger;
>  import javax.servlet.ServletContext;
>  import javax.servlet.http.HttpServletRequest;
>  import javax.servlet.http.HttpServletResponse;
> +
>  import java.io.IOException;
>  import java.lang.annotation.Annotation;
>  import java.math.BigDecimal;
> @@ -372,6 +375,7 @@ public final class TapestryModule
>          binder.bind(DateUtilities.class, DateUtilitiesImpl.class);
>          binder.bind(PartialTemplateRenderer.class,
> PartialTemplateRendererImpl.class);
>
>  binder.bind(org.apache.tapestry5.services.exceptions.ExceptionReporter.class,
> ExceptionReporterImpl.class);
> +        binder.bind(ComponentReplacer.class,
> ComponentReplacerImpl.class).eagerLoad();
>      }
>
>      //
> ========================================================================
> @@ -2660,4 +2664,32 @@ public final class TapestryModule
>      {
>          return strategyBuilder.build(ValueLabelProvider.class,
> configuration);
>      }
> +
> +    @Advise(serviceInterface = ComponentInstantiatorSource.class)
> +    public static void componentReplacer(MethodAdviceReceiver
> methodAdviceReceiver,
> +          final ComponentReplacer componentReplacer) throws
> NoSuchMethodException, SecurityException {
> +
> +        if (componentReplacer.getReplacements().size() > 0) {
> +
> +            MethodAdvice advice = new MethodAdvice()
> +            {
> +                @Override
> +                public void advise(MethodInvocation invocation)
> +                {
> +                    String className = (String)
> invocation.getParameter(0);
> +                    final Class<?> replacement =
> componentReplacer.getReplacement(className);
> +                    if (replacement != null)
> +                    {
> +                        invocation.setParameter(0, replacement.getName());
> +                    }
> +                    invocation.proceed();
> +                }
> +            };
> +
> +            methodAdviceReceiver.adviseMethod(
> +
>  ComponentInstantiatorSource.class.getMethod("getInstantiator",
> String.class), advice);
> +
> +        }
> +    }
> +
>  }
>
>
> http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/e6a83e03/tapestry-core/src/main/java/org/apache/tapestry5/services/ComponentReplacer.java
> ----------------------------------------------------------------------
> diff --git
> a/tapestry-core/src/main/java/org/apache/tapestry5/services/ComponentReplacer.java
> b/tapestry-core/src/main/java/org/apache/tapestry5/services/ComponentReplacer.java
> new file mode 100644
> index 0000000..375a8c6
> --- /dev/null
> +++
> b/tapestry-core/src/main/java/org/apache/tapestry5/services/ComponentReplacer.java
> @@ -0,0 +1,51 @@
> +// Copyright 2014 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.services;
> +
> +import java.util.Map;
> +
> +import org.apache.tapestry5.ioc.MethodAdviceReceiver;
> +import org.apache.tapestry5.ioc.annotations.UsesMappedConfiguration;
> +
> +/**
> + * Service that allows replacing one component, page or mixin class by
> another without changing the sources.
> + * This service shouldn't be used directly: it's not an internal service
> just because it receives
> + * contributions.
> + *
> + * Contributions to it are mapped: the key is the component, page or
> mixin class to be
> + * replaced, the value is the replacement.
> + *
> + * @since 5.4
> + * @see ComponentClassResolver.
> + */
> +@UsesMappedConfiguration(key = Class.class, value = Class.class)
> +public interface ComponentReplacer
> +{
> +
> +    /**
> +     * Returns an immutable map of replacements. Internal use only.
> +     *
> +     * @return a {@link Map}.
> +     */
> +    Map<Class, Class> getReplacements();
> +
> +    /**
> +     * Returns the replacement for a class given its name.
> +     * @param className the fully qualified class name.
> +     * @return a {@link Class} or null.
> +     */
> +    Class getReplacement(String className);
> +
> +}
>
>
> http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/e6a83e03/tapestry-core/src/test/app3/Login.tml
> ----------------------------------------------------------------------
> diff --git a/tapestry-core/src/test/app3/Login.tml
> b/tapestry-core/src/test/app3/Login.tml
> index 9fba45c..6937cd2 100644
> --- a/tapestry-core/src/test/app3/Login.tml
> +++ b/tapestry-core/src/test/app3/Login.tml
> @@ -22,6 +22,12 @@
>              <li>
>                  <t:pagelink
> page="BeanEditorWithOverridenCssClassesDemo">BeanEditor with overriden CSS
> classes demo</t:pagelink>
>              </li>
> +            <li>
> +                <t:pagelink page="OverridenPage">ComponentReplacer
> demo</t:pagelink>
> +            </li>
> +            <li>
> +                <t:pagelink
> page="OverridePageAtComponent">ComponentReplacer demo (using @Component to
> declare component instances)</t:pagelink>
> +            </li>
>          </ul>
>
>      </body>
>
>
> http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/e6a83e03/tapestry-core/src/test/app3/OverridePage.tml
> ----------------------------------------------------------------------
> diff --git a/tapestry-core/src/test/app3/OverridePage.tml
> b/tapestry-core/src/test/app3/OverridePage.tml
> new file mode 100644
> index 0000000..cddb3e3
> --- /dev/null
> +++ b/tapestry-core/src/test/app3/OverridePage.tml
> @@ -0,0 +1,12 @@
> +<html xmlns:t="http://tapestry.apache.org/schema/tapestry_5_0_0.xsd";>
> +    <head>
> +        <title>Override Page</title>
> +    </head>
> +    <body>
> +        <h1>Override Page</h1>
> +        <p>
> +               Link with mixin <t:pagelink t:page="Index"
> t:mixins="OverridenMixin">Index</t:pagelink>
> +        </p>
> +        <t:overridenComponent/>
> +    </body>
> +</html>
> \ No newline at end of file
>
>
> http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/e6a83e03/tapestry-core/src/test/app3/OverridePageAtComponent.tml
> ----------------------------------------------------------------------
> diff --git a/tapestry-core/src/test/app3/OverridePageAtComponent.tml
> b/tapestry-core/src/test/app3/OverridePageAtComponent.tml
> new file mode 100644
> index 0000000..d10610b
> --- /dev/null
> +++ b/tapestry-core/src/test/app3/OverridePageAtComponent.tml
> @@ -0,0 +1,12 @@
> +<html xmlns:t="http://tapestry.apache.org/schema/tapestry_5_0_0.xsd";>
> +    <head>
> +        <title>Override Page</title>
> +    </head>
> +    <body>
> +        <h1>Override Page with @Component</h1>
> +        <p>
> +               Link with mixin <a t:id="link" href="#">Index</a>
> +        </p>
> +        <div t:id="overridenComponent"/>
> +    </body>
> +</html>
> \ No newline at end of file
>
>
> http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/e6a83e03/tapestry-core/src/test/app3/OverridenPage.tml
> ----------------------------------------------------------------------
> diff --git a/tapestry-core/src/test/app3/OverridenPage.tml
> b/tapestry-core/src/test/app3/OverridenPage.tml
> new file mode 100644
> index 0000000..cf9b1a7
> --- /dev/null
> +++ b/tapestry-core/src/test/app3/OverridenPage.tml
> @@ -0,0 +1,8 @@
> +<html xmlns:t="http://tapestry.apache.org/schema/tapestry_5_0_0.xsd";>
> +    <head>
> +        <title>Overriden</title>
> +    </head>
> +    <body>
> +        <h1>Overriden</h1>
> +    </body>
> +</html>
> \ No newline at end of file
>
>
> http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/e6a83e03/tapestry-core/src/test/java/org/apache/tapestry5/integration/app3/AdditionalIntegrationTests.java
> ----------------------------------------------------------------------
> diff --git
> a/tapestry-core/src/test/java/org/apache/tapestry5/integration/app3/AdditionalIntegrationTests.java
> b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app3/AdditionalIntegrationTests.java
> index 8e03e34..774df44 100644
> ---
> a/tapestry-core/src/test/java/org/apache/tapestry5/integration/app3/AdditionalIntegrationTests.java
> +++
> b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app3/AdditionalIntegrationTests.java
> @@ -15,12 +15,14 @@
>  package org.apache.tapestry5.integration.app3;
>
>  import org.apache.tapestry5.integration.TapestryCoreTestCase;
> +import org.apache.tapestry5.test.TapestryTestConfiguration;
>  import org.testng.annotations.Test;
>
>  /**
>   * Additional integration tests that do not fit with the main group due
> to the need for special
>   * configuration.
>   */
> +@TapestryTestConfiguration(webAppFolder = "src/test/app3")
>  public class AdditionalIntegrationTests extends TapestryCoreTestCase
>  {
>      /**
> @@ -88,4 +90,23 @@ public class AdditionalIntegrationTests extends
> TapestryCoreTestCase
>
>          assertTextPresent("Communication with the server failed:
> Server-side exception.");
>      }
> +
> +    // TAP5-1611
> +    @Test
> +    public void component_replacer()
> +    {
> +
> +        final String[] pageNames = {"ComponentReplacer demo",
> "ComponentReplacer demo (using @Component to declare component instances)"};
> +        for (String pageName : pageNames)
> +        {
> +            openLinks(pageName);
> +
> +            assertTrue(isElementPresent("overrideMixin"));
> +            assertFalse(isElementPresent("overridenMixin"));
> +            assertTrue(isElementPresent("overrideComponent"));
> +            assertFalse(isElementPresent("overridenComponent"));
> +        }
> +
> +    }
> +
>  }
>
>
> http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/e6a83e03/tapestry-core/src/test/java/org/apache/tapestry5/integration/app3/components/OverrideComponent.java
> ----------------------------------------------------------------------
> diff --git
> a/tapestry-core/src/test/java/org/apache/tapestry5/integration/app3/components/OverrideComponent.java
> b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app3/components/OverrideComponent.java
> new file mode 100644
> index 0000000..a43a745
> --- /dev/null
> +++
> b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app3/components/OverrideComponent.java
> @@ -0,0 +1,24 @@
> +// Copyright 2014 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.app3.components;
> +
> +import org.apache.tapestry5.MarkupWriter;
> +
> +public class OverrideComponent
> +{
> +    void beginRender(MarkupWriter writer) {
> +        writer.element("div", "id",
> "overrideComponent").element("p").text("Override component");
> +        writer.end(); // div
> +    }
> +}
>
>
> http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/e6a83e03/tapestry-core/src/test/java/org/apache/tapestry5/integration/app3/components/OverridenComponent.java
> ----------------------------------------------------------------------
> diff --git
> a/tapestry-core/src/test/java/org/apache/tapestry5/integration/app3/components/OverridenComponent.java
> b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app3/components/OverridenComponent.java
> new file mode 100644
> index 0000000..01f5130
> --- /dev/null
> +++
> b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app3/components/OverridenComponent.java
> @@ -0,0 +1,24 @@
> +// Copyright 2014 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.app3.components;
> +
> +import org.apache.tapestry5.MarkupWriter;
> +
> +public class OverridenComponent
> +{
> +    void beginRender(MarkupWriter writer) {
> +        writer.element("div", "id",
> "overridenComponent").element("p").text("Overriden component");
> +        writer.end(); // div
> +    }
> +}
>
>
> http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/e6a83e03/tapestry-core/src/test/java/org/apache/tapestry5/integration/app3/mixins/OverrideMixin.java
> ----------------------------------------------------------------------
> diff --git
> a/tapestry-core/src/test/java/org/apache/tapestry5/integration/app3/mixins/OverrideMixin.java
> b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app3/mixins/OverrideMixin.java
> new file mode 100644
> index 0000000..5614178
> --- /dev/null
> +++
> b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app3/mixins/OverrideMixin.java
> @@ -0,0 +1,32 @@
> +// Copyright 2014 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.app3.mixins;
> +
> +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.dom.Element;
> +
> +@MixinAfter
> +public class OverrideMixin
> +{
> +    @InjectContainer
> +    private ClientElement clientElement;
> +
> +    void afterRender(MarkupWriter writer) {
> +        final Element element =
> writer.getDocument().getElementById(clientElement.getClientId());
> +        element.element("span", "id", "overrideMixin").text(" [Override
> mixin]");
> +    }
> +}
>
>
> http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/e6a83e03/tapestry-core/src/test/java/org/apache/tapestry5/integration/app3/mixins/OverridenMixin.java
> ----------------------------------------------------------------------
> diff --git
> a/tapestry-core/src/test/java/org/apache/tapestry5/integration/app3/mixins/OverridenMixin.java
> b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app3/mixins/OverridenMixin.java
> new file mode 100644
> index 0000000..50ea142
> --- /dev/null
> +++
> b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app3/mixins/OverridenMixin.java
> @@ -0,0 +1,30 @@
> +// Copyright 2014 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.app3.mixins;
> +
> +import org.apache.tapestry5.ClientElement;
> +import org.apache.tapestry5.MarkupWriter;
> +import org.apache.tapestry5.annotations.InjectContainer;
> +import org.apache.tapestry5.dom.Element;
> +
> +public class OverridenMixin
> +{
> +    @InjectContainer
> +    private ClientElement clientElement;
> +
> +    void afterRender(MarkupWriter writer) {
> +        final Element element =
> writer.getDocument().getElementById(clientElement.getClientId());
> +        element.element("span", "id", "overridenMixin").text(" [Overriden
> mixin]");
> +    }
> +}
> \ No newline at end of file
>
>
> http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/e6a83e03/tapestry-core/src/test/java/org/apache/tapestry5/integration/app3/pages/OverridePage.java
> ----------------------------------------------------------------------
> diff --git
> a/tapestry-core/src/test/java/org/apache/tapestry5/integration/app3/pages/OverridePage.java
> b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app3/pages/OverridePage.java
> new file mode 100644
> index 0000000..7f803b7
> --- /dev/null
> +++
> b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app3/pages/OverridePage.java
> @@ -0,0 +1,18 @@
> +// Copyright 2014 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.app3.pages;
> +
> +public class OverridePage
> +{
> +}
>
>
> http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/e6a83e03/tapestry-core/src/test/java/org/apache/tapestry5/integration/app3/pages/OverridePageAtComponent.java
> ----------------------------------------------------------------------
> diff --git
> a/tapestry-core/src/test/java/org/apache/tapestry5/integration/app3/pages/OverridePageAtComponent.java
> b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app3/pages/OverridePageAtComponent.java
> new file mode 100644
> index 0000000..33ba903
> --- /dev/null
> +++
> b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app3/pages/OverridePageAtComponent.java
> @@ -0,0 +1,35 @@
> +// Copyright 2014 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.app3.pages;
> +
> +import org.apache.tapestry5.annotations.Component;
> +import org.apache.tapestry5.annotations.MixinClasses;
> +import org.apache.tapestry5.corelib.components.PageLink;
> +import
> org.apache.tapestry5.integration.app3.components.OverridenComponent;
> +import org.apache.tapestry5.integration.app3.mixins.OverridenMixin;
> +
> +/**
> + * Same as OverridePage, but using @Component to declare components.
> + */
> +public class OverridePageAtComponent
> +{
> +
> +    @Component(id = "link", parameters={"page=Index"})
> +    @MixinClasses(OverridenMixin.class)
> +    private PageLink pageLink;
> +
> +    @Component
> +    private OverridenComponent overridenComponent;
> +
> +}
>
>
> http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/e6a83e03/tapestry-core/src/test/java/org/apache/tapestry5/integration/app3/pages/OverridenPage.java
> ----------------------------------------------------------------------
> diff --git
> a/tapestry-core/src/test/java/org/apache/tapestry5/integration/app3/pages/OverridenPage.java
> b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app3/pages/OverridenPage.java
> new file mode 100644
> index 0000000..6a03091
> --- /dev/null
> +++
> b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app3/pages/OverridenPage.java
> @@ -0,0 +1,18 @@
> +// Copyright 2014 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.app3.pages;
> +
> +public class OverridenPage
> +{
> +}
>
>
> http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/e6a83e03/tapestry-core/src/test/java/org/apache/tapestry5/integration/app3/services/AppModule.java
> ----------------------------------------------------------------------
> diff --git
> a/tapestry-core/src/test/java/org/apache/tapestry5/integration/app3/services/AppModule.java
> b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app3/services/AppModule.java
> index 2f4a73d..58648bd 100644
> ---
> a/tapestry-core/src/test/java/org/apache/tapestry5/integration/app3/services/AppModule.java
> +++
> b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app3/services/AppModule.java
> @@ -15,10 +15,17 @@
>  package org.apache.tapestry5.integration.app3.services;
>
>  import org.apache.tapestry5.SymbolConstants;
> +import org.apache.tapestry5.integration.app3.components.OverrideComponent;
> +import
> org.apache.tapestry5.integration.app3.components.OverridenComponent;
> +import org.apache.tapestry5.integration.app3.mixins.OverrideMixin;
> +import org.apache.tapestry5.integration.app3.mixins.OverridenMixin;
> +import org.apache.tapestry5.integration.app3.pages.OverridePage;
> +import org.apache.tapestry5.integration.app3.pages.OverridenPage;
>  import org.apache.tapestry5.ioc.Configuration;
>  import org.apache.tapestry5.ioc.MappedConfiguration;
>  import org.apache.tapestry5.ioc.OrderedConfiguration;
>  import org.apache.tapestry5.ioc.annotations.Contribute;
> +import org.apache.tapestry5.services.ComponentReplacer;
>  import org.apache.tapestry5.services.DisplayBlockContribution;
>  import org.apache.tapestry5.services.Request;
>  import org.apache.tapestry5.services.compatibility.Compatibility;
> @@ -58,7 +65,7 @@ public class AppModule
>          configuration.add(SymbolConstants.FORM_FIELD_CSS_CLASS,
> FORM_FIELD_CSS_CLASS_VALUE);
>
>      }
> -
> +
>      @Contribute(Compatibility.class)
>      public static void
> disableBackwardsCompatibleFeatures(MappedConfiguration<Trait, Boolean>
> configuration)
>      {
> @@ -78,5 +85,12 @@ public class AppModule
>              }
>          }, "before:*");
>      }
> +
> +    @Contribute(ComponentReplacer.class)
> +    public static void
> overridePageAndComponentAndMixin(MappedConfiguration<Class, Class>
> configuration) {
> +        configuration.add(OverridenPage.class, OverridePage.class);
> +        configuration.add(OverridenComponent.class,
> OverrideComponent.class);
> +        configuration.add(OverridenMixin.class, OverrideMixin.class);
> +    }
>
>  }
>
>

Reply via email to