View Javadoc

1   /***************************************************************************************
2    * Copyright (c) Jonas BonŽr, Alexandre Vasseur. All rights reserved.                 *
3    * http://aspectwerkz.codehaus.org                                                    *
4    * ---------------------------------------------------------------------------------- *
5    * The software in this package is published under the terms of the LGPL license      *
6    * a copy of which has been included with this distribution in the license.txt file.  *
7    **************************************************************************************/
8   package org.codehaus.aspectwerkz.reflect;
9   
10  import org.codehaus.aspectwerkz.exception.WrappedRuntimeException;
11  import org.codehaus.aspectwerkz.transform.TransformationConstants;
12  import org.codehaus.aspectwerkz.util.Strings;
13  
14  import java.lang.reflect.Method;
15  import java.util.Comparator;
16  
17  /***
18   * Compares Methods. To be used when sorting methods.
19   *
20   * @author <a href="mailto:jboner@codehaus.org">Jonas BonŽr </a>
21   */
22  public final class MethodComparator implements java.util.Comparator {
23      /***
24       * Compares normal method names.
25       */
26      public static final int NORMAL_METHOD = 0;
27  
28      /***
29       * Compares prefixed method names.
30       */
31      public static final int PREFIXED_METHOD = 1;
32  
33      /***
34       * Compares method infos.
35       */
36      public static final int METHOD_INFO = 2;
37  
38      /***
39       * Defines the type of comparator.
40       */
41      private final int m_type;
42  
43      /***
44       * Sets the type.
45       *
46       * @param type the type
47       */
48      private MethodComparator(final int type) {
49          m_type = type;
50      }
51  
52      /***
53       * Returns the comparator instance.
54       *
55       * @param type the type of the method comparison
56       * @return the instance
57       */
58      public static Comparator getInstance(final int type) {
59          return new MethodComparator(type);
60      }
61  
62      /***
63       * Compares two objects.
64       *
65       * @param o1
66       * @param o2
67       * @return int
68       */
69      public int compare(final Object o1, final Object o2) {
70          switch (m_type) {
71              case NORMAL_METHOD:
72                  return compareNormal((Method) o1, (Method) o2);
73              case PREFIXED_METHOD:
74                  return comparePrefixed((Method) o1, (Method) o2);
75              case METHOD_INFO:
76                  return compareMethodInfo((MethodInfo) o1, (MethodInfo) o2);
77              default:
78                  throw new RuntimeException("invalid method comparison type");
79          }
80      }
81  
82      /***
83       * Compares two methods.
84       *
85       * @param m1
86       * @param m2
87       * @return int
88       */
89      private int compareNormal(final Method m1, final Method m2) {
90          try {
91              if (m1.equals(m2)) {
92                  return 0;
93              }
94              final String m1Name = m1.getName();
95              final String m2Name = m2.getName();
96              if (!m1Name.equals(m2Name)) {
97                  return m1Name.compareTo(m2Name);
98              }
99              final Class[] args1 = m1.getParameterTypes();
100             final Class[] args2 = m2.getParameterTypes();
101             if (args1.length < args2.length) {
102                 return -1;
103             }
104             if (args1.length > args2.length) {
105                 return 1;
106             }
107             if (args1.length == 0) {
108                 return 0;
109             }
110             for (int i = 0; i < args1.length; i++) {
111                 //handles array types - AW-104
112                 int result = TypeConverter.convertTypeToJava(args1[i]).compareTo(
113                         TypeConverter.convertTypeToJava(args2[i])
114                 );
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(), TransformationConstants.DELIMITER);
142             final String[] m2Tokens = Strings.splitString(m2.getName(), TransformationConstants.DELIMITER);
143             final String m1Name = m1Tokens[1];
144             final String m2Name = m2Tokens[1];
145             if (!m1Name.equals(m2Name)) {
146                 return m1Name.compareTo(m2Name);
147             }
148             final Class[] args1 = m1.getParameterTypes();
149             final Class[] args2 = m2.getParameterTypes();
150             if (args1.length < args2.length) {
151                 return -1;
152             }
153             if (args1.length > args2.length) {
154                 return 1;
155             }
156             if (args1.length == 0) {
157                 return 0;
158             }
159             for (int i = 0; i < args1.length; i++) {
160                 //handles array types - AW-104
161                 int result = TypeConverter.convertTypeToJava(args1[i]).compareTo(
162                         TypeConverter.convertTypeToJava(args2[i])
163                 );
164                 if (result != 0) {
165                     return result;
166                 }
167             }
168         } catch (Throwable e) {
169             throw new WrappedRuntimeException(e);
170         }
171         java.lang.System.err.println(m1.getName());
172         java.lang.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, final MethodInfo m2) {
184         try {
185             if (m1.equals(m2)) {
186                 return 0;
187             }
188             final String m1Name = m1.getName();
189             final String m2Name = m2.getName();
190             if (!m1Name.equals(m2Name)) {
191                 return m1Name.compareTo(m2Name);
192             }
193             final ClassInfo[] args1 = m1.getParameterTypes();
194             final ClassInfo[] args2 = m2.getParameterTypes();
195             if (args1.length < args2.length) {
196                 return -1;
197             }
198             if (args1.length > args2.length) {
199                 return 1;
200             }
201             if (args1.length == 0) {
202                 return 0;
203             }
204             for (int i = 0; i < args1.length; i++) {
205                 int result;
206                 if (args1[i].getName().equals(args2[i].getName())) {
207                     result = 0;
208                 } else {
209                     result = args1[i].getName().compareTo(args2[i].getName());
210                 }
211                 if (result != 0) {
212                     return result;
213                 }
214             }
215         } catch (Throwable e) {
216             throw new WrappedRuntimeException(e);
217         }
218         java.lang.System.err.println(m1.getName());
219         java.lang.System.err.println(m2.getName());
220         throw new Error("should be unreachable");
221     }
222 }