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 601107 2007-12-04 22:12:14Z bommel $ 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 public static UIComponent createComponent(String componentType, String rendererType) { 806 final FacesContext facesContext = FacesContext.getCurrentInstance(); 807 return createComponent(facesContext, componentType, rendererType); 808 } 809 810 public static UIComponent createComponent(FacesContext facesContext, String componentType, String rendererType) { 811 UIComponent component 812 = facesContext.getApplication().createComponent(componentType); 813 component.setRendererType(rendererType); 814 return component; 815 } 816 817 public static UIColumn createTextColumn(String label, String sortable, String align, String value) { 818 UIComponent text = createComponent(UIOutput.COMPONENT_TYPE, RENDERER_TYPE_OUT); 819 setStringProperty(text, ATTR_VALUE, value); 820 setBooleanProperty(text, ATTR_CREATE_SPAN, "false"); 821 setBooleanProperty(text, ATTR_ESCAPE, "false"); 822 return createColumn(label, sortable, align, text); 823 } 824 825 public static UIColumn createColumn(String label, String sortable, String align, UIComponent child) { 826 UIColumn column = createColumn(label, sortable, align); 827 column.getChildren().add(child); 828 return column; 829 } 830 831 private static UIColumn createColumn(String label, String sortable, String align) { 832 UIColumn column = (UIColumn) createComponent(UIColumn.COMPONENT_TYPE, null); 833 setStringProperty(column, ATTR_LABEL, label); 834 setBooleanProperty(column, ATTR_SORTABLE, sortable); 835 setStringProperty(column, ATTR_ALIGN, align); 836 return column; 837 } 838 839 public static UIMenuSelectOne createUIMenuSelectOneFacet(FacesContext facesContext, UICommand command) { 840 UIMenuSelectOne radio = null; 841 final ValueBinding valueBinding = command.getValueBinding(ATTR_VALUE); 842 if (valueBinding != null) { 843 radio = (UIMenuSelectOne) createComponent(facesContext, 844 UIMenuSelectOne.COMPONENT_TYPE, RENDERER_TYPE_SELECT_ONE_RADIO); 845 command.getFacets().put(FACET_ITEMS, radio); 846 radio.setValueBinding(ATTR_VALUE, valueBinding); 847 } 848 return radio; 849 } 850 851 852 public static boolean hasSelectedValue(List<SelectItem> items, Object value) { 853 for (SelectItem item : items) { 854 if (item.getValue().equals(value)) { 855 return true; 856 } 857 } 858 return false; 859 } 860 861 public static UIComponent createUISelectBooleanFacet(FacesContext facesContext, UICommand command) { 862 UIComponent checkbox 863 = createComponent(facesContext, UISelectBoolean.COMPONENT_TYPE, RENDERER_TYPE_SELECT_BOOLEAN_CHECKBOX); 864 command.getFacets().put(FACET_ITEMS, checkbox); 865 ValueBinding valueBinding = command.getValueBinding(ATTR_VALUE); 866 if (valueBinding != null) { 867 checkbox.setValueBinding(ATTR_VALUE, valueBinding); 868 } else { 869 checkbox.getAttributes().put(ATTR_VALUE, command.getAttributes().get(ATTR_VALUE)); 870 } 871 return checkbox; 872 } 873 874 public static int getIntValue(ValueBinding valueBinding) { 875 return getAsInt(valueBinding.getValue(FacesContext.getCurrentInstance())); 876 } 877 878 private static int getAsInt(Object value) { 879 int result; 880 if (value instanceof Number) { 881 result = ((Number) value).intValue(); 882 } else if (value instanceof String) { 883 result = Integer.parseInt((String) value); 884 } else { 885 throw new IllegalArgumentException("Can't convert " + value + " to int!"); 886 } 887 return result; 888 } 889 890 891 public static String createPickerId(FacesContext facesContext, UIComponent component, String postfix) { 892 //String id = component.getId(); 893 String id = getComponentId(facesContext, component); 894 return id + "_picker" + postfix; 895 } 896 897 public static String getComponentId(FacesContext facesContext, UIComponent component) { 898 String id = component.getId(); 899 //if (id == null) { 900 // XXX What is this? 901 // id = component.getClientId(facesContext).substring(id.lastIndexOf('_')); 902 //} 903 return id; 904 } 905 906 public static UIComponent provideLabel(FacesContext facesContext, UIComponent component) { 907 UIComponent label = component.getFacet(FACET_LABEL); 908 909 910 if (label == null) { 911 final Map attributes = component.getAttributes(); 912 Object labelText = component.getValueBinding(ATTR_LABEL); 913 if (labelText == null) { 914 labelText = attributes.get(ATTR_LABEL); 915 } 916 917 if (labelText != null) { 918 Application application = FacesContext.getCurrentInstance().getApplication(); 919 label = application.createComponent(UIOutput.COMPONENT_TYPE); 920 label.setRendererType(RENDERER_TYPE_LABEL); 921 String idprefix = ComponentUtil.getComponentId(facesContext, component); 922 label.setId(idprefix + "_" + FACET_LABEL); 923 label.setRendered(true); 924 925 if (labelText instanceof ValueBinding) { 926 label.setValueBinding(ATTR_VALUE, (ValueBinding) labelText); 927 } else { 928 label.getAttributes().put(ATTR_VALUE, labelText); 929 } 930 931 component.getFacets().put(FACET_LABEL, label); 932 } 933 } 934 return label; 935 } 936 937 /*public static void debug(UIComponent component) { 938 LOG.error("###############################"); 939 LOG.error("ID " + component.getId()); 940 LOG.error("ClassName " + component.getClass().getName()); 941 if (component instanceof EditableValueHolder) { 942 EditableValueHolder editableValueHolder = (EditableValueHolder) component; 943 LOG.error("Valid " + editableValueHolder.isValid()); 944 LOG.error("SubmittedValue " + editableValueHolder.getSubmittedValue()); 945 } 946 for (Iterator it = component.getFacetsAndChildren(); it.hasNext(); ) { 947 debug((UIComponent)it.next()); 948 } 949 } */ 950 951 952 public static List<SelectItem> getItemsToRender(javax.faces.component.UISelectOne component) { 953 return getItems(component); 954 } 955 956 public static List<SelectItem> getItemsToRender(javax.faces.component.UISelectMany component) { 957 return getItems(component); 958 } 959 960 private static List<SelectItem> getItems(javax.faces.component.UIInput component) { 961 962 List<SelectItem> selectItems = ComponentUtil.getSelectItems(component); 963 964 String renderRange = (String) 965 component.getAttributes().get(ATTR_RENDER_RANGE_EXTERN); 966 if (renderRange == null) { 967 renderRange = (String) 968 component.getAttributes().get(ATTR_RENDER_RANGE); 969 } 970 if (renderRange == null) { 971 return selectItems; 972 } 973 974 int[] indices = RangeParser.getIndices(renderRange); 975 List<SelectItem> items = new ArrayList<SelectItem>(indices.length); 976 977 if (selectItems.size() != 0) { 978 for (int indice : indices) { 979 items.add(selectItems.get(indice)); 980 } 981 } else { 982 LOG.warn("No items found! rendering dummys instead!"); 983 for (int i = 0; i < indices.length; i++) { 984 items.add(new SelectItem(Integer.toString(i), "Item " + i, "")); 985 } 986 } 987 return items; 988 } 989 990 public static void setValidator(EditableValueHolder editableValueHolder, String validator) { 991 if (validator != null && editableValueHolder.getValidator() == null) { 992 if (UIComponentTag.isValueReference(validator)) { 993 MethodBinding methodBinding = 994 FacesContext.getCurrentInstance().getApplication().createMethodBinding(validator, VALIDATOR_ARGS); 995 editableValueHolder.setValidator(methodBinding); 996 } 997 } 998 } 999 1000 /** 1001 * @param component 1002 * @param converterId 1003 * @deprecated please use the typesave method {@link #setConverter(javax.faces.component.ValueHolder, String)} 1004 */ 1005 @Deprecated 1006 public static void setConverter(UIComponent component, String converterId) { 1007 if (component instanceof ValueHolder) { 1008 setConverter((ValueHolder) component, converterId); 1009 } 1010 } 1011 1012 public static void setConverter(ValueHolder valueHolder, String converterId) { 1013 if (converterId != null && valueHolder.getConverter() == null) { 1014 final FacesContext facesContext = FacesContext.getCurrentInstance(); 1015 final Application application = facesContext.getApplication(); 1016 if (UIComponentTag.isValueReference(converterId)) { 1017 ValueBinding valueBinding = application.createValueBinding(converterId); 1018 if (valueHolder instanceof UIComponent) { 1019 ((UIComponent) valueHolder).setValueBinding(ATTR_CONVERTER, valueBinding); 1020 } 1021 } else { 1022 Converter converter = application.createConverter(converterId); 1023 valueHolder.setConverter(converter); 1024 } 1025 } 1026 } 1027 1028 /** 1029 * @param component 1030 * @param type 1031 * @param action 1032 * @deprecated please use the typesave method {@link #setAction(javax.faces.component.UICommand, String, String)} 1033 */ 1034 @Deprecated 1035 public static void setAction(UIComponent component, String type, String action) { 1036 if (component instanceof UICommand) { 1037 setAction((UICommand) component, type, action); 1038 } 1039 } 1040 1041 public static void setAction(UICommand component, String type, String action) { 1042 String commandType; 1043 final FacesContext facesContext = FacesContext.getCurrentInstance(); 1044 final Application application = facesContext.getApplication(); 1045 if (type != null && UIComponentTag.isValueReference(type)) { 1046 commandType = (String) application.createValueBinding(type).getValue(facesContext); 1047 } else { 1048 commandType = type; 1049 } 1050 if (commandType != null 1051 && (commandType.equals(COMMAND_TYPE_NAVIGATE) 1052 || commandType.equals(COMMAND_TYPE_RESET) 1053 || commandType.equals(COMMAND_TYPE_SCRIPT))) { 1054 if (commandType.equals(COMMAND_TYPE_NAVIGATE)) { 1055 setStringProperty(component, ATTR_ACTION_LINK, action); 1056 } else if (commandType.equals(COMMAND_TYPE_SCRIPT)) { 1057 setStringProperty(component, ATTR_ACTION_ONCLICK, action); 1058 } else { 1059 LOG.warn("Type reset is not supported"); 1060 } 1061 } else { 1062 if (action != null) { 1063 if (UIComponentTag.isValueReference(action)) { 1064 MethodBinding binding = application.createMethodBinding(action, null); 1065 component.setAction(binding); 1066 } else { 1067 component.setAction(new ConstantMethodBinding(action)); 1068 } 1069 } 1070 } 1071 1072 } 1073 1074 /** 1075 * @param component 1076 * @param suggestMethod 1077 * @deprecated please use the typesave method {@link #setSuggestMethodBinding(UIInput, String)} 1078 */ 1079 @Deprecated 1080 public static void setSuggestMethodBinding(UIComponent component, String suggestMethod) { 1081 if (component instanceof UIInput) { 1082 setSuggestMethodBinding((UIInput) component, suggestMethod); 1083 } 1084 } 1085 1086 public static void setSuggestMethodBinding(UIInput component, String suggestMethod) { 1087 if (suggestMethod != null) { 1088 if (UIComponentTag.isValueReference(suggestMethod)) { 1089 final MethodBinding methodBinding = FacesContext.getCurrentInstance().getApplication() 1090 .createMethodBinding(suggestMethod, new Class[]{String.class}); 1091 component.setSuggestMethod(methodBinding); 1092 } else { 1093 throw new IllegalArgumentException( 1094 "Must be a valueReference (suggestMethod): " + suggestMethod); 1095 } 1096 } 1097 } 1098 1099 public static void setActionListener(ActionSource command, String actionListener) { 1100 final FacesContext facesContext = FacesContext.getCurrentInstance(); 1101 final Application application = facesContext.getApplication(); 1102 if (actionListener != null) { 1103 if (UIComponentTag.isValueReference(actionListener)) { 1104 MethodBinding binding 1105 = application.createMethodBinding(actionListener, ACTION_LISTENER_ARGS); 1106 command.setActionListener(binding); 1107 } else { 1108 throw new IllegalArgumentException( 1109 "Must be a valueReference (actionListener): " + actionListener); 1110 } 1111 } 1112 } 1113 1114 public static void setValueChangeListener(EditableValueHolder valueHolder, String valueChangeListener) { 1115 final FacesContext facesContext = FacesContext.getCurrentInstance(); 1116 final Application application = facesContext.getApplication(); 1117 if (valueChangeListener != null) { 1118 if (UIComponentTag.isValueReference(valueChangeListener)) { 1119 MethodBinding binding 1120 = application.createMethodBinding(valueChangeListener, VALUE_CHANGE_LISTENER_ARGS); 1121 valueHolder.setValueChangeListener(binding); 1122 } else { 1123 throw new IllegalArgumentException( 1124 "Must be a valueReference (valueChangeListener): " + valueChangeListener); 1125 } 1126 } 1127 } 1128 1129 1130 public static void setSortActionListener(UIData data, String actionListener) { 1131 final FacesContext facesContext = FacesContext.getCurrentInstance(); 1132 final Application application = facesContext.getApplication(); 1133 if (actionListener != null) { 1134 if (UIComponentTag.isValueReference(actionListener)) { 1135 MethodBinding binding = application.createMethodBinding( 1136 actionListener, ACTION_LISTENER_ARGS); 1137 data.setSortActionListener(binding); 1138 } else { 1139 throw new IllegalArgumentException( 1140 "Must be a valueReference (sortActionListener): " + actionListener); 1141 } 1142 } 1143 } 1144 1145 public static void setValueBinding(UIComponent component, String name, String state) { 1146 // TODO: check, if it is an writeable object 1147 if (state != null && UIComponentTag.isValueReference(state)) { 1148 ValueBinding valueBinding = createValueBinding(state); 1149 component.setValueBinding(name, valueBinding); 1150 } 1151 } 1152 1153 public static void setStateChangeListener(UIData data, String stateChangeListener) { 1154 final FacesContext facesContext = FacesContext.getCurrentInstance(); 1155 final Application application = facesContext.getApplication(); 1156 1157 if (stateChangeListener != null) { 1158 if (UIComponentTag.isValueReference(stateChangeListener)) { 1159 Class[] arguments = {SheetStateChangeEvent.class}; 1160 MethodBinding binding 1161 = application.createMethodBinding(stateChangeListener, arguments); 1162 data.setStateChangeListener(binding); 1163 } else { 1164 throw new IllegalArgumentException( 1165 "Must be a valueReference (actionListener): " + stateChangeListener); 1166 } 1167 } 1168 } 1169 1170 1171 public static String[] getMarkupBinding(FacesContext facesContext, SupportsMarkup component) { 1172 ValueBinding vb = ((UIComponent) component).getValueBinding(ATTR_MARKUP); 1173 if (vb != null) { 1174 Object markups = vb.getValue(facesContext); 1175 if (markups instanceof String[]) { 1176 return (String[]) markups; 1177 } else if (markups instanceof String) { 1178 String[] strings = ((String) markups).split("[, ]"); 1179 List<String> result = new ArrayList<String>(strings.length); 1180 for (String string : strings) { 1181 if (string.trim().length() != 0) { 1182 result.add(string.trim()); 1183 } 1184 } 1185 return result.toArray(new String[result.size()]); 1186 } else if (markups == null) { 1187 return new String[0]; 1188 } else { 1189 return new String[]{markups.toString()}; 1190 } 1191 } 1192 1193 return new String[0]; 1194 } 1195 1196 /** 1197 * colonCount == 0: fully relative 1198 * colonCount == 1: absolute (still normal findComponent syntax) 1199 * colonCount > 1: for each extra colon after 1, go up a naming container 1200 * (to the view root, if naming containers run out) 1201 */ 1202 1203 public static UIComponent findComponent(UIComponent from, String relativeId) { 1204 int idLength = relativeId.length(); 1205 // Figure out how many colons 1206 int colonCount = 0; 1207 while (colonCount < idLength) { 1208 if (relativeId.charAt(colonCount) != NamingContainer.SEPARATOR_CHAR) { 1209 break; 1210 } 1211 colonCount++; 1212 } 1213 1214 // colonCount == 0: fully relative 1215 // colonCount == 1: absolute (still normal findComponent syntax) 1216 // colonCount > 1: for each extra colon after 1, go up a naming container 1217 // (to the view root, if naming containers run out) 1218 if (colonCount > 1) { 1219 relativeId = relativeId.substring(colonCount); 1220 for (int j = 1; j < colonCount; j++) { 1221 while (from.getParent() != null) { 1222 from = from.getParent(); 1223 if (from instanceof NamingContainer) { 1224 break; 1225 } 1226 } 1227 } 1228 } 1229 return from.findComponent(relativeId); 1230 } 1231 1232 public static void invokeOnComponent(FacesContext facesContext, String clientId, UIComponent component, 1233 Callback callback) { 1234 List<UIComponent> list = new ArrayList<UIComponent>(); 1235 while (component != null) { 1236 list.add(component); 1237 component = component.getParent(); 1238 } 1239 Collections.reverse(list); 1240 invokeOrPrepare(facesContext, list, clientId, callback); 1241 } 1242 1243 private static void invokeOrPrepare(FacesContext facesContext, List<UIComponent> list, String clientId, 1244 Callback callback) { 1245 if (list.size() == 1) { 1246 callback.execute(facesContext, list.get(0)); 1247 } else if (list.get(0) instanceof UIData) { 1248 prepareOnUIData(facesContext, list, clientId, callback); 1249 } else if (list.get(0) instanceof UIForm) { 1250 prepareOnUIForm(facesContext, list, clientId, callback); 1251 } else { 1252 prepareOnUIComponent(facesContext, list, clientId, callback); 1253 } 1254 } 1255 1256 @SuppressWarnings(value = "unchecked") 1257 private static void prepareOnUIForm(FacesContext facesContext, List<UIComponent> list, String clientId, 1258 Callback callback) { 1259 UIComponent currentComponent = list.remove(0); 1260 if (!(currentComponent instanceof UIForm)) { 1261 throw new IllegalStateException(currentComponent.getClass().getName()); 1262 } 1263 // TODO is this needed? 1264 if (callback instanceof TobagoCallback) { 1265 if (PhaseId.APPLY_REQUEST_VALUES.equals(((TobagoCallback) callback).getPhaseId())) { 1266 currentComponent.decode(facesContext); 1267 } 1268 } 1269 UIForm uiForm = (UIForm) currentComponent; 1270 facesContext.getExternalContext().getRequestMap().put(UIForm.SUBMITTED_MARKER, uiForm.isSubmitted()); 1271 invokeOrPrepare(facesContext, list, clientId, callback); 1272 1273 } 1274 1275 private static void prepareOnUIComponent(FacesContext facesContext, List<UIComponent> list, String clientId, 1276 Callback callback) { 1277 list.remove(0); 1278 invokeOrPrepare(facesContext, list, clientId, callback); 1279 } 1280 1281 private static void prepareOnUIData(FacesContext facesContext, List<UIComponent> list, String clientId, 1282 Callback callback) { 1283 UIComponent currentComponent = list.remove(0); 1284 if (!(currentComponent instanceof UIData)) { 1285 throw new IllegalStateException(currentComponent.getClass().getName()); 1286 } 1287 1288 // we may need setRowIndex on UIData 1289 javax.faces.component.UIData uiData = (javax.faces.component.UIData) currentComponent; 1290 int oldRowIndex = uiData.getRowIndex(); 1291 String sheetId = uiData.getClientId(facesContext); 1292 String idRemainder = clientId.substring(sheetId.length()); 1293 LOG.info("idRemainder = \"" + idRemainder + "\""); 1294 if (idRemainder.matches("^:\\d+:.*")) { 1295 idRemainder = idRemainder.substring(1); 1296 int idx = idRemainder.indexOf(":"); 1297 try { 1298 int rowIndex = Integer.parseInt(idRemainder.substring(0, idx)); 1299 LOG.info("set rowIndex = \"" + rowIndex + "\""); 1300 uiData.setRowIndex(rowIndex); 1301 } catch (NumberFormatException e) { 1302 LOG.error("idRemainder = \"" + idRemainder + "\"", e); 1303 } 1304 } else { 1305 LOG.info("no match for \"^:\\d+:.*\""); 1306 } 1307 1308 invokeOrPrepare(facesContext, list, clientId, callback); 1309 1310 // we should reset rowIndex on UIData 1311 uiData.setRowIndex(oldRowIndex); 1312 } 1313 }