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 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 return Framework.getService(DirectoryService.class); 246 } 247 248}