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