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/05/15 01:19:42 UTC

svn commit: r944513 - in /tapestry/tapestry5/trunk/tapestry-ioc/src: main/java/org/apache/tapestry5/ioc/internal/services/ main/java/org/apache/tapestry5/ioc/services/ test/java/org/apache/tapestry5/ioc/internal/services/

Author: hlship
Date: Fri May 14 23:19:42 2010
New Revision: 944513

URL: http://svn.apache.org/viewvc?rev=944513&view=rev
Log:
TAP5-1152: TypeCoercer should include a method exposing the coercion it would use for a given source and target type

Modified:
    tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/TypeCoercerImpl.java
    tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/services/TypeCoercer.java
    tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/services/TypeCoercerImplTest.java

Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/TypeCoercerImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/TypeCoercerImpl.java?rev=944513&r1=944512&r2=944513&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/TypeCoercerImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/TypeCoercerImpl.java Fri May 14 23:19:42 2010
@@ -100,6 +100,14 @@ public class TypeCoercerImpl implements 
      */
     private final Map<Class, TargetCoercion> typeToTargetCoercion = new WeakHashMap<Class, TargetCoercion>();
 
+    private static final Coercion NO_COERCION = new Coercion<Object, Object>()
+    {
+        public Object coerce(Object input)
+        {
+            return input;
+        }
+    };
+
     private static final Coercion COERCION_NULL_TO_OBJECT = new Coercion<Void, Object>()
     {
         public Object coerce(Void input)
@@ -138,21 +146,36 @@ public class TypeCoercerImpl implements 
     }
 
     @SuppressWarnings("unchecked")
-    public <S, T> String explain(Class<S> inputType, Class<T> targetType)
+    public <S, T> Coercion<S, T> getCoercion(Class<S> sourceType, Class<T> targetType)
+    {
+        Defense.notNull(sourceType, "sourceType");
+        Defense.notNull(targetType, "targetType");
+
+        Class effectiveSourceType = ClassFabUtils.getWrapperType(sourceType);
+        Class effectiveTargetType = ClassFabUtils.getWrapperType(targetType);
+
+        if (effectiveTargetType.isAssignableFrom(effectiveSourceType))
+            return NO_COERCION;
+
+        return getTargetCoercion(effectiveTargetType).getCoercion(effectiveSourceType);
+    }
+
+    @SuppressWarnings("unchecked")
+    public <S, T> String explain(Class<S> sourceType, Class<T> targetType)
     {
-        Defense.notNull(inputType, "inputType");
+        Defense.notNull(sourceType, "effectiveInputType");
         Defense.notNull(targetType, "targetType");
 
         Class effectiveTargetType = ClassFabUtils.getWrapperType(targetType);
-        Class effctiveInputType = ClassFabUtils.getWrapperType(inputType);
+        Class effectiveSourceType = ClassFabUtils.getWrapperType(sourceType);
 
         // Is a coercion even necessary? Not if the target type is assignable from the
         // input value.
 
-        if (effectiveTargetType.isAssignableFrom(effctiveInputType))
+        if (effectiveTargetType.isAssignableFrom(effectiveSourceType))
             return "";
 
-        return getTargetCoercion(targetType).explain(inputType);
+        return getTargetCoercion(targetType).explain(sourceType);
     }
 
     private synchronized TargetCoercion getTargetCoercion(Class targetType)

Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/services/TypeCoercer.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/services/TypeCoercer.java?rev=944513&r1=944512&r2=944513&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/services/TypeCoercer.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/services/TypeCoercer.java Fri May 14 23:19:42 2010
@@ -1,10 +1,10 @@
-// Copyright 2006, 2007, 2008 The Apache Software Foundation
+// Copyright 2006, 2007, 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,
@@ -17,7 +17,7 @@ package org.apache.tapestry5.ioc.service
 import org.apache.tapestry5.ioc.annotations.UsesConfiguration;
 
 /**
- * Makes use of {@link org.apache.tapestry5.ioc.services.Coercion}s  to convert between an input value (of some specific
+ * Makes use of {@link org.apache.tapestry5.ioc.services.Coercion}s to convert between an input value (of some specific
  * type) and a desired output type. Smart about coercing, even if it requires multiple coercion steps (i.e., via an
  * intermediate type, such as String).
  */
@@ -32,26 +32,53 @@ public interface TypeCoercer
      * <p/>
      * <p/>
      * The TypeCoercer also caches the results of a coercion search.
-     *
-     * @param <S>        source type (input)
-     * @param <T>        target type (output)
+     * 
+     * @param <S>
+     *            source type (input)
+     * @param <T>
+     *            target type (output)
      * @param input
-     * @param targetType defines the target type
+     * @param targetType
+     *            defines the target type
      * @return the coerced value
      */
     <S, T> T coerce(S input, Class<T> targetType);
 
     /**
+     * Given a source and target type, computes the coercion that will be used.
+     * <p>
+     * Note: holding the returned coercion past the time when {@linkplain #clearCache() the cache is cleared} can cause
+     * a memory leak, especially in the context of live reloading (wherein holding a reference to a single class make
+     * keep an entire ClassLoader from being reclaimed).
+     * 
+     * @since 5.2.0
+     * @param <S>
+     *            source type (input)
+     * @param <T>
+     *            target type (output)
+     * @param sourceType
+     *            type to coerce from
+     * @param targetType
+     *            defines the target type
+     * @return the coercion that will ultimately be used
+     */
+    <S, T> Coercion<S, T> getCoercion(Class<S> sourceType, Class<T> targetType);
+
+    /**
      * Used primarily inside test suites, this method performs the same steps as {@link #coerce(Object, Class)}, but
      * returns a string describing the series of coercision, such as "Object --&gt; String --&gt; Long --&gt; Integer".
-     *
-     * @param <S>        source type (input)
-     * @param <T>        target type (output)
-     * @param inputType  the source coercion type (use void.class for coercions from null)
-     * @param targetType defines the target type
+     * 
+     * @param <S>
+     *            source type (input)
+     * @param <T>
+     *            target type (output)
+     * @param sourceType
+     *            the source coercion type (use void.class for coercions from null)
+     * @param targetType
+     *            defines the target type
      * @return a string identifying the series of coercions, or the empty string if no coercion is necessary
      */
-    <S, T> String explain(Class<S> inputType, Class<T> targetType);
+    <S, T> String explain(Class<S> sourceType, Class<T> targetType);
 
     /**
      * Clears cached information stored by the TypeCoercer.

Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/services/TypeCoercerImplTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/services/TypeCoercerImplTest.java?rev=944513&r1=944512&r2=944513&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/services/TypeCoercerImplTest.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/services/TypeCoercerImplTest.java Fri May 14 23:19:42 2010
@@ -16,6 +16,7 @@ package org.apache.tapestry5.ioc.interna
 
 import org.apache.tapestry5.ioc.internal.IOCInternalTestCase;
 import org.apache.tapestry5.ioc.internal.util.CollectionFactory;
+import org.apache.tapestry5.ioc.services.Coercion;
 import org.apache.tapestry5.ioc.services.TypeCoercer;
 import org.apache.tapestry5.ioc.util.TimeInterval;
 import org.testng.annotations.AfterClass;
@@ -63,12 +64,17 @@ public class TypeCoercerImplTest extends
         assertEquals(coercer.coerce(227l, int.class), new Integer(227));
     }
 
+    @SuppressWarnings("unchecked")
     @Test
     public void no_coercion_necessary()
     {
         Object input = new Integer(-37);
 
         assertSame(coercer.coerce(input, Number.class), input);
+
+        Coercion coercion = coercer.getCoercion(int.class, Number.class);
+
+        assertSame(coercion.coerce(input), input);
     }
 
     @Test
@@ -145,6 +151,10 @@ public class TypeCoercerImplTest extends
         Object actual = coercer.coerce(input, targetType);
 
         assertEquals(actual, expected);
+
+        Coercion c = coercer.getCoercion(input == null ? void.class : input.getClass(), targetType);
+
+        assertEquals(c.coerce(input), expected);
     }
 
     @SuppressWarnings("unchecked")