incubator-imperius-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From daw...@apache.org
Subject svn commit: r945351 - /incubator/imperius/trunk/imperius-javaspl/src/main/java/org/apache/imperius/javaspl/JavaActuatorImpl.java
Date Mon, 17 May 2010 20:34:45 GMT
Author: dawood
Date: Mon May 17 20:34:45 2010
New Revision: 945351

URL: http://svn.apache.org/viewvc?rev=945351&view=rev
Log:
add findMatchingMethod() to allow subclasses to match method parameters.

Modified:
    incubator/imperius/trunk/imperius-javaspl/src/main/java/org/apache/imperius/javaspl/JavaActuatorImpl.java

Modified: incubator/imperius/trunk/imperius-javaspl/src/main/java/org/apache/imperius/javaspl/JavaActuatorImpl.java
URL: http://svn.apache.org/viewvc/incubator/imperius/trunk/imperius-javaspl/src/main/java/org/apache/imperius/javaspl/JavaActuatorImpl.java?rev=945351&r1=945350&r2=945351&view=diff
==============================================================================
--- incubator/imperius/trunk/imperius-javaspl/src/main/java/org/apache/imperius/javaspl/JavaActuatorImpl.java
(original)
+++ incubator/imperius/trunk/imperius-javaspl/src/main/java/org/apache/imperius/javaspl/JavaActuatorImpl.java
Mon May 17 20:34:45 2010
@@ -89,8 +89,8 @@ public class JavaActuatorImpl implements
 			Class[] arrayOfParameterTypes = _getParameterTypeArray(arguments);
 
 			// Load the method using reflection
-
-			Method method = c.getMethod(methodName, arrayOfParameterTypes);
+//			Method method = c.getMethod(methodName, arrayOfParameterTypes);
+			Method method = findMatchingMethod(c, methodName, arrayOfParameterTypes);
 
 			// If No. of formal params > 0
 			if (arguments.size() != 0) {
@@ -129,6 +129,93 @@ public class JavaActuatorImpl implements
 	}
 
 	/**
+	 * We build our own method search routine because the
+	 * parameter types might be sub-classes of the declared method parameters.
+	 * Unfortunately, Class.getMethod() does not handle sub-classes.
+	 * @param c
+	 * @param name
+	 * @param parameterTypes
+	 * @return
+	 * @throws NoSuchMethodException 
+	 */
+	private static Method findMatchingMethod(Class c, String name,	Class[] parameterTypes) throws
NoSuchMethodException {
+		Method m = null;
+		try {
+			m = c.getMethod(name, parameterTypes);
+			return m;
+		} catch (Exception e) {
+			; // fall through
+		}
+		
+		// Search all method that match the name and find the one that is
+		// closest 
+		int minDistance = Integer.MAX_VALUE;
+		Method[] methods = c.getMethods();
+		for (int i=0 ; i<methods.length ; i++) {
+			if (methods[i].getName().equals(name)) {
+				int distance = parameterMatchDistance(methods[i].getParameterTypes(), parameterTypes);
+				if (distance >= 0 && distance < minDistance) {
+					distance = minDistance;
+					m = methods[i];
+				}
+			}
+		}
+		if (m == null)
+			throw new NoSuchMethodException("Could not find method named " + name +
+					" and correct set of parameters");
+		
+		return m;
+	}
+
+	private static int parameterMatchDistance(Class<?>[] expectedTypes, Class[] givenTypes)
{
+		if (expectedTypes.length != givenTypes.length)
+			return -1; 	// No match is possible.
+		
+		int score = 0;
+		for (int i=0 ; i<expectedTypes.length ; i++) {
+			if (expectedTypes[i].isAssignableFrom(givenTypes[i])) {
+				score += typeMatchDistance(expectedTypes[i], givenTypes[i]);
+			} else {
+				return -1;
+			}
+		}
+		return score;
+	}
+
+	/**
+	 * Calculate a 'distance' between the types.
+	 * @param lhs
+	 * @param rhs
+	 * @return
+	 */
+	private static int typeMatchDistance(Class<?> lhs, Class rhs) {
+		int score = 0;
+		Class superClass = rhs;
+		boolean foundMatch = superClass.equals(lhs);
+
+		// First search up the super class heirarchy.
+		while (superClass != null && !foundMatch) {
+			superClass = superClass.getSuperclass();
+			if (superClass != null)
+				foundMatch = superClass.equals(lhs);
+			score++;
+		}
+		
+		// If no match in super-classes, try the interfaces.
+		if (!foundMatch) {
+			score = Integer.MAX_VALUE;
+			Class[] interfaces = lhs.getInterfaces();
+			for (int i=0 ; i<interfaces.length ; i++) {
+				int tmp = typeMatchDistance(interfaces[i], rhs);
+				if (tmp < score) {
+					score = tmp;
+				}
+			}
+		}
+		return score;
+	}
+
+	/**
 	 * @param className : fully qualified name of the class whoose instance is to be modified
 	 * @param instance : instance to be modified
 	 * @param memberMap: A map of the form (String member Name ->  Object value to be set
to)



Mime
View raw message