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 }