[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