/*
* Copyright (c) 2010 Lockheed Martin Corporation
*
* Licensed under the Apache 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.apache.org/licenses/LICENSE-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.eurekastreams.server.action.execution.profile;
import java.io.Serializable;
import java.util.Collections;
import java.util.List;
import org.apache.commons.logging.Log;
import org.eurekastreams.commons.actions.ExecutionStrategy;
import org.eurekastreams.commons.actions.context.Principal;
import org.eurekastreams.commons.actions.context.PrincipalActionContext;
import org.eurekastreams.commons.logging.LogFactory;
import org.eurekastreams.server.action.request.profile.GetCurrentUserFollowingStatusRequest;
import org.eurekastreams.server.domain.EntityType;
import org.eurekastreams.server.domain.Follower;
import org.eurekastreams.server.persistence.mappers.DomainMapper;
import org.eurekastreams.server.persistence.mappers.stream.GetDomainGroupsByShortNames;
import org.eurekastreams.server.persistence.mappers.stream.GetPeopleByOpenSocialIds;
import org.eurekastreams.server.search.modelview.DomainGroupModelView;
import org.eurekastreams.server.search.modelview.PersonModelView;
/**
* Action to determine if current user has Follower relationship with another user.
*
*/
public class GetCurrentUserFollowingStatusExecution implements ExecutionStrategy<PrincipalActionContext>
{
/**
* Logger.
*/
private Log log = LogFactory.make();
/**
* Mapper that looks-to/loads cache with people modelviews by open social id.
*/
private GetPeopleByOpenSocialIds getPeopleByOpenSocialIdsMapper;
/**
* Mapper to get followers of a group.
*/
private DomainMapper<Long, List<Long>> groupFollowerIdsMapper;
/**
* Mapper to get followers of a person.
*/
private DomainMapper<Long, List<Long>> followerIdsMapper;
/**
* Mapper to get a group by shortname.
*/
private GetDomainGroupsByShortNames groupsByNameMapper;
/**
* Mapper to get personmodelviews by accountids.
*/
private DomainMapper<List<String>, List<PersonModelView>> getPersonModelViewsByAccountIdsMapper;
/**
* A Regex pattern to match OpenSocial ids used by the local container.
*/
private String openSocialPattern;
/**
* Constructor that sets up the mapper.
*
* @param inGetPeopleByOpenSocialIdsMapper
* instance of GetPeopleByOpenSocialIdsMapper
* @param inPattern
* the pattern for matching open social ids.
* @param inGroupFollowerIdsMapper
* instance of GetGroupFollowerIds.
* @param inGollowerIdsMapper
* instance of GetFollowerIds.
* @param inGroupsByNameMapper
* instance of GetDomainGroupsByShortNames.
* @param inGetPersonModelViewsByAccountIdsMapper
* mapper to get personmodelviews by accountids.
*/
public GetCurrentUserFollowingStatusExecution(final GetPeopleByOpenSocialIds inGetPeopleByOpenSocialIdsMapper,
final String inPattern, final DomainMapper<Long, List<Long>> inGroupFollowerIdsMapper,
final DomainMapper<Long, List<Long>> inGollowerIdsMapper,
final GetDomainGroupsByShortNames inGroupsByNameMapper,
final DomainMapper<List<String>, List<PersonModelView>> inGetPersonModelViewsByAccountIdsMapper)
{
getPeopleByOpenSocialIdsMapper = inGetPeopleByOpenSocialIdsMapper;
openSocialPattern = inPattern;
groupFollowerIdsMapper = inGroupFollowerIdsMapper;
followerIdsMapper = inGollowerIdsMapper;
groupsByNameMapper = inGroupsByNameMapper;
getPersonModelViewsByAccountIdsMapper = inGetPersonModelViewsByAccountIdsMapper;
}
/**
* Returns true or false if the group exists and the current user is a coordinator.
*
* @param inActionContext
* The action context.
* @return true if the group exists and the user is authorized, false otherwise
*/
@Override
public Serializable execute(final PrincipalActionContext inActionContext)
{
// get the request.
GetCurrentUserFollowingStatusRequest inRequest = (GetCurrentUserFollowingStatusRequest) inActionContext
.getParams();
// get the user's account id.
final Principal principal = inActionContext.getPrincipal();
final String accountId = principal.getAccountId();
final Long userId = principal.getId();
// the followed entity's account id.
String followedEntityId = inRequest.getFollowedEntityId();
// the followed entity's entity type.
final EntityType entityType = inRequest.getEntityType();
if (log.isTraceEnabled())
{
log.trace("Checking the following status for the user " + accountId + " following " + followedEntityId
+ " of entity type " + entityType.toString());
}
// if open social id was passed for person, convert to acct. id. else entityId is an accountId
if (followedEntityId.matches(openSocialPattern) && entityType == EntityType.PERSON)
{
followedEntityId = getPeopleByOpenSocialIdsMapper.fetchUniqueResult(followedEntityId).getAccountId();
}
// if not logged in or trying to follow yourself, disable.
if (accountId == null || (accountId.equalsIgnoreCase(followedEntityId) && entityType == EntityType.PERSON))
{
return Follower.FollowerStatus.DISABLED;
}
Follower.FollowerStatus status = Follower.FollowerStatus.DISABLED;
if (EntityType.PERSON == entityType)
{
status = isUserFollowingUser(userId, followedEntityId);
}
else if (EntityType.GROUP == entityType)
{
status = isUserFollowingGroup(userId, followedEntityId);
}
return status;
}
/**
* Checks to see if a user is following a group.
*
* @param userId
* id of the user that is being checked as a follower.
* @param groupShortName
* id of the group being checked for followers.
* @return FollowerStatus of the user.
*/
private Follower.FollowerStatus isUserFollowingGroup(final long userId, final String groupShortName)
{
List<DomainGroupModelView> groups = groupsByNameMapper.execute(Collections.singletonList(groupShortName));
if (groups.size() > 0)
{
long groupId = groups.get(0).getEntityId();
List<Long> ids = groupFollowerIdsMapper.execute(groupId);
if (ids.contains(userId))
{
return Follower.FollowerStatus.FOLLOWING;
}
}
return Follower.FollowerStatus.NOTFOLLOWING;
}
/**
* Checks to see if a user is following another user.
*
* @param userId
* id of the user that is being checked as a follower.
* @param personAccountId
* id of the user being checked for followers
* @return FollowerStatus of the user.
*/
private Follower.FollowerStatus isUserFollowingUser(final long userId, final String personAccountId)
{
List<PersonModelView> people = getPersonModelViewsByAccountIdsMapper.execute(Collections
.singletonList(personAccountId));
if (people.size() > 0)
{
long followingUserId = people.get(0).getEntityId();
List<Long> ids = followerIdsMapper.execute(followingUserId);
if (ids.contains(userId))
{
return Follower.FollowerStatus.FOLLOWING;
}
}
return Follower.FollowerStatus.NOTFOLLOWING;
}
}