You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tapestry.apache.org by an...@apache.org on 2006/10/05 20:45:05 UTC

svn commit: r453311 - in /tapestry/tapestry4/trunk/tapestry-annotations/src: java/org/apache/tapestry/annotations/ test/org/apache/tapestry/annotations/

Author: andyhot
Date: Thu Oct  5 11:45:05 2006
New Revision: 453311

URL: http://svn.apache.org/viewvc?view=rev&rev=453311
Log:
TAPESTRY-913: Support copyOf attribute for @Component annotation

Modified:
    tapestry/tapestry4/trunk/tapestry-annotations/src/java/org/apache/tapestry/annotations/AnnotationMessages.java
    tapestry/tapestry4/trunk/tapestry-annotations/src/java/org/apache/tapestry/annotations/AnnotationStrings.properties
    tapestry/tapestry4/trunk/tapestry-annotations/src/java/org/apache/tapestry/annotations/AnnotationUtils.java
    tapestry/tapestry4/trunk/tapestry-annotations/src/java/org/apache/tapestry/annotations/Component.java
    tapestry/tapestry4/trunk/tapestry-annotations/src/java/org/apache/tapestry/annotations/ComponentAnnotationWorker.java
    tapestry/tapestry4/trunk/tapestry-annotations/src/test/org/apache/tapestry/annotations/AnnotatedPage.java
    tapestry/tapestry4/trunk/tapestry-annotations/src/test/org/apache/tapestry/annotations/AnnotationEnhancementWorkerTest.java
    tapestry/tapestry4/trunk/tapestry-annotations/src/test/org/apache/tapestry/annotations/TestComponentAnnotationWorker.java

Modified: tapestry/tapestry4/trunk/tapestry-annotations/src/java/org/apache/tapestry/annotations/AnnotationMessages.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-annotations/src/java/org/apache/tapestry/annotations/AnnotationMessages.java?view=diff&rev=453311&r1=453310&r2=453311
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-annotations/src/java/org/apache/tapestry/annotations/AnnotationMessages.java (original)
+++ tapestry/tapestry4/trunk/tapestry-annotations/src/java/org/apache/tapestry/annotations/AnnotationMessages.java Thu Oct  5 11:45:05 2006
@@ -111,5 +111,15 @@
     static String invalidAnnotationInClass(Class annotation, Class clazz)
     {
         return _formatter.format("invalid-annotation-in-class", annotation.getName(), clazz.getName());
-    }    
+    }  
+    
+    static String unableToCopy(String id)
+    {
+        return _formatter.format("unable-to-copy", id);
+    }
+    
+    static String bothTypeAndCopyOf(String id)
+    {
+        return _formatter.format("both-type-and-copy-of", id);
+    }  
 }

Modified: tapestry/tapestry4/trunk/tapestry-annotations/src/java/org/apache/tapestry/annotations/AnnotationStrings.properties
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-annotations/src/java/org/apache/tapestry/annotations/AnnotationStrings.properties?view=diff&rev=453311&r1=453310&r2=453311
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-annotations/src/java/org/apache/tapestry/annotations/AnnotationStrings.properties (original)
+++ tapestry/tapestry4/trunk/tapestry-annotations/src/java/org/apache/tapestry/annotations/AnnotationStrings.properties Thu Oct  5 11:45:05 2006
@@ -29,3 +29,5 @@
 no-targets-found=No targets found for annotated method {0}. You must specify at least one of targets or elements.
 no-form-found=Unable to find form with id while enhancing method bound with submitForm annotation {0}: {1}
 invalid-annotation-in-class=Annotation {0} is not allowed in a class (''{1}'') that implements the IPage interface.
+unable-to-copy=Unable to copy component {0}, which does not exist.
+both-type-and-copy-of=Annotation for component {0} contains both type and copy-of attributes.

Modified: tapestry/tapestry4/trunk/tapestry-annotations/src/java/org/apache/tapestry/annotations/AnnotationUtils.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-annotations/src/java/org/apache/tapestry/annotations/AnnotationUtils.java?view=diff&rev=453311&r1=453310&r2=453311
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-annotations/src/java/org/apache/tapestry/annotations/AnnotationUtils.java (original)
+++ tapestry/tapestry4/trunk/tapestry-annotations/src/java/org/apache/tapestry/annotations/AnnotationUtils.java Thu Oct  5 11:45:05 2006
@@ -17,10 +17,13 @@
 import java.beans.Introspector;
 import java.lang.annotation.Annotation;
 import java.lang.reflect.Method;
+import java.util.Iterator;
 
 import org.apache.hivemind.ApplicationRuntimeException;
 import org.apache.hivemind.Location;
 import org.apache.hivemind.Resource;
+import org.apache.tapestry.spec.IBindingSpecification;
+import org.apache.tapestry.spec.IContainedComponent;
 import org.apache.tapestry.util.DescribedLocation;
 
 /**
@@ -106,6 +109,26 @@
         }
     
         return buffer.toString();
+    }    
+    
+    /**
+     * Copies all bindings of a component to another one.
+     * @param source
+     * @param target
+     * 
+     * @since 4.1.1
+     */
+    public static void copyBindings(IContainedComponent source, IContainedComponent target)
+    {
+        Iterator i = source.getBindingNames().iterator();
+        while (i.hasNext())
+        {
+            String bindingName = (String) i.next();
+            IBindingSpecification binding = source.getBinding(bindingName);
+            target.setBinding(bindingName, binding);
+        }
+    
+        target.setType(source.getType());
     }    
 
     private static void checkGetter(Method method)

Modified: tapestry/tapestry4/trunk/tapestry-annotations/src/java/org/apache/tapestry/annotations/Component.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-annotations/src/java/org/apache/tapestry/annotations/Component.java?view=diff&rev=453311&r1=453310&r2=453311
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-annotations/src/java/org/apache/tapestry/annotations/Component.java (original)
+++ tapestry/tapestry4/trunk/tapestry-annotations/src/java/org/apache/tapestry/annotations/Component.java Thu Oct  5 11:45:05 2006
@@ -45,6 +45,14 @@
      */
 
     String type() default "";
+    
+    /**
+     * The name of a previously defined component. 
+     * The type and bindings of that component will be copied to this component. 
+     * Either type or copy-of must be specified. 
+     */
+
+    String copyOf() default "";    
 
     /**
      * If true, then the component inherits informal parameters from its container.

Modified: tapestry/tapestry4/trunk/tapestry-annotations/src/java/org/apache/tapestry/annotations/ComponentAnnotationWorker.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-annotations/src/java/org/apache/tapestry/annotations/ComponentAnnotationWorker.java?view=diff&rev=453311&r1=453310&r2=453311
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-annotations/src/java/org/apache/tapestry/annotations/ComponentAnnotationWorker.java (original)
+++ tapestry/tapestry4/trunk/tapestry-annotations/src/java/org/apache/tapestry/annotations/ComponentAnnotationWorker.java Thu Oct  5 11:45:05 2006
@@ -17,6 +17,7 @@
 import java.lang.reflect.Method;
 
 import org.apache.hivemind.ApplicationRuntimeException;
+import org.apache.hivemind.HiveMind;
 import org.apache.hivemind.Location;
 import org.apache.tapestry.enhance.EnhancementOperation;
 import org.apache.tapestry.spec.BindingSpecification;
@@ -45,16 +46,30 @@
 
         String propertyName = AnnotationUtils.getPropertyName(method);
         String type = component.type();
-        if (type.equals(""))
+        String copyOf = component.copyOf();
+        boolean hasCopyOf = HiveMind.isNonBlank(copyOf);
+        
+        if (hasCopyOf)
         {
-            Class retTypeClazz = method.getReturnType();
-            type = retTypeClazz.getSimpleName();
+            if (HiveMind.isNonBlank(type))
+                throw new ApplicationRuntimeException(AnnotationMessages.bothTypeAndCopyOf(propertyName));
+            type = null;
         }
+        else
+        {
+            if (type.equals(""))
+            {
+                Class retTypeClazz = method.getReturnType();
+                type = retTypeClazz.getSimpleName();
+            }            
+            copyOf = null;
+        }        
 
         IContainedComponent cc = new ContainedComponent();
 
         cc.setInheritInformalParameters(component.inheritInformalParameters());
         cc.setType(type);
+        cc.setCopyOf(copyOf);
         cc.setPropertyName(propertyName);
         cc.setLocation(location);
 
@@ -67,8 +82,15 @@
 
         if (id.equals(""))
             id = propertyName;
-
+        
         spec.addComponent(id, cc);
+        
+        if (hasCopyOf)
+        {
+            IContainedComponent source = spec.getComponent(copyOf);
+            if (source != null)                
+                AnnotationUtils.copyBindings(source, cc);
+        }
     }
 
     void addBinding(IContainedComponent component, String binding, Location location)
@@ -90,7 +112,7 @@
         bs.setLocation(location);
 
         component.setBinding(name, bs);
-    }
+    }    
 
     private void invalidBinding(String binding)
     {

Modified: tapestry/tapestry4/trunk/tapestry-annotations/src/test/org/apache/tapestry/annotations/AnnotatedPage.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-annotations/src/test/org/apache/tapestry/annotations/AnnotatedPage.java?view=diff&rev=453311&r1=453310&r2=453311
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-annotations/src/test/org/apache/tapestry/annotations/AnnotatedPage.java (original)
+++ tapestry/tapestry4/trunk/tapestry-annotations/src/test/org/apache/tapestry/annotations/AnnotatedPage.java Thu Oct  5 11:45:05 2006
@@ -107,6 +107,12 @@
     @Component(type = "TextField", bindings =
     { "value = email", "displayName = message:email-label" })
     public abstract IComponent getWhitespace();
+    
+    @Component(id = "anEmailCopy", copyOf = "email", type = "Checkbox")
+    public abstract IComponent getInvalidEmailCopy();
+    
+    @Component(id = "aComponentCopy", copyOf = "componentWithBindings")
+    public abstract IComponent getComponentWithBindingsCopy();
 
     @Message
     public abstract String noArgsMessage();

Modified: tapestry/tapestry4/trunk/tapestry-annotations/src/test/org/apache/tapestry/annotations/AnnotationEnhancementWorkerTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-annotations/src/test/org/apache/tapestry/annotations/AnnotationEnhancementWorkerTest.java?view=diff&rev=453311&r1=453310&r2=453311
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-annotations/src/test/org/apache/tapestry/annotations/AnnotationEnhancementWorkerTest.java (original)
+++ tapestry/tapestry4/trunk/tapestry-annotations/src/test/org/apache/tapestry/annotations/AnnotationEnhancementWorkerTest.java Thu Oct  5 11:45:05 2006
@@ -60,7 +60,7 @@
     /**
      * No method annotations registered.
      */
-    public void testNoAnnotations()
+    public void test_No_Annotations()
     {
         EnhancementOperation op = newOp(AnnotatedPage.class);
         IComponentSpecification spec = newSpec();
@@ -76,7 +76,7 @@
         verify();
     }
 
-    public void testAnnotationMatch()
+    public void test_Annotation_Match()
     {
         ClassResolver resolver = new DefaultClassResolver();
 
@@ -118,7 +118,7 @@
                 baseClass));
     }
 
-    public void testAnnotationWithSubclass()
+    public void test_Annotation_With_Subclass()
     {
         ClassResolver resolver = new DefaultClassResolver();
 
@@ -145,7 +145,7 @@
         verify();
     }
 
-    public void testAnnotationFailure()
+    public void test_Annotation_Failure()
     {
         ClassResolver resolver = new DefaultClassResolver();
 
@@ -183,7 +183,7 @@
         verify();
     }
 
-    public void testClassAnnotation()
+    public void test_Class_Annotation()
     {
         ClassResolver resolver = new DefaultClassResolver();
 
@@ -208,7 +208,7 @@
         verify();
     }
 
-    public void testClassAnnotationFailure()
+    public void test_Class_Annotation_Failure()
     {
         ClassResolver resolver = new DefaultClassResolver();
 
@@ -243,7 +243,7 @@
         verify();
     }
 
-    public void testClassAnnotationNoMatch()
+    public void test_Class_Annotation_No_Match()
     {
         EnhancementOperation op = newOp(DeprecatedBean.class);
         IComponentSpecification spec = newSpec();
@@ -259,7 +259,7 @@
         verify();
     }
 
-    public void testSecondaryEnhancementWorker()
+    public void test_Secondary_EnhancementWorker()
     {
         SecondaryAnnotationWorker secondary = newSecondaryAnnotationWorker();
         
@@ -287,7 +287,7 @@
         verify();
     }
 
-    public void testSecondaryEnhancementWorkerFailure()
+    public void test_Secondary_EnhancementWorker_Failure()
     {
         SecondaryAnnotationWorker secondary = newSecondaryAnnotationWorker();
         

Modified: tapestry/tapestry4/trunk/tapestry-annotations/src/test/org/apache/tapestry/annotations/TestComponentAnnotationWorker.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-annotations/src/test/org/apache/tapestry/annotations/TestComponentAnnotationWorker.java?view=diff&rev=453311&r1=453310&r2=453311
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-annotations/src/test/org/apache/tapestry/annotations/TestComponentAnnotationWorker.java (original)
+++ tapestry/tapestry4/trunk/tapestry-annotations/src/test/org/apache/tapestry/annotations/TestComponentAnnotationWorker.java Thu Oct  5 11:45:05 2006
@@ -16,6 +16,7 @@
 
 import java.lang.reflect.Method;
 
+import org.apache.hivemind.ApplicationRuntimeException;
 import org.apache.hivemind.Location;
 import org.apache.tapestry.enhance.EnhancementOperation;
 import org.apache.tapestry.spec.BindingType;
@@ -36,13 +37,18 @@
 {
     private IContainedComponent run(String id, String methodName, Location location)
     {
+        IComponentSpecification spec = new ComponentSpecification();
+        
+        return run(spec, id, methodName, location);
+    }
+
+    private IContainedComponent run(IComponentSpecification spec, String id, String methodName, Location location)
+    {
         Method method = findMethod(AnnotatedPage.class, methodName);
 
         EnhancementOperation op = newOp();
 
-        replay();
-
-        IComponentSpecification spec = new ComponentSpecification();
+        replay();        
 
         new ComponentAnnotationWorker().performEnhancement(op, spec, method, location);
 
@@ -51,7 +57,7 @@
         return spec.getComponent(id);
     }
 
-    public void testSimple()
+    public void test_Simple()
     {
         Location l = newLocation();
 
@@ -65,28 +71,28 @@
         assertEquals("textField", cc.getPropertyName());
     }
     
-    public void testWithoutType()
+    public void test_Without_Type()
     {
         IContainedComponent cc = run("usernameField", "getUsernameField", null);
         
         assertEquals("TextField", cc.getType());
     }
 
-    public void testExplicitId()
+    public void test_Explicit_Id()
     {
         IContainedComponent cc = run("email", "getEmailField", null);
 
         assertEquals("emailField", cc.getPropertyName());
     }
 
-    public void testInheritInformalParameters()
+    public void test_Inherit_Informal_Parameters()
     {
         IContainedComponent cc = run("inherit", "getInherit", null);
 
         assertEquals(true, cc.getInheritInformalParameters());
     }
 
-    public void testWithBindings()
+    public void test_With_Bindings()
     {
         Location l = newLocation();
         IContainedComponent cc = run("componentWithBindings", "getComponentWithBindings", l);
@@ -100,7 +106,7 @@
         assertEquals("div", bs2.getValue());
     }
 
-    public void testBindingWhitespaceTrimmed()
+    public void test_Binding_Whitespace_Trimmed()
     {
         Location l = newLocation();
 
@@ -114,4 +120,33 @@
         IBindingSpecification bs2 = cc.getBinding("displayName");
         assertEquals("message:email-label", bs2.getValue());
     }
+    
+    public void test_With_Type_And_CopyOf()
+    {
+        try
+        {
+            run("anEmailCopy", "getInvalidEmailCopy", null);
+            unreachable();
+        }
+        catch (ApplicationRuntimeException ex)
+        {           
+            assertExceptionSubstring(ex, "both type and copy-of");
+        }        
+    }      
+    
+    public void test_CopyOf()
+    {
+        Location l = newLocation();
+        IComponentSpecification spec = new ComponentSpecification();
+        run(spec, "componentWithBindings", "getComponentWithBindings", l);
+        IContainedComponent cc = run(spec, "aComponentCopy", "getComponentWithBindingsCopy", l);
+        
+        IBindingSpecification bs1 = cc.getBinding("condition");
+        assertSame(l, bs1.getLocation());
+        assertEquals(BindingType.PREFIXED, bs1.getType());
+        assertEquals("message", bs1.getValue());
+
+        IBindingSpecification bs2 = cc.getBinding("element");
+        assertEquals("div", bs2.getValue());
+    }     
 }