You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tapestry.apache.org by hl...@apache.org on 2010/02/04 01:45:52 UTC

svn commit: r906306 - in /tapestry/tapestry5/trunk/tapestry-core/src: main/java/org/apache/tapestry5/internal/transform/ main/java/org/apache/tapestry5/services/ test/java/org/apache/tapestry5/integration/app1/

Author: hlship
Date: Thu Feb  4 00:45:51 2010
New Revision: 906306

URL: http://svn.apache.org/viewvc?rev=906306&view=rev
Log:
Rework InjectComponentWorker around the new ClassTransformation APIs

Modified:
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/InjectComponentWorker.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/TapestryModule.java
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/CoreBehaviorsTests.java

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/InjectComponentWorker.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/InjectComponentWorker.java?rev=906306&r1=906305&r2=906306&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/InjectComponentWorker.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/InjectComponentWorker.java Thu Feb  4 00:45:51 2010
@@ -1,10 +1,10 @@
-// Copyright 2008 The Apache Software Foundation
+// Copyright 2008, 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
+// 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,
@@ -16,61 +16,93 @@
 
 import org.apache.tapestry5.ComponentResources;
 import org.apache.tapestry5.annotations.InjectComponent;
+import org.apache.tapestry5.internal.services.ComponentClassCache;
 import org.apache.tapestry5.ioc.internal.util.InternalUtils;
-import org.apache.tapestry5.ioc.util.BodyBuilder;
+import org.apache.tapestry5.ioc.services.FieldValueConduit;
 import org.apache.tapestry5.model.MutableComponentModel;
+import org.apache.tapestry5.runtime.Component;
+import org.apache.tapestry5.runtime.PageLifecycleAdapter;
 import org.apache.tapestry5.services.ClassTransformation;
 import org.apache.tapestry5.services.ComponentClassTransformWorker;
-import org.apache.tapestry5.services.TransformConstants;
+import org.apache.tapestry5.services.ComponentValueProvider;
+import org.apache.tapestry5.services.TransformField;
 
 /**
  * Recognizes the {@link org.apache.tapestry5.annotations.InjectComponent} annotation, and converts the field into a
- * read-only field containing the component.  The id of the component may be explicitly stated or will be determined
+ * read-only field containing the component. The id of the component may be explicitly stated or will be determined
  * from the field name.
  */
 public class InjectComponentWorker implements ComponentClassTransformWorker
 {
-    public void transform(ClassTransformation transformation,
-                          MutableComponentModel model)
-    {
-        for (String fieldName : transformation.findFieldsWithAnnotation(InjectComponent.class))
-        {
-            InjectComponent annotation = transformation.getFieldAnnotation(fieldName, InjectComponent.class);
+    private final ComponentClassCache classCache;
 
-            String type = transformation.getFieldType(fieldName);
+    public InjectComponentWorker(ComponentClassCache classCache)
+    {
+        this.classCache = classCache;
+    }
 
-            String resourcesFieldName = transformation.getResourcesFieldName();
+    public void transform(ClassTransformation transformation, MutableComponentModel model)
+    {
+        for (TransformField field : transformation.matchFieldsWithAnnotation(InjectComponent.class))
+        {
+            InjectComponent annotation = field.getAnnotation(InjectComponent.class);
 
-            String componentId = annotation.value();
-            if (InternalUtils.isBlank(componentId))
-                componentId = InternalUtils.stripMemberName(fieldName);
+            field.claim(annotation);
 
-            transformation.makeReadOnly(fieldName);
+            final String type = field.getType();
 
-            BodyBuilder builder = new BodyBuilder().addln("try").begin();
+            final String componentId = getComponentId(field, annotation);
 
-            builder.addln(
-                    "%s = (%s) %s.getEmbeddedComponent(\"%s\");",
-                    fieldName,
-                    type,
-                    resourcesFieldName,
-                    componentId);
-            builder.end();
-            builder.addln("catch (ClassCastException ex)").begin();
-            builder.addln("throw new RuntimeException(%s.formatMessage(%s, \"%s\", \"%s\", \"%s\"), ex);",
-                          getClass().getName(), resourcesFieldName, fieldName, type, componentId);
-            builder.end();
+            final String fieldName = field.getName();
+
+            ComponentValueProvider<FieldValueConduit> provider = new ComponentValueProvider<FieldValueConduit>()
+            {
+                public FieldValueConduit get(final ComponentResources resources)
+                {
+                    return new ReadOnlyFieldValueConduit(resources, fieldName)
+                    {
+                        private Component embedded;
+
+                        {
+                            resources.addPageLifecycleListener(new PageLifecycleAdapter()
+                            {
+                                public void containingPageDidLoad()
+                                {
+                                    embedded = resources.getEmbeddedComponent(componentId);
+
+                                    Class fieldType = classCache.forName(type);
+
+                                    if (!fieldType.isInstance(embedded))
+                                        throw new RuntimeException(
+                                                String
+                                                        .format(
+                                                                "Unable to inject component '%s' into field %s of component %s.  Class %s is not assignable to a field of type %s.",
+                                                                componentId, fieldName, resources.getCompleteId(),
+                                                                embedded.getClass().getName(), fieldType.getName()));
+                                };
+                            });
+                        }
+
+                        public Object get()
+                        {
+                            return embedded;
+                        }
+                    };
+                }
+            };
 
-            transformation.extendMethod(TransformConstants.CONTAINING_PAGE_DID_LOAD_SIGNATURE, builder.toString());
+            field.replaceAccess(provider);
         }
+
     }
 
-    public static String formatMessage(ComponentResources resources, String fieldName, String fieldType,
-                                       String componentId)
+    private String getComponentId(TransformField field, InjectComponent annotation)
     {
-        return String.format(
-                "Unable to inject component '%s' into field %s of component %s.  Class %s is not assignable to a field of type %s.",
-                componentId, fieldName, resources.getCompleteId(),
-                resources.getEmbeddedComponent(componentId).getClass().getName(), fieldType);
+        String id = annotation.value();
+
+        if (InternalUtils.isNonBlank(id))
+            return id;
+
+        return InternalUtils.stripMemberName(field.getName());
     }
 }

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=906306&r1=906305&r2=906306&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 Thu Feb  4 00:45:51 2010
@@ -539,7 +539,7 @@
         configuration.add("SupportsInformalParameters", new SupportsInformalParametersWorker());
         configuration.addInstance("InjectPage", InjectPageWorker.class);
         configuration.addInstance("InjectContainer", InjectContainerWorker.class);
-        configuration.add("InjectComponent", new InjectComponentWorker());
+        configuration.addInstance("InjectComponent",  InjectComponentWorker.class);
         configuration.add("RenderCommand", new RenderCommandWorker());
 
         // Default values for parameters are often some form of injection, so

Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/CoreBehaviorsTests.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/CoreBehaviorsTests.java?rev=906306&r1=906305&r2=906306&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/CoreBehaviorsTests.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/CoreBehaviorsTests.java Thu Feb  4 00:45:51 2010
@@ -111,8 +111,7 @@
         // mismatched tag.
         clickThru("BadTemplate Page");
 
-        assertTextPresent(
-                "org.apache.tapestry5.ioc.internal.util.TapestryException",
+        assertTextPresent("org.apache.tapestry5.ioc.internal.util.TapestryException",
                 "Failure parsing template classpath:org/apache/tapestry5/integration/app1/pages/BadTemplate.tml",
                 "The element type \"t:foobar\" must be terminated by the matching end-tag \"</t:foobar>\"",
                 "classpath:org/apache/tapestry5/integration/app1/pages/BadTemplate.tml, line 6",
@@ -149,9 +148,7 @@
     {
         clickThru("InjectComponentMismatch");
 
-        assertTextPresent(
-                "Unable to inject component 'form' into field form of component InjectComponentMismatch. Class org.apache.tapestry5.corelib.components.BeanEditForm is not assignable to a field of type org.apache.tapestry5.corelib.components.Form.",
-                "ClassCastException");
+        assertTextPresent("Unable to inject component 'form' into field form of component InjectComponentMismatch. Class org.apache.tapestry5.corelib.components.BeanEditForm is not assignable to a field of type org.apache.tapestry5.corelib.components.Form.");
     }
 
     @Test
@@ -343,8 +340,7 @@
         clickAndWait("link=go");
 
         assertTextSeries("//li[%d]", 1, "betty", "wilma", "betty/wilma", "\u82B1\u5B50");
-        assertTextSeries("//ul[2]/li[%d]", 1, "fred", "barney", "clark kent", "fred/barney",
-                "\u592A\u90CE");
+        assertTextSeries("//ul[2]/li[%d]", 1, "fred", "barney", "clark kent", "fred/barney", "\u592A\u90CE");
     }
 
     @Test
@@ -430,8 +426,7 @@
         clickAndWait(clear);
 
         clickAndWait("link=No Context");
-        assertText("methodNames",
-                "[parent.eventHandlerZero(), parent.onAction(), child.eventHandlerZeroChild()]");
+        assertText("methodNames", "[parent.eventHandlerZero(), parent.onAction(), child.eventHandlerZeroChild()]");
 
         clickAndWait(clear);
         clickAndWait("link=Single context value");
@@ -460,8 +455,7 @@
     {
         clickThru("Inherited Bindings Demo");
 
-        assertTextPresent("Bound: [ value: the-bound-value, bound: true ]",
-                "Unbound: [ value: null, bound: false ]");
+        assertTextPresent("Bound: [ value: the-bound-value, bound: true ]", "Unbound: [ value: null, bound: false ]");
     }
 
     @Test
@@ -490,8 +484,7 @@
         assertAttribute("//div[@id='single']/@class", "red");
         assertAttribute("//div[@id='consecutive']/@class", "goober-red");
         assertAttribute("//div[@id='trailer']/@class", "goober-green");
-        assertText("//div[@id='formal']",
-                "ALERT-expansions work inside formal component parameters as well");
+        assertText("//div[@id='formal']", "ALERT-expansions work inside formal component parameters as well");
 
         // An unrelated test, but fills in a bunch of minor gaps.
 
@@ -641,8 +634,7 @@
         clickAndWait("link=force invalid event context");
 
         assertTextPresent("An unexpected application exception has occurred.",
-                "org.apache.tapestry5.runtime.ComponentEventException",
-                "java.lang.NumberFormatException");
+                "org.apache.tapestry5.runtime.ComponentEventException", "java.lang.NumberFormatException");
     }
 
     /**
@@ -672,8 +664,8 @@
         // Just sample a smattering of the vast amount of data in the exception
         // report.
 
-        assertTextPresent("RenderErrorDemo", "class " + RenderErrorDemo.class.getName(),
-                "RenderErrorDemo:border", "RenderErrorDemo:echo");
+        assertTextPresent("RenderErrorDemo", "class " + RenderErrorDemo.class.getName(), "RenderErrorDemo:border",
+                "RenderErrorDemo:echo");
     }
 
     /**
@@ -863,8 +855,7 @@
         assertText("version", "5");
 
         // @ReverseStrings filtered the checked exception to a string result
-        assertText(
-                "cranky",
+        assertText("cranky",
                 "Invocation of method getCranky() failed with org.apache.tapestry5.integration.app1.services.DearGodWhyMeException.");
 
         // Now to check advice on a setter that manipulates parameters
@@ -903,8 +894,7 @@
         clickThru("Informal Parameters Demo");
 
         assertTextSeries("//dl[@id='informals']/dt[%d]", 1, "barney", "fred", "pageName");
-        assertTextSeries("//dl[@id='informals']/dd[%d]", 1, "rubble", "flintstone",
-                "InformalParametersDemo");
+        assertTextSeries("//dl[@id='informals']/dd[%d]", 1, "rubble", "flintstone", "InformalParametersDemo");
     }
 
     /**
@@ -1170,8 +1160,8 @@
      *                 "from" is < 0, checking the corresponding mixin values is disabled.
      */
 
-    private void assertEchoMixins(String fieldName, String originalValue, int echo1From,
-            int echo2From, int echo3From, int fieldFrom, boolean isField)
+    private void assertEchoMixins(String fieldName, String originalValue, int echo1From, int echo2From, int echo3From,
+            int fieldFrom, boolean isField)
     {
         String[] vals =
         { originalValue, "temporaryvaluefromechovaluemixin", "3", "world" };