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