Author: hlship
Date: Fri Jun 25 00:06:04 2010
New Revision: 957763

URL: http://svn.apache.org/viewvc?rev=957763&view=rev
Log:
TAP5-1190: Add @QueryParameterMapped annotation and supporting logic

Added:
    
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/annotations/QueryParameterMapped.java
   (with props)
    
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/QueryParameterMappedWorker.java
   (with props)
    
tapestry/tapestry5/trunk/tapestry-core/src/test/app1/QueryParameterMappedDemo.tml
    
tapestry/tapestry5/trunk/tapestry-core/src/test/groovy/org/apache/tapestry5/integration/
    
tapestry/tapestry5/trunk/tapestry-core/src/test/groovy/org/apache/tapestry5/integration/app1/
    
tapestry/tapestry5/trunk/tapestry-core/src/test/groovy/org/apache/tapestry5/integration/app1/QueryParameterMappedTests.groovy
    
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/QueryParameterMappedDemo.java
   (with props)
Modified:
    
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/annotations/Persist.java
    
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/annotations/QueryParameter.java
    
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/TapestryModule.java
    tapestry/tapestry5/trunk/tapestry-core/src/test/conf/testng-limited.xml
    
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/annotations/Persist.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/annotations/Persist.java?rev=957763&r1=957762&r2=957763&view=diff
==============================================================================
--- 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/annotations/Persist.java
 (original)
+++ 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/annotations/Persist.java
 Fri Jun 25 00:06:04 2010
@@ -1,4 +1,4 @@
-// Copyright 2006, 2007, 2008, 2009 The Apache Software Foundation
+// Copyright 2006, 2007, 2008, 2009, 2010 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.
@@ -40,6 +40,7 @@ import org.apache.tapestry5.ioc.annotati
  *
  * @see org.apache.tapestry5.services.MetaDataLocator
  * @see org.apache.tapestry5.PersistenceConstants
+ * @see QueryParameterMapped
  */
 @Target(FIELD)
 @Documented

Modified: 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/annotations/QueryParameter.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/annotations/QueryParameter.java?rev=957763&r1=957762&r2=957763&view=diff
==============================================================================
--- 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/annotations/QueryParameter.java
 (original)
+++ 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/annotations/QueryParameter.java
 Fri Jun 25 00:06:04 2010
@@ -24,6 +24,7 @@ import java.lang.annotation.Documented;
 import java.lang.annotation.Retention;
 import java.lang.annotation.Target;
 
+import org.apache.tapestry5.internal.transform.OnEventWorker;
 import org.apache.tapestry5.ioc.annotations.UseWith;
 import org.apache.tapestry5.ioc.services.TypeCoercer;
 import org.apache.tapestry5.services.Request;
@@ -31,12 +32,15 @@ import org.apache.tapestry5.services.Req
 /**
  * Annotation that may be placed on parameters of event handler methods.
  * Annotated parameters will be {...@linkplain Request#getParameter(String) 
extracted from the request},
- * then {...@linkplain TypeCoercer coerced} to the type of the parameter. Such 
parameters are seperate
+ * then {...@linkplain TypeCoercer coerced} to the type of the parameter. Such 
parameters are separate
  * from ordinary context parameters (extracted from the Request path). 
Typically, this is used when
  * client-side JavaScript adds a query parameter to a request to communicate 
some information from the client
  * side to the server side.
+ * <p>
+ * Individual fields may also be directly mapped to query parameters using the 
{...@link QueryParameterMapped} annotation.
  * 
  * @since 5.2.0
+ * @see OnEventWorker
  */
 @Target(
 { PARAMETER })

Added: 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/annotations/QueryParameterMapped.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/annotations/QueryParameterMapped.java?rev=957763&view=auto
==============================================================================
--- 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/annotations/QueryParameterMapped.java
 (added)
+++ 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/annotations/QueryParameterMapped.java
 Fri Jun 25 00:06:04 2010
@@ -0,0 +1,67 @@
+// Copyright 2010 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.annotations;
+
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+import static org.apache.tapestry5.ioc.annotations.AnnotationUseContext.PAGE;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import org.apache.tapestry5.ComponentResources;
+import org.apache.tapestry5.EventConstants;
+import org.apache.tapestry5.Link;
+import org.apache.tapestry5.ValueEncoder;
+import org.apache.tapestry5.ioc.annotations.UseWith;
+import org.apache.tapestry5.services.ValueEncoderSource;
+
+/**
+ * Marks a field of a page (not a component) as persistent within the URL. The 
field is mapped
+ * to a query parameter. When component event or page render links are 
generated for the page,
+ * additional values will be added to the {...@link Link} (via the {...@link 
EventConstants#DECORATE_COMPONENT_EVENT_LINK} or
+ * {...@link EventConstants#DECORATE_PAGE_RENDER_LINK} events).
+ * <p>
+ * Care must be taken that the query parameter name does not clash with a 
query parameter name generated for a form
+ * field.
+ * <p>
+ * The field may be of any type; a {...@link ValueEncoder} (from the {...@link 
ValueEncoderSource}) will be used to convert
+ * between client-side and server-side representations. Null values are not 
added as query parameters (just non-null).
+ * <p>
+ * When a page is activated, the mapped fields will receive their values 
before an {...@linkplain EventConstants#ACTIVATE
+ * activate} event handler method is invoked.
+ * <p>
+ * This annotation is an alternative to {...@link Persist}.
+ * <p>
+ * Fields annotated with QueryParameterMapped are <em>not</em> considered 
persistent (its a process parallel to the one
+ * related to the {...@link Persist} annotation). Invoking {...@link 
ComponentResources#discardPersistentFieldChanges()} will
+ * <em>not</em> affect annotated fields, only assigning them back to null will.
+ * 
+ * @see QueryParameter
+ */
+...@target(
+{ ElementType.FIELD })
+...@retention(RUNTIME)
+...@documented
+...@usewith(
+{ PAGE })
+public @interface QueryParameterMapped
+{
+    /** The name of the query parameter, which defaults to the name of the 
field. */
+    String value() default "";
+
+    // TODO: Attributes to limit it to just render links, or just component 
event links?
+}

Propchange: 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/annotations/QueryParameterMapped.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/QueryParameterMappedWorker.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/QueryParameterMappedWorker.java?rev=957763&view=auto
==============================================================================
--- 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/QueryParameterMappedWorker.java
 (added)
+++ 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/QueryParameterMappedWorker.java
 Fri Jun 25 00:06:04 2010
@@ -0,0 +1,163 @@
+// Copyright 2010 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.transform;
+
+import org.apache.tapestry5.EventConstants;
+import org.apache.tapestry5.Link;
+import org.apache.tapestry5.ValueEncoder;
+import org.apache.tapestry5.annotations.QueryParameterMapped;
+import org.apache.tapestry5.internal.services.ComponentClassCache;
+import org.apache.tapestry5.model.MutableComponentModel;
+import org.apache.tapestry5.runtime.Component;
+import org.apache.tapestry5.runtime.ComponentEvent;
+import org.apache.tapestry5.services.*;
+
+/**
+ * Hooks the activate event handler on the component (presumably, a page) to
+ * extract query parameters, and hooks the link decoration events to extract 
values
+ * and add them to the {...@link Link}.
+ * 
+ * @see QueryParameterMapped
+ * @since 5.2.0
+ */
+public class QueryParameterMappedWorker implements 
ComponentClassTransformWorker
+{
+    private final Request request;
+
+    private final ComponentClassCache classCache;
+
+    private final ValueEncoderSource valueEncoderSource;
+
+    interface EventHandler
+    {
+        void invoke(Component component, ComponentEvent event);
+    }
+
+    public QueryParameterMappedWorker(Request request, ComponentClassCache 
classCache,
+            ValueEncoderSource valueEncoderSource)
+    {
+        this.request = request;
+        this.classCache = classCache;
+        this.valueEncoderSource = valueEncoderSource;
+    }
+
+    public void transform(ClassTransformation transformation, 
MutableComponentModel model)
+    {
+        for (TransformField field : 
transformation.matchFieldsWithAnnotation(QueryParameterMapped.class))
+        {
+            mapFieldToQueryParameter(field, transformation, model);
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    private void mapFieldToQueryParameter(TransformField field, 
ClassTransformation transformation,
+            MutableComponentModel model)
+    {
+        QueryParameterMapped annotation = 
field.getAnnotation(QueryParameterMapped.class);
+
+        String parameterName = getParameterName(field, annotation);
+
+        TransformMethod dispatchMethod = 
transformation.getOrCreateMethod(TransformConstants.DISPATCH_COMPONENT_EVENT);
+
+        // Assumption: the field type is not one that's loaded by the 
component class loader, so it's safe
+        // to convert to a hard type during class transformation.
+
+        Class fieldType = classCache.forName(field.getType());
+
+        ValueEncoder encoder = valueEncoderSource.getValueEncoder(fieldType);
+
+        FieldAccess access = field.getAccess();
+
+        setValueFromInitializeEventHandler(access, parameterName, encoder, 
dispatchMethod, model);
+        decorateLinks(access, parameterName, encoder, dispatchMethod, model);
+    }
+
+    @SuppressWarnings("unchecked")
+    private void setValueFromInitializeEventHandler(final FieldAccess access, 
final String parameterName,
+            final ValueEncoder encoder, TransformMethod dispatchMethod, 
MutableComponentModel model)
+    {
+        EventHandler handler = new EventHandler()
+        {
+            public void invoke(Component component, ComponentEvent event)
+            {
+                String clientValue = request.getParameter(parameterName);
+
+                if (clientValue == null)
+                    return;
+
+                Object value = encoder.toValue(clientValue);
+
+                access.write(component, value);
+            }
+        };
+
+        add(dispatchMethod, model, EventConstants.ACTIVATE, handler);
+    }
+
+    @SuppressWarnings("unchecked")
+    private void decorateLinks(final FieldAccess access, final String 
parameterName, final ValueEncoder encoder,
+            TransformMethod dispatchMethod, MutableComponentModel model)
+    {
+        EventHandler handler = new EventHandler()
+        {
+            public void invoke(Component component, ComponentEvent event)
+            {
+                Object value = access.read(component);
+
+                if (value == null)
+                    return;
+
+                Link link = event.getEventContext().get(Link.class, 0);
+
+                String clientValue = encoder.toClient(value);
+
+                link.addParameter(parameterName, clientValue);
+            }
+        };
+
+        add(dispatchMethod, model, 
EventConstants.DECORATE_COMPONENT_EVENT_LINK, handler);
+        add(dispatchMethod, model, EventConstants.DECORATE_PAGE_RENDER_LINK, 
handler);
+    }
+
+    private void add(TransformMethod dispatchMethod, MutableComponentModel 
model, final String eventType,
+            final EventHandler handler)
+    {
+        dispatchMethod.addAdvice(new ComponentMethodAdvice()
+        {
+            public void advise(ComponentMethodInvocation invocation)
+            {
+                ComponentEvent event = (ComponentEvent) 
invocation.getParameter(0);
+
+                if (event.matches(eventType, "", 0))
+                {
+                    handler.invoke(invocation.getInstance(), event);
+                }
+                
+                invocation.proceed();
+            }
+        });
+
+        model.addEventHandler(eventType);
+    }
+
+    private String getParameterName(TransformField field, QueryParameterMapped 
annotation)
+    {
+        if (annotation.value().equals(""))
+            return field.getName();
+
+        return annotation.value();
+    }
+
+}

Propchange: 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/QueryParameterMappedWorker.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/TapestryModule.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/TapestryModule.java?rev=957763&r1=957762&r2=957763&view=diff
==============================================================================
--- 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/TapestryModule.java
 (original)
+++ 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/TapestryModule.java
 Fri Jun 25 00:06:04 2010
@@ -588,6 +588,8 @@ public final class TapestryModule
      * <dd>Checks for the {...@link PageReset} annotation
      * <dt>HeartbeatDeferred
      * <dd>Support for the {...@link HeartbeatDeferred} annotation
+     * <dt>QueryParameterMapped
+     * <dd>Support for the {...@link QueryParameterMapped} annotation
      * </dl>
      */
     public static void contributeComponentClassTransformWorker(
@@ -607,6 +609,7 @@ public final class TapestryModule
         configuration.add("MixinAfter", new MixinAfterWorker());
         configuration.add("Component", new ComponentWorker(resolver));
         configuration.add("Mixin", new MixinWorker(resolver));
+        configuration.addInstance("QueryParameterMapped", 
QueryParameterMappedWorker.class, "before:OnEvent");
         configuration.addInstance("OnEvent", OnEventWorker.class);
         configuration.add("SupportsInformalParameters", new 
SupportsInformalParametersWorker());
         configuration.addInstance("InjectPage", InjectPageWorker.class);

Added: 
tapestry/tapestry5/trunk/tapestry-core/src/test/app1/QueryParameterMappedDemo.tml
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/app1/QueryParameterMappedDemo.tml?rev=957763&view=auto
==============================================================================
--- 
tapestry/tapestry5/trunk/tapestry-core/src/test/app1/QueryParameterMappedDemo.tml
 (added)
+++ 
tapestry/tapestry5/trunk/tapestry-core/src/test/app1/QueryParameterMappedDemo.tml
 Fri Jun 25 00:06:04 2010
@@ -0,0 +1,25 @@
+<html t:type="Border" 
xmlns:t="http://tapestry.apache.org/schema/tapestry_5_0_0.xsd";>
+
+  <h1>@QueryParameterMapped Demo</h1>
+
+  <dl>
+    <dt>Click count:</dt>
+    <dd id="clickCount">${clickCount}</dd>
+    <dt>Click count set:</dt>
+    <dd id="clickCountSet">${clickCountSet}</dd>
+    <dt>Message:</dt>
+    <dd id="message">${message}</dd>
+  </dl>
+
+  <ul>
+    <li>
+      <t:actionlink t:id="increment">increment count</t:actionlink>
+    </li>
+    <li>
+      <t:actionlink t:id="setMessage">set message</t:actionlink>
+    </li>
+    <li>
+      <t:actionlink t:id="reset">reset</t:actionlink>
+    </li>
+  </ul>
+</html>
\ No newline at end of file

Modified: 
tapestry/tapestry5/trunk/tapestry-core/src/test/conf/testng-limited.xml
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/conf/testng-limited.xml?rev=957763&r1=957762&r2=957763&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/conf/testng-limited.xml 
(original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/conf/testng-limited.xml Fri 
Jun 25 00:06:04 2010
@@ -11,7 +11,7 @@
       <class name="org.apache.tapestry5.test.SeleniumLauncher"/>
 
       <!--  Modify classes below as needed. -->
-      <class name="org.apache.tapestry5.integration.app1.AjaxTests"/>
+      <class 
name="org.apache.tapestry5.integration.app1.QueryParameterMappedTests"/>
 
     </classes>
   </test>

Added: 
tapestry/tapestry5/trunk/tapestry-core/src/test/groovy/org/apache/tapestry5/integration/app1/QueryParameterMappedTests.groovy
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/groovy/org/apache/tapestry5/integration/app1/QueryParameterMappedTests.groovy?rev=957763&view=auto
==============================================================================
--- 
tapestry/tapestry5/trunk/tapestry-core/src/test/groovy/org/apache/tapestry5/integration/app1/QueryParameterMappedTests.groovy
 (added)
+++ 
tapestry/tapestry5/trunk/tapestry-core/src/test/groovy/org/apache/tapestry5/integration/app1/QueryParameterMappedTests.groovy
 Fri Jun 25 00:06:04 2010
@@ -0,0 +1,42 @@
+// Copyright 2010 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;
+
+import org.apache.tapestry5.integration.TapestryCoreTestCase 
+import org.testng.annotations.Test 
+
+class QueryParameterMappedTests extends TapestryCoreTestCase
+{
+    @Test
+    void basic_links()
+    {
+        clickThru "@QueryParameterMapped Demo"
+        
+        assertText("clickCount", "")
+        assertText("clickCountSet", "false")
+        assertText("message", "")
+        
+        clickAndWait "link=increment count"
+        
+        assertText("clickCount", "1")
+        assertText("clickCountSet", "true")
+        
+        clickAndWait "link=set message"
+        
+        assertText("clickCount", "1")
+        assertText("clickCountSet", "true")
+        assertText("message", "Link clicked!")        
+    }
+}

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=957763&r1=957762&r2=957763&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
 Fri Jun 25 00:06:04 2010
@@ -67,6 +67,9 @@ public class Index
     private static final List<Item> ITEMS = CollectionFactory
             .newList(
 
+                    new Item("QueryParameterMappedDemo", 
"@QueryParameterMapped Demo",
+                            "Use of @QueryParameterMapped to encode page state 
into query parameters"),
+                            
                     new Item("LibraryMessagesDemo", "Library Messages Demo",
                             "Demo ability to contribute additional message 
catalog resources to the application global catalog."),
 

Added: 
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/QueryParameterMappedDemo.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/QueryParameterMappedDemo.java?rev=957763&view=auto
==============================================================================
--- 
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/QueryParameterMappedDemo.java
 (added)
+++ 
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/QueryParameterMappedDemo.java
 Fri Jun 25 00:06:04 2010
@@ -0,0 +1,54 @@
+// Copyright 2010 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;
+
+import org.apache.tapestry5.annotations.Property;
+import org.apache.tapestry5.annotations.QueryParameterMapped;
+
+public class QueryParameterMappedDemo
+{
+    
+    @Property
+    private boolean clickCountSet;
+    
+    @Property
+    @QueryParameterMapped
+    private Integer clickCount;
+
+    @Property
+    @QueryParameterMapped
+    private String message;
+
+    void onActivate()
+    {
+        clickCountSet = clickCount != null;
+    }
+    
+    void onActionFromIncrement()
+    {
+        clickCount = clickCount == null ? 1 : clickCount + 1;
+    }
+
+    void onActionFromSetMessage()
+    {
+        message = "Link clicked!";
+    }
+
+    void onActionFromReset()
+    {
+        clickCount = null;
+        message = null;
+    }
+}

Propchange: 
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/QueryParameterMappedDemo.java
------------------------------------------------------------------------------
    svn:eol-style = native


Reply via email to