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.validator.bean.simple;
23
24 import com.google.common.base.Preconditions;
25 import org.apache.commons.beanutils.ConversionException;
26 import org.apache.commons.collections4.CollectionUtils;
27 import org.apache.commons.lang3.ObjectUtils;
28 import org.apache.commons.logging.Log;
29 import org.apache.commons.logging.LogFactory;
30 import org.nuiton.util.beans.BeanUtil;
31 import org.nuiton.validator.NuitonValidator;
32 import org.nuiton.validator.NuitonValidatorFactory;
33 import org.nuiton.validator.NuitonValidatorModel;
34 import org.nuiton.validator.NuitonValidatorProvider;
35 import org.nuiton.validator.NuitonValidatorResult;
36 import org.nuiton.validator.NuitonValidatorScope;
37 import org.nuiton.validator.bean.AbstractNuitonValidatorContext;
38 import org.nuiton.validator.bean.AbstractValidator;
39
40 import java.beans.PropertyChangeListener;
41 import java.util.List;
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60 public class SimpleBeanValidator<O> extends AbstractValidator<O> {
61
62
63
64
65
66
67
68 public static final String BEAN_PROPERTY = "bean";
69
70
71 private static final Log log = LogFactory.getLog(SimpleBeanValidator.class);
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86 public static <O> SimpleBeanValidator<O> newValidator(
87 Class<O> type,
88 String context,
89 NuitonValidatorScope... scopes) throws NullPointerException {
90
91
92
93 String providerName = NuitonValidatorFactory.getDefaultProviderName();
94
95
96 SimpleBeanValidator<O> beanValidator = newValidator(providerName,
97 type,
98 context,
99 scopes
100 );
101 return beanValidator;
102 }
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119 public static <O> SimpleBeanValidator<O> newValidator(
120 String providerName,
121 Class<O> type,
122 String context,
123 NuitonValidatorScope... scopes) throws NullPointerException {
124
125 Preconditions.checkNotNull(type,
126 "type parameter can not be null.");
127
128
129 NuitonValidatorProvider provider =
130 NuitonValidatorFactory.getProvider(providerName);
131
132 Preconditions.checkState(
133 provider != null,
134 "Could not find provider with name " + providerName);
135
136
137 SimpleBeanValidator<O> validator = new SimpleBeanValidator<O>(
138 provider, type, context, scopes);
139
140 return validator;
141 }
142
143
144
145
146
147
148 protected final NuitonValidatorContext<O> context;
149
150
151
152
153
154
155 protected SimpleBeanValidator<?> parentValidator;
156
157 public SimpleBeanValidator(NuitonValidatorProvider validatorProvider,
158 Class<O> beanClass,
159 String context) {
160
161 this(validatorProvider, beanClass,
162 context,
163 NuitonValidatorScope.values()
164 );
165 }
166
167 public SimpleBeanValidator(NuitonValidatorProvider validatorProvider,
168 Class<O> beanClass,
169 String context,
170 NuitonValidatorScope... scopes) {
171
172 super(validatorProvider, beanClass);
173
174 this.context = new NuitonValidatorContext<O>();
175
176
177 rebuildDelegateValidator(beanClass, context, scopes);
178
179
180 firePropertyChange(CONTEXT_PROPERTY,
181 null,
182 context
183 );
184
185
186 firePropertyChange(SCOPES_PROPERTY,
187 null,
188 scopes
189 );
190 }
191
192
193
194
195
196
197
198 public O getBean() {
199 return context.getBean();
200 }
201
202
203
204
205
206
207
208
209
210
211 public void setBean(O bean) {
212 O oldBean = getBean();
213 if (log.isDebugEnabled()) {
214 log.debug(this + " : " + bean);
215 }
216
217 if (oldBean != null) {
218 try {
219 BeanUtil.removePropertyChangeListener(l, oldBean);
220 } catch (Exception eee) {
221 if (log.isInfoEnabled()) {
222 log.info("Can't unregister as listener for bean " + oldBean.getClass() +
223 " for reason " + eee.getMessage(), eee);
224 }
225 }
226 }
227 context.setBean(bean);
228
229 if (bean == null) {
230
231
232
233 mergeMessages(null);
234
235 } else {
236 try {
237
238 BeanUtil.addPropertyChangeListener(l, bean);
239 } catch (Exception eee) {
240 if (log.isInfoEnabled()) {
241 log.info("Can't register as listener for bean " + bean.getClass() +
242 " for reason " + eee.getMessage(), eee);
243 }
244 }
245 validate();
246 }
247 setChanged(false);
248 setValid(context.isValid());
249 firePropertyChange(BEAN_PROPERTY, oldBean, bean);
250 }
251
252 public SimpleBeanValidator<?> getParentValidator() {
253 return parentValidator;
254 }
255
256 public void setParentValidator(SimpleBeanValidator<?> parentValidator) {
257 this.parentValidator = parentValidator;
258 }
259
260 @Override
261 public boolean hasFatalErrors() {
262 boolean result = context.hasFatalErrors();
263 return result;
264 }
265
266 @Override
267 public boolean hasErrors() {
268 boolean result = context.hasErrors();
269 return result;
270 }
271
272 @Override
273 public boolean hasWarnings() {
274 boolean result = context.hasWarnings();
275 return result;
276 }
277
278 @Override
279 public boolean hasInfos() {
280 boolean result = context.hasInfos();
281 return result;
282 }
283
284 @Override
285 public boolean isValid(String fieldName) {
286
287
288 boolean result = context.isValid(fieldName);
289 return result;
290 }
291
292 @Override
293 public NuitonValidatorScope getHighestScope(String field) {
294 NuitonValidatorScope scope = context.getHighestScope(field);
295 return scope;
296 }
297
298 @Override
299 public <T> T convert(O bean, String fieldName, String value, Class<T> valueClass) {
300 Preconditions.checkState(
301 ObjectUtils.equals(bean, getBean()),
302 "Can not validate the bean [" + bean +
303 "] which is not the one registred [" + bean +
304 "] in this validator.");
305
306 T convert = convert(fieldName, value, valueClass);
307 return convert;
308 }
309
310 @Override
311 public void doValidate() {
312 validate();
313 setValid(context.isValid());
314 setChanged(true);
315 }
316
317
318
319
320
321
322
323
324
325
326
327
328 public <T> T convert(String fieldName, String value, Class<T> valueClass) {
329 T convert = null;
330
331 try {
332 convert = context.convert(fieldName, value, valueClass);
333 } catch (ConversionException e) {
334
335 validate();
336 }
337 return convert;
338 }
339
340 public void addSimpleBeanValidatorListener(SimpleBeanValidatorListener listener) {
341 listenerList.add(SimpleBeanValidatorListener.class, listener);
342 }
343
344 public void removeSimpleBeanValidatorListener(SimpleBeanValidatorListener listener) {
345 listenerList.remove(SimpleBeanValidatorListener.class, listener);
346 }
347
348 public SimpleBeanValidatorListener[] getSimpleBeanValidatorListeners() {
349 return listenerList.getListeners(SimpleBeanValidatorListener.class);
350 }
351
352 @Override
353 protected void doValidate(O bean) {
354
355 Preconditions.checkState(
356 ObjectUtils.equals(bean, getBean()),
357 "Can not validate the bean [" + bean +
358 "] which is not the one registred [" + bean +
359 "] in this validator.");
360
361 doValidate();
362 }
363
364 @Override
365 protected NuitonValidator<O> getDelegate() {
366 return context.getValidator();
367 }
368
369 @Override
370 protected void rebuildDelegateValidator(Class<O> beanType,
371 String context,
372 NuitonValidatorScope... scopes) {
373
374
375
376
377
378
379
380 if (getBean() != null) {
381 setBean(null);
382 }
383
384 if (scopes == null || scopes.length == 0) {
385 scopes = NuitonValidatorScope.values();
386 }
387
388
389 NuitonValidatorModel<O> validatorModel = validatorProvider.getModel(beanType,
390 context,
391 scopes
392 );
393
394
395 NuitonValidator<O> delegate = validatorProvider.newValidator(validatorModel);
396 this.context.setValidator(delegate);
397 }
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412 protected void validate() {
413
414
415
416 if (isCanValidate()) {
417
418 NuitonValidatorResult result = context.validate();
419
420 mergeMessages(result);
421
422 if (parentValidator != null) {
423
424
425 boolean wasModified = parentValidator.isChanged();
426 parentValidator.doValidate();
427 if (!wasModified) {
428
429 parentValidator.setChanged(false);
430 }
431 }
432 }
433 }
434
435 protected void fireFieldChanged(SimpleBeanValidatorEvent evt) {
436
437 for (SimpleBeanValidatorListener listener :
438 listenerList.getListeners(SimpleBeanValidatorListener.class)) {
439 listener.onFieldChanged(evt);
440 }
441 }
442
443 protected void mergeMessages(NuitonValidatorResult newMessages) {
444
445 List<SimpleBeanValidatorEvent> events = context.mergeMessages(this,
446 newMessages);
447
448 if (CollectionUtils.isNotEmpty(events)) {
449
450
451 for (SimpleBeanValidatorEvent event : events) {
452 fireFieldChanged(event);
453 }
454 }
455 }
456
457 protected static class NuitonValidatorContext<O> extends AbstractNuitonValidatorContext<O, SimpleBeanValidator<O>, SimpleBeanValidatorEvent> {
458
459 @Override
460 protected SimpleBeanValidatorEvent createEvent(SimpleBeanValidator<O> source,
461 O bean,
462 String field,
463 NuitonValidatorScope scope,
464 String[] toAdd,
465 String[] toDelete) {
466 SimpleBeanValidatorEvent evt = new SimpleBeanValidatorEvent(
467 source,
468 field,
469 scope,
470 toAdd,
471 toDelete
472 );
473 return evt;
474 }
475 }
476 }