/*
* 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.stream;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.logging.Log;
import org.eurekastreams.commons.logging.LogFactory;
import org.eurekastreams.server.domain.strategies.HashTagExtractor;
import org.eurekastreams.server.domain.stream.Activity;
import org.eurekastreams.server.domain.stream.HashTag;
import org.eurekastreams.server.domain.stream.StreamHashTag;
import org.eurekastreams.server.domain.stream.StreamScope.ScopeType;
import org.eurekastreams.server.persistence.mappers.DomainMapper;
import org.eurekastreams.server.persistence.mappers.InsertMapper;
import org.eurekastreams.server.persistence.mappers.chained.DecoratedPartialResponseDomainMapper;
import org.eurekastreams.server.persistence.mappers.requests.PersistenceRequest;
import org.eurekastreams.server.persistence.mappers.stream.ActivityContentExtractor;
import org.eurekastreams.server.search.modelview.OrganizationModelView;
/**
* Parse an Activity's content, find any hashtags, then store the hashtags in each stream that the activity falls under,
* including the person or group destination stream, as well as all orgs up the hierarchy, if the activity is public.
*/
public class StoreStreamHashTagsForActivityStrategyImpl implements StoreStreamHashTagsForActivityStrategy
{
/**
* Logger.
*/
private Log log = LogFactory.make();
/**
* Hashtag extractor.
*/
private final HashTagExtractor hashTagExtractor;
/**
* Content extractor - pulls out content for hashtag parsing.
*/
private final ActivityContentExtractor contentExtractor;
/**
* Mapper to store hash tags to an activity.
*/
private final DecoratedPartialResponseDomainMapper<List<String>, List<HashTag>> hashTagMapper;
/**
* Mapper to insert stream hashtags.
*/
private final InsertMapper<StreamHashTag> streamHashTagInsertMapper;
/**
* mapper to get all parent org ids for an org id.
*/
private DomainMapper<Long, List<Long>> getRecursiveParentOrgIds;
/**
* Get organizations by ids mapper.
*/
private final DomainMapper<List<Long>, List<OrganizationModelView>> organizationsByIdsMapper;
/**
* Constructor for the PostActivityAsyncExecutionStrategy class.
*
* @param inContentExtractor
* the activity content extractor
* @param inHashTagExtractor
* hash tag extractor
* @param inHashTagMapper
* mapper to get hashtags from the database
* @param inStreamHashTagInsertMapper
* mapper to insert stream hashtags
* @param inGetRecursiveParentOrgIds
* mapper to get all org ids up a parent tree
* @param inOrganizationsByIdsMapper
* mapper to get organization modelviews from ids
*/
public StoreStreamHashTagsForActivityStrategyImpl(final HashTagExtractor inHashTagExtractor,
final ActivityContentExtractor inContentExtractor,
final DecoratedPartialResponseDomainMapper<List<String>, List<HashTag>> inHashTagMapper,
final InsertMapper<StreamHashTag> inStreamHashTagInsertMapper,
final DomainMapper<Long, List<Long>> inGetRecursiveParentOrgIds,
final DomainMapper<List<Long>, List<OrganizationModelView>> inOrganizationsByIdsMapper)
{
hashTagExtractor = inHashTagExtractor;
contentExtractor = inContentExtractor;
hashTagMapper = inHashTagMapper;
streamHashTagInsertMapper = inStreamHashTagInsertMapper;
getRecursiveParentOrgIds = inGetRecursiveParentOrgIds;
organizationsByIdsMapper = inOrganizationsByIdsMapper;
}
/**
* Parse and insert any necessary StreamHashTags for the input activity.
*
* @param inActivity
* the activity to parse for stream hashtags
*/
public void execute(final Activity inActivity)
{
log.info("Finding hashtags for activity #" + inActivity.getId());
ScopeType scopeType = inActivity.getRecipientStreamScope().getScopeType();
if (scopeType != ScopeType.GROUP && scopeType != ScopeType.PERSON)
{
log.info("This activity isn't a group or person stream - not handled.");
return;
}
String recipientStreamKey = inActivity.getRecipientStreamScope().getUniqueKey();
List<String> orgHierarchyShortNames = null;
// create stream hashtag entries for each of the tags being applied
StreamHashTag streamHashTag;
List<String> hashTagStrings = getHashTags(inActivity);
if (hashTagStrings.size() == 0)
{
return;
}
for (HashTag hashTag : hashTagMapper.execute(hashTagStrings))
{
// insert the activity hashtag for the destination stream
if (log.isDebugEnabled())
{
log.debug("Adding StreamHashTag " + hashTag.getContent() + " for direct recipient stream of type "
+ scopeType + ", key: " + recipientStreamKey + ", activity id: #" + inActivity.getId());
}
streamHashTag = new StreamHashTag(hashTag, inActivity, recipientStreamKey, scopeType);
streamHashTagInsertMapper.execute(new PersistenceRequest<StreamHashTag>(streamHashTag));
if (inActivity.getIsDestinationStreamPublic())
{
// for public streams, bubble the hashtag up the org tree
if (orgHierarchyShortNames == null)
{
orgHierarchyShortNames = getAllOrgShortNamesInHierarchy(inActivity.getRecipientParentOrg().getId());
}
for (String orgShortName : orgHierarchyShortNames)
{
if (log.isDebugEnabled())
{
log.debug("Adding StreamHashTag " + hashTag.getContent() + " for public " + scopeType
+ " stream's parent org tree, organization " + orgShortName + ", activity id: #"
+ inActivity.getId());
}
streamHashTag = new StreamHashTag(hashTag, inActivity, orgShortName, ScopeType.ORGANIZATION);
streamHashTagInsertMapper.execute(new PersistenceRequest<StreamHashTag>(streamHashTag));
}
}
}
}
/**
* Get a set of all of the hashtags for a the input activity, based on its content.
*
* @param inActivity
* the activity to look for hashtags for
* @return the collection of hashtags
*/
private List<String> getHashTags(final Activity inActivity)
{
String content = contentExtractor.extractContent(inActivity.getBaseObjectType(), inActivity.getBaseObject());
return hashTagExtractor.extractAll(content);
}
/**
* Get all of the short names of all organizations up the hierarchy from and including the input org id.
*
* @param orgId
* the org id to start with (and include in the results)
* @return all of the short names of all organizations up the hierarchy from and including the input org id
*/
private List<String> getAllOrgShortNamesInHierarchy(final Long orgId)
{
List<String> shortNames = new ArrayList<String>();
List<Long> parentOrgIds = getRecursiveParentOrgIds.execute(orgId);
parentOrgIds.add(orgId);
if (log.isTraceEnabled())
{
log.trace("Fetching organization modelviews for all of the parent orgs of activity with parent org id "
+ parentOrgIds.toString());
}
for (OrganizationModelView org : organizationsByIdsMapper.execute(parentOrgIds))
{
shortNames.add(org.getShortName());
}
if (log.isTraceEnabled())
{
log.trace("Found org short names: " + shortNames.toString());
}
return shortNames;
}
}