001/*
002 *  Copyright 2016 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.core.user;
017
018import java.util.ArrayList;
019import java.util.Collection;
020import java.util.Collections;
021import java.util.List;
022import java.util.Map;
023import java.util.Set;
024
025import org.apache.avalon.framework.component.Component;
026import org.apache.avalon.framework.service.ServiceException;
027import org.apache.avalon.framework.service.ServiceManager;
028import org.apache.avalon.framework.service.Serviceable;
029
030import org.ametys.core.user.directory.UserDirectory;
031import org.ametys.core.user.population.PopulationContextHelper;
032import org.ametys.core.user.population.UserPopulation;
033import org.ametys.core.user.population.UserPopulationDAO;
034import org.ametys.runtime.plugin.component.AbstractLogEnabled;
035
036/**
037 * Component for getting user list and verify the presence of a particular user on a context or for user directory(ies).
038 */
039public class UserManager extends AbstractLogEnabled implements Component, Serviceable
040{
041    /** Avalon Role */
042    public static final String ROLE = UserManager.class.getName(); 
043            
044    /** The DAO for User Population */
045    protected UserPopulationDAO _userPopulationDAO;
046    /** The helper for the associations population/context */
047    protected PopulationContextHelper _populationContextHelper;
048    
049    @Override
050    public void service(ServiceManager manager) throws ServiceException
051    {
052        _userPopulationDAO = (UserPopulationDAO) manager.lookup(UserPopulationDAO.ROLE);
053        _populationContextHelper = (PopulationContextHelper) manager.lookup(PopulationContextHelper.ROLE);
054    }
055    
056    /**
057     * Get the list of users on some given contexts
058     * @param contexts The contexts
059     * @return the collection of users
060     */
061    public Collection<User> getUsersByContext(Set<String> contexts)
062    {
063        List<UserPopulation> userPopulations = new ArrayList<>();
064        List<String> upIds = _populationContextHelper.getUserPopulationsOnContexts(contexts, false);
065        for (String upId : upIds)
066        {
067            userPopulations.add(_userPopulationDAO.getUserPopulation(upId));
068        }
069        
070        return getUsersByPopulations(userPopulations);
071    }
072    
073    /**
074     * Get the users for given users' populations
075     * @param userPopulationIds the id of population of users
076     * @return the collection of users
077     */
078    public Collection<User> getUsersByPopulationIds(List<String> userPopulationIds)
079    {
080        List<User> users = new ArrayList<>();
081        for (String id : userPopulationIds)
082        {
083            UserPopulation userPopulation = _userPopulationDAO.getUserPopulation(id);
084            if (userPopulation != null)
085            {
086                for (User user : getUsers(userPopulation))
087                {
088                    if (!users.contains(user))
089                    {
090                        users.add(user);
091                    }
092                }
093            }
094        }
095        return users;
096    }
097    
098    /**
099     * Get the users for given users' populations
100     * @param userPopulations the population of users
101     * @return the collection of users
102     */
103    public Collection<User> getUsersByPopulations(List<UserPopulation> userPopulations)
104    {
105        List<User> users = new ArrayList<>();
106        for (UserPopulation userPopulation : userPopulations)
107        {
108            for (User user : getUsers(userPopulation))
109            {
110                if (!users.contains(user))
111                {
112                    users.add(user);
113                }
114            }
115        }
116        return users;
117    }
118    
119    /**
120     * Gets all the users of a {@link UserPopulation}
121     * @param userPopulationId The ID of user population
122     * @return list of users as Collection of {@link User}s, empty if a problem occurs.
123     */
124    public Collection<User> getUsers(String userPopulationId)
125    {
126        UserPopulation userPopulation = _userPopulationDAO.getUserPopulation(userPopulationId);
127        if (userPopulation != null)
128        {
129            return getUsers(userPopulation);
130        }
131        else
132        {
133            return Collections.EMPTY_LIST;
134        }
135    }
136    
137    /**
138     * Gets all the users of a {@link UserPopulation}
139     * @param userPopulation The user population
140     * @return list of users as Collection of {@link User}s, empty if a problem occurs.
141     */
142    public Collection<User> getUsers(UserPopulation userPopulation)
143    {
144        List<User> users = new ArrayList<>();
145        
146        for (UserDirectory ud : userPopulation.getUserDirectories())
147        {
148            for (User user : ud.getUsers())
149            {
150                if (!users.contains(user))
151                {
152                    users.add(user);
153                }
154            }
155        }
156        
157        return users;
158    }
159    
160    /**
161     * Get a list of users given the parameters
162     * @param contexts The contexts
163     * @param count The limit of users to retrieve
164     * @param offset The number of result to ignore before starting to collect users. 
165     * @param parameters A map of additional parameters, see implementation.
166     * @return The list of retrieved {@link User}
167     */
168    public List<User> getUsersByContext(Set<String> contexts, int count, int offset, Map<String, Object> parameters)
169    {
170        List<UserPopulation> userPopulations = new ArrayList<>();
171        List<String> upIds = _populationContextHelper.getUserPopulationsOnContexts(contexts, false);
172        for (String upId : upIds)
173        {
174            userPopulations.add(_userPopulationDAO.getUserPopulation(upId));
175        }
176        
177        return getUsers(userPopulations, count, offset, parameters);
178    }
179    
180    /**
181     * Get a list of users given the parameters
182     * @param userPopulations the population of users
183     * @param count The limit of users to retrieve
184     * @param offset The number of result to ignore before starting to collect users. 
185     * @param parameters A map of additional parameters, see implementation.
186     * @return The list of retrieved {@link User}
187     */
188    public List<User> getUsers(List<UserPopulation> userPopulations, int count, int offset, Map<String, Object> parameters)
189    {
190        List<User> users = new ArrayList<>();
191        for (UserPopulation userPopulation : userPopulations)
192        {
193            for (User user : getUsers(userPopulation, -1, 0, parameters))
194            {
195                if (!users.contains(user))
196                {
197                    users.add(user);
198                }
199            }
200        }
201        
202        int boundedCount = count >= 0 ? count : Integer.MAX_VALUE;
203        int boundedOffset = offset >= 0 ? offset : 0;
204        int toIndex;
205        if (boundedOffset + boundedCount >= 0)
206        {
207            toIndex = Math.min(boundedOffset + boundedCount, users.size());
208        }
209        else
210        {
211            // particular case where count was initially negative (to say "no limit") and we set it to Integer.MAX_VALUE
212            // so if the offset is strictly positive, the sum overflows
213            toIndex = users.size();
214        }
215        return users.subList(boundedOffset, toIndex);
216    }
217    
218    /**
219     * Gets all the users of a {@link UserPopulation}
220     * @param userPopulationId The ID of user population
221     * @param count The limit of users to retrieve
222     * @param offset The number of result to ignore before starting to collect users. 
223     * @param parameters A map of additional parameters, see implementation.
224     * @return list of users as Collection of {@link User}s, empty if a problem occurs.
225     */
226    public Collection<User> getUsers(String userPopulationId, int count, int offset, Map<String, Object> parameters)
227    {
228        UserPopulation userPopulation = _userPopulationDAO.getUserPopulation(userPopulationId);
229        if (userPopulation != null)
230        {
231            return getUsers(userPopulation, count, offset, parameters);
232        }
233        else
234        {
235            return Collections.EMPTY_LIST;
236        }
237    }
238    
239    /**
240     * Gets all the users of a given {@link UserPopulation} and {@link UserDirectory}
241     * @param userPopulationId The ID of user population
242     * @param userDirectoryId The id of the user directory
243     * @param count The limit of users to retrieve
244     * @param offset The number of result to ignore before starting to collect users. 
245     * @param parameters A map of additional parameters, see implementation.
246     * @return list of users as Collection of {@link User}s, empty if a problem occurs.
247     */
248    public Collection<User> getUsersByDirectory(String userPopulationId, String userDirectoryId, int count, int offset, Map<String, Object> parameters)
249    {
250        UserPopulation userPopulation = _userPopulationDAO.getUserPopulation(userPopulationId);
251        
252        if (userPopulation == null)
253        {
254            return Collections.EMPTY_LIST;
255        }
256        
257        UserDirectory ud = userPopulation.getUserDirectory(userDirectoryId);
258        if (ud == null)
259        {
260            throw new IllegalArgumentException("In the population '" + userPopulationId + "' the directory '" + userDirectoryId + "' was referenced but does not exists");
261        }
262        return ud.getUsers(count, offset, parameters);
263    }
264    
265    /**
266     * Gets all the users of a {@link UserPopulation}
267     * @param userPopulation The users population
268     * @param count The limit of users to retrieve
269     * @param offset The number of result to ignore before starting to collect users. 
270     * @param parameters A map of additional parameters, see implementation.
271     * @return list of users as Collection of {@link User}s, empty if a problem occurs.
272     */
273    public Collection<User> getUsers(UserPopulation userPopulation, int count, int offset, Map<String, Object> parameters)
274    {
275        List<User> users = new ArrayList<>();
276        
277        for (UserDirectory ud : userPopulation.getUserDirectories())
278        {
279            for (User user : ud.getUsers(-1, 0, parameters))
280            {
281                if (!users.contains(user))
282                {
283                    users.add(user);
284                }
285            }
286        }
287        
288        int boundedCount = count >= 0 ? count : Integer.MAX_VALUE;
289        int boundedOffset = offset >= 0 ? offset : 0;
290        int toIndex;
291        if (boundedOffset + boundedCount >= 0)
292        {
293            toIndex = Math.min(boundedOffset + boundedCount, users.size());
294        }
295        else
296        {
297            // particular case where count was initially negative (to say "no limit") and we set it to Integer.MAX_VALUE
298            // so if the offset is strictly positive, the sum overflows
299            toIndex = users.size();
300        }
301        return users.subList(boundedOffset, toIndex);
302    }
303    
304    /**
305     * Gets all the users of a {@link UserPopulation}
306     * @param userPopulation The users population
307     * @param userDirectoryId The id of the user directory
308     * @param count The limit of users to retrieve
309     * @param offset The number of result to ignore before starting to collect users. 
310     * @param parameters A map of additional parameters, see implementation.
311     * @return list of users as Collection of {@link User}s, empty if a problem occurs.
312     */
313    public Collection<User> getUsersByDirectory(UserPopulation userPopulation, String userDirectoryId, int count, int offset, Map<String, Object> parameters)
314    {
315        UserDirectory ud = userPopulation.getUserDirectory(userDirectoryId);
316        return ud.getUsers(count, offset, parameters);
317    }
318    
319    /**
320     * Get a user by his login on some given contexts
321     * @param contexts The contexts
322     * @param login Login of the user to get. Cannot be null.
323     * @return User's information as a {@link User} instance or null if the user login does not exist.
324     */
325    public User getUserByContext(Set<String> contexts, String login)
326    {
327        List<String> upIds = _populationContextHelper.getUserPopulationsOnContexts(contexts, false);
328        for (String upId : upIds)
329        {
330            UserPopulation userPopulation = _userPopulationDAO.getUserPopulation(upId);
331            User user = getUser(userPopulation, login);
332            if (user != null)
333            {
334                return user;
335            }
336        }
337        return null;
338    }
339    
340    /**
341     * Get the user from its user identity
342     * @param userIdentity The user identity
343     * @return The User or null if the user login does not exist.
344     */
345    public User getUser (UserIdentity userIdentity)
346    {
347        return getUser(userIdentity.getPopulationId(), userIdentity.getLogin());
348    }
349    
350    /**
351     * Get a particular user of the given users population by his login.
352     * @param userPopulationId The ID of user population
353     * @param login Login of the user to get. Cannot be null.
354     * @return User's information as a {@link User} instance or null if the user login does not exist.
355     */
356    public User getUser(String userPopulationId, String login)
357    {
358        UserPopulation userPopulation = _userPopulationDAO.getUserPopulation(userPopulationId);
359        if (userPopulation != null)
360        {
361            return getUser(userPopulation, login);
362        }
363        else
364        {
365            return null;
366        }
367    }
368    
369    /**
370     * Get a particular user of the given user population and given user directory by his login.
371     * @param userPopulationId The ID of user population
372     * @param userDirectoryId The id of the user directory
373     * @param login Login of the user to get. Cannot be null.
374     * @return User's information as a {@link User} instance or null if the user login does not exist.
375     */
376    public User getUserByDirectory(String userPopulationId, String userDirectoryId, String login)
377    {
378        UserPopulation userPopulation = _userPopulationDAO.getUserPopulation(userPopulationId);
379        if (userPopulation != null)
380        {
381            return getUserByDirectory(userPopulation, userDirectoryId, login);
382        }
383        else
384        {
385            return null;
386        }
387    }
388    
389    /**
390     * Get a particular user of the given user population by his login.
391     * @param userPopulation The user population
392     * @param login Login of the user to get. Cannot be null.
393     * @return User's information as a {@link User} instance or null if the user login does not exist.
394     */
395    public User getUser(UserPopulation userPopulation, String login)
396    {
397        for (UserDirectory ud : userPopulation.getUserDirectories())
398        {
399            User user = ud.getUser(login);
400            if (user != null)
401            {
402                return user;
403            }
404        }
405        return null;
406    }
407    
408    /**
409     * Get a particular user of the given user population and given user directory by his login.
410     * @param userPopulation The user population
411     * @param userDirectoryId The id of the user directory
412     * @param login Login of the user to get. Cannot be null.
413     * @return User's information as a {@link User} instance or null if the user login does not exist.
414     */
415    public User getUserByDirectory(UserPopulation userPopulation, String userDirectoryId, String login)
416    {
417        UserDirectory ud = userPopulation.getUserDirectory(userDirectoryId);
418        
419        User user = ud.getUser(login);
420        if (user != null)
421        {
422            return user;
423        }
424            
425        return null;
426    }
427    
428    /**
429     * Get the user directory the given user belongs to
430     * @param userPopulationId The id of the user population
431     * @param login Login of the user to get. Cannot be null.
432     * @return The user directory the user belongs to.
433     */
434    public UserDirectory getUserDirectory(String userPopulationId, String login)
435    {
436        UserPopulation userPopulation = _userPopulationDAO.getUserPopulation(userPopulationId);
437        if (userPopulation == null)
438        {
439            return null;
440        }
441        
442        for (UserDirectory ud : userPopulation.getUserDirectories())
443        {
444            User user = ud.getUser(login);
445            if (user != null)
446            {
447                return ud;
448            }
449        }
450        return null;
451    }
452}