/*
* Copyright (c) 2009 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.persistence.strategies;
import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.eurekastreams.server.domain.EntityType;
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.GetRecursiveOrgCoordinators;
import org.eurekastreams.server.persistence.mappers.stream.GetDomainGroupsByShortNames;
import org.eurekastreams.server.search.modelview.CommentDTO;
import org.eurekastreams.server.search.modelview.PersonModelView;
/**
* Strategy for setting Deletable property on comments for a given activity and user.
*
*/
public class CommentDeletePropertyStrategy
{
/** logger instance. */
private static Log log = LogFactory.getLog(CommentDeletePropertyStrategy.class);
/**
* Mapper to get a PersonModelView by account id.
*/
private DomainMapper<String, PersonModelView> getPersonModelViewByAccountIdMapper;
/**
* Mapper to get a person's id by their account id.
*/
private DomainMapper<String, Long> getPersonIdByAccountIdMapper;
/**
* DAO for looking up group by short name.
*/
private GetDomainGroupsByShortNames groupByShortNameDAO;
/**
* Mapper to check if the user has coordinator access to a group.
*/
private GetAllPersonIdsWhoHaveGroupCoordinatorAccess groupAccessMapper;
/**
* Mapper to get all coordinators of an org.
*/
private GetRecursiveOrgCoordinators orgCoordinatorDAO;
/**
* Constructor.
*
* @param inGetPersonModelViewByAccountIdMapper
* Mapper to get a PersonModelView by account id.
* @param inGetPersonIdByAccountIdMapper
* Mapper to get a person's id by their account id.
* @param inGroupByShortNameDAO
* DAO for looking up group by short name.
* @param inGroupAccessMapper
* Mapper to check if the user has coordinator access to a group.
* @param inOrgCoordinatorDAO
* Mapper for determining org coordinators.
*/
public CommentDeletePropertyStrategy(
final DomainMapper<String, PersonModelView> inGetPersonModelViewByAccountIdMapper,
final DomainMapper<String, Long> inGetPersonIdByAccountIdMapper,
final GetDomainGroupsByShortNames inGroupByShortNameDAO,
final GetAllPersonIdsWhoHaveGroupCoordinatorAccess inGroupAccessMapper,
final GetRecursiveOrgCoordinators inOrgCoordinatorDAO)
{
getPersonModelViewByAccountIdMapper = inGetPersonModelViewByAccountIdMapper;
getPersonIdByAccountIdMapper = inGetPersonIdByAccountIdMapper;
groupByShortNameDAO = inGroupByShortNameDAO;
groupAccessMapper = inGroupAccessMapper;
orgCoordinatorDAO = inOrgCoordinatorDAO;
}
/**
* Sets Deletable property on comments for a given activity and user.
*
* @param inUserAccountId
* The current user's account id.
* @param inParentActivity
* The parent activity of the comments.
* @param inComments
* The list of comments to set property on.
*/
public void execute(final String inUserAccountId, final ActivityDTO inParentActivity,
final List<CommentDTO> inComments)
{
// short-circuit right if no userAccountId is provided.
if (inUserAccountId == null)
{
setAll(inComments, false);
return;
}
// Set all comments deletable if you can delete the current comment.
if (inParentActivity.isDeletable())
{
setAll(inComments, true);
return;
}
// TODO This should be refactored to take advantage of ActivityDeletePropertyStrategy
// as the activity based logic is currently duplicated. Both should probably be refactored
// to use activity permission based decorators to determine setting for max flexibility.
// if comment is on person's stream and current user is that person,
// then allow
if (inParentActivity.getDestinationStream().getType() == EntityType.PERSON
&& inUserAccountId.equalsIgnoreCase(inParentActivity.getDestinationStream().getUniqueIdentifier()))
{
setAll(inComments, true);
return;
}
// need user's person id
Long userPersonId = getUserPersonIdByAccountId(inUserAccountId);
// if comment is on group stream, and current user is group coordinator,
// then allow
if (inParentActivity.getDestinationStream().getType() == EntityType.GROUP
&& isCurrentUserCoordinator(userPersonId, //
inParentActivity.getDestinationStream().getUniqueIdentifier()))
{
setAll(inComments, true);
return;
}
// if activity is on personal stream, and current user is org coordinator of personal
// stream's parent org (or up tree recursively), allow delete.
if (inParentActivity.getDestinationStream().getType() == EntityType.PERSON
&& orgCoordinatorDAO.isOrgCoordinatorRecursively(userPersonId, getPersonModelViewByAccountIdMapper
.execute(inParentActivity.getDestinationStream().getUniqueIdentifier())
.getParentOrganizationId()))
{
setAll(inComments, true);
return;
}
// No bulk settings apply. If user is author of comment, allow delete
for (CommentDTO comment : inComments)
{
// if user is author of comment they can delete.
comment.setDeletable(comment.getAuthorId() == userPersonId);
}
}
/**
* Set deletable property to true on all comments.
*
* @param inComments
* The comments to set.
* @param inValueToSet
* the value to set on all comments.
*/
private void setAll(final List<CommentDTO> inComments, final boolean inValueToSet)
{
for (CommentDTO comment : inComments)
{
comment.setDeletable(inValueToSet);
}
}
/**
* Return true if user is coordinator of group activity is posted to, or authority to act as group coordinator.
*
* @param inUserPersonId
* The current user's person id
* @param inGroupShortName
* Short name of the group.
* @return True if user is coordinator of group activity is posted to, or authority to act as group coordinator,
* false otherwise.
*/
private boolean isCurrentUserCoordinator(final Long inUserPersonId, final String inGroupShortName)
{
Long groupId = groupByShortNameDAO.fetchId(inGroupShortName);
if (groupId == null)
{
String msg = "Unable to locate group with shortName: " + inGroupShortName;
log.error(msg);
throw new RuntimeException(msg);
}
return groupAccessMapper.hasGroupCoordinatorAccessRecursively(inUserPersonId, groupId);
}
/**
* Returns user's person id.
*
* @param inCurrentUserAccountId
* Account id.
* @return user's person id
*/
private Long getUserPersonIdByAccountId(final String inCurrentUserAccountId)
{
Long personId = getPersonIdByAccountIdMapper.execute(inCurrentUserAccountId);
if (personId == null)
{
String msg = "Unable to locate user with account id: " + inCurrentUserAccountId;
log.error(msg);
throw new RuntimeException(msg);
}
return personId;
}
}