1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.myfaces.commons.validator;
20
21 import java.util.Comparator;
22
23 import javax.el.ValueExpression;
24 import javax.faces.FacesException;
25 import javax.faces.FactoryFinder;
26 import javax.faces.application.FacesMessage;
27 import javax.faces.component.EditableValueHolder;
28 import javax.faces.component.UIComponent;
29 import javax.faces.component.ValueHolder;
30 import javax.faces.context.FacesContext;
31 import javax.faces.convert.Converter;
32 import javax.faces.convert.ConverterException;
33 import javax.faces.render.RenderKit;
34 import javax.faces.render.RenderKitFactory;
35 import javax.faces.render.Renderer;
36 import javax.faces.validator.ValidatorException;
37
38 import org.apache.myfaces.commons.util.MessageUtils;
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112 public abstract class AbstractCompareToValidator extends ValidatorBase {
113
114
115
116 public static final String VALIDATOR_ID = "org.apache.myfaces.commons.validator.CompareTo";
117
118
119
120
121
122 public static final String COMPARE_TO_MESSAGE_ID = "org.apache.myfaces.commons.validator.CompareTo.INVALID";
123
124 public AbstractCompareToValidator(){
125 super();
126 }
127
128 public static final String OPERATOR_EQUALS = "eq";
129 public static final String OPERATOR_NOT_EQUALS = "ne";
130 public static final String OPERATOR_GREATER_THAN = "gt";
131 public static final String OPERATOR_LESS_THAN = "lt";
132 public static final String OPERATOR_GREATER_THAN_OR_EQUALS = "ge";
133 public static final String OPERATOR_LESS_THAN_OR_EQUALS = "le";
134
135 public static final String OPERATOR_EQUALS_ALT = "==";
136 public static final String OPERATOR_NOT_EQUALS_ALT = "!=";
137 public static final String OPERATOR_GREATER_THAN_ALT = ">";
138 public static final String OPERATOR_LESS_THAN_ALT = "<";
139 public static final String OPERATOR_GREATER_THAN_OR_EQUALS_ALT = ">=";
140 public static final String OPERATOR_LESS_THAN_OR_EQUALS_ALT = "<=";
141
142 public static final String OPERATOR_EQUALS_ALT2 = "=";
143
144 protected String getOperatorForString(String operatorSpecified)
145 {
146 if (OPERATOR_EQUALS.equalsIgnoreCase(operatorSpecified))
147 return OPERATOR_EQUALS;
148 else if (OPERATOR_NOT_EQUALS.equalsIgnoreCase(operatorSpecified))
149 return OPERATOR_NOT_EQUALS;
150 else if (OPERATOR_GREATER_THAN.equalsIgnoreCase(operatorSpecified))
151 return OPERATOR_GREATER_THAN;
152 else if (OPERATOR_LESS_THAN.equalsIgnoreCase(operatorSpecified))
153 return OPERATOR_LESS_THAN;
154 else if (OPERATOR_GREATER_THAN_OR_EQUALS.equalsIgnoreCase(operatorSpecified))
155 return OPERATOR_GREATER_THAN_OR_EQUALS;
156 else if (OPERATOR_LESS_THAN_OR_EQUALS.equalsIgnoreCase(operatorSpecified))
157 return OPERATOR_LESS_THAN_OR_EQUALS;
158
159 else if (OPERATOR_EQUALS_ALT.equalsIgnoreCase(operatorSpecified))
160 return OPERATOR_EQUALS;
161 else if (OPERATOR_NOT_EQUALS_ALT.equalsIgnoreCase(operatorSpecified))
162 return OPERATOR_NOT_EQUALS;
163 else if (OPERATOR_GREATER_THAN_ALT.equalsIgnoreCase(operatorSpecified))
164 return OPERATOR_GREATER_THAN;
165 else if (OPERATOR_LESS_THAN_ALT.equalsIgnoreCase(operatorSpecified))
166 return OPERATOR_LESS_THAN;
167 else if (OPERATOR_GREATER_THAN_OR_EQUALS_ALT.equalsIgnoreCase(operatorSpecified))
168 return OPERATOR_GREATER_THAN_OR_EQUALS;
169 else if (OPERATOR_LESS_THAN_OR_EQUALS_ALT.equalsIgnoreCase(operatorSpecified))
170 return OPERATOR_LESS_THAN_OR_EQUALS;
171
172 else if (OPERATOR_EQUALS_ALT2.equalsIgnoreCase(operatorSpecified))
173 return OPERATOR_EQUALS;
174
175 throw new IllegalStateException("Operator has unknown value of '" + operatorSpecified + "'");
176 }
177
178 protected String nameForOperator(String operator)
179 {
180 if (OPERATOR_EQUALS.equals(operator))
181 return "equal to";
182 else if (OPERATOR_NOT_EQUALS.equals(operator))
183 return "inequal to";
184 else if (OPERATOR_GREATER_THAN.equals(operator))
185 return "greater than";
186 else if (OPERATOR_LESS_THAN.equals(operator))
187 return "less than";
188 else if (OPERATOR_GREATER_THAN_OR_EQUALS.equals(operator))
189 return "greater than or equal to";
190 else if (OPERATOR_LESS_THAN_OR_EQUALS.equals(operator))
191 return "less than or equal to";
192
193 throw new IllegalStateException("Operator has unknown value of '" + operator + "'");
194 }
195
196 protected boolean validateOperatorOnComparisonResult(String operator, int result)
197 {
198 if (OPERATOR_EQUALS.equals(operator))
199 return result == 0;
200 else if (OPERATOR_NOT_EQUALS.equals(operator))
201 return result != 0;
202 else if (OPERATOR_GREATER_THAN.equals(operator))
203 return result > 0;
204 else if (OPERATOR_LESS_THAN.equals(operator))
205 return result < 0;
206 else if (OPERATOR_GREATER_THAN_OR_EQUALS.equals(operator))
207 return result >= 0;
208 else if (OPERATOR_LESS_THAN_OR_EQUALS.equals(operator))
209 return result <= 0;
210
211 throw new IllegalStateException("Operator has unknown value of '" + operator + "'");
212 }
213
214 public void validate(
215 FacesContext facesContext,
216 UIComponent uiComponent,
217 Object value)
218 throws ValidatorException {
219
220 if (facesContext == null) throw new NullPointerException("facesContext");
221 if (uiComponent == null) throw new NullPointerException("uiComponent");
222
223
224 if (value == null)
225 {
226 return;
227 }
228
229 String foreignComponentName = getFor();
230
231 UIComponent foreignComponent = (UIComponent) uiComponent.getParent().findComponent(foreignComponentName);
232 if(foreignComponent == null)
233 throw new FacesException("Unable to find component '" + foreignComponentName + "' (calling findComponent on component '" + uiComponent.getId() + "')");
234
235 if(false == foreignComponent instanceof EditableValueHolder)
236 throw new FacesException("Component '" + foreignComponent.getId() + "' does not implement EditableValueHolder");
237 EditableValueHolder foreignEditableValueHolder = (EditableValueHolder)foreignComponent;
238
239 if (foreignEditableValueHolder.isRequired() && foreignEditableValueHolder.getValue()== null ) {
240 return;
241 }
242
243 Object foreignValue;
244 if (foreignEditableValueHolder.isValid())
245 {
246 foreignValue = foreignEditableValueHolder.getValue();
247 }
248 else
249 {
250 try
251 {
252 foreignValue = getConvertedValueNonValid(facesContext, foreignComponent);
253 }
254 catch(ConverterException e)
255 {
256
257
258
259
260
261
262
263
264 return;
265 }
266 }
267
268
269 if (null == foreignValue)
270 {
271 return;
272 }
273
274 String operator = getOperatorForString(getOperator());
275
276 String alternateOperatorName = getAlternateOperatorName();
277 Object[] args = {
278 uiComponent.getId(),
279 value.toString(),
280 (alternateOperatorName == null) ? nameForOperator(operator) : alternateOperatorName,
281 foreignComponent.getId(),
282 foreignValue.toString()
283 };
284
285 String message = getMessage();
286 if (null == message) message = COMPARE_TO_MESSAGE_ID;
287
288 Comparator comparator = createComparator();
289
290 if (null != comparator)
291 {
292 if (false == validateOperatorOnComparisonResult(operator, comparator.compare(value, foreignValue)))
293 {
294 throw new ValidatorException(MessageUtils.getMessage(FacesMessage.SEVERITY_ERROR, message, args));
295 }
296 }
297 else if ( (value instanceof Comparable) && (foreignValue instanceof Comparable) )
298 {
299 try
300 {
301 if (false == validateOperatorOnComparisonResult(operator, ((Comparable)value).compareTo(foreignValue)))
302 {
303 throw new ValidatorException(MessageUtils.getMessage(FacesMessage.SEVERITY_ERROR, message, args));
304 }
305 }
306 catch (RuntimeException exception)
307 {
308 if (exception instanceof ValidatorException)
309 {
310 throw exception;
311 }
312 else
313 {
314 throw new ValidatorException(MessageUtils.getMessage(FacesMessage.SEVERITY_ERROR, message + ": " + exception.getLocalizedMessage(), args));
315 }
316 }
317 }
318 else if (value instanceof Comparable)
319 {
320 throw new ClassCastException(getClassCastExceptionMessage(foreignComponent.getId(), Comparable.class, foreignValue));
321 }
322 else if (foreignValue instanceof Comparable)
323 {
324 throw new ClassCastException(getClassCastExceptionMessage(uiComponent.getId(), Comparable.class, value));
325 }
326 }
327
328 protected String getClassCastExceptionMessage(String name, Class clazz, Object object)
329 {
330 if (null == object)
331 return name + " must be type " + clazz + " but is null";
332 else return name + " must be type " + clazz + " but is type " + object.getClass();
333 }
334
335 protected Comparator createComparator()
336 {
337 Object comparator = getComparator();
338
339 if (null == comparator) return null;
340
341 if (false == comparator instanceof Comparator)
342 {
343 throw new ClassCastException(getClassCastExceptionMessage("comparator", Comparator.class, comparator));
344 }
345
346 return (Comparator)comparator;
347 }
348
349
350
351
352
353
354
355
356
357 public abstract String getFor();
358
359
360
361
362 public abstract void setFor(String string);
363
364
365
366
367
368
369
370 public abstract String getOperator();
371
372 public abstract void setOperator(String operator);
373
374
375
376
377
378
379
380
381 public abstract Object getComparator();
382
383 public abstract void setComparator(Object comparator);
384
385
386
387
388
389
390
391 public abstract String getAlternateOperatorName();
392
393 public abstract void setAlternateOperatorName(String alternateOperatorName);
394
395
396
397 private Renderer getRenderer(FacesContext context, UIComponent foreignComponent)
398 {
399 if (context == null) throw new NullPointerException("context");
400 String rendererType = foreignComponent.getRendererType();
401 if (rendererType == null) return null;
402 String renderKitId = context.getViewRoot().getRenderKitId();
403 RenderKitFactory rkf = (RenderKitFactory)FactoryFinder.getFactory(FactoryFinder.RENDER_KIT_FACTORY);
404 RenderKit renderKit = rkf.getRenderKit(context, renderKitId);
405 Renderer renderer = renderKit.getRenderer(foreignComponent.getFamily(), rendererType);
406 if (renderer == null)
407 {
408 getFacesContext().getExternalContext().log("No Renderer found for component " + foreignComponent + " (component-family=" + foreignComponent.getFamily() + ", renderer-type=" + rendererType + ")");
409 }
410 return renderer;
411 }
412
413 private Converter findUIOutputConverter(FacesContext facesContext, UIComponent component)
414 {
415 Converter converter = null;
416 if (component instanceof ValueHolder)
417 {
418 converter = ((ValueHolder)component).getConverter();
419 }
420 if (converter != null) return converter;
421
422
423 ValueExpression vb = component.getValueExpression("value");
424 if (vb == null) return null;
425
426 Class valueType = vb.getType(facesContext.getELContext());
427 if (valueType == null) return null;
428
429 if (String.class.equals(valueType)) return null;
430 if (Object.class.equals(valueType)) return null;
431
432 try
433 {
434 return facesContext.getApplication().createConverter(valueType);
435 }
436 catch (FacesException e)
437 {
438 getFacesContext().getExternalContext().log("No Converter for type " + valueType.getName() + " found", e);
439 return null;
440 }
441 }
442
443
444
445
446 private Object getConvertedValueNonValid(FacesContext facesContext, UIComponent component)
447 throws ConverterException
448 {
449 Object componentValueObject;
450
451
452
453 if (!(component instanceof EditableValueHolder))
454 {
455 return null;
456 }
457 Object submittedValue = ((EditableValueHolder) component).getSubmittedValue();
458 if (submittedValue == null)
459 {
460 componentValueObject = null;
461 }
462 else
463 {
464 Renderer renderer = getRenderer(facesContext, component);
465 if (renderer != null)
466 {
467 componentValueObject = renderer.getConvertedValue(facesContext, component, submittedValue);
468 }
469 else if (submittedValue instanceof String)
470 {
471 Converter converter = findUIOutputConverter(facesContext, component);
472 if (converter != null)
473 {
474 componentValueObject = converter.getAsObject(facesContext, component, (String)submittedValue);
475 }
476 else
477 {
478 componentValueObject = submittedValue;
479 }
480 }else{
481 componentValueObject = submittedValue;
482 }
483 }
484 return componentValueObject;
485 }
486 }