/*
* Copyright (c) 2009-2011 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.service.actions.strategies.activity;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;
import org.eurekastreams.server.domain.stream.ActivityDTO;
import org.eurekastreams.server.persistence.mappers.DomainMapper;
import org.eurekastreams.server.persistence.mappers.GetAllPersonIdsWhoHaveGroupCoordinatorAccess;
import org.eurekastreams.server.persistence.mappers.stream.GetDomainGroupsByShortNames;
import org.eurekastreams.server.search.modelview.DomainGroupModelView;
import org.eurekastreams.server.search.modelview.PersonModelView;
/**
* A filter to set the can comment bit to an activityDTO.
*/
public class CanCommentFilter implements ActivityFilter
{
/**
* Mapper to get PersonModelViews by account ids.
*/
private final DomainMapper<List<String>, List<PersonModelView>> getPersonModelViewsByAccountIdsMapper;
/**
* DomainGroup model view mapper.
*/
private final GetDomainGroupsByShortNames groupMapper;
/**
* Mapper to get all Coordinators of a Group.
*/
private final GetAllPersonIdsWhoHaveGroupCoordinatorAccess groupCoordinators;
/**
* Constructor.
*
* @param inGetPersonModelViewsByAccountIdsMapper
* Mapper to get PersonModelViews by account ids
* @param inGroupMapper
* A group Mapper to get if a group has restricted access.
* @param inGroupCoordinators
* The groupCoordinatormapper used to get coordinators.
*/
public CanCommentFilter(
final DomainMapper<List<String>, List<PersonModelView>> inGetPersonModelViewsByAccountIdsMapper,
final GetDomainGroupsByShortNames inGroupMapper,
final GetAllPersonIdsWhoHaveGroupCoordinatorAccess inGroupCoordinators)
{
getPersonModelViewsByAccountIdsMapper = inGetPersonModelViewsByAccountIdsMapper;
groupMapper = inGroupMapper;
groupCoordinators = inGroupCoordinators;
}
/**
* apply the filter.
*
* @param activities
* The list of activities to filter.
* @param inCurrentUserAccountId
* The currently logged in user's account id.
*/
@Override
public void filter(final List<ActivityDTO> activities, final PersonModelView inCurrentUserAccountId)
{
// short-circuit if no work to do.
if (activities.isEmpty())
{
return;
}
// collect destination stream ids in hashtables (by type) to eliminate duplication
Hashtable<String, Boolean> personCommentable = new Hashtable<String, Boolean>();
Hashtable<String, Boolean> groupCommentable = new Hashtable<String, Boolean>();
for (ActivityDTO activity : activities)
{
switch (activity.getDestinationStream().getType())
{
case PERSON:
personCommentable.put(activity.getDestinationStream().getUniqueIdentifier().trim().toLowerCase(),
Boolean.TRUE);
break;
case GROUP:
groupCommentable.put(activity.getDestinationStream().getUniqueIdentifier().trim().toLowerCase(),
Boolean.TRUE);
break;
case RESOURCE:
break;
default:
throw new IllegalArgumentException(
"Attempted to filter Activity with unsupported destination stream type.");
}
}
// do work of determining if destination streams are commentable.
setPersonCommentableValues(inCurrentUserAccountId.getAccountId(), personCommentable);
setGroupCommentableValues(inCurrentUserAccountId.getAccountId(), groupCommentable);
// loop through activities and set the appropriate values.
for (ActivityDTO activity : activities)
{
switch (activity.getDestinationStream().getType())
{
case PERSON:
activity.setCommentable(personCommentable.get(activity.getDestinationStream().getUniqueIdentifier()
.trim().toLowerCase()));
break;
case GROUP:
activity.setCommentable(groupCommentable.get(activity.getDestinationStream().getUniqueIdentifier()
.trim().toLowerCase()));
break;
case RESOURCE:
activity.setCommentable(true);
break;
default:
throw new IllegalArgumentException(
"Attempted to filter Activity with unsupported destination stream type.");
}
}
}
/**
* Determine if current user is allowed to comment on activites with person destinations.
*
* @param inCurrentUserAccountId
* Current user's account Id.
* @param inPersonCommentable
* Hashtable of person account Ids to set value for.
*/
private void setPersonCommentableValues(final String inCurrentUserAccountId,
final Hashtable<String, Boolean> inPersonCommentable)
{
// short-circuit here if no work to be done.
if (inPersonCommentable.size() == 0)
{
return;
}
// grab all people associated with activity destination streams in one shot.
List<PersonModelView> destinations = getPersonModelViewsByAccountIdsMapper.execute(new ArrayList(
inPersonCommentable.keySet()));
// loop through them and set commentable appropriately
for (PersonModelView destination : destinations)
{
inPersonCommentable.put(destination.getAccountId().trim().toLowerCase(),
(destination.isCommentable() || (inCurrentUserAccountId != null && destination.getAccountId()
.trim().equalsIgnoreCase(inCurrentUserAccountId))));
}
}
/**
* Determine if current user is allowed to comment on activites with group destinations.
*
* @param inCurrentUserAccountId
* Current user's account Id.
* @param inGroupCommentable
* Hashtable of group shortnames to set value for.
*/
private void setGroupCommentableValues(final String inCurrentUserAccountId,
final Hashtable<String, Boolean> inGroupCommentable)
{
// short-circuit here if no work to be done.
if (inGroupCommentable.size() == 0)
{
return;
}
// grab all groups associated with activity destination streams in one shot.
List<DomainGroupModelView> destinations = groupMapper.execute(new ArrayList(inGroupCommentable.keySet()));
// Create cache for current user's group coordinator status to attempt to minimize calls to
// hasGroupCoordinatorAccessRecursively
Hashtable<String, Boolean> currentUserCoordinatorCache = new Hashtable<String, Boolean>();
// loop through groups and set commentable appropriately
for (DomainGroupModelView destination : destinations)
{
boolean canComment = destination.isCommentable();
// if group not commentable, see if current user is coordinator and can override setting.
if (!canComment)
{
// check cache to see if we've determined this before.
Boolean isCoordinator = currentUserCoordinatorCache
.get(destination.getShortName().trim().toLowerCase());
if (isCoordinator == null && inCurrentUserAccountId != null)
{
// not cached, have to figure it out
isCoordinator = groupCoordinators.hasGroupCoordinatorAccessRecursively(inCurrentUserAccountId,
destination.getEntityId());
// cache it
currentUserCoordinatorCache.put(destination.getShortName().trim().toLowerCase(), isCoordinator);
}
canComment = isCoordinator == null ? Boolean.FALSE : isCoordinator;
}
inGroupCommentable.put(destination.getShortName().trim().toLowerCase(), canComment);
}
}
}