org.ajax4jsf.util.SelectUtils.java Source code

Java tutorial

Introduction

Here is the source code for org.ajax4jsf.util.SelectUtils.java

Source

/**
 * License Agreement.
 *
 * Rich Faces - Natural Ajax for Java Server Faces (JSF)
 *
 * Copyright (C) 2007 Exadel, Inc.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License version 2.1 as published by the Free Software Foundation.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
 */

package org.ajax4jsf.util;

import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;

import javax.el.ELContext;
import javax.el.ValueExpression;
import javax.faces.FacesException;
import javax.faces.component.UIComponent;
import javax.faces.component.UIInput;
import javax.faces.component.UIOutput;
import javax.faces.component.UISelectItem;
import javax.faces.component.UISelectItems;
import javax.faces.component.UISelectMany;
import javax.faces.context.FacesContext;
import javax.faces.convert.Converter;
import javax.faces.convert.ConverterException;
import javax.faces.el.ValueBinding;
import javax.faces.model.SelectItem;

import org.ajax4jsf.Messages;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * @author Maksim Kaszynski
 *
 */
public class SelectUtils {

    private static final Log log = LogFactory.getLog(SelectUtils.class);

    /**
     * Gathers all select items from specified component's children
     * @param context
     * @param component
     * @return list of {@link SelectItems} taken from f:selectItem and f:selectItems
     */
    public static List<SelectItem> getSelectItems(FacesContext context, UIComponent component) {
        ArrayList<SelectItem> list = new ArrayList<SelectItem>();
        Iterator<UIComponent> kids = component.getChildren().iterator();
        while (kids.hasNext()) {
            UIComponent kid = kids.next();
            if (kid instanceof UISelectItem) {
                Object value = ((UISelectItem) kid).getValue();
                if (value == null) {
                    UISelectItem item = (UISelectItem) kid;
                    list.add(new SelectItem(item.getItemValue(), item.getItemLabel(), item.getItemDescription(),
                            item.isItemDisabled()));
                } else if (value instanceof SelectItem) {
                    list.add((SelectItem) value);
                } else {
                    String valueClass = (value != null ? "'" + value.getClass().getName() + "'" : "");
                    throw new IllegalArgumentException(
                            Messages.getMessage(Messages.INVALID_ATTRIBUTE_VALUE, valueClass, "<selectItem>"));
                }
            } else if (kid instanceof UISelectItems && null != context) {
                Object value = ((UISelectItems) kid).getValue();
                if (value instanceof SelectItem) {
                    list.add((SelectItem) value);
                } else if (value instanceof SelectItem[]) {
                    SelectItem items[] = (SelectItem[]) value;
                    list.addAll(Arrays.asList(items));
                } else if (value instanceof Collection) {
                    list.addAll(((Collection<SelectItem>) value));
                } else if (value instanceof Map) {
                    Map<Object, Object> map = (Map<Object, Object>) value;
                    Set<Entry<Object, Object>> entrySet = map.entrySet();
                    for (Entry<Object, Object> entry : entrySet) {
                        list.add(new SelectItem(entry.getValue(), entry.getKey().toString(), null));
                    }
                } else {
                    String valueClass = (value != null ? "'" + value.getClass().getName() + "'" : "");
                    throw new IllegalArgumentException(
                            Messages.getMessage(Messages.INVALID_ATTRIBUTE_VALUE, valueClass, "<selectItems>"));
                }
            }
        }
        return list;

    }

    /**
     * Converts UISelectMany submitted value to converted value
     * 
     * @author Manfred Geiler
     * @param facesContext
     * @param component
     * @param submittedValue
     * @return
     * @throws ConverterException
     */
    public static Object getConvertedUISelectManyValue(FacesContext facesContext, UISelectMany component,
            String[] submittedValue) throws ConverterException {
        // Attention!
        // This code is duplicated in jsfapi component package.
        // If you change something here please do the same in the other class!

        if (submittedValue == null)
            throw new NullPointerException("submittedValue");

        ELContext elContext = facesContext.getELContext();
        ValueExpression vb = component.getValueExpression("value");
        Class<?> valueType = null;
        Class<?> arrayComponentType = null;
        if (vb != null) {
            valueType = vb.getType(elContext);
            if (valueType != null && valueType.isArray()) {
                arrayComponentType = valueType.getComponentType();
            }
        }

        Converter converter = component.getConverter();
        if (converter == null) {
            if (valueType == null) {
                // No converter, and no idea of expected type
                // --> return the submitted String array
                return submittedValue;
            }

            if (List.class.isAssignableFrom(valueType)) {
                // expected type is a List
                // --> according to javadoc of UISelectMany we assume that the
                // element type
                // is java.lang.String, and copy the String array to a new List
                List<String> lst = Arrays.asList(submittedValue);
                return lst;
            }

            if (arrayComponentType == null) {
                throw new IllegalArgumentException(Messages.getMessage(Messages.VALUE_BINDING_TYPE_ERROR));
            }

            if (String.class.equals(arrayComponentType))
                return submittedValue; // No conversion needed for String type
            if (Object.class.equals(arrayComponentType))
                return submittedValue; // No conversion for Object class

            try {
                converter = facesContext.getApplication().createConverter(arrayComponentType);
            } catch (FacesException e) {
                log.error(Messages.getMessage(Messages.NO_CONVERTER_FOUND_ERROR, arrayComponentType.getName()), e);
                return submittedValue;
            }
        }

        // Now, we have a converter...
        if (valueType == null) {
            // ...but have no idea of expected type
            // --> so let's convert it to an Object array
            int len = submittedValue.length;
            Object[] convertedValues = (Object[]) Array
                    .newInstance(arrayComponentType == null ? Object.class : arrayComponentType, len);
            for (int i = 0; i < len; i++) {
                convertedValues[i] = converter.getAsObject(facesContext, component, submittedValue[i]);
            }
            return convertedValues;
        }

        if (List.class.isAssignableFrom(valueType)) {
            // Curious case: According to specs we should assume, that the
            // element type
            // of this List is java.lang.String. But there is a Converter set
            // for this
            // component. Because the user must know what he is doing, we will
            // convert the values.
            int len = submittedValue.length;
            List<Object> lst = new ArrayList<Object>(len);
            for (int i = 0; i < len; i++) {
                lst.add(converter.getAsObject(facesContext, component, submittedValue[i]));
            }
            return lst;
        }

        if (arrayComponentType == null) {
            throw new IllegalArgumentException(Messages.getMessage(Messages.VALUE_BINDING_TYPE_ERROR));
        }

        if (arrayComponentType.isPrimitive()) {
            // primitive array
            int len = submittedValue.length;
            Object convertedValues = Array.newInstance(arrayComponentType, len);
            for (int i = 0; i < len; i++) {
                Array.set(convertedValues, i, converter.getAsObject(facesContext, component, submittedValue[i]));
            }
            return convertedValues;
        } else {
            // Object array
            int len = submittedValue.length;
            ArrayList<Object> convertedValues = new ArrayList<Object>(len);
            for (int i = 0; i < len; i++) {
                convertedValues.add(i, converter.getAsObject(facesContext, component, submittedValue[i]));
            }
            return convertedValues.toArray((Object[]) Array.newInstance(arrayComponentType, len));
        }
    }

    public static Object getConvertedUIInputValue(FacesContext facesContext, UIInput component,
            String submittedValue) throws ConverterException {

        Object convertedValue = null;

        /*
        if (submittedValue == null)
           throw new NullPointerException("submittedValue");
        */
        if (InputUtils.EMPTY_STRING.equals(submittedValue)) {
            return null;
        }
        Converter converter = getConverterForProperty(facesContext, component, "value");
        if (converter != null) {
            convertedValue = converter.getAsObject(facesContext, component, submittedValue);
        } else {
            convertedValue = submittedValue;
        }

        return convertedValue;

    }

    /**
     * 
     * @param facesContext
     * @param component
     * @param property
     * @return converter for specified component attribute
     */
    public static Converter getConverterForProperty(FacesContext facesContext, UIOutput component,
            String property) {
        Converter converter = component.getConverter();
        if (converter == null) {
            ValueExpression ve = component.getValueExpression(property);
            if (ve != null) {
                Class<?> valueType = ve.getType(facesContext.getELContext());
                if (valueType == null || String.class.equals(valueType) || Object.class.equals(valueType)) {
                    //No converter needed
                } else {
                    converter = facesContext.getApplication().createConverter(valueType);
                    if (converter == null) {
                        throw new ConverterException(
                                Messages.getMessage(Messages.NO_CONVERTER_FOUND_ERROR, valueType.getName()));
                    }
                }
            }
        }
        return converter;
    }

}