001 package org.apache.myfaces.tobago.component; 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.StringUtils; 021 import org.apache.commons.lang.math.NumberUtils; 022 import org.apache.commons.logging.Log; 023 import org.apache.commons.logging.LogFactory; 024 import org.apache.myfaces.tobago.TobagoConstants; 025 import org.apache.myfaces.tobago.context.TransientStateHolder; 026 import org.apache.myfaces.tobago.el.ConstantMethodBinding; 027 import org.apache.myfaces.tobago.event.PopupActionListener; 028 import org.apache.myfaces.tobago.event.SheetStateChangeEvent; 029 import org.apache.myfaces.tobago.renderkit.LayoutableRendererBase; 030 import org.apache.myfaces.tobago.renderkit.html.StyleClasses; 031 import org.apache.myfaces.tobago.util.Callback; 032 import org.apache.myfaces.tobago.util.RangeParser; 033 import org.apache.myfaces.tobago.util.TobagoCallback; 034 035 import javax.faces.FactoryFinder; 036 import javax.faces.application.Application; 037 import javax.faces.application.FacesMessage; 038 import javax.faces.component.ActionSource; 039 import javax.faces.component.EditableValueHolder; 040 import javax.faces.component.NamingContainer; 041 import javax.faces.component.UICommand; 042 import javax.faces.component.UIComponent; 043 import javax.faces.component.UIGraphic; 044 import javax.faces.component.UIOutput; 045 import javax.faces.component.UIParameter; 046 import javax.faces.component.UISelectItem; 047 import javax.faces.component.UISelectItems; 048 import javax.faces.component.ValueHolder; 049 import javax.faces.context.FacesContext; 050 import javax.faces.convert.Converter; 051 import javax.faces.el.MethodBinding; 052 import javax.faces.el.ValueBinding; 053 import javax.faces.event.ActionEvent; 054 import javax.faces.event.ActionListener; 055 import javax.faces.event.PhaseId; 056 import javax.faces.event.ValueChangeEvent; 057 import javax.faces.model.SelectItem; 058 import javax.faces.render.RenderKit; 059 import javax.faces.render.RenderKitFactory; 060 import javax.faces.render.Renderer; 061 import javax.faces.webapp.UIComponentTag; 062 import javax.servlet.jsp.JspException; 063 import java.util.ArrayList; 064 import java.util.Arrays; 065 import java.util.Collection; 066 import java.util.Collections; 067 import java.util.Iterator; 068 import java.util.List; 069 import java.util.Map; 070 import java.util.Set; 071 072 import static org.apache.myfaces.tobago.TobagoConstants.ATTR_ACTION_LINK; 073 import static org.apache.myfaces.tobago.TobagoConstants.ATTR_ACTION_ONCLICK; 074 import static org.apache.myfaces.tobago.TobagoConstants.ATTR_ALIGN; 075 import static org.apache.myfaces.tobago.TobagoConstants.ATTR_CONVERTER; 076 import static org.apache.myfaces.tobago.TobagoConstants.ATTR_CREATE_SPAN; 077 import static org.apache.myfaces.tobago.TobagoConstants.ATTR_DISABLED; 078 import static org.apache.myfaces.tobago.TobagoConstants.ATTR_ESCAPE; 079 import static org.apache.myfaces.tobago.TobagoConstants.ATTR_FOR; 080 import static org.apache.myfaces.tobago.TobagoConstants.ATTR_HOVER; 081 import static org.apache.myfaces.tobago.TobagoConstants.ATTR_LABEL; 082 import static org.apache.myfaces.tobago.TobagoConstants.ATTR_MARKUP; 083 import static org.apache.myfaces.tobago.TobagoConstants.ATTR_READONLY; 084 import static org.apache.myfaces.tobago.TobagoConstants.ATTR_RENDERED_PARTIALLY; 085 import static org.apache.myfaces.tobago.TobagoConstants.ATTR_RENDER_RANGE; 086 import static org.apache.myfaces.tobago.TobagoConstants.ATTR_RENDER_RANGE_EXTERN; 087 import static org.apache.myfaces.tobago.TobagoConstants.ATTR_SORTABLE; 088 import static org.apache.myfaces.tobago.TobagoConstants.ATTR_STYLE_CLASS; 089 import static org.apache.myfaces.tobago.TobagoConstants.ATTR_VALUE; 090 import static org.apache.myfaces.tobago.TobagoConstants.COMMAND_TYPE_NAVIGATE; 091 import static org.apache.myfaces.tobago.TobagoConstants.COMMAND_TYPE_RESET; 092 import static org.apache.myfaces.tobago.TobagoConstants.COMMAND_TYPE_SCRIPT; 093 import static org.apache.myfaces.tobago.TobagoConstants.FACET_ITEMS; 094 import static org.apache.myfaces.tobago.TobagoConstants.FACET_LABEL; 095 import static org.apache.myfaces.tobago.TobagoConstants.RENDERER_TYPE_LABEL; 096 import static org.apache.myfaces.tobago.TobagoConstants.RENDERER_TYPE_OUT; 097 import static org.apache.myfaces.tobago.TobagoConstants.RENDERER_TYPE_SELECT_BOOLEAN_CHECKBOX; 098 import static org.apache.myfaces.tobago.TobagoConstants.RENDERER_TYPE_SELECT_ONE_RADIO; 099 100 public class ComponentUtil { 101 102 private static final Log LOG = LogFactory.getLog(ComponentUtil.class); 103 104 private static final String RENDER_KEY_PREFIX 105 = "org.apache.myfaces.tobago.component.ComponentUtil.RendererKeyPrefix_"; 106 107 public static final Class[] ACTION_ARGS = {}; 108 public static final Class[] ACTION_LISTENER_ARGS = {ActionEvent.class}; 109 public static final Class[] VALUE_CHANGE_LISTENER_ARGS = {ValueChangeEvent.class}; 110 public static final Class[] VALIDATOR_ARGS = {FacesContext.class, UIComponent.class, Object.class}; 111 112 private ComponentUtil() { 113 } 114 115 116 public static boolean hasErrorMessages(FacesContext context) { 117 for (Iterator iter = context.getMessages(); iter.hasNext();) { 118 FacesMessage message = (FacesMessage) iter.next(); 119 if (FacesMessage.SEVERITY_ERROR.compareTo(message.getSeverity()) <= 0) { 120 return true; 121 } 122 } 123 return false; 124 } 125 126 public static boolean containsPopupActionListener(UICommand command) { 127 ActionListener[] actionListeners = command.getActionListeners(); 128 for (ActionListener actionListener : actionListeners) { 129 if (actionListener instanceof PopupActionListener) { 130 return true; 131 } 132 } 133 return false; 134 } 135 136 public static String getFacesMessageAsString(FacesContext facesContext, UIComponent component) { 137 Iterator messages = facesContext.getMessages( 138 component.getClientId(facesContext)); 139 StringBuilder stringBuffer = new StringBuilder(); 140 while (messages.hasNext()) { 141 FacesMessage message = (FacesMessage) messages.next(); 142 stringBuffer.append(message.getDetail()); 143 } 144 if (stringBuffer.length() > 0) { 145 return stringBuffer.toString(); 146 } else { 147 return null; 148 } 149 } 150 151 public static boolean isInPopup(UIComponent component) { 152 while (component != null) { 153 if (component instanceof UIPopup) { 154 return true; 155 } 156 component = component.getParent(); 157 } 158 return false; 159 } 160 161 public static void resetPage(FacesContext context) { 162 javax.faces.component.UIViewRoot view = context.getViewRoot(); 163 if (view != null) { 164 view.getAttributes().remove(UIPage.COMPONENT_TYPE); 165 } 166 } 167 168 @SuppressWarnings(value = "unchecked") 169 public static UIPage findPage(FacesContext context, UIComponent component) { 170 javax.faces.component.UIViewRoot view = context.getViewRoot(); 171 if (view != null) { 172 TransientStateHolder stateHolder = (TransientStateHolder) view.getAttributes().get(UIPage.COMPONENT_TYPE); 173 if (stateHolder == null || stateHolder.isEmpty()) { 174 UIPage page = findPage(component); 175 stateHolder = new TransientStateHolder(page); 176 context.getViewRoot().getAttributes().put(UIPage.COMPONENT_TYPE, stateHolder); 177 } 178 return (UIPage) stateHolder.get(); 179 } else { 180 return findPage(component); 181 } 182 } 183 184 public static UIPage findPage(UIComponent component) { 185 while (component != null) { 186 if (component instanceof UIPage) { 187 return (UIPage) component; 188 } 189 component = component.getParent(); 190 } 191 return null; 192 } 193 194 public static void addStyles(UIComponent component, String[] styles) { 195 UIPage uiPage = ComponentUtil.findPage(component); 196 uiPage.getStyleFiles().addAll(Arrays.asList(styles)); 197 } 198 199 public static void addScripts(UIComponent component, String[] scripts) { 200 UIPage uiPage = ComponentUtil.findPage(component); 201 uiPage.getScriptFiles().addAll(Arrays.asList(scripts)); 202 } 203 204 public static void addOnloadCommands(UIComponent component, String[] cmds) { 205 UIPage uiPage = ComponentUtil.findPage(component); 206 uiPage.getOnloadScripts().addAll(Arrays.asList(cmds)); 207 } 208 209 public static UIPage findPage(FacesContext facesContext) { 210 return findPageBreadthFirst(facesContext.getViewRoot()); 211 } 212 213 private static UIPage findPageBreadthFirst(UIComponent component) { 214 for (Object o : component.getChildren()) { 215 UIComponent child = (UIComponent) o; 216 if (child instanceof UIPage) { 217 return (UIPage) child; 218 } 219 } 220 for (Object o : component.getChildren()) { 221 UIComponent child = (UIComponent) o; 222 UIPage result = findPageBreadthFirst(child); 223 if (result != null) { 224 return result; 225 } 226 } 227 return null; 228 } 229 230 231 public static UIForm findForm(UIComponent component) { 232 while (component != null) { 233 if (component instanceof UIForm) { 234 return (UIForm) component; 235 } 236 component = component.getParent(); 237 } 238 return null; 239 } 240 241 /** 242 * Find all subforms of a component, and collects it. 243 * It does not find subforms of subforms. 244 */ 245 public static List<UIForm> findSubForms(UIComponent component) { 246 List<UIForm> collect = new ArrayList<UIForm>(); 247 findSubForms(collect, component); 248 return collect; 249 } 250 251 @SuppressWarnings(value = "unchecked") 252 private static void findSubForms(List<UIForm> collect, UIComponent component) { 253 Iterator<UIComponent> kids = component.getFacetsAndChildren(); 254 while (kids.hasNext()) { 255 UIComponent child = kids.next(); 256 if (child instanceof UIForm) { 257 collect.add((UIForm) child); 258 } else { 259 findSubForms(collect, child); 260 } 261 } 262 } 263 264 public static <T extends UIComponent> T findDescendant(UIComponent component, Class<T> type) { 265 266 for (UIComponent child : (List<UIComponent>) component.getChildren()) { 267 if (child.getClass().equals(type)) { 268 return (T) component; 269 } 270 final T descendant = findDescendant(child, type); 271 if (descendant != null) { 272 return descendant; 273 } 274 } 275 return null; 276 } 277 278 /** 279 * Looks for the attribute "for" in the component. If there is any 280 * search for the component which is referenced by the "for" attribute, 281 * and return their clientId. 282 * If there is no "for" attribute, return the "clientId" of the parent 283 * (if it has a parent). This is useful for labels. 284 */ 285 public static String findClientIdFor(UIComponent component, 286 FacesContext facesContext) { 287 UIComponent forComponent = findFor(component); 288 if (forComponent != null) { 289 String clientId = forComponent.getClientId(facesContext); 290 if (LOG.isDebugEnabled()) { 291 LOG.debug("found clientId: '" + clientId + "'"); 292 } 293 return clientId; 294 } 295 if (LOG.isDebugEnabled()) { 296 LOG.debug("found no clientId"); 297 } 298 return null; 299 } 300 301 public static UIComponent findFor(UIComponent component) { 302 String forValue = (String) component.getAttributes().get(ATTR_FOR); 303 if (forValue == null) { 304 return component.getParent(); 305 } 306 return component.findComponent(forValue); 307 } 308 309 public static boolean isInActiveForm(UIComponent component) { 310 while (component != null) { 311 //log.debug("compoent= " + component.getClientId(FacesContext.getCurrentInstance()) 312 // + " " + component.getRendererType()); 313 if (component instanceof UIForm) { 314 UIForm form = (UIForm) component; 315 if (form.isSubmitted()) { 316 //log.debug("in active form = " + form.getClientId(FacesContext.getCurrentInstance())); 317 return true; 318 } /*else { 319 log.debug("form found but not active = " + form.getClientId(FacesContext.getCurrentInstance())); 320 } */ 321 } 322 component = component.getParent(); 323 } 324 //log.debug("not in an active form"); 325 return false; 326 } 327 328 public static FacesMessage.Severity getMaximumSeverity(UIComponent component) { 329 final boolean invalid = component instanceof javax.faces.component.UIInput 330 && !((javax.faces.component.UIInput) component).isValid(); 331 FacesMessage.Severity max = invalid ? FacesMessage.SEVERITY_ERROR : null; 332 FacesContext facesContext = FacesContext.getCurrentInstance(); 333 final Iterator messages = facesContext.getMessages(component.getClientId(facesContext)); 334 while (messages.hasNext()) { 335 FacesMessage message = (FacesMessage) messages.next(); 336 if (max == null || message.getSeverity().getOrdinal() > max.getOrdinal()) { 337 max = message.getSeverity(); 338 } 339 } 340 return max; 341 } 342 343 public static boolean isError(javax.faces.component.UIInput uiInput) { 344 FacesContext facesContext = FacesContext.getCurrentInstance(); 345 return !uiInput.isValid() 346 || facesContext.getMessages(uiInput.getClientId(facesContext)).hasNext(); 347 } 348 349 public static boolean isError(UIComponent component) { 350 if (component instanceof UIInput) { 351 return isError((UIInput) component); 352 } 353 return false; 354 } 355 356 public static boolean isOutputOnly(UIComponent component) { 357 return getBooleanAttribute(component, ATTR_DISABLED) 358 || getBooleanAttribute(component, ATTR_READONLY); 359 } 360 361 public static boolean mayValidate(UIComponent component) { 362 return !isOutputOnly(component) 363 && ComponentUtil.isInActiveForm(component); 364 } 365 366 public static boolean mayUpdateModel(UIComponent component) { 367 return mayValidate(component); 368 } 369 370 public static boolean getBooleanAttribute(UIComponent component, String name) { 371 372 Object bool = component.getAttributes().get(name); 373 if (bool == null) { 374 return false; 375 } 376 if (bool instanceof ValueBinding) { 377 bool = ((ValueBinding) bool).getValue(FacesContext.getCurrentInstance()); 378 } 379 if (bool instanceof Boolean) { 380 return (Boolean) bool; 381 } else if (bool instanceof String) { 382 if (LOG.isInfoEnabled()) { 383 LOG.info("Searching for a boolean, but find a String. Should not happen. " 384 + "attribute: '" + name + "' id: '" + component.getClientId(FacesContext.getCurrentInstance()) 385 + "' comp: '" + component + "'"); 386 } 387 return Boolean.valueOf((String) bool); 388 } else { 389 LOG.warn("Unknown type '" + bool.getClass().getName() 390 + "' for boolean attribute: " + name + " id: " + component.getClientId(FacesContext.getCurrentInstance()) 391 + " comp: " + component); 392 return false; 393 } 394 } 395 396 public static void setRenderedPartially(org.apache.myfaces.tobago.component.UICommand command, 397 String renderers) { 398 if (renderers != null) { 399 if (UIComponentTag.isValueReference(renderers)) { 400 command.setValueBinding(ATTR_RENDERED_PARTIALLY, createValueBinding(renderers)); 401 } else { 402 String[] components = StringUtils.split(renderers, ","); 403 command.setRenderedPartially(components); 404 } 405 } 406 } 407 408 public static void setStyleClasses(UIComponent component, String styleClasses) { 409 if (styleClasses != null) { 410 if (UIComponentTag.isValueReference(styleClasses)) { 411 component.setValueBinding(ATTR_STYLE_CLASS, createValueBinding(styleClasses)); 412 } else { 413 String[] classes = StringUtils.split(styleClasses, ", "); 414 if (classes.length > 0) { 415 StyleClasses styles = StyleClasses.ensureStyleClasses(component); 416 for (String clazz : classes) { 417 styles.addFullQualifiedClass(clazz); 418 } 419 } 420 } 421 } 422 } 423 424 public static void setMarkup(UIComponent markupComponent, String markup) { 425 if (markup != null) { 426 if (markupComponent instanceof SupportsMarkup) { 427 if (UIComponentTag.isValueReference(markup)) { 428 markupComponent.setValueBinding(ATTR_MARKUP, createValueBinding(markup)); 429 } else { 430 String[] markups = StringUtils.split(markup, ","); 431 ((SupportsMarkup) markupComponent).setMarkup(markups); 432 } 433 } else { 434 LOG.error("Component did not support Markup " + markupComponent.getClass().getName()); 435 } 436 } 437 } 438 439 public static Object getAttribute(UIComponent component, String name) { 440 Object value = component.getAttributes().get(name); 441 if (value instanceof ValueBinding) { 442 value = ((ValueBinding) value).getValue(FacesContext.getCurrentInstance()); 443 } 444 return value; 445 } 446 447 public static String getStringAttribute(UIComponent component, String name) { 448 return (String) getAttribute(component, name); 449 } 450 451 public static int getIntAttribute(UIComponent component, String name) { 452 return getIntAttribute(component, name, 0); 453 } 454 455 public static int getIntAttribute(UIComponent component, String name, 456 int defaultValue) { 457 Object integer = component.getAttributes().get(name); 458 if (integer instanceof Number) { 459 return ((Number) integer).intValue(); 460 } else if (integer instanceof String) { 461 try { 462 return Integer.parseInt((String) integer); 463 } catch (NumberFormatException e) { 464 LOG.warn("Can't parse number from string : \"" + integer + "\"!"); 465 return defaultValue; 466 } 467 } else if (integer == null) { 468 return defaultValue; 469 } else { 470 LOG.warn("Unknown type '" + integer.getClass().getName() 471 + "' for integer attribute: " + name + " comp: " + component); 472 return defaultValue; 473 } 474 } 475 476 /** 477 * @param component 478 * @param name 479 * @deprecated please use the method {@link #getCharacterAttribute(javax.faces.component.UIComponent, String)} 480 */ 481 @Deprecated 482 public static Character getCharakterAttribute(UIComponent component, String name) { 483 return getCharacterAttribute(component, name); 484 } 485 486 public static Character getCharacterAttribute(UIComponent component, String name) { 487 Object character = component.getAttributes().get(name); 488 if (character == null) { 489 return null; 490 } else if (character instanceof Character) { 491 return ((Character) character); 492 } else if (character instanceof String) { 493 String asString = ((String) character); 494 return asString.length() > 0 ? asString.charAt(0) : null; 495 } else { 496 LOG.warn("Unknown type '" + character.getClass().getName() 497 + "' for integer attribute: " + name + " comp: " + component); 498 return null; 499 } 500 } 501 502 public static boolean isFacetOf(UIComponent component, UIComponent parent) { 503 for (Object o : parent.getFacets().keySet()) { 504 UIComponent facet = parent.getFacet((String) o); 505 if (component.equals(facet)) { 506 return true; 507 } 508 } 509 return false; 510 } 511 512 // TODO This should not be neseccary, but UIComponentBase.getRenderer() is protected 513 public static LayoutableRendererBase getRenderer(FacesContext facesContext, UIComponent component) { 514 return getRenderer(facesContext, component.getFamily(), component.getRendererType()); 515 516 } 517 518 public static LayoutableRendererBase getRenderer(FacesContext facesContext, String family, String rendererType) { 519 if (rendererType == null) { 520 return null; 521 } 522 523 LayoutableRendererBase renderer; 524 525 Map requestMap = facesContext.getExternalContext().getRequestMap(); 526 renderer = (LayoutableRendererBase) requestMap.get(RENDER_KEY_PREFIX + rendererType); 527 528 if (renderer == null) { 529 RenderKitFactory rkFactory = (RenderKitFactory) 530 FactoryFinder.getFactory(FactoryFinder.RENDER_KIT_FACTORY); 531 RenderKit renderKit = rkFactory.getRenderKit(facesContext, facesContext.getViewRoot().getRenderKitId()); 532 Renderer myRenderer = renderKit.getRenderer(family, rendererType); 533 if (myRenderer instanceof LayoutableRendererBase) { 534 requestMap.put(RENDER_KEY_PREFIX + rendererType, myRenderer); 535 renderer = (LayoutableRendererBase) myRenderer; 536 } else { 537 return null; 538 } 539 } 540 return renderer; 541 } 542 543 public static String currentValue(UIComponent component) { 544 String currentValue = null; 545 if (component instanceof ValueHolder) { 546 Object value; 547 if (component instanceof EditableValueHolder) { 548 value = ((EditableValueHolder) component).getSubmittedValue(); 549 if (value != null) { 550 return (String) value; 551 } 552 } 553 554 value = ((ValueHolder) component).getValue(); 555 if (value != null) { 556 Converter converter = ((ValueHolder) component).getConverter(); 557 if (converter == null) { 558 FacesContext context = FacesContext.getCurrentInstance(); 559 converter = context.getApplication().createConverter(value.getClass()); 560 } 561 if (converter != null) { 562 currentValue = 563 converter.getAsString(FacesContext.getCurrentInstance(), 564 component, value); 565 } else { 566 currentValue = value.toString(); 567 } 568 } 569 } 570 return currentValue; 571 } 572 573 public static List<SelectItem> getSelectItems(UIComponent component) { 574 575 ArrayList<SelectItem> list = new ArrayList<SelectItem>(); 576 577 for (Object o1 : component.getChildren()) { 578 UIComponent kid = (UIComponent) o1; 579 if (LOG.isDebugEnabled()) { 580 LOG.debug("kid " + kid); 581 LOG.debug("kid " + kid.getClass().getName()); 582 } 583 if (kid instanceof UISelectItem) { 584 Object value = ((UISelectItem) kid).getValue(); 585 if (value == null) { 586 UISelectItem item = (UISelectItem) kid; 587 if (kid instanceof org.apache.myfaces.tobago.component.UISelectItem) { 588 list.add(new org.apache.myfaces.tobago.model.SelectItem( 589 (org.apache.myfaces.tobago.component.UISelectItem) kid)); 590 } else { 591 list.add(new SelectItem(item.getItemValue() == null ? "" : item.getItemValue(), 592 item.getItemLabel() != null ? item.getItemLabel() : item.getItemValue().toString(), 593 item.getItemDescription())); 594 } 595 } else if (value instanceof SelectItem) { 596 list.add((SelectItem) value); 597 } else { 598 throw new IllegalArgumentException("TYPE ERROR: value NOT instanceof SelectItem. type=" 599 + value.getClass().getName()); 600 } 601 } else if (kid instanceof UISelectItems) { 602 Object value = ((UISelectItems) kid).getValue(); 603 if (LOG.isDebugEnabled()) { 604 LOG.debug("value " + value); 605 if (value != null) { 606 LOG.debug("value " + value.getClass().getName()); 607 } 608 } 609 if (value == null) { 610 if (LOG.isDebugEnabled()) { 611 LOG.debug("value is null"); 612 } 613 } else if (value instanceof SelectItem) { 614 list.add((SelectItem) value); 615 } else if (value instanceof SelectItem[]) { 616 SelectItem[] items = (SelectItem[]) value; 617 list.addAll(Arrays.asList(items)); 618 } else if (value instanceof Collection) { 619 for (Object o : ((Collection) value)) { 620 list.add((SelectItem) o); 621 } 622 } else if (value instanceof Map) { 623 for (Object key : ((Map) value).keySet()) { 624 if (key != null) { 625 Object val = ((Map) value).get(key); 626 if (val != null) { 627 list.add(new SelectItem(val.toString(), key.toString(), null)); 628 } 629 } 630 } 631 } else { 632 throw new IllegalArgumentException("TYPE ERROR: value NOT instanceof " 633 + "SelectItem, SelectItem[], Collection, Map. type=" 634 + value.getClass().getName()); 635 } 636 } 637 } 638 639 return list; 640 } 641 642 public static Object findParameter(UIComponent component, String name) { 643 for (Object o : component.getChildren()) { 644 UIComponent child = (UIComponent) o; 645 if (child instanceof UIParameter) { 646 UIParameter parameter = (UIParameter) child; 647 if (LOG.isDebugEnabled()) { 648 LOG.debug("Select name='" + parameter.getName() + "'"); 649 LOG.debug("Select value='" + parameter.getValue() + "'"); 650 } 651 if (name.equals(parameter.getName())) { 652 return parameter.getValue(); 653 } 654 } 655 } 656 return null; 657 } 658 659 public static String toString(UIComponent component, int offset) { 660 return toString(component, offset, false); 661 } 662 663 private static String toString(UIComponent component, int offset, boolean asFacet) { 664 StringBuilder result = new StringBuilder(); 665 if (component == null) { 666 result.append("null"); 667 } else { 668 result.append('\n'); 669 if (!asFacet) { 670 result.append(spaces(offset)); 671 result.append(toString(component)); 672 } 673 Map facets = component.getFacets(); 674 if (facets.size() > 0) { 675 for (Map.Entry<String, UIComponent> entry : (Set<Map.Entry<String, UIComponent>>) facets.entrySet()) { 676 UIComponent facet = entry.getValue(); 677 result.append('\n'); 678 result.append(spaces(offset + 1)); 679 result.append('\"'); 680 result.append(entry.getKey()); 681 result.append("\" = "); 682 result.append(toString(facet)); 683 result.append(toString(facet, offset + 1, true)); 684 } 685 } 686 for (Object o : component.getChildren()) { 687 result.append(toString((UIComponent) o, offset + 1, false)); 688 } 689 } 690 return result.toString(); 691 } 692 693 private static String toString(UIComponent component) { 694 StringBuilder buf = new StringBuilder(component.getClass().getName()); 695 buf.append('@'); 696 buf.append(Integer.toHexString(component.hashCode())); 697 buf.append(" "); 698 buf.append(component.getRendererType()); 699 buf.append(" "); 700 if (component instanceof javax.faces.component.UIViewRoot) { 701 buf.append(((javax.faces.component.UIViewRoot) component).getViewId()); 702 } else { 703 buf.append(component.getId()); 704 buf.append(" "); 705 buf.append(component.getClientId(FacesContext.getCurrentInstance())); 706 } 707 return buf.toString(); 708 } 709 710 private static String spaces(int n) { 711 StringBuilder buffer = new StringBuilder(n * 2); 712 for (int i = 0; i < n; i++) { 713 buffer.append(" "); 714 } 715 return buffer.toString(); 716 } 717 718 public static ActionListener createActionListener(String type) 719 throws JspException { 720 try { 721 ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); 722 if (classLoader == null) { 723 classLoader = type.getClass().getClassLoader(); 724 } 725 Class clazz = classLoader.loadClass(type); 726 return (ActionListener) clazz.newInstance(); 727 } catch (Exception e) { 728 if (LOG.isDebugEnabled()) { 729 LOG.debug("type=" + type, e); 730 } 731 throw new JspException(e); 732 } 733 } 734 735 public static UIGraphic getFirstGraphicChild(UIComponent component) { 736 UIGraphic graphic = null; 737 for (Object o : component.getChildren()) { 738 UIComponent uiComponent = (UIComponent) o; 739 if (uiComponent instanceof UIGraphic) { 740 graphic = (UIGraphic) uiComponent; 741 break; 742 } 743 } 744 return graphic; 745 } 746 747 public static boolean isHoverEnabled(UIComponent component) { 748 return ComponentUtil.getBooleanAttribute(component, ATTR_HOVER); 749 } 750 751 public static UIOutput getFirstNonGraphicChild(UIComponent component) { 752 UIOutput output = null; 753 for (Object o : component.getChildren()) { 754 UIComponent uiComponent = (UIComponent) o; 755 if ((uiComponent instanceof UIOutput) 756 && !(uiComponent instanceof UIGraphic)) { 757 output = (UIOutput) uiComponent; 758 break; 759 } 760 } 761 return output; 762 } 763 764 public static void setIntegerSizeProperty(UIComponent component, 765 String name, String value) { 766 if (value != null) { 767 if (UIComponentTag.isValueReference(value)) { 768 component.setValueBinding(name, createValueBinding(value)); 769 } else { 770 value = removePx(value); 771 component.getAttributes().put(name, new Integer(value)); 772 } 773 } 774 } 775 776 public static String removePx(String value) { 777 if (value != null && value.endsWith("px")) { 778 value = value.substring(0, value.length() - 2); 779 } 780 return value; 781 } 782 783 public static void setIntegerProperty(UIComponent component, 784 String name, String value) { 785 if (value != null) { 786 if (UIComponentTag.isValueReference(value)) { 787 component.setValueBinding(name, createValueBinding(value)); 788 } else { 789 component.getAttributes().put(name, new Integer(value)); 790 } 791 } 792 } 793 794 public static void setBooleanProperty(UIComponent component, 795 String name, String value) { 796 if (value != null) { 797 if (UIComponentTag.isValueReference(value)) { 798 component.setValueBinding(name, createValueBinding(value)); 799 } else { 800 component.getAttributes().put(name, Boolean.valueOf(value)); 801 } 802 } 803 } 804 805 public static void setStringProperty(UIComponent component, String name, 806 String value) { 807 if (value != null) { 808 if (UIComponentTag.isValueReference(value)) { 809 component.setValueBinding(name, createValueBinding(value)); 810 } else { 811 component.getAttributes().put(name, value); 812 } 813 } 814 } 815 816 public static void setValueForValueBinding(String name, Object value) { 817 FacesContext context = FacesContext.getCurrentInstance(); 818 ValueBinding valueBinding = context.getApplication().createValueBinding(name); 819 valueBinding.setValue(context, value); 820 } 821 822 public static ValueBinding createValueBinding(String value) { 823 return FacesContext.getCurrentInstance().getApplication() 824 .createValueBinding(value); 825 } 826 827 public static String getValueFromEl(String script) { 828 if (UIComponentTag.isValueReference(script)) { 829 ValueBinding valueBinding = ComponentUtil.createValueBinding(script); 830 script = (String) valueBinding.getValue(FacesContext.getCurrentInstance()); 831 } 832 return script; 833 } 834 835 /** 836 * Please use createComponent(String componentType, String rendererType, String id) 837 * 838 * @deprecated 839 */ 840 @Deprecated 841 public static UIComponent createComponent(String componentType, String rendererType) { 842 return createComponent(componentType, rendererType, null); 843 } 844 845 public static UIComponent createComponent(String componentType, String rendererType, String id) { 846 final FacesContext facesContext = FacesContext.getCurrentInstance(); 847 return createComponent(facesContext, componentType, rendererType, id); 848 } 849 850 /** 851 * Please use createComponent(FacesContext facesContext, String componentType, String rendererType, String id) 852 * 853 * @deprecated 854 */ 855 @Deprecated 856 public static UIComponent createComponent(FacesContext facesContext, String componentType, String rendererType) { 857 return createComponent(facesContext, componentType, rendererType, null); 858 } 859 860 public static UIComponent createComponent( 861 FacesContext facesContext, String componentType, String rendererType, String id) { 862 UIComponent component 863 = facesContext.getApplication().createComponent(componentType); 864 component.setRendererType(rendererType); 865 component.setId(id); 866 return component; 867 } 868 869 /** 870 * Please use createTextColumn(String label, String sortable, String align, String value, String id) 871 * 872 * @deprecated 873 */ 874 @Deprecated 875 public static UIColumn createTextColumn(String label, String sortable, String align, String value) { 876 return createTextColumn(label, sortable, align, value, null); 877 } 878 879 public static UIColumn createTextColumn(String label, String sortable, String align, String value, String id) { 880 UIComponent text = createComponent(UIOutput.COMPONENT_TYPE, RENDERER_TYPE_OUT, id + "_t"); 881 setStringProperty(text, ATTR_VALUE, value); 882 setBooleanProperty(text, ATTR_CREATE_SPAN, "false"); 883 setBooleanProperty(text, ATTR_ESCAPE, "false"); 884 return createColumn(label, sortable, align, text, id); 885 } 886 887 /** 888 * Please use createColumn(String label, String sortable, String align, UIComponent child) 889 * 890 * @deprecated 891 */ 892 @Deprecated 893 public static UIColumn createColumn(String label, String sortable, String align, UIComponent child) { 894 return createColumn(label, sortable, align, child, null); 895 } 896 897 public static UIColumn createColumn(String label, String sortable, String align, UIComponent child, String id) { 898 UIColumn column = createColumn(label, sortable, align, id); 899 column.getChildren().add(child); 900 return column; 901 } 902 903 private static UIColumn createColumn(String label, String sortable, String align, String id) { 904 UIColumn column = (UIColumn) createComponent(UIColumn.COMPONENT_TYPE, null, id); 905 setStringProperty(column, ATTR_LABEL, label); 906 setBooleanProperty(column, ATTR_SORTABLE, sortable); 907 setStringProperty(column, ATTR_ALIGN, align); 908 return column; 909 } 910 911 /** 912 * Please use createUIMenuSelectOneFacet(FacesContext facesContext, UICommand command, String id) 913 * 914 * @deprecated 915 */ 916 @Deprecated 917 public static UIMenuSelectOne createUIMenuSelectOneFacet(FacesContext facesContext, UICommand command) { 918 return createUIMenuSelectOneFacet(facesContext, command, null); 919 } 920 921 public static UIMenuSelectOne createUIMenuSelectOneFacet(FacesContext facesContext, UICommand command, String id) { 922 UIMenuSelectOne radio = null; 923 final ValueBinding valueBinding = command.getValueBinding(ATTR_VALUE); 924 if (valueBinding != null) { 925 radio = (UIMenuSelectOne) createComponent(facesContext, 926 UIMenuSelectOne.COMPONENT_TYPE, RENDERER_TYPE_SELECT_ONE_RADIO, id); 927 command.getFacets().put(FACET_ITEMS, radio); 928 radio.setValueBinding(ATTR_VALUE, valueBinding); 929 } 930 return radio; 931 } 932 933 934 public static boolean hasSelectedValue(List<SelectItem> items, Object value) { 935 for (SelectItem item : items) { 936 if (item.getValue().equals(value)) { 937 return true; 938 } 939 } 940 return false; 941 } 942 943 /** 944 * Please use createUISelectBooleanFacet(FacesContext facesContext, UICommand command, String id) 945 * 946 * @deprecated 947 */ 948 @Deprecated 949 public static UIComponent createUISelectBooleanFacet(FacesContext facesContext, UICommand command) { 950 return createUISelectBooleanFacet(facesContext, command, null); 951 } 952 953 public static UIComponent createUISelectBooleanFacet(FacesContext facesContext, UICommand command, String id) { 954 UIComponent checkbox 955 = createComponent(facesContext, UISelectBoolean.COMPONENT_TYPE, RENDERER_TYPE_SELECT_BOOLEAN_CHECKBOX, id); 956 command.getFacets().put(FACET_ITEMS, checkbox); 957 ValueBinding valueBinding = command.getValueBinding(ATTR_VALUE); 958 if (valueBinding != null) { 959 checkbox.setValueBinding(ATTR_VALUE, valueBinding); 960 } else { 961 checkbox.getAttributes().put(ATTR_VALUE, command.getAttributes().get(ATTR_VALUE)); 962 } 963 return checkbox; 964 } 965 966 public static int getIntValue(ValueBinding valueBinding) { 967 return getAsInt(valueBinding.getValue(FacesContext.getCurrentInstance())); 968 } 969 970 private static int getAsInt(Object value) { 971 int result; 972 if (value instanceof Number) { 973 result = ((Number) value).intValue(); 974 } else if (value instanceof String) { 975 result = Integer.parseInt((String) value); 976 } else { 977 throw new IllegalArgumentException("Can't convert " + value + " to int!"); 978 } 979 return result; 980 } 981 982 983 public static String createPickerId(FacesContext facesContext, UIComponent component, String postfix) { 984 //String id = component.getId(); 985 String id = getComponentId(facesContext, component); 986 return id + "_picker" + postfix; 987 } 988 989 public static String getComponentId(FacesContext facesContext, UIComponent component) { 990 String id = component.getId(); 991 //if (id == null) { 992 // XXX What is this? 993 // id = component.getClientId(facesContext).substring(id.lastIndexOf('_')); 994 //} 995 return id; 996 } 997 998 public static UIComponent provideLabel(FacesContext facesContext, UIComponent component) { 999 UIComponent label = component.getFacet(FACET_LABEL); 1000 1001 1002 if (label == null) { 1003 final Map attributes = component.getAttributes(); 1004 Object labelText = component.getValueBinding(ATTR_LABEL); 1005 if (labelText == null) { 1006 labelText = attributes.get(ATTR_LABEL); 1007 } 1008 1009 if (labelText != null) { 1010 Application application = FacesContext.getCurrentInstance().getApplication(); 1011 label = application.createComponent(UIOutput.COMPONENT_TYPE); 1012 label.setRendererType(RENDERER_TYPE_LABEL); 1013 String idprefix = ComponentUtil.getComponentId(facesContext, component); 1014 label.setId(idprefix + "_" + FACET_LABEL); 1015 label.setRendered(true); 1016 1017 if (labelText instanceof ValueBinding) { 1018 label.setValueBinding(ATTR_VALUE, (ValueBinding) labelText); 1019 } else { 1020 label.getAttributes().put(ATTR_VALUE, labelText); 1021 } 1022 1023 component.getFacets().put(FACET_LABEL, label); 1024 } 1025 } 1026 return label; 1027 } 1028 1029 /*public static void debug(UIComponent component) { 1030 LOG.error("###############################"); 1031 LOG.error("ID " + component.getId()); 1032 LOG.error("ClassName " + component.getClass().getName()); 1033 if (component instanceof EditableValueHolder) { 1034 EditableValueHolder editableValueHolder = (EditableValueHolder) component; 1035 LOG.error("Valid " + editableValueHolder.isValid()); 1036 LOG.error("SubmittedValue " + editableValueHolder.getSubmittedValue()); 1037 } 1038 for (Iterator it = component.getFacetsAndChildren(); it.hasNext(); ) { 1039 debug((UIComponent)it.next()); 1040 } 1041 } */ 1042 1043 1044 public static List<SelectItem> getItemsToRender(javax.faces.component.UISelectOne component) { 1045 return getItems(component); 1046 } 1047 1048 public static List<SelectItem> getItemsToRender(javax.faces.component.UISelectMany component) { 1049 return getItems(component); 1050 } 1051 1052 private static List<SelectItem> getItems(javax.faces.component.UIInput component) { 1053 1054 List<SelectItem> selectItems = ComponentUtil.getSelectItems(component); 1055 1056 String renderRange = (String) 1057 component.getAttributes().get(ATTR_RENDER_RANGE_EXTERN); 1058 if (renderRange == null) { 1059 renderRange = (String) 1060 component.getAttributes().get(ATTR_RENDER_RANGE); 1061 } 1062 if (renderRange == null) { 1063 return selectItems; 1064 } 1065 1066 int[] indices = RangeParser.getIndices(renderRange); 1067 List<SelectItem> items = new ArrayList<SelectItem>(indices.length); 1068 1069 if (selectItems.size() != 0) { 1070 for (int indice : indices) { 1071 items.add(selectItems.get(indice)); 1072 } 1073 } else { 1074 LOG.warn("No items found! rendering dummys instead!"); 1075 for (int i = 0; i < indices.length; i++) { 1076 items.add(new SelectItem(Integer.toString(i), "Item " + i, "")); 1077 } 1078 } 1079 return items; 1080 } 1081 1082 public static void setValidator(EditableValueHolder editableValueHolder, String validator) { 1083 if (validator != null && editableValueHolder.getValidator() == null) { 1084 if (UIComponentTag.isValueReference(validator)) { 1085 MethodBinding methodBinding = 1086 FacesContext.getCurrentInstance().getApplication().createMethodBinding(validator, VALIDATOR_ARGS); 1087 editableValueHolder.setValidator(methodBinding); 1088 } 1089 } 1090 } 1091 1092 /** 1093 * @param component 1094 * @param converterId 1095 * @deprecated please use the typesave method {@link #setConverter(javax.faces.component.ValueHolder, String)} 1096 */ 1097 @Deprecated 1098 public static void setConverter(UIComponent component, String converterId) { 1099 if (component instanceof ValueHolder) { 1100 setConverter((ValueHolder) component, converterId); 1101 } 1102 } 1103 1104 public static void setConverter(ValueHolder valueHolder, String converterId) { 1105 if (converterId != null && valueHolder.getConverter() == null) { 1106 final FacesContext facesContext = FacesContext.getCurrentInstance(); 1107 final Application application = facesContext.getApplication(); 1108 if (UIComponentTag.isValueReference(converterId)) { 1109 ValueBinding valueBinding = application.createValueBinding(converterId); 1110 if (valueHolder instanceof UIComponent) { 1111 ((UIComponent) valueHolder).setValueBinding(ATTR_CONVERTER, valueBinding); 1112 } 1113 } else { 1114 Converter converter = application.createConverter(converterId); 1115 valueHolder.setConverter(converter); 1116 } 1117 } 1118 } 1119 1120 /** 1121 * @param component 1122 * @param type 1123 * @param action 1124 * @deprecated please use the typesave method {@link #setAction(javax.faces.component.UICommand, String, String)} 1125 */ 1126 @Deprecated 1127 public static void setAction(UIComponent component, String type, String action) { 1128 if (component instanceof UICommand) { 1129 setAction((UICommand) component, type, action); 1130 } 1131 } 1132 1133 public static void setAction(UICommand component, String type, String action) { 1134 String commandType; 1135 final FacesContext facesContext = FacesContext.getCurrentInstance(); 1136 final Application application = facesContext.getApplication(); 1137 if (type != null && UIComponentTag.isValueReference(type)) { 1138 commandType = (String) application.createValueBinding(type).getValue(facesContext); 1139 } else { 1140 commandType = type; 1141 } 1142 if (commandType != null 1143 && (commandType.equals(COMMAND_TYPE_NAVIGATE) 1144 || commandType.equals(COMMAND_TYPE_RESET) 1145 || commandType.equals(COMMAND_TYPE_SCRIPT))) { 1146 if (commandType.equals(COMMAND_TYPE_NAVIGATE)) { 1147 setStringProperty(component, ATTR_ACTION_LINK, action); 1148 } else if (commandType.equals(COMMAND_TYPE_SCRIPT)) { 1149 setStringProperty(component, ATTR_ACTION_ONCLICK, action); 1150 } else { 1151 LOG.warn("Type reset is not supported"); 1152 } 1153 } else { 1154 if (action != null) { 1155 if (UIComponentTag.isValueReference(action)) { 1156 MethodBinding binding = application.createMethodBinding(action, null); 1157 component.setAction(binding); 1158 } else { 1159 component.setAction(new ConstantMethodBinding(action)); 1160 } 1161 } 1162 } 1163 1164 } 1165 1166 /** 1167 * @param component 1168 * @param suggestMethod 1169 * @deprecated please use the typesave method {@link #setSuggestMethodBinding(UIInput, String)} 1170 */ 1171 @Deprecated 1172 public static void setSuggestMethodBinding(UIComponent component, String suggestMethod) { 1173 if (component instanceof UIInput) { 1174 setSuggestMethodBinding((UIInput) component, suggestMethod); 1175 } 1176 } 1177 1178 public static void setSuggestMethodBinding(UIInput component, String suggestMethod) { 1179 if (suggestMethod != null) { 1180 if (UIComponentTag.isValueReference(suggestMethod)) { 1181 final MethodBinding methodBinding = FacesContext.getCurrentInstance().getApplication() 1182 .createMethodBinding(suggestMethod, new Class[]{String.class}); 1183 component.setSuggestMethod(methodBinding); 1184 } else { 1185 throw new IllegalArgumentException( 1186 "Must be a valueReference (suggestMethod): " + suggestMethod); 1187 } 1188 } 1189 } 1190 1191 public static void setActionListener(ActionSource command, String actionListener) { 1192 final FacesContext facesContext = FacesContext.getCurrentInstance(); 1193 final Application application = facesContext.getApplication(); 1194 if (actionListener != null) { 1195 if (UIComponentTag.isValueReference(actionListener)) { 1196 MethodBinding binding 1197 = application.createMethodBinding(actionListener, ACTION_LISTENER_ARGS); 1198 command.setActionListener(binding); 1199 } else { 1200 throw new IllegalArgumentException( 1201 "Must be a valueReference (actionListener): " + actionListener); 1202 } 1203 } 1204 } 1205 1206 public static void setValueChangeListener(EditableValueHolder valueHolder, String valueChangeListener) { 1207 final FacesContext facesContext = FacesContext.getCurrentInstance(); 1208 final Application application = facesContext.getApplication(); 1209 if (valueChangeListener != null) { 1210 if (UIComponentTag.isValueReference(valueChangeListener)) { 1211 MethodBinding binding 1212 = application.createMethodBinding(valueChangeListener, VALUE_CHANGE_LISTENER_ARGS); 1213 valueHolder.setValueChangeListener(binding); 1214 } else { 1215 throw new IllegalArgumentException( 1216 "Must be a valueReference (valueChangeListener): " + valueChangeListener); 1217 } 1218 } 1219 } 1220 1221 1222 public static void setSortActionListener(UIData data, String actionListener) { 1223 final FacesContext facesContext = FacesContext.getCurrentInstance(); 1224 final Application application = facesContext.getApplication(); 1225 if (actionListener != null) { 1226 if (UIComponentTag.isValueReference(actionListener)) { 1227 MethodBinding binding = application.createMethodBinding( 1228 actionListener, ACTION_LISTENER_ARGS); 1229 data.setSortActionListener(binding); 1230 } else { 1231 throw new IllegalArgumentException( 1232 "Must be a valueReference (sortActionListener): " + actionListener); 1233 } 1234 } 1235 } 1236 1237 public static void setValueBinding(UIComponent component, String name, String state) { 1238 // TODO: check, if it is an writeable object 1239 if (state != null && UIComponentTag.isValueReference(state)) { 1240 ValueBinding valueBinding = createValueBinding(state); 1241 component.setValueBinding(name, valueBinding); 1242 } 1243 } 1244 1245 public static void setStateChangeListener(UIData data, String stateChangeListener) { 1246 final FacesContext facesContext = FacesContext.getCurrentInstance(); 1247 final Application application = facesContext.getApplication(); 1248 1249 if (stateChangeListener != null) { 1250 if (UIComponentTag.isValueReference(stateChangeListener)) { 1251 Class[] arguments = {SheetStateChangeEvent.class}; 1252 MethodBinding binding 1253 = application.createMethodBinding(stateChangeListener, arguments); 1254 data.setStateChangeListener(binding); 1255 } else { 1256 throw new IllegalArgumentException( 1257 "Must be a valueReference (actionListener): " + stateChangeListener); 1258 } 1259 } 1260 } 1261 1262 1263 public static String[] getMarkupBinding(FacesContext facesContext, SupportsMarkup component) { 1264 ValueBinding vb = ((UIComponent) component).getValueBinding(ATTR_MARKUP); 1265 if (vb != null) { 1266 Object markups = vb.getValue(facesContext); 1267 if (markups instanceof String[]) { 1268 return (String[]) markups; 1269 } else if (markups instanceof String) { 1270 String[] strings = StringUtils.split((String) markups, ", "); 1271 List<String> result = new ArrayList<String>(strings.length); 1272 for (String string : strings) { 1273 if (string.trim().length() != 0) { 1274 result.add(string.trim()); 1275 } 1276 } 1277 return result.toArray(new String[result.size()]); 1278 } else if (markups == null) { 1279 return new String[0]; 1280 } else { 1281 return new String[]{markups.toString()}; 1282 } 1283 } 1284 1285 return new String[0]; 1286 } 1287 1288 /** 1289 * colonCount == 0: fully relative 1290 * colonCount == 1: absolute (still normal findComponent syntax) 1291 * colonCount > 1: for each extra colon after 1, go up a naming container 1292 * (to the view root, if naming containers run out) 1293 */ 1294 1295 public static UIComponent findComponent(UIComponent from, String relativeId) { 1296 int idLength = relativeId.length(); 1297 // Figure out how many colons 1298 int colonCount = 0; 1299 while (colonCount < idLength) { 1300 if (relativeId.charAt(colonCount) != NamingContainer.SEPARATOR_CHAR) { 1301 break; 1302 } 1303 colonCount++; 1304 } 1305 1306 // colonCount == 0: fully relative 1307 // colonCount == 1: absolute (still normal findComponent syntax) 1308 // colonCount > 1: for each extra colon after 1, go up a naming container 1309 // (to the view root, if naming containers run out) 1310 if (colonCount > 1) { 1311 relativeId = relativeId.substring(colonCount); 1312 for (int j = 1; j < colonCount; j++) { 1313 while (from.getParent() != null) { 1314 from = from.getParent(); 1315 if (from instanceof NamingContainer) { 1316 break; 1317 } 1318 } 1319 } 1320 } 1321 return from.findComponent(relativeId); 1322 } 1323 1324 public static void invokeOnComponent(FacesContext facesContext, String clientId, UIComponent component, 1325 Callback callback) { 1326 List<UIComponent> list = new ArrayList<UIComponent>(); 1327 while (component != null) { 1328 list.add(component); 1329 component = component.getParent(); 1330 } 1331 Collections.reverse(list); 1332 invokeOrPrepare(facesContext, list, clientId, callback); 1333 facesContext.getExternalContext().getRequestMap().remove(TobagoConstants.ATTR_ZINDEX); 1334 } 1335 1336 private static void invokeOrPrepare(FacesContext facesContext, List<UIComponent> list, String clientId, 1337 Callback callback) { 1338 if (list.size() == 1) { 1339 callback.execute(facesContext, list.get(0)); 1340 } else if (list.get(0) instanceof UIData) { 1341 prepareOnUIData(facesContext, list, clientId, callback); 1342 } else if (list.get(0) instanceof UIForm) { 1343 prepareOnUIForm(facesContext, list, clientId, callback); 1344 } else if (list.get(0) instanceof UIPopup) { 1345 prepareOnUIPopup(facesContext, list, clientId, callback); 1346 } else { 1347 prepareOnUIComponent(facesContext, list, clientId, callback); 1348 } 1349 } 1350 1351 @SuppressWarnings(value = "unchecked") 1352 private static void prepareOnUIForm(FacesContext facesContext, List<UIComponent> list, String clientId, 1353 Callback callback) { 1354 UIComponent currentComponent = list.remove(0); 1355 if (!(currentComponent instanceof UIForm)) { 1356 throw new IllegalStateException(currentComponent.getClass().getName()); 1357 } 1358 // TODO is this needed? 1359 if (callback instanceof TobagoCallback) { 1360 if (PhaseId.APPLY_REQUEST_VALUES.equals(((TobagoCallback) callback).getPhaseId())) { 1361 currentComponent.decode(facesContext); 1362 } 1363 } 1364 UIForm uiForm = (UIForm) currentComponent; 1365 facesContext.getExternalContext().getRequestMap().put(UIForm.SUBMITTED_MARKER, uiForm.isSubmitted()); 1366 invokeOrPrepare(facesContext, list, clientId, callback); 1367 1368 } 1369 1370 private static void prepareOnUIComponent( 1371 FacesContext facesContext, List<UIComponent> list, String clientId, Callback callback) { 1372 list.remove(0); 1373 invokeOrPrepare(facesContext, list, clientId, callback); 1374 } 1375 1376 private static void prepareOnUIPopup( 1377 FacesContext facesContext, List<UIComponent> list, String clientId, Callback callback) { 1378 if (callback instanceof TobagoCallback 1379 && PhaseId.RENDER_RESPONSE.equals(((TobagoCallback) callback).getPhaseId())) { 1380 Integer zIndex = (Integer) facesContext.getExternalContext().getRequestMap().get(TobagoConstants.ATTR_ZINDEX); 1381 if (zIndex == null) { 1382 zIndex = 0; 1383 } else { 1384 zIndex += 10; 1385 } 1386 facesContext.getExternalContext().getRequestMap().put(TobagoConstants.ATTR_ZINDEX, zIndex); 1387 } 1388 list.remove(0); 1389 invokeOrPrepare(facesContext, list, clientId, callback); 1390 } 1391 1392 private static void prepareOnUIData(FacesContext facesContext, List<UIComponent> list, String clientId, 1393 Callback callback) { 1394 UIComponent currentComponent = list.remove(0); 1395 if (!(currentComponent instanceof UIData)) { 1396 throw new IllegalStateException(currentComponent.getClass().getName()); 1397 } 1398 1399 // we may need setRowIndex on UIData 1400 javax.faces.component.UIData uiData = (javax.faces.component.UIData) currentComponent; 1401 int oldRowIndex = uiData.getRowIndex(); 1402 String sheetId = uiData.getClientId(facesContext); 1403 String idRemainder = clientId.substring(sheetId.length()); 1404 if (LOG.isInfoEnabled()) { 1405 LOG.info("idRemainder = \"" + idRemainder + "\""); 1406 } 1407 if (idRemainder.startsWith(String.valueOf(NamingContainer.SEPARATOR_CHAR))) { 1408 idRemainder = idRemainder.substring(1); 1409 int idx = idRemainder.indexOf(NamingContainer.SEPARATOR_CHAR); 1410 if (idx > 0) { 1411 String firstPart = idRemainder.substring(0, idx); 1412 if (NumberUtils.isDigits(firstPart)) { 1413 try { 1414 int rowIndex = Integer.parseInt(firstPart); 1415 if (LOG.isInfoEnabled()) { 1416 LOG.info("set rowIndex = \"" + rowIndex + "\""); 1417 } 1418 uiData.setRowIndex(rowIndex); 1419 } catch (NumberFormatException e) { 1420 LOG.error("idRemainder = \"" + idRemainder + "\"", e); 1421 } 1422 } 1423 } 1424 } else { 1425 if (LOG.isInfoEnabled()) { 1426 LOG.info("no match for \"^:\\d+:.*\""); 1427 } 1428 } 1429 1430 invokeOrPrepare(facesContext, list, clientId, callback); 1431 1432 // we should reset rowIndex on UIData 1433 uiData.setRowIndex(oldRowIndex); 1434 } 1435 1436 public static Object getConvertedValue( 1437 FacesContext facesContext, javax.faces.component.UIInput component, String stringValue) { 1438 try { 1439 Renderer renderer = getRenderer(facesContext, component); 1440 if (renderer != null) { 1441 if (component instanceof UISelectMany) { 1442 final Object converted = renderer.getConvertedValue(facesContext, component, new String[]{stringValue}); 1443 return ((Object[]) converted)[0]; 1444 } else { 1445 return renderer.getConvertedValue(facesContext, component, stringValue); 1446 } 1447 } else { 1448 Converter converter = component.getConverter(); 1449 if (converter == null) { 1450 //Try to find out by value binding 1451 ValueBinding vb = component.getValueBinding("value"); 1452 if (vb != null) { 1453 Class valueType = vb.getType(facesContext); 1454 if (valueType != null) { 1455 converter = facesContext.getApplication().createConverter(valueType); 1456 } 1457 } 1458 } 1459 if (converter != null) { 1460 converter.getAsObject(facesContext, component, stringValue); 1461 } 1462 } 1463 } catch (Exception e) { 1464 LOG.warn("Can't convert string value '" + stringValue + "'", e); 1465 } 1466 return stringValue; 1467 } 1468 }