/* * Copyright (c) 1998-2011 Caucho Technology -- all rights reserved * * This file is part of Resin(R) Open Source * * Each copy or derived work must preserve the copyright notice and this * notice unmodified. * * Resin Open Source is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 * as published by the Free Software Foundation. * * Resin Open Source 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, or any warranty * of NON-INFRINGEMENT. See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License * along with Resin Open Source; if not, write to the * * Free Software Foundation, Inc. * 59 Temple Place, Suite 330 * Boston, MA 02111-1307 USA * * @author Scott Ferguson */ package com.caucho.jsf.html; import com.caucho.util.Html; import javax.faces.component.*; import javax.faces.context.*; import javax.faces.model.*; import javax.faces.convert.*; import javax.el.*; import java.io.*; import java.util.*; import java.lang.reflect.*; /** * The base renderer */ abstract class SelectRenderer extends BaseRenderer { private static Map<Class, Class> _primitiveTypeMap = new HashMap<Class, Class>(); @Override public Object getConvertedValue(FacesContext context, UIComponent component, Object submittedValue) throws ConverterException { if (component instanceof UISelectMany) { return getConvertedValue(context, (UISelectMany)component, submittedValue); } return super.getConvertedValue(context, component, submittedValue); } private Object getConvertedValue(FacesContext context, UISelectMany uiSelectMany, Object submittedValue) throws ConverterException { String []strValues = (String[]) submittedValue; Converter converter = uiSelectMany.getConverter(); Object []values = null; ValueExpression valueExpr = uiSelectMany.getValueExpression("value"); if (valueExpr != null) { Class cl; cl = valueExpr.getType(context.getELContext()); if (cl.isArray()) { cl = cl.getComponentType(); if (cl.isPrimitive()) { cl = _primitiveTypeMap.get(cl); } converter = context.getApplication().createConverter(cl); values = (Object []) Array.newInstance(cl, strValues.length); } else if (java.util.List.class.isAssignableFrom(cl)) { values = strValues; return values; } else { //todo should never happen as per spec. should an exception be thrown? } } else { values = new Object[strValues.length]; } for (int i = 0; i < strValues.length; i++) { if (converter != null) { values[i] = converter.getAsObject(context, uiSelectMany, strValues[i]); } else { values[i] = strValues[i]; } } return values; } public List<SelectItem> accrueSelectItems(UIComponent component) { ArrayList<SelectItem> itemList = new ArrayList<SelectItem>(); int count = component.getChildCount(); if (count == 0) return itemList; List<UIComponent> children = component.getChildren(); for (int i = 0; i < count; i++) { UIComponent child = children.get(i); if (child instanceof UISelectItem) { UISelectItem uiSelectItem = (UISelectItem) child; SelectItem item = (SelectItem) uiSelectItem.getValue(); if (item == null) { item = new SelectItem(uiSelectItem.getItemValue(), uiSelectItem.getItemLabel(), uiSelectItem.getItemDescription(), uiSelectItem.isItemDisabled(), uiSelectItem.isItemEscaped()); } itemList.add(item); } else if (child instanceof UISelectItems) { UISelectItems selectedItems = (UISelectItems) child; Object value = selectedItems.getValue(); if (value instanceof SelectItem) { itemList.add((SelectItem) value); } else if (value instanceof SelectItem []) { SelectItem []items = (SelectItem []) value; itemList.ensureCapacity(itemList.size() + items.length); for (SelectItem item : items) { itemList.add(item); } } else if (value instanceof Collection) { Collection items = (Collection) value; itemList.ensureCapacity(itemList.size() + items.size()); itemList.addAll(items); } else if (value instanceof Map) { Map map = (Map) value; itemList.ensureCapacity(itemList.size() + map.size()); Set<Map.Entry> entries = map.entrySet(); for (Map.Entry entry : entries) { itemList.add(new SelectItem(entry.getValue(), String.valueOf(entry.getKey()))); } } } } return itemList; } protected void encodeChildren(ResponseWriter out, FacesContext context, UIComponent component, Object []values, String enabledClass, String disabledClass) throws IOException { List<SelectItem> list = accrueSelectItems(component); for (int i = 0; i < list.size(); i++) { SelectItem selectItem = list.get(i); out.startElement("option", component); // jsf/31c4 /* out.writeAttribute("id", childId, "id"); //out.writeAttribute("name", child.getClientId(context), "name"); */ if (selectItem.isDisabled()) { out.writeAttribute("disabled", "disabled", "disabled"); if (disabledClass != null) out.writeAttribute("class", disabledClass, "disabledClass"); } else { if (enabledClass != null) out.writeAttribute("class", enabledClass, "enabledClass"); } if (values != null) { for (int j = 0; j < values.length; j++) { if (values[j].equals(selectItem.getValue())) { out.writeAttribute("selected", "selected", "selected"); break; } } } out.writeAttribute("value", String.valueOf(selectItem.getValue()), "value"); String label = selectItem.getLabel(); if (label != null) { if (selectItem.isEscape()) label = Html.escapeHtml(label); out.writeText(label, "label"); } out.endElement("option"); out.write("\n"); } } protected void encodeOneChildren(ResponseWriter out, FacesContext context, UIComponent component, Object value, String enabledClass, String disabledClass) throws IOException { String clientId = component.getClientId(context); ValueExpression ve = component.getValueExpression("value"); Class type = null; if (ve != null) { type = ve.getType(context.getELContext()); } List<SelectItem> items = accrueSelectItems(component); for (int i = 0; i < items.size(); i++) { String childId = clientId + ":" + i; SelectItem selectItem = items.get(i); String itemLabel = selectItem.getLabel(); Object itemValue = selectItem.getValue(); out.startElement("option", component); // jsf/31c4 /* out.writeAttribute("id", childId, "id"); //out.writeAttribute("name", child.getClientId(context), "name"); */ Object optionValue; if (type != null) { optionValue = context.getApplication() .getExpressionFactory() .coerceToType(itemValue, type); } else { optionValue = selectItem.getValue(); } if (value != null && value.equals(optionValue)) out.writeAttribute("selected", "selected", "selected"); if (selectItem.isDisabled()) { out.writeAttribute("disabled", "disabled", "disabled"); if (disabledClass != null) out.writeAttribute("class", disabledClass, "disabledClass"); } else { if (enabledClass != null) out.writeAttribute("class", enabledClass, "enabledClass"); } String itemValueString = toString(context, component, itemValue); out.writeAttribute("value", itemValueString, "value"); if (itemLabel == null) itemLabel = itemValueString; if (selectItem.isEscape()) itemLabel = Html.escapeHtml(itemLabel); out.writeText(itemLabel, "label"); out.endElement("option"); out.write("\n"); } } static { _primitiveTypeMap.put(boolean.class, Boolean.class); _primitiveTypeMap.put(byte.class, Byte.class); _primitiveTypeMap.put(char.class, Character.class); _primitiveTypeMap.put(short.class, Short.class); _primitiveTypeMap.put(int.class, Integer.class); _primitiveTypeMap.put(long.class, Long.class); _primitiveTypeMap.put(float.class, Float.class); _primitiveTypeMap.put(double.class, Double.class); } }