/**************************************************************************************
* Copyright (c) Jonas Bon�r, Alexandre Vasseur. All rights reserved. *
* http://aspectwerkz.codehaus.org *
* ---------------------------------------------------------------------------------- *
* The software in this package is published under the terms of the LGPL license *
* a copy of which has been included with this distribution in the license.txt file. *
**************************************************************************************/
package org.codehaus.aspectwerkz.reflect;
import org.codehaus.aspectwerkz.exception.WrappedRuntimeException;
import org.codehaus.aspectwerkz.transform.TransformationConstants;
import org.codehaus.aspectwerkz.util.Strings;
import java.lang.reflect.Method;
import java.util.Comparator;
/**
* Compares Methods. To be used when sorting methods.
*
* @author <a href="mailto:jboner@codehaus.org">Jonas Bon�r </a>
*/
public final class MethodComparator implements java.util.Comparator {
/**
* Compares normal method names.
*/
public static final int NORMAL_METHOD = 0;
/**
* Compares prefixed method names.
*/
public static final int PREFIXED_METHOD = 1;
/**
* Compares method infos.
*/
public static final int METHOD_INFO = 2;
/**
* Defines the type of comparator.
*/
private final int m_type;
/**
* Sets the type.
*
* @param type the type
*/
private MethodComparator(final int type) {
m_type = type;
}
/**
* Returns the comparator instance.
*
* @param type the type of the method comparison
* @return the instance
*/
public static Comparator getInstance(final int type) {
return new MethodComparator(type);
}
/**
* Compares two objects.
*
* @param o1
* @param o2
* @return int
*/
public int compare(final Object o1, final Object o2) {
switch (m_type) {
case NORMAL_METHOD:
return compareNormal((Method) o1, (Method) o2);
case PREFIXED_METHOD:
return comparePrefixed((Method) o1, (Method) o2);
case METHOD_INFO:
return compareMethodInfo((MethodInfo) o1, (MethodInfo) o2);
default:
throw new RuntimeException("invalid method comparison type");
}
}
/**
* Compares two methods.
*
* @param m1
* @param m2
* @return int
*/
private int compareNormal(final Method m1, final Method m2) {
try {
if (m1.equals(m2)) {
return 0;
}
final String m1Name = m1.getName();
final String m2Name = m2.getName();
if (!m1Name.equals(m2Name)) {
return m1Name.compareTo(m2Name);
}
final Class[] args1 = m1.getParameterTypes();
final Class[] args2 = m2.getParameterTypes();
if (args1.length < args2.length) {
return -1;
}
if (args1.length > args2.length) {
return 1;
}
if (args1.length == 0) {
return 0;
}
for (int i = 0; i < args1.length; i++) {
//handles array types - AW-104
int result = TypeConverter.convertTypeToJava(args1[i]).compareTo(
TypeConverter.convertTypeToJava(args2[i])
);
if (result != 0) {
return result;
}
}
} catch (Throwable e) {
throw new WrappedRuntimeException(e);
}
java.lang.System.err.println(m1.getName());
java.lang.System.err.println(m2.getName());
throw new Error("should be unreachable");
}
/**
* Compares two prefixed methods. Assumes the the prefixed methods looks like this: "somePrefix SEP methodName SEP"
*
* @param m1
* @param m2
* @return int
*/
private int comparePrefixed(final Method m1, final Method m2) {
try {
if (m1.equals(m2)) {
return 0;
}
// compare only the original method names, i.e. remove the prefix and suffix
final String[] m1Tokens = Strings.splitString(m1.getName(), TransformationConstants.DELIMITER);
final String[] m2Tokens = Strings.splitString(m2.getName(), TransformationConstants.DELIMITER);
final String m1Name = m1Tokens[1];
final String m2Name = m2Tokens[1];
if (!m1Name.equals(m2Name)) {
return m1Name.compareTo(m2Name);
}
final Class[] args1 = m1.getParameterTypes();
final Class[] args2 = m2.getParameterTypes();
if (args1.length < args2.length) {
return -1;
}
if (args1.length > args2.length) {
return 1;
}
if (args1.length == 0) {
return 0;
}
for (int i = 0; i < args1.length; i++) {
//handles array types - AW-104
int result = TypeConverter.convertTypeToJava(args1[i]).compareTo(
TypeConverter.convertTypeToJava(args2[i])
);
if (result != 0) {
return result;
}
}
} catch (Throwable e) {
throw new WrappedRuntimeException(e);
}
java.lang.System.err.println(m1.getName());
java.lang.System.err.println(m2.getName());
throw new Error("should be unreachable");
}
/**
* Compares two methods meta-data.
*
* @param m1
* @param m2
* @return int
*/
private int compareMethodInfo(final MethodInfo m1, final MethodInfo m2) {
try {
if (m1.equals(m2)) {
return 0;
}
final String m1Name = m1.getName();
final String m2Name = m2.getName();
if (!m1Name.equals(m2Name)) {
return m1Name.compareTo(m2Name);
}
final ClassInfo[] args1 = m1.getParameterTypes();
final ClassInfo[] args2 = m2.getParameterTypes();
if (args1.length < args2.length) {
return -1;
}
if (args1.length > args2.length) {
return 1;
}
if (args1.length == 0) {
return 0;
}
for (int i = 0; i < args1.length; i++) {
int result;
if (args1[i].getName().equals(args2[i].getName())) {
result = 0;
} else {
result = args1[i].getName().compareTo(args2[i].getName());
}
if (result != 0) {
return result;
}
}
} catch (Throwable e) {
throw new WrappedRuntimeException(e);
}
java.lang.System.err.println(m1.getName());
java.lang.System.err.println(m2.getName());
throw new Error("should be unreachable");
}
}