001/* 002 * (C) Copyright 2014 Nuxeo SA (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-2.1.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 * Anahide Tchertchian 016 */ 017package org.nuxeo.ecm.platform.ui.web.directory; 018 019import java.io.Serializable; 020import java.util.ArrayList; 021import java.util.Collection; 022import java.util.HashMap; 023import java.util.List; 024import java.util.Map; 025 026import javax.el.PropertyNotFoundException; 027import javax.faces.model.ListDataModel; 028import javax.faces.model.SelectItem; 029 030import org.apache.commons.lang.StringUtils; 031import org.apache.commons.logging.Log; 032import org.apache.commons.logging.LogFactory; 033import org.nuxeo.ecm.core.api.DocumentModel; 034import org.nuxeo.ecm.core.api.DocumentModelList; 035import org.nuxeo.ecm.directory.DirectoryException; 036import org.nuxeo.ecm.directory.Session; 037import org.nuxeo.ecm.platform.ui.web.component.SelectItemsFactory; 038import org.nuxeo.ecm.platform.ui.web.component.VariableManager; 039 040/** 041 * @since 6.0 042 */ 043public abstract class DirectorySelectItemsFactory extends SelectItemsFactory { 044 045 private static final Log log = LogFactory.getLog(DirectorySelectItemsFactory.class); 046 047 @Override 048 protected abstract String getVar(); 049 050 protected abstract String getDirectoryName(); 051 052 protected abstract String getFilter(); 053 054 protected abstract boolean isDisplayObsoleteEntries(); 055 056 protected abstract DirectorySelectItem createSelectItem(String label, Long ordering); 057 058 protected abstract String[] retrieveSelectEntryId(); 059 060 protected abstract Object retrieveItemLabel(); 061 062 protected abstract String retrieveLabelFromEntry(DocumentModel directoryEntry); 063 064 protected abstract Long retrieveOrderingFromEntry(DocumentModel directoryEntry); 065 066 @SuppressWarnings({ "unchecked", "rawtypes" }) 067 public List<DirectorySelectItem> createDirectorySelectItems(Object value, String separator) { 068 Object varValue = saveRequestMapVarValue(); 069 try { 070 // build select items 071 List<DirectorySelectItem> items = new ArrayList<DirectorySelectItem>(); 072 String dirName = getDirectoryName(); 073 if (StringUtils.isBlank(dirName)) { 074 items.add(new DirectorySelectItem("", "ERROR: mising directoryName property " 075 + "configuration on widget")); 076 } else { 077 try (Session directorySession = DirectorySelectItemFactory.getDirectorySession(dirName)) { 078 if (directorySession != null) { 079 if (value instanceof ListDataModel) { 080 ListDataModel ldm = (ListDataModel) value; 081 List<Object> entries = (List) ldm.getWrappedData(); 082 for (Object entry : entries) { 083 DirectorySelectItem res = createSelectItemFrom(directorySession, separator, entry); 084 if (res != null) { 085 items.add(res); 086 } 087 } 088 } else if (value instanceof Collection) { 089 Collection<Object> collection = (Collection<Object>) value; 090 for (Object entry : collection) { 091 DirectorySelectItem res = createSelectItemFrom(directorySession, separator, entry); 092 if (res != null) { 093 items.add(res); 094 } 095 } 096 } else if (value instanceof Object[]) { 097 Object[] entries = (Object[]) value; 098 for (Object entry : entries) { 099 DirectorySelectItem res = createSelectItemFrom(directorySession, separator, entry); 100 if (res != null) { 101 items.add(res); 102 } 103 } 104 } 105 } else { 106 items.add(new DirectorySelectItem("", String.format( 107 "ERROR: mising directorySession for directory '%s'", dirName))); 108 } 109 } 110 } 111 return items; 112 } finally { 113 restoreRequestMapVarValue(varValue); 114 } 115 } 116 117 @SuppressWarnings("boxing") 118 public List<DirectorySelectItem> createAllDirectorySelectItems() { 119 return createAllDirectorySelectItems(ChainSelect.DEFAULT_KEY_SEPARATOR); 120 } 121 122 /** 123 * @since 7.3 124 */ 125 @SuppressWarnings("boxing") 126 public List<DirectorySelectItem> createAllDirectorySelectItems(String separator) { 127 Object varValue = saveRequestMapVarValue(); 128 try { 129 List<DirectorySelectItem> items = new ArrayList<DirectorySelectItem>(); 130 try (Session directorySession = DirectorySelectItemFactory.getDirectorySession(getDirectoryName())) { 131 if (directorySession != null) { 132 Map<String, Serializable> filter = new HashMap<String, Serializable>(); 133 if (!isDisplayObsoleteEntries()) { 134 filter.put("obsolete", 0); 135 } 136 if (getFilter() != null) { 137 filter.put("parentFilter", getFilter()); 138 } 139 DocumentModelList entries = directorySession.query(filter); 140 for (DocumentModel entry : entries) { 141 if (entry != null) { 142 List<DocumentModel> entryL = new ArrayList<DocumentModel>(); 143 entryL.add(entry); 144 DirectorySelectItem res = createSelectItemForEntry(entry, separator, entry); 145 if (res != null) { 146 items.add(res); 147 } 148 } 149 } 150 } else { 151 log.error("No session provided for directory, returning empty selection"); 152 } 153 } 154 return items; 155 } finally { 156 restoreRequestMapVarValue(varValue); 157 } 158 } 159 160 protected String[] retrieveEntryIdFrom(Object item) { 161 Object varValue = saveRequestMapVarValue(); 162 try { 163 putIteratorToRequestParam(item); 164 String[] id = retrieveSelectEntryId(); 165 removeIteratorFromRequestParam(); 166 return id; 167 } finally { 168 restoreRequestMapVarValue(varValue); 169 } 170 } 171 172 protected DirectorySelectItem createSelectItemForEntry(Object itemValue, DocumentModel ... entries) { 173 return createSelectItemForEntry(itemValue, ChainSelect.DEFAULT_KEY_SEPARATOR, entries); 174 } 175 176 /** 177 * @since 7.4 178 */ 179 protected DirectorySelectItem createSelectItemForEntry(Object itemValue, String separator, DocumentModel ... entries) { 180 return createSelectItemForEntry(itemValue, separator, null, entries); 181 } 182 183 /** 184 * @since 7.3 185 */ 186 protected DirectorySelectItem createSelectItemForEntry(Object itemValue, String separator, String[] defaultLabels, DocumentModel ... entries) { 187 if (defaultLabels != null && (entries.length != defaultLabels.length)) { 188 throw new IllegalArgumentException("entryIds must be the same size that entries"); 189 } 190 String var = getVar(); 191 String varEntry = var + "Entry"; 192 Object varEntryExisting = VariableManager.saveRequestMapVarValue(varEntry); 193 194 DirectorySelectItem selectItem = null; 195 try { 196 VariableManager.putVariableToRequestParam(var, itemValue); 197 VariableManager.putVariableToRequestParam(varEntry, entries[entries.length - 1]); 198 String label = ""; 199 for (int i = 0; i < entries.length; i++) { 200 final DocumentModel entry = entries[i]; 201 if (label.length() != 0) { 202 label += separator; 203 } 204 if (entry == null && defaultLabels != null) { 205 label += defaultLabels[i]; 206 } else { 207 label += retrieveLabelFromEntry(entry); 208 } 209 } 210 Long ordering = retrieveOrderingFromEntry(entries[entries.length - 1]); 211 selectItem = createSelectItem(label, ordering); 212 removeIteratorFromRequestParam(); 213 VariableManager.removeVariableFromRequestParam(var); 214 VariableManager.removeVariableFromRequestParam(varEntry); 215 if (selectItem != null) { 216 return selectItem; 217 } else if (itemValue instanceof DirectorySelectItem) { 218 // maybe lookup was not necessary 219 return (DirectorySelectItem) itemValue; 220 } 221 return selectItem; 222 } catch (PropertyNotFoundException e) { 223 if (itemValue instanceof DirectorySelectItem) { 224 // maybe lookup was not necessary 225 return (DirectorySelectItem) itemValue; 226 } else { 227 throw e; 228 } 229 } finally { 230 VariableManager.restoreRequestMapVarValue(varEntry, varEntryExisting); 231 } 232 233 } 234 235 protected DirectorySelectItem createSelectItemFrom(Session session, Object entry) { 236 return createSelectItemFrom(session, ChainSelect.DEFAULT_KEY_SEPARATOR, entry); 237 } 238 239 /** 240 * @since 7.3 241 */ 242 protected DirectorySelectItem createSelectItemFrom(Session session, String separator, Object entry) { 243 String[] entryIds; 244 if (entry instanceof String) { 245 entryIds = new String[] {(String) entry}; 246 } else { 247 // first resolve entry id to be able to lookup 248 // corresponding doc entry 249 entryIds = retrieveEntryIdFrom(entry); 250 } 251 if (entryIds == null || entryIds.length == 0) { 252 return null; 253 } 254 try { 255 DocumentModel[] docEntries = new DocumentModel[entryIds.length]; 256 int i = 0; 257 for (String entryId : entryIds) { 258 DocumentModel docEntry = session.getEntry(entryId); 259 docEntries[i] = docEntry; 260 i++; 261 } 262 if (docEntries == null || docEntries.length == 0) { 263 putIteratorToRequestParam(entry); 264 Object labelObject = retrieveItemLabel(); 265 String label = labelObject == null ? null : String.valueOf(labelObject); 266 if (StringUtils.isBlank(label) && entry != null) { 267 label = entry.toString(); 268 } 269 DirectorySelectItem item = createSelectItem(label, Long.valueOf(0L)); 270 removeIteratorFromRequestParam(); 271 return item; 272 } 273 return createSelectItemForEntry(entry, separator, entryIds, docEntries); 274 } catch (DirectoryException e) { 275 } 276 return null; 277 } 278 279 @Override 280 public SelectItem createSelectItem() { 281 throw new IllegalArgumentException("Use createSelectDirectoryItems instead"); 282 } 283 284}