001/* 002 * Copyright 2004 The Apache Software Foundation. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.nuxeo.ecm.platform.ui.web.component; 017 018import java.util.Collections; 019import java.util.List; 020import java.util.Locale; 021import java.util.Map; 022 023import javax.el.ValueExpression; 024import javax.faces.context.FacesContext; 025import javax.faces.model.SelectItem; 026 027import org.apache.commons.lang3.StringUtils; 028import org.nuxeo.common.utils.i18n.I18NUtils; 029import org.nuxeo.ecm.platform.ui.web.util.ComponentTagUtils; 030 031/** 032 * EasySelectItems from http://jsf-comp.sourceforge.net/components/easysi/index.html, adapted to work with jboss seam 033 * ListDataModel instances. 034 * <p> 035 * Adapted to handle ordering and disabling of select items. 036 * 037 * @author Cagatay-Mert 038 * @author <a href="mailto:[email protected]">Anahide Tchertchian</a> 039 */ 040public class UISelectItems extends javax.faces.component.UISelectItems implements ResettableComponent { 041 042 public static final String COMPONENT_TYPE = UISelectItems.class.getName(); 043 044 protected enum PropertyKeys { 045 value, var, itemLabel, itemLabels, resolveItemLabelTwice, 046 // 047 itemLabelPrefix, itemLabelPrefixSeparator, 048 // 049 itemLabelSuffix, itemLabelSuffixSeparator, 050 // 051 itemValue, itemRendered, itemDisabled, itemEscaped, 052 // 053 ordering, caseSensitive, 054 // 055 displayIdAndLabel, displayIdAndLabelSeparator, 056 // 057 localize, dbl10n; 058 } 059 060 public String getVar() { 061 return (String) getStateHelper().eval(PropertyKeys.var); 062 } 063 064 public void setVar(String var) { 065 getStateHelper().put(PropertyKeys.var, var); 066 } 067 068 public Object getItemLabel() { 069 return getStateHelper().eval(PropertyKeys.itemLabel); 070 } 071 072 public void setItemLabel(Object itemLabel) { 073 getStateHelper().put(PropertyKeys.itemLabel, itemLabel); 074 } 075 076 @SuppressWarnings("unchecked") 077 public Map<String, String> getItemLabels() { 078 return (Map<String, String>) getStateHelper().eval(PropertyKeys.itemLabels); 079 } 080 081 public void setItemLabels(Map<String, String> itemLabels) { 082 getStateHelper().put(PropertyKeys.itemLabels, itemLabels); 083 } 084 085 public String getItemLabelPrefix() { 086 return (String) getStateHelper().eval(PropertyKeys.itemLabelPrefix); 087 } 088 089 public void setItemLabelPrefix(String itemLabelPrefix) { 090 getStateHelper().put(PropertyKeys.itemLabelPrefix, itemLabelPrefix); 091 } 092 093 public String getItemLabelPrefixSeparator() { 094 return (String) getStateHelper().eval(PropertyKeys.itemLabelPrefixSeparator, " "); 095 } 096 097 public void setItemLabelPrefixSeparator(String itemLabelPrefix) { 098 getStateHelper().put(PropertyKeys.itemLabelPrefixSeparator, itemLabelPrefix); 099 } 100 101 public String getItemLabelSuffix() { 102 return (String) getStateHelper().eval(PropertyKeys.itemLabelSuffix); 103 } 104 105 public void setItemLabelSuffix(String itemLabelSuffix) { 106 getStateHelper().put(PropertyKeys.itemLabelSuffix, itemLabelSuffix); 107 } 108 109 public String getItemLabelSuffixSeparator() { 110 return (String) getStateHelper().eval(PropertyKeys.itemLabelSuffixSeparator, " "); 111 } 112 113 public void setItemLabelSuffixSeparator(String itemLabelSuffix) { 114 getStateHelper().put(PropertyKeys.itemLabelSuffixSeparator, itemLabelSuffix); 115 } 116 117 public Object getItemValue() { 118 return getStateHelper().eval(PropertyKeys.itemValue); 119 } 120 121 public void setItemValue(Object itemValue) { 122 getStateHelper().put(PropertyKeys.itemValue, itemValue); 123 } 124 125 public boolean isItemDisabled() { 126 return Boolean.TRUE.equals(getStateHelper().eval(PropertyKeys.itemDisabled, Boolean.FALSE)); 127 } 128 129 @SuppressWarnings("boxing") 130 public void setItemDisabled(boolean itemDisabled) { 131 getStateHelper().put(PropertyKeys.itemDisabled, itemDisabled); 132 } 133 134 public boolean isResolveItemLabelTwice() { 135 return Boolean.TRUE.equals(getStateHelper().eval(PropertyKeys.resolveItemLabelTwice, Boolean.FALSE)); 136 } 137 138 @SuppressWarnings("boxing") 139 public void setResolveItemLabelTwice(boolean resolveItemLabelTwice) { 140 getStateHelper().put(PropertyKeys.resolveItemLabelTwice, resolveItemLabelTwice); 141 } 142 143 public boolean isItemRendered() { 144 return Boolean.TRUE.equals(getStateHelper().eval(PropertyKeys.itemRendered, Boolean.TRUE)); 145 } 146 147 @SuppressWarnings("boxing") 148 public void setItemRendered(boolean itemRendered) { 149 getStateHelper().put(PropertyKeys.itemRendered, itemRendered); 150 } 151 152 public boolean isItemEscaped() { 153 return Boolean.TRUE.equals(getStateHelper().eval(PropertyKeys.itemEscaped, Boolean.FALSE)); 154 } 155 156 @SuppressWarnings("boxing") 157 public void setItemEscaped(boolean itemEscaped) { 158 getStateHelper().put(PropertyKeys.itemEscaped, itemEscaped); 159 } 160 161 public String getOrdering() { 162 return (String) getStateHelper().eval(PropertyKeys.ordering); 163 } 164 165 public void setOrdering(String ordering) { 166 getStateHelper().put(PropertyKeys.ordering, ordering); 167 } 168 169 public boolean isCaseSensitive() { 170 return Boolean.TRUE.equals(getStateHelper().eval(PropertyKeys.caseSensitive)); 171 } 172 173 @SuppressWarnings("boxing") 174 public void setCaseSensitive(boolean caseSensitive) { 175 getStateHelper().put(PropertyKeys.caseSensitive, caseSensitive); 176 } 177 178 public boolean isDisplayIdAndLabel() { 179 return Boolean.TRUE.equals(getStateHelper().eval(PropertyKeys.displayIdAndLabel)); 180 } 181 182 @SuppressWarnings("boxing") 183 public void setDisplayIdAndLabel(boolean displayIdAndLabel) { 184 getStateHelper().put(PropertyKeys.displayIdAndLabel, displayIdAndLabel); 185 } 186 187 public String getDisplayIdAndLabelSeparator() { 188 return (String) getStateHelper().eval(PropertyKeys.displayIdAndLabelSeparator, " "); 189 } 190 191 public void setDisplayIdAndLabelSeparator(String idAndLabelSeparator) { 192 getStateHelper().put(PropertyKeys.displayIdAndLabelSeparator, idAndLabelSeparator); 193 } 194 195 @SuppressWarnings("boxing") 196 public boolean isLocalize() { 197 return (Boolean) getStateHelper().eval(PropertyKeys.localize, Boolean.FALSE); 198 } 199 200 @SuppressWarnings("boxing") 201 public void setLocalize(boolean localize) { 202 getStateHelper().put(PropertyKeys.localize, localize); 203 } 204 205 @SuppressWarnings("boxing") 206 public boolean isdbl10n() { 207 return (Boolean) getStateHelper().eval(PropertyKeys.dbl10n, Boolean.FALSE); 208 } 209 210 @SuppressWarnings("boxing") 211 public void setdbl10n(boolean dbl10n) { 212 getStateHelper().put(PropertyKeys.dbl10n, dbl10n); 213 } 214 215 @Override 216 public Object getValue() { 217 Object value = super.getValue(); 218 List<SelectItem> items = new SelectItemsFactory() { 219 @Override 220 protected String getVar() { 221 return UISelectItems.this.getVar(); 222 } 223 224 @Override 225 protected SelectItem createSelectItem() { 226 return UISelectItems.this.createSelectItem(); 227 } 228 229 }.createSelectItems(value); 230 231 String ordering = getOrdering(); 232 boolean caseSensitive = isCaseSensitive(); 233 if (!StringUtils.isBlank(ordering)) { 234 Collections.sort(items, new SelectItemComparator(ordering, Boolean.valueOf(caseSensitive))); 235 } 236 return items.toArray(new SelectItem[0]); 237 } 238 239 protected String translate(FacesContext context, Locale locale, String label) { 240 if (StringUtils.isBlank(label)) { 241 return label; 242 } 243 String bundleName = context.getApplication().getMessageBundle(); 244 label = I18NUtils.getMessageString(bundleName, label, null, locale); 245 return label; 246 } 247 248 protected String retrieveItemLabel() { 249 FacesContext ctx = FacesContext.getCurrentInstance(); 250 Locale locale = ctx.getViewRoot().getLocale(); 251 String label = null; 252 if (isdbl10n()) { 253 Map<String, String> labels = getItemLabels(); 254 if (labels != null) { 255 if (labels.containsKey(locale.getLanguage())) { 256 label = labels.get(locale.getLanguage()); 257 } else { 258 // fallback on en 259 label = labels.get("en"); 260 } 261 } 262 } 263 if (StringUtils.isBlank(label)) { 264 Object labelObject = getItemLabel(); 265 label = labelObject != null ? labelObject.toString() : null; 266 } 267 if (isResolveItemLabelTwice() && ComponentTagUtils.isValueReference(label)) { 268 ValueExpression ve = ctx.getApplication().getExpressionFactory().createValueExpression(ctx.getELContext(), 269 label, Object.class); 270 if (ve != null) { 271 Object newLabel = ve.getValue(ctx.getELContext()); 272 if (newLabel instanceof String) { 273 label = (String) newLabel; 274 } 275 } 276 } 277 if (isLocalize()) { 278 label = translate(ctx, locale, label); 279 } 280 return label; 281 } 282 283 protected SelectItem createSelectItem() { 284 if (!isItemRendered()) { 285 return null; 286 } 287 Object value = getItemValue(); 288 String label = retrieveItemLabel(); 289 if (isDisplayIdAndLabel() && label != null) { 290 label = value + getDisplayIdAndLabelSeparator() + label; 291 } 292 // make sure label is never blank 293 if (StringUtils.isBlank(label)) { 294 label = String.valueOf(value); 295 } 296 String labelPrefix = getItemLabelPrefix(); 297 if (!StringUtils.isBlank(labelPrefix)) { 298 label = labelPrefix + getItemLabelPrefixSeparator() + label; 299 } 300 String labelSuffix = getItemLabelSuffix(); 301 if (!StringUtils.isBlank(labelSuffix)) { 302 label = label + getItemLabelSuffixSeparator() + labelSuffix; 303 } 304 return new SelectItem(value, label, null, isItemDisabled(), isItemEscaped()); 305 } 306 307 /** 308 * Reset the local value set, useful to reset cache on ajax action when using a shuttle widget for instance. 309 * 310 * @since 5.7 311 */ 312 @Override 313 public void resetCachedModel() { 314 setValue(null); 315 } 316 317}