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 2011/03/20 22:00:59 UTC

svn commit: r1083568 - in /tapestry/tapestry5/trunk: tapestry-core/src/main/java/org/apache/tapestry5/services/ tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/ tapestry-ioc/src/main/resources/org/apache/tapestry5/ioc/internal/ tapestry-io...

Author: hlship
Date: Sun Mar 20 21:00:58 2011
New Revision: 1083568

URL: http://svn.apache.org/viewvc?rev=1083568&view=rev
Log:
TAP5-1356: When contributing to a service configuration, values should be coerced to the correct type rather than rejected if not the correct type

Added:
    tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/TypeCoercerProxy.java
    tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/TypeCoercerProxyImpl.java
    tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/ContributedValueCoercionModule.java
Modified:
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/TapestryModule.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/RegistryImpl.java
    tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/ValidatingConfigurationWrapper.java
    tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/ValidatingMappedConfigurationWrapper.java
    tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/ValidatingOrderedConfigurationWrapper.java
    tapestry/tapestry5/trunk/tapestry-ioc/src/main/resources/org/apache/tapestry5/ioc/internal/IOCStrings.properties
    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/IOCInternalTestCase.java
    tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/ValidatingConfigurationWrapperTest.java
    tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/ValidatingMappedConfigurationWrapperTest.java
    tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/ValidatingOrderedConfigurationWrapperTest.java

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=1083568&r1=1083567&r2=1083568&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 Sun Mar 20 21:00:58 2011
@@ -2394,7 +2394,7 @@ public final class TapestryModule
     /**
      * Contributes factory defaults that may be overridden.
      */
-    public static void contributeFactoryDefaults(MappedConfiguration<String, String> configuration)
+    public static void contributeFactoryDefaults(MappedConfiguration<String, Object> configuration)
     {
         // Remember this is request-to-request time, presumably it'll take the
         // developer more than
@@ -2420,15 +2420,15 @@ public final class TapestryModule
         configuration.add(SymbolConstants.DEFAULT_STYLESHEET, "classpath:/org/apache/tapestry5/default.css");
         configuration.add("tapestry.spacer-image", "classpath:/org/apache/tapestry5/spacer.gif");
 
-        configuration.add(SymbolConstants.SUPPRESS_REDIRECT_FROM_ACTION_REQUESTS, "false");
+        configuration.add(SymbolConstants.SUPPRESS_REDIRECT_FROM_ACTION_REQUESTS, false);
 
-        configuration.add(SymbolConstants.PRODUCTION_MODE, "true");
+        configuration.add(SymbolConstants.PRODUCTION_MODE, true);
 
-        configuration.add(SymbolConstants.COMPRESS_WHITESPACE, "true");
+        configuration.add(SymbolConstants.COMPRESS_WHITESPACE, true);
 
-        configuration.add(MetaDataConstants.SECURE_PAGE, "false");
+        configuration.add(MetaDataConstants.SECURE_PAGE, false);
 
-        configuration.add(SymbolConstants.FORM_CLIENT_LOGIC_ENABLED, "true");
+        configuration.add(SymbolConstants.FORM_CLIENT_LOGIC_ENABLED, true);
 
         // This is designed to make it easy to keep synchronized with
         // script.aculo.ous. As we support a new version, we create a new folder, and update the
@@ -2459,29 +2459,29 @@ public final class TapestryModule
 
         configuration.add(SymbolConstants.EXCEPTION_REPORT_PAGE, "ExceptionReport");
 
-        configuration.add(SymbolConstants.MIN_GZIP_SIZE, "100");
+        configuration.add(SymbolConstants.MIN_GZIP_SIZE, 100);
 
         Random random = new Random(System.currentTimeMillis());
 
         configuration.add(SymbolConstants.APPLICATION_VERSION, Long.toHexString(random.nextLong()));
 
-        configuration.add(SymbolConstants.OMIT_GENERATOR_META, "false");
+        configuration.add(SymbolConstants.OMIT_GENERATOR_META, false);
 
         configuration.add(SymbolConstants.SECURE_ENABLED, SymbolConstants.PRODUCTION_MODE_VALUE);
         configuration.add(SymbolConstants.COMPACT_JSON, SymbolConstants.PRODUCTION_MODE_VALUE);
 
-        configuration.add(SymbolConstants.ENCODE_LOCALE_INTO_PATH, "true");
+        configuration.add(SymbolConstants.ENCODE_LOCALE_INTO_PATH, true);
 
-        configuration.add(SymbolConstants.BLACKBIRD_ENABLED, "false");
+        configuration.add(SymbolConstants.BLACKBIRD_ENABLED, false);
 
         configuration.add(InternalSymbols.PRE_SELECTED_FORM_NAMES, "reset,submit,select,id,method,action,onsubmit");
 
-        configuration.add(SymbolConstants.COMPONENT_RENDER_TRACING_ENABLED, "false");
+        configuration.add(SymbolConstants.COMPONENT_RENDER_TRACING_ENABLED, false);
 
         // The default values denote "use values from request"
         configuration.add(SymbolConstants.HOSTNAME, "");
-        configuration.add(SymbolConstants.HOSTPORT, "0");
-        configuration.add(SymbolConstants.HOSTPORT_SECURE, "0");
+        configuration.add(SymbolConstants.HOSTPORT, 0);
+        configuration.add(SymbolConstants.HOSTPORT_SECURE, 0);
     }
 
     /**

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=1083568&r1=1083567&r2=1083568&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 Sun Mar 20 21:00:58 2011
@@ -172,12 +172,6 @@ final class IOCMessages
         return MESSAGES.format("contribution-key-was-null", serviceId);
     }
 
-    static String contributionWrongValueType(String serviceId, Class actualClass,
-                                             Class expectedClass)
-    {
-        return MESSAGES.format("contribution-wrong-value-type", serviceId, actualClass
-                .getName(), expectedClass.getName());
-    }
 
     static String contributionWrongKeyType(String serviceId, Class actualClass,
                                            Class expectedClass)

Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/RegistryImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/RegistryImpl.java?rev=1083568&r1=1083567&r2=1083568&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/RegistryImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/RegistryImpl.java Sun Mar 20 21:00:58 2011
@@ -1,4 +1,4 @@
-// Copyright 2006, 2007, 2008, 2009, 2010 The Apache Software Foundation
+// Copyright 2006, 2007, 2008, 2009, 2010, 2011 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.
@@ -74,6 +74,7 @@ import org.apache.tapestry5.ioc.services
 import org.apache.tapestry5.ioc.services.Status;
 import org.apache.tapestry5.ioc.services.SymbolSource;
 import org.apache.tapestry5.ioc.services.TapestryIOCModule;
+import org.apache.tapestry5.ioc.services.TypeCoercer;
 import org.apache.tapestry5.ioc.util.AvailableValues;
 import org.apache.tapestry5.ioc.util.UnknownValueException;
 import org.apache.tapestry5.services.UpdateListenerHub;
@@ -147,6 +148,8 @@ public class RegistryImpl implements Reg
 
     private final OperationTracker operationTracker;
 
+    private final TypeCoercerProxy typeCoercerProxy = new TypeCoercerProxyImpl(this);
+
     /**
      * Constructs the registry from a set of module definitions and other resources.
      * 
@@ -566,7 +569,7 @@ public class RegistryImpl implements Reg
         for (final ContributionDef def : contributions)
         {
             final MappedConfiguration<K, V> validating = new ValidatingMappedConfigurationWrapper<K, V>(valueType,
-                    resources, map, overrides, serviceId, def, keyClass, keyToContribution);
+                    resources, typeCoercerProxy, map, overrides, serviceId, def, keyClass, keyToContribution);
 
             String description = IOCMessages.invokingMethod(def);
 
@@ -600,8 +603,8 @@ public class RegistryImpl implements Reg
 
         for (final ContributionDef def : contributions)
         {
-            final Configuration<T> validating = new ValidatingConfigurationWrapper<T>(valueType, resources, collection,
-                    serviceId);
+            final Configuration<T> validating = new ValidatingConfigurationWrapper<T>(valueType, resources,
+                    typeCoercerProxy, collection, serviceId);
 
             String description = IOCMessages.invokingMethod(def);
 
@@ -636,7 +639,7 @@ public class RegistryImpl implements Reg
         for (final ContributionDef def : contributions)
         {
             final OrderedConfiguration<T> validating = new ValidatingOrderedConfigurationWrapper<T>(valueType,
-                    resources, orderer, overrides, def, serviceId);
+                    resources, typeCoercerProxy, orderer, overrides, def, serviceId);
 
             String description = IOCMessages.invokingMethod(def);
 
@@ -1098,5 +1101,4 @@ public class RegistryImpl implements Reg
     {
         return markerToServiceDef.keySet();
     }
-
 }

Added: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/TypeCoercerProxy.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/TypeCoercerProxy.java?rev=1083568&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/TypeCoercerProxy.java (added)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/TypeCoercerProxy.java Sun Mar 20 21:00:58 2011
@@ -0,0 +1,43 @@
+// Copyright 2011 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.internal;
+
+import org.apache.tapestry5.ioc.services.TypeCoercer;
+
+/**
+ * A simplified version of {@link TypeCoercer} used to defer the instantiation of the actual TypeCoercer
+ * service until necessary.
+ * 
+ * @since 5.3.0
+ */
+public interface TypeCoercerProxy
+{
+    /**
+     * Returns input cast to targetType if input is an instance of target type, otherwise delegates
+     * to {@link TypeCoercer#coerce(Object, Class)}.
+     * 
+     * @param <S>
+     * @param <T>
+     * @param input
+     *            value to be coerced
+     * @param targetType
+     *            desired type of value
+     * @return the value, coerced
+     * @throws RuntimeException
+     *             if the input can not be coerced
+     */
+    <S, T> T coerce(S input, Class<T> targetType);
+
+}

Added: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/TypeCoercerProxyImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/TypeCoercerProxyImpl.java?rev=1083568&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/TypeCoercerProxyImpl.java (added)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/TypeCoercerProxyImpl.java Sun Mar 20 21:00:58 2011
@@ -0,0 +1,52 @@
+// Copyright 2011 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.internal;
+
+import org.apache.tapestry5.ioc.ObjectLocator;
+import org.apache.tapestry5.ioc.services.TypeCoercer;
+
+/**
+ * A proxy for the {@link TypeCoercer}
+ * 
+ * @since 5.3.0
+ */
+public final class TypeCoercerProxyImpl implements TypeCoercerProxy
+{
+    private final ObjectLocator locator;
+
+    private TypeCoercer delegate;
+
+    public TypeCoercerProxyImpl(ObjectLocator locator)
+    {
+        this.locator = locator;
+    }
+
+    private synchronized TypeCoercer delegate()
+    {
+        if (delegate == null)
+            delegate = locator.getService(TypeCoercer.class);
+
+        return delegate;
+    }
+
+    public <S, T> T coerce(S input, Class<T> targetType)
+    {
+        if (targetType.isInstance(input))
+            return targetType.cast(input);
+
+        return delegate().coerce(input, targetType);
+    }
+
+}

Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/ValidatingConfigurationWrapper.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/ValidatingConfigurationWrapper.java?rev=1083568&r1=1083567&r2=1083568&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/ValidatingConfigurationWrapper.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/ValidatingConfigurationWrapper.java Sun Mar 20 21:00:58 2011
@@ -1,4 +1,4 @@
-// Copyright 2006, 2007, 2008, 2010 The Apache Software Foundation
+// Copyright 2006, 2007, 2008, 2010,, 2011 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.
@@ -25,16 +25,19 @@ import org.apache.tapestry5.ioc.ObjectLo
  */
 public class ValidatingConfigurationWrapper<T> extends AbstractConfigurationImpl<T> implements Configuration<T>
 {
+    private final TypeCoercerProxy typeCoercer;
+
     private final String serviceId;
 
     private final Class<T> expectedType;
 
     private final Collection<T> collection;
 
-    public ValidatingConfigurationWrapper(Class<T> expectedType, ObjectLocator locator, Collection<T> collection,
-            String serviceId)
+    public ValidatingConfigurationWrapper(Class<T> expectedType, ObjectLocator locator, TypeCoercerProxy typeCoercer,
+            Collection<T> collection, String serviceId)
     {
         super(expectedType, locator);
+        this.typeCoercer = typeCoercer;
 
         this.collection = collection;
         this.serviceId = serviceId;
@@ -46,13 +49,9 @@ public class ValidatingConfigurationWrap
         if (object == null)
             throw new NullPointerException(IOCMessages.contributionWasNull(serviceId));
 
-        // Sure, we say it is type T ... but is it really?
-
-        if (!expectedType.isInstance(object))
-            throw new IllegalArgumentException(IOCMessages.contributionWrongValueType(serviceId, object.getClass(),
-                    expectedType));
+        T coerced = typeCoercer.coerce(object, expectedType);
 
-        collection.add(object);
+        collection.add(coerced);
     }
 
     public void addInstance(Class<? extends T> clazz)

Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/ValidatingMappedConfigurationWrapper.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/ValidatingMappedConfigurationWrapper.java?rev=1083568&r1=1083567&r2=1083568&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/ValidatingMappedConfigurationWrapper.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/ValidatingMappedConfigurationWrapper.java Sun Mar 20 21:00:58 2011
@@ -1,4 +1,4 @@
-// Copyright 2006, 2007, 2008, 2009, 2010 The Apache Software Foundation
+// Copyright 2006, 2007, 2008, 2009, 2010, 2011 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.
@@ -39,6 +39,8 @@ import org.apache.tapestry5.ioc.def.Cont
 public class ValidatingMappedConfigurationWrapper<K, V> extends AbstractConfigurationImpl<V> implements
         MappedConfiguration<K, V>
 {
+    private final TypeCoercerProxy typeCoercer;
+
     private final Map<K, V> map;
 
     private final Map<K, MappedConfigurationOverride<K, V>> overrides;
@@ -53,12 +55,14 @@ public class ValidatingMappedConfigurati
 
     private final Map<K, ContributionDef> keyToContributor;
 
-    public ValidatingMappedConfigurationWrapper(Class<V> expectedValueType, ObjectLocator locator, Map<K, V> map,
-            Map<K, MappedConfigurationOverride<K, V>> overrides, String serviceId, ContributionDef contributionDef,
-            Class<K> expectedKeyType, Map<K, ContributionDef> keyToContributor)
+    public ValidatingMappedConfigurationWrapper(Class<V> expectedValueType, ObjectLocator locator,
+            TypeCoercerProxy typeCoercer, Map<K, V> map, Map<K, MappedConfigurationOverride<K, V>> overrides,
+            String serviceId, ContributionDef contributionDef, Class<K> expectedKeyType,
+            Map<K, ContributionDef> keyToContributor)
     {
         super(expectedValueType, locator);
 
+        this.typeCoercer = typeCoercer;
         this.map = map;
         this.overrides = overrides;
         this.serviceId = serviceId;
@@ -75,14 +79,14 @@ public class ValidatingMappedConfigurati
         if (value == null)
             throw new NullPointerException(IOCMessages.contributionWasNull(serviceId));
 
-        validateValue(value);
+        V coerced = typeCoercer.coerce(value, expectedValueType);
 
         ContributionDef existing = keyToContributor.get(key);
 
         if (existing != null)
             throw new IllegalArgumentException(IOCMessages.contributionDuplicateKey(serviceId, existing));
 
-        map.put(key, value);
+        map.put(key, coerced);
 
         // Remember that this key is provided by this contribution, when looking
         // for future conflicts.
@@ -90,18 +94,14 @@ public class ValidatingMappedConfigurati
         keyToContributor.put(key, contributionDef);
     }
 
-    private void validateValue(V value)
-    {
-        if (!expectedValueType.isInstance(value))
-            throw new IllegalArgumentException(IOCMessages.contributionWrongValueType(serviceId, value.getClass(),
-                    expectedValueType));
-    }
-
     private void validateKey(K key)
     {
         if (key == null)
             throw new NullPointerException(IOCMessages.contributionKeyWasNull(serviceId));
 
+        // Key types don't get coerced; not worth the effort, keys are almost always String or Class
+        // anyway.
+
         if (!expectedKeyType.isInstance(key))
             throw new IllegalArgumentException(IOCMessages.contributionWrongKeyType(serviceId, key.getClass(),
                     expectedKeyType));
@@ -116,8 +116,7 @@ public class ValidatingMappedConfigurati
     {
         validateKey(key);
 
-        if (value != null)
-            validateValue(value);
+        V coerced = value == null ? null : typeCoercer.coerce(value, expectedValueType);
 
         MappedConfigurationOverride<K, V> existing = overrides.get(key);
 
@@ -125,7 +124,7 @@ public class ValidatingMappedConfigurati
             throw new IllegalArgumentException(String.format(
                     "Contribution key %s has already been overridden (by %s).", key, existing.getContribDef()));
 
-        overrides.put(key, new MappedConfigurationOverride<K, V>(contributionDef, map, key, value));
+        overrides.put(key, new MappedConfigurationOverride<K, V>(contributionDef, map, key, coerced));
     }
 
     public void overrideInstance(K key, Class<? extends V> clazz)

Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/ValidatingOrderedConfigurationWrapper.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/ValidatingOrderedConfigurationWrapper.java?rev=1083568&r1=1083567&r2=1083568&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/ValidatingOrderedConfigurationWrapper.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/ValidatingOrderedConfigurationWrapper.java Sun Mar 20 21:00:58 2011
@@ -1,4 +1,4 @@
-// Copyright 2006, 2007, 2008, 2009, 2010 The Apache Software Foundation
+// Copyright 2006, 2007, 2008, 2009, 2010, 2011 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.
@@ -31,6 +31,8 @@ import org.apache.tapestry5.ioc.internal
 public class ValidatingOrderedConfigurationWrapper<T> extends AbstractConfigurationImpl<T> implements
         OrderedConfiguration<T>
 {
+    private final TypeCoercerProxy typeCoercer;
+
     private final Orderer<T> orderer;
 
     private final String serviceId;
@@ -41,10 +43,12 @@ public class ValidatingOrderedConfigurat
 
     private final ContributionDef contribDef;
 
-    public ValidatingOrderedConfigurationWrapper(Class<T> expectedType, ObjectLocator locator, Orderer<T> orderer,
-            Map<String, OrderedConfigurationOverride<T>> overrides, ContributionDef contribDef, String serviceId)
+    public ValidatingOrderedConfigurationWrapper(Class<T> expectedType, ObjectLocator locator,
+            TypeCoercerProxy typeCoercer, Orderer<T> orderer, Map<String, OrderedConfigurationOverride<T>> overrides,
+            ContributionDef contribDef, String serviceId)
     {
         super(expectedType, locator);
+        this.typeCoercer = typeCoercer;
 
         this.orderer = orderer;
         this.overrides = overrides;
@@ -55,15 +59,16 @@ public class ValidatingOrderedConfigurat
 
     public void add(String id, T object, String... constraints)
     {
-        checkValid(object);
+        T coerced = object == null ? null : typeCoercer.coerce(object, expectedType);
 
-        orderer.add(id, object, constraints);
+        orderer.add(id, coerced, constraints);
     }
 
     public void override(String id, T object, String... constraints)
     {
         assert InternalUtils.isNonBlank(id);
-        checkValid(object);
+
+        T coerced = object == null ? null : typeCoercer.coerce(object, expectedType);
 
         OrderedConfigurationOverride<T> existing = overrides.get(id);
 
@@ -71,7 +76,7 @@ public class ValidatingOrderedConfigurat
             throw new IllegalArgumentException(String.format("Contribution '%s' has already been overridden (by %s).",
                     id, existing.getContribDef()));
 
-        overrides.put(id, new OrderedConfigurationOverride<T>(orderer, id, object, constraints, contribDef));
+        overrides.put(id, new OrderedConfigurationOverride<T>(orderer, id, coerced, constraints, contribDef));
     }
 
     public void addInstance(String id, Class<? extends T> clazz, String... constraints)
@@ -83,13 +88,4 @@ public class ValidatingOrderedConfigurat
     {
         override(id, instantiate(clazz), constraints);
     }
-
-    private void checkValid(T object)
-    {
-        if (object == null || expectedType.isInstance(object))
-            return;
-
-        throw new IllegalArgumentException(IOCMessages.contributionWrongValueType(serviceId, object.getClass(),
-                expectedType));
-    }
 }

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=1083568&r1=1083567&r2=1083568&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 Sun Mar 20 21:00:58 2011
@@ -52,8 +52,6 @@ no-contribution-parameter=Service contri
 contribution-method-error=Error invoking service contribution method %s: %s
 contribution-was-null=Service contribution (to service '%s') was null.
 contribution-key-was-null=Key for service contribution (to service '%s') was null.
-contribution-wrong-value-type=Service contribution (to service '%s') was an instance of %s, \
-  which is not assignable to the configuration type %s.
 contribution-wrong-key-type=Key for service contribution (to service '%s') was an instance of %s, \
   but the expected key type was %s.
 contribution-duplicate-key=Service contribution (to service '%s') conflicts with existing contribution (by %s).

Added: tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/ContributedValueCoercionModule.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/ContributedValueCoercionModule.java?rev=1083568&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/ContributedValueCoercionModule.java (added)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/ContributedValueCoercionModule.java Sun Mar 20 21:00:58 2011
@@ -0,0 +1,31 @@
+// Copyright 2011 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;
+
+import org.apache.tapestry5.ioc.annotations.Contribute;
+import org.apache.tapestry5.ioc.services.FactoryDefaults;
+import org.apache.tapestry5.ioc.services.SymbolProvider;
+
+public class ContributedValueCoercionModule
+{
+    @Contribute(SymbolProvider.class)
+    @FactoryDefaults
+    public static void contributeValuesRequiringCoercion(MappedConfiguration<String, Object> configuration)
+    {
+        configuration.add("bool-true", true);
+        configuration.add("bool-false", false);
+        configuration.add("num-12345", 12345);
+    }
+}

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=1083568&r1=1083567&r2=1083568&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 Sun Mar 20 21:00:58 2011
@@ -1,4 +1,4 @@
-// Copyright 2006, 2007, 2008, 2009, 2010 The Apache Software Foundation
+// Copyright 2006, 2007, 2008, 2009, 2010, 2011 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.
@@ -866,7 +866,8 @@ public class IntegrationTest extends IOC
             if (serviceId.equals("ClassFactory"))
                 assertEquals(a.getStatus(), Status.BUILTIN);
 
-            if (serviceId.equals("RedGreeter1")) {
+            if (serviceId.equals("RedGreeter1"))
+            {
                 assertEquals(a.getStatus(), Status.DEFINED);
                 assertEquals(a.getMarkers().contains(BlueMarker.class), false);
                 assertEquals(a.getMarkers().contains(RedMarker.class), true);
@@ -875,7 +876,8 @@ public class IntegrationTest extends IOC
             if (serviceId.equals("TypeCoercer"))
                 assertEquals(a.getStatus(), Status.REAL);
 
-            if (serviceId.equals("BlueGreeter")) {
+            if (serviceId.equals("BlueGreeter"))
+            {
                 assertEquals(a.getStatus(), Status.VIRTUAL);
                 assertEquals(a.getMarkers().contains(BlueMarker.class), true);
                 assertEquals(a.getMarkers().contains(RedMarker.class), false);
@@ -1568,7 +1570,7 @@ public class IntegrationTest extends IOC
 
         r.shutdown();
     }
-   
+
     @Test
     public void advise_by_annotation()
     {
@@ -1581,12 +1583,12 @@ public class IntegrationTest extends IOC
         r.shutdown();
 
     }
-   
+
     @Test
     public void advise_by_locale_annotation()
     {
         Registry r = buildRegistry(GreeterModule2.class, AdviseByMarkerModule.class);
-       
+
         Greeter red = r.getService("RedGreeter", Greeter.class);
 
         assertEquals(red.getGreeting(), "delta[Red]");
@@ -1594,7 +1596,7 @@ public class IntegrationTest extends IOC
         r.shutdown();
 
     }
-   
+
     @Test
     public void decorate_by_annotation()
     {
@@ -1607,12 +1609,12 @@ public class IntegrationTest extends IOC
         r.shutdown();
 
     }
-   
+
     @Test
     public void decorate_by_locale_annotation()
     {
         Registry r = buildRegistry(GreeterModule2.class, DecorateByMarkerModule.class);
-       
+
         Greeter red = r.getService("RedGreeter", Greeter.class);
 
         assertEquals(red.getGreeting(), "Decorated by barney[Red]");
@@ -1650,4 +1652,16 @@ public class IntegrationTest extends IOC
 
         r.shutdown();
     }
+
+    @Test
+    public void contributed_values_may_be_coerced_to_correct_type()
+    {
+        Registry r = buildRegistry(ContributedValueCoercionModule.class);
+
+        SymbolSource source = r.getService(SymbolSource.class);
+
+        assertEquals(source.valueForSymbol("bool-true"), "true");
+        assertEquals(source.valueForSymbol("bool-false"), "false");
+        assertEquals(source.valueForSymbol("num-12345"), "12345");
+    }
 }

Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/IOCInternalTestCase.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/IOCInternalTestCase.java?rev=1083568&r1=1083567&r2=1083568&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/IOCInternalTestCase.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/IOCInternalTestCase.java Sun Mar 20 21:00:58 2011
@@ -1,4 +1,4 @@
-// Copyright 2006, 2007, 2009, 2010 The Apache Software Foundation
+// Copyright 2006, 2007, 2009, 2010, 2011 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.
@@ -146,4 +146,10 @@ public class IOCInternalTestCase extends
         return newMock(ServiceActivityTracker.class);
     }
 
+    /** @since 5.3.0 */
+    protected final TypeCoercerProxy mockTypeCoercerProxy()
+    {
+        return newMock(TypeCoercerProxy.class);
+    }
+
 }

Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/ValidatingConfigurationWrapperTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/ValidatingConfigurationWrapperTest.java?rev=1083568&r1=1083567&r2=1083568&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/ValidatingConfigurationWrapperTest.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/ValidatingConfigurationWrapperTest.java Sun Mar 20 21:00:58 2011
@@ -1,10 +1,10 @@
-// Copyright 2006, 2007, 2008 The Apache Software Foundation
+// Copyright 2006, 2007, 2008, 2009, 2011 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,
@@ -14,28 +14,31 @@
 
 package org.apache.tapestry5.ioc.internal;
 
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
 import org.apache.tapestry5.ioc.Configuration;
 import org.apache.tapestry5.ioc.ObjectLocator;
 import org.apache.tapestry5.ioc.internal.util.CollectionFactory;
 import org.testng.annotations.Test;
 
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
+@SuppressWarnings(
+{ "rawtypes", "unchecked" })
 public class ValidatingConfigurationWrapperTest extends IOCInternalTestCase
 {
-    @SuppressWarnings("unchecked")
     @Test
     public void valid_contribution()
     {
         List<Runnable> collection = CollectionFactory.newList();
         Runnable value = mockRunnable();
+        TypeCoercerProxy tc = mockTypeCoercerProxy();
+
+        expect(tc.coerce(value, Runnable.class)).andReturn(value);
 
         replay();
 
-        Configuration wrapper = new ValidatingConfigurationWrapper(Runnable.class, null,
-                                                                   collection, "foo.Bar");
+        Configuration wrapper = new ValidatingConfigurationWrapper(Runnable.class, null, tc, collection, "foo.Bar");
 
         wrapper.add(value);
 
@@ -44,35 +47,55 @@ public class ValidatingConfigurationWrap
         assertListsEquals(collection, value);
     }
 
-    @SuppressWarnings({"unchecked"})
+    @Test
+    public void coerced_contribution()
+    {
+        List<Runnable> collection = CollectionFactory.newList();
+        Runnable value = mockRunnable();
+        TypeCoercerProxy tc = mockTypeCoercerProxy();
+        String contributed = "coerceme";
+
+        expect(tc.coerce(contributed, Runnable.class)).andReturn(value);
+
+        replay();
+
+        Configuration wrapper = new ValidatingConfigurationWrapper(Runnable.class, null, tc, collection, "foo.Bar");
+
+        wrapper.add(contributed);
+
+        verify();
+
+        assertListsEquals(collection, value);
+    }
+
     @Test
     public void valid_class_contribution()
     {
         ObjectLocator locator = mockObjectLocator();
-        final HashMap value = new HashMap();
-        train_autobuild(locator, HashMap.class, value);
+        HashMap contributedValue = new HashMap();
+        train_autobuild(locator, HashMap.class, contributedValue);
         List<Map> collection = CollectionFactory.newList();
+        TypeCoercerProxy tc = mockTypeCoercerProxy();
+
+        expect(tc.coerce(contributedValue, Map.class)).andReturn(contributedValue);
 
         replay();
 
-        Configuration wrapper = new ValidatingConfigurationWrapper(Map.class, locator,
-                                                                   collection, "foo.Bar");
+        Configuration wrapper = new ValidatingConfigurationWrapper(Map.class, locator, tc, collection, "foo.Bar");
 
         wrapper.addInstance(HashMap.class);
 
         verify();
 
-        assertListsEquals(collection, value);
+        assertListsEquals(collection, contributedValue);
     }
 
-    @SuppressWarnings("unchecked")
     @Test
     public void null_contribution()
     {
         List<Runnable> collection = CollectionFactory.newList();
 
-        Configuration wrapper = new ValidatingConfigurationWrapper(Runnable.class, null, collection,
-                                                                   "Bar");
+        Configuration wrapper = new ValidatingConfigurationWrapper(Runnable.class, null, null, collection, "Bar");
 
         try
         {
@@ -85,25 +108,30 @@ public class ValidatingConfigurationWrap
         }
     }
 
-    @SuppressWarnings("unchecked")
     @Test
     public void wrong_type_of_contribution()
     {
         List<Runnable> collection = CollectionFactory.newList();
+        Throwable e = new RuntimeException("No go");
+        TypeCoercerProxy tc = mockTypeCoercerProxy();
+        String contributedValue = "runnable";
 
+        expect(tc.coerce(contributedValue, Runnable.class)).andThrow(e);
 
-        Configuration wrapper = new ValidatingConfigurationWrapper(Runnable.class, null, collection,
-                                                                   "Bar");
+        Configuration wrapper = new ValidatingConfigurationWrapper(Runnable.class, null, tc, collection, "Bar");
+
+        replay();
 
         try
         {
-            wrapper.add("runnable");
+            wrapper.add(contributedValue);
             unreachable();
         }
-        catch (IllegalArgumentException ex)
+        catch (RuntimeException ex)
         {
-            assertEquals(ex.getMessage(),
-                         "Service contribution (to service 'Bar') was an instance of java.lang.String, which is not assignable to the configuration type java.lang.Runnable.");
+            assertSame(ex, e);
         }
+
+        verify();
     }
 }

Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/ValidatingMappedConfigurationWrapperTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/ValidatingMappedConfigurationWrapperTest.java?rev=1083568&r1=1083567&r2=1083568&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/ValidatingMappedConfigurationWrapperTest.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/ValidatingMappedConfigurationWrapperTest.java Sun Mar 20 21:00:58 2011
@@ -1,10 +1,10 @@
-// Copyright 2006, 2007, 2008, 2009 The Apache Software Foundation
+// Copyright 2006, 2007, 2008, 2009, 2011 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,7 +16,6 @@ package org.apache.tapestry5.ioc.interna
 
 import static org.apache.tapestry5.ioc.internal.util.CollectionFactory.newMap;
 
-import java.util.List;
 import java.util.Map;
 
 import org.apache.tapestry5.ioc.MappedConfiguration;
@@ -25,6 +24,8 @@ import org.apache.tapestry5.ioc.def.Cont
 import org.apache.tapestry5.ioc.internal.util.CollectionFactory;
 import org.testng.annotations.Test;
 
+@SuppressWarnings(
+{ "rawtypes", "unchecked" })
 public class ValidatingMappedConfigurationWrapperTest extends IOCInternalTestCase
 {
     private static final String SERVICE_ID = "Baz";
@@ -36,14 +37,17 @@ public class ValidatingMappedConfigurati
         Map<Class, ContributionDef> keyToContribution = newMap();
         ObjectLocator locator = mockObjectLocator();
         Map<Class, Runnable> map = CollectionFactory.newMap();
+        TypeCoercerProxy tc = mockTypeCoercerProxy();
 
         Class key = Integer.class;
         Runnable value = mockRunnable();
 
+        expect(tc.coerce(value, Runnable.class)).andReturn(value);
+
         replay();
 
         MappedConfiguration<Class, Runnable> wrapper = new ValidatingMappedConfigurationWrapper<Class, Runnable>(
-                Runnable.class, locator, map, null, SERVICE_ID, def, Class.class, keyToContribution);
+                Runnable.class, locator, tc, map, null, SERVICE_ID, def, Class.class, keyToContribution);
 
         wrapper.add(key, value);
 
@@ -54,6 +58,34 @@ public class ValidatingMappedConfigurati
     }
 
     @Test
+    public void coerced_value()
+    {
+        ContributionDef def = mockContributionDef();
+        Map<Class, ContributionDef> keyToContribution = newMap();
+        ObjectLocator locator = mockObjectLocator();
+        Map<Class, Runnable> map = CollectionFactory.newMap();
+        TypeCoercerProxy tc = mockTypeCoercerProxy();
+        String contributedValue = "coerceme";
+
+        Class key = Integer.class;
+        Runnable value = mockRunnable();
+
+        expect(tc.coerce(contributedValue, Runnable.class)).andReturn(value);
+
+        replay();
+
+        MappedConfiguration<Class, Object> wrapper = new ValidatingMappedConfigurationWrapper(Runnable.class, locator,
+                tc, map, null, SERVICE_ID, def, Class.class, keyToContribution);
+
+        wrapper.add(key, contributedValue);
+
+        verify();
+
+        assertSame(map.get(key), value);
+        assertSame(keyToContribution.get(Integer.class), def);
+    }
+
+    @Test
     public void duplicate_key()
     {
         ContributionDef def1 = newContributionDef("contributionPlaceholder1");
@@ -61,16 +93,19 @@ public class ValidatingMappedConfigurati
         Map<Class, ContributionDef> keyToContribution = newMap();
         ObjectLocator locator = mockObjectLocator();
         Map<Class, Runnable> map = CollectionFactory.newMap();
+        TypeCoercerProxy tc = mockTypeCoercerProxy();
 
         keyToContribution.put(Integer.class, def1);
 
         Class key = Integer.class;
         Runnable value = mockRunnable();
 
+        expect(tc.coerce(value, Runnable.class)).andReturn(value);
+
         replay();
 
         MappedConfiguration<Class, Runnable> wrapper = new ValidatingMappedConfigurationWrapper<Class, Runnable>(
-                Runnable.class, locator, map, null, SERVICE_ID, def2, Class.class, keyToContribution);
+                Runnable.class, locator, tc, map, null, SERVICE_ID, def2, Class.class, keyToContribution);
 
         try
         {
@@ -79,8 +114,7 @@ public class ValidatingMappedConfigurati
         }
         catch (IllegalArgumentException ex)
         {
-            assertMessageContains(ex,
-                                  "Service contribution (to service 'Baz') conflicts with existing contribution");
+            assertMessageContains(ex, "Service contribution (to service 'Baz') conflicts with existing contribution");
         }
 
         verify();
@@ -101,7 +135,7 @@ public class ValidatingMappedConfigurati
         replay();
 
         MappedConfiguration<Class, Runnable> wrapper = new ValidatingMappedConfigurationWrapper<Class, Runnable>(
-                Runnable.class, locator, map, null, SERVICE_ID, def, Class.class, keyToContribution);
+                Runnable.class, locator, null, map, null, SERVICE_ID, def, Class.class, keyToContribution);
 
         try
         {
@@ -130,9 +164,8 @@ public class ValidatingMappedConfigurati
 
         replay();
 
-        MappedConfiguration wrapper = new ValidatingMappedConfigurationWrapper(Runnable.class, locator, map, null,
-                                                                               SERVICE_ID, def,
-                                                                               Class.class, keyToContribution);
+        MappedConfiguration wrapper = new ValidatingMappedConfigurationWrapper(Runnable.class, locator, null, map,
+                null, SERVICE_ID, def, Class.class, keyToContribution);
 
         try
         {
@@ -141,40 +174,9 @@ public class ValidatingMappedConfigurati
         }
         catch (IllegalArgumentException ex)
         {
-            assertEquals(ex.getMessage(),
-                         "Key for service contribution (to service 'Baz') was an instance of java.lang.String, but the expected key type was java.lang.Class.");
-        }
-
-        verify();
-
-        assertTrue(map.isEmpty());
-    }
-
-    @SuppressWarnings("unchecked")
-    @Test
-    public void wrong_value_type()
-    {
-        ContributionDef def = newContributionDef("contributionPlaceholder1");
-        Map<?, ContributionDef> keyToContribution = CollectionFactory.newMap();
-        ObjectLocator locator = mockObjectLocator();
-        Map<Class, Runnable> map = CollectionFactory.newMap();
-
-
-        replay();
-
-        MappedConfiguration wrapper = new ValidatingMappedConfigurationWrapper(Runnable.class, locator, map, null,
-                                                                               SERVICE_ID, def,
-                                                                               Class.class, keyToContribution);
-
-        try
-        {
-            wrapper.add(List.class, "do something");
-            unreachable();
-        }
-        catch (IllegalArgumentException ex)
-        {
-            assertEquals(ex.getMessage(),
-                         "Service contribution (to service 'Baz') was an instance of java.lang.String, which is not assignable to the configuration type java.lang.Runnable.");
+            assertEquals(
+                    ex.getMessage(),
+                    "Key for service contribution (to service 'Baz') was an instance of java.lang.String, but the expected key type was java.lang.Class.");
         }
 
         verify();
@@ -193,7 +195,7 @@ public class ValidatingMappedConfigurati
         replay();
 
         MappedConfiguration<Class, Runnable> wrapper = new ValidatingMappedConfigurationWrapper<Class, Runnable>(
-                Runnable.class, locator, map, null, SERVICE_ID, def, Class.class, keyToContribution);
+                Runnable.class, locator, null, map, null, SERVICE_ID, def, Class.class, keyToContribution);
 
         try
         {

Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/ValidatingOrderedConfigurationWrapperTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/ValidatingOrderedConfigurationWrapperTest.java?rev=1083568&r1=1083567&r2=1083568&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/ValidatingOrderedConfigurationWrapperTest.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/ValidatingOrderedConfigurationWrapperTest.java Sun Mar 20 21:00:58 2011
@@ -1,10 +1,10 @@
-// Copyright 2006, 2007, 2008, 2009 The Apache Software Foundation
+// Copyright 2006, 2007, 2008, 2009, 2011 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,
@@ -23,31 +23,36 @@ import org.testng.annotations.Test;
 import java.util.HashMap;
 import java.util.Map;
 
+@SuppressWarnings(
+{ "rawtypes", "unchecked" })
 public class ValidatingOrderedConfigurationWrapperTest extends IOCInternalTestCase
 {
     @Test
     public void valid_type_long_form()
     {
         Runnable contribution = mockRunnable();
+        Runnable coerced = mockRunnable();
         Runnable pre = mockRunnable();
         Runnable post = mockRunnable();
         Logger logger = mockLogger();
         Orderer<Runnable> orderer = new Orderer<Runnable>(logger);
+        TypeCoercerProxy tc = mockTypeCoercerProxy();
 
+        expect(tc.coerce(contribution, Runnable.class)).andReturn(coerced);
 
         orderer.add("pre", pre);
         orderer.add("post", post);
 
         replay();
 
-        OrderedConfiguration<Runnable> wrapper = new ValidatingOrderedConfigurationWrapper<Runnable>(
-                Runnable.class, null, orderer, null, null, "Service");
+        OrderedConfiguration<Runnable> wrapper = new ValidatingOrderedConfigurationWrapper<Runnable>(Runnable.class,
+                null, tc, orderer, null, null, "Service");
 
         wrapper.add("id", contribution, "after:pre", "before:post");
 
         verify();
 
-        assertListsEquals(orderer.getOrdered(), pre, contribution, post);
+        assertListsEquals(orderer.getOrdered(), pre, coerced, post);
     }
 
     @Test
@@ -59,16 +64,19 @@ public class ValidatingOrderedConfigurat
         Map post = new HashMap();
         HashMap contribution = new HashMap();
         ObjectLocator locator = mockObjectLocator();
+        TypeCoercerProxy tc = mockTypeCoercerProxy();
 
         train_autobuild(locator, HashMap.class, contribution);
 
+        expect(tc.coerce(contribution, Map.class)).andReturn(contribution);
+
         orderer.add("pre", pre);
         orderer.add("post", post);
 
         replay();
 
-        OrderedConfiguration<Map> wrapper = new ValidatingOrderedConfigurationWrapper<Map>(
-                Map.class, locator, orderer, null, null, "Service");
+        OrderedConfiguration<Map> wrapper = new ValidatingOrderedConfigurationWrapper<Map>(Map.class, locator, tc,
+                orderer, null, null, "Service");
 
         wrapper.addInstance("id", HashMap.class, "after:pre", "before:post");
 
@@ -85,8 +93,8 @@ public class ValidatingOrderedConfigurat
 
         replay();
 
-        OrderedConfiguration<Runnable> wrapper = new ValidatingOrderedConfigurationWrapper<Runnable>(
-                Runnable.class, null, orderer, null, null, "Service");
+        OrderedConfiguration<Runnable> wrapper = new ValidatingOrderedConfigurationWrapper<Runnable>(Runnable.class,
+                null, null, orderer, null, null, "Service");
 
         wrapper.add("id", null);
 
@@ -95,29 +103,4 @@ public class ValidatingOrderedConfigurat
         assertTrue(orderer.getOrdered().isEmpty());
     }
 
-    @SuppressWarnings("unchecked")
-    @Test
-    public void incorrect_contribution_type_is_passed_through_as_null()
-    {
-        Logger logger = mockLogger();
-        Orderer<Runnable> orderer = new Orderer<Runnable>(logger);
-
-        replay();
-
-        OrderedConfiguration wrapper = new ValidatingOrderedConfigurationWrapper(Runnable.class, null, orderer, null,
-                                                                                 null, "Service");
-
-        try
-        {
-            wrapper.add("id", "string");
-            unreachable();
-        }
-        catch (IllegalArgumentException ex)
-        {
-            assertEquals(ex.getMessage(),
-                         "Service contribution (to service 'Service') was an instance of java.lang.String, which is not assignable to the configuration type java.lang.Runnable.");
-        }
-
-        verify();
-    }
 }