1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 package org.nuiton.util.beans;
23
24 import org.apache.commons.lang3.ObjectUtils;
25 import org.apache.commons.logging.Log;
26 import org.apache.commons.logging.LogFactory;
27
28 import java.beans.PropertyChangeEvent;
29 import java.beans.PropertyChangeListener;
30 import java.util.*;
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53 public class BeanMonitor {
54
55
56 private static final Log log = LogFactory.getLog(BeanMonitor.class);
57
58
59 protected final List<String> propertyNames;
60
61
62 protected boolean excludeMode;
63
64
65 protected final Map<String, PropertyDiff> propertyDiffs;
66
67
68
69
70
71 protected final PropertyChangeListener listener;
72
73
74 protected Object bean;
75
76
77
78
79
80
81 public BeanMonitor(String... propertyNames) {
82 this(false, propertyNames);
83 }
84
85 public BeanMonitor(boolean exclude, String... propertyNames) {
86 this.excludeMode = exclude;
87 this.propertyNames = new ArrayList<String>(Arrays.asList(propertyNames));
88 propertyDiffs = new LinkedHashMap<String, PropertyDiff>();
89
90 listener = new PropertyChangeListener() {
91 @Override
92 public void propertyChange(PropertyChangeEvent evt) {
93 String propertyName = evt.getPropertyName();
94 if (excludeMode && BeanMonitor.this.propertyNames.contains(propertyName)
95 || !excludeMode && !BeanMonitor.this.propertyNames.contains(propertyName)) {
96 return;
97 }
98
99
100
101 Object newValue = evt.getNewValue();
102 Object oldValue = evt.getOldValue();
103
104 PropertyDiff propertyDiff;
105
106 if (propertyDiffs.containsKey(propertyName)) {
107
108
109 propertyDiff = propertyDiffs.get(propertyName);
110
111
112 propertyDiff.setTargetValue(newValue);
113
114
115 Object originalValue = propertyDiff.getSourceValue();
116
117 if (Objects.equals(originalValue, newValue)) {
118
119
120
121 propertyDiffs.remove(propertyName);
122 }
123 } else {
124
125
126 if (ObjectUtils.notEqual(newValue, oldValue)) {
127 propertyDiff = new PropertyDiff(
128 propertyName,
129 oldValue,
130 propertyName,
131 newValue,
132 null
133 );
134
135
136 propertyDiffs.put(propertyName, propertyDiff);
137 }
138
139 }
140 }
141 };
142 }
143
144
145
146
147
148
149 public Object getBean() {
150 return bean;
151 }
152
153
154
155
156
157
158
159
160
161 public boolean wasModified() {
162 return !propertyDiffs.isEmpty();
163 }
164
165
166
167
168
169
170
171
172 public String[] getModifiedProperties() {
173 Set<String> propertyNames = propertyDiffs.keySet();
174 return propertyNames.toArray(new String[propertyNames.size()]);
175 }
176
177
178
179
180
181
182 public Map<String, Object> getOriginalValues() {
183
184
185 Map<String, Object> map = new TreeMap<String, Object>();
186 for (PropertyDiff propertyDiff : propertyDiffs.values()) {
187 map.put(propertyDiff.getSourceProperty(),
188 propertyDiff.getSourceValue());
189 }
190 return map;
191 }
192
193
194
195
196
197
198
199 public PropertyDiff[] getPropertyDiffs() {
200 Collection<PropertyDiff> values = propertyDiffs.values();
201 return values.toArray(new PropertyDiff[values.size()]);
202 }
203
204
205
206
207
208
209
210
211
212
213
214
215 public void setBean(Object bean) {
216 Object oldBean = this.bean;
217 this.bean = bean;
218
219
220 clearModified();
221
222 if (oldBean != null) {
223
224
225 try {
226 BeanUtil.removePropertyChangeListener(listener, oldBean);
227 } catch (Exception eee) {
228 log.error(String.format("Could remove the PropertychangeListener %1$s from object %2$s for following reason \\: %3$s",
229 listener, oldBean, eee.getMessage()));
230 }
231 }
232 if (bean != null) {
233
234
235 try {
236 BeanUtil.addPropertyChangeListener(listener, bean);
237 } catch (Exception eee) {
238 log.error(String.format("Could not add the PropertychangeListener %1$s on object %2$s for following reason \\: %3$s",
239 listener, bean, eee.getMessage()));
240 }
241 }
242 }
243
244
245 public void clearModified() {
246 propertyDiffs.clear();
247 }
248
249
250
251
252
253
254
255
256
257
258
259 public void setProperties(String... properties) {
260 propertyNames.clear();
261 propertyNames.addAll(Arrays.asList(properties));
262 clearModified();
263 }
264
265 public boolean isExcludeMode() {
266 return excludeMode;
267 }
268
269 public void setExcludeMode(boolean excludeMode) {
270 this.excludeMode = excludeMode;
271 clearModified();
272 }
273 }