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