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;
9   
10  import org.codehaus.aspectwerkz.exception.WrappedRuntimeException;
11  import org.codehaus.aspectwerkz.reflect.ClassInfo;
12  import org.codehaus.aspectwerkz.reflect.MethodInfo;
13  import org.codehaus.aspectwerkz.reflect.TypeConverter;
14  import org.codehaus.aspectwerkz.transform.TransformationUtil;
15  import org.codehaus.aspectwerkz.transform.TransformationConstants;
16  import org.codehaus.aspectwerkz.transform.TransformationConstants;
17  import org.codehaus.aspectwerkz.util.Strings;
18  
19  import java.lang.reflect.Method;
20  import java.util.Comparator;
21  
22  /***
23   * Compares Methods. To be used when sorting methods.
24   * 
25   * @author <a href="mailto:jboner@codehaus.org">Jonas Bonér </a>
26   */
27  public final class MethodComparator implements java.util.Comparator {
28      /***
29       * Compares normal method names.
30       */
31      public static final int NORMAL_METHOD = 0;
32  
33      /***
34       * Compares prefixed method names.
35       */
36      public static final int PREFIXED_METHOD = 1;
37  
38      /***
39       * Compares method meta-data.
40       */
41      public static final int METHOD_META_DATA = 2;
42  
43      /***
44       * Defines the type of comparator.
45       */
46      private final int m_type;
47  
48      /***
49       * Sets the type.
50       * 
51       * @param type the type
52       */
53      private MethodComparator(final int type) {
54          m_type = type;
55      }
56  
57      /***
58       * Returns the comparator instance.
59       * 
60       * @param type the type of the method comparison
61       * @return the instance
62       */
63      public static Comparator getInstance(final int type) {
64          return new MethodComparator(type);
65      }
66  
67      /***
68       * Compares two objects.
69       * 
70       * @param o1
71       * @param o2
72       * @return int
73       */
74      public int compare(final Object o1, final Object o2) {
75          switch (m_type) {
76              case NORMAL_METHOD:
77                  return compareNormal((Method) o1, (Method) o2);
78              case PREFIXED_METHOD:
79                  return comparePrefixed((Method) o1, (Method) o2);
80              case METHOD_META_DATA:
81                  return compareMethodInfo((MethodInfo) o1, (MethodInfo) o2);
82              default:
83                  throw new RuntimeException("invalid method comparison type");
84          }
85      }
86  
87      /***
88       * Compares two methods.
89       * 
90       * @param m1
91       * @param m2
92       * @return int
93       */
94      private int compareNormal(final Method m1, final Method m2) {
95          try {
96              if (m1.equals(m2)) {
97                  return 0;
98              }
99              final String m1Name = m1.getName();
100             final String m2Name = m2.getName();
101             if (!m1Name.equals(m2Name)) {
102                 return m1Name.compareTo(m2Name);
103             }
104             final Class[] args1 = m1.getParameterTypes();
105             final Class[] args2 = m2.getParameterTypes();
106             if (args1.length < args2.length) {
107                 return -1;
108             }
109             if (args1.length > args2.length) {
110                 return 1;
111             }
112             if (args1.length == 0) {
113                 return 0;
114             }
115             for (int i = 0; i < args1.length; i++) {
116                 //handles array types - AW-104
117                 int result = TypeConverter.convertTypeToJava(args1[i]).compareTo(
118                     TypeConverter.convertTypeToJava(args2[i]));
119                 if (result != 0) {
120                     return result;
121                 }
122             }
123         } catch (Throwable e) {
124             throw new WrappedRuntimeException(e);
125         }
126         java.lang.System.err.println(m1.getName());
127         java.lang.System.err.println(m2.getName());
128         throw new Error("should be unreachable");
129     }
130 
131     /***
132      * Compares two prefixed methods. Assumes the the prefixed methods looks like this: "somePrefix SEP methodName SEP"
133      * 
134      * @param m1
135      * @param m2
136      * @return int
137      */
138     private int comparePrefixed(final Method m1, final Method m2) {
139         try {
140             if (m1.equals(m2)) {
141                 return 0;
142             }
143 
144             // compare only the original method names, i.e. remove the prefix and suffix
145             final String[] m1Tokens = Strings.splitString(m1.getName(), TransformationConstants.DELIMITER);
146             final String[] m2Tokens = Strings.splitString(m2.getName(), TransformationConstants.DELIMITER);
147             final String m1Name = m1Tokens[1];
148             final String m2Name = m2Tokens[1];
149             if (!m1Name.equals(m2Name)) {
150                 return m1Name.compareTo(m2Name);
151             }
152             final Class[] args1 = m1.getParameterTypes();
153             final Class[] args2 = m2.getParameterTypes();
154             if (args1.length < args2.length) {
155                 return -1;
156             }
157             if (args1.length > args2.length) {
158                 return 1;
159             }
160             if (args1.length == 0) {
161                 return 0;
162             }
163             for (int i = 0; i < args1.length; i++) {
164                 //handles array types - AW-104
165                 int result = TypeConverter.convertTypeToJava(args1[i]).compareTo(
166                     TypeConverter.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, final MethodInfo m2) {
187         try {
188             if (m1.equals(m2)) {
189                 return 0;
190             }
191             final String m1Name = m1.getName();
192             final String m2Name = m2.getName();
193             if (!m1Name.equals(m2Name)) {
194                 return m1Name.compareTo(m2Name);
195             }
196             final ClassInfo[] args1 = m1.getParameterTypes();
197             final ClassInfo[] args2 = m2.getParameterTypes();
198             if (args1.length < args2.length) {
199                 return -1;
200             }
201             if (args1.length > args2.length) {
202                 return 1;
203             }
204             if (args1.length == 0) {
205                 return 0;
206             }
207             for (int i = 0; i < args1.length; i++) {
208                 if (args1[i].getName().equals(args2[i].getName())) {
209                     return 0;
210                 }
211             }
212         } catch (Throwable e) {
213             throw new WrappedRuntimeException(e);
214         }
215         java.lang.System.err.println(m1.getName());
216         java.lang.System.err.println(m2.getName());
217         throw new Error("should be unreachable");
218     }
219 }