1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package javax.faces.component;
20
21 import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFComponent;
22 import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFListener;
23 import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFProperty;
24 import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFWebConfigParam;
25
26 import javax.el.ValueExpression;
27 import javax.faces.application.FacesMessage;
28 import javax.faces.application.ProjectStage;
29 import javax.faces.context.ExternalContext;
30 import javax.faces.context.FacesContext;
31 import javax.faces.convert.Converter;
32 import javax.faces.convert.ConverterException;
33 import javax.faces.el.EvaluationException;
34 import javax.faces.el.MethodBinding;
35 import javax.faces.event.AbortProcessingException;
36 import javax.faces.event.ExceptionQueuedEvent;
37 import javax.faces.event.ExceptionQueuedEventContext;
38 import javax.faces.event.FacesEvent;
39 import javax.faces.event.PhaseId;
40 import javax.faces.event.PostValidateEvent;
41 import javax.faces.event.PreValidateEvent;
42 import javax.faces.event.ValueChangeEvent;
43 import javax.faces.event.ValueChangeListener;
44 import javax.faces.render.Renderer;
45 import javax.faces.validator.Validator;
46 import javax.faces.webapp.FacesServlet;
47 import java.util.ArrayList;
48 import java.util.Arrays;
49 import java.util.Collection;
50 import java.util.HashMap;
51 import java.util.LinkedList;
52 import java.util.List;
53 import java.util.Map;
54
55
56
57
58
59
60
61
62 @JSFComponent(defaultRendererType = "javax.faces.Text")
63 public class UIInput extends UIOutput implements EditableValueHolder
64 {
65 public static final String COMPONENT_TYPE = "javax.faces.Input";
66 public static final String COMPONENT_FAMILY = "javax.faces.Input";
67
68 public static final String CONVERSION_MESSAGE_ID = "javax.faces.component.UIInput.CONVERSION";
69 public static final String REQUIRED_MESSAGE_ID = "javax.faces.component.UIInput.REQUIRED";
70 public static final String UPDATE_MESSAGE_ID = "javax.faces.component.UIInput.UPDATE";
71
72
73
74
75
76 @JSFWebConfigParam(defaultValue="auto", expectedValues="auto, true, false", since="2.0", group="validation")
77 public static final String VALIDATE_EMPTY_FIELDS_PARAM_NAME = "javax.faces.VALIDATE_EMPTY_FIELDS";
78
79
80
81
82
83
84 @JSFWebConfigParam(defaultValue="false", expectedValues="true, false", since="2.0", group="validation")
85 public static final String EMPTY_STRING_AS_NULL_PARAM_NAME
86 = "javax.faces.INTERPRET_EMPTY_STRING_SUBMITTED_VALUES_AS_NULL";
87
88
89
90
91
92
93
94 @JSFWebConfigParam(defaultValue="true", expectedValues="true, false", since="2.3.0", group="validation")
95 private static final String CLEAR_INPUT_WHEN_SUBMITTED_VALUE_IS_NULL_OR_EMPTY_PARAM_NAME
96 = "org.apache.myfaces.CLEAR_INPUT_WHEN_SUBMITTED_VALUE_IS_NULL_OR_EMPTY";
97
98
99
100
101 @JSFWebConfigParam(defaultValue="false", expectedValues="true, false", since="2.3", group="validation")
102 public static final String ALWAYS_PERFORM_VALIDATION_WHEN_REQUIRED_IS_TRUE
103 = "javax.faces.ALWAYS_PERFORM_VALIDATION_WHEN_REQUIRED_IS_TRUE";
104
105
106 private static final String MYFACES_EMPTY_VALUES_AS_NULL_PARAM_NAME =
107 "org.apache.myfaces.UIInput.INTERPRET_EMPTY_STRING_SUBMITTED_VALUES_AS_NULL";
108
109
110
111
112
113
114 private static final String DEBUG_INFO_KEY = "org.apache.myfaces.debug.DEBUG_INFO";
115
116 private final static String BEAN_BEFORE_JSF_PROPERTY = "oam.beanBeforeJsf";
117
118 private static final Validator[] EMPTY_VALIDATOR_ARRAY = new Validator[0];
119
120 private _DeltaList<Validator> _validatorList;
121
122
123
124
125 public UIInput()
126 {
127 setRendererType("javax.faces.Text");
128 }
129
130 @Override
131 public String getFamily()
132 {
133 return COMPONENT_FAMILY;
134 }
135
136
137
138
139
140
141
142 @Override
143 public void setValue(Object value)
144 {
145 FacesContext facesContext = getFacesContext();
146 if (facesContext != null && facesContext.isProjectStage(ProjectStage.Development))
147 {
148
149 _createFieldDebugInfo(facesContext, "localValue",
150 getLocalValue(), value, 1);
151 }
152 setLocalValueSet(true);
153 super.setValue(value);
154 }
155
156
157
158
159
160
161
162
163
164 public Object getValue()
165 {
166 if (isLocalValueSet())
167 {
168 return super.getLocalValue();
169 }
170 return super.getValue();
171 }
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186 @Override
187 public void processDecodes(FacesContext context)
188 {
189 if (context == null)
190 {
191 throw new NullPointerException("context");
192 }
193 try
194 {
195 setCachedFacesContext(context);
196 pushComponentToEL(context, this);
197 if (!isRendered())
198 {
199 return;
200 }
201 }
202 finally
203 {
204 setCachedFacesContext(null);
205 popComponentFromEL(context);
206 }
207 super.processDecodes(context);
208 try
209 {
210 setCachedFacesContext(context);
211 pushComponentToEL(context, this);
212 if (isImmediate())
213 {
214
215 context.getApplication().publishEvent(context, PreValidateEvent.class, getClass(), this);
216 try
217 {
218 validate(context);
219 }
220 catch (RuntimeException e)
221 {
222 context.renderResponse();
223 throw e;
224 }
225 finally
226 {
227 context.getApplication().publishEvent(context, PostValidateEvent.class, getClass(), this);
228 }
229 if (!isValid())
230 {
231 context.renderResponse();
232 }
233 }
234 }
235 finally
236 {
237 setCachedFacesContext(null);
238 popComponentFromEL(context);
239 }
240 }
241
242 @Override
243 public void processValidators(FacesContext context)
244 {
245 if (context == null)
246 {
247 throw new NullPointerException("context");
248 }
249 try
250 {
251 setCachedFacesContext(context);
252 pushComponentToEL(context, this);
253 if (!isRendered())
254 {
255 return;
256 }
257 }
258 finally
259 {
260 setCachedFacesContext(null);
261 popComponentFromEL(context);
262 }
263
264
265
266
267
268 int facetCount = getFacetCount();
269 if (facetCount > 0)
270 {
271 for (UIComponent facet : getFacets().values())
272 {
273 facet.processValidators(context);
274 }
275 }
276
277 for (int i = 0, childCount = getChildCount(); i < childCount; i++)
278 {
279 UIComponent child = getChildren().get(i);
280 child.processValidators(context);
281 }
282
283 try
284 {
285 setCachedFacesContext(context);
286 pushComponentToEL(context, this);
287 if (!isImmediate())
288 {
289
290 context.getApplication().publishEvent(context, PreValidateEvent.class, getClass(), this);
291 try
292 {
293 validate(context);
294 }
295 catch (RuntimeException e)
296 {
297 context.renderResponse();
298 throw e;
299 }
300 finally
301 {
302 context.getApplication().publishEvent(context, PostValidateEvent.class, getClass(), this);
303 }
304 if (!isValid())
305 {
306 context.validationFailed();
307 context.renderResponse();
308 }
309 }
310 }
311 finally
312 {
313 setCachedFacesContext(null);
314 popComponentFromEL(context);
315 }
316 }
317
318 @Override
319 public void processUpdates(FacesContext context)
320 {
321 if (context == null)
322 {
323 throw new NullPointerException("context");
324 }
325 try
326 {
327 setCachedFacesContext(context);
328 pushComponentToEL(context, this);
329 if (!isRendered())
330 {
331 return;
332 }
333 }
334 finally
335 {
336 setCachedFacesContext(null);
337 popComponentFromEL(context);
338 }
339 super.processUpdates(context);
340
341 try
342 {
343 setCachedFacesContext(context);
344 pushComponentToEL(context, this);
345 try
346 {
347 updateModel(context);
348 }
349 catch (RuntimeException e)
350 {
351 context.renderResponse();
352 throw e;
353 }
354 if (!isValid())
355 {
356 context.renderResponse();
357 }
358 }
359 finally
360 {
361 setCachedFacesContext(null);
362 popComponentFromEL(context);
363 }
364 }
365
366 @Override
367 public void decode(FacesContext context)
368 {
369
370 setValid(true);
371 super.decode(context);
372 }
373
374 @Override
375 public void broadcast(FacesEvent event) throws AbortProcessingException
376 {
377
378 super.broadcast(event);
379
380
381 if (event instanceof ValueChangeEvent)
382 {
383
384 MethodBinding valueChangeListenerBinding = getValueChangeListener();
385 if (valueChangeListenerBinding != null)
386 {
387 try
388 {
389 valueChangeListenerBinding.invoke(getFacesContext(), new Object[] { event });
390 }
391 catch (EvaluationException e)
392 {
393 Throwable cause = e.getCause();
394 if (cause != null && cause instanceof AbortProcessingException)
395 {
396 throw (AbortProcessingException) cause;
397 }
398 else
399 {
400 throw e;
401 }
402 }
403 }
404 }
405 }
406
407 public void updateModel(FacesContext context)
408 {
409 if (context == null)
410 {
411 throw new NullPointerException();
412 }
413 if (!isValid())
414 {
415 return;
416 }
417 if (!isLocalValueSet())
418 {
419 return;
420 }
421 ValueExpression expression = getValueExpression("value");
422 if (expression == null)
423 {
424 return;
425 }
426
427 try
428 {
429 expression.setValue(context.getELContext(), getLocalValue());
430 setValue(null);
431 setLocalValueSet(false);
432 }
433 catch (Exception e)
434 {
435
436
437
438
439 FacesMessage facesMessage = _MessageUtils.getMessage(context,
440 context.getViewRoot().getLocale(), FacesMessage.SEVERITY_ERROR, UPDATE_MESSAGE_ID,
441 new Object[] { _MessageUtils.getLabel(context, this) });
442
443
444
445
446
447 UpdateModelException updateModelException = new UpdateModelException(facesMessage, e);
448 ExceptionQueuedEventContext exceptionQueuedContext
449 = new ExceptionQueuedEventContext(context, updateModelException, this, PhaseId.UPDATE_MODEL_VALUES);
450
451
452
453 context.getApplication().publishEvent(context, ExceptionQueuedEvent.class, exceptionQueuedContext);
454
455
456 setValid(false);
457 }
458 }
459
460 protected void validateValue(FacesContext context, Object convertedValue)
461 {
462 if (!isValid())
463 {
464 return;
465 }
466
467
468 boolean isEmpty = isEmpty(convertedValue);
469
470 if (isRequired() && isEmpty)
471 {
472 if (getRequiredMessage() != null)
473 {
474 String requiredMessage = getRequiredMessage();
475 context.addMessage(this.getClientId(context), new FacesMessage(FacesMessage.SEVERITY_ERROR,
476 requiredMessage, requiredMessage));
477 }
478 else
479 {
480 _MessageUtils.addErrorMessage(context, this, REQUIRED_MESSAGE_ID,
481 new Object[] { _MessageUtils.getLabel(context, this) });
482 }
483 setValid(false);
484 return;
485 }
486
487 if (!isEmpty || shouldValidateEmptyFields(context))
488 {
489 _ComponentUtils.callValidators(context, this, convertedValue);
490 }
491 }
492
493
494
495
496
497
498
499 private boolean shouldInterpretEmptyStringSubmittedValuesAsNull(FacesContext context)
500 {
501 ExternalContext ec = context.getExternalContext();
502 Boolean interpretEmptyStringAsNull
503 = (Boolean)ec.getApplicationMap().get(MYFACES_EMPTY_VALUES_AS_NULL_PARAM_NAME);
504
505
506 if (interpretEmptyStringAsNull == null)
507 {
508
509 String param = ec.getInitParameter(EMPTY_STRING_AS_NULL_PARAM_NAME);
510
511
512 interpretEmptyStringAsNull = "true".equalsIgnoreCase(param);
513
514
515 ec.getApplicationMap().put(MYFACES_EMPTY_VALUES_AS_NULL_PARAM_NAME, interpretEmptyStringAsNull);
516 }
517
518 return interpretEmptyStringAsNull;
519 }
520
521
522
523
524 private boolean isEmptyString(Object value)
525 {
526 return ((value instanceof String) && (((String) value).length() == 0));
527 }
528
529
530 private boolean shouldValidateEmptyFields(FacesContext context)
531 {
532 ExternalContext ec = context.getExternalContext();
533 Boolean validateEmptyFields = (Boolean) ec.getApplicationMap().get(VALIDATE_EMPTY_FIELDS_PARAM_NAME);
534
535 if (validateEmptyFields == null)
536 {
537 String param = ec.getInitParameter(VALIDATE_EMPTY_FIELDS_PARAM_NAME);
538
539
540 if (param == null)
541 {
542 param = "auto";
543 }
544 else
545 {
546
547 param = param.toLowerCase();
548 }
549
550 if (param.equals("auto") && _ExternalSpecifications.isBeanValidationAvailable())
551 {
552 validateEmptyFields = true;
553 }
554 else if (param.equals("true"))
555 {
556 validateEmptyFields = true;
557 }
558 else
559 {
560 validateEmptyFields = false;
561 }
562
563
564 ec.getApplicationMap().put(VALIDATE_EMPTY_FIELDS_PARAM_NAME, validateEmptyFields);
565 }
566
567 return validateEmptyFields;
568 }
569
570
571
572
573
574
575
576 private boolean shouldClearInputWhenSubmittedValueIsNullOrEmpty(FacesContext context)
577 {
578 ExternalContext ec = context.getExternalContext();
579 Boolean clearInputWhenSubmittedValueIsNullOrEmpty =
580 (Boolean) ec.getApplicationMap().get(CLEAR_INPUT_WHEN_SUBMITTED_VALUE_IS_NULL_OR_EMPTY_PARAM_NAME);
581
582 if (clearInputWhenSubmittedValueIsNullOrEmpty == null)
583 {
584
585
586 String param = ec.getInitParameter(CLEAR_INPUT_WHEN_SUBMITTED_VALUE_IS_NULL_OR_EMPTY_PARAM_NAME);
587
588
589
590 if (param == null)
591 {
592 clearInputWhenSubmittedValueIsNullOrEmpty = true;
593 }
594 else if ("false".equalsIgnoreCase(param))
595 {
596 clearInputWhenSubmittedValueIsNullOrEmpty = false;
597 }
598 else
599 {
600 clearInputWhenSubmittedValueIsNullOrEmpty = true;
601 }
602
603
604 ec.getApplicationMap().put(CLEAR_INPUT_WHEN_SUBMITTED_VALUE_IS_NULL_OR_EMPTY_PARAM_NAME, clearInputWhenSubmittedValueIsNullOrEmpty);
605 }
606
607 return clearInputWhenSubmittedValueIsNullOrEmpty;
608 }
609
610 private boolean shouldAlwaysPerformValidationWhenRequiredTrue(FacesContext context)
611 {
612 ExternalContext ec = context.getExternalContext();
613 Boolean alwaysPerformValidationWhenRequiredTrue = (Boolean) ec.getApplicationMap().get(
614 ALWAYS_PERFORM_VALIDATION_WHEN_REQUIRED_IS_TRUE);
615
616 if (alwaysPerformValidationWhenRequiredTrue == null)
617 {
618 String param = ec.getInitParameter(ALWAYS_PERFORM_VALIDATION_WHEN_REQUIRED_IS_TRUE);
619
620
621 if (param == null)
622 {
623 param = "false";
624 }
625 else
626 {
627
628 param = param.toLowerCase();
629 }
630
631 if (param.equals("true"))
632 {
633 alwaysPerformValidationWhenRequiredTrue = true;
634 }
635 else
636 {
637 alwaysPerformValidationWhenRequiredTrue = false;
638 }
639
640
641 ec.getApplicationMap().put(ALWAYS_PERFORM_VALIDATION_WHEN_REQUIRED_IS_TRUE,
642 alwaysPerformValidationWhenRequiredTrue);
643 }
644
645 return alwaysPerformValidationWhenRequiredTrue;
646 }
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669 public void validate(FacesContext context)
670 {
671 if (context == null)
672 {
673 throw new NullPointerException("context");
674 }
675
676 Object submittedValue = getSubmittedValue();
677 if (submittedValue == null)
678 {
679 if (isRequired() && shouldAlwaysPerformValidationWhenRequiredTrue(context))
680 {
681
682 }
683 else
684 {
685 return;
686 }
687 }
688
689
690 if (shouldInterpretEmptyStringSubmittedValuesAsNull(context) && isEmptyString(submittedValue))
691 {
692 setSubmittedValue(null);
693
694 if (!shouldClearInputWhenSubmittedValueIsNullOrEmpty(context))
695 {
696 submittedValue = null;
697 }
698 }
699
700
701 Object convertedValue;
702 try
703 {
704 if (shouldClearInputWhenSubmittedValueIsNullOrEmpty(context))
705 {
706
707
708 convertedValue = getConvertedValue(context, getSubmittedValue());
709 }
710 else
711 {
712 convertedValue = getConvertedValue(context, submittedValue);
713 }
714 }
715 catch (ConverterException e)
716 {
717 String converterMessage = getConverterMessage();
718 if (converterMessage != null)
719 {
720 context.addMessage(getClientId(context), new FacesMessage(FacesMessage.SEVERITY_ERROR,
721 converterMessage, converterMessage));
722 }
723 else
724 {
725 FacesMessage facesMessage = e.getFacesMessage();
726 if (facesMessage != null)
727 {
728 context.addMessage(getClientId(context), facesMessage);
729 }
730 else
731 {
732 _MessageUtils.addErrorMessage(context, this, CONVERSION_MESSAGE_ID,
733 new Object[] { _MessageUtils.getLabel(context, this) });
734 }
735 }
736 setValid(false);
737 if (shouldClearInputWhenSubmittedValueIsNullOrEmpty(context))
738 {
739
740
741 setSubmittedValue(submittedValue);
742 }
743 return;
744 }
745
746 validateValue(context, convertedValue);
747
748 if (!isValid())
749 {
750 if (shouldClearInputWhenSubmittedValueIsNullOrEmpty(context))
751 {
752
753
754 setSubmittedValue(submittedValue);
755 }
756 return;
757 }
758
759 Object previousValue = getValue();
760 setValue(convertedValue);
761 setSubmittedValue(null);
762 if (compareValues(previousValue, convertedValue))
763 {
764 queueEvent(new ValueChangeEvent(this, previousValue, convertedValue));
765 }
766 }
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784 protected Object getConvertedValue(FacesContext context, Object submittedValue) throws ConverterException
785 {
786 Renderer renderer = getRenderer(context);
787 if (renderer != null)
788 {
789 return renderer.getConvertedValue(context, this, submittedValue);
790 }
791 else if (submittedValue instanceof String)
792 {
793 Converter converter = _SharedRendererUtils.findUIOutputConverter(context, this);
794 if (converter != null)
795 {
796 return converter.getAsObject(context, this, (String) submittedValue);
797 }
798 }
799 return submittedValue;
800 }
801
802 protected boolean compareValues(Object previous, Object value)
803 {
804 return previous == null ? (value != null) : (!previous.equals(value));
805 }
806
807
808
809
810 public void resetValue()
811 {
812 super.resetValue();
813 setSubmittedValue(null);
814 setLocalValueSet(false);
815 setValid(true);
816 }
817
818
819
820
821
822
823
824
825
826 @JSFProperty
827 public boolean isImmediate()
828 {
829 return (Boolean) getStateHelper().eval(PropertyKeys.immediate, Boolean.FALSE);
830 }
831
832 public void setImmediate(boolean immediate)
833 {
834 getStateHelper().put(PropertyKeys.immediate, immediate );
835 }
836
837
838
839
840
841
842
843
844
845
846
847 @JSFProperty(defaultValue = "false")
848 public boolean isRequired()
849 {
850 return (Boolean) getStateHelper().eval(PropertyKeys.required, Boolean.FALSE);
851 }
852
853 public void setRequired(boolean required)
854 {
855 getStateHelper().put(PropertyKeys.required, required );
856 }
857
858
859
860
861
862
863
864 @JSFProperty
865 public String getConverterMessage()
866 {
867 return (String) getStateHelper().eval(PropertyKeys.converterMessage);
868 }
869
870 public void setConverterMessage(String converterMessage)
871 {
872 getStateHelper().put(PropertyKeys.converterMessage, converterMessage );
873 }
874
875
876
877
878
879 @JSFProperty
880 public String getRequiredMessage()
881 {
882 return (String) getStateHelper().eval(PropertyKeys.requiredMessage);
883 }
884
885 public void setRequiredMessage(String requiredMessage)
886 {
887 getStateHelper().put(PropertyKeys.requiredMessage, requiredMessage );
888 }
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903 @SuppressWarnings("dep-ann")
904 @JSFProperty(stateHolder=true, returnSignature = "void",
905 methodSignature = "javax.faces.context.FacesContext,javax.faces.component.UIComponent,java.lang.Object")
906 public MethodBinding getValidator()
907 {
908 return (MethodBinding) getStateHelper().eval(PropertyKeys.validator);
909 }
910
911
912
913
914
915 public void setValidator(MethodBinding validator)
916 {
917 getStateHelper().put(PropertyKeys.validator, validator);
918 }
919
920
921 public void addValidator(Validator validator)
922 {
923 if (validator == null)
924 {
925 throw new NullPointerException("validator");
926 }
927
928 if (_validatorList == null)
929 {
930
931 _validatorList = new _DeltaList<Validator>(3);
932 }
933
934 _validatorList.add(validator);
935
936
937
938 }
939
940
941 public void removeValidator(Validator validator)
942 {
943 if (validator == null || _validatorList == null)
944 {
945 return;
946 }
947
948 _validatorList.remove(validator);
949 }
950
951
952 public Validator[] getValidators()
953 {
954 if (_ExternalSpecifications.isBeanValidationAvailable() &&
955 Boolean.TRUE.equals(this.getAttributes().containsKey(BEAN_BEFORE_JSF_PROPERTY)))
956 {
957 int bvIndex = -1;
958 for (int i = 0; i < _validatorList.size(); i++)
959 {
960 Validator v = _validatorList.get(i);
961 if (_BeanValidationUtils.isBeanValidator(v))
962 {
963 bvIndex = i;
964 break;
965 }
966 }
967 if (bvIndex != -1)
968 {
969 Validator[] array = new Validator[_validatorList.size()];
970 for (int i = 0; i < _validatorList.size(); i++)
971 {
972 if (i == bvIndex)
973 {
974 array[0] = _validatorList.get(i);
975 bvIndex = -1;
976 }
977 else
978 {
979 array[i+1] = _validatorList.get(i);
980 }
981 }
982 return array;
983 }
984 else
985 {
986 return _validatorList == null ? EMPTY_VALIDATOR_ARRAY
987 : _validatorList.toArray(new Validator[_validatorList.size()]);
988 }
989 }
990 else
991 {
992 return _validatorList == null ? EMPTY_VALIDATOR_ARRAY
993 : _validatorList.toArray(new Validator[_validatorList.size()]);
994 }
995 }
996
997
998
999
1000 @JSFProperty
1001 public String getValidatorMessage()
1002 {
1003 return (String) getStateHelper().eval(PropertyKeys.validatorMessage);
1004 }
1005
1006 public void setValidatorMessage(String validatorMessage)
1007 {
1008 getStateHelper().put(PropertyKeys.validatorMessage, validatorMessage );
1009 }
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020 @JSFProperty(stateHolder=true, returnSignature = "void",
1021 methodSignature = "javax.faces.event.ValueChangeEvent", clientEvent="valueChange")
1022 public MethodBinding getValueChangeListener()
1023 {
1024 return (MethodBinding) getStateHelper().eval(PropertyKeys.valueChangeListener);
1025 }
1026
1027
1028
1029
1030
1031
1032 public void setValueChangeListener(MethodBinding valueChangeListener)
1033 {
1034 getStateHelper().put(PropertyKeys.valueChangeListener, valueChangeListener);
1035 }
1036
1037
1038
1039
1040
1041 @JSFProperty(defaultValue = "true", tagExcluded = true)
1042 public boolean isValid()
1043 {
1044 Object value = getStateHelper().get(PropertyKeys.valid);
1045 if (value != null)
1046 {
1047 return (Boolean) value;
1048 }
1049 return true;
1050 }
1051
1052 public void setValid(boolean valid)
1053 {
1054
1055
1056
1057
1058 if (getStateHelper().get(PropertyKeys.valid) != null || !valid)
1059 {
1060 getStateHelper().put(PropertyKeys.valid, valid );
1061 }
1062 }
1063
1064
1065
1066
1067
1068
1069 @JSFProperty(defaultValue = "false", tagExcluded = true)
1070 public boolean isLocalValueSet()
1071 {
1072 Object value = getStateHelper().get(PropertyKeys.localValueSet);
1073 if (value != null)
1074 {
1075 return (Boolean) value;
1076 }
1077 return false;
1078 }
1079
1080 public void setLocalValueSet(boolean localValueSet)
1081 {
1082
1083
1084
1085
1086 if (getStateHelper().get(PropertyKeys.localValueSet) != null || localValueSet)
1087 {
1088 getStateHelper().put(PropertyKeys.localValueSet, localValueSet );
1089 }
1090 }
1091
1092
1093
1094
1095
1096
1097
1098 @JSFProperty(tagExcluded = true)
1099 public Object getSubmittedValue()
1100 {
1101 return getStateHelper().get(PropertyKeys.submittedValue);
1102 }
1103
1104 public void setSubmittedValue(Object submittedValue)
1105 {
1106 FacesContext facesContext = getFacesContext();
1107 if (facesContext != null && facesContext.isProjectStage(ProjectStage.Development))
1108 {
1109
1110 _createFieldDebugInfo(facesContext, "submittedValue",
1111 getStateHelper().get(PropertyKeys.submittedValue), submittedValue, 1);
1112 }
1113 getStateHelper().put(PropertyKeys.submittedValue, submittedValue );
1114 }
1115
1116 public void addValueChangeListener(ValueChangeListener listener)
1117 {
1118 addFacesListener(listener);
1119 }
1120
1121 public void removeValueChangeListener(ValueChangeListener listener)
1122 {
1123 removeFacesListener(listener);
1124 }
1125
1126
1127
1128
1129
1130 @JSFListener(event="javax.faces.event.ValueChangeEvent")
1131 public ValueChangeListener[] getValueChangeListeners()
1132 {
1133 return (ValueChangeListener[]) getFacesListeners(ValueChangeListener.class);
1134 }
1135
1136 enum PropertyKeys
1137 {
1138 immediate
1139 , required
1140 , converterMessage
1141 , requiredMessage
1142 , validator
1143 , validatorListSet
1144 , validatorMessage
1145 , valueChangeListener
1146 , valid
1147 , localValueSet
1148 , submittedValue
1149 }
1150
1151 private static final Object[] INITIAL_STATE_PROPERTIES = new
1152 Object[]{
1153 UIOutput.PropertyKeys.value,
1154 null,
1155 UIInput.PropertyKeys.localValueSet,
1156 false,
1157 UIInput.PropertyKeys.submittedValue,
1158 null,
1159 UIInput.PropertyKeys.valid,
1160 true
1161 };
1162
1163 public void markInitialState()
1164 {
1165 StateHelper helper = getStateHelper(false);
1166 if (helper != null && helper instanceof _DeltaStateHelper)
1167 {
1168 ((_DeltaStateHelper)helper).markPropertyInInitialState(INITIAL_STATE_PROPERTIES);
1169 }
1170 super.markInitialState();
1171 if (_validatorList != null)
1172 {
1173 _validatorList.markInitialState();
1174 }
1175 }
1176
1177 public void clearInitialState()
1178 {
1179 if (initialStateMarked())
1180 {
1181 super.clearInitialState();
1182 if (_validatorList != null)
1183 {
1184 _validatorList.clearInitialState();
1185 }
1186 }
1187 }
1188
1189 @Override
1190 public Object saveState(FacesContext facesContext)
1191 {
1192 if (initialStateMarked())
1193 {
1194 Object parentSaved = super.saveState(facesContext);
1195 Object validatorListSaved = saveValidatorList(facesContext);
1196 if (parentSaved == null && validatorListSaved == null)
1197 {
1198
1199 return null;
1200 }
1201
1202 Object[] values = new Object[2];
1203 values[0] = parentSaved;
1204 values[1] = validatorListSaved;
1205 return values;
1206 }
1207 else
1208 {
1209 Object[] values = new Object[2];
1210 values[0] = super.saveState(facesContext);
1211 values[1] = saveValidatorList(facesContext);
1212 return values;
1213 }
1214 }
1215
1216 @SuppressWarnings("unchecked")
1217 @Override
1218 public void restoreState(FacesContext facesContext, Object state)
1219 {
1220 if (state == null)
1221 {
1222 return;
1223 }
1224
1225 Object[] values = (Object[])state;
1226 super.restoreState(facesContext,values[0]);
1227 if (values[1] instanceof _AttachedDeltaWrapper)
1228 {
1229
1230 if (_validatorList != null)
1231 {
1232 ((StateHolder)_validatorList).restoreState(facesContext,
1233 ((_AttachedDeltaWrapper) values[1]).getWrappedStateObject());
1234 }
1235 }
1236 else if (values[1] != null || !initialStateMarked())
1237 {
1238
1239 _validatorList = (_DeltaList<Validator>)
1240 restoreAttachedState(facesContext,values[1]);
1241 }
1242 }
1243
1244 private Object saveValidatorList(FacesContext facesContext)
1245 {
1246 PartialStateHolder holder = (PartialStateHolder) _validatorList;
1247 if (initialStateMarked() && _validatorList != null && holder.initialStateMarked())
1248 {
1249 Object attachedState = holder.saveState(facesContext);
1250 if (attachedState != null)
1251 {
1252 return new _AttachedDeltaWrapper(_validatorList.getClass(),
1253 attachedState);
1254 }
1255
1256 return null;
1257 }
1258 else
1259 {
1260 return saveAttachedState(facesContext,_validatorList);
1261 }
1262 }
1263
1264
1265
1266
1267
1268 @SuppressWarnings("unchecked")
1269 private Map<String, List<Object[]>> _getDebugInfoMap()
1270 {
1271 Map<String, Object> requestMap = getFacesContext()
1272 .getExternalContext().getRequestMap();
1273 Map<String, List<Object[]>> debugInfo = (Map<String, List<Object[]>>)
1274 requestMap.get(DEBUG_INFO_KEY + getClientId());
1275 if (debugInfo == null)
1276 {
1277
1278 debugInfo = new HashMap<String, List<Object[]>>();
1279 requestMap.put(DEBUG_INFO_KEY + getClientId(), debugInfo);
1280 }
1281 return debugInfo;
1282 }
1283
1284
1285
1286
1287
1288
1289 private List<Object[]> _getFieldDebugInfos(final String field)
1290 {
1291 Map<String, List<Object[]>> debugInfo = _getDebugInfoMap();
1292 List<Object[]> fieldDebugInfo = debugInfo.get(field);
1293 if (fieldDebugInfo == null)
1294 {
1295
1296 fieldDebugInfo = new ArrayList<Object[]>();
1297 debugInfo.put(field, fieldDebugInfo);
1298 }
1299 return fieldDebugInfo;
1300 }
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313 private void _createFieldDebugInfo(FacesContext facesContext,
1314 final String field, Object oldValue,
1315 Object newValue, final int skipStackTaceElements)
1316 {
1317 if (oldValue == null && newValue == null)
1318 {
1319
1320
1321 return;
1322 }
1323
1324 if (facesContext.getViewRoot() == null)
1325 {
1326
1327
1328
1329
1330 return;
1331 }
1332
1333 if (getParent() == null || !isInView())
1334 {
1335
1336 return;
1337 }
1338
1339
1340 if (oldValue != null && oldValue.getClass().isArray() && Object[].class.isAssignableFrom(oldValue.getClass()))
1341 {
1342 oldValue = Arrays.deepToString((Object[]) oldValue);
1343 }
1344 if (newValue != null && newValue.getClass().isArray() && Object[].class.isAssignableFrom(newValue.getClass()))
1345 {
1346 newValue = Arrays.deepToString((Object[]) newValue);
1347 }
1348
1349
1350 Throwable throwableHelper = new Throwable();
1351 StackTraceElement[] stackTraceElements = throwableHelper.getStackTrace();
1352 List<StackTraceElement> debugStackTraceElements = new LinkedList<StackTraceElement>();
1353
1354
1355 for (int i = skipStackTaceElements + 1; i < stackTraceElements.length; i++)
1356 {
1357 debugStackTraceElements.add(stackTraceElements[i]);
1358
1359 if (FacesServlet.class.getCanonicalName()
1360 .equals(stackTraceElements[i].getClassName()))
1361 {
1362
1363 break;
1364 }
1365 }
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375 Object[] debugInfo = new Object[4];
1376 debugInfo[0] = facesContext.getCurrentPhaseId();
1377 debugInfo[1] = oldValue;
1378 debugInfo[2] = newValue;
1379 debugInfo[3] = debugStackTraceElements;
1380
1381
1382 _getFieldDebugInfos(field).add(debugInfo);
1383 }
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393 public static boolean isEmpty(Object value)
1394 {
1395 if (value == null)
1396 {
1397 return true;
1398 }
1399 else if (value instanceof String)
1400 {
1401 if ( ((String)value).trim().length() <= 0 )
1402 {
1403 return true;
1404 }
1405 }
1406 else if (value instanceof Collection)
1407 {
1408 if ( ((Collection)value).isEmpty())
1409 {
1410 return true;
1411 }
1412 }
1413 else if (value.getClass().isArray())
1414 {
1415 if (java.lang.reflect.Array.getLength(value) <= 0)
1416 {
1417 return true;
1418 }
1419 }
1420 else if (value instanceof Map)
1421 {
1422 if ( ((Map)value).isEmpty())
1423 {
1424 return true;
1425 }
1426 }
1427 return false;
1428 }
1429
1430 }