001: /**************************************************************************************
002: * Copyright (c) Jonas BonŽr, Alexandre Vasseur. All rights reserved. *
003: * http://aspectwerkz.codehaus.org *
004: * ---------------------------------------------------------------------------------- *
005: * The software in this package is published under the terms of the LGPL license *
006: * a copy of which has been included with this distribution in the license.txt file. *
007: **************************************************************************************/package org.codehaus.aspectwerkz.reflect;
008:
009: import org.codehaus.aspectwerkz.exception.WrappedRuntimeException;
010: import org.codehaus.aspectwerkz.transform.TransformationConstants;
011: import org.codehaus.aspectwerkz.util.Strings;
012:
013: import java.lang.reflect.Method;
014: import java.util.Comparator;
015:
016: /**
017: * Compares Methods. To be used when sorting methods.
018: *
019: * @author <a href="mailto:jboner@codehaus.org">Jonas BonŽr </a>
020: */
021: public final class MethodComparator implements java.util.Comparator {
022: /**
023: * Compares normal method names.
024: */
025: public static final int NORMAL_METHOD = 0;
026:
027: /**
028: * Compares prefixed method names.
029: */
030: public static final int PREFIXED_METHOD = 1;
031:
032: /**
033: * Compares method infos.
034: */
035: public static final int METHOD_INFO = 2;
036:
037: /**
038: * Defines the type of comparator.
039: */
040: private final int m_type;
041:
042: /**
043: * Sets the type.
044: *
045: * @param type the type
046: */
047: private MethodComparator(final int type) {
048: m_type = type;
049: }
050:
051: /**
052: * Returns the comparator instance.
053: *
054: * @param type the type of the method comparison
055: * @return the instance
056: */
057: public static Comparator getInstance(final int type) {
058: return new MethodComparator(type);
059: }
060:
061: /**
062: * Compares two objects.
063: *
064: * @param o1
065: * @param o2
066: * @return int
067: */
068: public int compare(final Object o1, final Object o2) {
069: switch (m_type) {
070: case NORMAL_METHOD:
071: return compareNormal((Method) o1, (Method) o2);
072: case PREFIXED_METHOD:
073: return comparePrefixed((Method) o1, (Method) o2);
074: case METHOD_INFO:
075: return compareMethodInfo((MethodInfo) o1, (MethodInfo) o2);
076: default:
077: throw new RuntimeException("invalid method comparison type");
078: }
079: }
080:
081: /**
082: * Compares two methods.
083: *
084: * @param m1
085: * @param m2
086: * @return int
087: */
088: private int compareNormal(final Method m1, final Method m2) {
089: try {
090: if (m1.equals(m2)) {
091: return 0;
092: }
093: final String m1Name = m1.getName();
094: final String m2Name = m2.getName();
095: if (!m1Name.equals(m2Name)) {
096: return m1Name.compareTo(m2Name);
097: }
098: final Class[] args1 = m1.getParameterTypes();
099: final Class[] args2 = m2.getParameterTypes();
100: if (args1.length < args2.length) {
101: return -1;
102: }
103: if (args1.length > args2.length) {
104: return 1;
105: }
106: if (args1.length == 0) {
107: return 0;
108: }
109: for (int i = 0; i < args1.length; i++) {
110: //handles array types - AW-104
111: int result = TypeConverter.convertTypeToJava(args1[i])
112: .compareTo(
113: TypeConverter
114: .convertTypeToJava(args2[i]));
115: if (result != 0) {
116: return result;
117: }
118: }
119: } catch (Throwable e) {
120: throw new WrappedRuntimeException(e);
121: }
122: java.lang.System.err.println(m1.getName());
123: java.lang.System.err.println(m2.getName());
124: throw new Error("should be unreachable");
125: }
126:
127: /**
128: * Compares two prefixed methods. Assumes the the prefixed methods looks like this: "somePrefix SEP methodName SEP"
129: *
130: * @param m1
131: * @param m2
132: * @return int
133: */
134: private int comparePrefixed(final Method m1, final Method m2) {
135: try {
136: if (m1.equals(m2)) {
137: return 0;
138: }
139:
140: // compare only the original method names, i.e. remove the prefix and suffix
141: final String[] m1Tokens = Strings.splitString(m1.getName(),
142: TransformationConstants.DELIMITER);
143: final String[] m2Tokens = Strings.splitString(m2.getName(),
144: TransformationConstants.DELIMITER);
145: final String m1Name = m1Tokens[1];
146: final String m2Name = m2Tokens[1];
147: if (!m1Name.equals(m2Name)) {
148: return m1Name.compareTo(m2Name);
149: }
150: final Class[] args1 = m1.getParameterTypes();
151: final Class[] args2 = m2.getParameterTypes();
152: if (args1.length < args2.length) {
153: return -1;
154: }
155: if (args1.length > args2.length) {
156: return 1;
157: }
158: if (args1.length == 0) {
159: return 0;
160: }
161: for (int i = 0; i < args1.length; i++) {
162: //handles array types - AW-104
163: int result = TypeConverter.convertTypeToJava(args1[i])
164: .compareTo(
165: TypeConverter
166: .convertTypeToJava(args2[i]));
167: if (result != 0) {
168: return result;
169: }
170: }
171: } catch (Throwable e) {
172: throw new WrappedRuntimeException(e);
173: }
174: java.lang.System.err.println(m1.getName());
175: java.lang.System.err.println(m2.getName());
176: throw new Error("should be unreachable");
177: }
178:
179: /**
180: * Compares two methods meta-data.
181: *
182: * @param m1
183: * @param m2
184: * @return int
185: */
186: private int compareMethodInfo(final MethodInfo m1,
187: final MethodInfo m2) {
188: try {
189: if (m1.equals(m2)) {
190: return 0;
191: }
192: final String m1Name = m1.getName();
193: final String m2Name = m2.getName();
194: if (!m1Name.equals(m2Name)) {
195: return m1Name.compareTo(m2Name);
196: }
197: final ClassInfo[] args1 = m1.getParameterTypes();
198: final ClassInfo[] args2 = m2.getParameterTypes();
199: if (args1.length < args2.length) {
200: return -1;
201: }
202: if (args1.length > args2.length) {
203: return 1;
204: }
205: if (args1.length == 0) {
206: return 0;
207: }
208: for (int i = 0; i < args1.length; i++) {
209: int result;
210: if (args1[i].getName().equals(args2[i].getName())) {
211: result = 0;
212: } else {
213: result = args1[i].getName().compareTo(
214: args2[i].getName());
215: }
216: if (result != 0) {
217: return result;
218: }
219: }
220: } catch (Throwable e) {
221: throw new WrappedRuntimeException(e);
222: }
223: java.lang.System.err.println(m1.getName());
224: java.lang.System.err.println(m2.getName());
225: throw new Error("should be unreachable");
226: }
227: }
|