/**
* OLAT - Online Learning and Training<br>
* http://www.olat.orgrmform
* <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.
* <p>
*/
package org.olat.modules.fo.ui;
import java.util.List;
import org.olat.basesecurity.BaseSecurity;
import org.olat.core.commons.services.notifications.PublisherData;
import org.olat.core.commons.services.notifications.SubscriptionContext;
import org.olat.core.commons.services.notifications.ui.ContextualSubscriptionController;
import org.olat.core.gui.UserRequest;
import org.olat.core.gui.components.Component;
import org.olat.core.gui.components.velocity.VelocityContainer;
import org.olat.core.gui.control.Controller;
import org.olat.core.gui.control.Event;
import org.olat.core.gui.control.WindowControl;
import org.olat.core.gui.control.controller.BasicController;
import org.olat.core.gui.control.generic.dtabs.Activateable2;
import org.olat.core.id.Identity;
import org.olat.core.id.OLATResourceable;
import org.olat.core.id.context.BusinessControlFactory;
import org.olat.core.id.context.ContextEntry;
import org.olat.core.id.context.StateEntry;
import org.olat.core.util.StringHelper;
import org.olat.core.util.Util;
import org.olat.core.util.coordinate.CoordinatorManager;
import org.olat.core.util.event.GenericEventListener;
import org.olat.core.util.resource.OresHelper;
import org.olat.modules.fo.Forum;
import org.olat.modules.fo.ForumCallback;
import org.olat.modules.fo.ForumChangedEvent;
import org.olat.modules.fo.Message;
import org.olat.modules.fo.Status;
import org.olat.modules.fo.manager.ForumManager;
import org.olat.modules.fo.ui.events.DeleteMessageEvent;
import org.olat.modules.fo.ui.events.DeleteThreadEvent;
import org.olat.modules.fo.ui.events.SelectMessageEvent;
import org.olat.modules.fo.ui.events.SelectUserEvent;
import org.olat.modules.fo.ui.events.SelectUserListEvent;
import org.olat.util.logging.activity.LoggingResourceable;
import org.springframework.beans.factory.annotation.Autowired;
/**
* Description: <br>
* CREATE: - new thread (topmessage) -> ask ForumCallback 'mayOpenNewThread' -
* new message -> ask ForumCallback 'mayReplyMessage' <br>
* READ: - everybody may read every message <br>
* UPDATE: - who wrote a message may edit and save his message as long as it has
* no children. - if somebody want to edit a message of somebodyelse -> ask
* ForumCallback 'mayEditMessageAsModerator' <br>
* DELETE: - who wrote a message may delete his message as long as it has no
* children. - if somebody want to delete a message of somebodyelse -> ask
* ForumCallback 'mayDeleteMessageAsModerator' <br>
* <br>
* Notifications: notified when: <br>
* a new thread is opened <br>
* a new reply is given <br>
* a message has been edited <br>
* but not when a message has been deleted <br>
*
* @author Felix Jost
* @author Refactorings: Roman Haag, roman.haag@frentix.com, frentix GmbH
*/
public class ForumController extends BasicController implements GenericEventListener, Activateable2 {
private VelocityContainer forumPanel;
private ThreadListController threadListCtrl;
private ForumUserListController userListCtrl;
private MessageListController viewCtrl, userViewCtrl;
private Forum forum;
private ForumCallback focallback;
private boolean reloadThreadList = false;
private SubscriptionContext subsContext;
private ContextualSubscriptionController csc;
@Autowired
private ForumManager fm;
@Autowired
private BaseSecurity securityManager;
/**
* @param forum
* @param focallback
* @param ureq
* @param wControl
*/
public ForumController(UserRequest ureq, WindowControl wControl,
Forum forum, ForumCallback focallback, boolean showSubscriptionButton) {
super(ureq, wControl);
setTranslator(Util.createPackageTranslator(Forum.class, getLocale(), getTranslator()));
this.forum = forum;
this.focallback = focallback;
addLoggingResourceable(LoggingResourceable.wrap(forum));
forumPanel = createVelocityContainer("forum");
// --- subscription ---
subsContext = focallback.getSubscriptionContext();
// if sc is null, then no subscription is desired
if (subsContext != null && showSubscriptionButton) {
String businessPath = wControl.getBusinessControl().getAsString();
String data = String.valueOf(forum.getKey());
PublisherData pdata = new PublisherData(OresHelper.calculateTypeName(Forum.class), data, businessPath);
csc = new ContextualSubscriptionController(ureq, getWindowControl(), subsContext, pdata);
listenTo(csc);
forumPanel.put("subscription", csc.getInitialComponent());
}
threadListCtrl = new ThreadListController(ureq, getWindowControl(), forum, focallback);
listenTo(threadListCtrl);
threadListCtrl.loadModel();
// Default view
putInitialPanel(forumPanel);
putContent(threadListCtrl);
// Register for forum events
CoordinatorManager.getInstance().getCoordinator().getEventBus().registerFor(this, getIdentity(), forum);
}
@Override
protected void doDispose() {
CoordinatorManager.getInstance().getCoordinator().getEventBus().deregisterFor(this, forum);
}
@Override
public void activate(UserRequest ureq, List<ContextEntry> entries, StateEntry state) {
if(entries == null || entries.isEmpty()) {
doThreadList(ureq);
} else {
String type = entries.get(0).getOLATResourceable().getResourceableTypeName();
if("Message".equalsIgnoreCase(type)) {
Long resId = entries.get(0).getOLATResourceable().getResourceableId();
if (resId.longValue() != 0) {
Message message = fm.getMessageById(resId);
if (message != null) {
doThreadList(ureq);
Message thread = message.getThreadtop() == null ? message : message.getThreadtop();
if(focallback.mayEditMessageAsModerator() || !Status.getStatus(thread.getStatusCode()).isHidden()) {
String subType = null;
if(entries.size() > 1) {
subType = entries.get(1).getOLATResourceable().getResourceableTypeName();
}
if("Marked".equalsIgnoreCase(subType)) {
doMarkedView(ureq, thread, message);
} else if("New".equalsIgnoreCase(subType)) {
doMarkedView(ureq, thread, message);
} else {
doThreadView(ureq, thread, message);
}
}
}
}
} else if("Identity".equalsIgnoreCase(type)) {
Long resId = entries.get(0).getOLATResourceable().getResourceableId();
doUserList(ureq);
if (resId.longValue() > 0) {
doUserMessageList(ureq, resId);
}
}
}
}
@Override
public void event(Event event) {
if(event instanceof ForumChangedEvent) {
reloadThreadList = true;
}
}
@Override
public void event(UserRequest ureq, Component source, Event event) {
//
}
@Override
public void event(UserRequest ureq, Controller source, Event event) {
if (threadListCtrl == source) {
if(event instanceof SelectMessageEvent) {
doProcessSelectEvent(ureq, (SelectMessageEvent)event);
} else if(event instanceof SelectUserListEvent) {
doUserList(ureq);
}
} else if(viewCtrl == source) {
if(event == Event.BACK_EVENT) {
reloadThreadList |= viewCtrl.hasMarkedNewMessages();
doThreadList(ureq);
} else if(event instanceof DeleteThreadEvent) {
reloadThreadList = true;
doThreadList(ureq);
} else if(event instanceof DeleteMessageEvent) {
reloadThreadList = true;
} else if(event instanceof SelectMessageEvent) {
doProcessSelectEvent(ureq, (SelectMessageEvent)event);
}
} else if(userViewCtrl == source) {
if(event == Event.BACK_EVENT) {
reloadThreadList |= userViewCtrl.hasMarkedNewMessages();
cleanUpMessageViews();
doUserList(ureq);
} else if(event instanceof SelectMessageEvent) {
doProcessSelectEvent(ureq, (SelectMessageEvent)event);
}
} else if(userListCtrl == source) {
if(event == Event.BACK_EVENT) {
removeAsListenerAndDispose(userListCtrl);
userListCtrl = null;
doThreadList(ureq);
} else if(event instanceof SelectUserEvent) {
SelectUserEvent sue = (SelectUserEvent)event;
if(sue.isGuest()) {
doGuestMessageList(ureq);
} else if(StringHelper.containsNonWhitespace(sue.getPseudonym())) {
doPseudonymMessageList(ureq, sue.getIdentityKey(), sue.getPseudonym());
} else if(sue.getIdentityKey() != null) {
doUserMessageList(ureq, sue.getIdentityKey());
}
}
}
}
private void doProcessSelectEvent(UserRequest ureq, SelectMessageEvent sme) {
Message thread = fm.getMessageById(sme.getMessageKey());
if(thread == null) {
logError("Thread doesn't exists: " + sme.getMessageKey(), new Exception());
reloadThreadList = true;
doThreadList(ureq);
} else {
Message scrollTo = null;
if(sme.getScrollToMessageKey() != null) {
scrollTo = fm.getMessageById(sme.getScrollToMessageKey());
}
if(SelectMessageEvent.SELECT_THREAD.equals(sme.getCommand())) {
doThreadView(ureq, thread, scrollTo);
} else if(SelectMessageEvent.SELECT_MARKED.equals(sme.getCommand())) {
doMarkedView(ureq, thread, scrollTo);
} else if(SelectMessageEvent.SELECT_NEW.equals(sme.getCommand())) {
doNewView(ureq, thread, scrollTo);
}
}
}
private void doThreadView(UserRequest ureq, Message thread, Message scrollTo) {
cleanUpMessageViews();
OLATResourceable ores = OresHelper.createOLATResourceableInstance("Message", thread.getKey());
WindowControl bwControl = BusinessControlFactory.getInstance().createBusinessWindowControl(ores, null, getWindowControl());
viewCtrl = new MessageListController(ureq, bwControl, forum, focallback);
viewCtrl.loadThread(ureq, thread);
viewCtrl.scrollTo(scrollTo);
viewCtrl.doShowBySettings(ureq);
listenTo(viewCtrl);
putContent(viewCtrl);
addToHistory(ureq, viewCtrl);
}
private void doMarkedView(UserRequest ureq, Message thread, Message scrollTo) {
cleanUpMessageViews();
OLATResourceable ores = OresHelper.createOLATResourceableInstance("Message", thread.getKey());
WindowControl bwControl = BusinessControlFactory.getInstance().createBusinessWindowControl(ores, null, getWindowControl());
OLATResourceable markedOres = OresHelper.createOLATResourceableInstance("Marked", 0l);
WindowControl bbwControl = BusinessControlFactory.getInstance().createBusinessWindowControl(markedOres, null, bwControl);
viewCtrl = new MessageListController(ureq, bbwControl, forum, focallback);
viewCtrl.loadThread(ureq, thread);
viewCtrl.scrollTo(scrollTo);
viewCtrl.doShowMarked(ureq);
listenTo(viewCtrl);
putContent(viewCtrl);
addToHistory(ureq, viewCtrl);
}
private void doNewView(UserRequest ureq, Message thread, Message scrollTo) {
cleanUpMessageViews();
OLATResourceable ores = OresHelper.createOLATResourceableInstance("Message", thread.getKey());
WindowControl bwControl = BusinessControlFactory.getInstance().createBusinessWindowControl(ores, null, getWindowControl());
OLATResourceable markedOres = OresHelper.createOLATResourceableInstance("New", 0l);
WindowControl bbwControl = BusinessControlFactory.getInstance().createBusinessWindowControl(markedOres, null, bwControl);
viewCtrl = new MessageListController(ureq, bbwControl, forum, focallback);
viewCtrl.loadThread(ureq, thread);
viewCtrl.scrollTo(scrollTo);
viewCtrl.doShowNew(ureq);
listenTo(viewCtrl);
putContent(viewCtrl);
addToHistory(ureq, viewCtrl);
}
private void doUserMessageList(UserRequest ureq, Long identityKey) {
cleanUpMessageViews();
OLATResourceable ores = OresHelper.createOLATResourceableInstance("Identity", identityKey);
WindowControl bwControl = BusinessControlFactory.getInstance().createBusinessWindowControl(ores, null, getWindowControl());
userViewCtrl = new MessageListController(ureq, bwControl, forum, focallback);
Identity user = securityManager.loadIdentityByKey(identityKey);
userViewCtrl.loadUserMessages(ureq, user);
listenTo(userViewCtrl);
putContent(userViewCtrl);
addToHistory(ureq, userViewCtrl);
}
private void doGuestMessageList(UserRequest ureq) {
cleanUpMessageViews();
userViewCtrl = new MessageListController(ureq, getWindowControl(), forum, focallback);
userViewCtrl.loadGuestMessages(ureq);
listenTo(userViewCtrl);
putContent(userViewCtrl);
}
private void doPseudonymMessageList(UserRequest ureq, Long identityKey, String pseudonym) {
cleanUpMessageViews();
userViewCtrl = new MessageListController(ureq, getWindowControl(), forum, focallback);
Identity user = securityManager.loadIdentityByKey(identityKey);
userViewCtrl.loadUserMessagesUnderPseudo(ureq, user, pseudonym);
listenTo(userViewCtrl);
putContent(userViewCtrl);
}
private void doThreadList(UserRequest ureq) {
cleanUpMessageViews();
if(reloadThreadList) {
threadListCtrl.loadModel();
reloadThreadList = false;
}
putContent(threadListCtrl);
addToHistory(ureq, threadListCtrl);
}
private void doUserList(UserRequest ureq) {
cleanUpMessageViews();
OLATResourceable ores = OresHelper.createOLATResourceableInstance("Identity", 0l);
WindowControl bwControl = BusinessControlFactory.getInstance().createBusinessWindowControl(ores, null, getWindowControl());
userListCtrl = new ForumUserListController(ureq, bwControl, forum);
listenTo(userListCtrl);
putContent(userListCtrl);
addToHistory(ureq, userListCtrl);
}
private void putContent(Controller controller) {
forumPanel.put("forum", controller.getInitialComponent());
}
private void cleanUpMessageViews() {
removeAsListenerAndDispose(userViewCtrl);
removeAsListenerAndDispose(viewCtrl);
userViewCtrl = null;
viewCtrl = null;
}
}