1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.rice.krad.util;
17
18 import org.apache.commons.beanutils.PropertyUtils;
19 import org.apache.commons.collections.comparators.ComparableComparator;
20 import org.kuali.rice.core.api.exception.KualiException;
21 import org.kuali.rice.core.api.util.type.TypeUtils;
22
23 import java.beans.PropertyDescriptor;
24 import java.io.Serializable;
25 import java.lang.reflect.InvocationTargetException;
26 import java.util.Collections;
27 import java.util.Comparator;
28 import java.util.Iterator;
29 import java.util.List;
30
31
32
33
34
35
36 public class BeanPropertyComparator implements Comparator, Serializable {
37 private static final long serialVersionUID = -2675700473766186018L;
38 boolean ignoreCase;
39 private List propertyNames;
40 private Comparator stringComparator;
41 private Comparator booleanComparator;
42 private Comparator genericComparator;
43
44
45
46
47
48
49
50
51
52
53 public BeanPropertyComparator(List propertyNames) {
54 this(propertyNames, true);
55 }
56
57
58
59
60
61
62
63
64
65
66 public BeanPropertyComparator(List propertyNames, boolean ignoreCase) {
67 if (propertyNames == null) {
68 throw new IllegalArgumentException("invalid (null) propertyNames list");
69 }
70 if (propertyNames.size() == 0) {
71 throw new IllegalArgumentException("invalid (empty) propertyNames list");
72 }
73 this.propertyNames = Collections.unmodifiableList(propertyNames);
74 this.ignoreCase = ignoreCase;
75
76 if (ignoreCase) {
77 this.stringComparator = String.CASE_INSENSITIVE_ORDER;
78 }
79 else {
80 this.stringComparator = ComparableComparator.getInstance();
81 }
82 this.booleanComparator = new Comparator() {
83 public int compare(Object o1, Object o2) {
84 int compared = 0;
85
86 Boolean b1 = (Boolean) o1;
87 Boolean b2 = (Boolean) o2;
88
89 if (!b1.equals(b2)) {
90 if (b1.equals(Boolean.FALSE)) {
91 compared = -1;
92 }
93 else {
94 compared = 1;
95 }
96 }
97
98 return compared;
99 }
100
101 };
102 this.genericComparator = ComparableComparator.getInstance();
103 }
104
105
106
107
108
109
110
111
112
113 public int compare(Object o1, Object o2) {
114 int compared = 0;
115
116 try {
117 for (Iterator i = propertyNames.iterator(); (compared == 0) && i.hasNext();) {
118 String currentProperty = i.next().toString();
119
120
121 Comparator currentComparator = null;
122 try {
123 PropertyDescriptor propertyDescriptor = PropertyUtils.getPropertyDescriptor(o1, currentProperty);
124 Class propertyClass = propertyDescriptor.getPropertyType();
125 if (propertyClass.equals(String.class)) {
126 currentComparator = this.stringComparator;
127 }
128 else if (TypeUtils.isBooleanClass(propertyClass)) {
129 currentComparator = this.booleanComparator;
130 }
131 else {
132 currentComparator = this.genericComparator;
133 }
134 }
135 catch (NullPointerException e) {
136 throw new BeanComparisonException("unable to find property '" + o1.getClass().getName() + "." + currentProperty + "'", e);
137 }
138
139
140 Object value1 = PropertyUtils.getProperty(o1, currentProperty);
141 Object value2 = PropertyUtils.getProperty(o2, currentProperty);
142
143 if ( value1 == null && value2 == null)
144 return 0;
145 else if ( value1 == null)
146 return -1;
147 else if ( value2 == null )
148 return 1;
149
150 compared = currentComparator.compare(value1, value2);
151 }
152 }
153 catch (IllegalAccessException e) {
154 throw new BeanComparisonException("unable to compare property values", e);
155 }
156 catch (NoSuchMethodException e) {
157 throw new BeanComparisonException("unable to compare property values", e);
158 }
159 catch (InvocationTargetException e) {
160 throw new BeanComparisonException("unable to compare property values", e);
161 }
162
163 return compared;
164 }
165
166 public static class BeanComparisonException extends KualiException {
167 private static final long serialVersionUID = 2622379680100640029L;
168
169
170
171
172
173 public BeanComparisonException(String message, Throwable t) {
174 super(message, t);
175 }
176 }
177 }