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