2009/05/20 - Apache Shale has been retired.
For more information, please explore the Attic.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.shale.usecases.rolodex;
19
20 import java.beans.BeanInfo;
21 import java.beans.Introspector;
22 import java.beans.PropertyDescriptor;
23 import java.lang.reflect.InvocationTargetException;
24 import java.util.ArrayList;
25 import java.util.Comparator;
26 import java.util.Iterator;
27 import java.util.List;
28 import java.util.Map;
29 import java.util.StringTokenizer;
30 import javax.faces.FacesException;
31 import javax.faces.el.PropertyNotFoundException;
32 import org.apache.commons.logging.Log;
33 import org.apache.commons.logging.LogFactory;
34
35 /***
36 * <p>Generic comparator that uses a list of property names to compare
37 * the state of two objects using the reflection API. The property names
38 * are passed via a comma delimited. The collating sequence is determined
39 * by the <code>sortAcending</code> attribute.</p>
40 */
41 public class GenericComparator implements Comparator {
42
43 /***
44 * <p>Common logger utility.</p>
45 */
46 public static Log log;
47 static {
48 log = LogFactory.getLog(GenericComparator.class);
49 }
50
51 /***
52 * <p>Determines the collating sequence. A <code>true</code> value
53 * will sort acending; otherwise, the list will be sorted in descending
54 * order.</p>
55 */
56 private boolean sortAscending = true;
57
58 /***
59 * <p>Holds an array of property names in the target object that
60 * will be use to compare the two objects.
61 * </p>
62 */
63 protected List sortBy;
64
65 /***
66 * <p>Returns <code>true</code> if the collection should be sorted ascending by
67 * the <code>sortBy</code> properties list.<p>
68 */
69 public boolean getSortAscending() {
70 return sortAscending;
71 }
72
73 /***
74 * <p>Sets the sequence the collection should be sorted. A <code>true</code>
75 * will result in sort ascending.</p>
76 */
77 public void setSortAscending(boolean value) {
78 sortAscending = value;
79 }
80
81 /***
82 * <p>Passed a comma delimited list of property names to compare two object by.<p>
83 */
84 public void setSortBy(String properties) {
85 StringTokenizer tokenizer = new StringTokenizer(properties, ",");
86 sortBy = new ArrayList();
87 while (tokenizer.hasMoreTokens()) {
88 String token = tokenizer.nextToken().trim();
89 sortBy.add(token);
90 }
91
92 }
93
94 /***
95 * <p>Returns a comma delimited list of property names used to compare
96 * two objects.</p>
97 */
98 public String getSortBy() {
99 StringBuffer tmp = new StringBuffer();
100 if (sortBy != null) {
101 Iterator li = sortBy.iterator();
102 while (li.hasNext()) {
103 if (tmp.length() > 0) {
104 tmp.append(", ");
105 }
106 tmp.append(li.next());
107 }
108 }
109
110 return tmp.toString();
111 }
112
113 /***
114 * <p>Compares the property names in the <code>sortBy</code> list with
115 * the target sortable objects. The collating sequence is determined
116 * by the <code>sortAcending</code> attribute.
117 * </p>
118 *
119 * @param o1 -
120 * target object 1
121 * @param o2 -
122 * target object 2
123 * @return - integer value representing the comparison of the two objects
124 * key properties.
125 */
126 public int compare(Object o1, Object o2) {
127 Iterator it = sortBy.iterator();
128 int result = 0;
129 while (result == 0 && it.hasNext()) {
130 String nextProperty = (String) it.next();
131
132 Object col1 = null;
133 Object col2 = null;
134
135 col1 = value(o1, nextProperty);
136 col2 = value(o2, nextProperty);
137
138 if ((col1 == null) && (col2 == null))
139 result = 0;
140 else if ((col1 == null) && (col2 != null))
141 result = -1;
142 else if ((col2 == null) && (col1 != null))
143 result = 1;
144 else if ((col1 instanceof Comparable)
145 && (col2 instanceof Comparable))
146 result = ((Comparable) col1).compareTo(col2);
147 else {
148
149 result = ((Comparable) col1.toString()).compareTo(col2
150 .toString());
151 }
152
153 col1 = null;
154 col2 = null;
155
156 }
157 return (sortAscending ? 1 : -1) * result;
158 }
159
160
161
162
163
164 /***
165 * <p>Return the specified property value from the specified object,
166 * if possible.</p>
167 *
168 * @param base Base object from which to retrieve a property
169 * @param name Name of the property to be retrieved
170 */
171 private Object value(Object base, String name) {
172
173 if (base instanceof Map) {
174 return ((Map) base).get(name);
175 }
176 try {
177 BeanInfo info = Introspector.getBeanInfo(base.getClass());
178 PropertyDescriptor[] descriptors = info.getPropertyDescriptors();
179 for (int i = 0; i < descriptors.length; i++) {
180 if (name.equals(descriptors[i].getName())) {
181 return descriptors[i].getReadMethod().invoke(base, null);
182 }
183 }
184 throw new PropertyNotFoundException(name);
185 } catch (RuntimeException e) {
186 throw e;
187 } catch (Exception e) {
188 throw new FacesException(e);
189 }
190
191 }
192
193
194
195 }