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