/**
* <a href="http://www.openolat.org">
* OpenOLAT - Online Learning and Training</a><br>
* <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 the
* <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a>
* <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>
* Initial code contributed and copyrighted by<br>
* frentix GmbH, http://www.frentix.com
* <p>
*/
package org.olat.repository.ui;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
import org.olat.NewControllerFactory;
import org.olat.core.commons.services.mark.Mark;
import org.olat.core.commons.services.mark.MarkManager;
import org.olat.core.gui.UserRequest;
import org.olat.core.gui.components.Component;
import org.olat.core.gui.components.dropdown.Dropdown;
import org.olat.core.gui.components.dropdown.Dropdown.Spacer;
import org.olat.core.gui.components.htmlheader.jscss.CustomCSS;
import org.olat.core.gui.components.link.Link;
import org.olat.core.gui.components.link.LinkFactory;
import org.olat.core.gui.components.stack.PopEvent;
import org.olat.core.gui.components.stack.TooledStackedPanel;
import org.olat.core.gui.components.stack.TooledStackedPanel.Align;
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.MainLayoutBasicController;
import org.olat.core.gui.control.generic.closablewrapper.CloseableModalController;
import org.olat.core.gui.control.generic.dtabs.Activateable2;
import org.olat.core.gui.control.generic.layout.MainLayoutController;
import org.olat.core.gui.media.MediaResource;
import org.olat.core.id.OLATResourceable;
import org.olat.core.id.Roles;
import org.olat.core.id.context.BusinessControlFactory;
import org.olat.core.id.context.ContextEntry;
import org.olat.core.id.context.HistoryPoint;
import org.olat.core.id.context.StateEntry;
import org.olat.core.logging.OLATSecurityException;
import org.olat.core.logging.activity.ThreadLocalUserActivityLogger;
import org.olat.core.util.StringHelper;
import org.olat.core.util.UserSession;
import org.olat.core.util.Util;
import org.olat.core.util.coordinate.LockResult;
import org.olat.core.util.event.EventBus;
import org.olat.core.util.event.GenericEventListener;
import org.olat.core.util.resource.OresHelper;
import org.olat.course.CourseModule;
import org.olat.course.assessment.AssessmentMode;
import org.olat.course.assessment.AssessmentModeManager;
import org.olat.course.assessment.manager.UserCourseInformationsManager;
import org.olat.course.assessment.model.TransientAssessmentMode;
import org.olat.repository.RepositoryEntry;
import org.olat.repository.RepositoryEntryManagedFlag;
import org.olat.repository.RepositoryEntryRef;
import org.olat.repository.RepositoryManager;
import org.olat.repository.RepositoryModule;
import org.olat.repository.RepositoryService;
import org.olat.repository.controllers.EntryChangedEvent;
import org.olat.repository.controllers.EntryChangedEvent.Change;
import org.olat.repository.handlers.EditionSupport;
import org.olat.repository.handlers.RepositoryHandler;
import org.olat.repository.handlers.RepositoryHandlerFactory;
import org.olat.repository.model.RepositoryEntrySecurity;
import org.olat.repository.ui.author.AuthoringEditAccessController;
import org.olat.repository.ui.author.CatalogSettingsController;
import org.olat.repository.ui.author.ConfirmDeleteSoftlyController;
import org.olat.repository.ui.author.CopyRepositoryEntryController;
import org.olat.repository.ui.author.RepositoryEditDescriptionController;
import org.olat.repository.ui.author.RepositoryMembersController;
import org.olat.repository.ui.list.LeavingEvent;
import org.olat.repository.ui.list.RepositoryEntryDetailsController;
import org.olat.resource.OLATResource;
import org.olat.resource.accesscontrol.ACService;
import org.olat.resource.accesscontrol.AccessResult;
import org.olat.resource.accesscontrol.OfferAccess;
import org.olat.resource.accesscontrol.ui.AccessEvent;
import org.olat.resource.accesscontrol.ui.AccessListController;
import org.olat.resource.accesscontrol.ui.AccessRefusedController;
import org.olat.resource.accesscontrol.ui.OrdersAdminController;
import org.olat.user.UserManager;
import org.olat.util.logging.activity.LoggingResourceable;
import org.springframework.beans.factory.annotation.Autowired;
/**
*
* Initial date: 14.08.2014<br>
* @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
*
*/
public class RepositoryEntryRuntimeController extends MainLayoutBasicController implements Activateable2, GenericEventListener {
private Controller runtimeController;
protected final TooledStackedPanel toolbarPanel;
private final RuntimeControllerCreator runtimeControllerCreator;
protected Controller editorCtrl;
protected Controller currentToolCtr;
private CloseableModalController cmc;
protected Controller accessController;
private OrdersAdminController ordersCtlr;
private CatalogSettingsController catalogCtlr;
private CopyRepositoryEntryController copyCtrl;
private ConfirmDeleteSoftlyController confirmDeleteCtrl;
protected AuthoringEditAccessController accessCtrl;
private RepositoryEntryDetailsController detailsCtrl;
private RepositoryMembersController membersEditController;
protected RepositoryEditDescriptionController descriptionCtrl;
private Dropdown tools;
private Dropdown settings;
protected Link editLink, membersLink, ordersLink,
editDescriptionLink, accessLink, catalogLink,
detailsLink, bookmarkLink,
copyLink, downloadLink, deleteLink;
protected final boolean isOlatAdmin;
protected final boolean isGuestOnly;
protected final boolean isAuthor;
protected RepositoryEntrySecurity reSecurity;
protected final Roles roles;
protected final boolean showInfos;
protected final boolean allowBookmark;
protected boolean corrupted;
protected boolean overrideReadOnly = false;
private RepositoryEntry re;
private LockResult lockResult;
private boolean assessmentLock;// by Assessment mode
private AssessmentMode assessmentMode;
protected final RepositoryHandler handler;
private AtomicBoolean launchDateUpdated = new AtomicBoolean(false);
private final EventBus eventBus;
private HistoryPoint launchedFromPoint;
@Autowired
protected ACService acService;
@Autowired
protected UserManager userManager;
@Autowired
protected MarkManager markManager;
@Autowired
protected RepositoryModule repositoryModule;
@Autowired
protected RepositoryService repositoryService;
@Autowired
protected RepositoryManager repositoryManager;
@Autowired
private RepositoryHandlerFactory handlerFactory;
@Autowired
private AssessmentModeManager assessmentModeMgr;
@Autowired
private UserCourseInformationsManager userCourseInfoMgr;
public RepositoryEntryRuntimeController(UserRequest ureq, WindowControl wControl, RepositoryEntry re,
RepositoryEntrySecurity reSecurity, RuntimeControllerCreator runtimeControllerCreator) {
this(ureq, wControl, re, reSecurity, runtimeControllerCreator, true, true);
}
public RepositoryEntryRuntimeController(UserRequest ureq, WindowControl wControl, RepositoryEntry re,
RepositoryEntrySecurity reSecurity, RuntimeControllerCreator runtimeControllerCreator, boolean allowBookmark, boolean showInfos) {
super(ureq, wControl);
setTranslator(Util.createPackageTranslator(RepositoryService.class, getLocale(), getTranslator()));
ThreadLocalUserActivityLogger.addLoggingResourceInfo(LoggingResourceable
.wrapBusinessPath(OresHelper.createOLATResourceableType("RepositorySite")));
//! check corrupted
corrupted = isCorrupted(re);
assessmentLock = isAssessmentLock(ureq, re, reSecurity);
UserSession session = ureq.getUserSession();
Object wcard = session.removeEntry("override_readonly_" + re.getKey());
if(Boolean.TRUE.equals(wcard)) {
overrideReadOnly = true;
}
this.re = re;
this.showInfos = showInfos;
this.allowBookmark = allowBookmark;
this.runtimeControllerCreator = runtimeControllerCreator;
if(assessmentLock) {
TransientAssessmentMode mode = session.getLockMode();
assessmentMode = assessmentModeMgr.getAssessmentModeById(mode.getModeKey());
}
if(session != null && session.getHistoryStack() != null && session.getHistoryStack().size() >= 2) {
// Set previous business path as back link for this course - brings user back to place from which he launched the course
List<HistoryPoint> stack = session.getHistoryStack();
for(int i=stack.size() - 2; i-->0; ) {
HistoryPoint point = stack.get(stack.size() - 2);
if(point.getEntries().size() > 0) {
OLATResourceable ores = point.getEntries().get(0).getOLATResourceable();
if(!OresHelper.equals(re, ores) && !OresHelper.equals(re.getOlatResource(), ores)) {
launchedFromPoint = point;
break;
}
}
}
}
handler = handlerFactory.getRepositoryHandler(re);
roles = session.getRoles();
isOlatAdmin = roles.isOLATAdmin();
isGuestOnly = roles.isGuestOnly();
isAuthor = roles.isAuthor();
this.reSecurity = reSecurity;
// set up the components
toolbarPanel = new TooledStackedPanel("courseStackPanel", getTranslator(), this);
toolbarPanel.setInvisibleCrumb(0); // show root (course) level
toolbarPanel.setShowCloseLink(!assessmentLock, !assessmentLock);
toolbarPanel.getBackLink().setEnabled(!assessmentLock);
putInitialPanel(toolbarPanel);
doRun(ureq, reSecurity);
loadRights(reSecurity);
initToolbar();
eventBus = ureq.getUserSession().getSingleUserEventCenter();
eventBus.registerFor(this, getIdentity(), RepositoryService.REPOSITORY_EVENT_ORES);
}
protected boolean isCorrupted(RepositoryEntry entry) {
return entry == null;
}
protected final boolean isAssessmentLock() {
return assessmentLock;
}
private final boolean isAssessmentLock(UserRequest ureq, RepositoryEntry entry, RepositoryEntrySecurity reSec) {
OLATResource resource = entry.getOlatResource();
OLATResourceable lock = ureq.getUserSession().getLockResource();
return lock != null && !reSec.isOwner() && !ureq.getUserSession().getRoles().isOLATAdmin()
&& lock.getResourceableId().equals(resource.getResourceableId())
&& lock.getResourceableTypeName().equals(resource.getResourceableTypeName());
}
/**
* If override, need to set isOwner and isEntryAdmin
*/
protected void loadRights(RepositoryEntrySecurity security) {
this.reSecurity = security;
}
protected RepositoryEntry getRepositoryEntry() {
return re;
}
protected RepositoryEntry loadRepositoryEntry() {
re = repositoryService.loadByKey(re.getKey());
return re;
}
protected RepositoryEntry refreshRepositoryEntry(RepositoryEntry refreshedEntry) {
re = refreshedEntry;
return re;
}
protected OLATResourceable getOlatResourceable() {
return OresHelper.clone(re.getOlatResource());
}
protected Controller getRuntimeController() {
return runtimeController;
}
protected final void initToolbar() {
tools = new Dropdown("toolbox.tools", "toolbox.tools", false, getTranslator());
tools.setElementCssClass("o_sel_repository_tools");
tools.setIconCSS("o_icon o_icon_tools");
String resourceType = re.getOlatResource().getResourceableTypeName();
String name = NewControllerFactory.translateResourceableTypeName(resourceType, getLocale());
settings = new Dropdown("settings", "toolbox.settings", false, getTranslator());
settings.setTranslatedLabel(name);
settings.setElementCssClass("o_sel_course_settings");
settings.setIconCSS("o_icon o_icon_actions");
initToolbar(tools, settings);
if(tools.size() > 0) {
toolbarPanel.addTool(tools, Align.left, true);
}
if(settings.size() > 0) {
toolbarPanel.addTool(settings, Align.left, true);
}
}
protected void initToolbar(Dropdown toolsDropdown, Dropdown settingsDropdown) {
initRuntimeTools(toolsDropdown);
initSettingsTools(settingsDropdown);
initEditionTools(settingsDropdown);
initDeleteTools(settingsDropdown, true);
detailsLink = LinkFactory.createToolLink("details", translate("details.header"), this, "o_sel_repo_details");
detailsLink.setIconLeftCSS("o_icon o_icon-fw o_icon_details");
detailsLink.setElementCssClass("o_sel_author_details");
detailsLink.setVisible(showInfos);
toolbarPanel.addTool(detailsLink);
boolean marked = markManager.isMarked(re, getIdentity(), null);
String css = marked ? Mark.MARK_CSS_ICON : Mark.MARK_ADD_CSS_ICON;
bookmarkLink = LinkFactory.createToolLink("bookmark", translate("details.bookmark.label"), this, css);
bookmarkLink.setTitle(translate(marked ? "details.bookmark.remove" : "details.bookmark"));
bookmarkLink.setVisible(allowBookmark);
toolbarPanel.addTool(bookmarkLink, Align.right);
}
protected void initRuntimeTools(Dropdown toolsDropdown) {
if (reSecurity.isEntryAdmin()) {
//tools
if(handler.supportsEdit(re.getOlatResource()) == EditionSupport.yes) {
boolean managed = RepositoryEntryManagedFlag.isManaged(getRepositoryEntry(), RepositoryEntryManagedFlag.editcontent);
editLink = LinkFactory.createToolLink("edit.cmd", translate("details.openeditor"), this, "o_sel_repository_editor");
editLink.setIconLeftCSS("o_icon o_icon-lg o_icon_edit");
editLink.setEnabled(!managed);
toolsDropdown.addComponent(editLink);
}
membersLink = LinkFactory.createToolLink("members", translate("details.members"), this, "o_sel_repo_members");
membersLink.setIconLeftCSS("o_icon o_icon-fw o_icon_membersmanagement");
toolsDropdown.addComponent(membersLink);
ordersLink = LinkFactory.createToolLink("bookings", translate("details.orders"), this, "o_sel_repo_booking");
ordersLink.setIconLeftCSS("o_icon o_icon-fw o_icon_booking");
boolean booking = acService.isResourceAccessControled(re.getOlatResource(), null);
ordersLink.setEnabled(booking);
toolsDropdown.addComponent(ordersLink);
}
}
protected void initSettingsTools(Dropdown settingsDropdown) {
if (reSecurity.isEntryAdmin()) {
//settings
editDescriptionLink = LinkFactory.createToolLink("settings.cmd", translate("details.chdesc"), this, "o_icon_details");
editDescriptionLink.setElementCssClass("o_sel_course_settings");
editDescriptionLink.setEnabled(!corrupted);
settingsDropdown.addComponent(editDescriptionLink);
accessLink = LinkFactory.createToolLink("access.cmd", translate("tab.accesscontrol"), this, "o_icon_password");
accessLink.setElementCssClass("o_sel_course_access");
settingsDropdown.addComponent(accessLink);
catalogLink = LinkFactory.createToolLink("cat", translate("details.categoriesheader"), this, "o_icon_catalog");
catalogLink.setElementCssClass("o_sel_repo_add_to_catalog");
catalogLink.setVisible(repositoryModule.isCatalogEnabled());
settingsDropdown.addComponent(catalogLink);
}
}
protected void initEditionTools(Dropdown settingsDropdown) {
boolean copyManaged = RepositoryEntryManagedFlag.isManaged(re, RepositoryEntryManagedFlag.copy);
boolean canCopy = (isAuthor || reSecurity.isEntryAdmin()) && (re.getCanCopy() || reSecurity.isEntryAdmin()) && !copyManaged;
boolean canDownload = re.getCanDownload() && handler.supportsDownload();
// disable download for courses if not author or owner
if (re.getOlatResource().getResourceableTypeName().equals(CourseModule.getCourseTypeName()) && !(reSecurity.isEntryAdmin() || isAuthor)) {
canDownload = false;
}
// always enable download for owners
if (reSecurity.isEntryAdmin() && handler.supportsDownload()) {
canDownload = true;
}
if(canCopy || canDownload) {
if(settingsDropdown.size() > 0) {
settingsDropdown.addComponent(new Spacer("copy-download"));
}
if (canCopy) {
copyLink = LinkFactory.createToolLink("copy", translate("details.copy"), this, "o_icon o_icon-fw o_icon_copy");
copyLink.setElementCssClass("o_sel_repo_copy");
settingsDropdown.addComponent(copyLink);
}
if(canDownload) {
downloadLink = LinkFactory.createToolLink("download", translate("details.download"), this, "o_icon o_icon-fw o_icon_download");
downloadLink.setElementCssClass("o_sel_repo_download");
settingsDropdown.addComponent(downloadLink);
}
}
}
protected void initDeleteTools(Dropdown settingsDropdown, boolean needSpacer) {
if(reSecurity.isEntryAdmin()) {
boolean deleteManaged = RepositoryEntryManagedFlag.isManaged(re, RepositoryEntryManagedFlag.delete);
if(needSpacer && settingsDropdown.size() > 0 && !deleteManaged) {
settingsDropdown.addComponent(new Spacer("close-delete"));
}
if(!deleteManaged) {
String type = translate(handler.getSupportedType());
String deleteTitle = translate("details.delete.alt", new String[]{ type });
deleteLink = LinkFactory.createToolLink("delete", deleteTitle, this, "o_icon o_icon-fw o_icon_delete_item");
deleteLink.setElementCssClass("o_sel_repo_close");
settingsDropdown.addComponent(deleteLink);
}
}
}
public void setActiveTool(Link tool) {
if(tools != null) {
tools.setActiveLink(tool);
}
if(settings != null) {
settings.setActiveLink(tool);
}
}
@Override
public CustomCSS getCustomCSS() {
return runtimeController instanceof MainLayoutController ? ((MainLayoutController)runtimeController).getCustomCSS() : null;
}
@Override
public void setCustomCSS(CustomCSS newCustomCSS) {
if(runtimeController instanceof MainLayoutController) {
((MainLayoutController)runtimeController).setCustomCSS(newCustomCSS);
}
}
@Override
public void activate(UserRequest ureq, List<ContextEntry> entries, StateEntry state) {
entries = removeRepositoryEntry(entries);
if(entries != null && entries.size() > 0) {
String type = entries.get(0).getOLATResourceable().getResourceableTypeName();
if("Editor".equalsIgnoreCase(type)) {
if(handler.supportsEdit(re) == EditionSupport.yes
&& !repositoryManager.createRepositoryEntryStatus(re.getStatusCode()).isClosed()) {
doEdit(ureq);
}
} else if("Catalog".equalsIgnoreCase(type)) {
doCatalog(ureq);
} else if("Infos".equalsIgnoreCase(type)) {
doDetails(ureq);
} else if("EditDescription".equalsIgnoreCase(type) || "Settings".equalsIgnoreCase(type)) {
doEditSettings(ureq);
} else if("MembersMgmt".equalsIgnoreCase(type)) {
doMembers(ureq);
}
}
if(runtimeController instanceof Activateable2) {
((Activateable2)runtimeController).activate(ureq, entries, state);
}
}
protected List<ContextEntry> removeRepositoryEntry(List<ContextEntry> entries) {
if(entries != null && entries.size() > 0) {
String type = entries.get(0).getOLATResourceable().getResourceableTypeName();
if("RepositoryEntry".equals(type)) {
if(entries.size() > 1) {
entries = entries.subList(1, entries.size());
} else {
entries = Collections.emptyList();
}
}
}
return entries;
}
protected WindowControl getSubWindowControl(String name) {
OLATResourceable ores = OresHelper.createOLATResourceableInstance(name, 0l);
ThreadLocalUserActivityLogger.addLoggingResourceInfo(LoggingResourceable.wrapBusinessPath(ores));
return BusinessControlFactory.getInstance().createBusinessWindowControl(ores, null, getWindowControl());
}
@Override
protected void doDispose() {
if(runtimeController != null && !runtimeController.isDisposed()) {
runtimeController.dispose();
}
eventBus.deregisterFor(this, RepositoryService.REPOSITORY_EVENT_ORES);
}
@Override
public void event(Event event) {
//
}
protected void processEntryChangedEvent(EntryChangedEvent repoEvent) {
if(repoEvent.isMe(getIdentity()) &&
(repoEvent.getChange() == Change.addBookmark || repoEvent.getChange() == Change.removeBookmark)) {
boolean marked = markManager.isMarked(OresHelper.clone(re), getIdentity(), null);
String css = "o_icon " + (marked ? Mark.MARK_CSS_ICON : Mark.MARK_ADD_CSS_ICON);
bookmarkLink.setIconLeftCSS(css);
bookmarkLink.setTitle( translate(marked ? "details.bookmark.remove" : "details.bookmark"));
}
}
@Override
protected void event(UserRequest ureq, Component source, Event event) {
if(source == runtimeController) {
fireEvent(ureq, event);
} else if(editLink == source) {
doEdit(ureq);
} else if(membersLink == source) {
doMembers(ureq);
} else if(editDescriptionLink == source) {
doEditSettings(ureq);
} else if(accessLink == source) {
doAccess(ureq);
} else if(catalogLink == source) {
doCatalog(ureq);
} else if(ordersLink == source) {
doOrders(ureq);
} else if(detailsLink == source) {
doDetails(ureq);
} else if(bookmarkLink == source) {
boolean marked = doMark(ureq);
String css = "o_icon " + (marked ? Mark.MARK_CSS_ICON : Mark.MARK_ADD_CSS_ICON);
bookmarkLink.setIconLeftCSS(css);
bookmarkLink.setTitle( translate(marked ? "details.bookmark.remove" : "details.bookmark"));
} else if(copyLink == source) {
doCopy(ureq);
} else if(downloadLink == source) {
doDownload(ureq);
} else if(deleteLink == source) {
doDelete(ureq);
} else if(source == toolbarPanel) {
if (event == Event.CLOSE_EVENT) {
doClose(ureq);
} else if(event instanceof PopEvent) {
setActiveTool(null);
}
}
}
@Override
protected void event(UserRequest ureq, Controller source, Event event) {
if(cmc == source) {
cleanUp();
} else if (source == accessController) {
if(event.equals(AccessEvent.ACCESS_OK_EVENT)) {
doPostSuccessfullAccess(ureq);
} else if(event.equals(AccessEvent.ACCESS_FAILED_EVENT)) {
String msg = ((AccessEvent)event).getMessage();
if(StringHelper.containsNonWhitespace(msg)) {
getWindowControl().setError(msg);
} else {
showError("error.accesscontrol");
}
}
} else if(accessCtrl == source) {
if(event == Event.CHANGED_EVENT) {
refreshRepositoryEntry(accessCtrl.getEntry());
if(ordersLink != null) {
boolean booking = acService.isResourceAccessControled(re.getOlatResource(), null);
ordersLink.setVisible(!corrupted && booking);
}
} else if(event == Event.CLOSE_EVENT) {
doClose(ureq);
}
} else if(descriptionCtrl == source) {
if(event == Event.CHANGED_EVENT) {
refreshRepositoryEntry(descriptionCtrl.getEntry());
} else if(event == Event.CLOSE_EVENT) {
doClose(ureq);
}
} else if(detailsCtrl == source) {
if(event instanceof LeavingEvent) {
doClose(ureq);
} else if(event == Event.DONE_EVENT) {
popToRoot(ureq);
cleanUp();
if(getRuntimeController() == null) {
doRun(ureq, reSecurity);
}
}
} else if(confirmDeleteCtrl == source) {
if(event == Event.CANCELLED_EVENT) {
cmc.deactivate();
removeAsListenerAndDispose(confirmDeleteCtrl);
removeAsListenerAndDispose(cmc);
confirmDeleteCtrl = null;
cmc = null;
} else if (event == Event.DONE_EVENT || event == Event.CHANGED_EVENT) {
cmc.deactivate();
EntryChangedEvent e = new EntryChangedEvent(getRepositoryEntry(), getIdentity(), Change.deleted, "runtime");
ureq.getUserSession().getSingleUserEventCenter().fireEventToListenersOf(e, RepositoryService.REPOSITORY_EVENT_ORES);
doClose(ureq);
cleanUp();
}
} else if(copyCtrl == source) {
cmc.deactivate();
if (event == Event.DONE_EVENT) {
RepositoryEntryRef copy = copyCtrl.getCopiedEntry();
String businessPath = "[RepositoryEntry:" + copy.getKey() + "][EditDescription:0]";
NewControllerFactory.getInstance().launch(businessPath, ureq, getWindowControl());
EntryChangedEvent e = new EntryChangedEvent(getRepositoryEntry(), getIdentity(), Change.added, "runtime");
ureq.getUserSession().getSingleUserEventCenter().fireEventToListenersOf(e, RepositoryService.REPOSITORY_EVENT_ORES);
}
cleanUp();
}
}
protected RepositoryEntryRuntimeController popToRoot(UserRequest ureq) {
toolbarPanel.popUpToRootController(ureq);
return this;
}
protected void cleanUp() {
removeAsListenerAndDispose(membersEditController);
removeAsListenerAndDispose(confirmDeleteCtrl);
removeAsListenerAndDispose(accessController);
removeAsListenerAndDispose(descriptionCtrl);
removeAsListenerAndDispose(catalogCtlr);
removeAsListenerAndDispose(detailsCtrl);
removeAsListenerAndDispose(editorCtrl);
removeAsListenerAndDispose(ordersCtlr);
removeAsListenerAndDispose(copyCtrl);
removeAsListenerAndDispose(cmc);
membersEditController = null;
confirmDeleteCtrl = null;
accessController = null;
descriptionCtrl = null;
catalogCtlr = null;
detailsCtrl = null;
editorCtrl = null;
ordersCtlr = null;
copyCtrl = null;
cmc = null;
}
/**
* Pop to root, clean up, and push
* @param ureq
* @param name
* @param controller
*/
protected <T extends Controller> T pushController(UserRequest ureq, String name, T controller) {
popToRoot(ureq).cleanUp();
toolbarPanel.pushController(name, controller);
if(controller instanceof ToolbarAware) {
((ToolbarAware)controller).initToolbar();
}
return controller;
}
/**
* Open the editor for all repository entry metadata, access control...
* @param ureq
*/
protected void doAccess(UserRequest ureq) {
WindowControl bwControl = getSubWindowControl("Access");
RepositoryEntry refreshedEntry = loadRepositoryEntry();
AuthoringEditAccessController ctrl = new AuthoringEditAccessController(ureq, addToHistory(ureq, bwControl), refreshedEntry);
listenTo(ctrl);
accessCtrl = pushController(ureq, translate("tab.accesscontrol"), ctrl);
setActiveTool(accessLink);
currentToolCtr = accessCtrl;
}
protected void doPostSuccessfullAccess(UserRequest ureq) {
reSecurity = repositoryManager.isAllowed(ureq, getRepositoryEntry());
launchContent(ureq, reSecurity);
initToolbar();
cleanUp();
}
protected final void doClose(UserRequest ureq) {
// Now try to go back to place that is attacked to (optional) root back business path
getWindowControl().getWindowBackOffice().getWindow().getDTabs()
.closeDTab(ureq, re.getOlatResource(), launchedFromPoint);
}
protected void doEdit(UserRequest ureq) {
if(!reSecurity.isEntryAdmin()) return;
WindowControl bwControl = getSubWindowControl("Editor");
Controller ctrl = handler.createEditorController(re, ureq, addToHistory(ureq, bwControl), toolbarPanel);
if(ctrl != null) {
listenTo(ctrl);
editorCtrl = pushController(ureq, translate("resource.editor"), ctrl);
currentToolCtr = editorCtrl;
setActiveTool(editLink);
}
}
protected void doDetails(UserRequest ureq) {
WindowControl bwControl = getSubWindowControl("Infos");
RepositoryEntryDetailsController ctrl = new RepositoryEntryDetailsController(ureq, addToHistory(ureq, bwControl), re, true);
listenTo(ctrl);
detailsCtrl = pushController(ureq, translate("details.header"), ctrl);
currentToolCtr = detailsCtrl;
}
/**
* Open the editor for all repository entry metadata, access control...
* @param ureq
*/
protected void doEditSettings(UserRequest ureq) {
if(!reSecurity.isEntryAdmin()) return;
WindowControl bwControl = getSubWindowControl("Settings");
RepositoryEntry refreshedEntry = loadRepositoryEntry();
RepositoryEditDescriptionController ctrl
= new RepositoryEditDescriptionController(ureq, addToHistory(ureq, bwControl), refreshedEntry);
listenTo(ctrl);
descriptionCtrl = pushController(ureq, translate("settings.editor"), ctrl);
currentToolCtr = descriptionCtrl;
setActiveTool(editDescriptionLink);
}
/**
* Internal helper to initiate the add to catalog workflow
* @param ureq
*/
protected void doCatalog(UserRequest ureq) {
if(!reSecurity.isEntryAdmin()) return;
popToRoot(ureq).cleanUp();
WindowControl bwControl = getSubWindowControl("Catalog");
catalogCtlr = new CatalogSettingsController(ureq, addToHistory(ureq, bwControl), toolbarPanel, re);
listenTo(catalogCtlr);
catalogCtlr.initToolbar();
currentToolCtr = catalogCtlr;
setActiveTool(catalogLink);
}
protected Activateable2 doMembers(UserRequest ureq) {
if(!reSecurity.isEntryAdmin()) return null;
WindowControl bwControl = getSubWindowControl("MembersMgmt");
RepositoryMembersController ctrl = new RepositoryMembersController(ureq, addToHistory(ureq, bwControl), toolbarPanel ,re);
listenTo(ctrl);
membersEditController = pushController(ureq, translate("details.members"), ctrl);
currentToolCtr = membersEditController;
setActiveTool(membersLink);
return membersEditController;
}
protected void doOrders(UserRequest ureq) {
if(!reSecurity.isEntryAdmin()) return;
WindowControl bwControl = getSubWindowControl("Booking");
OrdersAdminController ctrl = new OrdersAdminController(ureq, addToHistory(ureq, bwControl), toolbarPanel, re.getOlatResource());
listenTo(ctrl);
ordersCtlr = pushController(ureq, translate("details.orders"), ctrl);
currentToolCtr = ordersCtlr;
setActiveTool(ordersLink);
}
private void doRun(UserRequest ureq, RepositoryEntrySecurity security) {
if(ureq.getUserSession().getRoles().isOLATAdmin()) {
launchContent(ureq, security);
} else {
// guest are allowed to see resource with BARG
if(re.getAccess() == RepositoryEntry.ACC_USERS_GUESTS && ureq.getUserSession().getRoles().isGuestOnly()) {
launchContent(ureq, security);
} else {
AccessResult acResult = acService.isAccessible(re, getIdentity(), security.isMember(), false);
if(acResult.isAccessible()) {
launchContent(ureq, security);
} else if (re != null
&& !re.getRepositoryEntryStatus().isUnpublished()
&& !re.getRepositoryEntryStatus().isClosed()
&& acResult.getAvailableMethods().size() > 0) {
//try auto booking
ACResultAndSecurity autoResult = tryAutoBooking(ureq, acResult, security);
acResult = autoResult.getAcResult();
security = autoResult.getSecurity();
if(acResult.isAccessible()) {
launchContent(ureq, security);
} else {
accessController = new AccessListController(ureq, getWindowControl(), acResult.getAvailableMethods());
listenTo(accessController);
toolbarPanel.rootController(re.getDisplayname(), accessController);
}
} else {
Controller ctrl = new AccessRefusedController(ureq, getWindowControl());
listenTo(ctrl);
toolbarPanel.rootController(re.getDisplayname(), ctrl);
}
}
}
}
private ACResultAndSecurity tryAutoBooking(UserRequest ureq, AccessResult acResult, RepositoryEntrySecurity security) {
if(acResult.getAvailableMethods().size() == 1) {
OfferAccess offerAccess = acResult.getAvailableMethods().get(0);
if(offerAccess.getOffer().isAutoBooking() && !offerAccess.getMethod().isNeedUserInteraction()) {
acResult = acService.accessResource(getIdentity(), offerAccess, null);
if(acResult.isAccessible()) {
security = repositoryManager.isAllowed(ureq, re);
}
}
}
return new ACResultAndSecurity(acResult, security);
}
protected boolean doMark(UserRequest ureq) {
OLATResourceable item = OresHelper.clone(re);
if(markManager.isMarked(item, getIdentity(), null)) {
markManager.removeMark(item, getIdentity(), null);
EntryChangedEvent e = new EntryChangedEvent(getRepositoryEntry(), getIdentity(), Change.removeBookmark, "runtime");
ureq.getUserSession().getSingleUserEventCenter().fireEventToListenersOf(e, RepositoryService.REPOSITORY_EVENT_ORES);
return false;
} else {
String businessPath = "[RepositoryEntry:" + item.getResourceableId() + "]";
markManager.setMark(item, getIdentity(), null, businessPath);
EntryChangedEvent e = new EntryChangedEvent(getRepositoryEntry(), getIdentity(), Change.addBookmark, "runtime");
ureq.getUserSession().getSingleUserEventCenter().fireEventToListenersOf(e, RepositoryService.REPOSITORY_EVENT_ORES);
return true;
}
}
private void doCopy(UserRequest ureq) {
removeAsListenerAndDispose(cmc);
removeAsListenerAndDispose(copyCtrl);
copyCtrl = new CopyRepositoryEntryController(ureq, getWindowControl(), re);
listenTo(copyCtrl);
String title = translate("details.copy");
cmc = new CloseableModalController(getWindowControl(), translate("close"), copyCtrl.getInitialComponent(), true, title);
listenTo(cmc);
cmc.activate();
}
private void doDownload(UserRequest ureq) {
if (handler == null) {
StringBuilder sb = new StringBuilder(translate("error.download"));
sb.append(": No download handler for repository entry: ").append(
re.getKey());
showError(sb.toString());
return;
}
RepositoryEntry entry = repositoryService.loadByKey(re.getKey());
OLATResourceable ores = entry.getOlatResource();
if (ores == null) {
showError("error.download");
return;
}
boolean isAlreadyLocked = handler.isLocked(ores);
try {
lockResult = handler.acquireLock(ores, ureq.getIdentity());
if (lockResult == null
|| (lockResult != null && lockResult.isSuccess() && !isAlreadyLocked)) {
MediaResource mr = handler.getAsMediaResource(ores, false);
if (mr != null) {
repositoryService.incrementDownloadCounter(entry);
ureq.getDispatchResult().setResultingMediaResource(mr);
} else {
showError("error.export");
fireEvent(ureq, Event.FAILED_EVENT);
}
} else if (lockResult != null && lockResult.isSuccess()
&& isAlreadyLocked) {
String fullName = userManager.getUserDisplayName(lockResult
.getOwner());
showInfo("warning.course.alreadylocked.bySameUser", fullName);
lockResult = null; // invalid lock, it was already locked
} else {
String fullName = userManager.getUserDisplayName(lockResult
.getOwner());
showInfo("warning.course.alreadylocked", fullName);
}
} finally {
if ((lockResult != null && lockResult.isSuccess() && !isAlreadyLocked)) {
handler.releaseLock(lockResult);
lockResult = null;
}
}
}
private void doDelete(UserRequest ureq) {
if (!reSecurity.isEntryAdmin()) {
throw new OLATSecurityException("Trying to delete, but not allowed: user = " + ureq.getIdentity());
}
List<RepositoryEntry> entryToDelete = Collections.singletonList(getRepositoryEntry());
confirmDeleteCtrl = new ConfirmDeleteSoftlyController(ureq, getWindowControl(), entryToDelete, false);
listenTo(confirmDeleteCtrl);
String title = translate("del.header", re.getDisplayname());
cmc = new CloseableModalController(getWindowControl(), "close", confirmDeleteCtrl.getInitialComponent(), true, title);
listenTo(cmc);
cmc.activate();
}
protected void launchContent(UserRequest ureq, RepositoryEntrySecurity security) {
if(corrupted) {
runtimeController = new CorruptedCourseController(ureq, getWindowControl());
listenTo(runtimeController);
toolbarPanel.rootController(re.getDisplayname(), runtimeController);
} else if(security.canLaunch()) {
removeAsListenerAndDispose(runtimeController);
runtimeController = runtimeControllerCreator.create(ureq, getWindowControl(), toolbarPanel, re, reSecurity, assessmentMode);
listenTo(runtimeController);
toolbarPanel.rootController(re.getDisplayname(), runtimeController);
if(!launchDateUpdated.getAndSet(true)) {
userCourseInfoMgr.updateUserCourseInformations(re.getOlatResource(), getIdentity());
}
} else {
runtimeController = new AccessRefusedController(ureq, getWindowControl());
listenTo(runtimeController);
toolbarPanel.rootController(re.getDisplayname(), runtimeController);
}
}
protected void disposeRuntimeController() {
if(runtimeController != null) {
removeAsListenerAndDispose(runtimeController);
runtimeController = null;
}
}
public interface RuntimeControllerCreator {
public Controller create(UserRequest ureq, WindowControl wControl, TooledStackedPanel toolbarPanel,
RepositoryEntry entry, RepositoryEntrySecurity reSecurity, AssessmentMode mode);
}
public interface ToolbarAware {
public void initToolbar();
}
private static class ACResultAndSecurity {
private final AccessResult acResult;
private final RepositoryEntrySecurity security;
public ACResultAndSecurity(AccessResult acResult, RepositoryEntrySecurity security) {
this.acResult = acResult;
this.security = security;
}
public AccessResult getAcResult() {
return acResult;
}
public RepositoryEntrySecurity getSecurity() {
return security;
}
}
}