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$ 018 */ 019 020package org.nuxeo.ecm.platform.ui.web.directory; 021 022import java.io.Serializable; 023import java.util.ArrayList; 024import java.util.Collections; 025import java.util.LinkedHashMap; 026import java.util.LinkedList; 027import java.util.List; 028import java.util.Locale; 029import java.util.Map; 030import java.util.Set; 031 032import javax.faces.context.FacesContext; 033 034import org.apache.commons.logging.Log; 035import org.apache.commons.logging.LogFactory; 036import org.nuxeo.common.utils.i18n.I18NUtils; 037import org.nuxeo.ecm.core.api.DocumentModel; 038import org.nuxeo.ecm.core.api.DocumentModelList; 039import org.nuxeo.ecm.core.api.NuxeoException; 040import org.nuxeo.ecm.directory.DirectoryException; 041import org.nuxeo.ecm.directory.Session; 042import org.nuxeo.ecm.directory.api.DirectoryService; 043import org.nuxeo.runtime.api.Framework; 044 045/** 046 * @author <a href="mailto:glefter@nuxeo.com">George Lefter</a> 047 */ 048public final class DirectoryHelper { 049 050 private static final Log log = LogFactory.getLog(DirectoryHelper.class); 051 052 /** Directory with a parent column. */ 053 public static final String XVOCABULARY_TYPE = "xvocabulary"; 054 055 public static final String[] VOCABULARY_TYPES = { "vocabulary", XVOCABULARY_TYPE }; 056 057 private static final String[] displayOptions = { "id", "label", "idAndLabel" }; 058 059 private static DirectoryHelper instance; 060 061 private static DirectoryService service; 062 063 private DirectoryHelper() { 064 } 065 066 public static DirectoryHelper instance() { 067 if (null == instance) { 068 instance = new DirectoryHelper(); 069 } 070 return instance; 071 } 072 073 public boolean hasParentColumn(String directoryName) { 074 try { 075 return XVOCABULARY_TYPE.equals(getService().getDirectorySchema(directoryName)); 076 } catch (DirectoryException e) { 077 // GR: our callers can't throw anything. Better to catch here, then 078 log.error("Could not retrieve schema name for directory: " + directoryName, e); 079 return false; 080 } 081 } 082 083 public DirectorySelectItem getSelectItem(String directoryName, Map<String, Serializable> filter) { 084 List<DirectorySelectItem> items = getSelectItems(directoryName, filter); 085 if (items.size() > 1) { 086 log.warn("More than one entry found in directory " + directoryName + " and filter:"); 087 for (Map.Entry<String, Serializable> e : filter.entrySet()) { 088 log.warn(String.format("%s=%s", e.getKey(), e.getValue())); 089 } 090 } else if (items.isEmpty()) { 091 return null; 092 } 093 return items.get(0); 094 } 095 096 public List<DirectorySelectItem> getSelectItems(String directoryName, Map<String, Serializable> filter) { 097 return getSelectItems(directoryName, filter, Boolean.FALSE); 098 } 099 100 public List<DirectorySelectItem> getSelectItems(String directoryName, Map<String, Serializable> filter, 101 Boolean localize) { 102 List<DirectorySelectItem> list = new LinkedList<DirectorySelectItem>(); 103 104 Set<String> emptySet = Collections.emptySet(); 105 106 Map<String, String> orderBy = new LinkedHashMap<String, String>(); 107 108 FacesContext context = FacesContext.getCurrentInstance(); 109 110 // an extended schema also has parent field 111 try (Session session = getService().open(directoryName)) { 112 String schema = getService().getDirectorySchema(directoryName); 113 if (session == null) { 114 throw new NuxeoException("could not open session on directory: " + directoryName); 115 } 116 117 // adding sorting support 118 // XXX It seems that this ordering is obsolete as 119 // DirectoryAwareComponent made it's own (NXP-7349) 120 if (schema.equals(VOCABULARY_TYPES[0]) || schema.equals(VOCABULARY_TYPES[1])) { 121 orderBy.put("ordering", "asc"); 122 orderBy.put("id", "asc"); 123 } 124 125 DocumentModelList docModelList = session.query(filter, emptySet, orderBy); 126 127 for (DocumentModel docModel : docModelList) { 128 String id = (String) docModel.getProperty(schema, "id"); 129 String label = (String) docModel.getProperty(schema, "label"); 130 long ordering = (Long) docModel.getProperty(schema, "ordering"); 131 132 if (Boolean.TRUE.equals(localize)) { 133 label = translate(context, label); 134 } 135 DirectorySelectItem item = new DirectorySelectItem(id, label, ordering); 136 list.add(item); 137 } 138 139 } 140 141 return list; 142 } 143 144 public static DirectoryService getDirectoryService() { 145 return instance().getService(); 146 } 147 148 public static List<DirectorySelectItem> getSelectItems(VocabularyEntryList directoryValues, 149 Map<String, Serializable> filter) { 150 return getSelectItems(directoryValues, filter, Boolean.FALSE); 151 } 152 153 public static List<DirectorySelectItem> getSelectItems(VocabularyEntryList directoryValues, 154 Map<String, Serializable> filter, Boolean localize) { 155 List<DirectorySelectItem> list = new ArrayList<DirectorySelectItem>(); 156 157 // in obsolete filter we have either null (include obsoletes) 158 // or 0 (don't include obsoletes) 159 boolean obsolete = filter.get("obsolete") == null; 160 String parentFilter = (String) filter.get("parent"); 161 162 FacesContext context = FacesContext.getCurrentInstance(); 163 for (VocabularyEntry entry : directoryValues.getEntries()) { 164 if (!obsolete && Boolean.TRUE.equals(entry.getObsolete())) { 165 continue; 166 } 167 String parent = entry.getParent(); 168 if (parentFilter == null) { 169 if (parent != null) { 170 continue; 171 } 172 } else if (!parentFilter.equals(parent)) { 173 continue; 174 } 175 176 String idValue = (String) filter.get("id"); 177 if (idValue != null && !idValue.equals(entry.getId())) { 178 continue; 179 } 180 String id = entry.getId(); 181 String label = entry.getLabel(); 182 if (Boolean.TRUE.equals(localize)) { 183 label = translate(context, label); 184 } 185 DirectorySelectItem item = new DirectorySelectItem(id, label); 186 list.add(item); 187 } 188 return list; 189 } 190 191 public static String getOptionValue(String optionId, String optionLabel, String display, boolean displayIdAndLabel, 192 String displayIdAndLabelSeparator) { 193 StringBuilder displayValue = new StringBuilder(); 194 if (display != null && !"".equals(display)) { 195 if (display.equals(displayOptions[0])) { 196 displayValue.append(optionId); 197 } else if (display.equals(displayOptions[1])) { 198 displayValue.append(optionLabel); 199 } else if (display.equals(displayOptions[2])) { 200 displayValue.append(optionId).append(displayIdAndLabelSeparator).append(optionLabel); 201 } else { 202 displayValue.append(optionLabel); 203 } 204 } else if (displayIdAndLabel) { 205 displayValue.append(optionId).append(displayIdAndLabelSeparator).append(optionLabel); 206 } else { 207 displayValue.append(optionLabel); 208 } 209 return displayValue.toString(); 210 } 211 212 private static DocumentModel getEntryThrows(String directoryName, String entryId) { 213 DirectoryService dirService = getDirectoryService(); 214 try (Session session = dirService.open(directoryName)) { 215 return session.getEntry(entryId); 216 } 217 } 218 219 /** 220 * Returns the entry with given id from specified directory. 221 * <p> 222 * Method to use from components, since JSF base class that we extend don't allow to throw proper exceptions. 223 * 224 * @param directoryName 225 * @param entryId 226 * @return the entry, or null in case of exception in callees. 227 */ 228 public static DocumentModel getEntry(String directoryName, String entryId) { 229 try { 230 return getEntryThrows(directoryName, entryId); 231 } catch (DirectoryException e) { 232 log.error(String.format("Error retrieving the entry (dirname=%s, entryId=%s)", directoryName, entryId), e); 233 return null; 234 } 235 } 236 237 protected static String translate(FacesContext context, String label) { 238 String bundleName = context.getApplication().getMessageBundle(); 239 Locale locale = context.getViewRoot().getLocale(); 240 label = I18NUtils.getMessageString(bundleName, label, null, locale); 241 return label; 242 } 243 244 protected DirectoryService getService() { 245 if (service == null) { 246 service = Framework.getService(DirectoryService.class); 247 } 248 return service; 249 } 250 251}