Author: dadams
Date: Sat Mar  8 12:53:25 2008
New Revision: 635085

URL: http://svn.apache.org/viewvc?rev=635085&view=rev
Log:
TAPESTRY-2244: Add @Once annotation for caching method values

Added:
    
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/annotations/Once.java
    
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/transform/OnceWorker.java
    
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app1/pages/OncePage.java
    
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app1/pages/OncePage2.java
    
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/transform/OnceWorkerTest.java
    
tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/integration/app1/pages/OncePage.tml
Modified:
    
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/corelib/components/Unless.java
    
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/transform/TransformMessages.java
    
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/TapestryModule.java
    
tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/internal/transform/TransformStrings.properties
    tapestry/tapestry5/trunk/tapestry-core/src/site/apt/index.apt
    
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/IntegrationTests.java
    
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app1/pages/Start.java

Added: 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/annotations/Once.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/annotations/Once.java?rev=635085&view=auto
==============================================================================
--- 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/annotations/Once.java
 (added)
+++ 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/annotations/Once.java
 Sat Mar  8 12:53:25 2008
@@ -0,0 +1,41 @@
+// Copyright 2006, 2007, 2008 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.tapestry.annotations;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/** Indicates that a method should only be evaluated once and the result 
cached.
+ * All further calls to the method will return the cached result. Note that 
this
+ * annotation is inheritence-safe; if a subclass calls a superclass method 
that 
+ * has @Once then the value the subclass method gets is the cached value. 
+ * <p>
+ * The watch parameter can be passed a binding expression
+ * which will be evaluated each time the method is called. The method will then
+ * only be executed the first time it is called and after that only when the
+ * value of the binding changes. This can be used, for instance, to have the
+ * method only evaluated once per iteration of a loop by setting watch to
+ * the value or index of the loop.
+ */
[EMAIL PROTECTED](ElementType.METHOD)
[EMAIL PROTECTED](RetentionPolicy.RUNTIME)
[EMAIL PROTECTED]
+public @interface Once {
+       /** The optional binding to watch (default binding prefix is "prop") */
+       String watch() default "";
+}

Modified: 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/corelib/components/Unless.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/corelib/components/Unless.java?rev=635085&r1=635084&r2=635085&view=diff
==============================================================================
--- 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/corelib/components/Unless.java
 (original)
+++ 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/corelib/components/Unless.java
 Sat Mar  8 12:53:25 2008
@@ -14,9 +14,8 @@
 
 package org.apache.tapestry.corelib.components;
 
-import org.apache.tapestry.annotations.Parameter;
-import org.apache.tapestry.annotations.Component;
 import org.apache.tapestry.Block;
+import org.apache.tapestry.annotations.Parameter;
 
 /**
  * A close relative of the [EMAIL PROTECTED] 
org.apache.tapestry.corelib.components.If} component that inverts the meaning 
of its

Added: 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/transform/OnceWorker.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/transform/OnceWorker.java?rev=635085&view=auto
==============================================================================
--- 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/transform/OnceWorker.java
 (added)
+++ 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/transform/OnceWorker.java
 Sat Mar  8 12:53:25 2008
@@ -0,0 +1,128 @@
+// Copyright 2006, 2007, 2008 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.tapestry.internal.transform;
+
+import static java.lang.reflect.Modifier.PRIVATE;
+
+import java.util.List;
+
+import org.apache.tapestry.Binding;
+import org.apache.tapestry.TapestryConstants;
+import org.apache.tapestry.annotations.Once;
+import org.apache.tapestry.ioc.util.BodyBuilder;
+import org.apache.tapestry.model.MutableComponentModel;
+import org.apache.tapestry.services.BindingSource;
+import org.apache.tapestry.services.ClassTransformation;
+import org.apache.tapestry.services.ComponentClassTransformWorker;
+import org.apache.tapestry.services.TransformConstants;
+import org.apache.tapestry.services.TransformMethodSignature;
+import org.apache.tapestry.services.TransformUtils;
+
+/** Caches method return values for methods annotated with [EMAIL PROTECTED] 
Once}. */
+public class OnceWorker implements ComponentClassTransformWorker {
+       private final BindingSource _bindingSource;
+       
+       public OnceWorker(BindingSource bindingSource) {
+               super();
+               this._bindingSource = bindingSource;
+       }
+
+       public void transform(ClassTransformation transformation, 
MutableComponentModel model) {
+               List<TransformMethodSignature> methods = 
transformation.findMethodsWithAnnotation(Once.class);
+               if (methods.isEmpty())
+                       return;
+               
+               for(TransformMethodSignature method : methods) {
+                       if (method.getReturnType().equals("void"))
+                               throw new 
IllegalArgumentException(TransformMessages.onceMethodMustHaveReturnValue(method));
+       
+                       if (method.getParameterTypes().length != 0)
+                               throw new 
IllegalArgumentException(TransformMessages.onceMethodsHaveNoParameters(method));
+                       
+                       String propertyName = method.getMethodName();
+                                               
+                       // add a property to store whether or not the method 
has been called
+                       String fieldName = transformation.addField(PRIVATE, 
method.getReturnType(), propertyName);
+                       String calledField = transformation.addField(PRIVATE, 
"boolean", fieldName + "$called");
+       
+                       Once once = transformation.getMethodAnnotation(method, 
Once.class);
+                       String bindingField = null;
+                       String bindingValueField = null;
+                       boolean watching = once.watch().length() > 0;
+                       if (watching) {
+                               // add fields to store the binding and the value
+                               bindingField = transformation.addField(PRIVATE, 
Binding.class.getCanonicalName(), fieldName + "$binding");
+                               bindingValueField = 
transformation.addField(PRIVATE, "java.lang.Object", fieldName + 
"$bindingValue");
+
+                               String bindingSourceField = 
transformation.addInjectedField(BindingSource.class, fieldName + 
"$bindingsource", _bindingSource);
+               
+                               String body = String.format("%s = 
%s.newBinding(\"Watch expression\", %s, \"%s\", \"%s\");", 
+                                               bindingField,
+                                               bindingSourceField,
+                                               
transformation.getResourcesFieldName(),
+                                               
TapestryConstants.PROP_BINDING_PREFIX,
+                                               once.watch());
+                               
transformation.extendMethod(TransformConstants.CONTAINING_PAGE_DID_LOAD_SIGNATURE,
 body);
+                       }
+                       
+                       BodyBuilder b = new BodyBuilder();
+
+                       // on cleanup, reset the field values
+                       b.begin();
+                                               
+                       if (!TransformUtils.isPrimitive(method.getReturnType()))
+                               b.addln("%s = null;", fieldName);
+                       b.addln("%s = false;", calledField);
+                       
+                       if (watching)
+                               b.addln("%s = null;", bindingValueField);
+                       
+                       b.end();
+                       
transformation.extendMethod(TransformConstants.POST_RENDER_CLEANUP_SIGNATURE, 
b.toString());
+                                               
+                       // prefix the existing method to cache the result
+                       b.clear();
+                       b.begin();
+                       
+                       // if it has been called and watch is set and the old 
value is the same as the new value then return
+                       // get the old value and cache it
+                       /* NOTE: evaluates the binding twice when checking the 
new value.
+                        * this is probably not a problem because in most cases 
properties
+                        * that are being watched are not expensive operations. 
plus, we
+                        * never guaranteed that it would be called exactly 
once when
+                        * watching.
+                        */
+                       if (watching) {
+                               b.addln("if (%s && %s == %s.get()) return %s;",
+                                               calledField, bindingValueField, 
bindingField, fieldName);
+                               b.addln("%s = %s.get();", bindingValueField, 
bindingField);
+                       }
+                       else {
+                               b.addln("if (%s) return %s;", calledField, 
fieldName);
+                       }
+                       
+                       b.addln("%s = true;", calledField);                     
+                       b.end();                        
+                       transformation.prefixMethod(method, b.toString());
+                       
+                       // cache the return value
+                       b.clear();
+                       b.begin();
+                       b.addln("%s = $_;", fieldName);
+                       b.end();
+                       transformation.extendExistingMethod(method, 
b.toString());
+               }
+       }
+}

Modified: 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/transform/TransformMessages.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/transform/TransformMessages.java?rev=635085&r1=635084&r2=635085&view=diff
==============================================================================
--- 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/transform/TransformMessages.java
 (original)
+++ 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/transform/TransformMessages.java
 Sat Mar  8 12:53:25 2008
@@ -17,6 +17,7 @@
 import org.apache.tapestry.ioc.Messages;
 import org.apache.tapestry.ioc.internal.util.MessagesImpl;
 import org.apache.tapestry.runtime.Component;
+import org.apache.tapestry.services.TransformMethodSignature;
 
 class TransformMessages
 {
@@ -33,4 +34,11 @@
                 .getComponentResources().getCompleteId(), fieldName, 
fieldType);
     }
 
+    static String onceMethodMustHaveReturnValue(TransformMethodSignature 
method) {
+        return MESSAGES.format("once-no-return-value", method);
+    }
+    
+    static String onceMethodsHaveNoParameters(TransformMethodSignature method) 
{
+        return MESSAGES.format("once-no-parameters", method);
+    }
 }

Modified: 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/TapestryModule.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/TapestryModule.java?rev=635085&r1=635084&r2=635085&view=diff
==============================================================================
--- 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/TapestryModule.java
 (original)
+++ 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/TapestryModule.java
 Sat Mar  8 12:53:25 2008
@@ -223,7 +223,7 @@
      * annotation</dd> <dt>ContentType</dt> <dd>Checks for [EMAIL PROTECTED] 
org.apache.tapestry.annotations.ContentType}
      * annotation</dd> <dt>ResponseEncoding</dt> <dd>Checks for the [EMAIL 
PROTECTED] org.apache.tapestry.annotations.ResponseEncoding}
      * annotation</dd> <dt>GenerateAccessors</dt> <dd>Generates accessor 
methods if [EMAIL PROTECTED]
-     * org.apache.tapestry.annotations.Property} annotation is present </dd> 
</dl>
+     * org.apache.tapestry.annotations.Property} annotation is present </dd> 
<dt>Once</dt> <dd>Checks for the [EMAIL PROTECTED] Once} annotation</dd></dl>
      */
     public static void contributeComponentClassTransformWorker(
             OrderedConfiguration<ComponentClassTransformWorker> configuration,
@@ -243,6 +243,8 @@
         // TODO: Proper scheduling of all of this. Since a given field or 
method should
         // only have a single annotation, the order doesn't matter so much, as 
long as
         // UnclaimedField is last.
+        
+        configuration.add("Once", locator.autobuild(OnceWorker.class));
 
         configuration.add("Meta", new MetaWorker());
 

Modified: 
tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/internal/transform/TransformStrings.properties
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/internal/transform/TransformStrings.properties?rev=635085&r1=635084&r2=635085&view=diff
==============================================================================
--- 
tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/internal/transform/TransformStrings.properties
 (original)
+++ 
tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/internal/transform/TransformStrings.properties
 Sat Mar  8 12:53:25 2008
@@ -14,3 +14,5 @@
 
 field-injection-error=Error obtaining injected value for field %s.%s: %s
 component-not-assignable-to-field=Component %s is not assignable to field %s 
(of type %s).
[EMAIL PROTECTED] may only be used with methods that return values: %s
[EMAIL PROTECTED] cannot be used with methods that accept parameters: %s
\ No newline at end of file

Modified: tapestry/tapestry5/trunk/tapestry-core/src/site/apt/index.apt
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/site/apt/index.apt?rev=635085&r1=635084&r2=635085&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/site/apt/index.apt (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/site/apt/index.apt Sat Mar  8 
12:53:25 2008
@@ -10,6 +10,8 @@
 
 New And Of Note
 
+  * The @Once annotation has been added to allowing the caching of method 
results.
+
   * Tapestry can now generate accessor methods for fields automatically via 
the @Property annotation.
 
   * It is now possible to override the built-in display and edit blocks for 
data types.

Modified: 
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/IntegrationTests.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/IntegrationTests.java?rev=635085&r1=635084&r2=635085&view=diff
==============================================================================
--- 
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/IntegrationTests.java
 (original)
+++ 
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/IntegrationTests.java
 Sat Mar  8 12:53:25 2008
@@ -1860,6 +1860,26 @@
                 "Class org.apache.tapestry.integration.app1.pages.Datum 
contains field(s) (_value) that are not private. You should change these fields 
to private, and add accessor methods if needed.");
     }
 
+    /** TAPESTRY-2244 */
+    @Test
+    public void once()
+    {
+        start("Once Annotation");
+
+        assertText("//[EMAIL PROTECTED]'value']", "000");
+        assertText("//[EMAIL PROTECTED]'value2size']", "111");
+        
+        assertText("//[EMAIL PROTECTED]'watch'][1]", "0");
+        assertText("//[EMAIL PROTECTED]'watch'][2]", "0");
+        assertText("//[EMAIL PROTECTED]'watch'][3]", "1");
+    }
+    
+    /** TAPESTRY-2244 */
+    @Test
+    public void override_method_with_once() {
+        start("Once Annotation2");
+        assertText("//[EMAIL PROTECTED]'value']", "111");
+    }
 
     private void sleep(long timeout)
     {

Added: 
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app1/pages/OncePage.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app1/pages/OncePage.java?rev=635085&view=auto
==============================================================================
--- 
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app1/pages/OncePage.java
 (added)
+++ 
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app1/pages/OncePage.java
 Sat Mar  8 12:53:25 2008
@@ -0,0 +1,50 @@
+package org.apache.tapestry.integration.app1.pages;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.tapestry.annotations.Once;
+
+public class OncePage {
+       private int value;
+       private List<String> value2;
+       private int value3;
+
+       private Integer watchValue;
+       
+       void beginRender() {
+               value = 0;
+               value2 = new ArrayList<String>();
+               value3 = 0;
+               watchValue = 0;
+       }
+
+       @Once
+       public int getValue() {
+               return value++;
+       }
+       
+       @Once
+       public List<String> getValue2() {
+               value2.add("a");
+               return value2;
+       }
+       
+       @Once(watch="watchValue")
+       public int getValue3() {
+               return value3++;
+       }
+
+       public Integer getWatchValue() {
+               return watchValue;
+       }
+
+       public void setWatchValue(Integer watchValue) {
+               this.watchValue = watchValue;
+       }
+       
+       public Object incrWatchValue() {
+               watchValue++;
+               return null;
+       }
+}

Added: 
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app1/pages/OncePage2.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app1/pages/OncePage2.java?rev=635085&view=auto
==============================================================================
--- 
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app1/pages/OncePage2.java
 (added)
+++ 
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app1/pages/OncePage2.java
 Sat Mar  8 12:53:25 2008
@@ -0,0 +1,10 @@
+package org.apache.tapestry.integration.app1.pages;
+
+public class OncePage2 extends OncePage {
+
+       @Override
+       public int getValue() {
+               return super.getValue()+1;
+       }
+       
+}

Modified: 
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app1/pages/Start.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app1/pages/Start.java?rev=635085&r1=635084&r2=635085&view=diff
==============================================================================
--- 
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app1/pages/Start.java
 (original)
+++ 
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app1/pages/Start.java
 Sat Mar  8 12:53:25 2008
@@ -247,7 +247,12 @@
             new Item("IndirectProtectedFields", "Protected Fields Demo", "demo 
exception when component class contains protected fields"),
 
             new Item("injectcomponentdemo", "Inject Component Demo",
-                     "inject component defined in template"));
+                     "inject component defined in template"),
+            
+            new Item("oncepage", "Once Annotation", "Caching method return 
values"),
+            
+            new Item("oncepage2", "Once Annotation2", "Caching method return 
values w/ inheritence")
+    );
 
     static
     {

Added: 
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/transform/OnceWorkerTest.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/transform/OnceWorkerTest.java?rev=635085&view=auto
==============================================================================
--- 
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/transform/OnceWorkerTest.java
 (added)
+++ 
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/transform/OnceWorkerTest.java
 Sat Mar  8 12:53:25 2008
@@ -0,0 +1,57 @@
+// Copyright 2006, 2007, 2008 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.tapestry.internal.transform;
+
+import java.lang.reflect.Modifier;
+import java.util.Arrays;
+
+import org.apache.tapestry.annotations.Once;
+import org.apache.tapestry.services.ClassTransformation;
+import org.apache.tapestry.services.TransformMethodSignature;
+import org.apache.tapestry.test.TapestryTestCase;
+import org.testng.annotations.Test;
+
+/** Mostly just testing error conditions here. Functionality testing in 
integration tests. */
[EMAIL PROTECTED]
+public class OnceWorkerTest extends TapestryTestCase
+{
+    public void must_have_return_type() throws Exception {
+        ClassTransformation ct = mockClassTransformation();
+        TransformMethodSignature sig = new 
TransformMethodSignature(Modifier.PUBLIC, "void", "getFoo", new String[0], new 
String[0]);
+        
+        
expect(ct.findMethodsWithAnnotation(Once.class)).andReturn(Arrays.asList(sig));
+        
+        replay();
+        try {
+            new OnceWorker(null).transform(ct, null);
+            fail("did not throw");
+        } catch (IllegalArgumentException e) {}
+        verify();
+    }
+    
+    public void must_not_have_parameters() throws Exception {
+        ClassTransformation ct = mockClassTransformation();
+        TransformMethodSignature sig = new 
TransformMethodSignature(Modifier.PUBLIC, "java.lang.Object", "getFoo", new 
String[] { "boolean" }, new String[0]);
+        
+        
expect(ct.findMethodsWithAnnotation(Once.class)).andReturn(Arrays.asList(sig));
+        
+        replay();
+        try {
+            new OnceWorker(null).transform(ct, null);
+            fail("did not throw");
+        } catch (IllegalArgumentException e) {}
+        verify();
+    }
+}

Added: 
tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/integration/app1/pages/OncePage.tml
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/integration/app1/pages/OncePage.tml?rev=635085&view=auto
==============================================================================
--- 
tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/integration/app1/pages/OncePage.tml
 (added)
+++ 
tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/integration/app1/pages/OncePage.tml
 Sat Mar  8 12:53:25 2008
@@ -0,0 +1,13 @@
+<html t:type="Border" 
xmlns:t="http://tapestry.apache.org/schema/tapestry_5_0_0.xsd";>
+       <h1>@Once tests</h1>
+       <p>This page tests the @Once annotation.</p>
+       
+       <span id="value">${value}${value}${value}</span>
+       <span 
id="value2size">${value2.size()}${value2.size()}${value2.size()}</span>
+       
+       ${incrWatchValue()}
+       <span class="watch">${value3}</span>
+       <span class="watch">${value3}</span>
+       ${incrWatchValue()}
+       <span class="watch">${value3}</span>
+</html>


Reply via email to