/* * 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.persistence.mappers.db; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; import org.apache.commons.logging.Log; import org.eurekastreams.commons.logging.LogFactory; import org.eurekastreams.server.domain.EntityType; import org.eurekastreams.server.domain.stream.Activity; import org.eurekastreams.server.persistence.mappers.BaseArgDomainMapper; import org.eurekastreams.server.persistence.mappers.DomainMapper; import org.eurekastreams.server.persistence.mappers.cache.CacheKeys; /** * This mapper finds all cache keys that could contain a reference to one of the activities passed as input. Lists of * starred activities are not included, nor are the streams that the activities were posted to . * * NOTE: This is probably incomplete. This is used for deleting activities. Rather than maintain these lists, we're * looking into ignoring deleted activity ids in lists and removing those ids as they're found. */ public class GetListsContainingActivities extends BaseArgDomainMapper<List<Long>, List<String>> { /** * Local instance of logger. */ private final Log logger = LogFactory.make(); /** * mapper to get all parent org ids for an org id. */ private DomainMapper<Long, List<Long>> parentOrgIdsMapper; /** * Mapper to get the short names from org ids. */ private final GetOrgShortNamesByIdsMapper orgShortNamesFromIdsMapper; /** * Constructor. * * @param inParentOrgIdsMapper * parent org mapper * @param inOrgShortNamesFromIdsMapper * org short names from ids mapper */ public GetListsContainingActivities(final DomainMapper<Long, List<Long>> inParentOrgIdsMapper, final GetOrgShortNamesByIdsMapper inOrgShortNamesFromIdsMapper) { parentOrgIdsMapper = inParentOrgIdsMapper; orgShortNamesFromIdsMapper = inOrgShortNamesFromIdsMapper; } /** * Execute database queries to find which cached lists of activity ids could contain a reference to a given list of * activity ids. * * @param activityIds * the list of activity ids. * @return the list of cache keys that could contain a reference to the input activities. */ @SuppressWarnings("unchecked") public List<String> execute(final List<Long> activityIds) { Set<String> lists = new HashSet<String>(); Set<String> authorAccountIds = new HashSet<String>(); Set<Long> parentOrgIds = new HashSet<Long>(); if (logger.isTraceEnabled()) { logger.trace("Retrieve the activities for the supplied activity ids: " + activityIds.size()); } List<Activity> activities = getHibernateSession().createQuery("from Activity where id in (:activityIds)") .setParameterList("activityIds", activityIds).list(); if (logger.isTraceEnabled()) { logger.trace("Loop through the retrieved activities " + activities.size() + " to build the list of stream scopes and the authorAccountIds."); } for (Activity activity : activities) { // Add the destination streamscope to the list of streamscopes that need // to have their corresponding streamviews looked up for. lists.add(CacheKeys.ENTITY_STREAM_BY_SCOPE_ID + activity.getRecipientStreamScope().getId()); // gets the author account ids for later use // Actors don't always have to be people, but we want the people here // so that their followers can be looked up and their following streams // can be updated. if (activity.getActorType() == EntityType.PERSON) { authorAccountIds.add(activity.getActorId()); } parentOrgIds.add(activity.getRecipientParentOrg().getId()); } // add all the org streams List<String> parentOrgShortNames = getAllParentOrgShortNames(parentOrgIds); for (String orgShortName : parentOrgShortNames) { logger.trace("Found org containing one of our activities: " + orgShortName); lists.add(CacheKeys.ACTIVITY_IDS_FOR_ORG_BY_SHORTNAME_RECURSIVE + orgShortName.toLowerCase()); } if (logger.isTraceEnabled()) { logger.trace("Retrieve the CompositeStreamViews that contain the streamscopes: " + activities.size() + " for the activities to be deleted."); } if (logger.isTraceEnabled()) { logger.trace("Retrieve the follower ids of the authors: " + authorAccountIds.size() + " of the activities to be deleted: "); } // following lists for everyone following the authors of the expired activities. List<Long> followerIds = getHibernateSession().createQuery( "select f.pk.followerId from Follower f where f.pk.followingId in " + "(select id from Person p where p.accountId in (:authorIds))").setParameterList("authorIds", authorAccountIds).list(); if (logger.isTraceEnabled()) { logger.trace("Retrieved follower ids " + followerIds.size() + " of the authors of the activities to be deleted: "); } for (long followerId : followerIds) { lists.add(CacheKeys.ACTIVITIES_BY_FOLLOWING + followerId); } lists.add(CacheKeys.EVERYONE_ACTIVITY_IDS); if (logger.isTraceEnabled()) { logger.trace("Retrieve all lists containing the supplied activities count: " + lists.size() + " keys: " + lists); } return new ArrayList(lists); } /** * Returns all parent org short names up the tree. * * @param inOrgIds * The id of the org. * @return all parent org ids up the tree */ private List<String> getAllParentOrgShortNames(final Set<Long> inOrgIds) { Set<Long> parentIds = new HashSet<Long>(); for (Long orgId : inOrgIds) { if (!parentIds.contains(orgId)) { logger.trace("Looking for parent orgs of " + orgId); parentIds.addAll(parentOrgIdsMapper.execute(orgId)); } // now add the looped org id - we have all orgs up the tree for this one, so don't look for it again parentIds.add(orgId); } return orgShortNamesFromIdsMapper.execute(new ArrayList<Long>(parentIds)); } }