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