1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.myfaces.tobago.util;
21
22 import org.apache.commons.lang.ArrayUtils;
23 import org.apache.commons.lang.StringUtils;
24 import org.apache.myfaces.tobago.component.Attributes;
25 import org.apache.myfaces.tobago.component.Facets;
26 import org.apache.myfaces.tobago.component.RendererTypes;
27 import org.apache.myfaces.tobago.component.SupportsMarkup;
28 import org.apache.myfaces.tobago.context.Markup;
29 import org.apache.myfaces.tobago.context.TransientStateHolder;
30 import org.apache.myfaces.tobago.el.ConstantMethodBinding;
31 import org.apache.myfaces.tobago.event.AbstractPopupActionListener;
32 import org.apache.myfaces.tobago.internal.component.AbstractUIForm;
33 import org.apache.myfaces.tobago.internal.component.AbstractUIInput;
34 import org.apache.myfaces.tobago.internal.component.AbstractUIPage;
35 import org.apache.myfaces.tobago.internal.component.AbstractUIPopup;
36 import org.apache.myfaces.tobago.internal.util.FindComponentUtils;
37 import org.apache.myfaces.tobago.renderkit.RendererBase;
38 import org.apache.myfaces.tobago.renderkit.html.StyleClasses;
39 import org.slf4j.Logger;
40 import org.slf4j.LoggerFactory;
41
42 import javax.faces.FactoryFinder;
43 import javax.faces.application.Application;
44 import javax.faces.application.FacesMessage;
45 import javax.faces.component.ActionSource;
46 import javax.faces.component.EditableValueHolder;
47 import javax.faces.component.NamingContainer;
48 import javax.faces.component.UICommand;
49 import javax.faces.component.UIComponent;
50 import javax.faces.component.UIGraphic;
51 import javax.faces.component.UIInput;
52 import javax.faces.component.UIOutput;
53 import javax.faces.component.UIParameter;
54 import javax.faces.component.UISelectMany;
55 import javax.faces.component.UIViewRoot;
56 import javax.faces.component.ValueHolder;
57 import javax.faces.context.FacesContext;
58 import javax.faces.convert.Converter;
59 import javax.faces.el.MethodBinding;
60 import javax.faces.el.ValueBinding;
61 import javax.faces.event.ActionEvent;
62 import javax.faces.event.ActionListener;
63 import javax.faces.event.ValueChangeEvent;
64 import javax.faces.model.SelectItem;
65 import javax.faces.render.RenderKit;
66 import javax.faces.render.RenderKitFactory;
67 import javax.faces.render.Renderer;
68 import javax.faces.view.facelets.FaceletContext;
69 import javax.faces.webapp.UIComponentTag;
70 import javax.servlet.jsp.JspException;
71 import java.util.ArrayList;
72 import java.util.HashMap;
73 import java.util.Iterator;
74 import java.util.List;
75 import java.util.Map;
76
77 public class ComponentUtils {
78
79 private static final Logger LOG = LoggerFactory.getLogger(ComponentUtils.class);
80
81 public static final String SUB_SEPARATOR = "::";
82
83 private static final String RENDER_KEY_PREFIX
84 = "org.apache.myfaces.tobago.util.ComponentUtils.RendererKeyPrefix_";
85
86 private static final String PAGE_KEY = "org.apache.myfaces.tobago.Page.Key";
87
88 public static final Class[] ACTION_ARGS = {};
89 public static final Class[] ACTION_LISTENER_ARGS = {ActionEvent.class};
90 public static final Class[] VALUE_CHANGE_LISTENER_ARGS = {ValueChangeEvent.class};
91 public static final Class[] VALIDATOR_ARGS = {FacesContext.class, UIComponent.class, Object.class};
92 public static final String LIST_SEPARATOR_CHARS = ", ";
93
94
95
96
97
98 public static final String DATA_ATTRIBUTES_KEY = "javax.faces.component.DATA_ATTRIBUTES_KEY";
99
100 private ComponentUtils() {
101 }
102
103 public static boolean hasErrorMessages(FacesContext context) {
104 for (Iterator iter = context.getMessages(); iter.hasNext();) {
105 FacesMessage message = (FacesMessage) iter.next();
106 if (FacesMessage.SEVERITY_ERROR.compareTo(message.getSeverity()) <= 0) {
107 return true;
108 }
109 }
110 return false;
111 }
112
113 public static boolean containsPopupActionListener(UICommand command) {
114 ActionListener[] actionListeners = command.getActionListeners();
115 for (ActionListener actionListener : actionListeners) {
116 if (actionListener instanceof AbstractPopupActionListener) {
117 return true;
118 }
119 }
120 return false;
121 }
122
123 public static String getFacesMessageAsString(FacesContext facesContext, UIComponent component) {
124 Iterator messages = facesContext.getMessages(
125 component.getClientId(facesContext));
126 StringBuilder stringBuffer = new StringBuilder();
127 while (messages.hasNext()) {
128 FacesMessage message = (FacesMessage) messages.next();
129 stringBuffer.append(message.getDetail());
130 }
131 if (stringBuffer.length() > 0) {
132 return stringBuffer.toString();
133 } else {
134 return null;
135 }
136 }
137
138 public static boolean isInPopup(UIComponent component) {
139 while (component != null) {
140 if (component instanceof AbstractUIPopup) {
141 return true;
142 }
143 component = component.getParent();
144 }
145 return false;
146 }
147
148 public static void resetPage(FacesContext context) {
149 UIViewRoot view = context.getViewRoot();
150 if (view != null) {
151 view.getAttributes().remove(PAGE_KEY);
152 }
153 }
154
155
156
157
158
159 public static UIViewRoot findViewRoot(FaceletContext faceletContext, UIComponent component) {
160 UIViewRoot viewRoot = findAncestor(component, UIViewRoot.class);
161 if (viewRoot != null) {
162 return viewRoot;
163 } else {
164 return faceletContext.getFacesContext().getViewRoot();
165 }
166 }
167
168 public static AbstractUIPage findPage(FacesContext context, UIComponent component) {
169 UIViewRoot view = context.getViewRoot();
170 if (view != null) {
171 TransientStateHolder stateHolder = (TransientStateHolder) view.getAttributes().get(PAGE_KEY);
172 if (stateHolder == null || stateHolder.isEmpty()) {
173 AbstractUIPage page = findPage(component);
174 stateHolder = new TransientStateHolder(page);
175 context.getViewRoot().getAttributes().put(PAGE_KEY, stateHolder);
176 }
177 return (AbstractUIPage) stateHolder.get();
178 } else {
179 return findPage(component);
180 }
181 }
182
183 public static AbstractUIPage findPage(UIComponent component) {
184 while (component != null) {
185 if (component instanceof AbstractUIPage) {
186 return (AbstractUIPage) component;
187 }
188 component = component.getParent();
189 }
190 return null;
191 }
192
193 public static AbstractUIPage findPage(FacesContext facesContext) {
194 return findPageBreadthFirst(facesContext.getViewRoot());
195 }
196
197 private static AbstractUIPage findPageBreadthFirst(UIComponent component) {
198 for (UIComponent child : component.getChildren()) {
199 if (child instanceof AbstractUIPage) {
200 return (AbstractUIPage) child;
201 }
202 }
203 for (UIComponent child : component.getChildren()) {
204 AbstractUIPage result = findPageBreadthFirst(child);
205 if (result != null) {
206 return result;
207 }
208 }
209 return null;
210 }
211
212
213 public static AbstractUIForm findForm(UIComponent component) {
214 while (component != null) {
215 if (component instanceof AbstractUIForm) {
216 return (AbstractUIForm) component;
217 }
218 component = component.getParent();
219 }
220 return null;
221 }
222
223 public static <T> T findAncestor(UIComponent component, Class<T> type) {
224
225 while (component != null) {
226 if (type.isAssignableFrom(component.getClass())) {
227 return (T) component;
228 }
229 component = component.getParent();
230 }
231 return null;
232 }
233
234
235
236
237
238 public static List<AbstractUIForm> findSubForms(UIComponent component) {
239 List<AbstractUIForm> collect = new ArrayList<AbstractUIForm>();
240 findSubForms(collect, component);
241 return collect;
242 }
243
244 @SuppressWarnings("unchecked")
245 private static void findSubForms(List<AbstractUIForm> collect, UIComponent component) {
246 Iterator<UIComponent> kids = component.getFacetsAndChildren();
247 while (kids.hasNext()) {
248 UIComponent child = kids.next();
249 if (child instanceof AbstractUIForm) {
250 collect.add((AbstractUIForm) child);
251 } else {
252 findSubForms(collect, child);
253 }
254 }
255 }
256
257
258
259
260 public static <T extends UIComponent> T findDescendant(UIComponent component, Class<T> type) {
261
262 for (UIComponent child : component.getChildren()) {
263 if (type.isAssignableFrom(child.getClass())) {
264 return (T) child;
265 }
266 final T descendant = findDescendant(child, type);
267 if (descendant != null) {
268 return descendant;
269 }
270 }
271 return null;
272 }
273
274
275
276
277 public static <T extends UIComponent> List<T> findDescendantList(UIComponent component, Class<T> type) {
278
279 List<T> result = new ArrayList<T>();
280
281 for (UIComponent child : component.getChildren()) {
282 if (type.isAssignableFrom(child.getClass())) {
283 result.add((T) child);
284 }
285 result.addAll(findDescendantList(child, type));
286 }
287 return result;
288 }
289
290
291
292
293
294
295
296
297 public static String findClientIdFor(UIComponent component, FacesContext facesContext) {
298 UIComponent forComponent = findFor(component);
299 if (forComponent != null) {
300 String clientId = forComponent.getClientId(facesContext);
301 if (LOG.isDebugEnabled()) {
302 LOG.debug("found clientId: '" + clientId + "'");
303 }
304 return clientId;
305 }
306 if (LOG.isDebugEnabled()) {
307 LOG.debug("found no clientId");
308 }
309 return null;
310 }
311
312 public static UIComponent findFor(UIComponent component) {
313 String forValue = (String) component.getAttributes().get(Attributes.FOR);
314 if (forValue == null) {
315 return component.getParent();
316 }
317 return ComponentUtils.findComponent(component, forValue);
318 }
319
320
321
322
323
324
325
326
327 @Deprecated
328 public static void evaluateAutoFor(UIComponent component) {
329 String forComponent = (String) component.getAttributes().get(Attributes.FOR);
330 if (LOG.isDebugEnabled()) {
331 LOG.debug("for = '" + forComponent + "'");
332 }
333 if ("@auto".equals(forComponent)) {
334 for (UIComponent child : component.getParent().getChildren()) {
335 if (setForToInput(component, child, AbstractUIInput.class, false)) {
336 break;
337 }
338 }
339 }
340 }
341
342
343
344
345
346
347
348 public static void evaluateAutoFor(UIComponent component, Class<? extends UIComponent> clazz) {
349 String forComponent = (String) component.getAttributes().get(Attributes.FOR);
350 if (LOG.isDebugEnabled()) {
351 LOG.debug("for = '" + forComponent + "'");
352 }
353 if ("@auto".equals(forComponent)) {
354
355 for (UIComponent child : component.getParent().getChildren()) {
356 if (setForToInput(component, child, clazz, component instanceof NamingContainer)) {
357 return;
358 }
359 }
360
361 for (UIComponent child : component.getParent().getParent().getChildren()) {
362 if (setForToInput(component, child, clazz, component.getParent() instanceof NamingContainer)) {
363 return;
364 }
365 }
366 }
367 }
368
369 private static boolean setForToInput(
370 UIComponent component, UIComponent child, Class<? extends UIComponent> clazz, boolean namingContainer) {
371 if (clazz.isAssignableFrom(child.getClass())) {
372 final String forComponent;
373 if (namingContainer) {
374 forComponent = ":::" + child.getId();
375 } else {
376 forComponent = child.getId();
377 }
378 component.getAttributes().put(Attributes.FOR, forComponent);
379 return true;
380 }
381 return false;
382 }
383
384 public static boolean isInActiveForm(UIComponent component) {
385 while (component != null) {
386 if (component instanceof AbstractUIForm) {
387 AbstractUIForm form = (AbstractUIForm) component;
388 if (form.isSubmitted()) {
389 return true;
390 }
391 }
392 component = component.getParent();
393 }
394 return false;
395 }
396
397 public static FacesMessage.Severity getMaximumSeverity(UIComponent component) {
398 final boolean invalid = component instanceof UIInput && !((UIInput) component).isValid();
399 FacesMessage.Severity max = invalid ? FacesMessage.SEVERITY_ERROR : null;
400 FacesContext facesContext = FacesContext.getCurrentInstance();
401 final Iterator messages = facesContext.getMessages(component.getClientId(facesContext));
402 while (messages.hasNext()) {
403 FacesMessage message = (FacesMessage) messages.next();
404 if (max == null || message.getSeverity().getOrdinal() > max.getOrdinal()) {
405 max = message.getSeverity();
406 }
407 }
408 return max;
409 }
410
411 public static boolean isError(UIInput uiInput) {
412 FacesContext facesContext = FacesContext.getCurrentInstance();
413 return !uiInput.isValid()
414 || facesContext.getMessages(uiInput.getClientId(facesContext)).hasNext();
415 }
416
417 public static boolean isError(UIComponent component) {
418 if (component instanceof AbstractUIInput) {
419 return isError((AbstractUIInput) component);
420 }
421 return false;
422 }
423
424 public static boolean isOutputOnly(UIComponent component) {
425 return getBooleanAttribute(component, Attributes.DISABLED)
426 || getBooleanAttribute(component, Attributes.READONLY);
427 }
428
429 public static boolean mayValidate(UIComponent component) {
430 return !isOutputOnly(component)
431 && ComponentUtils.isInActiveForm(component);
432 }
433
434 public static boolean mayUpdateModel(UIComponent component) {
435 return mayValidate(component);
436 }
437
438 public static boolean getBooleanAttribute(UIComponent component, String name) {
439
440 Object bool = component.getAttributes().get(name);
441 if (bool == null) {
442 return false;
443 }
444 if (bool instanceof ValueBinding) {
445 bool = ((ValueBinding) bool).getValue(FacesContext.getCurrentInstance());
446 }
447 if (bool instanceof Boolean) {
448 return (Boolean) bool;
449 } else if (bool instanceof String) {
450 LOG.warn("Searching for a boolean, but find a String. Should not happen. "
451 + "attribute: '" + name + "' id: '" + component.getClientId(FacesContext.getCurrentInstance())
452 + "' comp: '" + component + "'");
453 return Boolean.valueOf((String) bool);
454 } else {
455 LOG.warn("Unknown type '" + bool.getClass().getName()
456 + "' for boolean attribute: " + name + " id: " + component.getClientId(FacesContext.getCurrentInstance())
457 + " comp: " + component);
458 return false;
459 }
460 }
461
462
463
464 public static ValueBinding createValueBinding(String value) {
465 return FacesContext.getCurrentInstance().getApplication().createValueBinding(value);
466 }
467
468
469
470
471
472 @Deprecated
473 public static void setStyleClasses(UIComponent component, String styleClasses) {
474 if (styleClasses != null) {
475 if (UIComponentTag.isValueReference(styleClasses)) {
476 component.setValueBinding(Attributes.STYLE_CLASS, createValueBinding(styleClasses));
477 } else {
478 String[] classes = splitList(styleClasses);
479 if (classes.length > 0) {
480 StyleClasses styles = StyleClasses.ensureStyleClasses(component);
481 for (String clazz : classes) {
482 styles.addFullQualifiedClass(clazz);
483 }
484 }
485 }
486 }
487 }
488
489
490
491
492 @Deprecated
493 public static void setMarkup(UIComponent markupComponent, String markup) {
494 if (markup != null) {
495 if (markupComponent instanceof SupportsMarkup) {
496 if (UIComponentTag.isValueReference(markup)) {
497 markupComponent.setValueBinding(Attributes.MARKUP, createValueBinding(markup));
498 } else {
499 ((SupportsMarkup) markupComponent).setMarkup(Markup.valueOf(markup));
500 }
501 } else {
502 LOG.error("Component did not support Markup " + markupComponent.getClass().getName());
503 }
504 }
505 }
506
507 public static Object getAttribute(UIComponent component, String name) {
508 Object value = component.getAttributes().get(name);
509 if (value instanceof ValueBinding) {
510 value = ((ValueBinding) value).getValue(FacesContext.getCurrentInstance());
511 }
512 return value;
513 }
514
515 public static Object getObjectAttribute(UIComponent component, String name) {
516 return getAttribute(component, name);
517 }
518
519 public static String getStringAttribute(UIComponent component, String name) {
520 return (String) getAttribute(component, name);
521 }
522
523 public static int getIntAttribute(UIComponent component, String name) {
524 return getIntAttribute(component, name, 0);
525 }
526
527 public static int getIntAttribute(UIComponent component, String name,
528 int defaultValue) {
529 Object integer = component.getAttributes().get(name);
530 if (integer instanceof Number) {
531 return ((Number) integer).intValue();
532 } else if (integer instanceof String) {
533 try {
534 return Integer.parseInt((String) integer);
535 } catch (NumberFormatException e) {
536 LOG.warn("Can't parse number from string : \"" + integer + "\"!");
537 return defaultValue;
538 }
539 } else if (integer == null) {
540 return defaultValue;
541 } else {
542 LOG.warn("Unknown type '" + integer.getClass().getName()
543 + "' for integer attribute: " + name + " comp: " + component);
544 return defaultValue;
545 }
546 }
547
548 public static Character getCharacterAttribute(UIComponent component, String name) {
549 Object character = component.getAttributes().get(name);
550 if (character == null) {
551 return null;
552 } else if (character instanceof Character) {
553 return ((Character) character);
554 } else if (character instanceof String) {
555 String asString = ((String) character);
556 return asString.length() > 0 ? asString.charAt(0) : null;
557 } else {
558 LOG.warn("Unknown type '" + character.getClass().getName()
559 + "' for integer attribute: " + name + " comp: " + component);
560 return null;
561 }
562 }
563
564 public static boolean isFacetOf(UIComponent component, UIComponent parent) {
565 for (Object o : parent.getFacets().keySet()) {
566 UIComponent facet = parent.getFacet((String) o);
567 if (component.equals(facet)) {
568 return true;
569 }
570 }
571 return false;
572 }
573
574 public static RendererBase getRenderer(FacesContext facesContext, UIComponent component) {
575 return getRenderer(facesContext, component.getFamily(), component.getRendererType());
576 }
577
578 public static RendererBase getRenderer(FacesContext facesContext, String family, String rendererType) {
579 if (rendererType == null) {
580 return null;
581 }
582
583 Map<String, Object> requestMap = (Map<String, Object>) facesContext.getExternalContext().getRequestMap();
584 StringBuilder key = new StringBuilder(RENDER_KEY_PREFIX);
585 key.append(rendererType);
586 RendererBase renderer = (RendererBase) requestMap.get(key.toString());
587
588 if (renderer == null) {
589 Renderer myRenderer = getRendererInternal(facesContext, family, rendererType);
590 if (myRenderer instanceof RendererBase) {
591 requestMap.put(key.toString(), myRenderer);
592 renderer = (RendererBase) myRenderer;
593 } else {
594 return null;
595 }
596 }
597 return renderer;
598 }
599
600
601 private static Renderer getRendererInternal(FacesContext facesContext, String family, String rendererType) {
602 RenderKitFactory rkFactory = (RenderKitFactory) FactoryFinder.getFactory(FactoryFinder.RENDER_KIT_FACTORY);
603 RenderKit renderKit = rkFactory.getRenderKit(facesContext, facesContext.getViewRoot().getRenderKitId());
604 Renderer myRenderer = renderKit.getRenderer(family, rendererType);
605 return myRenderer;
606 }
607
608 public static Object findParameter(UIComponent component, String name) {
609 for (UIComponent child : component.getChildren()) {
610 if (child instanceof UIParameter) {
611 UIParameter parameter = (UIParameter) child;
612 if (LOG.isDebugEnabled()) {
613 LOG.debug("Select name='" + parameter.getName() + "'");
614 LOG.debug("Select value='" + parameter.getValue() + "'");
615 }
616 if (name.equals(parameter.getName())) {
617 return parameter.getValue();
618 }
619 }
620 }
621 return null;
622 }
623
624 public static ActionListener createActionListener(String type)
625 throws JspException {
626 try {
627 ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
628 if (classLoader == null) {
629 classLoader = type.getClass().getClassLoader();
630 }
631 Class clazz = classLoader.loadClass(type);
632 return (ActionListener) clazz.newInstance();
633 } catch (Exception e) {
634 if (LOG.isDebugEnabled()) {
635 LOG.debug("type=" + type, e);
636 }
637 throw new JspException(e);
638 }
639 }
640
641 public static UIGraphic getFirstGraphicChild(UIComponent component) {
642 UIGraphic graphic = null;
643 for (UIComponent child : component.getChildren()) {
644 if (child instanceof UIGraphic) {
645 graphic = (UIGraphic) child;
646 break;
647 }
648 }
649 return graphic;
650 }
651
652 public static boolean isHoverEnabled(UIComponent component) {
653 return ComponentUtils.getBooleanAttribute(component, Attributes.HOVER);
654 }
655
656 public static UIOutput getFirstNonGraphicChild(UIComponent component) {
657 for (UIComponent child : component.getChildren()) {
658 if (child instanceof UIOutput) {
659 return (UIOutput) child;
660 }
661 }
662 return null;
663 }
664
665
666
667
668 @Deprecated
669 public static void setIntegerSizeProperty(UIComponent component, String name, String value) {
670 if (value != null) {
671 if (UIComponentTag.isValueReference(value)) {
672 component.setValueBinding(name, createValueBinding(value));
673 } else {
674 value = removePx(value);
675 component.getAttributes().put(name, new Integer(value));
676 }
677 }
678 }
679
680 public static String removePx(String value) {
681 if (value != null && value.endsWith("px")) {
682 value = value.substring(0, value.length() - 2);
683 }
684 return value;
685 }
686
687 public static void setValueForValueBinding(String name, Object value) {
688 FacesContext context = FacesContext.getCurrentInstance();
689 ValueBinding valueBinding = context.getApplication().createValueBinding(name);
690 valueBinding.setValue(context, value);
691 }
692
693
694 public static boolean hasSelectedValue(List<SelectItem> items, Object value) {
695 for (SelectItem item : items) {
696 if (item.getValue().equals(value)) {
697 return true;
698 }
699 }
700 return false;
701 }
702
703 public static int getIntValue(ValueBinding valueBinding) {
704 return getAsInt(valueBinding.getValue(FacesContext.getCurrentInstance()));
705 }
706
707 private static int getAsInt(Object value) {
708 int result;
709 if (value instanceof Number) {
710 result = ((Number) value).intValue();
711 } else if (value instanceof String) {
712 result = Integer.parseInt((String) value);
713 } else {
714 throw new IllegalArgumentException("Can't convert " + value + " to int!");
715 }
716 return result;
717 }
718
719
720 public static String createPickerId(FacesContext facesContext, UIComponent component, String postfix) {
721
722 String id = getComponentId(facesContext, component);
723 return id + "_picker" + postfix;
724 }
725
726 public static String getComponentId(FacesContext facesContext, UIComponent component) {
727 String id = component.getId();
728
729
730
731
732 return id;
733 }
734
735
736
737
738
739
740 public static UIComponent provideLabel(FacesContext facesContext, UIComponent component) {
741 UIComponent label = component.getFacet(Facets.LABEL);
742
743
744 if (label == null) {
745 final Map attributes = component.getAttributes();
746 Object labelText = component.getValueBinding(Attributes.LABEL);
747 if (labelText == null) {
748 labelText = attributes.get(Attributes.LABEL);
749 }
750
751 if (labelText != null) {
752 Application application = FacesContext.getCurrentInstance().getApplication();
753 label = application.createComponent(UIOutput.COMPONENT_TYPE);
754 label.setRendererType(RendererTypes.LABEL);
755 String idprefix = ComponentUtils.getComponentId(facesContext, component);
756 label.setId(idprefix + "_" + Facets.LABEL);
757 label.setRendered(true);
758
759 if (labelText instanceof ValueBinding) {
760 label.setValueBinding(Attributes.VALUE, (ValueBinding) labelText);
761 } else {
762 label.getAttributes().put(Attributes.VALUE, labelText);
763 }
764
765 component.getFacets().put(Facets.LABEL, label);
766 }
767 }
768 return label;
769 }
770
771
772
773
774 @Deprecated
775 public static void setValidator(EditableValueHolder editableValueHolder, String validator) {
776 if (validator != null && editableValueHolder.getValidator() == null) {
777 if (UIComponentTag.isValueReference(validator)) {
778 MethodBinding methodBinding =
779 FacesContext.getCurrentInstance().getApplication().createMethodBinding(validator, VALIDATOR_ARGS);
780 editableValueHolder.setValidator(methodBinding);
781 }
782 }
783 }
784
785
786
787
788 @Deprecated
789 public static void setConverter(ValueHolder valueHolder, String converterId) {
790 if (converterId != null && valueHolder.getConverter() == null) {
791 final FacesContext facesContext = FacesContext.getCurrentInstance();
792 final Application application = facesContext.getApplication();
793 if (UIComponentTag.isValueReference(converterId)) {
794 ValueBinding valueBinding = application.createValueBinding(converterId);
795 if (valueHolder instanceof UIComponent) {
796 ((UIComponent) valueHolder).setValueBinding(Attributes.CONVERTER, valueBinding);
797 }
798 } else {
799 Converter converter = application.createConverter(converterId);
800 valueHolder.setConverter(converter);
801 }
802 }
803 }
804
805
806
807
808 @Deprecated
809 public static void setAction(ActionSource component, String action) {
810 if (action != null) {
811 if (UIComponentTag.isValueReference(action)) {
812 final FacesContext facesContext = FacesContext.getCurrentInstance();
813 final Application application = facesContext.getApplication();
814 MethodBinding binding = application.createMethodBinding(action, null);
815 component.setAction(binding);
816 } else {
817 component.setAction(new ConstantMethodBinding(action));
818 }
819 }
820 }
821
822
823
824
825 @Deprecated
826 public static void setActionListener(ActionSource command, String actionListener) {
827 final FacesContext facesContext = FacesContext.getCurrentInstance();
828 final Application application = facesContext.getApplication();
829 if (actionListener != null) {
830 if (UIComponentTag.isValueReference(actionListener)) {
831 MethodBinding binding
832 = application.createMethodBinding(actionListener, ACTION_LISTENER_ARGS);
833 command.setActionListener(binding);
834 } else {
835 throw new IllegalArgumentException(
836 "Must be a valueReference (actionListener): " + actionListener);
837 }
838 }
839 }
840
841
842
843
844 @Deprecated
845 public static void setValueChangeListener(EditableValueHolder valueHolder, String valueChangeListener) {
846 final FacesContext facesContext = FacesContext.getCurrentInstance();
847 final Application application = facesContext.getApplication();
848 if (valueChangeListener != null) {
849 if (UIComponentTag.isValueReference(valueChangeListener)) {
850 MethodBinding binding
851 = application.createMethodBinding(valueChangeListener, VALUE_CHANGE_LISTENER_ARGS);
852 valueHolder.setValueChangeListener(binding);
853 } else {
854 throw new IllegalArgumentException(
855 "Must be a valueReference (valueChangeListener): " + valueChangeListener);
856 }
857 }
858 }
859
860
861
862
863 @Deprecated
864 public static void setValueBinding(UIComponent component, String name, String state) {
865
866 if (state != null && UIComponentTag.isValueReference(state)) {
867 ValueBinding valueBinding = createValueBinding(state);
868 component.setValueBinding(name, valueBinding);
869 }
870 }
871
872
873
874
875 @Deprecated
876 public static String[] getMarkupBinding(FacesContext facesContext, SupportsMarkup component) {
877 ValueBinding vb = ((UIComponent) component).getValueBinding(Attributes.MARKUP);
878 if (vb != null) {
879 Object markups = vb.getValue(facesContext);
880 if (markups instanceof String[]) {
881 return (String[]) markups;
882 } else if (markups instanceof String) {
883 String[] strings = StringUtils.split((String) markups, ", ");
884 List<String> result = new ArrayList<String>(strings.length);
885 for (String string : strings) {
886 if (string.trim().length() != 0) {
887 result.add(string.trim());
888 }
889 }
890 return result.toArray(new String[result.size()]);
891 } else if (markups == null) {
892 return ArrayUtils.EMPTY_STRING_ARRAY;
893 } else {
894 return new String[]{markups.toString()};
895 }
896 }
897
898 return ArrayUtils.EMPTY_STRING_ARRAY;
899 }
900
901
902
903
904
905
906
907
908
909
910
911
912
913 public static UIComponent findComponent(UIComponent from, String relativeId) {
914 return FindComponentUtils.findComponent(from, relativeId);
915 }
916
917 public static String[] splitList(String renderers) {
918 return StringUtils.split(renderers, LIST_SEPARATOR_CHARS);
919 }
920
921 public static Object getConvertedValue(
922 FacesContext facesContext, UIComponent component, String stringValue) {
923 try {
924 Renderer renderer = getRenderer(facesContext, component);
925 if (renderer != null) {
926 if (component instanceof UISelectMany) {
927 final Object converted = renderer.getConvertedValue(facesContext, component, new String[]{stringValue});
928 return converted instanceof List ? ((List) converted).get(0) : ((Object[]) converted)[0];
929 } else {
930 return renderer.getConvertedValue(facesContext, component, stringValue);
931 }
932 } else if (component instanceof ValueHolder) {
933 Converter converter = ((ValueHolder) component).getConverter();
934 if (converter == null) {
935
936 ValueBinding vb = component.getValueBinding("value");
937 if (vb != null) {
938 Class valueType = vb.getType(facesContext);
939 if (valueType != null) {
940 converter = facesContext.getApplication().createConverter(valueType);
941 }
942 }
943 }
944 if (converter != null) {
945 converter.getAsObject(facesContext, component, stringValue);
946 }
947 }
948 } catch (Exception e) {
949 LOG.warn("Can't convert string value '" + stringValue + "'", e);
950 }
951 return stringValue;
952 }
953
954 public static Markup updateMarkup(UIComponent component, Markup markup) {
955 if (markup == null) {
956 markup = Markup.NULL;
957 }
958 if (ComponentUtils.getBooleanAttribute(component, Attributes.DISABLED)) {
959 markup = markup.add(Markup.DISABLED);
960 }
961 if (ComponentUtils.getBooleanAttribute(component, Attributes.READONLY)) {
962 markup = markup.add(Markup.READONLY);
963 }
964 if (component instanceof UIInput) {
965 UIInput input = (UIInput) component;
966
967 final FacesMessage.Severity maximumSeverity = ComponentUtils.getMaximumSeverity(input);
968 markup = markup.add(markupOfSeverity(maximumSeverity));
969
970 if (input.isRequired()) {
971 markup = markup.add(Markup.REQUIRED);
972 }
973 }
974 return markup;
975 }
976
977 public static Markup markupOfSeverity(FacesMessage.Severity maximumSeverity) {
978 if (FacesMessage.SEVERITY_FATAL.equals(maximumSeverity)) {
979 return Markup.FATAL;
980 } else if (FacesMessage.SEVERITY_ERROR.equals(maximumSeverity)) {
981 return Markup.ERROR;
982 } else if (FacesMessage.SEVERITY_WARN.equals(maximumSeverity)) {
983 return Markup.WARN;
984 } else if (FacesMessage.SEVERITY_INFO.equals(maximumSeverity)) {
985 return Markup.INFO;
986 }
987 return null;
988 }
989
990 public static void addCurrentMarkup(SupportsMarkup component, Markup markup) {
991 component.setCurrentMarkup(markup.add(component.getCurrentMarkup()));
992 }
993
994 public static boolean hasChildrenWithMessages(FacesContext facesContext, NamingContainer container) {
995 if (container instanceof UIComponent) {
996 String clientId = ((UIComponent) container).getClientId(facesContext);
997 for (Iterator ids = facesContext.getClientIdsWithMessages(); ids.hasNext();) {
998 String id = (String) ids.next();
999 if (id.startsWith(clientId)) {
1000 return true;
1001 }
1002 }
1003 }
1004 return false;
1005 }
1006
1007 public static FacesMessage.Severity getMaximumSeverityOfChildrenMessages(
1008 FacesContext facesContext, NamingContainer container) {
1009 if (container instanceof UIComponent) {
1010 String clientId = ((UIComponent) container).getClientId(facesContext);
1011 FacesMessage.Severity max = null;
1012 for (Iterator ids = facesContext.getClientIdsWithMessages(); ids.hasNext();) {
1013 String id = (String) ids.next();
1014 if (id != null && id.startsWith(clientId)) {
1015 final Iterator messages = facesContext.getMessages(id);
1016 while (messages.hasNext()) {
1017 FacesMessage message = (FacesMessage) messages.next();
1018 if (max == null || message.getSeverity().getOrdinal() > max.getOrdinal()) {
1019 max = message.getSeverity();
1020 }
1021 }
1022 }
1023 }
1024 return max;
1025 }
1026 return null;
1027 }
1028
1029 public static String[] getChildrenWithMessages(FacesContext facesContext, NamingContainer container) {
1030 if (container instanceof UIComponent) {
1031 List<String> clientIds = new ArrayList<String>();
1032 String clientId = ((UIComponent) container).getClientId(facesContext);
1033 for (Iterator ids = facesContext.getClientIdsWithMessages(); ids.hasNext();) {
1034 String id = (String) ids.next();
1035 if (id.startsWith(clientId)) {
1036 clientIds.add(id);
1037 }
1038 }
1039 return clientIds.toArray(new String[clientIds.size()]);
1040 }
1041 return ArrayUtils.EMPTY_STRING_ARRAY;
1042 }
1043
1044
1045
1046
1047
1048 public static void putDataAttributeWithPrefix(UIComponent component, String name, Object value) {
1049 if (name.startsWith("data-")) {
1050 putDataAttribute(component, name.substring(5), value);
1051 } else {
1052 LOG.error("The name must start with 'data-' but it doesn't: '" + name + "'");
1053 }
1054 }
1055
1056
1057
1058
1059
1060 public static void putDataAttribute(UIComponent component, Object name, Object value) {
1061 Map<Object, Object> map = (Map<Object, Object>) component.getAttributes().get(DATA_ATTRIBUTES_KEY);
1062 if (map == null) {
1063 map = new HashMap<Object, Object>();
1064 component.getAttributes().put(DATA_ATTRIBUTES_KEY, map);
1065 }
1066 map.put(name, value);
1067 }
1068
1069 public static Map<Object, Object> getDataAttributes(UIComponent component) {
1070 return (Map<Object, Object>) component.getAttributes().get(DATA_ATTRIBUTES_KEY);
1071 }
1072
1073 public static boolean invokeOnComponent(
1074 FacesContext context, UIComponent component, String clientId, javax.faces.component.ContextCallback callback) {
1075 String thisClientId = component.getClientId(context);
1076
1077 if (clientId.equals(thisClientId)) {
1078 callback.invokeContextCallback(context, component);
1079 return true;
1080 } else if (component instanceof NamingContainer) {
1081
1082
1083
1084
1085 if (clientId.startsWith(thisClientId)
1086 && (clientId.charAt(thisClientId.length()) == NamingContainer.SEPARATOR_CHAR)) {
1087 if (invokeOnComponentFacetsAndChildren(context, component, clientId, callback)) {
1088 return true;
1089 }
1090 }
1091 } else {
1092 if (invokeOnComponentFacetsAndChildren(context, component, clientId, callback)) {
1093 return true;
1094 }
1095 }
1096
1097 return false;
1098 }
1099
1100 private static boolean invokeOnComponentFacetsAndChildren(
1101 FacesContext context, UIComponent component, String clientId, javax.faces.component.ContextCallback callback) {
1102 for (java.util.Iterator<UIComponent> it = component.getFacetsAndChildren(); it.hasNext();) {
1103 UIComponent child = it.next();
1104 if (child.invokeOnComponent(context, clientId, callback)) {
1105 return true;
1106 }
1107 }
1108 return false;
1109 }
1110
1111 }