/*
* Copyright 2015-Present Entando Inc. (http://www.entando.com) All rights reserved.
*
* This library is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 2.1 of the License, or (at your option)
* any later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*/
package org.entando.entando.aps.system.services.userprofile;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.entando.entando.aps.system.services.cache.CacheInfoEvict;
import org.entando.entando.aps.system.services.cache.CacheableInfo;
import org.entando.entando.aps.system.services.cache.ICacheInfoManager;
import org.entando.entando.aps.system.services.userprofile.event.ProfileChangedEvent;
import org.entando.entando.aps.system.services.userprofile.model.IUserProfile;
import org.entando.entando.aps.system.services.userprofile.model.UserProfileRecord;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import com.agiletec.aps.system.SystemConstants;
import com.agiletec.aps.system.common.entity.ApsEntityManager;
import com.agiletec.aps.system.common.entity.IEntityDAO;
import com.agiletec.aps.system.common.entity.IEntitySearcherDAO;
import com.agiletec.aps.system.common.entity.model.IApsEntity;
import com.agiletec.aps.system.exception.ApsSystemException;
import com.agiletec.aps.system.services.category.ICategoryManager;
import com.agiletec.aps.system.services.user.AbstractUser;
import com.agiletec.aps.system.services.user.UserDetails;
/**
* Implementation of ProfileManager.
* The service is included in a transparent manner in the workflow of required
* to insert, update or delete user, using the Aspect-oriented programming.
* In that way, you can join a user with his Profile whatever implementation of User Management.
* @author E.Santoboni
*/
@Aspect
public class UserProfileManager extends ApsEntityManager implements IUserProfileManager {
private static final Logger _logger = LoggerFactory.getLogger(UserProfileManager.class);
@AfterReturning(pointcut = "execution(* com.agiletec.aps.system.services.user.IUserManager.getUser(..))", returning = "user")
public void injectProfile(Object user) {
if (user != null) {
AbstractUser userDetails = (AbstractUser) user;
if (null == userDetails.getProfile()) {
try {
IUserProfile profile = this.getProfile(userDetails.getUsername());
userDetails.setProfile(profile);
} catch (Throwable t) {
_logger.error("Error injecting profile on user {}", userDetails.getUsername(), t);
}
}
}
}
@AfterReturning(pointcut = "execution(* com.agiletec.aps.system.services.user.IUserManager.addUser(..)) && args(user,..)")
public void addProfile(Object user) {
if (user != null) {
UserDetails userDetails = (UserDetails) user;
Object profile = userDetails.getProfile();
if (null != profile) {
try {
this.addProfile(userDetails.getUsername(), (IUserProfile) profile);
} catch (Throwable t) {
_logger.error("Error adding profile on user {}", userDetails.getUsername(), t);
}
}
}
}
@AfterReturning(pointcut = "execution(* com.agiletec.aps.system.services.user.IUserManager.updateUser(..)) && args(user,..)")
@CacheEvict(value = ICacheInfoManager.DEFAULT_CACHE_NAME, key = "'UserProfile_'.concat(#user.username)")
public void updateProfile(Object user) {
if (user != null) {
UserDetails userDetails = (UserDetails) user;
Object profile = userDetails.getProfile();
if (null != profile) {
try {
this.updateProfile(userDetails.getUsername(), (IUserProfile) profile);
} catch (Throwable t) {
_logger.error("Error updating profile to user {}", userDetails.getUsername(), t);
}
}
}
}
@AfterReturning(pointcut = "execution(* com.agiletec.aps.system.services.user.IUserManager.removeUser(..)) && args(key)")
@CacheEvict(value = ICacheInfoManager.DEFAULT_CACHE_NAME, key = "'UserProfile_'.concat(#key)")
public void deleteProfile(Object key) {
String username = null;
if (key instanceof String) {
username = key.toString();
} else if (key instanceof UserDetails) {
UserDetails userDetails = (UserDetails) key;
username = userDetails.getUsername();
}
if (username != null) {
try {
this.deleteProfile(username);
} catch (Throwable t) {
_logger.error("Error deleting profile. user: {}", username, t);
}
}
}
@Override
public IApsEntity getEntity(String entityId) throws ApsSystemException {
return this.getProfile(entityId);
}
@Override
public IUserProfile getDefaultProfileType() {
IUserProfile profileType = (IUserProfile) super.getEntityPrototype(SystemConstants.DEFAULT_PROFILE_TYPE_CODE);
if (null == profileType) {
List<String> entityTypes = new ArrayList<String>();
entityTypes.addAll(this.getEntityPrototypes().keySet());
if (!entityTypes.isEmpty()) {
Collections.sort(entityTypes);
profileType = (IUserProfile) super.getEntityPrototype(entityTypes.get(0));
}
}
return profileType;
}
@Override
public IUserProfile getProfileType(String typeCode) {
return (IUserProfile) super.getEntityPrototype(typeCode);
}
@Override
public void addProfile(String username, IUserProfile profile) throws ApsSystemException {
try {
profile.setId(username);
this.getProfileDAO().addEntity(profile);
this.notifyProfileChanging(profile, ProfileChangedEvent.INSERT_OPERATION_CODE);
} catch (Throwable t) {
_logger.error("Error saving profile - user: {}", username, t);
throw new ApsSystemException("Error saving profile", t);
}
}
@Override
@CacheEvict(value = ICacheInfoManager.DEFAULT_CACHE_NAME, key = "'UserProfile_'.concat(#username)")
public void deleteProfile(String username) throws ApsSystemException {
try {
IUserProfile profileToDelete = this.getProfile(username);
if (null == profileToDelete) {
return;
}
this.getProfileDAO().deleteEntity(username);
this.notifyProfileChanging(profileToDelete, ProfileChangedEvent.REMOVE_OPERATION_CODE);
} catch (Throwable t) {
_logger.error("Error deleting user profile {}", username, t);
throw new ApsSystemException("Error deleting user profile", t);
}
}
@Override
@Cacheable(value = ICacheInfoManager.DEFAULT_CACHE_NAME, key = "'UserProfile_'.concat(#username)")
@CacheableInfo(groups = "'UserProfileTypes_cacheGroup'")
public IUserProfile getProfile(String username) throws ApsSystemException {
IUserProfile profile = null;
try {
UserProfileRecord profileVO = (UserProfileRecord) this.getProfileDAO().loadEntityRecord(username);
if (profileVO != null) {
profile = (IUserProfile) this.createEntityFromXml(profileVO.getTypeCode(), profileVO.getXml());
profile.setPublicProfile(profileVO.isPublicProfile());
}
} catch (Throwable t) {
_logger.error("Error loading profile. user: {} ", username, t);
throw new ApsSystemException("Error loading profile", t);
}
return profile;
}
@Override
@CacheEvict(value = ICacheInfoManager.DEFAULT_CACHE_NAME, key = "'UserProfile_'.concat(#username)")
public void updateProfile(String username, IUserProfile profile) throws ApsSystemException {
try {
profile.setId(username);
this.getProfileDAO().updateEntity(profile);
this.notifyProfileChanging(profile, ProfileChangedEvent.UPDATE_OPERATION_CODE);
} catch (Throwable t) {
_logger.error("Error updating profile {}", username, t);
throw new ApsSystemException("Error updating profile", t);
}
}
private void notifyProfileChanging(IUserProfile profile, int operationCode) throws ApsSystemException {
ProfileChangedEvent event = new ProfileChangedEvent();
event.setProfile(profile);
event.setOperationCode(operationCode);
this.notifyEvent(event);
}
@Override
@CacheInfoEvict(value = ICacheInfoManager.DEFAULT_CACHE_NAME, groups = "'UserProfileTypes_cacheGroup'")
public void removeEntityPrototype(String entityTypeCode) throws ApsSystemException {
super.removeEntityPrototype(entityTypeCode);
}
@Override
@CacheInfoEvict(value = ICacheInfoManager.DEFAULT_CACHE_NAME, groups = "'UserProfileTypes_cacheGroup'")
public void updateEntityPrototype(IApsEntity entityType) throws ApsSystemException {
super.updateEntityPrototype(entityType);
}
@Override
protected ICategoryManager getCategoryManager() {
return null;
}
@Override
protected IEntityDAO getEntityDao() {
return (IEntityDAO) this.getProfileDAO();
}
@Override
protected IEntitySearcherDAO getEntitySearcherDao() {
return _entitySearcherDAO;
}
protected IUserProfileDAO getProfileDAO() {
return _profileDAO;
}
public void setProfileDAO(IUserProfileDAO profileDAO) {
this._profileDAO = profileDAO;
}
protected IEntitySearcherDAO getEntitySearcherDAO() {
return _entitySearcherDAO;
}
public void setEntitySearcherDAO(IEntitySearcherDAO entitySearcherDAO) {
this._entitySearcherDAO = entitySearcherDAO;
}
private IUserProfileDAO _profileDAO;
private IEntitySearcherDAO _entitySearcherDAO;
}