001/* 002 * (C) Copyright 2013 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 * Thomas Roger 018 */ 019 020package org.nuxeo.ecm.platform.usermanager.providers; 021 022import java.io.Serializable; 023import java.util.ArrayList; 024import java.util.Collection; 025import java.util.Collections; 026import java.util.HashMap; 027import java.util.List; 028import java.util.Map; 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.core.api.impl.DocumentModelListImpl; 036import org.nuxeo.ecm.directory.SizeLimitExceededException; 037import org.nuxeo.ecm.platform.query.api.AbstractPageProvider; 038import org.nuxeo.ecm.platform.usermanager.UserManager; 039import org.nuxeo.runtime.api.Framework; 040 041/** 042 * @since 5.8 043 */ 044public abstract class AbstractUsersPageProvider<T> extends AbstractPageProvider<T> { 045 046 private static final Log log = LogFactory.getLog(UsersPageProvider.class); 047 048 private static final long serialVersionUID = 1L; 049 050 protected static final String USERS_LISTING_MODE_PROPERTY = "usersListingMode"; 051 052 protected static final String ALL_MODE = "all"; 053 054 protected static final String SEARCH_ONLY_MODE = "search_only"; 055 056 protected static final String TABBED_MODE = "tabbed"; 057 058 protected static final String SEARCH_OVERFLOW_ERROR_MESSAGE = "label.security.searchOverFlow"; 059 060 /** 061 * Map with first letter as key and users list as value. 062 */ 063 protected Map<String, DocumentModelList> userCatalog; 064 065 protected List<DocumentModel> pageUsers; 066 067 protected List<DocumentModel> computeCurrentPage() { 068 if (pageUsers == null) { 069 error = null; 070 errorMessage = null; 071 pageUsers = new ArrayList<>(); 072 073 List<DocumentModel> users = new ArrayList<DocumentModel>(); 074 try { 075 UserManager userManager = Framework.getLocalService(UserManager.class); 076 String userListingMode = getUserListingMode(); 077 if (ALL_MODE.equals(userListingMode)) { 078 users = searchAllUsers(userManager); 079 } else if (SEARCH_ONLY_MODE.equals(userListingMode)) { 080 users = searchUsers(userManager); 081 } else if (TABBED_MODE.equals(userListingMode)) { 082 users = searchUsersFromCatalog(userManager); 083 } 084 } catch (SizeLimitExceededException slee) { 085 error = slee; 086 errorMessage = SEARCH_OVERFLOW_ERROR_MESSAGE; 087 log.warn(slee.getMessage(), slee); 088 } 089 090 if (!hasError()) { 091 long resultsCount = users.size(); 092 setResultsCount(resultsCount); 093 // post-filter the results "by hand" to handle pagination 094 long pageSize = getMinMaxPageSize(); 095 if (pageSize == 0) { 096 pageUsers.addAll(users); 097 } else { 098 // handle offset 099 long offset = getCurrentPageOffset(); 100 if (offset <= resultsCount) { 101 for (int i = Long.valueOf(offset).intValue(); i < resultsCount && i < offset + pageSize; i++) { 102 pageUsers.add(users.get(i)); 103 } 104 } 105 } 106 } 107 } 108 return pageUsers; 109 } 110 111 protected String getUserListingMode() { 112 Map<String, Serializable> props = getProperties(); 113 if (props.containsKey(USERS_LISTING_MODE_PROPERTY)) { 114 return (String) props.get(USERS_LISTING_MODE_PROPERTY); 115 } 116 return SEARCH_ONLY_MODE; 117 } 118 119 protected String getFirstParameter() { 120 Object[] parameters = getParameters(); 121 if (parameters.length > 0) { 122 String param = (String) parameters[0]; 123 if (param != null) { 124 return param.trim(); 125 } 126 } 127 return ""; 128 } 129 130 protected List<DocumentModel> searchAllUsers(UserManager userManager) { 131 return userManager.searchUsers(null); 132 } 133 134 protected List<DocumentModel> searchUsers(UserManager userManager) { 135 List<DocumentModel> users = new ArrayList<DocumentModel>(); 136 String searchString = getFirstParameter(); 137 if ("*".equals(searchString)) { 138 users = searchAllUsers(userManager); 139 } else if (!StringUtils.isEmpty(searchString)) { 140 users = userManager.searchUsers(searchString); 141 } 142 return users; 143 } 144 145 protected List<DocumentModel> searchUsersFromCatalog(UserManager userManager) { 146 if (userCatalog == null) { 147 updateUserCatalog(userManager); 148 } 149 String selectedLetter = getFirstParameter(); 150 if (StringUtils.isEmpty(selectedLetter) || !userCatalog.containsKey(selectedLetter)) { 151 Collection<String> catalogLetters = getCatalogLetters(); 152 if (!catalogLetters.isEmpty()) { 153 selectedLetter = catalogLetters.iterator().next(); 154 } 155 } 156 return userCatalog.get(selectedLetter); 157 } 158 159 protected void updateUserCatalog(UserManager userManager) { 160 DocumentModelList allUsers = userManager.searchUsers(null); 161 userCatalog = new HashMap<String, DocumentModelList>(); 162 String userSortField = userManager.getUserSortField(); 163 for (DocumentModel user : allUsers) { 164 // FIXME: this should use a "display name" dedicated API 165 String displayName = null; 166 if (userSortField != null) { 167 displayName = (String) user.getPropertyValue(userSortField); 168 } 169 if (StringUtils.isEmpty(displayName)) { 170 displayName = user.getId(); 171 } 172 String firstLetter = displayName.substring(0, 1).toUpperCase(); 173 DocumentModelList list = userCatalog.get(firstLetter); 174 if (list == null) { 175 list = new DocumentModelListImpl(); 176 userCatalog.put(firstLetter, list); 177 } 178 list.add(user); 179 } 180 } 181 182 public Collection<String> getCatalogLetters() { 183 if (userCatalog == null) { 184 UserManager userManager = Framework.getService(UserManager.class); 185 updateUserCatalog(userManager); 186 } 187 List<String> list = new ArrayList<String>(userCatalog.keySet()); 188 Collections.sort(list); 189 return list; 190 } 191 192 /** 193 * This page provider does not support sort for now => override what may be contributed in the definition 194 */ 195 @Override 196 public boolean isSortable() { 197 return false; 198 } 199 200 @Override 201 protected void pageChanged() { 202 pageUsers = null; 203 super.pageChanged(); 204 } 205 206 @Override 207 public void refresh() { 208 pageUsers = null; 209 super.refresh(); 210 } 211}