001 package org.apache.myfaces.tobago.util; 002 003 /* 004 * Licensed to the Apache Software Foundation (ASF) under one or more 005 * contributor license agreements. See the NOTICE file distributed with 006 * this work for additional information regarding copyright ownership. 007 * The ASF licenses this file to You under the Apache License, Version 2.0 008 * (the "License"); you may not use this file except in compliance with 009 * the License. You may obtain a copy of the License at 010 * 011 * http://www.apache.org/licenses/LICENSE-2.0 012 * 013 * Unless required by applicable law or agreed to in writing, software 014 * distributed under the License is distributed on an "AS IS" BASIS, 015 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 016 * See the License for the specific language governing permissions and 017 * limitations under the License. 018 */ 019 020 import org.apache.commons.lang.ArrayUtils; 021 import org.apache.commons.lang.StringUtils; 022 import org.apache.myfaces.tobago.component.Attributes; 023 import org.apache.myfaces.tobago.component.Facets; 024 import org.apache.myfaces.tobago.component.RendererTypes; 025 import org.apache.myfaces.tobago.component.SupportsMarkup; 026 import org.apache.myfaces.tobago.context.Markup; 027 import org.apache.myfaces.tobago.context.TransientStateHolder; 028 import org.apache.myfaces.tobago.el.ConstantMethodBinding; 029 import org.apache.myfaces.tobago.event.AbstractPopupActionListener; 030 import org.apache.myfaces.tobago.internal.component.AbstractUIForm; 031 import org.apache.myfaces.tobago.internal.component.AbstractUIInput; 032 import org.apache.myfaces.tobago.internal.component.AbstractUIPage; 033 import org.apache.myfaces.tobago.internal.component.AbstractUIPopup; 034 import org.apache.myfaces.tobago.internal.util.FindComponentUtils; 035 import org.apache.myfaces.tobago.renderkit.RendererBase; 036 import org.apache.myfaces.tobago.renderkit.html.StyleClasses; 037 import org.slf4j.Logger; 038 import org.slf4j.LoggerFactory; 039 040 import javax.faces.FactoryFinder; 041 import javax.faces.application.Application; 042 import javax.faces.application.FacesMessage; 043 import javax.faces.component.ActionSource; 044 import javax.faces.component.EditableValueHolder; 045 import javax.faces.component.NamingContainer; 046 import javax.faces.component.UICommand; 047 import javax.faces.component.UIComponent; 048 import javax.faces.component.UIGraphic; 049 import javax.faces.component.UIInput; 050 import javax.faces.component.UIOutput; 051 import javax.faces.component.UIParameter; 052 import javax.faces.component.UISelectMany; 053 import javax.faces.component.ValueHolder; 054 import javax.faces.context.FacesContext; 055 import javax.faces.convert.Converter; 056 import javax.faces.el.MethodBinding; 057 import javax.faces.el.ValueBinding; 058 import javax.faces.event.ActionEvent; 059 import javax.faces.event.ActionListener; 060 import javax.faces.event.ValueChangeEvent; 061 import javax.faces.model.SelectItem; 062 import javax.faces.render.RenderKit; 063 import javax.faces.render.RenderKitFactory; 064 import javax.faces.render.Renderer; 065 import javax.faces.webapp.UIComponentTag; 066 import javax.servlet.jsp.JspException; 067 import java.util.ArrayList; 068 import java.util.Iterator; 069 import java.util.List; 070 import java.util.Map; 071 072 public class ComponentUtils { 073 074 private static final Logger LOG = LoggerFactory.getLogger(ComponentUtils.class); 075 076 public static final String SUB_SEPARATOR = "::"; 077 078 private static final String RENDER_KEY_PREFIX 079 = "org.apache.myfaces.tobago.util.ComponentUtils.RendererKeyPrefix_"; 080 081 private static final String PAGE_KEY = "org.apache.myfaces.tobago.Page.Key"; 082 083 public static final Class[] ACTION_ARGS = {}; 084 public static final Class[] ACTION_LISTENER_ARGS = {ActionEvent.class}; 085 public static final Class[] VALUE_CHANGE_LISTENER_ARGS = {ValueChangeEvent.class}; 086 public static final Class[] VALIDATOR_ARGS = {FacesContext.class, UIComponent.class, Object.class}; 087 public static final String LIST_SEPARATOR_CHARS = ", "; 088 089 private ComponentUtils() { 090 } 091 092 public static boolean hasErrorMessages(FacesContext context) { 093 for (Iterator iter = context.getMessages(); iter.hasNext();) { 094 FacesMessage message = (FacesMessage) iter.next(); 095 if (FacesMessage.SEVERITY_ERROR.compareTo(message.getSeverity()) <= 0) { 096 return true; 097 } 098 } 099 return false; 100 } 101 102 public static boolean containsPopupActionListener(UICommand command) { 103 ActionListener[] actionListeners = command.getActionListeners(); 104 for (ActionListener actionListener : actionListeners) { 105 if (actionListener instanceof AbstractPopupActionListener) { 106 return true; 107 } 108 } 109 return false; 110 } 111 112 public static String getFacesMessageAsString(FacesContext facesContext, UIComponent component) { 113 Iterator messages = facesContext.getMessages( 114 component.getClientId(facesContext)); 115 StringBuilder stringBuffer = new StringBuilder(); 116 while (messages.hasNext()) { 117 FacesMessage message = (FacesMessage) messages.next(); 118 stringBuffer.append(message.getDetail()); 119 } 120 if (stringBuffer.length() > 0) { 121 return stringBuffer.toString(); 122 } else { 123 return null; 124 } 125 } 126 127 public static boolean isInPopup(UIComponent component) { 128 while (component != null) { 129 if (component instanceof AbstractUIPopup) { 130 return true; 131 } 132 component = component.getParent(); 133 } 134 return false; 135 } 136 137 public static void resetPage(FacesContext context) { 138 javax.faces.component.UIViewRoot view = context.getViewRoot(); 139 if (view != null) { 140 view.getAttributes().remove(PAGE_KEY); 141 } 142 } 143 144 @SuppressWarnings("unchecked") 145 public static AbstractUIPage findPage(FacesContext context, UIComponent component) { 146 javax.faces.component.UIViewRoot view = context.getViewRoot(); 147 if (view != null) { 148 TransientStateHolder stateHolder = (TransientStateHolder) view.getAttributes().get(PAGE_KEY); 149 if (stateHolder == null || stateHolder.isEmpty()) { 150 AbstractUIPage page = findPage(component); 151 stateHolder = new TransientStateHolder(page); 152 context.getViewRoot().getAttributes().put(PAGE_KEY, stateHolder); 153 } 154 return (AbstractUIPage) stateHolder.get(); 155 } else { 156 return findPage(component); 157 } 158 } 159 160 public static AbstractUIPage findPage(UIComponent component) { 161 while (component != null) { 162 if (component instanceof AbstractUIPage) { 163 return (AbstractUIPage) component; 164 } 165 component = component.getParent(); 166 } 167 return null; 168 } 169 170 public static AbstractUIPage findPage(FacesContext facesContext) { 171 return findPageBreadthFirst(facesContext.getViewRoot()); 172 } 173 174 private static AbstractUIPage findPageBreadthFirst(UIComponent component) { 175 for (Object o : component.getChildren()) { 176 UIComponent child = (UIComponent) o; 177 if (child instanceof AbstractUIPage) { 178 return (AbstractUIPage) child; 179 } 180 } 181 for (Object o : component.getChildren()) { 182 UIComponent child = (UIComponent) o; 183 AbstractUIPage result = findPageBreadthFirst(child); 184 if (result != null) { 185 return result; 186 } 187 } 188 return null; 189 } 190 191 192 public static AbstractUIForm findForm(UIComponent component) { 193 while (component != null) { 194 if (component instanceof AbstractUIForm) { 195 return (AbstractUIForm) component; 196 } 197 component = component.getParent(); 198 } 199 return null; 200 } 201 202 public static <T> T findAncestor(UIComponent component, Class<T> type) { 203 204 while (component != null) { 205 if (type.isAssignableFrom(component.getClass())) { 206 return (T) component; 207 } 208 component = component.getParent(); 209 } 210 return null; 211 } 212 213 /** 214 * Find all sub forms of a component, and collects it. 215 * It does not find sub forms of sub forms. 216 */ 217 public static List<AbstractUIForm> findSubForms(UIComponent component) { 218 List<AbstractUIForm> collect = new ArrayList<AbstractUIForm>(); 219 findSubForms(collect, component); 220 return collect; 221 } 222 223 @SuppressWarnings("unchecked") 224 private static void findSubForms(List<AbstractUIForm> collect, UIComponent component) { 225 Iterator<UIComponent> kids = component.getFacetsAndChildren(); 226 while (kids.hasNext()) { 227 UIComponent child = kids.next(); 228 if (child instanceof AbstractUIForm) { 229 collect.add((AbstractUIForm) child); 230 } else { 231 findSubForms(collect, child); 232 } 233 } 234 } 235 236 /** 237 * Searches the component tree beneath the component and return the first component matching the type. 238 */ 239 public static <T extends UIComponent> T findDescendant(UIComponent component, Class<T> type) { 240 241 for (UIComponent child : (List<UIComponent>) component.getChildren()) { 242 if (type.isAssignableFrom(child.getClass())) { 243 return (T) child; 244 } 245 final T descendant = findDescendant(child, type); 246 if (descendant != null) { 247 return descendant; 248 } 249 } 250 return null; 251 } 252 253 /** 254 * Looks for the attribute "for" in the component. If there is any 255 * search for the component which is referenced by the "for" attribute, 256 * and return their clientId. 257 * If there is no "for" attribute, return the "clientId" of the parent 258 * (if it has a parent). This is useful for labels. 259 */ 260 public static String findClientIdFor(UIComponent component, FacesContext facesContext) { 261 UIComponent forComponent = findFor(component); 262 if (forComponent != null) { 263 String clientId = forComponent.getClientId(facesContext); 264 if (LOG.isDebugEnabled()) { 265 LOG.debug("found clientId: '" + clientId + "'"); 266 } 267 return clientId; 268 } 269 if (LOG.isDebugEnabled()) { 270 LOG.debug("found no clientId"); 271 } 272 return null; 273 } 274 275 public static UIComponent findFor(UIComponent component) { 276 String forValue = (String) component.getAttributes().get(Attributes.FOR); 277 if (forValue == null) { 278 return component.getParent(); 279 } 280 return component.findComponent(forValue); 281 } 282 283 /** 284 * Looks for the attribute "for" of the component. 285 * In case that the value is equals to "@auto" the children of the parent will be 286 * checked if they are a UIInput. The "id" of the first one will be used to reset the "for" 287 * attribute of the component. 288 */ 289 public static void evaluateAutoFor(UIComponent component) { 290 String forComponent = (String) component.getAttributes().get(Attributes.FOR); 291 if (LOG.isDebugEnabled()) { 292 LOG.debug("for = '" + forComponent + "'"); 293 } 294 if ("@auto".equals(forComponent)) { 295 for (Object object : component.getParent().getChildren()) { 296 UIComponent child = (UIComponent) object; 297 if (child instanceof UIInput) { 298 forComponent = child.getId(); 299 component.getAttributes().put(Attributes.FOR, forComponent); 300 break; 301 } 302 } 303 } 304 } 305 306 public static boolean isInActiveForm(UIComponent component) { 307 while (component != null) { 308 if (component instanceof AbstractUIForm) { 309 AbstractUIForm form = (AbstractUIForm) component; 310 if (form.isSubmitted()) { 311 return true; 312 } 313 } 314 component = component.getParent(); 315 } 316 return false; 317 } 318 319 public static FacesMessage.Severity getMaximumSeverity(UIComponent component) { 320 final boolean invalid = component instanceof javax.faces.component.UIInput 321 && !((javax.faces.component.UIInput) component).isValid(); 322 FacesMessage.Severity max = invalid ? FacesMessage.SEVERITY_ERROR : null; 323 FacesContext facesContext = FacesContext.getCurrentInstance(); 324 final Iterator messages = facesContext.getMessages(component.getClientId(facesContext)); 325 while (messages.hasNext()) { 326 FacesMessage message = (FacesMessage) messages.next(); 327 if (max == null || message.getSeverity().getOrdinal() > max.getOrdinal()) { 328 max = message.getSeverity(); 329 } 330 } 331 return max; 332 } 333 334 public static boolean isError(javax.faces.component.UIInput uiInput) { 335 FacesContext facesContext = FacesContext.getCurrentInstance(); 336 return !uiInput.isValid() 337 || facesContext.getMessages(uiInput.getClientId(facesContext)).hasNext(); 338 } 339 340 public static boolean isError(UIComponent component) { 341 if (component instanceof AbstractUIInput) { 342 return isError((AbstractUIInput) component); 343 } 344 return false; 345 } 346 347 public static boolean isOutputOnly(UIComponent component) { 348 return getBooleanAttribute(component, Attributes.DISABLED) 349 || getBooleanAttribute(component, Attributes.READONLY); 350 } 351 352 public static boolean mayValidate(UIComponent component) { 353 return !isOutputOnly(component) 354 && ComponentUtils.isInActiveForm(component); 355 } 356 357 public static boolean mayUpdateModel(UIComponent component) { 358 return mayValidate(component); 359 } 360 361 public static boolean getBooleanAttribute(UIComponent component, String name) { 362 363 Object bool = component.getAttributes().get(name); 364 if (bool == null) { 365 return false; 366 } 367 if (bool instanceof ValueBinding) { 368 bool = ((ValueBinding) bool).getValue(FacesContext.getCurrentInstance()); 369 } 370 if (bool instanceof Boolean) { 371 return (Boolean) bool; 372 } else if (bool instanceof String) { 373 LOG.warn("Searching for a boolean, but find a String. Should not happen. " 374 + "attribute: '" + name + "' id: '" + component.getClientId(FacesContext.getCurrentInstance()) 375 + "' comp: '" + component + "'"); 376 return Boolean.valueOf((String) bool); 377 } else { 378 LOG.warn("Unknown type '" + bool.getClass().getName() 379 + "' for boolean attribute: " + name + " id: " + component.getClientId(FacesContext.getCurrentInstance()) 380 + " comp: " + component); 381 return false; 382 } 383 } 384 385 386 387 public static ValueBinding createValueBinding(String value) { 388 return FacesContext.getCurrentInstance().getApplication().createValueBinding(value); 389 } 390 391 /** 392 * @deprecated Please define a {@link Markup} and set it to the component with 393 * {@link SupportsMarkup#setMarkup(Markup markup)} before the rendering phase. 394 */ 395 @Deprecated 396 public static void setStyleClasses(UIComponent component, String styleClasses) { 397 if (styleClasses != null) { 398 if (UIComponentTag.isValueReference(styleClasses)) { 399 component.setValueBinding(Attributes.STYLE_CLASS, createValueBinding(styleClasses)); 400 } else { 401 String[] classes = splitList(styleClasses); 402 if (classes.length > 0) { 403 StyleClasses styles = StyleClasses.ensureStyleClasses(component); 404 for (String clazz : classes) { 405 styles.addFullQualifiedClass(clazz); 406 } 407 } 408 } 409 } 410 } 411 412 /** 413 * @deprecated since 1.5.0 414 */ 415 @Deprecated 416 public static void setMarkup(UIComponent markupComponent, String markup) { 417 if (markup != null) { 418 if (markupComponent instanceof SupportsMarkup) { 419 if (UIComponentTag.isValueReference(markup)) { 420 markupComponent.setValueBinding(Attributes.MARKUP, createValueBinding(markup)); 421 } else { 422 ((SupportsMarkup) markupComponent).setMarkup(Markup.valueOf(markup)); 423 } 424 } else { 425 LOG.error("Component did not support Markup " + markupComponent.getClass().getName()); 426 } 427 } 428 } 429 430 public static Object getAttribute(UIComponent component, String name) { 431 Object value = component.getAttributes().get(name); 432 if (value instanceof ValueBinding) { 433 value = ((ValueBinding) value).getValue(FacesContext.getCurrentInstance()); 434 } 435 return value; 436 } 437 438 public static Object getObjectAttribute(UIComponent component, String name) { 439 return getAttribute(component, name); 440 } 441 442 public static String getStringAttribute(UIComponent component, String name) { 443 return (String) getAttribute(component, name); 444 } 445 446 public static int getIntAttribute(UIComponent component, String name) { 447 return getIntAttribute(component, name, 0); 448 } 449 450 public static int getIntAttribute(UIComponent component, String name, 451 int defaultValue) { 452 Object integer = component.getAttributes().get(name); 453 if (integer instanceof Number) { 454 return ((Number) integer).intValue(); 455 } else if (integer instanceof String) { 456 try { 457 return Integer.parseInt((String) integer); 458 } catch (NumberFormatException e) { 459 LOG.warn("Can't parse number from string : \"" + integer + "\"!"); 460 return defaultValue; 461 } 462 } else if (integer == null) { 463 return defaultValue; 464 } else { 465 LOG.warn("Unknown type '" + integer.getClass().getName() 466 + "' for integer attribute: " + name + " comp: " + component); 467 return defaultValue; 468 } 469 } 470 471 public static Character getCharacterAttribute(UIComponent component, String name) { 472 Object character = component.getAttributes().get(name); 473 if (character == null) { 474 return null; 475 } else if (character instanceof Character) { 476 return ((Character) character); 477 } else if (character instanceof String) { 478 String asString = ((String) character); 479 return asString.length() > 0 ? asString.charAt(0) : null; 480 } else { 481 LOG.warn("Unknown type '" + character.getClass().getName() 482 + "' for integer attribute: " + name + " comp: " + component); 483 return null; 484 } 485 } 486 487 public static boolean isFacetOf(UIComponent component, UIComponent parent) { 488 for (Object o : parent.getFacets().keySet()) { 489 UIComponent facet = parent.getFacet((String) o); 490 if (component.equals(facet)) { 491 return true; 492 } 493 } 494 return false; 495 } 496 497 public static RendererBase getRenderer(FacesContext facesContext, UIComponent component) { 498 return getRenderer(facesContext, component.getFamily(), component.getRendererType()); 499 } 500 501 public static RendererBase getRenderer(FacesContext facesContext, String family, String rendererType) { 502 if (rendererType == null) { 503 return null; 504 } 505 506 Map<String, Object> requestMap = (Map<String, Object>) facesContext.getExternalContext().getRequestMap(); 507 StringBuilder key = new StringBuilder(RENDER_KEY_PREFIX); 508 key.append(rendererType); 509 RendererBase renderer = (RendererBase) requestMap.get(key.toString()); 510 511 if (renderer == null) { 512 Renderer myRenderer = getRendererInternal(facesContext, family, rendererType); 513 if (myRenderer instanceof RendererBase) { 514 requestMap.put(key.toString(), myRenderer); 515 renderer = (RendererBase) myRenderer; 516 } else { 517 return null; 518 } 519 } 520 return renderer; 521 } 522 523 524 private static Renderer getRendererInternal(FacesContext facesContext, String family, String rendererType) { 525 RenderKitFactory rkFactory = (RenderKitFactory) FactoryFinder.getFactory(FactoryFinder.RENDER_KIT_FACTORY); 526 RenderKit renderKit = rkFactory.getRenderKit(facesContext, facesContext.getViewRoot().getRenderKitId()); 527 Renderer myRenderer = renderKit.getRenderer(family, rendererType); 528 return myRenderer; 529 } 530 531 public static Object findParameter(UIComponent component, String name) { 532 for (Object o : component.getChildren()) { 533 UIComponent child = (UIComponent) o; 534 if (child instanceof UIParameter) { 535 UIParameter parameter = (UIParameter) child; 536 if (LOG.isDebugEnabled()) { 537 LOG.debug("Select name='" + parameter.getName() + "'"); 538 LOG.debug("Select value='" + parameter.getValue() + "'"); 539 } 540 if (name.equals(parameter.getName())) { 541 return parameter.getValue(); 542 } 543 } 544 } 545 return null; 546 } 547 548 public static ActionListener createActionListener(String type) 549 throws JspException { 550 try { 551 ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); 552 if (classLoader == null) { 553 classLoader = type.getClass().getClassLoader(); 554 } 555 Class clazz = classLoader.loadClass(type); 556 return (ActionListener) clazz.newInstance(); 557 } catch (Exception e) { 558 if (LOG.isDebugEnabled()) { 559 LOG.debug("type=" + type, e); 560 } 561 throw new JspException(e); 562 } 563 } 564 565 public static UIGraphic getFirstGraphicChild(UIComponent component) { 566 UIGraphic graphic = null; 567 for (Object o : component.getChildren()) { 568 UIComponent uiComponent = (UIComponent) o; 569 if (uiComponent instanceof UIGraphic) { 570 graphic = (UIGraphic) uiComponent; 571 break; 572 } 573 } 574 return graphic; 575 } 576 577 public static boolean isHoverEnabled(UIComponent component) { 578 return ComponentUtils.getBooleanAttribute(component, Attributes.HOVER); 579 } 580 581 public static UIOutput getFirstNonGraphicChild(UIComponent component) { 582 for (UIComponent child : (List<UIComponent>) component.getChildren()) { 583 if (child instanceof UIOutput) { 584 return (UIOutput) child; 585 } 586 } 587 return null; 588 } 589 590 /** 591 * @deprecated since 1.5.0 592 */ 593 @Deprecated 594 public static void setIntegerSizeProperty(UIComponent component, String name, String value) { 595 if (value != null) { 596 if (UIComponentTag.isValueReference(value)) { 597 component.setValueBinding(name, createValueBinding(value)); 598 } else { 599 value = removePx(value); 600 component.getAttributes().put(name, new Integer(value)); 601 } 602 } 603 } 604 605 public static String removePx(String value) { 606 if (value != null && value.endsWith("px")) { 607 value = value.substring(0, value.length() - 2); 608 } 609 return value; 610 } 611 612 public static void setValueForValueBinding(String name, Object value) { 613 FacesContext context = FacesContext.getCurrentInstance(); 614 ValueBinding valueBinding = context.getApplication().createValueBinding(name); 615 valueBinding.setValue(context, value); 616 } 617 618 619 public static boolean hasSelectedValue(List<SelectItem> items, Object value) { 620 for (SelectItem item : items) { 621 if (item.getValue().equals(value)) { 622 return true; 623 } 624 } 625 return false; 626 } 627 628 public static int getIntValue(ValueBinding valueBinding) { 629 return getAsInt(valueBinding.getValue(FacesContext.getCurrentInstance())); 630 } 631 632 private static int getAsInt(Object value) { 633 int result; 634 if (value instanceof Number) { 635 result = ((Number) value).intValue(); 636 } else if (value instanceof String) { 637 result = Integer.parseInt((String) value); 638 } else { 639 throw new IllegalArgumentException("Can't convert " + value + " to int!"); 640 } 641 return result; 642 } 643 644 645 public static String createPickerId(FacesContext facesContext, UIComponent component, String postfix) { 646 //String id = component.getId(); 647 String id = getComponentId(facesContext, component); 648 return id + "_picker" + postfix; 649 } 650 651 public static String getComponentId(FacesContext facesContext, UIComponent component) { 652 String id = component.getId(); 653 //if (id == null) { 654 // XXX What is this? 655 // id = component.getClientId(facesContext).substring(id.lastIndexOf('_')); 656 //} 657 return id; 658 } 659 660 /** 661 * Checks if the Component has a label facet and if not creates one with the label attribute. 662 * 663 * Todo: check if this method should be set to deprecated. 664 */ 665 public static UIComponent provideLabel(FacesContext facesContext, UIComponent component) { 666 UIComponent label = component.getFacet(Facets.LABEL); 667 668 669 if (label == null) { 670 final Map attributes = component.getAttributes(); 671 Object labelText = component.getValueBinding(Attributes.LABEL); 672 if (labelText == null) { 673 labelText = attributes.get(Attributes.LABEL); 674 } 675 676 if (labelText != null) { 677 Application application = FacesContext.getCurrentInstance().getApplication(); 678 label = application.createComponent(UIOutput.COMPONENT_TYPE); 679 label.setRendererType(RendererTypes.LABEL); 680 String idprefix = ComponentUtils.getComponentId(facesContext, component); 681 label.setId(idprefix + "_" + Facets.LABEL); 682 label.setRendered(true); 683 684 if (labelText instanceof ValueBinding) { 685 label.setValueBinding(Attributes.VALUE, (ValueBinding) labelText); 686 } else { 687 label.getAttributes().put(Attributes.VALUE, labelText); 688 } 689 690 component.getFacets().put(Facets.LABEL, label); 691 } 692 } 693 return label; 694 } 695 696 /** 697 * @deprecated since 1.5.0 698 */ 699 @Deprecated 700 public static void setValidator(EditableValueHolder editableValueHolder, String validator) { 701 if (validator != null && editableValueHolder.getValidator() == null) { 702 if (UIComponentTag.isValueReference(validator)) { 703 MethodBinding methodBinding = 704 FacesContext.getCurrentInstance().getApplication().createMethodBinding(validator, VALIDATOR_ARGS); 705 editableValueHolder.setValidator(methodBinding); 706 } 707 } 708 } 709 710 /** 711 * @deprecated since 1.5.0 712 */ 713 @Deprecated 714 public static void setConverter(ValueHolder valueHolder, String converterId) { 715 if (converterId != null && valueHolder.getConverter() == null) { 716 final FacesContext facesContext = FacesContext.getCurrentInstance(); 717 final Application application = facesContext.getApplication(); 718 if (UIComponentTag.isValueReference(converterId)) { 719 ValueBinding valueBinding = application.createValueBinding(converterId); 720 if (valueHolder instanceof UIComponent) { 721 ((UIComponent) valueHolder).setValueBinding(Attributes.CONVERTER, valueBinding); 722 } 723 } else { 724 Converter converter = application.createConverter(converterId); 725 valueHolder.setConverter(converter); 726 } 727 } 728 } 729 730 /** 731 * @deprecated since 1.5.0 732 */ 733 @Deprecated 734 public static void setAction(ActionSource component, String action) { 735 if (action != null) { 736 if (UIComponentTag.isValueReference(action)) { 737 final FacesContext facesContext = FacesContext.getCurrentInstance(); 738 final Application application = facesContext.getApplication(); 739 MethodBinding binding = application.createMethodBinding(action, null); 740 component.setAction(binding); 741 } else { 742 component.setAction(new ConstantMethodBinding(action)); 743 } 744 } 745 } 746 747 /** 748 * @deprecated since 1.5.0 749 */ 750 @Deprecated 751 public static void setActionListener(ActionSource command, String actionListener) { 752 final FacesContext facesContext = FacesContext.getCurrentInstance(); 753 final Application application = facesContext.getApplication(); 754 if (actionListener != null) { 755 if (UIComponentTag.isValueReference(actionListener)) { 756 MethodBinding binding 757 = application.createMethodBinding(actionListener, ACTION_LISTENER_ARGS); 758 command.setActionListener(binding); 759 } else { 760 throw new IllegalArgumentException( 761 "Must be a valueReference (actionListener): " + actionListener); 762 } 763 } 764 } 765 766 /** 767 * @deprecated since 1.5.0 768 */ 769 @Deprecated 770 public static void setValueChangeListener(EditableValueHolder valueHolder, String valueChangeListener) { 771 final FacesContext facesContext = FacesContext.getCurrentInstance(); 772 final Application application = facesContext.getApplication(); 773 if (valueChangeListener != null) { 774 if (UIComponentTag.isValueReference(valueChangeListener)) { 775 MethodBinding binding 776 = application.createMethodBinding(valueChangeListener, VALUE_CHANGE_LISTENER_ARGS); 777 valueHolder.setValueChangeListener(binding); 778 } else { 779 throw new IllegalArgumentException( 780 "Must be a valueReference (valueChangeListener): " + valueChangeListener); 781 } 782 } 783 } 784 785 /** 786 * @deprecated since 1.5.0 787 */ 788 @Deprecated 789 public static void setValueBinding(UIComponent component, String name, String state) { 790 // TODO: check, if it is an writeable object 791 if (state != null && UIComponentTag.isValueReference(state)) { 792 ValueBinding valueBinding = createValueBinding(state); 793 component.setValueBinding(name, valueBinding); 794 } 795 } 796 797 /** 798 * @deprecated since 1.5 799 */ 800 @Deprecated 801 public static String[] getMarkupBinding(FacesContext facesContext, SupportsMarkup component) { 802 ValueBinding vb = ((UIComponent) component).getValueBinding(Attributes.MARKUP); 803 if (vb != null) { 804 Object markups = vb.getValue(facesContext); 805 if (markups instanceof String[]) { 806 return (String[]) markups; 807 } else if (markups instanceof String) { 808 String[] strings = StringUtils.split((String) markups, ", "); 809 List<String> result = new ArrayList<String>(strings.length); 810 for (String string : strings) { 811 if (string.trim().length() != 0) { 812 result.add(string.trim()); 813 } 814 } 815 return result.toArray(new String[result.size()]); 816 } else if (markups == null) { 817 return ArrayUtils.EMPTY_STRING_ARRAY; 818 } else { 819 return new String[]{markups.toString()}; 820 } 821 } 822 823 return ArrayUtils.EMPTY_STRING_ARRAY; 824 } 825 826 /** 827 * The search depends on the number of colons in the relativeId: 828 * <dl> 829 * <dd>colonCount == 0</dd> 830 * <dt>fully relative</dt> 831 * <dd>colonCount == 1</dd> 832 * <dt>absolute (still normal findComponent syntax)</dt> 833 * <dd>colonCount > 1</dd> 834 * <dt>for each extra colon after 1, go up a naming container</dt> 835 * </dl> 836 * (to the view root, if naming containers run out) 837 */ 838 public static UIComponent findComponent(UIComponent from, String relativeId) { 839 return FindComponentUtils.findComponent(from, relativeId); 840 } 841 842 public static String[] splitList(String renderers) { 843 return StringUtils.split(renderers, LIST_SEPARATOR_CHARS); 844 } 845 846 public static Object getConvertedValue( 847 FacesContext facesContext, UIComponent component, String stringValue) { 848 try { 849 Renderer renderer = getRenderer(facesContext, component); 850 if (renderer != null) { 851 if (component instanceof UISelectMany) { 852 final Object converted = renderer.getConvertedValue(facesContext, component, new String[]{stringValue}); 853 return ((Object[]) converted)[0]; 854 } else { 855 return renderer.getConvertedValue(facesContext, component, stringValue); 856 } 857 } else if (component instanceof ValueHolder) { 858 Converter converter = ((ValueHolder) component).getConverter(); 859 if (converter == null) { 860 //Try to find out by value binding 861 ValueBinding vb = component.getValueBinding("value"); 862 if (vb != null) { 863 Class valueType = vb.getType(facesContext); 864 if (valueType != null) { 865 converter = facesContext.getApplication().createConverter(valueType); 866 } 867 } 868 } 869 if (converter != null) { 870 converter.getAsObject(facesContext, component, stringValue); 871 } 872 } 873 } catch (Exception e) { 874 LOG.warn("Can't convert string value '" + stringValue + "'", e); 875 } 876 return stringValue; 877 } 878 879 public static Markup updateMarkup(UIComponent component, Markup markup) { 880 if (markup == null) { 881 markup = Markup.NULL; 882 } 883 if (ComponentUtils.getBooleanAttribute(component, Attributes.DISABLED)) { 884 markup = markup.add(Markup.DISABLED); 885 } 886 if (ComponentUtils.getBooleanAttribute(component, Attributes.READONLY)) { 887 markup = markup.add(Markup.READONLY); 888 } 889 if (component instanceof UIInput) { 890 UIInput input = (UIInput) component; 891 892 final FacesMessage.Severity maximumSeverity = ComponentUtils.getMaximumSeverity(input); 893 markup = markup.add(markupOfSeverity(maximumSeverity)); 894 895 if (input.isRequired()) { 896 markup = markup.add(Markup.REQUIRED); 897 } 898 } 899 return markup; 900 } 901 902 public static Markup markupOfSeverity(FacesMessage.Severity maximumSeverity) { 903 if (FacesMessage.SEVERITY_FATAL.equals(maximumSeverity)) { 904 return Markup.FATAL; 905 } else if (FacesMessage.SEVERITY_ERROR.equals(maximumSeverity)) { 906 return Markup.ERROR; 907 } else if (FacesMessage.SEVERITY_WARN.equals(maximumSeverity)) { 908 return Markup.WARN; 909 } else if (FacesMessage.SEVERITY_INFO.equals(maximumSeverity)) { 910 return Markup.INFO; 911 } 912 return null; 913 } 914 915 public static boolean hasChildrenWithMessages(FacesContext facesContext, NamingContainer container) { 916 if (container instanceof UIComponent) { 917 String clientId = ((UIComponent) container).getClientId(facesContext); 918 for (Iterator ids = facesContext.getClientIdsWithMessages(); ids.hasNext();) { 919 String id = (String) ids.next(); 920 if (id.startsWith(clientId)) { 921 return true; 922 } 923 } 924 } 925 return false; 926 } 927 928 public static FacesMessage.Severity getMaximumSeverityOfChildrenMessages( 929 FacesContext facesContext, NamingContainer container) { 930 if (container instanceof UIComponent) { 931 String clientId = ((UIComponent) container).getClientId(facesContext); 932 FacesMessage.Severity max = null; 933 for (Iterator ids = facesContext.getClientIdsWithMessages(); ids.hasNext();) { 934 String id = (String) ids.next(); 935 if (id != null && id.startsWith(clientId)) { 936 final Iterator messages = facesContext.getMessages(id); 937 while (messages.hasNext()) { 938 FacesMessage message = (FacesMessage) messages.next(); 939 if (max == null || message.getSeverity().getOrdinal() > max.getOrdinal()) { 940 max = message.getSeverity(); 941 } 942 } 943 } 944 } 945 return max; 946 } 947 return null; 948 } 949 950 public static String[] getChildrenWithMessages(FacesContext facesContext, NamingContainer container) { 951 if (container instanceof UIComponent) { 952 List<String> clientIds = new ArrayList<String>(); 953 String clientId = ((UIComponent) container).getClientId(facesContext); 954 for (Iterator ids = facesContext.getClientIdsWithMessages(); ids.hasNext();) { 955 String id = (String) ids.next(); 956 if (id.startsWith(clientId)) { 957 clientIds.add(id); 958 } 959 } 960 return clientIds.toArray(new String[clientIds.size()]); 961 } 962 return ArrayUtils.EMPTY_STRING_ARRAY; 963 } 964 }