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/03/01 21:28:49 UTC

svn commit: r917694 - in /tapestry/tapestry5/trunk/tapestry-ioc/src: main/java/org/apache/tapestry5/ioc/internal/services/ main/java/org/apache/tapestry5/ioc/internal/util/ main/resources/org/apache/tapestry5/ioc/internal/services/ test/java/org/apache...

Author: hlship
Date: Mon Mar  1 20:28:48 2010
New Revision: 917694

URL: http://svn.apache.org/viewvc?rev=917694&view=rev
Log:
TAP5-1035: Use UnknownValueException when no coercion can be found by TypeCoercer

Added:
    tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/util/PossibleValues.java   (with props)
    tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/util/UnknownValueException.java   (with props)
Modified:
    tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/TypeCoercerImpl.java
    tapestry/tapestry5/trunk/tapestry-ioc/src/main/resources/org/apache/tapestry5/ioc/internal/services/ServiceStrings.properties
    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=917694&r1=917693&r2=917694&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 Mon Mar  1 20:28:48 2010
@@ -14,18 +14,24 @@
 
 package org.apache.tapestry5.ioc.internal.services;
 
+import java.util.Collection;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.WeakHashMap;
+
 import org.apache.tapestry5.ioc.internal.util.CollectionFactory;
-import static org.apache.tapestry5.ioc.internal.util.CollectionFactory.newList;
 import org.apache.tapestry5.ioc.internal.util.Defense;
 import org.apache.tapestry5.ioc.internal.util.InheritanceSearch;
 import org.apache.tapestry5.ioc.internal.util.InternalUtils;
+import org.apache.tapestry5.ioc.internal.util.PossibleValues;
+import org.apache.tapestry5.ioc.internal.util.UnknownValueException;
 import org.apache.tapestry5.ioc.services.ClassFabUtils;
 import org.apache.tapestry5.ioc.services.Coercion;
 import org.apache.tapestry5.ioc.services.CoercionTuple;
 import org.apache.tapestry5.ioc.services.TypeCoercer;
 
-import java.util.*;
-
 public class TypeCoercerImpl implements TypeCoercer
 {
     // Constructed from the service's configuration.
@@ -182,22 +188,20 @@
      * coercions, that accomplish
      * the desired coercion.
      * <p/>
-     * There's <strong>TREMENDOUS</strong> room to improve this algorithm. For example, inheritance
-     * lists could be cached. Further, there's probably more ways to early prune the search.
-     * However, even with dozens or perhaps hundreds of tuples, I suspect the search will still
-     * grind to a conclusion quickly.
+     * There's <strong>TREMENDOUS</strong> room to improve this algorithm. For example, inheritance lists could be
+     * cached. Further, there's probably more ways to early prune the search. However, even with dozens or perhaps
+     * hundreds of tuples, I suspect the search will still grind to a conclusion quickly.
      * <p/>
-     * The order of operations should help ensure that the most efficient tuple chain is located. If
-     * you think about how tuples are added to the queue, there are two factors: size (the number of
-     * steps in the coercion) and "class distance" (that is, number of steps up the inheritance
-     * hiearchy). All the appropriate 1 step coercions will be considered first, in class distance
-     * order. Along the way, we'll queue up all the 2 step coercions, again in class distance order.
-     * By the time we reach some of those, we'll have begun queing up the 3 step coercions, and so
-     * forth, until we run out of input tuples we can use to fabricate multi-step compound
-     * coercions, or reach a final response.
+     * The order of operations should help ensure that the most efficient tuple chain is located. If you think about how
+     * tuples are added to the queue, there are two factors: size (the number of steps in the coercion) and
+     * "class distance" (that is, number of steps up the inheritance hiearchy). All the appropriate 1 step coercions
+     * will be considered first, in class distance order. Along the way, we'll queue up all the 2 step coercions, again
+     * in class distance order. By the time we reach some of those, we'll have begun queing up the 3 step coercions, and
+     * so forth, until we run out of input tuples we can use to fabricate multi-step compound coercions, or reach a
+     * final response.
      * <p/>
-     * This does create a good number of short lived temporary objects (the compound tuples), but
-     * that's what the GC is really good at.
+     * This does create a good number of short lived temporary objects (the compound tuples), but that's what the GC is
+     * really good at.
      * 
      * @param sourceType
      * @param targetType
@@ -246,8 +250,8 @@
         // Not found anywhere. Identify the source and target type and a (sorted) list of
         // all the known coercions.
 
-        throw new IllegalArgumentException(ServiceMessages.noCoercionFound(sourceType, targetType,
-                buildCoercionCatalog()));
+        throw new UnknownValueException(String.format("Could not find a coercion from type %s to type %s.", sourceType
+                .getName(), targetType.getName()), buildCoercionCatalog());
     }
 
     /**
@@ -287,24 +291,23 @@
      * Builds a string listing all the coercions configured for the type coercer, sorted
      * alphabetically.
      */
-    private String buildCoercionCatalog()
+    @SuppressWarnings("unchecked")
+    private PossibleValues buildCoercionCatalog()
     {
-        List<String> descriptions = newList();
+        List<CoercionTuple> masterList = CollectionFactory.newList();
 
         for (List<CoercionTuple> list : sourceTypeToTuple.values())
         {
-            for (CoercionTuple tuple : list)
-                descriptions.add(tuple.toString());
+            masterList.addAll(list);
         }
 
-        return InternalUtils.joinSorted(descriptions);
+        return new PossibleValues("coercions", masterList);
     }
 
     /**
      * Seeds the pool with the initial set of coercions for the given type.
      */
-    private void seedQueue(Class sourceType, Set<CoercionTuple> consideredTuples,
-            LinkedList<CoercionTuple> queue)
+    private void seedQueue(Class sourceType, Set<CoercionTuple> consideredTuples, LinkedList<CoercionTuple> queue)
     {
         // Work from the source type up looking for tuples
 
@@ -378,11 +381,9 @@
                 // from I1 (i.e., I2 is a superclass/superinterface of I1) and X is a new
                 // intermediate type, hopefully closer to our eventual target type.
 
-                Coercion compoundCoercer = new CompoundCoercion(intermediateTuple.getCoercion(),
-                        tuple.getCoercion());
+                Coercion compoundCoercer = new CompoundCoercion(intermediateTuple.getCoercion(), tuple.getCoercion());
 
-                CoercionTuple compoundTuple = new CoercionTuple(sourceType, newIntermediateType,
-                        compoundCoercer, false);
+                CoercionTuple compoundTuple = new CoercionTuple(sourceType, newIntermediateType, compoundCoercer, false);
 
                 // So, every tuple that is added to the queue can take as input the sourceType.
                 // The target type may be another intermdiate type, or may be something

Added: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/util/PossibleValues.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/util/PossibleValues.java?rev=917694&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/util/PossibleValues.java (added)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/util/PossibleValues.java Mon Mar  1 20:28:48 2010
@@ -0,0 +1,82 @@
+// Copyright 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
+//
+// 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.util;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Used (as part of a {@link UnknownValueException} to identify what available values
+ * are present.
+ * 
+ * @since 5.2.0
+ */
+public class PossibleValues
+{
+    private final String valueType;
+
+    private final List<String> values;
+
+    /**
+     * @param valueType
+     *            a word or phrase that describes what the values are such as "component types" or "service ids"
+     *@param values
+     *            a set of objects defining the values; the values will be converted to strings and sorted into
+     *            ascending order
+     */
+    public PossibleValues(String valueType, Collection<?> values)
+    {
+        this.valueType = valueType;
+        this.values = sortValues(values);
+    }
+
+    public PossibleValues(String valueType, Map<?, ?> map)
+    {
+        this(valueType, map.keySet());
+    }
+
+    private static List<String> sortValues(Collection<?> values)
+    {
+        List<String> result = CollectionFactory.newList();
+
+        for (Object v : values)
+        {
+            result.add(String.valueOf(v));
+        }
+
+        return Collections.unmodifiableList(result);
+    }
+
+    /** The type of value, i.e., "component types" or "service ids". */
+    public String getValueType()
+    {
+        return valueType;
+    }
+
+    /** The values, as strings, in sorted order. */
+    public List<String> getValues()
+    {
+        return values;
+    }
+
+    @Override
+    public String toString()
+    {
+        return String.format("PossibleValues[%s: %s]", valueType, InternalUtils.join(values));
+    }
+
+}

Propchange: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/util/PossibleValues.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/util/UnknownValueException.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/util/UnknownValueException.java?rev=917694&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/util/UnknownValueException.java (added)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/util/UnknownValueException.java Mon Mar  1 20:28:48 2010
@@ -0,0 +1,47 @@
+// Copyright 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
+//
+// 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.util;
+
+/**
+ * Special exception used when a value (typically from a map) is referenced that does not exist. Uses a
+ * {@link PossibleValues} object
+ * to track what the known values are.
+ * 
+ * @since 5.2.0
+ */
+public class UnknownValueException extends TapestryException
+{
+    private static final long serialVersionUID = -8131503136299055706L;
+
+    private final PossibleValues possibleValues;
+
+    public UnknownValueException(String message, PossibleValues values)
+    {
+        this(message, null, null, values);
+    }
+
+    public UnknownValueException(String message, Object location, Throwable cause, PossibleValues values)
+    {
+        super(message, location, cause);
+
+        this.possibleValues = values;
+    }
+
+    public PossibleValues getPossibleValues()
+    {
+        return possibleValues;
+    }
+
+}

Propchange: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/util/UnknownValueException.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/main/resources/org/apache/tapestry5/ioc/internal/services/ServiceStrings.properties
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/resources/org/apache/tapestry5/ioc/internal/services/ServiceStrings.properties?rev=917694&r1=917693&r2=917694&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/main/resources/org/apache/tapestry5/ioc/internal/services/ServiceStrings.properties (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/resources/org/apache/tapestry5/ioc/internal/services/ServiceStrings.properties Mon Mar  1 20:28:48 2010
@@ -31,7 +31,6 @@
 unmatched-service-method=Method %s has no match in filter interface %s.
 unknown-object-proxyProvider=Object proxyProvider '%s' does not exist (in object reference '%s').
 shutdown-listener-error=Error notifying %s of registry shutdown: %s
-no-coercion-found=Could not find a coercion from type %s to type %s.  Available coercions: %s.
 recursive-symbol=Symbol '%s' is defined in terms of itself (%s).
 symbol-undefined=Symbol '%s' is not defined.
 symbol-undefined-in-path=Symbol '%s' is not defined (in %s). 

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=917694&r1=917693&r2=917694&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 Mon Mar  1 20:28:48 2010
@@ -113,7 +113,7 @@
             coercer.coerce("", Map.class);
             unreachable();
         }
-        catch (IllegalArgumentException ex)
+        catch (RuntimeException ex)
         {
             assertTrue(ex.getMessage().contains(
                     "Could not find a coercion from type java.lang.String to type java.util.Map"));
@@ -279,14 +279,12 @@
     {
         return new Object[][]
         {
-                { StringBuffer.class, Integer.class,
-                        "Object --> String, String --> Long, Long --> Integer" },
-                { void.class, Map.class, "null --> null" },
-                { void.class, Boolean.class, "null --> Boolean" },
-                { String[].class, List.class, "Object[] --> java.util.List" },
-                { Float.class, Double.class, "Float --> Double" },
-                { Double.class, BigDecimal.class,
-                        "Object --> String, String --> java.math.BigDecimal" }, };
+        { StringBuffer.class, Integer.class, "Object --> String, String --> Long, Long --> Integer" },
+        { void.class, Map.class, "null --> null" },
+        { void.class, Boolean.class, "null --> Boolean" },
+        { String[].class, List.class, "Object[] --> java.util.List" },
+        { Float.class, Double.class, "Float --> Double" },
+        { Double.class, BigDecimal.class, "Object --> String, String --> java.math.BigDecimal" }, };
     }
 
     @Test