001/* 002 * Copyright 2015 Anyware Services 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 */ 016package org.ametys.plugins.core.user; 017 018import java.util.ArrayList; 019import java.util.Collection; 020import java.util.Collections; 021import java.util.HashMap; 022import java.util.LinkedHashSet; 023import java.util.List; 024import java.util.Map; 025import java.util.Objects; 026import java.util.Optional; 027import java.util.Set; 028import java.util.stream.Collectors; 029 030import javax.xml.transform.TransformerException; 031 032import org.apache.avalon.framework.component.Component; 033import org.apache.avalon.framework.configuration.Configuration; 034import org.apache.avalon.framework.configuration.ConfigurationException; 035import org.apache.avalon.framework.configuration.ConfigurationUtil; 036import org.apache.avalon.framework.service.ServiceException; 037import org.apache.avalon.framework.service.ServiceManager; 038import org.apache.avalon.framework.service.Serviceable; 039import org.apache.cocoon.xml.AttributesImpl; 040import org.apache.cocoon.xml.XMLUtils; 041import org.apache.xpath.XPathAPI; 042import org.w3c.dom.Element; 043import org.w3c.dom.Node; 044import org.xml.sax.ContentHandler; 045import org.xml.sax.SAXException; 046 047import org.ametys.core.user.User; 048import org.ametys.core.user.UserIdentity; 049import org.ametys.core.user.UserManager; 050import org.ametys.core.user.directory.NotUniqueUserException; 051import org.ametys.core.user.directory.UserDirectoryFactory; 052import org.ametys.core.user.population.UserPopulationDAO; 053import org.ametys.runtime.plugin.component.AbstractLogEnabled; 054 055/** 056 * Simple user helper, for common function working on {@link User} 057 */ 058public class UserHelper extends AbstractLogEnabled implements Component, Serviceable 059{ 060 /** The Avalon role */ 061 public static final String ROLE = UserHelper.class.getName(); 062 063 /** The user population DAO */ 064 private UserPopulationDAO _userPopulationDAO; 065 066 /** The user directory factory */ 067 private UserDirectoryFactory _userDirectoryFactory; 068 069 private UserManager _userManager; 070 071 @Override 072 public void service(ServiceManager smanager) throws ServiceException 073 { 074 _userManager = (UserManager) smanager.lookup(UserManager.ROLE); 075 _userPopulationDAO = (UserPopulationDAO) smanager.lookup(UserPopulationDAO.ROLE); 076 _userDirectoryFactory = (UserDirectoryFactory) smanager.lookup(UserDirectoryFactory.ROLE); 077 } 078 079 /** 080 * Get the user's full name handling request cache 081 * @param userIdentity The user identity 082 * @return user's full name or null if user does not exist 083 */ 084 public String getUserFullName (UserIdentity userIdentity) 085 { 086 User user = _userManager.getUser(userIdentity); 087 return user != null ? user.getFullName() : null; 088 } 089 090 /** 091 * Get the user's sortable name handling request cache 092 * @param userIdentity The user identity 093 * @return user's full name or null if user does not exist 094 */ 095 public String getUserSortableName (UserIdentity userIdentity) 096 { 097 User user = _userManager.getUser(userIdentity); 098 return user != null ? user.getSortableName() : null; 099 } 100 101 /** 102 * Populate a list of map, where each map representing an user. 103 * @param users The list of users 104 * @return The list of map. 105 */ 106 public List<Map<String, Object>> userIdentities2json(Collection<UserIdentity> users) 107 { 108 return users.stream().map(identity -> _userManager.getUser(identity)).filter(Objects::nonNull).map(user -> user2json(user)).collect(Collectors.toList()); 109 } 110 111 112 /** 113 * Populate a list of map, where each map representing an user. 114 * @param users The list of users 115 * @return The list of map. 116 */ 117 public List<Map<String, Object>> users2json(Collection<User> users) 118 { 119 return users2json(users, false); 120 } 121 122 /** 123 * Populate a list of map, where each map representing an user. 124 * @param users The list of users 125 * @param full Set to <code>true</code> to get full information on user 126 * @return The list of map. 127 */ 128 public List<Map<String, Object>> users2json(Collection<User> users, boolean full) 129 { 130 List<Map<String, Object>> userList = new ArrayList<>(); 131 132 Set<User> distinctUsers = new LinkedHashSet<>(users); 133 for (User user : distinctUsers) 134 { 135 userList.add(user2json(user, full)); 136 } 137 138 return userList; 139 } 140 141 /** 142 * Get the JSON object representing a user 143 * @param userIdentity The user identity 144 * @return The user as JSON object 145 */ 146 public Map<String, Object> user2json (UserIdentity userIdentity) 147 { 148 return user2json(userIdentity, false); 149 } 150 151 /** 152 * Get the JSON object representing a user 153 * @param userIdentity The user identity 154 * @param full Set to <code>true</code> to get full information on user 155 * @return The user as JSON object 156 */ 157 public Map<String, Object> user2json (UserIdentity userIdentity, boolean full) 158 { 159 User user = _userManager.getUser(userIdentity); 160 if (user != null) 161 { 162 return user2json(user, full); 163 } 164 return Collections.EMPTY_MAP; 165 } 166 167 /** 168 * Get the JSON object representing a user 169 * @param user The user 170 * @return The user as JSON object 171 */ 172 public Map<String, Object> user2json(User user) 173 { 174 return _user2json(user, false); 175 } 176 177 /** 178 * Get the JSON object representing a user 179 * @param user The user 180 * @param full Set to <code>true</code> to get full information on user 181 * @return The user as JSON object or null, if the given user is null 182 */ 183 public Map<String, Object> user2json(User user, boolean full) 184 { 185 return _user2json(user, full); 186 } 187 188 private Map<String, Object> _user2json(User user, boolean full) 189 { 190 if (user == null) 191 { 192 return null; 193 } 194 195 Map<String, Object> userInfos = new HashMap<>(); 196 197 userInfos.put("login", user.getIdentity().getLogin()); 198 199 String populationId = user.getIdentity().getPopulationId(); 200 userInfos.put("populationId", populationId); 201 202 userInfos.put("fullname", user.getFullName()); 203 userInfos.put("sortablename", user.getSortableName()); 204 205 if (full) 206 { 207 String udModelId = user.getUserDirectory() != null ? user.getUserDirectory().getUserDirectoryModelId() : ""; 208 209 userInfos.put("populationLabel", _userPopulationDAO.getUserPopulation(populationId).getLabel()); 210 userInfos.put("directory", _userDirectoryFactory.hasExtension(udModelId) ? _userDirectoryFactory.getExtension(udModelId).getLabel() : ""); 211 212 userInfos.put("lastname", user.getLastName()); 213 userInfos.put("firstname", user.getFirstName()); 214 userInfos.put("email", user.getEmail()); 215 } 216 217 return userInfos; 218 } 219 220 /** 221 * Get the user identity from a JSON object 222 * @param json the JSON object representing the user 223 * @return the user identity 224 */ 225 public UserIdentity json2userIdentity(Map<String, ? extends Object> json) 226 { 227 // If the user is empty, return null 228 return Optional.ofNullable(json) 229 .filter(u -> !u.isEmpty() && u.get("login") != null && u.get("populationId") != null) 230 .map(u -> new UserIdentity((String) u.get("login"), (String) u.get("populationId"))) 231 .orElse(null); 232 } 233 234 /** 235 * Get the user from its identity 236 * @param userIdentity The user identity 237 * @return The user or null if not found 238 * @deprecated use {@link UserManager#getUser(UserIdentity)} instead 239 */ 240 @Deprecated 241 public User getUser (UserIdentity userIdentity) 242 { 243 if (userIdentity == null) 244 { 245 return null; 246 } 247 248 return _userManager.getUser(userIdentity.getPopulationId(), userIdentity.getLogin()); 249 } 250 251 /** 252 * Get the user from its email 253 * @param populationId The population id 254 * @param email The email 255 * @return The user or null if not found or if multiple user were found with this email 256 * @deprecated use {@link UserManager#getUserByEmail(String, String)} instead 257 */ 258 @Deprecated 259 public User getUserByEmail (String populationId, String email) 260 { 261 if (email == null) 262 { 263 return null; 264 } 265 266 try 267 { 268 return _userManager.getUserByEmail(populationId, email); 269 } 270 catch (NotUniqueUserException e) 271 { 272 return null; 273 } 274 } 275 276 /** 277 * SAX an user identity 278 * @param userIdentity The user identity to SAX 279 * @param handler The content handler 280 * @throws SAXException If a SAX error occurs 281 */ 282 public void saxUserIdentity(UserIdentity userIdentity, ContentHandler handler) throws SAXException 283 { 284 saxUserIdentity(userIdentity, handler, "user"); 285 } 286 287 /** 288 * SAX an user identity 289 * @param userIdentity The user identity to SAX 290 * @param handler The content handler 291 * @param tagName The XML tag for saxed user 292 * @throws SAXException If a SAX error occurs 293 */ 294 public void saxUserIdentity(UserIdentity userIdentity, ContentHandler handler, String tagName) throws SAXException 295 { 296 User user = _userManager.getUser(userIdentity); 297 if (user != null) 298 { 299 saxUser(user, handler, tagName); 300 } 301 else 302 { 303 getLogger().warn("Unable to sax unknown user with identity {}", userIdentity); 304 } 305 306 } 307 308 /** 309 * SAX an user 310 * @param user The user. If null no sax events will be generated. 311 * @param handler The content handler 312 * @throws SAXException If a SAX error occurs 313 */ 314 public void saxUser(User user, ContentHandler handler) throws SAXException 315 { 316 saxUser(user, handler, "user"); 317 } 318 319 /** 320 * SAX an user 321 * @param user The user. If null no sax events will be generated. 322 * @param handler The content handler 323 * @param tagName The XML tag for saxed user 324 * @throws SAXException If a SAX error occurs 325 */ 326 public void saxUser(User user, ContentHandler handler, String tagName) throws SAXException 327 { 328 if (user != null) 329 { 330 AttributesImpl attr = new AttributesImpl(); 331 attr.addCDATAAttribute("login", user.getIdentity().getLogin()); 332 attr.addCDATAAttribute("population", user.getIdentity().getPopulationId()); 333 334 XMLUtils.startElement(handler, tagName, attr); 335 336 XMLUtils.createElement(handler, "lastname", user.getLastName()); 337 XMLUtils.createElement(handler, "firstname", user.getFirstName()); 338 XMLUtils.createElement(handler, "email", user.getEmail()); 339 340 XMLUtils.createElement(handler, "fullname", user.getFullName()); 341 XMLUtils.createElement(handler, "sortablename", user.getSortableName()); 342 343 _userPopulationDAO.getUserPopulation(user.getIdentity().getPopulationId()).getLabel().toSAX(handler, "populationLabel"); 344 345 XMLUtils.endElement(handler, tagName); 346 } 347 else if (getLogger().isWarnEnabled()) 348 { 349 getLogger().warn("Unable to sax null user", new Exception()); 350 } 351 } 352 353 /** 354 * Get the user identity from an XML configuration 355 * @param userConfiguration The configuration 356 * @return The user identity 357 * @throws ConfigurationException if an error occurs during value retrieving 358 */ 359 public UserIdentity xml2userIdentity(Configuration userConfiguration) throws ConfigurationException 360 { 361 Element userElement = ConfigurationUtil.toElement(userConfiguration); 362 try 363 { 364 return xml2userIdentity(userElement); 365 } 366 catch (TransformerException e) 367 { 368 throw new ConfigurationException("An error occurred while parsing the configuration of an I/O data", e); 369 } 370 } 371 372 /** 373 * Get the user identity from a DOM Node object 374 * @param userNode The node 375 * @return The user identity 376 * @throws TransformerException if an error occurs during value retrieving 377 */ 378 public UserIdentity xml2userIdentity(Node userNode) throws TransformerException 379 { 380 String login = Objects.requireNonNull(XPathAPI.eval(userNode, "@login").str()); 381 String population = Objects.requireNonNull(XPathAPI.eval(userNode, "@population").str()); 382 return new UserIdentity(login, population); 383 } 384}