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