/*
*
* Copyright (C) 2007-2015 Licensed to the Comunes Association (CA) under
* one or more contributor license agreements (see COPYRIGHT for details).
* The CA licenses this file to you under the GNU Affero General Public
* License version 3, (the "License"); you may not use this file except in
* compliance with the License. This file is part of kune.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package cc.kune.core.server.manager.impl;
import java.util.List;
import java.util.Set;
import javax.persistence.EntityManager;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import cc.kune.core.client.errors.AccessViolationException;
import cc.kune.core.client.errors.AlreadyGroupMemberException;
import cc.kune.core.client.errors.AlreadyUserMemberException;
import cc.kune.core.client.errors.DefaultException;
import cc.kune.core.client.errors.InvalidSNOperationException;
import cc.kune.core.client.errors.LastAdminInGroupException;
import cc.kune.core.client.errors.UserMustBeLoggedException;
import cc.kune.core.server.access.AccessRightsService;
import cc.kune.core.server.error.ServerException;
import cc.kune.core.server.manager.SocialNetworkManager;
import cc.kune.core.server.manager.UserManager;
import cc.kune.core.server.mapper.KuneMapper;
import cc.kune.core.server.notifier.NotificationService;
import cc.kune.core.server.persist.DataSourceKune;
import cc.kune.core.shared.domain.AdmissionType;
import cc.kune.core.shared.domain.GroupListMode;
import cc.kune.core.shared.domain.SocialNetworkVisibility;
import cc.kune.core.shared.domain.UserSNetVisibility;
import cc.kune.core.shared.domain.utils.AccessRights;
import cc.kune.core.shared.dto.GroupType;
import cc.kune.core.shared.dto.SocialNetworkDataDTO;
import cc.kune.core.shared.dto.SocialNetworkRequestResult;
import cc.kune.domain.Group;
import cc.kune.domain.ParticipationData;
import cc.kune.domain.SocialNetwork;
import cc.kune.domain.SocialNetworkData;
import cc.kune.domain.User;
import cc.kune.domain.UserBuddiesData;
import cc.kune.domain.finders.GroupFinder;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;
// TODO: Auto-generated Javadoc
/**
* The Class SocialNetworkManagerDefault.
*
* @author vjrj@ourproject.org (Vicente J. Ruiz Jurado)
*/
@Singleton
public class SocialNetworkManagerDefault extends DefaultManager<SocialNetwork, Long> implements
SocialNetworkManager {
/** The Constant LOG. */
public static final Log LOG = LogFactory.getLog(SocialNetworkManagerDefault.class);
/** The access rights service. */
private final AccessRightsService accessRightsService;
/** The finder. */
private final GroupFinder finder;
/** The mapper. */
private final KuneMapper mapper;
/** The notify service. */
private final NotificationService notifyService;
/** The sn cache. */
private final SocialNetworkCache snCache;
/** The user manager. */
private final UserManager userManager;
/**
* Instantiates a new social network manager default.
*
* @param provider
* the provider
* @param finder
* the finder
* @param accessRightsService
* the access rights service
* @param mapper
* the mapper
* @param userManager
* the user manager
* @param snCache
* the sn cache
* @param notifyService
* the notify service
*/
@Inject
public SocialNetworkManagerDefault(@DataSourceKune final Provider<EntityManager> provider,
final GroupFinder finder, final AccessRightsService accessRightsService, final KuneMapper mapper,
final UserManager userManager, final SocialNetworkCache snCache,
final NotificationService notifyService) {
super(provider, SocialNetwork.class);
this.finder = finder;
this.accessRightsService = accessRightsService;
this.mapper = mapper;
this.userManager = userManager;
this.snCache = snCache;
this.notifyService = notifyService;
}
/*
* (non-Javadoc)
*
* @see
* cc.kune.core.server.manager.SocialNetworkManager#acceptJoinGroup(cc.kune
* .domain.User, cc.kune.domain.Group, cc.kune.domain.Group)
*/
@Override
public void acceptJoinGroup(final User userLogged, final Group group, final Group inGroup)
throws DefaultException, AccessViolationException {
final SocialNetwork sn = inGroup.getSocialNetwork();
checkUserLoggedIsAdmin(userLogged, sn);
final Set<Group> pendingCollabs = sn.getPendingCollaborators().getList();
if (pendingCollabs.contains(group)) {
addGroupToCollabs(userLogged, group, inGroup);
notifyService.notifyGroupMembers(group, inGroup, "Accepted as member",
"You are now member of this group");
} else {
throw new DefaultException("User is not a pending collaborator");
}
}
/**
* Adds the admin.
*
* @param newAdmin
* the new admin
* @param group
* the group
*/
void addAdmin(final User newAdmin, final Group group) {
final SocialNetwork sn = group.getSocialNetwork();
sn.addAdmin(newAdmin.getUserGroup());
snCache.expire(group);
}
/*
* (non-Javadoc)
*
* @see
* cc.kune.core.server.manager.SocialNetworkManager#addAsBuddie(cc.kune.domain
* .User, cc.kune.domain.User)
*/
@Override
public void addAsBuddie(final User userLogged, final User toUser) {
notifyService.notifyUserToUserByEmail(userLogged, toUser, "Added as buddie",
"He/she added you as buddie");
snCache.expire(userLogged.getUserGroup());
snCache.expire(toUser.getUserGroup());
}
/*
* (non-Javadoc)
*
* @see
* cc.kune.core.server.manager.SocialNetworkManager#addGroupToAdmins(cc.kune
* .domain.User, cc.kune.domain.Group, cc.kune.domain.Group)
*/
@Override
public void addGroupToAdmins(final User userLogged, final Group group, final Group inGroup)
throws DefaultException {
checkGroupAddingToSelf(group, inGroup);
final SocialNetwork sn = inGroup.getSocialNetwork();
checkUserLoggedIsAdmin(userLogged, sn);
checkGroupIsNotAlreadyAMember(group, sn);
sn.addAdmin(group);
if (sn.isPendingCollab(group)) {
sn.removePendingCollaborator(group);
}
notifyService.notifyGroupMembers(group, inGroup, "Added as administrator",
"You are now admin of this group");
snCache.expire(group);
snCache.expire(inGroup);
}
/*
* (non-Javadoc)
*
* @see
* cc.kune.core.server.manager.SocialNetworkManager#addGroupToCollabs(cc.kune
* .domain.User, cc.kune.domain.Group, cc.kune.domain.Group)
*/
@Override
public void addGroupToCollabs(final User userLogged, final Group group, final Group inGroup)
throws DefaultException {
checkGroupAddingToSelf(group, inGroup);
final SocialNetwork sn = inGroup.getSocialNetwork();
checkUserLoggedIsAdmin(userLogged, sn);
checkGroupIsNotAlreadyAMember(group, sn);
sn.addCollaborator(group);
if (sn.isPendingCollab(group)) {
sn.removePendingCollaborator(group);
}
notifyService.notifyGroupMembers(group, inGroup, "Added as collaborator",
"You are now a collaborator of this group");
snCache.expire(group);
snCache.expire(inGroup);
}
/*
* (non-Javadoc)
*
* @see
* cc.kune.core.server.manager.SocialNetworkManager#addGroupToViewers(cc.kune
* .domain.User, cc.kune.domain.Group, cc.kune.domain.Group)
*/
@Override
public void addGroupToViewers(final User userLogged, final Group group, final Group inGroup)
throws DefaultException {
checkGroupAddingToSelf(group, inGroup);
final SocialNetwork sn = inGroup.getSocialNetwork();
checkUserLoggedIsAdmin(userLogged, sn);
checkGroupIsNotAlreadyAMember(group, sn);
sn.addViewer(group);
if (sn.isPendingCollab(group)) {
sn.removePendingCollaborator(group);
}
snCache.expire(group);
snCache.expire(inGroup);
}
/**
* Check group adding to self.
*
* @param group
* the group
* @param inGroup
* the in group
* @throws DefaultException
* the default exception
*/
private void checkGroupAddingToSelf(final Group group, final Group inGroup) throws DefaultException {
if (group.equals(inGroup)) {
throwGroupMemberException(group);
}
}
/**
* Check group is not already a member.
*
* @param group
* the group
* @param sn
* the sn
* @throws DefaultException
* the default exception
*/
private void checkGroupIsNotAlreadyAMember(final Group group, final SocialNetwork sn)
throws DefaultException {
if (sn.isAdmin(group) || sn.isCollab(group) || sn.isViewer(group) && notEveryOneCanView(sn)) {
throwGroupMemberException(group);
}
}
/**
* Check user logged is admin.
*
* @param userLogged
* the user logged
* @param sn
* the sn
* @throws AccessViolationException
* the access violation exception
*/
private void checkUserLoggedIsAdmin(final User userLogged, final SocialNetwork sn)
throws AccessViolationException {
if (!accessRightsService.get(userLogged, sn.getAccessLists()).isAdministrable()) {
throw new AccessViolationException();
}
}
/*
* (non-Javadoc)
*
* @see
* cc.kune.core.server.manager.SocialNetworkManager#deleteMember(cc.kune.domain
* .User, cc.kune.domain.Group, cc.kune.domain.Group)
*/
@Override
public void deleteMember(final User userLogged, final Group group, final Group inGroup)
throws DefaultException, AccessViolationException {
final SocialNetwork sn = inGroup.getSocialNetwork();
checkUserLoggedIsAdmin(userLogged, sn);
unJoinGroup(group, inGroup);
notifyService.notifyGroupMembers(group, inGroup, "Removed as collaborator",
"You have been removed as collaborator of this group");
snCache.expire(group);
snCache.expire(inGroup);
}
/*
* (non-Javadoc)
*
* @see
* cc.kune.core.server.manager.SocialNetworkManager#denyJoinGroup(cc.kune.
* domain.User, cc.kune.domain.Group, cc.kune.domain.Group)
*/
@Override
public void denyJoinGroup(final User userLogged, final Group group, final Group inGroup)
throws DefaultException {
final SocialNetwork sn = inGroup.getSocialNetwork();
checkUserLoggedIsAdmin(userLogged, sn);
final Set<Group> pendingCollabs = sn.getPendingCollaborators().getList();
if (pendingCollabs.contains(group)) {
sn.removePendingCollaborator(group);
notifyService.notifyGroupMembers(group, inGroup, "Membership denied",
"Your membership to this group has been rejected");
} else {
throw new DefaultException("Person/Group is not a pending collaborator");
}
snCache.expire(group);
snCache.expire(inGroup);
}
/*
* (non-Javadoc)
*
* @see
* cc.kune.core.server.manager.SocialNetworkManager#findParticipation(cc.kune
* .domain.User, cc.kune.domain.Group)
*/
@Override
public ParticipationData findParticipation(final User userLogged, final Group group)
throws AccessViolationException {
final SocialNetwork sn = group.getSocialNetwork();
get(userLogged, group); // check access
final Long groupId = group.getId();
final boolean isMember = sn.isAdmin(userLogged.getUserGroup())
|| sn.isCollab(userLogged.getUserGroup());
final Set<Group> adminInGroups = (isMember ? finder.findAdminInGroups(groupId)
: finder.findAdminInGroups(groupId, GroupType.CLOSED));
// Don't show self user group
if (group.isPersonal()) {
adminInGroups.remove(group);
}
// adminInGroups.remove(userLogged.getUserGroup());
final Set<Group> collabInGroups = isMember ? finder.findCollabInGroups(groupId)
: finder.findCollabInGroups(groupId, GroupType.CLOSED);
return new ParticipationData(adminInGroups, collabInGroups);
}
/*
* (non-Javadoc)
*
* @see
* cc.kune.core.server.manager.SocialNetworkManager#findParticipationAggregated
* (cc.kune.domain.User, cc.kune.domain.Group)
*/
@Override
public List<Group> findParticipationAggregated(final User userLogged, final Group group)
throws AccessViolationException {
get(userLogged, group); // check access
final Long groupId = group.getId();
final List<Group> groups = finder.findParticipatingInGroups(groupId);
// Don't show self user group
if (group.isPersonal()) {
groups.remove(group);
}
return groups;
}
/*
* (non-Javadoc)
*
* @see
* cc.kune.core.server.manager.SocialNetworkManager#generateResponse(cc.kune
* .domain.User, cc.kune.domain.Group)
*/
@Override
public SocialNetworkDataDTO generateResponse(final User userLogged, final Group group) {
return mapper.map(getSocialNetworkData(userLogged, group), SocialNetworkDataDTO.class);
}
/*
* (non-Javadoc)
*
* @see
* cc.kune.core.server.manager.SocialNetworkManager#get(cc.kune.domain.User,
* cc.kune.domain.Group)
*/
@Override
public SocialNetwork get(final User petitioner, final Group group) throws AccessViolationException {
final SocialNetwork sn = group.getSocialNetwork();
if (!sn.getAccessLists().getViewers().includes(petitioner.getUserGroup())
&& !sn.getAccessLists().getEditors().includes(petitioner.getUserGroup())
&& !sn.getAccessLists().getAdmins().includes(petitioner.getUserGroup())) {
throw new AccessViolationException();
}
return sn;
}
/*
* (non-Javadoc)
*
* @see
* cc.kune.core.server.manager.SocialNetworkManager#getSocialNetworkData(cc
* .kune.domain.User, cc.kune.domain.Group)
*/
@Override
public SocialNetworkData getSocialNetworkData(final User userLogged, final Group group) {
final SocialNetworkData socialNetData = new SocialNetworkData();
socialNetData.setGroupMembers(get(userLogged, group));
final SocialNetworkData cached = snCache.get(userLogged, group);
if (cached != null) {
LOG.debug("Returning cached SN");
return cached;
}
final AccessRights groupRights = accessRightsService.get(userLogged, group.getAccessLists());
socialNetData.setGroupRights(groupRights);
socialNetData.setUserParticipation(findParticipation(userLogged, group));
// socialNetData.setGroupMembers(get(userLogged, group));
if (group.isPersonal()) {
final UserBuddiesData userBuddies = userManager.getUserBuddies(group.getShortName());
final User userGroup = userManager.findByShortname(group.getShortName());
socialNetData.setUserBuddies(userBuddies);
final UserSNetVisibility buddiesVisibility = userGroup.getSNetVisibility();
socialNetData.setIsBuddiesVisible(true);
switch (buddiesVisibility) {
case anyone:
break;
case onlyyou:
if (userLogged.equals(User.UNKNOWN_USER) || !userLogged.getUserGroup().equals(group)) {
socialNetData.setIsBuddiesVisible(false);
socialNetData.setUserBuddies(UserBuddiesData.EMPTY);
}
break;
case yourbuddies:
final boolean notMe = !userLogged.equals(userGroup);
final boolean notABuddie = !userBuddies.contains(userLogged.getShortName());
if (notMe && notABuddie) {
socialNetData.setIsBuddiesVisible(false);
socialNetData.setUserBuddies(UserBuddiesData.EMPTY);
}
break;
}
socialNetData.setUserBuddiesVisibility(buddiesVisibility);
} else {
final SocialNetworkVisibility visibility = group.getSocialNetwork().getVisibility();
socialNetData.setIsMembersVisible(true);
switch (visibility) {
case anyone:
break;
case onlyadmins:
if (!groupRights.isAdministrable()) {
socialNetData.setIsMembersVisible(false);
socialNetData.setGroupMembers(SocialNetwork.EMPTY);
}
break;
case onlymembers:
if (!groupRights.isEditable()) {
socialNetData.setIsMembersVisible(false);
socialNetData.setGroupMembers(SocialNetwork.EMPTY);
}
break;
}
socialNetData.setSocialNetworkVisibility(visibility);
socialNetData.setUserBuddies(UserBuddiesData.EMPTY);
}
snCache.put(userLogged, group, socialNetData);
return socialNetData;
}
/**
* Checks if is closed.
*
* @param admissionType
* the admission type
* @return true, if is closed
*/
private boolean isClosed(final AdmissionType admissionType) {
return admissionType.equals(AdmissionType.Closed);
}
/**
* Checks if is moderated.
*
* @param admissionType
* the admission type
* @return true, if is moderated
*/
private boolean isModerated(final AdmissionType admissionType) {
return admissionType.equals(AdmissionType.Moderated);
}
/**
* Checks if is open.
*
* @param admissionType
* the admission type
* @return true, if is open
*/
private boolean isOpen(final AdmissionType admissionType) {
return admissionType.equals(AdmissionType.Open);
}
/**
* Not every one can view.
*
* @param sn
* the sn
* @return true, if successful
*/
private boolean notEveryOneCanView(final SocialNetwork sn) {
return !sn.getAccessLists().getViewers().getMode().equals(GroupListMode.EVERYONE);
}
/*
* (non-Javadoc)
*
* @see
* cc.kune.core.server.manager.SocialNetworkManager#requestToJoin(cc.kune.
* domain.User, cc.kune.domain.Group)
*/
@Override
public SocialNetworkRequestResult requestToJoin(final User userLogged, final Group inGroup)
throws DefaultException, UserMustBeLoggedException {
final SocialNetwork sn = inGroup.getSocialNetwork();
if (!User.isKnownUser(userLogged)) {
throw new UserMustBeLoggedException();
}
final AdmissionType admissionType = inGroup.getAdmissionType();
if (admissionType == null) {
throw new ServerException("No admissionType");
}
final Group userGroup = userLogged.getUserGroup();
checkGroupIsNotAlreadyAMember(userGroup, sn);
if (isModerated(admissionType)) {
sn.addPendingCollaborator(userGroup);
notifyService.notifyGroupAdmins(inGroup, inGroup, "Pending collaborator",
"There is a pending collaborator in this group. Please accept or deny him/her");
snCache.expire(userGroup);
snCache.expire(inGroup);
return SocialNetworkRequestResult.moderated;
} else if (isOpen(admissionType)) {
if (inGroup.getGroupType().equals(GroupType.ORPHANED_PROJECT)) {
sn.addAdmin(userGroup);
inGroup.setGroupType(GroupType.PROJECT);
inGroup.setAdmissionType(AdmissionType.Moderated);
persist(inGroup, Group.class);
} else {
sn.addCollaborator(userGroup);
}
snCache.expire(userGroup);
snCache.expire(inGroup);
return SocialNetworkRequestResult.accepted;
} else if (isClosed(admissionType)) {
return SocialNetworkRequestResult.denied;
} else {
throw new DefaultException("State not expected in SocialNetworkManagerDefault class");
}
}
/*
* (non-Javadoc)
*
* @see
* cc.kune.core.server.manager.SocialNetworkManager#setAdminAsCollab(cc.kune
* .domain.User, cc.kune.domain.Group, cc.kune.domain.Group)
*/
@Override
public void setAdminAsCollab(final User userLogged, final Group group, final Group inGroup)
throws DefaultException {
final SocialNetwork sn = inGroup.getSocialNetwork();
checkUserLoggedIsAdmin(userLogged, sn);
if (sn.isAdmin(group)) {
if (sn.getAccessLists().getAdmins().getList().size() == 1) {
throw new LastAdminInGroupException();
}
sn.removeAdmin(group);
sn.addCollaborator(group);
notifyService.notifyGroupMembers(group, inGroup, "Membership changed",
"Your membership to this group has changed. You are now a collaborator of this group");
snCache.expire(group);
snCache.expire(inGroup);
} else {
throw new InvalidSNOperationException("Person/Group is not an admin");
}
}
/*
* (non-Javadoc)
*
* @see
* cc.kune.core.server.manager.SocialNetworkManager#setCollabAsAdmin(cc.kune
* .domain.User, cc.kune.domain.Group, cc.kune.domain.Group)
*/
@Override
public void setCollabAsAdmin(final User userLogged, final Group group, final Group inGroup)
throws DefaultException {
final SocialNetwork sn = inGroup.getSocialNetwork();
checkUserLoggedIsAdmin(userLogged, sn);
if (sn.isCollab(group)) {
notifyService.notifyGroupMembers(group, inGroup, "Membership changed",
"Your membership to this group has changed. You are now an administrator of this group");
snCache.expire(group);
snCache.expire(inGroup);
sn.removeCollaborator(group);
sn.addAdmin(group);
} else {
throw new InvalidSNOperationException("Person/Group is not a collaborator");
}
}
/**
* Throw group member exception.
*
* @param group
* the group
* @throws DefaultException
* the default exception
*/
private void throwGroupMemberException(final Group group) throws DefaultException {
if (group.isPersonal()) {
throw new AlreadyUserMemberException();
} else {
throw new AlreadyGroupMemberException();
}
}
/*
* (non-Javadoc)
*
* @see
* cc.kune.core.server.manager.SocialNetworkManager#unJoinGroup(cc.kune.domain
* .Group, cc.kune.domain.Group)
*/
@Override
public void unJoinGroup(final Group groupToUnJoin, final Group inGroup) throws DefaultException {
final SocialNetwork sn = inGroup.getSocialNetwork();
if (sn.isAdmin(groupToUnJoin)) {
if (sn.getAccessLists().getAdmins().getList().size() == 1) {
if (sn.getAccessLists().getEditors().getList().size() > 0) {
throw new LastAdminInGroupException();
} else {
inGroup.setGroupType(GroupType.ORPHANED_PROJECT);
inGroup.setAdmissionType(AdmissionType.Open);
}
}
sn.removeAdmin(groupToUnJoin);
} else if (sn.isCollab(groupToUnJoin)) {
sn.removeCollaborator(groupToUnJoin);
} else {
throw new DefaultException("Person/Group is not a collaborator");
}
notifyService.notifyGroupAdmins(groupToUnJoin, inGroup, "A member left this group",
"A member has left this group");
snCache.expire(groupToUnJoin);
snCache.expire(inGroup);
}
}