1 package org.andromda.utils.beans.comparators;
2
3 import java.io.InputStream;
4 import java.io.Serializable;
5 import java.lang.reflect.InvocationTargetException;
6 import java.net.URL;
7 import java.util.Comparator;
8 import java.util.Properties;
9
10 import org.andromda.core.common.ClassUtils;
11 import org.andromda.core.common.ExceptionUtils;
12 import org.andromda.core.common.Introspector;
13 import org.andromda.utils.beans.BeanSorter;
14 import org.andromda.utils.beans.SortCriteria;
15 import org.apache.commons.lang.StringUtils;
16
17
18
19
20
21
22
23
24
25 public class BeanComparator
26 implements Comparator,
27 Serializable
28 {
29 private static final long serialVersionUID = 34L;
30
31
32
33
34 private static final Properties comparators = new Properties();
35
36 static
37 {
38 InputStream stream = null;
39 try
40 {
41 final String comparatorsFile = "/Comparators.properties";
42 final URL comparatorsUri = BeanComparator.class.getResource(comparatorsFile);
43 if (comparatorsUri == null)
44 {
45 throw new BeanComparatorException("The comparators resource '" + comparatorsFile +
46 " could not be loaded");
47 }
48 stream = comparatorsUri.openStream();
49 comparators.load(stream);
50 }
51 catch (final Throwable throwable)
52 {
53 throw new RuntimeException(throwable);
54 }
55 finally
56 {
57 if (stream != null) try {stream.close();} catch (Exception ex) {}
58 stream = null;
59 }
60 }
61
62 private Comparator comparator = null;
63 private SortCriteria sortCriteria;
64
65
66
67
68 public BeanComparator(SortCriteria sortCriteria)
69 {
70 ExceptionUtils.checkNull(
71 "sortCriteria",
72 sortCriteria);
73 this.sortCriteria = sortCriteria;
74 }
75
76
77
78
79 @Override
80 public int compare(
81 final Object objectA,
82 Object objectB)
83 {
84 ExceptionUtils.checkNull(
85 "objectA",
86 objectA);
87 ExceptionUtils.checkNull(
88 "objectB",
89 objectB);
90
91 try
92 {
93 Object aValue;
94 Object bValue;
95 if (this.sortCriteria.getOrdering().equals(SortCriteria.Ordering.DESCENDING))
96 {
97
98
99 aValue = getProperty(
100 objectB,
101 sortCriteria.getSortBy());
102 bValue = getProperty(
103 objectA,
104 sortCriteria.getSortBy());
105 }
106 else
107 {
108
109 aValue = getProperty(
110 objectA,
111 sortCriteria.getSortBy());
112 bValue = getProperty(
113 objectB,
114 sortCriteria.getSortBy());
115 }
116
117
118 int result = 0;
119
120
121 if (aValue != null || bValue != null)
122 {
123 if (aValue == null)
124 {
125 if (sortCriteria.isNullsFirst())
126 {
127 result = -1;
128 }
129 else
130 {
131 result = 1;
132 }
133 }
134 else if (bValue == null)
135 {
136 if (sortCriteria.isNullsFirst())
137 {
138 result = 1;
139 }
140 else
141 {
142 result = -1;
143 }
144 }
145 else
146 {
147 result = this.getComparator(aValue.getClass()).compare(
148 aValue,
149 bValue);
150 }
151 }
152 return result;
153 }
154 catch (final Throwable throwable)
155 {
156 throw new ComparatorException(throwable);
157 }
158 }
159
160
161
162
163
164
165
166
167
168 private Object getProperty(
169 final Object bean,
170 String propertyName)
171 throws IllegalAccessException, InvocationTargetException, NoSuchMethodException
172 {
173 Object value = null;
174 if (bean != null && StringUtils.isNotBlank(propertyName))
175 {
176 int index = getNestedIndex(propertyName);
177 if (index != -1)
178 {
179 String simpleProp = propertyName.substring(
180 0,
181 index);
182 value = Introspector.instance().getProperty(
183 bean,
184 simpleProp);
185 if (value != null)
186 {
187 if (getNestedIndex(propertyName) != -1)
188 {
189 propertyName = propertyName.substring(
190 index + 1,
191 propertyName.length());
192 value = getProperty(
193 value,
194 propertyName);
195 }
196 }
197 }
198 else
199 {
200 value = Introspector.instance().getProperty(
201 bean,
202 propertyName);
203 }
204 }
205 return value;
206 }
207
208
209
210
211
212
213
214
215 private final int getNestedIndex(final String propertyName)
216 {
217 int index = -1;
218 if (StringUtils.isNotBlank(propertyName))
219 {
220 index = propertyName.indexOf('.');
221 }
222 return index;
223 }
224
225
226
227
228
229
230 private final Comparator getComparator(final Class type)
231 {
232 try
233 {
234 if (this.comparator == null)
235 {
236 final String comparatorName = findComparatorName(type);
237 if (StringUtils.isNotBlank(comparatorName))
238 {
239 this.comparator = (Comparator)ClassUtils.loadClass(comparatorName).newInstance();
240 }
241 else
242 {
243 throw new ComparatorException("No comparator defined for the given type '" + type.getName() + '\'');
244 }
245 }
246 return this.comparator;
247 }
248 catch (final Throwable throwable)
249 {
250 throw new ComparatorException(throwable);
251 }
252 }
253
254 private String findComparatorName(final Class type)
255 {
256 String comparatorName = comparators.getProperty(type.getName());
257 if (StringUtils.isEmpty(comparatorName) && type.getSuperclass() != null)
258 {
259 comparatorName = findComparatorName(type.getSuperclass());
260 }
261 return comparatorName;
262 }
263
264
265
266
267
268 public SortCriteria getSortCriteria()
269 {
270 return this.sortCriteria;
271 }
272
273
274
275
276
277 public void setSortCriteria(final SortCriteria sortCriteria)
278 {
279 ExceptionUtils.checkNull(
280 "sortCriteria",
281 sortCriteria);
282 this.sortCriteria = sortCriteria;
283 }
284 }