package org.jboss.seam.wiki.plugin.forum;
import org.jboss.seam.Component;
import org.jboss.seam.ScopeType;
import org.jboss.seam.annotations.*;
import org.jboss.seam.annotations.Observer;
import org.jboss.seam.annotations.web.RequestParameter;
import org.jboss.seam.contexts.Contexts;
import org.jboss.seam.log.Log;
import org.jboss.seam.wiki.core.action.Pager;
import org.jboss.seam.wiki.core.wikitext.engine.WikiLink;
import org.jboss.seam.wiki.core.wikitext.engine.WikiLinkResolver;
import org.jboss.seam.wiki.core.model.User;
import org.jboss.seam.wiki.core.model.WikiDirectory;
import org.jboss.seam.wiki.core.plugin.WikiPluginMacro;
import org.jboss.seam.wiki.preferences.Preferences;
import java.io.Serializable;
import java.util.*;
@Name("forumQuery")
@Scope(ScopeType.CONVERSATION)
public class ForumQuery implements Serializable {
public static final String TOPIC_PAGE = "topicPage";
@Logger
Log log;
private Pager pager;
@In("#{preferences.get('Forum')}")
ForumPreferences forumPrefs;
@RequestParameter
public void setPage(Integer page) {
if (pager == null) pager = new Pager(forumPrefs.getTopicsPerPage());
pager.setPage(page);
Contexts.getSessionContext().set(TOPIC_PAGE, page);
}
public Pager getPager() {
return pager;
}
@In
WikiDirectory currentDirectory;
@In
User currentUser;
@In
int currentAccessLevel;
@In(create = true)
ForumDAO forumDAO;
/* ####################### FORUMS ########################## */
Boolean forumsAvailable;
public boolean isForumsAvailable() {
if (forumsAvailable == null) loadForumsAvailability();
return forumsAvailable;
}
@Observer(value = {"Forum.forumListRefresh"}, create = false)
public void loadForumsAvailability() {
// The whole point of this is so that we can use it as a cheaper query in the mess that is the rendered="true/false"
// attribute evaluation in JSF. It is called completely randomly, at any phase in the request, on any component in
// the tree. It needs to be a) as cheap as possible and b) free from dependencies.
forumsAvailable = forumDAO.findForumsAvailability(currentDirectory);
}
List<ForumInfo> forums;
public List<ForumInfo> getForums() {
if (forums == null) loadForums();
return forums;
}
@Observer(value = {"Forum.forumListRefresh"}, create = false)
public void loadForums() {
log.debug("loading forums");
Map<Long, ForumInfo> forumInfo = forumDAO.findForums(currentDirectory);
// Find unread postings
if (!currentUser.isAdmin() && !currentUser.isGuest()) {
log.debug("finding unread topics since: " + currentUser.getPreviousLastLoginOn());
Map<Long,Long> unreadTopicsWithParent =
forumDAO.findUnreadTopicAndParentIds(currentDirectory, currentUser.getPreviousLastLoginOn());
ForumTopicReadManager forumTopicReadManager = (ForumTopicReadManager)Component.getInstance(ForumTopicReadManager.class);
for (Map.Entry<Long, Long> unreadTopicAndParent: unreadTopicsWithParent.entrySet()) {
if (forumInfo.containsKey(unreadTopicAndParent.getValue()) &&
!forumTopicReadManager.isTopicIdRead(unreadTopicAndParent.getValue(), unreadTopicAndParent.getKey()) ) {
forumInfo.get(unreadTopicAndParent.getValue()).setUnreadPostings(true);
}
}
}
forums = new ArrayList<ForumInfo>();
forums.addAll(forumInfo.values());
}
/* ####################### TOPICS ########################## */
private Long numOfTopics;
private List<TopicInfo> topics;
public boolean isTopicsAvailable() {
if (numOfTopics == null) countTopics();
return numOfTopics > 0;
}
public List<TopicInfo> getTopics() {
if (isTopicsAvailable() && topics == null) {
loadTopics();
} else if (!isTopicsAvailable()) {
topics = Collections.emptyList();
}
return topics;
}
public void countTopics() {
log.debug("counting forum topics");
numOfTopics = forumDAO.findTopicCount(currentDirectory);
pager.setNumOfRecords(numOfTopics);
}
public void loadTopics() {
log.debug("loading forum topics");
Map<Long, TopicInfo> topicInfo = forumDAO.findTopics(currentDirectory, pager.getNextRecord(), pager.getPageSize());
if (!currentUser.isAdmin() && !currentUser.isGuest()) {
log.debug("finding unread topics since: " + currentUser.getPreviousLastLoginOn());
Map<Long,Long> unreadTopicsWithParent =
forumDAO.findUnreadTopicAndParentIdsInForum(currentDirectory, currentUser.getPreviousLastLoginOn());
ForumTopicReadManager forumTopicReadManager = (ForumTopicReadManager)Component.getInstance(ForumTopicReadManager.class);
for (Map.Entry<Long, TopicInfo> topicInfoEntry: topicInfo.entrySet()) {
topicInfoEntry.getValue().setUnread(
unreadTopicsWithParent.containsKey(topicInfoEntry.getKey()) &&
!forumTopicReadManager.isTopicIdRead(
unreadTopicsWithParent.get(topicInfoEntry.getKey()),
topicInfoEntry.getKey()
)
);
}
}
topics = new ArrayList<TopicInfo>();
topics.addAll(topicInfo.values());
}
@Observer(value = {"Forum.topicListRefresh"}, create = false)
public void refreshTopics() {
countTopics();
loadTopics();
}
/* ####################### POSTERS ########################## */
public static final String MACRO_ATTR_TOPPOSTERS = "forumTopPostersList";
public List<User> getTopPosters(WikiPluginMacro macro) {
ForumTopPostersPreferences forumTopPostersPrefs =
Preferences.instance().get(ForumTopPostersPreferences.class, macro);
// Cache the list in the macro, this getter is called a thousand times during datatable rendering
List<User> forumTopPosters =
(List<User>)macro.getAttributes().get(MACRO_ATTR_TOPPOSTERS + forumTopPostersPrefs.getForumLink());
if (forumTopPosters == null) {
Long forumId = resolveForumId(forumTopPostersPrefs.getForumLink());
if (forumId == null) {
log.debug("could not resolve forum id for forum start page link: " + forumTopPostersPrefs.getForumLink());
return null;
}
List<String> excludeRoles = new ArrayList<String>();
if (forumTopPostersPrefs.getExcludeRoles() != null &&
forumTopPostersPrefs.getExcludeRoles().length() > 0) {
log.debug("excluding posters with roles: " + forumTopPostersPrefs.getExcludeRoles());
excludeRoles = Arrays.asList(forumTopPostersPrefs.getExcludeRoles().split(" "));
}
log.debug("loading top " + forumTopPostersPrefs.getNumberOfPosters() + " posters of forum id: " + forumId);
forumTopPosters =
forumDAO.findPostersAndRatingPoints(
forumId,
forumTopPostersPrefs.getNumberOfPosters().intValue(),
excludeRoles
);
macro.getAttributes().put(MACRO_ATTR_TOPPOSTERS+forumTopPostersPrefs.getForumLink(), forumTopPosters);
}
return forumTopPosters;
}
private Long resolveForumId(String forumLink) {
if (forumLink == null || forumLink.length() == 0) return null;
WikiLinkResolver resolver = (WikiLinkResolver)Component.getInstance("wikiLinkResolver");
Map<String, WikiLink> resolvedLinks = new HashMap<String, WikiLink>();
resolver.resolveLinkText(currentDirectory.getAreaNumber(), resolvedLinks, forumLink);
WikiLink resolvedLink = resolvedLinks.get(forumLink);
if (resolvedLink.isBroken() || resolvedLink.getFile().getId() == null) {
return null;
} else {
// Parent of forum start page is the forum directory
return resolvedLink.getFile().getParent().getId();
}
}
}