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

jboss-cvs-commits at lists.jboss.org jboss-cvs-commits at lists.jboss.org
Fri Jul 6 22:03:49 EDT 2007


Author: flavia.rainone at jboss.com
Date: 2007-07-06 22:03:49 -0400 (Fri, 06 Jul 2007)
New Revision: 63895

Added:
   projects/aop/trunk/aop/src/main/org/jboss/aop/advice/annotation/assignability/DegreeAlgorithm.java
Log:
[JBAOP-421] Algorithm implemented.

Added: projects/aop/trunk/aop/src/main/org/jboss/aop/advice/annotation/assignability/DegreeAlgorithm.java
===================================================================
--- projects/aop/trunk/aop/src/main/org/jboss/aop/advice/annotation/assignability/DegreeAlgorithm.java	                        (rev 0)
+++ projects/aop/trunk/aop/src/main/org/jboss/aop/advice/annotation/assignability/DegreeAlgorithm.java	2007-07-07 02:03:49 UTC (rev 63895)
@@ -0,0 +1,286 @@
+/*
+ * 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.assignability;
+
+import java.lang.reflect.GenericArrayType;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.lang.reflect.TypeVariable;
+import java.util.ArrayList;
+
+import org.jboss.aop.advice.annotation.AdviceMethodFactory;
+
+/**
+ * 
+ * @author  <a href="flavia.rainone at jboss.com">Flavia Rainone</a>
+ */
+public class DegreeAlgorithm
+{
+   private static final short HIGHEST_DEGREE = 1000;
+   public static final short NOT_ASSIGNABLE_DEGREE = Short.MAX_VALUE;
+   public static final short MAX_DEGREE = NOT_ASSIGNABLE_DEGREE - 1;
+   
+   private static final DegreeAlgorithm INSTANCE = new DegreeAlgorithm();
+   
+   public static DegreeAlgorithm getInstance()
+   {
+      return INSTANCE;
+   }
+   
+   private DegreeAlgorithm(){}
+   
+   public short getAssignabilityDegree(Type type, Type fromType)
+   {
+      if (type == null || fromType == null)
+      {
+         return DegreeAlgorithm.MAX_DEGREE;
+      }
+       Class<?> clazz = getClassType(type);
+       if (clazz == null)
+       {
+          return HIGHEST_DEGREE;
+       }
+       Class<?> fromClass = getClassType(fromType);
+       if (fromClass == null)
+       {
+          return HIGHEST_DEGREE;
+       }
+       return getAssignabilityDegree(fromClass, clazz);
+   }
+   
+   private Class<?> getClassType(Type type)
+   {
+      if (type instanceof Class)
+      {
+         return (Class<?>) type;
+      }
+      if (type instanceof ParameterizedType)
+      {
+         return (Class<?>) ((ParameterizedType) type).getRawType();
+      }
+      if (type instanceof TypeVariable)
+      {
+         return null;
+      }
+      Type componentType = ((GenericArrayType) type).getGenericComponentType();
+      Class componentClass = getClassType(componentType);
+      try
+      {
+         return componentClass.getClassLoader().loadClass(
+               componentClass.getName() + "[]");
+      }
+      catch (ClassNotFoundException e)
+      {
+         throw new RuntimeException(e);
+      }
+   }
+   
+   /**
+    * Returns the assignability degree from <code>fromType</code> to </code>toType</code>. 
+    * <p>
+    * The assignability degree is the distance in class and interface hierarchy between
+    * <code>fromType</code> and </code>toType</code>. If <code>toType</code> is an
+    * interface implemented by <code>fromType</code>, then the degree is 1. Otherwise,
+    * the degree is exactly the number of hierarchical levels between <code>fromType
+    * </code> and <code>toType</code>.
+    * 
+    * @param fromType the type from which <code>toType</code> is supposedly assignable.
+    * @param toType   the type to which <code>fromType</code> can be converted without
+    *                 type casting.
+    * @return {@link AdviceMethodFactory#NOT_ASSIGNABLE_DEGREE if <code>toType</code> is
+    *         not assignable from <code>fromType</code>; the hierarchical distance between
+    *         <code>fromType</code> and <code>toType</code> otherwise.
+    *         
+    * @see java.lang.Class#isAssignableFrom(Class)
+    */
+   private short getAssignabilityDegree(Class<?> fromType, Class<?> toType)
+   {
+      // they're the same
+      if (fromType == toType)
+      {
+         return 0;
+      }
+      if (toType.isInterface())
+      {
+         if (fromType.isInterface())
+         {
+            // assignability degree on interface inheritance
+            return getInterfaceInheritanceAD(fromType, toType, (short) 0);
+         }
+         else
+         {
+            // assignability degree on interface implementation
+            return getImplementationAD(fromType, toType);
+         }
+      }
+      if (fromType.isInterface())
+      {
+         // if is object, the degree is the size of this interface hierarchy + 1
+         if (toType.getName() == "java.lang.Object")
+         {
+            ArrayList<Class[]> list1 = new ArrayList<Class[]>();
+            ArrayList<Class[]> list2 = new ArrayList<Class[]>();
+            Class[] fromTypeInterfaces = fromType.getInterfaces();
+            if (fromTypeInterfaces.length == 0)
+            {
+               return 1;
+            }
+            list1.add(fromTypeInterfaces);
+            short degree = 2;
+            while (true)
+            {
+               for (Class[] interfaces : list1)
+               {
+                  for (int i = 0; i < interfaces.length; i++)
+                  {
+                     Class[] superInterfaces = interfaces[i].getInterfaces();
+                     if (superInterfaces.length == 0)
+                     {
+                        return degree;
+                     }
+                     list2.add(superInterfaces);
+                  }
+               }
+               degree ++;
+               list1.clear();
+               ArrayList<Class[]> temp = list1;
+               list1 = list2;
+               list2 = temp;
+            }
+         }
+         // you can't get to a class (except Object) from an interface
+         return DegreeAlgorithm.NOT_ASSIGNABLE_DEGREE;
+      }
+      // assignability degree on class inheritance
+      return getClassInheritanceAD(fromType.getSuperclass(), toType, (short) 1);
+   }
+   
+   /**
+    * Returns the assignability degree between <code>fromClassType</code> and <code>
+    * toInterfaceType</code>.
+    * 
+    * @param fromClassType   a class type that supposedly implements <code>
+    *                        toInterfaceType</code>
+    * @param toInterfaceType an interface type that is supposedly implemented by <code>
+    *                        fromClassType</code>
+    * @return {@link AdviceMethodFactory#NOT_ASSIGNABLE_DEGREE} if <code>fromClassType
+    *         </code> does not implement <code>toInterfaceType</code>; otherwise, if
+    *         <code>fromType</code> implements a subinterface of <code>toInterfaceType
+    *         </code>, returns 1 + the assignability degree between this subinterface and
+    *         <code>toType</code>; otherwhise, returns 1.
+    *         
+    */
+   private short getImplementationAD(Class<?> fromClassType, Class<?> toInterfaceType)
+   {
+      if (fromClassType == null)
+      {
+         return DegreeAlgorithm.NOT_ASSIGNABLE_DEGREE;
+      }
+      
+      Class[] interfaces = fromClassType.getInterfaces();
+      for (int i = 0 ; i < interfaces.length ; i++)
+      {
+         if(interfaces[i] == toInterfaceType)
+         {
+            return 1;
+         }
+      }
+      short currentDegree = DegreeAlgorithm.NOT_ASSIGNABLE_DEGREE;
+      for (int i = 0 ; i < interfaces.length ; i++)
+      {
+         currentDegree = (short) Math.min(getInterfaceInheritanceAD(interfaces[i],
+               toInterfaceType, (short) 1), currentDegree);
+      }
+      if (currentDegree == DegreeAlgorithm.NOT_ASSIGNABLE_DEGREE)
+      {
+         return getImplementationAD(fromClassType.getSuperclass(), toInterfaceType);
+      }
+      return currentDegree;
+   }
+   
+   /**
+    * Recursive method that returns the assignability degree on an interface inheritance.
+    * 
+    * @param fromInterfaceType  the interface that supposedly inherits (directly or
+    *                           indirectly <code>toInterfaceType</code>.
+    * @param toInterfaceType    the interface which is supposedly assignable from <code>
+    *                           fromInterfaceType</code>. The type <code>
+    *                           toInterfaceType</code> is not the same as <code>
+    *                           fromInterfaceType</code>.
+    * @param currentDegree      the current assignability degree
+    * @return                   {@link AdviceMethodFactory#NOT_ASSIGNABLE_DEGREE} if
+    *                           <code>toInterfaceType</code> is not assignable from <code>
+    *                           fromInterfaceType</code>; <code>currentDegree + </code>
+    *                           the assignability degree from <code>fromInterfaceType
+    *                           </code> to <code>toInterfaceType</code>.
+    */
+   private short getInterfaceInheritanceAD(Class<?> fromInterfaceType,
+         Class<?> toInterfaceType, short currentDegree)
+   {
+      Class[] interfaces = fromInterfaceType.getInterfaces();
+      currentDegree ++;
+      for (int i = 0; i < interfaces.length; i++)
+      {
+         if(interfaces[i] == toInterfaceType)
+         {
+            return currentDegree;
+         }
+      }
+      short bestDegree = DegreeAlgorithm.NOT_ASSIGNABLE_DEGREE;
+      for (int i = 0; i < interfaces.length; i++)
+      {
+         bestDegree = (short) Math.min(getInterfaceInheritanceAD(interfaces[i],
+               toInterfaceType, currentDegree), bestDegree);
+      }
+      return bestDegree;
+   }
+   
+   /**
+    * Recursive method that returns the assignability degree on an class inheritance.
+    * 
+    * @param fromClassType  the class that supposedly inherits (directly or
+    *                       indirectly <code>toClassType</code>.
+    * @param toClassType    the class which is supposedly assignable from <code>
+    *                       fromInterfaceType</code>. The type <code>toClassType</code> is
+    *                       not the same as <code>fromClassType</code>.
+    * @param currentDegree  the current assignability degree
+    * @return               {@link AdviceMethodFactory#NOT_ASSIGNABLE_DEGREE} if <code>
+    *                       toClassType</code> is not assignable from <code>fromClassType
+    *                       </code>; <code>currentDegree + </code> the assignability
+    *                       degree from <code>fromClassType</code> to <code>toClassType
+    *                       </code>.
+    */
+   private short getClassInheritanceAD(Class<?> fromClassType, Class<?> toClassType,
+         short currentDegree)
+   {
+      if (fromClassType == null)
+      {
+         return DegreeAlgorithm.NOT_ASSIGNABLE_DEGREE;
+      }
+      if (fromClassType == toClassType)
+      {
+         return currentDegree;
+      }
+      return getClassInheritanceAD(fromClassType.getSuperclass(), toClassType,
+            ++currentDegree);
+   }
+}
\ No newline at end of file




More information about the jboss-cvs-commits mailing list