package org.jboss.seam.wiki.plugin.forum;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.annotations.In;
import org.jboss.seam.annotations.Scope;
import org.jboss.seam.wiki.core.model.*;
import org.jboss.seam.wiki.core.dao.WikiNodeDAO;
import org.jboss.seam.ScopeType;
import org.hibernate.Session;
import org.hibernate.transform.ResultTransformer;
import javax.persistence.EntityManager;
import java.util.*;
import java.io.Serializable;
@Name("forumDAO")
@Scope(ScopeType.CONVERSATION)
public class ForumDAO implements Serializable {
@In
EntityManager entityManager;
@In
EntityManager restrictedEntityManager;
@In
WikiNodeDAO wikiNodeDAO;
@In
Integer currentAccessLevel;
public List<WikiDirectory> findForumDirectories() {
return getSession(true).getNamedQuery("forumDirectories")
.setComment("Finding forum directories")
.list();
}
public Long findForumPostingsCount(List<WikiDirectory> forumDirectories, User user) {
if (forumDirectories == null || forumDirectories.size() == 0) {
return 0l;
} else {
return (Long) getSession(true).getNamedQuery("forumTopicsForUserCount")
.setParameterList("parentDirectories", forumDirectories)
.setParameter("user", user)
.setComment("Finding forum topcis count for user: " + user)
.uniqueResult();
}
}
public List<TopicInfo> findForumPostings(List<WikiDirectory> forumDirectories, User user, int firstResult, int maxResults) {
final Map<Long, TopicInfo> topicInfoMap = new LinkedHashMap();
if (forumDirectories == null || forumDirectories.size() == 0) {
return Collections.EMPTY_LIST;
}
getSession(true).getNamedQuery("forumTopicsForUser")
.setParameterList("parentDirectories", forumDirectories)
.setParameter("user", user)
.setComment("Finding forum topcis for user: " + user)
.setResultTransformer(
new ResultTransformer() {
public Object transformTuple(Object[] result, String[] strings) {
WikiDocument doc = (WikiDocument) result[0];
topicInfoMap.put(
doc.getId(),
new TopicInfo(doc)
);
return null;
}
public List transformList(List list) { return list; }
}
)
.setFirstResult(firstResult)
.setMaxResults(maxResults)
.list();
if (topicInfoMap.size() > 0) {
getSession(true).getNamedQuery("forumTopicsReplies")
.setParameterList("topicIds", topicInfoMap.keySet())
.setComment("Retrieving forum topic replies")
.setResultTransformer(
new ResultTransformer() {
public Object transformTuple(Object[] result, String[] strings) {
if (topicInfoMap.containsKey((Long)result[1])) {
TopicInfo info = topicInfoMap.get( (Long)result[1] );
info.setNumOfReplies((Long)result[2]);
info.setLastComment((WikiComment)result[0]);
}
return null;
}
public List transformList(List list) { return list; }
}
)
.list();
}
return new ArrayList(topicInfoMap.values());
}
public List<WikiMenuItem> findForumsMenuItems(WikiDirectory forumsDirectory) {
return getSession(true).getNamedQuery("forumsMenuItems")
.setParameter("parentDir", forumsDirectory)
.list();
}
public boolean findForumsAvailability(WikiDirectory forumsDirectory) {
Long forumsCount = (Long)
getSession(true).getNamedQuery("forumsCount")
.setParameter("parentDir", forumsDirectory)
.setComment("Counting all forums")
.uniqueResult();
return forumsCount > 0l;
}
public Map<Long, ForumInfo> findForums(WikiDirectory forumsDirectory) {
final Map<Long, ForumInfo> forumInfoMap = new LinkedHashMap<Long, ForumInfo>();
getSession(true).getNamedQuery("forums")
.setParameter("parentDir", forumsDirectory)
.setComment("Finding all forums")
.setResultTransformer(
new ResultTransformer() {
public Object transformTuple(Object[] result, String[] strings) {
forumInfoMap.put(
(Long) result[0],
new ForumInfo( (WikiDirectory)result[1])
);
return null;
}
public List transformList(List list) { return list; }
}
)
.list();
// Find topic and replies count (topics are just wiki documents in the forum directories)
getSession(true).getNamedQuery("forumTopicReplyCount")
.setParameter("parentDirId", forumsDirectory.getId())
.setParameter("readAccessLevel", currentAccessLevel)
.setComment("Finding topic and replies count for all forums")
.setResultTransformer(
new ResultTransformer() {
public Object transformTuple(Object[] result, String[] strings) {
if (forumInfoMap.containsKey((Long)result[0])) {
ForumInfo info = forumInfoMap.get( (Long)result[0] );
info.setTotalNumOfTopics((Long)result[1]);
info.setTotalNumOfPosts(info.getTotalNumOfTopics());
if (result[2] != null) {
info.setTotalNumOfPosts(info.getTotalNumOfPosts() + (Long)result[2]);
}
}
return null;
}
public List transformList(List list) { return list; }
}
)
.list();
// Append last topic WikiDocument (faster if we do it with a MySQL specific LIMIT subselect)
List<Object[]> forumsAndLastTopics = getSession(true).getNamedQuery("forumLastTopic")
.setParameter("parentDirId", forumsDirectory.getId())
.setParameter("readAccessLevel", currentAccessLevel)
.setComment("Finding last topics for all forums")
.list();
for (Object[] lastTopicRow : forumsAndLastTopics) {
if (forumInfoMap.containsKey((Long)lastTopicRow[0])) {
WikiDocument lastTopic = wikiNodeDAO.findWikiDocument( (Long)lastTopicRow[1] );
forumInfoMap.get( (Long)lastTopicRow[0] ).setLastTopic( lastTopic );
}
}
// Append last reply WikiComment
for (final Long forumId : forumInfoMap.keySet()) {
getSession(true).getNamedQuery("forumLastReply")
.setParameter("parentDirId", forumId)
.setParameter("readAccessLevel", currentAccessLevel)
.setComment("Finding last replies for forum : " + forumId)
.setResultTransformer(
new ResultTransformer() {
public Object transformTuple(Object[] result, String[] strings) {
forumInfoMap.get(forumId).setLastComment( (WikiComment)result[0] );
return null;
}
public List transformList(List list) { return list; }
}
)
.list();
}
return forumInfoMap;
}
public Map<Long, Long> findUnreadTopicAndParentIds(WikiDirectory forumsDir, Date lastLoginDate) {
return findUnreadTopicAndParentIds("forumUnreadTopics", "forumUnreadReplies", forumsDir, lastLoginDate);
}
public Map<Long, Long> findUnreadTopicAndParentIdsInForum(WikiDirectory forum, Date lastLoginDate) {
return findUnreadTopicAndParentIds("forumUnreadTopicsInForum", "forumUnreadRepliesInForum", forum, lastLoginDate);
}
private Map<Long, Long> findUnreadTopicAndParentIds(String unreadTopicsQuery, String unreadRepliesQuery,
WikiDirectory directory, Date lastLoginDate) {
final Map<Long, Long> unreadTopics = new HashMap<Long, Long>();
getSession(true).getNamedQuery(unreadTopicsQuery)
.setParameter("parentDir", directory)
.setParameter("lastLoginDate", lastLoginDate)
.setComment("Finding unread topics")
.setCacheable(true)
.setResultTransformer(
new ResultTransformer() {
public Object transformTuple(Object[] objects, String[] strings) {
unreadTopics.put((Long)objects[0], (Long)objects[1]);
return null;
}
public List transformList(List list) { return list;}
}
)
.list();
getSession(true).getNamedQuery(unreadRepliesQuery)
.setParameter("parentDirId", directory.getId())
.setParameter("readAccessLevel", currentAccessLevel)
.setParameter("lastLoginDate", lastLoginDate)
.setComment("Finding unread replies")
.setCacheable(true)
.setResultTransformer(
new ResultTransformer() {
public Object transformTuple(Object[] objects, String[] strings) {
unreadTopics.put((Long)objects[0], (Long)objects[1]);
return null;
}
public List transformList(List list) { return list;}
}
)
.list();
return unreadTopics;
}
public Long findTopicCount(WikiDirectory forum) {
return (Long)getSession(true).getNamedQuery("forumTopicsCount")
.setParameter("parentDir", forum)
.setComment("Retrieving forum topics count")
.setCacheable(true)
.uniqueResult();
}
public Map<Long, TopicInfo> findTopics(WikiDirectory forum, long firstResult, long maxResults) {
// Limited list of topics, first retrieve identifiers only (faster on ORDER BY/LIMIT) then
// batch select the topic instances, then batch select the reply instances, we collect all
// of this stuff in this map:
final Map<Long, TopicInfo> topicInfoMap = new LinkedHashMap<Long, TopicInfo>();
// Retrieve topic identifier, sticky? and hasReplies? data
getSession(true).getNamedQuery("forumTopicsList")
.setParameter("parentNodeId", forum.getId())
.setParameter("readAccessLevel", currentAccessLevel)
.setComment("Retrieving forum topics list")
.setFirstResult(new Long(firstResult).intValue())
.setMaxResults(new Long(maxResults).intValue())
.setResultTransformer(
new ResultTransformer() {
public Object transformTuple(Object[] result, String[] strings) {
Long topicId = (Long) result[0];
Integer sticky = (Integer)result[1];
Boolean hasReplies = (Boolean)result[2];
topicInfoMap.put(topicId, new TopicInfo(sticky, hasReplies));
return null;
}
public List transformList(List list) { return list; }
}
)
.list();
if (topicInfoMap.keySet().size() == 0) return topicInfoMap; // Early exit possible
// Retrieve the topic entity instances and shove them into the map
getSession(true).getNamedQuery("forumTopics")
.setParameterList("topicIds", topicInfoMap.keySet())
.setComment("Retrieving forum topic list instances")
.setResultTransformer(
new ResultTransformer() {
public Object transformTuple(Object[] result, String[] strings) {
WikiDocument topicInstance = (WikiDocument)result[0];
topicInfoMap.get(topicInstance.getId()).setTopic(topicInstance);
return null;
}
public List transformList(List list) { return list; }
}
)
.list();
// Figure out which and if we even should query the reply instances
List<Long> topicIdsWithReplies = new ArrayList<Long>();
for (Map.Entry<Long, TopicInfo> entry : topicInfoMap.entrySet()) {
if (entry.getValue().isReplies()) topicIdsWithReplies.add(entry.getKey());
}
if (topicIdsWithReplies.size() == 0) return topicInfoMap; // Early exit possible
getSession(true).getNamedQuery("forumTopicsReplies")
.setParameterList("topicIds", topicIdsWithReplies)
.setComment("Retrieving forum topic replies")
.setResultTransformer(
new ResultTransformer() {
public Object transformTuple(Object[] result, String[] strings) {
if (topicInfoMap.containsKey((Long)result[1])) {
TopicInfo info = topicInfoMap.get( (Long)result[1] );
info.setNumOfReplies((Long)result[2]);
info.setLastComment((WikiComment)result[0]);
}
return null;
}
public List transformList(List list) { return list; }
}
)
.list();
return topicInfoMap;
}
public List<User> findPostersAndRatingPoints(Long forumId, int maxResults, List<String> excludeRoles) {
if (excludeRoles.size() == 0) {
excludeRoles.add("guest"); // By default, don't show guests, query requires _some_ exclude
}
final List<User> postersAndRatingPoints = new ArrayList<User>();
getSession(true).getNamedQuery("forumPostersAndRatingPoints")
.setParameter("parentDirId", forumId)
.setParameterList("ignoreUserInRoles", excludeRoles )
.setMaxResults(maxResults)
.setComment("Retrieving forum posters and rating points")
.setCacheable(true)
.setResultTransformer(
new ResultTransformer() {
public Object transformTuple(Object[] result, String[] strings) {
((User)result[0]).setRatingPoints((Long)result[1]);
postersAndRatingPoints.add((User)result[0]);
return null;
}
public List transformList(List list) { return list; }
}
)
.list();
return postersAndRatingPoints;
}
private Session getSession(boolean restricted) {
if (restricted) {
return ((Session)((org.jboss.seam.persistence.EntityManagerProxy) restrictedEntityManager).getDelegate());
} else {
return ((Session)((org.jboss.seam.persistence.EntityManagerProxy) entityManager).getDelegate());
}
}
}