Author: hlship
Date: Mon Sep  8 17:27:32 2008
New Revision: 693326

URL: http://svn.apache.org/viewvc?rev=693326&view=rev
Log:
TAPESTRY-2554: When decorating a service using a decorate method, the 
underlying service (or interceptor) should be available as a parameter of the 
service type, not just java.lang.Object

Added:
    
tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/SpecificDecoratorModule.java
Modified:
    
tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/DefaultModuleDefImpl.java
    
tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/IOCMessages.java
    
tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/ServiceDecoratorImpl.java
    
tapestry/tapestry5/trunk/tapestry-ioc/src/main/resources/org/apache/tapestry5/ioc/internal/IOCStrings.properties
    tapestry/tapestry5/trunk/tapestry-ioc/src/site/apt/decorator.apt
    
tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/IntegrationTest.java
    
tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/DefaultModuleDefImplTest.java

Modified: 
tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/DefaultModuleDefImpl.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/DefaultModuleDefImpl.java?rev=693326&r1=693325&r2=693326&view=diff
==============================================================================
--- 
tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/DefaultModuleDefImpl.java
 (original)
+++ 
tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/DefaultModuleDefImpl.java
 Mon Sep  8 17:27:32 2008
@@ -1,4 +1,4 @@
-// Copyright 2006, 2007 The Apache Software Foundation
+// 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.
@@ -148,7 +148,6 @@
 
                 return result;
             }
-
         };
 
         Arrays.sort(methods, c);
@@ -174,7 +173,6 @@
                 addContributionDef(m);
                 continue;
             }
-
         }
     }
 
@@ -231,15 +229,6 @@
             return;
         }
 
-        if (!methodContainsObjectParameter(method))
-        {
-            
logger.warn(IOCMessages.decoratorMethodNeedsDelegateParameter(method));
-            return;
-        }
-
-        // TODO: Check that at least one parameter is type java.lang.Object,
-        // since that's how the delegate is passed in.
-
         Order orderAnnotation = method.getAnnotation(Order.class);
         Match match = method.getAnnotation(Match.class);
 
@@ -247,7 +236,7 @@
 
         // TODO: Validate constraints here?
 
-        String[] patterns = match == null ? new String[]{decoratorId} : 
match.value();
+        String[] patterns = match == null ? new String[] {decoratorId} : 
match.value();
 
         DecoratorDef def = new DecoratorDefImpl(decoratorId, method, patterns, 
constraints, classFactory);
 

Modified: 
tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/IOCMessages.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/IOCMessages.java?rev=693326&r1=693325&r2=693326&view=diff
==============================================================================
--- 
tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/IOCMessages.java
 (original)
+++ 
tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/IOCMessages.java
 Mon Sep  8 17:27:32 2008
@@ -112,11 +112,6 @@
         return MESSAGES.format("unknown-scope", name);
     }
 
-    static String decoratorMethodNeedsDelegateParameter(Method method)
-    {
-        return MESSAGES.format("decorator-method-needs-delegate-parameter", 
asString(method));
-    }
-
     static String decoratorReturnedWrongType(Method method, String serviceId, 
Object returned, Class serviceInterface)
     {
         return MESSAGES.format("decorator-returned-wrong-type", 
asString(method), serviceId, returned,

Modified: 
tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/ServiceDecoratorImpl.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/ServiceDecoratorImpl.java?rev=693326&r1=693325&r2=693326&view=diff
==============================================================================
--- 
tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/ServiceDecoratorImpl.java
 (original)
+++ 
tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/ServiceDecoratorImpl.java
 Mon Sep  8 17:27:32 2008
@@ -62,7 +62,6 @@
         parameterDefaults.put(ServiceResources.class, resources);
         parameterDefaults.put(Logger.class, logger);
         parameterDefaults.put(Class.class, serviceInterface);
-
     }
 
     private String methodId()
@@ -76,6 +75,7 @@
 
         Map<Class, Object> parameterDefaults = newMap(this.parameterDefaults);
         parameterDefaults.put(Object.class, delegate);
+        parameterDefaults.put(serviceInterface, delegate);
 
         if (logger.isDebugEnabled()) 
logger.debug(IOCMessages.invokingMethod(methodId()));
 

Modified: 
tapestry/tapestry5/trunk/tapestry-ioc/src/main/resources/org/apache/tapestry5/ioc/internal/IOCStrings.properties
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/resources/org/apache/tapestry5/ioc/internal/IOCStrings.properties?rev=693326&r1=693325&r2=693326&view=diff
==============================================================================
--- 
tapestry/tapestry5/trunk/tapestry-ioc/src/main/resources/org/apache/tapestry5/ioc/internal/IOCStrings.properties
 (original)
+++ 
tapestry/tapestry5/trunk/tapestry-ioc/src/main/resources/org/apache/tapestry5/ioc/internal/IOCStrings.properties
 Mon Sep  8 17:27:32 2008
@@ -33,9 +33,6 @@
 many-services-match-marker=Unable to locate a single service assignable to 
type %s with marker annotation(s) %s.  \
  All of the following services match: %s.
 unknown-scope=Unknown service scope '%s'.
-decorator-method-needs-delegate-parameter=Decorator methods must a parameter 
for the service delegate \
- (i.e., the object the created interceptor will delegate to). \
- Method %s does not include such a parameter, and has been ignored.
 decorator-returned-wrong-type=Decorator method %s (invoked for service '%s') 
returned %s, \
   which is not assignable to the %s service interface.
 creating-service=Creating service '%s'.

Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/site/apt/decorator.apt
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/site/apt/decorator.apt?rev=693326&r1=693325&r2=693326&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/site/apt/decorator.apt (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/site/apt/decorator.apt Mon Sep  8 
17:27:32 2008
@@ -91,9 +91,9 @@
    The values that may be provided to a decorator method are exactly the same 
as for a builder
    method, with one addition:  The underlying service will be passed in
    as a parameter of type java.lang.Object (after type erasure, the <<<T 
delegate>>> parameter
-   becomes <<<Object delegate>>>).  A decorator method must have one
-   parameter for this purpose.
-   
+   becomes <<<Object delegate>>>).
+
+
    In the above example, the decorator method recieves the core service 
implementation,
    the service interface for the Indexer service, the Log for the Indexer 
service,
    and an interceptor factory that generates logging interceptors.
@@ -104,7 +104,22 @@
    
    The return value of the method is the new interceptor. You may return null 
if your
    decorator method decides not to decorate the supplied service.
-   
+
+
+   Alternately, when targetting services whose type is known at compile time, 
you may provide
+   a parameter whose type matches the service interface.  For example, 
decorateIndexer() will
+   always be applied to the Indexer service, whose type (Indexer) is known. We 
could therefore rewrite
+   decorateIndexer() as:
+
++---------------------+
+  public static Indexer decorateIndexer(Indexer delegate, Logger logger, 
LoggingDecorator decorator)
+  {
+    return decorator.build(Indexer.class, delegate, "Indexer", logger);
+  }
++---------------------+
+
+
+
    Of course, nothing stops you from combining building with decorating inside
    the service builder method:
    
@@ -117,10 +132,9 @@
 
 public class MyAppModule
 {
-  public static Indexer build(Class serviceInterface, Logger logger,
-    LoggingDecorator decorator)
+  public static Indexer build(Logger logger, LoggingDecorator decorator)
   {
-    return decorator.build(serviceInterface, logger,  new IndexerImpl());
+    return decorator.build(Indexer.class, logger,  new IndexerImpl());
   } 
 }
 +---------------------+   
@@ -205,6 +219,10 @@
    and that is passed to the last decorator method. The interceptor created 
there
    is passed to the the next-to-last decorator method, and so forth.
 
+   It should now be evident that the delegate passed into a decorator method 
is sometimes
+   the core service implementation, and some times an interceptor object 
created by some other
+   decorator method.
+
 Creating your own Decorators
 
   Decorators are a limited form of Aspect Oriented Programming, so we have

Modified: 
tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/IntegrationTest.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/IntegrationTest.java?rev=693326&r1=693325&r2=693326&view=diff
==============================================================================
--- 
tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/IntegrationTest.java
 (original)
+++ 
tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/IntegrationTest.java
 Mon Sep  8 17:27:32 2008
@@ -183,7 +183,6 @@
         List<String> names = service.getNames();
 
         assertEquals(names, Arrays.asList("BARNEY", "FRED"));
-
     }
 
     @SuppressWarnings("unchecked")
@@ -903,4 +902,16 @@
 
         r.shutdown();
     }
+
+    @Test
+    public void decorator_receive_delegate_by_specific_type()
+    {
+        Registry r = buildRegistry(GreeterModule.class, 
SpecificDecoratorModule.class);
+
+        Greeter g = r.getService("HelloGreeter", Greeter.class);
+
+        assertEquals(g.getGreeting(), "HELLO");
+
+        r.shutdown();
+    }
 }

Added: 
tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/SpecificDecoratorModule.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/SpecificDecoratorModule.java?rev=693326&view=auto
==============================================================================
--- 
tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/SpecificDecoratorModule.java
 (added)
+++ 
tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/SpecificDecoratorModule.java
 Mon Sep  8 17:27:32 2008
@@ -0,0 +1,29 @@
+//  Copyright 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.tapestry5.ioc;
+
+public class SpecificDecoratorModule
+{
+    public Greeter decorateHelloGreeter(final Greeter delegate)
+    {
+        return new Greeter()
+        {
+            public String getGreeting()
+            {
+                return delegate.getGreeting().toUpperCase();
+            }
+        };
+    }
+}

Modified: 
tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/DefaultModuleDefImplTest.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/DefaultModuleDefImplTest.java?rev=693326&r1=693325&r2=693326&view=diff
==============================================================================
--- 
tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/DefaultModuleDefImplTest.java
 (original)
+++ 
tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/DefaultModuleDefImplTest.java
 Mon Sep  8 17:27:32 2008
@@ -233,25 +233,6 @@
     }
 
     @Test
-    public void decorator_method_does_not_include_delegate_parameter() throws 
Exception
-    {
-        Class moduleClass = NoDelegateDecoratorMethodModule.class;
-        Method m = moduleClass.getMethod("decorateNoDelegate");
-
-        Logger logger = mockLogger();
-
-        logger.warn(IOCMessages.decoratorMethodNeedsDelegateParameter(m));
-
-        replay();
-
-        ModuleDef md = new DefaultModuleDefImpl(moduleClass, logger, null);
-
-        assertTrue(md.getDecoratorDefs().isEmpty());
-
-        verify();
-    }
-
-    @Test
     public void contribution_without_annotation()
     {
         attemptConfigurationMethod(SimpleModule.class, "Barney", 
"contributeBarney(Configuration)");


Reply via email to