/**
* Copyright (c) 2008-2012 The Sakai Foundation
*
* Licensed under the Educational Community License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.osedu.org/licenses/ECL-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
*
*/
package org.sakaiproject.profile2.logic;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import lombok.Setter;
import org.apache.log4j.Logger;
import org.sakaiproject.authz.api.Member;
import org.sakaiproject.memory.api.Cache;
import org.sakaiproject.profile2.cache.CacheManager;
import org.sakaiproject.profile2.dao.ProfileDao;
import org.sakaiproject.profile2.model.BasicConnection;
import org.sakaiproject.profile2.model.Person;
import org.sakaiproject.profile2.model.ProfileSearchTerm;
import org.sakaiproject.profile2.util.ProfileConstants;
import org.sakaiproject.profile2.util.ProfileUtils;
import org.sakaiproject.site.api.Site;
import org.sakaiproject.user.api.User;
/**
* Implementation of ProfileSearchLogic API
*
* @author Steve Swinsburg (steve.swinsburg@gmail.com)
* @author Daniel Robinson (d.b.robinson@lancaster.ac.uk)
*/
public class ProfileSearchLogicImpl implements ProfileSearchLogic {
private static final Logger log = Logger.getLogger(ProfileSearchLogicImpl.class);
private Cache cache;
private final String CACHE_NAME = "org.sakaiproject.profile2.cache.search";
/**
* {@inheritDoc}
*/
public List<Person> findUsersByNameOrEmail(String search, boolean includeConnections, String worksiteId) {
//add users from SakaiPerson (clean list)
List<String> sakaiPersonUuids = dao.findSakaiPersonsByNameOrEmail(search);
List<User> users = sakaiProxy.getUsers(sakaiPersonUuids);
//add local users from UserDirectoryService
users.addAll(sakaiProxy.searchUsers(search));
//add external users from UserDirectoryService
users.addAll(sakaiProxy.searchExternalUsers(search));
//remove duplicates
ProfileUtils.removeDuplicates(users);
//remove connections if requested
if (false == includeConnections) {
removeConnectionsFromUsers(users);
}
//if worksite id is specified
if (null != worksiteId) {
//remove any matches that are not in specified worksite
users = removeNonWorksiteMembersFromUsers(users, worksiteId);
}
log.debug("Found " + users.size() + " results for search: " + search);
//restrict to only return the max number. UI will print message
int maxResults = sakaiProxy.getMaxSearchResults();
if(users.size() >= maxResults) {
users = users.subList(0, maxResults);
}
//remove invisible
users = removeInvisibleUsers(users);
return profileLogic.getPersons(users);
}
/**
* {@inheritDoc}
*/
public List<Person> findUsersByInterest(String search, boolean includeConnections, String worksiteId) {
//add users from SakaiPerson
List<String> sakaiPersonUuids = dao.findSakaiPersonsByInterest(search, sakaiProxy.isBusinessProfileEnabled());
//remove connections if requested
if (false == includeConnections) {
removeConnectionsFromUserIds(sakaiPersonUuids);
}
//if worksite id is specified
if (null != worksiteId) {
//remove any matches that are not in specified worksite
sakaiPersonUuids = removeNonWorksiteMembersFromUserIds(sakaiPersonUuids, worksiteId);
}
List<User> users = sakaiProxy.getUsers(sakaiPersonUuids);
//restrict to only return the max number. UI will print message
int maxResults = sakaiProxy.getMaxSearchResults();
if(users.size() >= maxResults) {
users = users.subList(0, maxResults);
}
//remove invisible
users = removeInvisibleUsers(users);
return profileLogic.getPersons(users);
}
/**
* {@inheritDoc}
*/
public ProfileSearchTerm getLastSearchTerm(String userUuid) {
List<ProfileSearchTerm> searchHistory = getSearchHistory(userUuid);
if (null != searchHistory && searchHistory.size() > 0) {
return searchHistory.get(searchHistory.size() - 1);
}
return null;
}
/**
* {@inheritDoc}
*/
public List<ProfileSearchTerm> getSearchHistory(String userUuid) {
if (cache.containsKey(userUuid)) {
List<ProfileSearchTerm> searchHistory = new ArrayList<ProfileSearchTerm>(
((Map<String, ProfileSearchTerm>) cache.get(userUuid))
.values());
Collections.sort(searchHistory);
return searchHistory;
} else {
return null;
}
}
/**
* {@inheritDoc}
*/
public void addSearchTermToHistory(String userUuid, ProfileSearchTerm searchTerm) {
if (null == searchTerm) {
throw new IllegalArgumentException("search term cannot be null");
}
if (null == searchTerm.getUserUuid()) {
throw new IllegalArgumentException("search term must contain UUID of user");
}
if (false == userUuid.equals(searchTerm.getUserUuid())) {
throw new IllegalArgumentException("userUuid must match search term userUuid");
}
Map<String, ProfileSearchTerm> searchHistory;
if (false == cache.containsKey(searchTerm.getUserUuid())) {
searchHistory = new HashMap<String, ProfileSearchTerm>();
} else {
searchHistory = (HashMap<String, ProfileSearchTerm>) cache.get(searchTerm.getUserUuid());
}
// if search term already in history, remove old one (do BEFORE checking size)
searchHistory.remove(searchTerm.getSearchTerm());
if (searchHistory.size() == ProfileConstants.DEFAULT_MAX_SEARCH_HISTORY) {
searchHistory.remove(getSearchHistory(userUuid).get(0).getSearchTerm());
}
// then add
searchHistory.put(searchTerm.getSearchTerm(), searchTerm);
cache.put(searchTerm.getUserUuid(), searchHistory);
}
/**
* {@inheritDoc}
*/
public void clearSearchHistory(String userUuid) {
if (cache.containsKey(userUuid)) {
cache.remove(userUuid);
} else {
log.warn("unable to clear search history; uuid not found: " + userUuid);
}
}
/**
* Remove invisible users from the list
* @param users
* @return cleaned list
*/
private List<User> removeInvisibleUsers(List<User> users){
//if superuser return list unchanged.
if(sakaiProxy.isSuperUser()){
return users;
}
//get list of invisible users as Users
List<User> invisibleUsers = sakaiProxy.getUsers(sakaiProxy.getInvisibleUsers());
if(invisibleUsers.isEmpty()) {
return users;
}
//remove
users.removeAll(invisibleUsers);
return users;
}
/**
* Remove any connections from list of users.
*
* @param users
*/
private void removeConnectionsFromUsers(List<User> users) {
List<BasicConnection> connections = connectionsLogic.getBasicConnectionsForUser(sakaiProxy.getCurrentUserId());
for (BasicConnection connection : connections) {
for (User user : users) {
if (user.getId().equals(connection.getUuid())) {
users.remove(user);
break;
}
}
}
}
/**
* Remove any connections from list of user ids.
*
* @param userIds
*/
private void removeConnectionsFromUserIds(List<String> userIds) {
List<BasicConnection> connections = connectionsLogic.getBasicConnectionsForUser(sakaiProxy.getCurrentUserId());
for (BasicConnection connection : connections) {
if (userIds.contains(connection.getUuid())) {
userIds.remove(connection.getUuid());
}
}
}
/**
* Remove any non-worksite members from list of users.
*
* @param users
* @param worksiteId
* @return a list of matching worksite member users.
*/
private List<User> removeNonWorksiteMembersFromUsers(List<User> users, String worksiteId) {
List<User> worksiteMembers = new ArrayList<User>();
Site site = sakaiProxy.getSite(worksiteId);
if (null == site) {
log.error("Unable to receive worksite with id: " + worksiteId);
} else {
Set<Member> members = sakaiProxy.getSite(worksiteId).getMembers();
for (Member member : members) {
for (User user : users) {
if (user.getId().equals(member.getUserId())) {
worksiteMembers.add(user);
break;
}
}
}
}
return worksiteMembers;
}
/**
* Remove any non-worksite members from list of user ids.
*
* @param userIds
* @param worksiteId
* @return a list of matching worksite member user ids.
*/
private List<String> removeNonWorksiteMembersFromUserIds(List<String> userIds, String worksiteId) {
List<String> worksiteMemberIds = new ArrayList<String>();
Site site = sakaiProxy.getSite(worksiteId);
if (null == site) {
log.error("Unable to receive worksite with id: " + worksiteId);
} else {
Set<Member> members = sakaiProxy.getSite(worksiteId).getMembers();
for (Member member : members) {
for (String userId : userIds) {
if (userId.equals(member.getUserId())) {
worksiteMemberIds.add(userId);
break;
}
}
}
}
return worksiteMemberIds;
}
public void init() {
cache = cacheManager.createCache(CACHE_NAME);
}
@Setter
private SakaiProxy sakaiProxy;
@Setter
private ProfileDao dao;
@Setter
private ProfileLogic profileLogic;
@Setter
private ProfileConnectionsLogic connectionsLogic;
@Setter
private CacheManager cacheManager;
}