/*
* 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;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.apache.commons.logging.Log;
import org.eurekastreams.commons.actions.InlineExecutionStrategyExecutor;
import org.eurekastreams.commons.actions.TaskHandlerExecutionStrategy;
import org.eurekastreams.commons.actions.context.DefaultPrincipal;
import org.eurekastreams.commons.actions.context.Principal;
import org.eurekastreams.commons.actions.context.PrincipalActionContext;
import org.eurekastreams.commons.actions.context.TaskHandlerActionContext;
import org.eurekastreams.commons.exceptions.ValidationException;
import org.eurekastreams.commons.logging.LogFactory;
import org.eurekastreams.commons.server.UserActionRequest;
import org.eurekastreams.server.action.request.notification.CreateNotificationsRequest;
import org.eurekastreams.server.action.request.notification.CreateNotificationsRequest.RequestType;
import org.eurekastreams.server.action.request.notification.TargetEntityNotificationsRequest;
import org.eurekastreams.server.action.request.profile.SetFollowingStatusByGroupCreatorRequest;
import org.eurekastreams.server.domain.BackgroundItem;
import org.eurekastreams.server.domain.DomainGroup;
import org.eurekastreams.server.domain.Follower;
import org.eurekastreams.server.domain.Person;
import org.eurekastreams.server.domain.SystemSettings;
import org.eurekastreams.server.domain.stream.StreamScope;
import org.eurekastreams.server.domain.stream.StreamScope.ScopeType;
import org.eurekastreams.server.persistence.DomainGroupMapper;
import org.eurekastreams.server.persistence.PersonMapper;
import org.eurekastreams.server.persistence.mappers.DomainMapper;
import org.eurekastreams.server.persistence.mappers.requests.MapperRequest;
/**
* Group Creator.
*/
public class GroupCreator extends GroupPersister
{
/**
* Logger.
*/
private final Log log = LogFactory.make();
/**
* Key value for group shortName.
*/
private static final String SHORTNAME_KEY = "shortName";
/**
* Message for duplicate group short name.
*/
private static final String DUP_SHORTNAME_MSG = "Group short name already present in system.";
/**
* Strategy for adding group followers (coordinators are automatically added as followers/members).
*/
private final TaskHandlerExecutionStrategy followStrategy;
/**
* used to lookup person creating the group.
*/
private final PersonMapper personMapper;
/**
* Mapper to get all the system administrator ids.
*/
private final DomainMapper<Serializable, List<Long>> getSystemAdministratorIdsMapper;
/**
* Mapper to get system settings.
*/
private final DomainMapper<MapperRequest, SystemSettings> getSystemSettingsMapper;
/**
* Constructor.
*
* @param inGroupMapper
* The Group Mapper
* @param inPersonMapper
* used to lookup person creating the group.
* @param inGetSystemAdministratorIdsMapper
* mapper to get system administrator ids
* @param inFollowStrategy
* used to automatically add coordinators as group followers/members.
* @param inGetSystemSettingsMapper
* mapper to get the system settings
*/
public GroupCreator(final DomainGroupMapper inGroupMapper, final PersonMapper inPersonMapper,
final DomainMapper<Serializable, List<Long>> inGetSystemAdministratorIdsMapper,
final TaskHandlerExecutionStrategy inFollowStrategy,
final DomainMapper<MapperRequest, SystemSettings> inGetSystemSettingsMapper)
{
super(inGroupMapper);
personMapper = inPersonMapper;
followStrategy = inFollowStrategy;
getSystemAdministratorIdsMapper = inGetSystemAdministratorIdsMapper;
getSystemSettingsMapper = inGetSystemSettingsMapper;
}
/**
* Returns DomainGroup based on id passed in inFields.
*
* @param inActionContext
* The action context.
* @param inFields
* the property map.
* @return new group.
*/
@Override
public DomainGroup get(final TaskHandlerActionContext<PrincipalActionContext> inActionContext,
final Map<String, Serializable> inFields)
{
// create the group
DomainGroup group = new DomainGroup();
StreamScope groupScope = new StreamScope(ScopeType.GROUP, (String) inFields.get("shortName"));
group.setStreamScope(groupScope);
// set the capabilities as a new list to avoid search indexing problems
group.setCapabilities(new ArrayList<BackgroundItem>());
return group;
}
/**
* Persists new group object.
*
* @param inGroup
* The group.
* @param inFields
* the property map.
* @param inActionContext
* the action context
* @throws Exception
* on error
*/
@Override
public void persist(final TaskHandlerActionContext<PrincipalActionContext> inActionContext,
final Map<String, Serializable> inFields, final DomainGroup inGroup) throws Exception
{
final Principal principal = inActionContext.getActionContext().getPrincipal();
ValidationException ve = new ValidationException();
String creatorUserName = principal.getAccountId();
final Long creatorPersonId = principal.getId();
SystemSettings settings = getSystemSettingsMapper.execute(null);
// Verify that group with given short name doesn't already exist.
if (getGroupMapper().findByShortName(inGroup.getShortName()) != null)
{
ve.addError(SHORTNAME_KEY, DUP_SHORTNAME_MSG);
}
// Verify that group has on coordinator.
if (inGroup.getCoordinators().isEmpty())
{
ve.addError("coordinators", "Group must have at least one coordinator");
}
if (!ve.getErrors().isEmpty())
{
throw ve;
}
// if the system requires approval to create groups, set the pending state to true.
boolean isPending = true;
if (settings.getAllUsersCanCreateGroups()
|| getSystemAdministratorIdsMapper.execute(null).contains(creatorPersonId))
{
isPending = false;
}
inGroup.setPending(isPending);
// Set the current user to the createdby person.
inGroup.setCreatedBy(personMapper.findByAccountId(creatorUserName));
getGroupMapper().insert(inGroup);
// sets the destination entity id for the group's stream scope
inGroup.getStreamScope().setDestinationEntityId(inGroup.getId());
queueAsyncAction(inActionContext, inGroup, false);
// Make all coordinators follow/join the new group
for (Person coordinator : inGroup.getCoordinators())
{
SetFollowingStatusByGroupCreatorRequest currentRequest = new SetFollowingStatusByGroupCreatorRequest(
coordinator.getId(), inGroup.getId(), Follower.FollowerStatus.FOLLOWING, inGroup.getName(),
inGroup.getShortName(), isPending);
new InlineExecutionStrategyExecutor().execute(followStrategy, currentRequest, new DefaultPrincipal(
creatorUserName, principal.getOpenSocialId(), creatorPersonId), inActionContext
.getUserActionRequests());
}
// trigger notification if group will be pending approval
if (isPending)
{
inActionContext.getUserActionRequests().add(
new UserActionRequest(CreateNotificationsRequest.ACTION_NAME, null,
new TargetEntityNotificationsRequest(RequestType.REQUEST_NEW_GROUP, creatorPersonId,
inGroup.getId())));
}
}
}