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