View Javadoc
1   package net.sourceforge.jenesis4java.impl.util;
2   
3   /*
4    * #%L
5    * Jenesis 4 Java Code Generator
6    * %%
7    * Copyright (C) 2000 - 2015 jenesis4java
8    * %%
9    * This program is free software: you can redistribute it and/or modify
10   * it under the terms of the GNU Lesser General Public License as
11   * published by the Free Software Foundation, either version 3 of the
12   * License, or (at your option) any later version.
13   * 
14   * This program is distributed in the hope that it will be useful,
15   * but WITHOUT ANY WARRANTY; without even the implied warranty of
16   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   * GNU General Lesser Public License for more details.
18   * 
19   * You should have received a copy of the GNU General Lesser Public
20   * License along with this program.  If not, see
21   * <http://www.gnu.org/licenses/lgpl-3.0.html>.
22   * #L%
23   */
24  
25  /**
26   * Copyright (C) 2008, 2010 Richard van Nieuwenhoven - ritchie [at] gmx [dot] at
27   * Copyright (C) 2000, 2001 Paul Cody Johnston - pcj@inxar.org <br>
28   * This file is part of Jenesis4java. Jenesis4java is free software: you can
29   * redistribute it and/or modify it under the terms of the GNU Lesser General
30   * Public License as published by the Free Software Foundation, either version 3
31   * of the License, or (at your option) any later version.<br>
32   * Jenesis4java is distributed in the hope that it will be useful, but WITHOUT
33   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
34   * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
35   * details.<br>
36   * You should have received a copy of the GNU Lesser General Public License
37   * along with Jenesis4java. If not, see <http://www.gnu.org/licenses/>.
38   */
39  
40  import java.io.Serializable;
41  
42  import net.sourceforge.jenesis4java.ClassDeclaration;
43  import net.sourceforge.jenesis4java.Constructor;
44  import net.sourceforge.jenesis4java.Field;
45  import net.sourceforge.jenesis4java.Interface;
46  import net.sourceforge.jenesis4java.Member;
47  import net.sourceforge.jenesis4java.Method;
48  import net.sourceforge.jenesis4java.StaticInitializer;
49  
50  /**
51   * Comparator which is used to sort {@code Members} in a class.
52   */
53  public class MemberComparator implements java.util.Comparator<Member>, Serializable {
54  
55      private static final long serialVersionUID = 2419912166943712377L;
56  
57      private static final int CONSTANT = 3;
58  
59      private static final int INTERFACE = 4;
60  
61      private static final int CONSTRUCTOR = 5;
62  
63      private static final int METHOD = 6;
64  
65      private static final int FIELD = 7;
66  
67      private static final int CLASS = 8;
68  
69      private static final int STATIC_INIT = 9;
70  
71      private static final int OTHER = 10;
72  
73      private static final int EQUAL = 0;
74  
75      private static final int LESS = -1;
76  
77      private static final int GREATER = 1;
78  
79      public MemberComparator() {
80      }
81  
82      @Override
83      public int compare(Member o1, Member o2) {
84          // assign an integer for the compared types
85          int i1 = assignInt(o1);
86          int i2 = assignInt(o2);
87  
88          // are they equal?...
89          if (i1 == i2) {
90  
91              // if so, we will fork to the appropriate type
92              // identity comparison method
93              switch (i1) {
94                  case CLASS:
95                      return compareClasses((ClassDeclaration) o1, (ClassDeclaration) o2);
96                  case METHOD:
97                      return compareMethods((Method) o1, (Method) o2);
98                  case FIELD:
99                      return compareFields((Field) o1, (Field) o2);
100                 case CONSTRUCTOR:
101                     return compareConstructors((Constructor) o1, (Constructor) o2);
102                 case INTERFACE:
103                     return compareInterfaces((Interface) o1, (Interface) o2);
104                 default:
105                     return MemberComparator.EQUAL;
106             }
107 
108             // the types are not the same,
109             // and therefore we can compare directly
110         } else {
111             return i1 < i2 ? MemberComparator.LESS : MemberComparator.GREATER;
112         }
113     }
114 
115     private int assignInt(Object o) {
116         if (o instanceof Interface) {
117             return MemberComparator.INTERFACE;
118         } else if (o instanceof Constructor) {
119             return MemberComparator.CONSTRUCTOR;
120         } else if (o instanceof Method) {
121             return MemberComparator.METHOD;
122         } else if (o instanceof Field) {
123             // Special case. See if it's static and final (a
124             // constant).
125             Field f = (Field) o;
126             return f.isStatic() && f.isFinal() ? MemberComparator.CONSTANT : MemberComparator.FIELD;
127         } else if (o instanceof ClassDeclaration) {
128             return MemberComparator.CLASS;
129         } else if (o instanceof StaticInitializer) {
130             return MemberComparator.STATIC_INIT;
131         } else {
132             return MemberComparator.OTHER;
133         }
134     }
135 
136     /**
137      * utility method to compare boolean state. If they are different, the first
138      * boolean arg (o1) is deemed GREATER if it is the true one.
139      */
140     private int compareBooleans(boolean b1, boolean b2) {
141         // if they are different, return the comparison, otw equal
142         if (b1 ^ b2) {
143             return b1 ? MemberComparator.GREATER : MemberComparator.LESS;
144         } else {
145             return MemberComparator.EQUAL;
146         }
147     }
148 
149     private int compareClasses(ClassDeclaration o1, ClassDeclaration o2) {
150         // compare abstract state
151         int x = compareBooleans(o1.isAbstract(), o2.isAbstract());
152         if (x != MemberComparator.EQUAL) {
153             return x;
154         }
155 
156         return compareMembers(o1, o2);
157     }
158 
159     private int compareConstructors(Constructor o1, Constructor o2) {
160         // compare access levels
161         int x = compareInts(o1.getAccess().ordinal(), o2.getAccess().ordinal());
162         if (x != MemberComparator.EQUAL) {
163             return x;
164         }
165 
166         // ctors have same acces, same # of ctors. We could continue
167         // and compare the arguments, but naw...
168         return x;
169     }
170 
171     private int compareFields(Field o1, Field o2) {
172         return compareMembers(o1, o2);
173     }
174 
175     private int compareInterfaces(Interface o1, Interface o2) {
176         // compare name state
177         int x = compareStrings(o1.getName(), o2.getName());
178         if (x != MemberComparator.EQUAL) {
179             return x;
180         }
181 
182         // pretty damn close enough
183         return x;
184     }
185 
186     /**
187      * utility method to compare integer state. If they are different, the they
188      * are compared with GREATER deemed to the larger number.
189      */
190     private int compareInts(int i1, int i2) {
191         if (i1 == i2) {
192             return MemberComparator.EQUAL;
193         } else {
194             return i1 < i2 ? MemberComparator.LESS : MemberComparator.GREATER;
195         }
196     }
197 
198     private int compareMembers(Member o1, Member o2) {
199         // compare access levels
200         int x = compareInts(o1.getAccess().ordinal(), o2.getAccess().ordinal());
201         if (x != MemberComparator.EQUAL) {
202             return x;
203         }
204 
205         // compare static state
206         x = compareBooleans(o1.isStatic(), o2.isStatic());
207         if (x != MemberComparator.EQUAL) {
208             return x;
209         }
210 
211         // compare final state
212         x = compareBooleans(o1.isFinal(), o2.isFinal());
213         if (x != MemberComparator.EQUAL) {
214             return x;
215         }
216 
217         // compare name state
218         x = compareStrings(o1.getName(), o2.getName());
219         if (x != MemberComparator.EQUAL) {
220             return x;
221         }
222 
223         // pretty damn close enough
224         return x;
225     }
226 
227     private int compareMethods(Method o1, Method o2) {
228         return compareMembers(o1, o2);
229     }
230 
231     /**
232      * utility method to compare strings. uses jdk1.2's compareTo method. 'does
233      * s1 compared to s2', not the other way around.
234      */
235     private int compareStrings(String s1, String s2) {
236         // compare strings
237         return s1.compareTo(s2);
238     }
239 }