blob: f5bea461364cc7b9d63c255381d5d0c2472900aa [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.myfaces.renderkit.html.util;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import javax.faces.component.UIComponent;
import javax.faces.component.UISelectItems;
import javax.faces.component.UISelectMany;
import javax.faces.component.UISelectOne;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
import javax.faces.convert.Converter;
import javax.faces.model.SelectItem;
import javax.faces.model.SelectItemGroup;
import org.apache.myfaces.core.api.shared.SelectItemsIterator;
import org.apache.myfaces.renderkit.RendererUtils;
import static org.apache.myfaces.renderkit.html.util.HtmlRendererUtils.isHideNoSelectionOption;
/**
* Utility methods to manipulate SelectItem/SelectItems
*/
public class SelectItemsUtils
{
private static final char TABULATOR = '\t';
public static List<SelectItemInfo> getSelectItemInfoList(UISelectMany uiSelectMany, FacesContext facesContext)
{
List<SelectItemInfo> list = new ArrayList<>();
for (SelectItemsIterator iter = new SelectItemsIterator(uiSelectMany, facesContext); iter.hasNext();)
{
list.add(new SelectItemInfo(iter.next(), iter.getCurrentComponent(), iter.getCurrentValue()));
}
return list;
}
public static List<SelectItemInfo> getSelectItemInfoList(UISelectOne uiSelectOne, FacesContext facesContext)
{
List<SelectItemInfo> list = new ArrayList<>();
for (SelectItemsIterator iter = new SelectItemsIterator(uiSelectOne, facesContext); iter.hasNext();)
{
list.add(new SelectItemInfo(iter.next(), iter.getCurrentComponent(), iter.getCurrentValue()));
}
return list;
}
public static void renderSelectOptions(FacesContext context,
UIComponent component, Converter converter, Set lookupSet,
List<SelectItemInfo> selectItemList) throws IOException
{
ResponseWriter writer = context.getResponseWriter();
// check for the hideNoSelectionOption attribute
boolean hideNoSelectionOption = isHideNoSelectionOption(component);
boolean componentDisabled = isTrue(component.getAttributes().get("disabled"));
for (int i = 0; i < selectItemList.size(); i++)
{
SelectItemInfo selectItemInfo = selectItemList.get(i);
SelectItem selectItem = selectItemInfo.getItem();
if (selectItem instanceof SelectItemGroup)
{
writer.startElement(HTML.OPTGROUP_ELEM, selectItemInfo.getComponent()); // component);
writer.writeAttribute(HTML.LABEL_ATTR, selectItem.getLabel(), null);
SelectItem[] selectItems = ((SelectItemGroup) selectItem).getSelectItems();
List<SelectItemInfo> selectItemsGroupList = new ArrayList<>(selectItems.length);
for (SelectItem item : selectItems)
{
selectItemsGroupList.add(new SelectItemInfo(item, null));
}
renderSelectOptions(context, component, converter, lookupSet,
selectItemsGroupList);
writer.endElement(HTML.OPTGROUP_ELEM);
}
else
{
String itemStrValue = org.apache.myfaces.renderkit.RendererUtils
.getConvertedStringValue(context, component, converter,
selectItem);
boolean selected = lookupSet.contains(itemStrValue);
//TODO/FIX: we always compare the String vales, better fill lookupSet with Strings
//only when useSubmittedValue==true, else use the real item value Objects
// IF the hideNoSelectionOption attribute of the component is true
// AND this selectItem is the "no selection option"
// AND there are currently selected items
// AND this item (the "no selection option") is not selected
// (if there is currently no value on UISelectOne, lookupSet contains "")
if (hideNoSelectionOption && selectItem.isNoSelectionOption()
&& !lookupSet.isEmpty()
&& !(lookupSet.size() == 1 && lookupSet.contains(""))
&& !selected)
{
// do not render this selectItem
continue;
}
writer.write(TABULATOR);
boolean wroteRequestMapVarValue = false;
Object oldRequestMapVarValue = null;
String var = null;
if (selectItemInfo != null && selectItemInfo.getComponent() instanceof UISelectItems)
{
var = (String) selectItemInfo.getComponent().getAttributes().get(JSFAttr.VAR_ATTR);
if(var != null && !var.isEmpty())
{
// save the current value of the key listed in var from the request map
oldRequestMapVarValue = context.getExternalContext().getRequestMap().put(var,
selectItemInfo.getValue());
wroteRequestMapVarValue = true;
}
}
writer.startElement(HTML.OPTION_ELEM, selectItemInfo.getComponent());
if (itemStrValue != null)
{
writer.writeAttribute(HTML.VALUE_ATTR, itemStrValue, null);
}
else
{
writer.writeAttribute(HTML.VALUE_ATTR, "", null);
}
if (selected)
{
writer.writeAttribute(HTML.SELECTED_ATTR, HTML.SELECTED_ATTR, null);
}
boolean disabled = selectItem.isDisabled();
if (disabled)
{
writer.writeAttribute(HTML.DISABLED_ATTR, HTML.DISABLED_ATTR, null);
}
String labelClass = null;
if (componentDisabled || disabled)
{
labelClass = (String) component.getAttributes().get(JSFAttr.DISABLED_CLASS_ATTR);
}
else
{
labelClass = (String) component.getAttributes().get(JSFAttr.ENABLED_CLASS_ATTR);
}
if (labelClass != null)
{
writer.writeAttribute("class", labelClass, "labelClass");
}
boolean escape = RendererUtils.getBooleanAttribute(component, JSFAttr.ESCAPE_ATTR, false);
//default is to escape
//In JSF 1.2, when a SelectItem is created by default
//selectItem.isEscape() returns true (this property
//is not available on JSF 1.1).
//so, if we found a escape property on the component
//set to true, escape every item, but if not
//check if isEscape() = true first.
if (escape || selectItem.isEscape())
{
writer.writeText(selectItem.getLabel(), null);
}
else
{
writer.write(selectItem.getLabel());
}
writer.endElement(HTML.OPTION_ELEM);
// remove the value with the key from var from the request map, if previously written
if(wroteRequestMapVarValue)
{
// If there was a previous value stored with the key from var in the request map, restore it
if (oldRequestMapVarValue != null)
{
context.getExternalContext().getRequestMap().put(var, oldRequestMapVarValue);
}
else
{
context.getExternalContext().getRequestMap().remove(var);
}
}
}
}
}
private static boolean isTrue(Object obj)
{
if (obj instanceof String)
{
return Boolean.valueOf((String) obj);
}
if (!(obj instanceof Boolean))
{
return false;
}
return ((Boolean) obj);
}
}