001/* 002 * (C) Copyright 2006-2007 Nuxeo SAS (http://nuxeo.com/) and contributors. 003 * 004 * All rights reserved. This program and the accompanying materials 005 * are made available under the terms of the GNU Lesser General Public License 006 * (LGPL) version 2.1 which accompanies this distribution, and is available at 007 * http://www.gnu.org/licenses/lgpl.html 008 * 009 * This library is distributed in the hope that it will be useful, 010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 012 * Lesser General Public License for more details. 013 * 014 * Contributors: 015 * Nuxeo - initial API and implementation 016 * 017 * $Id: DirectoryEntryOutputComponent.java 23036 2007-07-27 11:34:11Z btatar $ 018 */ 019 020package org.nuxeo.ecm.platform.ui.web.directory; 021 022import java.io.Serializable; 023import java.util.ArrayList; 024import java.util.HashMap; 025import java.util.List; 026import java.util.Locale; 027import java.util.Map; 028 029import javax.faces.component.UIOutput; 030import javax.faces.context.FacesContext; 031import javax.faces.el.ValueBinding; 032 033import org.apache.commons.lang.StringUtils; 034import org.apache.commons.logging.Log; 035import org.apache.commons.logging.LogFactory; 036import org.nuxeo.common.utils.i18n.I18NUtils; 037 038/** 039 * Component to display a chained directory entry. 040 * 041 * @author <a href="mailto:glefter@nuxeo.com">George Lefter</a> 042 */ 043public class ChainSelectOutputComponent extends UIOutput { 044 045 public static final String COMPONENT_TYPE = "nxdirectory.ChainSelectOutput"; 046 047 public static final String COMPONENT_FAMILY = "nxdirectory.ChainSelectOutput"; 048 049 @SuppressWarnings("unused") 050 private static final Log log = LogFactory.getLog(ChainSelect.class); 051 052 private static final String DISPLAY_ID_AND_LABEL_SEPARATOR = " "; 053 054 private static final String DEFAULT_ENTRY_SEPARATOR = ", "; 055 056 protected Boolean displayIdAndLabel; 057 058 protected Boolean localize; 059 060 protected String display; 061 062 protected String directoryNameList; 063 064 protected Boolean displayObsoleteEntries; 065 066 protected String keySeparator; 067 068 protected String displayKeySeparator; 069 070 protected Boolean qualifiedParentKeys; 071 072 protected Boolean handleMultipleValues = false; 073 074 private String entrySeparator; 075 076 private String cssStyle; 077 078 private String cssStyleClass; 079 080 public ChainSelectOutputComponent() { 081 setRendererType(COMPONENT_TYPE); 082 } 083 084 @Override 085 public String getFamily() { 086 return COMPONENT_FAMILY; 087 } 088 089 public String getKeySeparator() { 090 String ret = null; 091 ValueBinding vb = getValueBinding("keySeparator"); 092 if (vb != null) { 093 ret = (String) vb.getValue(getFacesContext()); 094 } else { 095 ret = keySeparator; 096 } 097 if (ret == null) { 098 ret = ChainSelect.DEFAULT_KEY_SEPARATOR; 099 } 100 return ret; 101 } 102 103 public void setDisplayKeySeparator(String keySeparator) { 104 displayKeySeparator = keySeparator; 105 } 106 107 public String getDisplayKeySeparator() { 108 String ret = null; 109 ValueBinding vb = getValueBinding("displayKeySeparator"); 110 if (vb != null) { 111 ret = (String) vb.getValue(getFacesContext()); 112 } else { 113 ret = displayKeySeparator; 114 } 115 if (ret == null) { 116 ret = getKeySeparator(); 117 } 118 return ret; 119 } 120 121 public void setKeySeparator(String keySeparator) { 122 this.keySeparator = keySeparator; 123 } 124 125 public boolean getQualifiedParentKeys() { 126 Boolean ret = null; 127 ValueBinding vb = getValueBinding("qualifiedParentKeys"); 128 if (vb != null) { 129 ret = (Boolean) vb.getValue(getFacesContext()); 130 } else { 131 ret = qualifiedParentKeys; 132 } 133 return Boolean.TRUE.equals(ret); 134 } 135 136 public boolean getHandleMultipleValues() { 137 Boolean ret = null; 138 ValueBinding vb = getValueBinding("handleMultipleValues"); 139 if (vb != null) { 140 ret = (Boolean) vb.getValue(getFacesContext()); 141 } else { 142 ret = handleMultipleValues; 143 } 144 return Boolean.TRUE.equals(ret); 145 } 146 147 public void setHandleMultipleValues(boolean handleMultipleValues) { 148 this.handleMultipleValues = handleMultipleValues; 149 } 150 151 public void setQualifiedParentKeys(boolean qualifiedParentKeys) { 152 this.qualifiedParentKeys = qualifiedParentKeys; 153 } 154 155 /** 156 * @deprecated use display=id|label|idAndLabel instead 157 */ 158 @Deprecated 159 public boolean getDisplayIdAndLabel() { 160 Boolean ret; 161 ValueBinding vb = getValueBinding("displayIdAndLabel"); 162 if (vb != null) { 163 ret = (Boolean) vb.getValue(getFacesContext()); 164 } else { 165 ret = displayIdAndLabel; 166 } 167 return Boolean.TRUE.equals(ret); 168 } 169 170 public void setDisplayIdAndLabel(boolean displayIdAndLabel) { 171 this.displayIdAndLabel = displayIdAndLabel; 172 } 173 174 public boolean getLocalize() { 175 return Boolean.TRUE.equals(localize); 176 } 177 178 public void setLocalize(boolean localize) { 179 this.localize = localize; 180 } 181 182 /** 183 * Hide legacy "displayIdAndLabel" property. Use "display" if set; else if "displayIdAndLabel" is true, return 184 * "idAndLabel", else default to "label". 185 * 186 * @return whether to display the id, the label or both 187 */ 188 public String getDisplay() { 189 String ret; 190 ValueBinding vb = getValueBinding("display"); 191 if (vb != null) { 192 ret = (String) vb.getValue(getFacesContext()); 193 } else { 194 ret = display; 195 } 196 197 if (ret == null) { 198 boolean displayIdAndLabel = getDisplayIdAndLabel(); 199 ret = displayIdAndLabel ? "idAndLabel" : "label"; 200 } 201 202 return ret; 203 } 204 205 public void setDisplay(String display) { 206 this.display = display; 207 } 208 209 @Override 210 public Object saveState(FacesContext context) { 211 Object[] values = new Object[12]; 212 values[0] = super.saveState(context); 213 values[1] = displayIdAndLabel; 214 values[2] = localize; 215 values[3] = display; 216 values[4] = displayObsoleteEntries; 217 values[5] = directoryNameList; 218 values[6] = qualifiedParentKeys; 219 values[7] = keySeparator; 220 values[8] = cssStyle; 221 values[9] = cssStyleClass; 222 values[10] = entrySeparator; 223 values[11] = handleMultipleValues; 224 return values; 225 } 226 227 @Override 228 public void restoreState(FacesContext context, Object state) { 229 Object[] values = (Object[]) state; 230 super.restoreState(context, values[0]); 231 displayIdAndLabel = (Boolean) values[1]; 232 localize = (Boolean) values[2]; 233 display = (String) values[3]; 234 displayObsoleteEntries = (Boolean) values[4]; 235 directoryNameList = (String) values[5]; 236 qualifiedParentKeys = (Boolean) values[6]; 237 keySeparator = (String) values[7]; 238 cssStyle = (String) values[8]; 239 cssStyleClass = (String) values[9]; 240 entrySeparator = (String) values[10]; 241 handleMultipleValues = (Boolean) values[11]; 242 } 243 244 public boolean getDisplayObsoleteEntries() { 245 return Boolean.TRUE.equals(displayObsoleteEntries); 246 } 247 248 /** 249 * Transform a comma-separated list of keys into a selection. The list can be separated by the <b>keySeparator</b> 250 * string 251 * 252 * @param keyEnum the comma-separated list of keys 253 * @return 254 */ 255 public Selection createSelection(String keyEnum) { 256 String keySeparator = getKeySeparator(); 257 String[] columns = StringUtils.split(keyEnum, keySeparator); 258 259 List<String> keyList = new ArrayList<String>(); 260 List<DirectorySelectItem> itemList = new ArrayList<DirectorySelectItem>(); 261 String directoryNameList = getDirectoryNameList(); 262 String[] directoryNames = StringUtils.split(directoryNameList, ","); 263 boolean qualifiedParentKeys = getQualifiedParentKeys(); 264 boolean displayObsoleteEntries = getDisplayObsoleteEntries(); 265 String display = getDisplay(); 266 267 for (int i = 0; i < directoryNames.length; i++) { 268 directoryNames[i] = directoryNames[i].trim(); 269 } 270 271 for (int i = 0; i < columns.length; i++) { 272 String id = columns[i]; 273 274 String directoryName = directoryNames[i]; 275 276 Map<String, Serializable> filter = new HashMap<String, Serializable>(); 277 filter.put("id", id); 278 279 if (i == 0) { 280 if (DirectoryHelper.instance().hasParentColumn(directoryName)) { 281 // explicitely filter on NULL parent in a xvocabulary 282 filter.put("parent", null); 283 } 284 } else { 285 String parentId; 286 if (qualifiedParentKeys) { 287 parentId = StringUtils.join(keyList.iterator(), keySeparator); 288 } else { 289 parentId = columns[i - 1]; 290 } 291 filter.put("parent", parentId); 292 } 293 294 keyList.add(id); 295 296 if (!displayObsoleteEntries) { 297 filter.put("obsolete", 0); 298 } 299 DirectorySelectItem item = DirectoryHelper.instance().getSelectItem(directoryName, filter); 300 if (item == null) { 301 item = new DirectorySelectItem(id, id); 302 } 303 String itemId = (String) item.getValue(); 304 String label = item.getLabel(); 305 if (getLocalize()) { 306 label = translate(getFacesContext(), label); 307 } 308 if ("id".equals(display)) { 309 label = id; 310 } else if ("idAndLabel".equals(display)) { 311 label = itemId + DISPLAY_ID_AND_LABEL_SEPARATOR + label; 312 } 313 item.setLabel(label); 314 itemList.add(item); 315 } 316 return new Selection(itemList.toArray(new DirectorySelectItem[columns.length])); 317 } 318 319 protected static String translate(FacesContext context, String label) { 320 String bundleName = context.getApplication().getMessageBundle(); 321 Locale locale = context.getViewRoot().getLocale(); 322 label = I18NUtils.getMessageString(bundleName, label, null, locale); 323 return label; 324 } 325 326 public String getEntrySeparator() { 327 String ret = null; 328 ValueBinding vb = getValueBinding("entrySeparator"); 329 if (vb != null) { 330 ret = (String) vb.getValue(getFacesContext()); 331 } else { 332 ret = entrySeparator; 333 } 334 return entrySeparator == null ? DEFAULT_ENTRY_SEPARATOR : entrySeparator; 335 } 336 337 public void setEntrySeparator(String entrySeparator) { 338 this.entrySeparator = entrySeparator; 339 } 340 341 public String getCssStyle() { 342 return cssStyle; 343 } 344 345 public void setCssStyle(String cssStyle) { 346 this.cssStyle = cssStyle; 347 } 348 349 public String getCssStyleClass() { 350 return cssStyleClass; 351 } 352 353 public void setCssStyleClass(String cssStyleClass) { 354 this.cssStyleClass = cssStyleClass; 355 } 356 357 public void setDisplayObsoleteEntries(Boolean displayObsoleteEntries) { 358 this.displayObsoleteEntries = displayObsoleteEntries; 359 } 360 361 public void setDisplayObsoleteEntries(boolean displayObsoleteEntries) { 362 this.displayObsoleteEntries = displayObsoleteEntries; 363 } 364 365 public void setQualifiedParentKeys(Boolean qualifiedParentKeys) { 366 this.qualifiedParentKeys = qualifiedParentKeys; 367 } 368 369 public String getDirectoryNameList() { 370 String ret; 371 ValueBinding vb = getValueBinding("directoryNameList"); 372 if (vb != null) { 373 ret = (String) vb.getValue(getFacesContext()); 374 } else { 375 ret = directoryNameList; 376 } 377 return ret; 378 } 379 380 public void setDirectoryNameList(String directoryNameList) { 381 this.directoryNameList = directoryNameList; 382 } 383 384}