/* * 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.HashSet; import java.util.Hashtable; import java.util.List; import java.util.Map; import java.util.Set; import org.eurekastreams.server.persistence.mappers.BaseArgDomainMapper; import org.eurekastreams.server.persistence.mappers.requests.BulkActivityDeleteResponse; /** * Given a group id, this mapper deletes all Activities and related objects (Comments and StarredActivities) from the * DB. */ public class DeleteGroupActivity extends BaseArgDomainMapper<Long, BulkActivityDeleteResponse> { /** * Deletes all Activities (and related objects) that were posted to specified group. * * @param inRequest * the group id. * @return {@link BulkActivityDeleteResponse} with info. needed to clean up cache and search index. * */ @Override public BulkActivityDeleteResponse execute(final Long inRequest) { // get groupDTO to fetch group stream id Long groupStreamId = getGroupStreamId(inRequest); if (groupStreamId == null) { // short-circut as group is no longer present. return new BulkActivityDeleteResponse(); } // get activity ids to return (cache and search index cleanup) List<Long> activityIds = getActivityIds(groupStreamId); // get comment ids to return (cache and search index cleanup) List<Long> commentIds = getCommentIds(groupStreamId); // get people with starred Activities map (cache clean up). Map<Long, Set<Long>> peopleWithStarredActivities = getPeopleWithStarredActivities(inRequest); // Why the following queries use sub-selects: // FROM HIBERNATE DOCS: No joins can be specified in a bulk HQL query. Sub-queries can be used in the // where-clause, // where the subqueries themselves may contain joins. getEntityManager().createQuery( "DELETE FROM Comment c WHERE c.target.id IN" + " (SELECT a.id FROM Activity a WHERE a.recipientStreamScope.id = :groupStreamId)")// \n .setParameter("groupStreamId", groupStreamId).executeUpdate(); // delete activity from currentUser's starred activity collections in DB. getEntityManager().createQuery( "DELETE FROM StarredActivity where activityId IN" + " (SELECT a.id FROM Activity a WHERE a.recipientStreamScope.id = :groupStreamId)")// \n .setParameter("groupStreamId", groupStreamId).executeUpdate(); // delete activity hashtags for this group stream if (!activityIds.isEmpty()) { getEntityManager().createQuery("DELETE FROM StreamHashTag where activityId IN (:activityIds)") .setParameter("activityIds", activityIds).executeUpdate(); } // delete the activities. getEntityManager().createQuery("DELETE FROM Activity a WHERE a.recipientStreamScope.id = :groupStreamId") .setParameter("groupStreamId", groupStreamId).executeUpdate(); return new BulkActivityDeleteResponse(activityIds, commentIds, peopleWithStarredActivities); } /** * Get the stream id for a group. * * @param groupId * Group id. * @return The stream id for a group. */ @SuppressWarnings("unchecked") private Long getGroupStreamId(final Long groupId) { List<Long> result = getEntityManager().createQuery( "SELECT g.streamScope.id FROM DomainGroup g WHERE g.id = :groupId").setParameter("groupId", groupId) .getResultList(); return result.size() == 0 ? null : result.get(0); } /** * Return activity ids for a group. This only returns the number of results based on max list size in cache, no need * to return more than that. * * @param groupStreamId * group stream id. * @return activity ids for a group. */ @SuppressWarnings("unchecked") private List<Long> getActivityIds(final Long groupStreamId) { return getEntityManager().createQuery( "SELECT a.id FROM Activity a WHERE a.recipientStreamScope.id = :groupStreamId ORDER BY a.id DESC") .setParameter("groupStreamId", groupStreamId).getResultList(); } /** * Return comment ids for all activities in a group. * * @param groupStreamId * group stream id. * @return Comment ids for all activities in a group. */ @SuppressWarnings("unchecked") private List<Long> getCommentIds(final Long groupStreamId) { return getEntityManager().createQuery( "SELECT c.id FROM Comment c, Activity a" + " WHERE a.recipientStreamScope.id = :groupStreamId AND c.target.id = a.id") // \n .setParameter("groupStreamId", groupStreamId).getResultList(); } /** * Return Map keyed by Person id that has set of activity ids that the person has starred that belong to the group * being deleted. * * @param groupStreamId * Group stream id. * @return Map keyed by Person id that has set of activity ids that the person has starred that belong to the group * being deleted. */ @SuppressWarnings("unchecked") private Map<Long, Set<Long>> getPeopleWithStarredActivities(final Long groupStreamId) { Hashtable<Long, Set<Long>> results = new Hashtable<Long, Set<Long>>(); List<Object[]> queryResults = getHibernateSession().createQuery( "SELECT sa.pk.personId, sa.pk.activityId from StarredActivity sa, Activity a" + " WHERE sa.pk.activityId = a.id AND a.recipientStreamScope.id = :groupStreamId") .setParameter("groupStreamId", groupStreamId).list(); Long personId; Long activityId; for (Object[] row : queryResults) { personId = (Long) row[0]; activityId = (Long) row[1]; if (results.containsKey(personId)) { results.get(personId).add(activityId); } else { HashSet<Long> set = new HashSet<Long>(); set.add(activityId); results.put(personId, set); } } return results; } }