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