/** * OLAT - Online Learning and Training<br> * http://www.olat.org * <p> * Licensed under the Apache License, Version 2.0 (the "License"); <br> * you may not use this file except in compliance with the License.<br> * You may obtain a copy of the License at * <p> * http://www.apache.org/licenses/LICENSE-2.0 * <p> * Unless required by applicable law or agreed to in writing,<br> * software distributed under the License is distributed on an "AS IS" BASIS, <br> * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> * See the License for the specific language governing permissions and <br> * limitations under the License. * <p> * Copyright (c) since 2004 at Multimedia- & E-Learning Services (MELS),<br> * University of Zurich, Switzerland. * <hr> * <a href="http://www.openolat.org"> * OpenOLAT - Online Learning and Training</a><br> * This file has been modified by the OpenOLAT community. Changes are licensed * under the Apache 2.0 license as the original file. */ package org.olat.modules.fo.archiver; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.Iterator; import java.util.List; import org.olat.core.logging.OLog; import org.olat.core.logging.Tracing; import org.olat.core.util.tree.TreeVisitor; import org.olat.modules.fo.Forum; import org.olat.modules.fo.ForumCallback; import org.olat.modules.fo.Message; import org.olat.modules.fo.archiver.formatters.ForumFormatter; import org.olat.modules.fo.manager.ForumManager; /** * Initial Date: Nov 11, 2005 <br> * @author Alexander Schneider */ public class ForumArchiveManager { private static final OLog log = Tracing.createLoggerFor(ForumArchiveManager.class); private static final ForumArchiveManager instance = new ForumArchiveManager(); private ForumArchiveManager() { // private since singleton } /** * @return the singleton */ public static ForumArchiveManager getInstance() { return instance; } /** * If the forumCallback is null no restriction applies to the forum archiver. * (that is it can archive all threads no matter the status) * @param forumFormatter * @param forumId * @param forumCallback * @return */ public String applyFormatter(ForumFormatter forumFormatter, Long forumId, ForumCallback forumCallback){ log.info("Archiving complete forum: " + forumId); //convert forum structure to trees List<MessageNode> threadTreesList = convertToThreadTrees(forumId, forumCallback); //format forum trees by using the formatter given by the callee return formatForum(threadTreesList, forumFormatter, forumId); } /** * It is assumed that if the caller of this method is allowed to see the forum thread * starting from topMessageId, then he also has the right to archive it, so no need for a ForumCallback. * @param forumFormatter * @param forumId * @param topMessageId * @return the message thread as String formatted */ public String applyFormatterForOneThread(ForumFormatter forumFormatter, Long forumId, Long topMessageId){ MessageNode topMessageNode = convertToThreadTree(topMessageId); return formatThread(topMessageNode, forumFormatter, forumId); } /** * If the forumCallback is null no filtering is executed, * else if a thread is hidden and the user doesn't have moderator rights the * hidden thread is not included into the archive. * @param forumId * @param metaInfo * @return all top message nodes together with their children in a list */ private List<MessageNode> convertToThreadTrees(Long forumId, ForumCallback forumCallback){ List<MessageNode> topNodeList = new ArrayList<>(); ForumManager fm = ForumManager.getInstance(); Forum f = fm.loadForum(forumId); List<Message> messages = fm.getMessagesByForum(f); for (Iterator<Message> iterTop = messages.iterator(); iterTop.hasNext();) { Message msg = iterTop.next(); if (msg.getParent() == null) { iterTop.remove(); MessageNode topNode = new MessageNode(msg); if(topNode.isHidden() && (forumCallback==null || (forumCallback!=null && forumCallback.mayEditMessageAsModerator()))) { addChildren(messages, topNode); topNodeList.add(topNode); } else if(!topNode.isHidden()) { addChildren(messages, topNode); topNodeList.add(topNode); } } } Collections.sort(topNodeList, new MessageNodeComparator()); return topNodeList; } public static class MessageNodeComparator implements Comparator<MessageNode> { @Override public int compare(final MessageNode m1, final MessageNode m2) { if(m1.isSticky() && m2.isSticky()) { return m2.getModifiedDate().compareTo(m1.getModifiedDate()); //last first } else if(m1.isSticky()) { return -1; } else if(m2.isSticky()){ return 1; } else { return m2.getModifiedDate().compareTo(m1.getModifiedDate()); //last first } } } /** * * @param messageId * @param metaInfo * @return the top message node with all its children */ private MessageNode convertToThreadTree(Long topMessageId){ MessageNode topNode = null; List<Message> messages = ForumManager.getInstance().getThread(topMessageId); for (Iterator<Message> iterTop = messages.iterator(); iterTop.hasNext();) { Message msg = iterTop.next(); if (msg.getParent() == null) { iterTop.remove(); topNode = new MessageNode(msg); addChildren(messages, topNode); } } return topNode; } private void addChildren(List<Message> messages, MessageNode mn){ for(Iterator<Message> iterMsg = messages.iterator(); iterMsg.hasNext(); ) { Message msg = iterMsg.next(); if ((msg.getParent() != null) && (msg.getParent().getKey() == mn.getKey())){ MessageNode childNode = new MessageNode(msg); mn.addChild(childNode); //FIXME:as:c next line is not necessary childNode.setParent(mn); addChildren(messages, childNode); } } } /** * * @param topNodeList * @param forumFormatter * @param metaInfo * @return */ private String formatForum(List<MessageNode> topNodeList, ForumFormatter forumFormatter, Long forumId) { forumFormatter.setForumKey(forumId); StringBuilder formattedForum = new StringBuilder(); forumFormatter.openForum(); for (Iterator<MessageNode> iterTop = topNodeList.iterator(); iterTop.hasNext();){ MessageNode mn = iterTop.next(); //a new top thread starts, inform formatter forumFormatter.openThread(); TreeVisitor tv = new TreeVisitor(forumFormatter, mn, false); tv.visitAll(); //commit formattedForum.append(forumFormatter.closeThread()); } return formattedForum.append(forumFormatter.closeForum().toString()).toString(); } /** * * @param mn * @param forumFormatter * @param metaInfo * @return */ private String formatThread(MessageNode mn, ForumFormatter forumFormatter, Long forumId){ forumFormatter.setForumKey(forumId); StringBuilder formattedThread = new StringBuilder(); forumFormatter.openThread(); TreeVisitor tv = new TreeVisitor(forumFormatter, mn, false); tv.visitAll(); return formattedThread.append(formattedThread.append(forumFormatter.closeThread())).toString(); } }