package com.delect.motiver.server.manager;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import com.delect.motiver.server.cache.UserCache;
import com.delect.motiver.server.dao.UserDAO;
import com.delect.motiver.server.dao.helper.CircleSearchParams;
import com.delect.motiver.server.jdo.Circle;
import com.delect.motiver.server.jdo.UserOpenid;
import com.delect.motiver.shared.Constants;
import com.delect.motiver.shared.Permission;
import com.delect.motiver.shared.exception.ConnectionException;
import com.delect.motiver.shared.exception.NoPermissionException;
import com.delect.motiver.shared.exception.NotLoggedInException;
import com.google.appengine.api.users.User;
import com.google.appengine.api.users.UserService;
import com.google.appengine.api.users.UserServiceFactory;
import com.prodeagle.java.counters.Counter;
public class UserManager extends AbstractManager {
/**
* Logger for this class
*/
private static final Logger logger = Logger.getLogger(UserManager.class.getName());
UserCache cache = UserCache.getInstance();
UserDAO dao = UserDAO.getInstance();
private static UserManager man;
public static UserManager getInstance() {
if(man == null) {
man = new UserManager();
}
return man;
}
/**
* Returns user. Throws exception if user not found
* @return null if no user found
*/
public UserOpenid getUser(ThreadLocal<HttpServletRequest> request) throws NotLoggedInException, ConnectionException {
if(logger.isLoggable(Level.FINE)) {
logger.log(Level.FINE, "Loading user: "+request);
}
String coachModeUid = null;
try {
String s = request.get().getHeader("coach_mode_uid");
if(s != null && s.length() > 1) {
coachModeUid = s;
}
} catch (Exception e) {
logger.log(Level.SEVERE, "Error checkin coach mode", e);
coachModeUid = null;
}
//increment
HttpSession session = request.get().getSession();
if(session == null || session.getAttribute("newLogin") == null) {
session.setAttribute("newLogin", "true");
Counter.increment("User.Login");
}
return _getUid(request, coachModeUid);
}
private UserOpenid _getUid(ThreadLocal<HttpServletRequest> request, String coachModeUid) throws NotLoggedInException, ConnectionException {
if(logger.isLoggable(Level.FINER)) {
logger.log(Level.FINER, "Loading user: "+coachModeUid);
}
UserOpenid user = null;
String openId = null;
UserService userService = UserServiceFactory.getUserService();
User userCurrent = userService.getCurrentUser();
if(userCurrent != null) {
openId = userCurrent.getUserId();
}
try {
//if coach mode -> return trainee
if(coachModeUid != null) {
if(logger.isLoggable(Level.FINER)) {
logger.log(Level.FINER, "Checking if user "+openId+" is coach to "+coachModeUid);
}
Circle circle = _getCircle(Permission.COACH, coachModeUid, openId);
if(circle != null) {
logger.log(Level.FINER, "Is coach!");
openId = circle.getUid();
}
}
if(openId != null) {
user = getUser(openId);
//if not found -> create
if(user == null) {
//get locale
String locale = Constants.LOCALE_DEFAULT;
Locale loc = request.get().getLocale();
if(loc != null) {
locale = loc.getLanguage()+"_"+loc.getCountry();
}
user = createUser(userCurrent, locale);
}
}
} catch (Exception e) {
logger.log(Level.SEVERE, "Error loading user", e);
}
if(user == null) {
handleException("UserManager._getUid", new NotLoggedInException());
}
return user;
}
private Circle _getCircle(int target, String uid, String friendUid) throws Exception {
if(logger.isLoggable(Level.FINER)) {
logger.log(Level.FINER, "Loading permission circle ("+target+", "+uid+", "+friendUid+")");
}
Circle circle = cache.getCircle(target, uid, friendUid);
if(circle == null) {
CircleSearchParams params = new CircleSearchParams(target, uid, friendUid);
params.limit = 1;
List<Circle> list = dao.getCircle(params);
if(list != null && list.size() > 0) {
circle = list.get(0);
cache.addCircle(circle);
}
}
return circle;
}
private boolean _checkPermission(int target, String ourUid, String uid) throws ConnectionException {
if(logger.isLoggable(Level.FINER)) {
logger.log(Level.FINER, "Checking permissions ("+target+", "+ourUid+", "+uid+")");
}
boolean ok = false;
Circle circle = null;
try {
//if read
if(target == Permission.READ_TRAINING
|| target == Permission.READ_NUTRITION
|| target == Permission.READ_NUTRITION_FOODS
|| target == Permission.READ_CARDIO
|| target == Permission.READ_MEASUREMENTS) {
circle = _getCircle(target, uid, ourUid);
}
//write permission -> check if coach
else {
circle = _getCircle(Permission.COACH, uid, ourUid);
}
if(circle != null) {
ok = true;
}
} catch (Exception e) {
logger.log(Level.SEVERE, "Error loading permission", e);
handleException("UserManager._checkPermission", e);
}
return ok;
}
/**
* Checks if user has permission to given target. Throws NoPermissionException if not
* @param target
* @param ourUid
* @param uid
* @return
* @throws NoPermissionException
*/
public void checkPermission(int target, String ourUid, String uid) throws NoPermissionException,ConnectionException {
if(logger.isLoggable(Level.FINE)) {
logger.log(Level.FINE, "Checking permissions ("+target+", "+ourUid+", "+uid+")");
}
//if own data -> return always true
if(ourUid.equals(uid)) {
return;
}
boolean ok = false;
try {
ok = _checkPermission(target, ourUid, uid);
} catch (ConnectionException e) {
logger.log(Level.SEVERE, "Error checking permissions", e);
}
if(!ok) {
handleException("UserManager.checkPermission", new NoPermissionException(target, ourUid, uid));
}
}
/**
* Return true if user has permission to given target.
* @param target
* @param ourUid
* @param uid
* @return
* @throws NoPermissionException
*/
public boolean hasPermission(int target, String ourUid, String uid) {
if(logger.isLoggable(Level.FINE)) {
logger.log(Level.FINE, "Checking if user has permission ("+target+", "+ourUid+", "+uid+")");
}
//if own data -> return always true
if(ourUid.equals(uid)) {
return true;
}
boolean ok = false;
try {
ok = _checkPermission(target, ourUid, uid);
} catch (ConnectionException e) {
logger.log(Level.SEVERE, "Error checking permissions", e);
}
return ok;
}
public void addUserToCircle(UserOpenid user, Circle circle) throws ConnectionException {
if(logger.isLoggable(Level.FINE)) {
logger.log(Level.FINE, "Adding permission to user ("+circle+")");
}
try {
circle.setUid(user.getUid());
dao.addCircle(circle);
cache.addCircle(circle);
//remove user's from cache if set as coach
if(circle.getTarget().equals(Permission.COACH)) {
cache.removeUser(circle.getFriendId());
}
} catch (Exception e) {
logger.log(Level.SEVERE, "Error adding user to circle", e);
handleException("UserManager.addUserToCircle", e);
}
}
public void removeUserFromCircle(UserOpenid user, int target, String uid) throws ConnectionException {
if(logger.isLoggable(Level.FINE)) {
logger.log(Level.FINE, "Removing permission from user ("+target+", "+uid+")");
}
try {
CircleSearchParams params = new CircleSearchParams(target, user.getUid(), uid);
params.limit = 1;
List<Circle> list = dao.getCircle(params);
if(list != null && list.size() > 0) {
Circle circle = list.get(0);
cache.removeCircle(circle);
dao.removeCircle(circle);
}
} catch (Exception e) {
logger.log(Level.SEVERE, "Error adding user to circle", e);
handleException("UserManager.removeUserFromCircle", e);
}
}
public List<UserOpenid> getUsersFromCircle(UserOpenid user, int target) throws ConnectionException {
if(logger.isLoggable(Level.FINE)) {
logger.log(Level.FINE, "Loading permissions ("+target+")");
}
List<UserOpenid> list = new ArrayList<UserOpenid>();
try {
List<Circle> circles = dao.getCircles(user.getUid(), target);
if(circles != null) {
for(Circle circle : circles) {
if(!circle.getFriendId().equals("-1")) {
UserOpenid u = getUser(circle.getFriendId());
if(u != null) {
list.add(u);
}
}
//all users
else {
list.add(new UserOpenid("-1"));
}
}
}
} catch (Exception e) {
logger.log(Level.SEVERE, "Error loading users", e);
handleException("UserManager.getUsersFromCircle", e);
}
return list;
}
/**
* Returns user based on given uid. Returns null if user not found
* @param uid
* @return
* @throws Exception
*/
public UserOpenid getUser(String uid) {
if(logger.isLoggable(Level.FINE)) {
logger.log(Level.FINE, "Loading single user ("+uid+")");
}
UserOpenid u = null;
try {
u = cache.getUser(uid);
if(u == null) {
u = dao.getUser(uid);
if(u != null) {
//check if someone has set this user as coach
Circle circle = _getCircle(Permission.COACH, null, u.getUid());
if(circle != null)
u.setCoach(true);
cache.setUser(u);
}
}
} catch (Exception e) {
logger.log(Level.WARNING, "User "+uid+" not found");
}
return u;
}
public List<UserOpenid> searchUsers(UserOpenid user, String query, int index) throws ConnectionException {
if(logger.isLoggable(Level.FINE)) {
logger.log(Level.FINE, "Searching users ("+index+", "+query+")");
}
List<UserOpenid> list = new ArrayList<UserOpenid>();
try {
//split query string
String[] arr = query.split(" ");
//load from cache
List<UserOpenid> listAll = dao.getUsers();
int i = 0;
for(UserOpenid m : listAll) {
if(!m.getUid().equals(user.getUid())) {
if(i >= index) {
final String name = m.getNickName();
//filter by query
boolean match = false;
for(String s : arr) {
match = name.toLowerCase().contains( s.toLowerCase() );
if(match) {
break;
}
}
if(match) {
list.add(m);
}
}
i++;
}
}
} catch (Exception e) {
logger.log(Level.SEVERE, "Error adding exercise names", e);
handleException("UserManager.searchUsers", e);
}
return list;
}
public void saveUser(UserOpenid user, UserOpenid updatedModel) throws ConnectionException {
if(logger.isLoggable(Level.FINE)) {
logger.log(Level.FINE, "Saving user ("+user.getUid()+", "+updatedModel+")");
}
try {
//to make sure we update our model
updatedModel.setUid(user.getUid());
dao.updateUser(updatedModel);
//update cache
cache.setUser(updatedModel);
} catch (Exception e) {
logger.log(Level.SEVERE, "Error saving user", e);
handleException("UserManager.saveUser", e);
}
}
/**
* Creates new user
* @param user
* @param userAppengine
* @throws ConnectionException
*/
public UserOpenid createUser(User userAppengine, String locale) throws ConnectionException {
if(logger.isLoggable(Level.FINE)) {
logger.log(Level.FINE, "Creating new user ("+userAppengine+")");
}
//new user
Counter.increment("User.New");
UserOpenid user = new UserOpenid();
try {
user.update(userAppengine);
user.setLocale(locale);
dao.updateUser(user);
//update cache
cache.setUser(user);
} catch (Exception e) {
logger.log(Level.SEVERE, "Error creating user", e);
handleException("UserManager.createUser", e);
}
return user;
}
}