[jboss-cvs] JBossAS SVN: r63807 - projects/aop/trunk/aop/src/main/org/jboss/aop/advice/annotation.

jboss-cvs-commits at lists.jboss.org jboss-cvs-commits at lists.jboss.org
Tue Jul 3 20:21:41 EDT 2007


Author: flavia.rainone at jboss.com
Date: 2007-07-03 20:21:41 -0400 (Tue, 03 Jul 2007)
New Revision: 63807

Added:
   projects/aop/trunk/aop/src/main/org/jboss/aop/advice/annotation/ArgumentContextualizer.java
   projects/aop/trunk/aop/src/main/org/jboss/aop/advice/annotation/ParamTypeAssignabilityAlgorithm.java
Removed:
   projects/aop/trunk/aop/src/main/org/jboss/aop/advice/annotation/ContextualizedArguments.java
Modified:
   projects/aop/trunk/aop/src/main/org/jboss/aop/advice/annotation/Algorithm.java
   projects/aop/trunk/aop/src/main/org/jboss/aop/advice/annotation/VariableNode.java
Log:
[JBAOP-420] New version of algorithm

Modified: projects/aop/trunk/aop/src/main/org/jboss/aop/advice/annotation/Algorithm.java
===================================================================
--- projects/aop/trunk/aop/src/main/org/jboss/aop/advice/annotation/Algorithm.java	2007-07-03 23:53:31 UTC (rev 63806)
+++ projects/aop/trunk/aop/src/main/org/jboss/aop/advice/annotation/Algorithm.java	2007-07-04 00:21:41 UTC (rev 63807)
@@ -61,13 +61,13 @@
       if (type instanceof TypeVariable)
       {
          VariableNode node = null;
-         TypeVariable fromVariable = (TypeVariable) type;
-         if (variableHierarchy.containsKey(fromVariable.getName()))
+         TypeVariable variable = (TypeVariable) type;
+         if (variableHierarchy.containsKey(variable.getName()))
          {
-            node = variableHierarchy.get(fromVariable.getName());
+            node = variableHierarchy.get(variable.getName());
          } else
          {
-            node = new VariableNode(fromVariable, variableHierarchy);
+            node = new VariableNode(variable, variableHierarchy);
          }
          return node.addLowerBound(fromType);
       }
@@ -165,7 +165,8 @@
          }
          return false;
       }
-      return ContextualizedArguments.isAssignable(CHECKER, paramType, fromType, variableHierarchy);
+      return ParamTypeAssignabilityAlgorithm.isAssignable(
+            paramType, fromType, CHECKER, variableHierarchy);
    }
 
    private boolean isAssignable(GenericArrayType arrayType, Type fromType,
@@ -190,75 +191,77 @@
       return false;
    }
 
-   // ////////////////////////////////////////////////////////
-   private static final ContextualizedArguments.EqualityChecker<Map<String, VariableNode>> CHECKER
-      = new ContextualizedArguments.EqualityChecker<Map<String,VariableNode>>()
+   //////////////////////////////////////////////////////////
+   private static final ParamTypeAssignabilityAlgorithm.EqualityChecker<Map<String, VariableNode>> CHECKER
+      = new ParamTypeAssignabilityAlgorithm.EqualityChecker<Map<String,VariableNode>>()
+   {
+      public boolean isSame(Type type, Type fromType, Map<String, VariableNode> variableHierarchy)
       {
-
-         public boolean isSame(Type type2, Type type1, Map<String, VariableNode> variableHierarchy)
+         if (type instanceof TypeVariable)
          {
-            if (type2 instanceof TypeVariable)
+            TypeVariable variable = (TypeVariable) type;
+            VariableNode node = variableHierarchy.containsKey(variable.getName())?
+                  variableHierarchy.get(variable.getName()):
+                     new VariableNode(variable, variableHierarchy);
+                  return node.assignValue(fromType);
+         }
+         if (type instanceof Class)
+         {
+            return type.equals(fromType);
+         }
+         if (type instanceof ParameterizedType)
+         {
+            if (!(fromType instanceof ParameterizedType))
             {
-               TypeVariable variable2 = (TypeVariable) type2;
-               VariableNode node = variableHierarchy.containsKey(variable2.getName())?
-                  variableHierarchy.get(variable2.getName()):
-                  new VariableNode(variable2, variableHierarchy);
-               return node.assignValue(type1);
+               return false;
             }
-            if (type2 instanceof Class)
+            ParameterizedType fromParamType = (ParameterizedType) fromType;
+            ParameterizedType paramType = (ParameterizedType) type;
+            if (!isSame(paramType.getRawType(), fromParamType.getRawType(),
+                  variableHierarchy))
             {
-               return type1.equals(type2);
+               return false;
             }
-            if (type2 instanceof ParameterizedType)
+            return isSame(paramType.getActualTypeArguments(),
+                  fromParamType.getActualTypeArguments(), variableHierarchy);
+         }
+         if (type instanceof WildcardType)
+         {
+            Type[] upperBounds = ((WildcardType) type).getUpperBounds();
+            Algorithm algorithm = Algorithm.getInstance();
+            if (fromType instanceof WildcardType)
             {
-               if (!(type1 instanceof ParameterizedType))
+               Type[] fromUpperBounds = ((WildcardType) fromType).getUpperBounds();
+               outer: for (int i = 0; i < upperBounds.length; i++)
                {
+                  for (int j = 0; j < fromUpperBounds.length; j++)
+                  {
+                     if (algorithm.isAssignable(upperBounds[i],
+                           fromUpperBounds[i], variableHierarchy))
+                     {
+                        continue outer;
+                     }
+                  }
                   return false;
                }
-               ParameterizedType paramType1 = (ParameterizedType) type1;
-               ParameterizedType paramType2 = (ParameterizedType) type2;
-               if (!isSame(paramType2.getRawType(), paramType1.getRawType(), variableHierarchy))
-               {
-                  return false;
-               }
-               return isSame(paramType2.getActualTypeArguments(), paramType1.getActualTypeArguments(), variableHierarchy);
+               // TODO lower bounds: inverted algorithm
+               return true;
             }
-            if (type2 instanceof WildcardType)
+            else
             {
-               Type[] upperBounds2 = ((WildcardType) type2).getUpperBounds();
-               Algorithm algorithm = Algorithm.getInstance();
-               if (type1 instanceof WildcardType)
+               for (int i = 0; i < upperBounds.length; i++)
                {
-                  Type[] upperBounds1 = ((WildcardType) type1).getUpperBounds();
-                  outer: for (int i = 0; i < upperBounds2.length; i++)
+                  if (!algorithm.isAssignable(upperBounds[i], fromType,
+                        variableHierarchy))
                   {
-                     for (int j = 0; j < upperBounds1.length; j++)
-                     {
-                        if (algorithm.isAssignable(upperBounds2[i], upperBounds1[i], variableHierarchy))
-                        {
-                           continue outer;
-                        }
-                     }
                      return false;
                   }
-                  // TODO lower bounds: inverted algorithm
-                  return true;
                }
-               else
-               {
-                  for (int i = 0; i < upperBounds2.length; i++)
-                  {
-                     if (!algorithm.isAssignable(upperBounds2[i], type1, variableHierarchy))
-                     {
-                           return false;
-                     }
-                  }
-                  // TODO lower bounds: inverted algorithm
-                  return true;
-               }
+               // TODO lower bounds: inverted algorithm
+               return true;
             }
-            return true;
          }
-      };
-   
+         return true;
+      }
+   };
 }
\ No newline at end of file

Added: projects/aop/trunk/aop/src/main/org/jboss/aop/advice/annotation/ArgumentContextualizer.java
===================================================================
--- projects/aop/trunk/aop/src/main/org/jboss/aop/advice/annotation/ArgumentContextualizer.java	                        (rev 0)
+++ projects/aop/trunk/aop/src/main/org/jboss/aop/advice/annotation/ArgumentContextualizer.java	2007-07-04 00:21:41 UTC (rev 63807)
@@ -0,0 +1,490 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.aop.advice.annotation;
+
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.lang.reflect.TypeVariable;
+import java.util.LinkedList;
+import java.util.ListIterator;
+
+/**
+ * Argument contextualizer. Performs contextualization of arguments through hierarchy
+ * 
+ * 
+ * @author  <a href="flavia.rainone at jboss.com">Flavia Rainone</a>
+ */
+class ArgumentContextualizer
+{
+   public static final Type[] getContextualizedArguments(ParameterizedType paramType,
+         Class rawType, Class desiredType)
+   {
+      ArgumentContextualizer contextualizedArguments = getContextualizedArgumentsInternal(
+            desiredType, rawType);
+      if (contextualizedArguments == null)
+      {
+         return null;
+      }
+      if (paramType != null)
+      {
+         contextualizedArguments.contextualizeVariables(null, paramType);
+      }
+      return contextualizedArguments.getArguments();
+   }
+
+   
+   private static final ArgumentContextualizer getContextualizedArgumentsInternal(
+         Class<?> desiredType, Class<?> classType)
+   {
+      Type superType = null;
+      if (desiredType.isInterface())
+      {
+         for (Type superInterface : classType.getGenericInterfaces())
+         {
+            if ((superInterface instanceof Class && desiredType
+                  .isAssignableFrom((Class<?>) superInterface))
+                  || (superInterface instanceof ParameterizedType &&
+                        desiredType.isAssignableFrom((Class<?>)
+                              ((ParameterizedType) superInterface).getRawType())))
+            {
+               superType = superInterface;
+               break;
+            }
+         }
+      }
+      if (superType == null)
+      {
+         superType = classType.getGenericSuperclass();
+      }
+      ArgumentContextualizer result = null;
+      if (superType instanceof Class)
+      {
+         if (superType == desiredType)
+         {
+            return null;
+         }
+         result = getContextualizedArgumentsInternal(desiredType,
+               (Class<?>) superType);
+      }
+      else
+      {
+         ParameterizedType superParamType = (ParameterizedType) superType;
+         Class<?> superClassType = (Class<?>) superParamType.getRawType();
+         if (superClassType == desiredType)
+         {
+            return new ArgumentContextualizer(superParamType
+                  .getActualTypeArguments(), classType);
+         }
+         else
+         {
+            result = getContextualizedArgumentsInternal(desiredType,
+                  superClassType);
+         }
+      }
+      if (result == null
+            || !result.contextualizeVariables(classType, superType))
+      {
+         return null;
+      }
+      return result;
+   }
+   
+   
+   private Type[] arguments;
+   private LinkedList<VariableReplacer> variableReplacements;
+
+   // declaring class extends queried class (DeclaringClass<A, B, C> extends Queried<X, Y, Z, ..., W>,
+   // where X, Y, Z...W, are a list of types for which we need to map (contextualize)
+   // variables
+   // A, B, C... D are variables of DeclaringClass, that may be used in the contextualization proccess
+   /**
+    * Constructor.
+    * 
+    * @param arguments      the set of arguments in their original context (the
+    *                       extends or implements declaration)
+    * @param declaringClass the class that declared those arguments. This class
+    *                       must be the same class that extends/implements a
+    *                       queried parameterized type.
+    */
+   private ArgumentContextualizer(Type[] arguments, Class<?> declaringClass)
+   {
+      this.arguments = arguments;
+      for (int i = 0; i < arguments.length; i++)
+      {
+         Type newArgument = processArgument(arguments, i, declaringClass,
+               replacementCreator, this);
+         if (newArgument != null)
+         {
+            this.arguments[i] = newArgument;
+         }
+      }
+   }
+
+   // newDeclaringClass extends/implements oldDeclaringType
+   // returns false = warning (work with raw type hence)
+   /**
+    * Performs a contextualization step.
+    * 
+    * @param subClass  a class that declares to extend/implement <code>superType
+    *                  </code> 
+    * @param superType the super type of <code>subClass</code>
+    * 
+    * @return <code>true</code> if the contextualization process was successfully
+    *         performed; </code>false</code> otherwise.
+    */
+   private boolean contextualizeVariables(Class subClass, Type superType)
+   {
+      if (!initialized || variableReplacements.isEmpty())
+      {
+         initialized = false;
+         return true;
+      }
+      if (superType instanceof Class)
+      {
+         return false; // warning: variables lost in hierarchy
+      }
+      ParameterizedType superParamType = (ParameterizedType) superType;
+      for (iterator = variableReplacements.listIterator(); iterator.hasNext(); )
+      {
+         if(iterator.next().replace(superParamType, subClass))
+         {
+            iterator.remove();
+         }
+      }
+      iterator = null;
+      return true; 
+   }
+   
+   /**
+    * Process an argument, definining whether it needs to be replaced during
+    * contextualization process or not.
+    * 
+    * @param <O>
+    * 
+    * @param argumentContainer the array that contains the argument to be
+    *                          processed 
+    * @param argumentIndex     the index of the argument in <code>
+    *                          argumentContainer</code>
+    * @param declaringClass    the class that declares the argument
+    * @param recorder          object responsible for recording future
+    *                          replacements to be performed during
+    *                          contextualization
+    * @param outer             
+    * @return the argument processed. This return value may be null if no
+    *         processement of <code>argumentContainer[argumentIndex]</code> is
+    *         rerquired, or an equivalent type otherwise.
+    */
+   private static <O> Type processArgument(Type[] argumentContainer,
+         int argumentIndex, Class<?> declaringClass,
+         ReplacementScheduler<O> recorder, O outer)
+   {
+      Type argument = argumentContainer[argumentIndex];
+      if (argument instanceof Class)
+      {
+         return null;
+      }
+      if (argument instanceof ParameterizedType)
+      {
+         ParameterizedType paramType = (ParameterizedType) argument;
+         ParameterizedType_ newParamType = null;
+         Type[] arguments = paramType.getActualTypeArguments();
+         for (int i = 0; i < arguments.length; i++)
+         {
+            Type newType = processArgument(arguments, i, declaringClass, recorder,
+                  outer);
+            if (newType != null)
+            {
+               if (newParamType == null)
+               {
+                  newParamType = new ParameterizedType_(paramType);
+               }
+               newParamType.getActualTypeArguments()[i] = newType;
+            }
+         }
+         return newParamType;
+      }
+      //else if (bounds[i] instanceof TypeVariable)
+      if (declaringClass == null)
+      {
+         return null;
+      }
+      String paramName = ((TypeVariable) argument).getName();
+      int index = 0;
+      TypeVariable[] typeVariables = declaringClass.getTypeParameters();
+      for (index = 0; index < typeVariables.length; index ++)
+      {
+         if (typeVariables[index].getName().equals(paramName)){
+            break;
+         }
+      }
+      recorder.scheduleReplacement(argumentContainer, argumentIndex, index, outer);
+      return argument; 
+   }
+
+   boolean initialized = false;
+
+   private void initialize()
+   {
+      if (!initialized)
+      {
+         Type[] oldResult = this.arguments;
+         this.arguments = new Type[oldResult.length];
+         System.arraycopy(oldResult, 0, this.arguments, 0, this.arguments.length);
+         this.variableReplacements = new LinkedList<VariableReplacer>();
+         initialized = true;
+      }
+   }
+   private ListIterator<VariableReplacer> iterator;
+
+   /**
+    * Returns contextualized arguments.
+    * 
+    * @return contextualized arguments
+    */
+   public Type[] getArguments()
+   {
+      return this.arguments;
+   }
+
+   /**
+    * Creates a variable replacement. This replacement should take place during the
+    * contextualization steps, where the variable will be replaced by its value.
+    * Notice this value may or may not be another variable.
+
+    * @param argumentContainer array on which the replacement will be executed 
+    * @param argumentIndex     the index that indicates a position of the variable
+    *                          to be replaced in <code>argumentContainer</code>
+    *                          array
+    * @param variableIndex     index of the variable value in the next argument
+    *                          context array. This index shall be used on the
+    *                          replacement, during contextualization process.
+    */
+   private void createVariableReplacement(Type[] argumentContainer, int argumentIndex,
+         int variableIndex)
+   {
+      if (iterator != null)
+      {
+         iterator.add(new VariableReplacer(argumentContainer, argumentIndex,
+               variableIndex));
+      }
+      else
+      {
+         this.variableReplacements.add(new VariableReplacer(
+               argumentContainer, argumentIndex, variableIndex));
+      }
+   }
+   
+   /**
+    * Replaces a variable by another type according to an argument context.
+    *  
+    * @author  <a href="flavia.rainone at jboss.com">Flavia Rainone</a>
+    */
+   class VariableReplacer
+   {
+      private Type[] arguments;
+      private int argumentIndex;
+      private int valueIndex;
+      private boolean pendingExecution;
+
+      /**
+       * Constructor.
+       * 
+       * @param arguments     array on which the replacement will be executed 
+       * @param argumentIndex the index that indicates a position of the variable
+       *                      to be replaced in <code>argumentContainer</code> array
+       * @param valueIndex    index of the variable value in the next argument
+       *                      context array. This index shall be used on the
+       *                      replacement, during contextualization process.
+       */
+      public VariableReplacer(Type[] arguments, int argumentIndex, int valueIndex)
+      {
+         this.valueIndex = valueIndex;
+         this.arguments = arguments;
+         this.argumentIndex = argumentIndex;
+         this.pendingExecution = true;
+      }
+
+      // return true if replacement has been done for good
+      /**
+       * Performs replacemen of a variable by a new type.
+       * 
+       * @param paramType      parameterized type that contains the context to be
+       *                       used during replacement proccess.
+       * @param declaringClass the class that declares the the variables used in the
+       *                       arguments of <code>paramType</code>. This class must
+       *                       extend/implement the generic type
+       *                       <code>paramType</code>.
+       */
+      public boolean replace(ParameterizedType paramType, Class<?> declaringClass)
+      {
+         arguments[argumentIndex] = paramType.getActualTypeArguments()[valueIndex];
+         this.pendingExecution = false;
+         Type newType = ArgumentContextualizer.processArgument(arguments, argumentIndex,
+               declaringClass, updater, this);
+         if (newType != null)
+         {
+            arguments[argumentIndex] = newType;
+            return false;
+         }
+         return true;
+      }
+
+      /**
+       * Returns the contextualizer that scheduled this replacement.
+       * 
+       * @return the contextualizer.
+       */
+      ArgumentContextualizer getContextualizer()
+      {
+         return ArgumentContextualizer.this;
+      }
+   }
+
+   /**
+    * Parameterized type implementation. Allows replacement of arguments without
+    * affecting reflection information.
+    * 
+    * @author  <a href="flavia.rainone at jboss.com">Flavia Rainone</a>
+    */
+   private static final class ParameterizedType_ implements ParameterizedType
+   {
+      private Type[] arguments;
+      private Type ownerType;
+      private Type rawType;
+
+      ParameterizedType_(ParameterizedType type)
+      {
+         Type[] actualArguments = type.getActualTypeArguments();
+         this.arguments = new Type[actualArguments.length];
+         System.arraycopy(actualArguments, 0, arguments, 0, actualArguments.length);
+         this.ownerType = type.getOwnerType();
+         this.rawType = type.getRawType();
+      }
+
+
+      public Type[] getActualTypeArguments()
+      {
+         return this.arguments;
+      }
+
+      public Type getOwnerType()
+      {
+         return this.ownerType;
+      }
+
+      public Type getRawType()
+      {
+         return this.rawType;
+      }
+
+      public boolean equals(Object obj)
+      {
+         if (!(obj instanceof ParameterizedType))
+         {
+            return false;
+         }
+         ParameterizedType other = (ParameterizedType) obj;
+         if (!this.ownerType.equals(other.getOwnerType()) ||
+               !this.rawType.equals(other.getRawType()))
+         {
+            return false;
+         }
+         Type[] otherArguments = other.getActualTypeArguments();
+         for (int i = 0; i < arguments.length; i++)
+         {
+            if (!arguments[i].equals(otherArguments[i]))
+            {
+               return false;
+            }
+         }
+         return true;
+      }
+   }
+
+   /**
+    * Schedules replacements to be performed during contextualization.
+    * 
+    * @author  <a href="flavia.rainone at jboss.com">Flavia Rainone</a>
+    *
+    * @param <C> the scheduler client 
+    */
+   interface ReplacementScheduler<C>
+   {
+      /**
+       * Schedules a variable replacement to be performed on next contextualization
+       * step.
+       * 
+       * @param argumentContainer array on which the replacement will be executed 
+       * @param argumentIndex     the index that indicates a position of the variable
+       *                          to be replaced in <code>argumentContainer</code>
+       *                          array
+       * @param variableIndex     index of the variable value in the next argument
+       *                          context array. This index shall be used on the
+       *                          replacement, during contextualization process.
+       * @param client            the client of recorder
+       */
+      public void scheduleReplacement(Type[] argumentContainer, int argumentIndex,
+            int variableIndex, C client);
+   }
+   
+   /**
+    * Schedules variable replacement when required by contextualizer.
+    * The effect of this scheduling process is the creation of variable replacement.
+    */
+   private static ReplacementScheduler<ArgumentContextualizer> replacementCreator =
+      new ReplacementScheduler<ArgumentContextualizer>()
+   {
+      public void scheduleReplacement(Type[] replacementTarget, int targetIndex,
+            int variableIndex, ArgumentContextualizer outer)
+      {
+         outer.initialize();
+         outer.createVariableReplacement(outer.arguments, targetIndex, variableIndex);
+      }
+   };
+   
+   /**
+    * Schedules variable replacement when required by a <code>VariableReplacement
+    * </code> object.
+    * Generally, the effect of this schedule process will be an update in
+    * the client object, unless this one already has a pending replacement scheduled.
+    */
+   private static ReplacementScheduler<VariableReplacer> updater =
+      new ReplacementScheduler<VariableReplacer>()
+   {
+      public void scheduleReplacement(Type[] replacementTarget, int targetIndex,
+            int variableIndex, VariableReplacer replacer)
+      {
+         if (replacer.pendingExecution) // replacer is already busy
+         {
+            replacer.getContextualizer().createVariableReplacement(replacementTarget,
+                  targetIndex, variableIndex);
+         }
+         else
+         {
+            replacer.valueIndex = variableIndex;
+            replacer.arguments = replacementTarget;
+            replacer.argumentIndex = targetIndex;
+            replacer.pendingExecution = true;
+         }
+      }
+   };
+}
\ No newline at end of file

Deleted: projects/aop/trunk/aop/src/main/org/jboss/aop/advice/annotation/ContextualizedArguments.java
===================================================================
--- projects/aop/trunk/aop/src/main/org/jboss/aop/advice/annotation/ContextualizedArguments.java	2007-07-03 23:53:31 UTC (rev 63806)
+++ projects/aop/trunk/aop/src/main/org/jboss/aop/advice/annotation/ContextualizedArguments.java	2007-07-04 00:21:41 UTC (rev 63807)
@@ -1,444 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- * Copyright 2005, JBoss Inc., and individual contributors as indicated
- * by the @authors tag. See the copyright.txt in the distribution for a
- * full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.aop.advice.annotation;
-
-import java.lang.reflect.ParameterizedType;
-import java.lang.reflect.Type;
-import java.lang.reflect.TypeVariable;
-import java.util.LinkedList;
-import java.util.ListIterator;
-
-/**
- * @author  <a href="flavia.rainone at jboss.com">Flavia Rainone</a>
- *
- */
-class ContextualizedArguments
-{
-   static abstract class EqualityChecker<T>
-   {
-      protected boolean isSame(Type[] arguments, Type[] assignableArguments, T token)
-      {
-         for (int i = 0; i < arguments.length; i++)
-         {
-            if (!isSame(arguments[i], assignableArguments[i], token))
-            {
-               return false;
-            }
-         }
-         return true;
-      }
-      
-      abstract boolean isSame(Type argument, Type assignableArgument, T token);
-   }
-   
-   
-   public static<T> boolean isAssignable(EqualityChecker<T> action, ParameterizedType paramType, Type assignable, T token)
-   {
-      Class<?> typeRaw = null;
-      ParameterizedType assignableParamType = null;
-      Class<?> desiredType = (Class<?>) paramType.getRawType();
-      if (assignable instanceof Class)
-      {
-         typeRaw = (Class<?>) assignable;
-         if (!desiredType.isAssignableFrom(typeRaw))
-         {
-            return false;
-         }
-         if (typeRaw.getTypeParameters().length > 0)
-         {
-            // notice that, if typeClass equals the fromParamType, we also have
-            // the
-            // result true with a warning (i.e., this if is not only for
-            // typeClass
-            // subclass of fromParamType, but also for typeCass same as
-            // fromParamType raw
-            return true;// TODO With warning
-         }
-      }
-      else if (assignable instanceof ParameterizedType)
-      {
-         assignableParamType = (ParameterizedType) assignable;
-         typeRaw = (Class<?>) assignableParamType.getRawType();
-         if (typeRaw == desiredType)
-         {
-            // compare arguments with arguments
-            return action.isSame(paramType.getActualTypeArguments(),
-                  assignableParamType.getActualTypeArguments(), token);
-         }
-         else if (!desiredType.isAssignableFrom(typeRaw))
-         {
-            return false;
-         }
-      }
-      else
-      {
-         return false;
-      }
-      // try to get, if null, warning, parameters lost in hierarchy
-      Type[] arguments = getContextualizedArguments(assignableParamType, typeRaw, desiredType);
-      if (arguments == null)
-      {
-         return true; // TODO with Warning
-      }
-      return action.isSame(paramType.getActualTypeArguments(), arguments, token);
-   }
-   
-   
-   
-   
-   public static final Type[] getContextualizedArguments(ParameterizedType paramType,
-         Class rawType, Class desiredType)
-   {
-      ContextualizedArguments contextualizedArguments = getContextualizedArgumentsInternal(
-            desiredType, rawType);
-      if (contextualizedArguments == null)
-      {
-         return null;
-      }
-      if (paramType != null)
-      {
-         contextualizedArguments.contextualizeVariables(null, paramType);
-      }
-      return contextualizedArguments.getArguments();
-   }
-
-   private static final ContextualizedArguments getContextualizedArgumentsInternal(
-         Class<?> desiredType, Class<?> classType)
-   {
-      Type superType = null;
-      if (desiredType.isInterface())
-      {
-         for (Type superInterface : classType.getGenericInterfaces())
-         {
-            if ((superInterface instanceof Class && desiredType
-                  .isAssignableFrom((Class<?>) superInterface))
-                  || (superInterface instanceof ParameterizedType &&
-                     desiredType.isAssignableFrom((Class<?>)
-                           ((ParameterizedType) superInterface).getRawType())))
-            {
-               superType = superInterface;
-               break;
-            }
-         }
-      }
-      else
-      {
-         superType = classType.getGenericSuperclass();
-      }
-      ContextualizedArguments result = null;
-      if (superType instanceof Class)
-      {
-         if (superType == desiredType)
-         {
-            return null;
-         }
-         result = getContextualizedArgumentsInternal(desiredType,
-               (Class<?>) superType);
-      }
-      else
-      {
-         ParameterizedType superParamType = (ParameterizedType) superType;
-         Class<?> superClassType = (Class<?>) superParamType.getRawType();
-         if (superClassType == desiredType)
-         {
-            return new ContextualizedArguments(superParamType
-                  .getActualTypeArguments(), classType);
-         }
-         else
-         {
-            result = getContextualizedArgumentsInternal(desiredType,
-                  superClassType);
-         }
-      }
-      if (result == null
-            || !result.contextualizeVariables(classType, superType))
-      {
-         return null;
-      }
-      return result;
-   }
-   
-   
-   
-   
-   
-   
-   
-   
-   
-   
-   
-   
-   
-   
-   
-   private static ReplacementRecorder<ContextualizedArguments> replacementCreator = new ReplacementRecorder<ContextualizedArguments>()
-   {
-      public void recordReplacement(ContextualizedArguments outer, int variableIndex, Type[] replacementTarget, int targetIndex)
-      {
-         outer.initialize();
-         outer.createVariableReplacement(variableIndex, outer.arguments, targetIndex);
-      }
-   };
-   
-   private Type[] arguments;
-   //private Collection<VariableReplacement> variableReplacements;
-   private LinkedList<VariableReplacement> variableReplacements;
-   
-   // declaring class extends queried class (DeclaringClass<A, B, C> extends Queried<X, Y, Z, ..., W>,
-   // where X, Y, Z...W, are a list of types for which we need to map (contextualize)
-   // variables
-   // A, B, C... D are variables of DeclaringClass, that may be used in the contextualization proccess
-   public ContextualizedArguments(Type[] result, Class<?> declaringClass)
-   {
-      this.arguments = result;
-      for (int i = 0; i < result.length; i++)
-      {
-         Type newArgument = processArgument(result, i, declaringClass,
-               replacementCreator, this);
-         if (newArgument != null)
-         {
-            this.arguments[i] = newArgument;
-         }
-      }
-   }
-
-   private static <O> Type processArgument(Type[] argumentContainer, int argumentIndex,
-         Class<?> declaringClass, ReplacementRecorder<O> recorder, O outer)
-   {
-      Type argument = argumentContainer[argumentIndex];
-      if (argument instanceof Class)
-      {
-         return null;
-      }
-      if (argument instanceof ParameterizedType)
-      {
-         ParameterizedType paramType = (ParameterizedType) argument;
-         ParameterizedType_ newParamType = null;
-         Type[] arguments = paramType.getActualTypeArguments();
-         for (int i = 0; i < arguments.length; i++)
-         {
-            Type newType = processArgument(arguments, i, declaringClass, recorder,
-                  outer);
-            if (newType != null)
-            {
-               if (newParamType == null)
-               {
-                  newParamType = new ParameterizedType_(paramType);
-               }
-               newParamType.getActualTypeArguments()[i] = newType;
-            }
-         }
-         return newParamType;
-      }
-      //else if (bounds[i] instanceof TypeVariable)
-      if (declaringClass == null)
-      {
-         return null;
-      }
-      String paramName = ((TypeVariable) argument).getName();
-      int index = 0;
-      TypeVariable[] typeVariables = declaringClass.getTypeParameters();
-      for (index = 0; index < typeVariables.length; index ++)
-      {
-         if (typeVariables[index].getName().equals(paramName)){
-            break;
-         }
-      }
-      recorder.recordReplacement(outer, index, argumentContainer, argumentIndex);
-      return argument; 
-   }
-
-   boolean initialized = false;
-   
-   private void initialize()
-   {
-      if (!initialized)
-      {
-         Type[] oldResult = this.arguments;
-         this.arguments = new Type[oldResult.length];
-         System.arraycopy(oldResult, 0, this.arguments, 0, this.arguments.length);
-         this.variableReplacements = new LinkedList<VariableReplacement>();
-         initialized = true;
-      }
-   }
-   private ListIterator<VariableReplacement> iterator;
-   // newDeclaringClass extends/implements oldDeclaringType
-   // returns false = warning (work with raw type hence)
-   public boolean contextualizeVariables(Class newDeclaringClass, Type oldDeclaringType)
-   {
-      if (!initialized || variableReplacements.isEmpty())
-      {
-         initialized = false;
-         return true;
-      }
-      if (oldDeclaringType instanceof Class)
-      {
-         return false; // warning
-      }
-      ParameterizedType oldParamType = (ParameterizedType) oldDeclaringType;
-      for (iterator = variableReplacements.listIterator(); iterator.hasNext(); )
-      {
-         if(iterator.next().replace(oldParamType, newDeclaringClass))
-         {
-            iterator.remove();
-         }
-      }
-      iterator = null;
-      return true; 
-   }
-   
-   public Type[] getArguments()
-   {
-      return this.arguments;
-   }
-   
-   public void createVariableReplacement(int variableIndex, Type[] replacementTarget,
-         int targetIndex)
-   {
-      if (iterator != null)
-      {
-         iterator.add(new VariableReplacement(variableIndex, replacementTarget,
-            targetIndex));
-      }
-      else
-      {
-         this.variableReplacements.add(new VariableReplacement(
-               variableIndex, replacementTarget, targetIndex));
-      }
-   }
-   private static ReplacementRecorder<VariableReplacement> updater = new ReplacementRecorder<VariableReplacement>()
-   {
-      public void recordReplacement(VariableReplacement outer, int variableIndex, Type[] replacementTarget, int targetIndex)
-      {
-         if (outer.pendingReplacement) // outer is already busy
-         {
-            outer.getOuter().createVariableReplacement(variableIndex,
-                  replacementTarget, targetIndex);
-         }
-         else
-         {
-            outer.variableIndex = variableIndex;
-            outer.target = replacementTarget;
-            outer.targetIndex = targetIndex;
-            outer.pendingReplacement = true;
-         }
-      }
-   };
-   
-   class VariableReplacement
-   {
-      private int variableIndex;
-      private Type[] target;
-      private int targetIndex;
-      private boolean pendingReplacement;
-      
-      public VariableReplacement(int variableIndex, Type[] target, int targetIndex)
-      {
-         this.variableIndex = variableIndex;
-         this.target = target;
-         this.targetIndex = targetIndex;
-         this.pendingReplacement = true;
-      }
-      
-      // return true if replacement has been done for good
-      public boolean replace(ParameterizedType paramType, Class<?> declaringClass)
-      {
-         target[targetIndex] = paramType.getActualTypeArguments()[variableIndex];
-         this.pendingReplacement = false;
-         Type newType = ContextualizedArguments.processArgument(target, targetIndex,
-               declaringClass, updater, this);
-         if (newType != null)
-         {
-            target[targetIndex] = newType;
-            return false;
-         }
-         return true;
-      }
-      
-      ContextualizedArguments getOuter()
-      {
-         return ContextualizedArguments.this;
-      }
-   }
-   
-   private static class ParameterizedType_ implements ParameterizedType
-   {
-      private Type[] arguments;
-      private Type ownerType;
-      private Type rawType;
-      
-      ParameterizedType_(ParameterizedType type)
-      {
-         Type[] actualArguments = type.getActualTypeArguments();
-         this.arguments = new Type[actualArguments.length];
-         System.arraycopy(actualArguments, 0, arguments, 0, actualArguments.length);
-         this.ownerType = type.getOwnerType();
-         this.rawType = type.getRawType();
-      }
-      
-      
-      public Type[] getActualTypeArguments()
-      {
-         return this.arguments;
-      }
-
-      public Type getOwnerType()
-      {
-         return this.ownerType;
-      }
-
-      public Type getRawType()
-      {
-         return this.rawType;
-      }
-      
-      public boolean equals(Object obj)
-      {
-         if (!(obj instanceof ParameterizedType))
-         {
-            return false;
-         }
-         ParameterizedType other = (ParameterizedType) obj;
-         if (!this.ownerType.equals(other.getOwnerType()) ||
-             !this.rawType.equals(other.getRawType()))
-         {
-            return false;
-         }
-         Type[] otherArguments = other.getActualTypeArguments();
-         for (int i = 0; i < arguments.length; i++)
-         {
-            if (!arguments[i].equals(otherArguments[i]))
-            {
-               return false;
-            }
-         }
-         return true;
-      }
-   }
-   
-   interface ReplacementRecorder<T>
-   {
-      public void recordReplacement(T outer, int variableIndex, Type[] replacementTarget, int targetIndex);
-      
-   }
-}
\ No newline at end of file

Copied: projects/aop/trunk/aop/src/main/org/jboss/aop/advice/annotation/ParamTypeAssignabilityAlgorithm.java (from rev 63629, projects/aop/trunk/aop/src/main/org/jboss/aop/advice/annotation/ContextualizedArguments.java)
===================================================================
--- projects/aop/trunk/aop/src/main/org/jboss/aop/advice/annotation/ParamTypeAssignabilityAlgorithm.java	                        (rev 0)
+++ projects/aop/trunk/aop/src/main/org/jboss/aop/advice/annotation/ParamTypeAssignabilityAlgorithm.java	2007-07-04 00:21:41 UTC (rev 63807)
@@ -0,0 +1,151 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.aop.advice.annotation;
+
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+
+/**
+ * 
+ * 
+ * @author  <a href="flavia.rainone at jboss.com">Flavia Rainone</a>
+ */
+class ParamTypeAssignabilityAlgorithm
+{
+   /**
+    * Class responsible for telling whether two groups of arguments, used on
+    * two different instances of ParameterizedType, can be considered the same
+    * group of arguments.
+    * 
+    * @author  <a href="flavia.rainone at jboss.com">Flavia Rainone</a>
+    *
+    * @param <T> this is a token that can be used to store information useful for
+    *            the implementor.
+    */
+   static abstract class EqualityChecker<T>
+   {
+      /**
+       * Indicates whether both argument list can be considered the same.
+       * This method is a facility that will invoke {@link #isSame(Type, Type, Object)}
+       * for each argument of the lists. Both lists have the same length.
+       * 
+       * @param arguments     list of arguments.
+       * @param fromArguments list of arguments that will be assigned to <code>
+       *                      arguments</code> only if this method returns <code>true
+       *                      </code>
+       * @param token         a token that may be needed by implementor as auxiliar
+       * @return              <code>true</code> only if values of <code>
+       *                      fromArguments</code> list can be assigned to a list of
+       *                      <code>arguments</code> type.
+       */
+      protected boolean isSame(Type[] arguments, Type[] fromArguments, T token)
+      {
+         for (int i = 0; i < arguments.length; i++)
+         {
+            if (!isSame(arguments[i], fromArguments[i], token))
+            {
+               return false;
+            }
+         }
+         return true;
+      }
+
+      /**
+       * Indicates whether both arguments can be considered the same.
+       * This method execution might require some variable inference process,
+       * in which case only a variable type referenced by <code>argument</code> can
+       * have its value infered according to the process.
+       * @param token         a token that may be needed by implementor as auxiliar
+       * @param arguments     an argument type
+       * @param fromArguments argument type that will have its value assigned to
+       *                      <code>argument</code> only if this method returns
+       *                      <code>true</code>
+       * 
+       * @return              <code>true</code> only if a parameterized type with
+       *                      <code>argument</code> as one of its parameter values
+       *                      can be assigned from the same parameterized type with
+       *                      <code>fromArgument</code> as the equivalent parameter
+       *                      value
+       */
+      abstract boolean isSame(Type argument, Type fromArgument, T token);
+   }
+
+   /**
+    * 
+    * @param <T>
+    * @param paramType
+    * @param fromType
+    * @param checker
+    * @param checkerToken
+    * @return
+    */
+   public static<T> boolean isAssignable(ParameterizedType paramType, Type fromType,
+         EqualityChecker<T> checker, T checkerToken)
+   {
+      Class<?> fromRaw = null;
+      ParameterizedType fromParamType = null;
+      Class<?> desiredType = (Class<?>) paramType.getRawType();
+      if (fromType instanceof Class)
+      {
+         fromRaw = (Class<?>) fromType;
+         if (!desiredType.isAssignableFrom(fromRaw))
+         {
+            return false;
+         }
+         if (fromRaw.getTypeParameters().length > 0)
+         {
+            // notice that, if fromRaw equals desiredType, we also have the
+            // result true with a warning (i.e., this if statemente is not only for
+            // fromRaw subclass of desiredType, but also for fromRaw same as
+            // desiredType
+            return true;// TODO With warning
+         }
+      }
+      else if (fromType instanceof ParameterizedType)
+      {
+         fromParamType = (ParameterizedType) fromType;
+         fromRaw = (Class<?>) fromParamType.getRawType();
+         if (fromRaw == desiredType)
+         {
+            // compare arguments with arguments
+            return checker.isSame(paramType.getActualTypeArguments(),
+                  fromParamType.getActualTypeArguments(), checkerToken);
+         }
+         else if (!desiredType.isAssignableFrom(fromRaw))
+         {
+            return false;
+         }
+      }
+      else
+      {
+         return false;
+      }
+      // try to get, if null, warning, parameters lost in hierarchy
+      Type[] arguments = ArgumentContextualizer.getContextualizedArguments(
+            fromParamType, fromRaw, desiredType);
+      if (arguments == null)
+      {
+         return true; // TODO with Warning
+      }
+      return checker.isSame(paramType.getActualTypeArguments(), arguments, checkerToken);
+   }
+}
\ No newline at end of file

Modified: projects/aop/trunk/aop/src/main/org/jboss/aop/advice/annotation/VariableNode.java
===================================================================
--- projects/aop/trunk/aop/src/main/org/jboss/aop/advice/annotation/VariableNode.java	2007-07-03 23:53:31 UTC (rev 63806)
+++ projects/aop/trunk/aop/src/main/org/jboss/aop/advice/annotation/VariableNode.java	2007-07-04 00:21:41 UTC (rev 63807)
@@ -34,8 +34,9 @@
 import java.util.Map;
 
 /**
+ * 
+ * 
  * @author  <a href="flavia.rainone at jboss.com">Flavia Rainone</a>
- *
  */
 public class VariableNode
 {
@@ -70,8 +71,15 @@
    {
       if (this.assignedValue != null)
       {
-         return isSame(this.assignedValue, value);
+         return isSame(this.assignedValue, value, true);
       }
+      
+      // TODO fix this
+      /*if (value instanceof WildcardType)
+      {
+         return false;
+      }*/
+      
       if (!isInsideBounds(value, true) ||
             (this.previous != null && !this.previous.areBoundsInside(value)))
       {
@@ -130,7 +138,7 @@
    
    private boolean isInsideBounds(Type lowerBound, boolean checkLowerBounds)
    {
-      if (this.assignedValue != null && !isAssignable(assignedValue, lowerBound))
+      if (this.assignedValue != null && !isAssignable(lowerBound, assignedValue))
       {
          return false;
       }
@@ -138,7 +146,7 @@
       {
          for (Type bound: this.lowerBounds)
          {
-            if (!isAssignable(bound, lowerBound))
+            if (!isAssignable(lowerBound, bound))
             {
                return false;
             }
@@ -160,43 +168,43 @@
    }
    
    // both type and bound belong to the same context
-   private boolean isAssignable(Type bound, Type type)
+   private boolean isAssignable(Type type, Type fromType)
    {
-      if (type instanceof TypeVariable)
+      if (fromType instanceof TypeVariable)
       {
-         if (bound instanceof TypeVariable)
+         TypeVariable fromVariable = (TypeVariable) fromType;
+         Type[] fromBounds = fromVariable.getBounds();
+         if (type instanceof TypeVariable)
          {
-            if (type == bound)
+            if (type == fromType)
             {
                return true;
             }
-            TypeVariable typeVariable = (TypeVariable) type;
-            Type[] bounds = typeVariable.getBounds();
-            while (bounds.length == 1 && bounds[0] instanceof TypeVariable)
+            while (fromBounds.length == 1 && fromBounds[0] instanceof TypeVariable)
             {
-               if (bounds[0] == bound)
+               if (fromBounds[0] == type)
                {
                   return true;
                }
-               type = (TypeVariable) bounds[0];
-               bounds = typeVariable.getBounds();
+               fromType = (TypeVariable) fromBounds[0];
+               fromBounds = fromVariable.getBounds();
             }
-            TypeVariable variableBound = (TypeVariable) bound;
-            Type[] variableBoundBounds = typeVariable.getBounds();
-            while (variableBoundBounds.length == 1 && variableBoundBounds[0] instanceof TypeVariable)
+            TypeVariable variable = (TypeVariable) type;
+            Type[] bounds = variable.getBounds();
+            while (bounds.length == 1 && bounds[0] instanceof TypeVariable)
             {
-               if (variableBoundBounds[0] == type)
+               if (bounds[0] == fromType)
                {
                   return false;
                }
-               variableBound = (TypeVariable) variableBoundBounds[0];
-               variableBoundBounds = variableBound.getBounds();
+               variable = (TypeVariable) bounds[0];
+               bounds = variable.getBounds();
             }
-            outer: for (int i = 0; i < variableBoundBounds.length; i++)
+            outer: for (int i = 0; i < bounds.length; i++)
             {
-               for (int j = 0; j < bounds.length; j++)
+               for (int j = 0; j < fromBounds.length; j++)
                {
-                  if (isAssignable(variableBoundBounds[i], bounds[j]))
+                  if (isAssignable(bounds[i], fromBounds[j]))
                   {
                      continue outer;
                   }
@@ -205,53 +213,94 @@
             }
             return true;
          }
-         for (Type variableBound: ((TypeVariable) type).getBounds())
+         while (fromBounds.length == 1 && fromBounds[0] instanceof TypeVariable)
          {
-            if (isAssignable(bound, variableBound))
+            fromBounds = fromVariable.getBounds();
+         }
+         for (Type fromBound: fromBounds)
+         {
+            if (isAssignable(type, fromBound))
             {
                return true;
             }
          }
          return false;
       }
-      if (bound instanceof Class)
+      if (type instanceof Class)
       {
-         if (bound == Object.class)
+         if (type == Object.class)
          {
             return true;
          }
-         Class<?> boundClass = (Class<?>) bound;
-         if (type instanceof Class)
+         Class<?> clazz = (Class<?>) type;
+         if (fromType instanceof Class)
          {
-            return boundClass.isAssignableFrom((Class<?>) type);
+            return clazz.isAssignableFrom((Class<?>) fromType);
          }
-         if (type instanceof ParameterizedType)
+         if (fromType instanceof ParameterizedType)
          {
-            return boundClass.isAssignableFrom((Class<?>) ((ParameterizedType) type).getRawType());
+            return clazz.isAssignableFrom((Class<?>) ((ParameterizedType) fromType).getRawType());
          }
-         return boundClass.isArray() && isAssignable(boundClass.getComponentType(), ((GenericArrayType) type).
-                     getGenericComponentType());
+         if (fromType instanceof WildcardType)
+         {
+            WildcardType fromWildcard = (WildcardType) fromType;
+            boolean boundOk = false;
+            for (Type upperBound: fromWildcard.getUpperBounds())
+            {
+               if (isAssignable(type, upperBound))
+               {
+                  boundOk = true;
+                  break;
+               }
+            }
+            if (!boundOk)
+            {
+               return false;
+            }
+            for (Type lowerBound: fromWildcard.getUpperBounds())
+            {
+               if (isAssignable(type, lowerBound))
+               {
+                  return true;
+               }
+            }
+            return false;
+         }
+         if (fromType instanceof TypeVariable)
+         {
+            for (Type upperBound: ((TypeVariable) fromType).getBounds())
+            {
+               if (isAssignable(type, upperBound))
+               {
+                  return true;
+               }
+            }
+            return false;
+         }
+         return clazz.isArray() && isAssignable(clazz.getComponentType(), 
+               ((GenericArrayType) fromType).getGenericComponentType());
       }
-      if (bound instanceof ParameterizedType)
+      if (type instanceof ParameterizedType)
       {
-         return ContextualizedArguments.isAssignable(CHECKER, (ParameterizedType) bound, type, this);
+         return ParamTypeAssignabilityAlgorithm.isAssignable(
+               (ParameterizedType) type, fromType, CHECKER, this);
       }
-      if (bound instanceof TypeVariable)
+      if (type instanceof TypeVariable)
       {
-         for (Type typeBound: ((TypeVariable) bound).getBounds())
+         for (Type bound: ((TypeVariable) type).getBounds())
          {
-            if (!isAssignable(typeBound, type))
+            if (!isAssignable(bound, fromType))
             {
                return false;
             }
          }
          return true;
       }
-      ChoiceBound choiceBound = (ChoiceBound) bound;
+      ChoiceBound choiceBound = (ChoiceBound) type;
       for (Iterator<Type> it = choiceBound.bounds.iterator(); it.hasNext();)
       {
-         Type option = it.next();
-         if (!isAssignable(option, type))
+         Type boundOption = it.next();
+         if (!isAssignable(boundOption, fromType))
          {
             it.remove();
          }
@@ -259,28 +308,28 @@
       return !choiceBound.bounds.isEmpty();
    }
    
-   protected boolean isSame(Type assignableArgument, Type argument)
+   protected boolean isSame(Type argument, Type fromArgument, boolean argumentAssigned)
    {
-      if (assignableArgument instanceof WildcardType)
+      if (argument instanceof WildcardType)
       {
-         WildcardType assignableWildcardArg = (WildcardType) assignableArgument;
-         Type[] upperAssignBounds = assignableWildcardArg.getUpperBounds();
-         Type[] lowerAssignBounds = assignableWildcardArg.getUpperBounds();
-         if (argument instanceof WildcardType)
+         WildcardType wildcard = (WildcardType) argument;
+         Type[] upperBounds = wildcard.getUpperBounds();
+         Type[] lowerBounds = wildcard.getLowerBounds();
+         if (fromArgument instanceof WildcardType)
          {
-            WildcardType wildcardArg = (WildcardType) argument;
-            Type[] upperBounds = wildcardArg.getUpperBounds();
-            if (!isAssignable(upperAssignBounds, upperBounds))
+            WildcardType fromWildcard = (WildcardType) fromArgument;
+            Type[] fromUpperBounds = fromWildcard.getUpperBounds();
+            if (!isAssignable(upperBounds, fromUpperBounds))
             {
                return false;
             }
             
-            Type[] lowerBounds = wildcardArg.getLowerBounds();
-            outer: for (int i = 0; i < lowerBounds.length; i++)
+            Type[] fromLowerBounds = fromWildcard.getLowerBounds();
+            outer: for (int i = 0; i < fromLowerBounds.length; i++)
             {
-               for (int j = 0; j < lowerAssignBounds.length; j++)
+               for (int j = 0; j < lowerBounds.length; j++)
                {
-                  if (isAssignable(lowerBounds[i], lowerAssignBounds[j]))
+                  if (isAssignable(fromLowerBounds[i], lowerBounds[j]))
                   {
                      continue outer;
                   }
@@ -289,18 +338,22 @@
             }
             return true;
          }
-         else if(argument instanceof TypeVariable)
+         if (argumentAssigned)
          {
-            if (!isAssignable(upperAssignBounds, ((TypeVariable) argument).getBounds()))
+            return false;
+         }
+         if(fromArgument instanceof TypeVariable)
+         {
+            if (!isAssignable(upperBounds, ((TypeVariable) fromArgument).getBounds()))
             {
                return false;
             }
          }
          else
          {
-            for (int i = 0; i < upperAssignBounds.length; i++)
+            for (int i = 0; i < upperBounds.length; i++)
             {
-               if (!isAssignable(upperAssignBounds[i], argument))
+               if (!isAssignable(upperBounds[i], fromArgument))
                {
                   return false;
                }
@@ -308,33 +361,34 @@
             return true;
          }
       }
-      else if (assignableArgument instanceof GenericArrayType)
+      else if (argument instanceof GenericArrayType)
       {
-         if (argument instanceof GenericArrayType)
+         if (fromArgument instanceof GenericArrayType)
          {
-            return isSame(((GenericArrayType) assignableArgument).getGenericComponentType(),
-                  ((GenericArrayType) argument).getGenericComponentType());
+            return isSame(((GenericArrayType) argument).getGenericComponentType(),
+                  ((GenericArrayType) fromArgument).getGenericComponentType(),
+                  argumentAssigned);
          }
          else
          {
             return false;
          }
       }
-      return assignableArgument.equals(argument);
+      return argument.equals(fromArgument); // TODO check this works correctly
    }
 
    /**
     * @param node
     * @param upperBounds
-    * @param upperAssignBounds
+    * @param upperBounds
     */
-   private boolean isAssignable(Type[] upperAssignBounds, Type[] upperBounds)
+   private boolean isAssignable(Type[] upperBounds, Type[] fromUpperBounds)
    {
-      outer: for (int i = 0; i < upperAssignBounds.length; i++)
+      outer: for (int i = 0; i < upperBounds.length; i++)
       {
-         for (int j = 0; j < upperBounds.length; j++)
+         for (int j = 0; j < fromUpperBounds.length; j++)
          {
-            if (isAssignable(upperAssignBounds[i], upperBounds[j]))
+            if (isAssignable(upperBounds[i], fromUpperBounds[j]))
             {
                continue outer;
             }
@@ -344,12 +398,12 @@
       return true;
    }
    
-   private static ContextualizedArguments.EqualityChecker<VariableNode> CHECKER =
-      new ContextualizedArguments.EqualityChecker<VariableNode>()
+   private static ParamTypeAssignabilityAlgorithm.EqualityChecker<VariableNode> CHECKER =
+      new ParamTypeAssignabilityAlgorithm.EqualityChecker<VariableNode>()
       {
-         public boolean isSame(Type assignableArgument, Type argument, VariableNode node)
+         public boolean isSame(Type argument, Type fromArgument, VariableNode node)
          {
-            return node.isSame(assignableArgument, argument);
+            return node.isSame(fromArgument, argument, false);
          }
       };
 }




More information about the jboss-cvs-commits mailing list