Skip to content
Snippets Groups Projects
CourseRuntimeController.java 98.3 KiB
Newer Older
/**
 * <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.course.run;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;

import org.olat.NewControllerFactory;
import org.olat.commons.calendar.CalendarModule;
import org.olat.commons.info.ui.InfoSecurityCallback;
import org.olat.core.CoreSpringFactory;
import org.olat.core.commons.controllers.linkchooser.CustomLinkTreeModel;
import org.olat.core.commons.fullWebApp.LayoutMain3ColsController;
import org.olat.core.commons.fullWebApp.popup.BaseFullWebappPopupLayoutFactory;
import org.olat.core.commons.modules.bc.FolderRunController;
import org.olat.core.commons.modules.glossary.GlossaryMainController;
import org.olat.core.commons.persistence.PersistenceHelper;
import org.olat.core.commons.services.mark.Mark;
import org.olat.core.gui.UserRequest;
import org.olat.core.gui.Windows;
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.link.LinkPopupSettings;
import org.olat.core.gui.components.stack.BreadcrumbedStackedPanel.BreadCrumb;
import org.olat.core.gui.components.stack.PopEvent;
import org.olat.core.gui.components.stack.TooledStackedPanel.Align;
import org.olat.core.gui.components.stack.VetoPopEvent;
import org.olat.core.gui.control.ChiefController;
import org.olat.core.gui.control.Controller;
import org.olat.core.gui.control.Event;
import org.olat.core.gui.control.VetoableCloseController;
import org.olat.core.gui.control.WindowControl;
import org.olat.core.gui.control.creator.ControllerCreator;
import org.olat.core.gui.control.generic.closablewrapper.CloseableCalloutWindowController;
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.dtabs.DTab;
import org.olat.core.gui.control.generic.dtabs.DTabs;
import org.olat.core.gui.control.generic.messages.MessageUIFactory;
import org.olat.core.gui.control.generic.popup.PopupBrowserWindow;
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.logging.OLATSecurityException;
import org.olat.core.logging.activity.ThreadLocalUserActivityLogger;
import org.olat.core.util.StringHelper;
import org.olat.core.util.coordinate.CoordinatorManager;
import org.olat.core.util.event.GenericEventListener;
import org.olat.core.util.event.MultiUserEvent;
import org.olat.core.util.mail.MailPackage;
import org.olat.core.util.mail.MailerResult;
import org.olat.core.util.prefs.Preferences;
import org.olat.core.util.resource.OresHelper;
import org.olat.core.util.tree.TreeVisitor;
import org.olat.core.util.vfs.NamedContainerImpl;
import org.olat.core.util.vfs.VFSContainer;
import org.olat.course.CourseFactory;
import org.olat.course.CourseModule;
import org.olat.course.ICourse;
import org.olat.course.archiver.ArchiverMainController;
import org.olat.course.archiver.FullAccessArchiverCallback;
import org.olat.course.area.CourseAreasController;
import org.olat.course.assessment.AssessmentModule;
import org.olat.course.assessment.ui.mode.AssessmentModeListController;
import org.olat.course.assessment.ui.mode.AssessmentModeSecurityCallback;
import org.olat.course.assessment.ui.mode.AssessmentModeSecurityCallbackFactory;
import org.olat.course.assessment.ui.tool.AssessmentToolController;
import org.olat.course.certificate.ui.CertificateAndEfficiencyStatementController;
import org.olat.course.config.CourseConfig;
import org.olat.course.config.CourseConfigEvent;
import org.olat.course.config.ui.CourseSettingsController;
import org.olat.course.db.CourseDBManager;
import org.olat.course.db.CustomDBMainController;
import org.olat.course.editor.EditorMainController;
import org.olat.course.groupsandrights.CourseGroupManager;
import org.olat.course.groupsandrights.CourseRights;
import org.olat.course.learningpath.LearningPathService;
import org.olat.course.learningpath.manager.LearningPathNodeAccessProvider;
import org.olat.course.learningpath.ui.LearningPathIdentityListController;
import org.olat.course.learningpath.ui.MyLearningPathController;
import org.olat.course.member.MembersManagementMainController;
import org.olat.course.nodeaccess.ui.UnsupportedCourseNodesController;
import org.olat.course.nodes.CourseNode;
import org.olat.course.nodes.ENCourseNode;
import org.olat.course.nodes.bc.CourseDocumentsController;
uhensler's avatar
uhensler committed
import org.olat.course.nodes.co.COToolController;
uhensler's avatar
uhensler committed
import org.olat.course.nodes.feed.blog.BlogToolController;
import org.olat.course.nodes.fo.FOToolController;
import org.olat.course.nodes.info.InfoCourseSecurityCallback;
import org.olat.course.nodes.info.InfoRunController;
import org.olat.course.nodes.members.MembersToolRunController;
uhensler's avatar
uhensler committed
import org.olat.course.nodes.wiki._content.WikiToolController;
import org.olat.course.reminder.ui.CourseRemindersController;
import org.olat.course.run.calendar.CourseCalendarController;
import org.olat.course.run.glossary.CourseGlossaryFactory;
import org.olat.course.run.glossary.CourseGlossaryToolLinkController;
import org.olat.course.run.userview.UserCourseEnvironment;
import org.olat.course.run.userview.UserCourseEnvironmentImpl;
import org.olat.course.statistic.StatisticCourseNodesController;
import org.olat.course.statistic.StatisticMainController;
import org.olat.course.statistic.StatisticType;
import org.olat.course.tree.CourseInternalLinkTreeModel;
import org.olat.group.BusinessGroup;
import org.olat.group.BusinessGroupRef;
import org.olat.group.BusinessGroupService;
import org.olat.group.ui.edit.BusinessGroupModifiedEvent;
import org.olat.instantMessaging.InstantMessagingModule;
import org.olat.instantMessaging.InstantMessagingService;
import org.olat.instantMessaging.OpenInstantMessageEvent;
import org.olat.modules.assessment.ui.AssessmentToolSecurityCallback;
import org.olat.modules.lecture.LectureModule;
import org.olat.modules.lecture.LectureService;
import org.olat.modules.lecture.RepositoryEntryLectureConfiguration;
import org.olat.modules.lecture.ui.LectureRepositoryAdminController;
import org.olat.modules.lecture.ui.LecturesSecurityCallback;
import org.olat.modules.lecture.ui.LecturesSecurityCallbackFactory;
import org.olat.modules.lecture.ui.TeacherOverviewController;
import org.olat.modules.reminder.ReminderModule;
import org.olat.note.NoteController;
import org.olat.repository.LeavingStatusList;
import org.olat.repository.RepositoryEntry;
import org.olat.repository.RepositoryEntryManagedFlag;
import org.olat.repository.RepositoryEntrySecurity;
import org.olat.repository.RepositoryEntryStatusEnum;
import org.olat.repository.RepositoryManager;
import org.olat.repository.controllers.EntryChangedEvent;
import org.olat.repository.ui.RepositoryEntryLifeCycleChangeController;
import org.olat.repository.ui.RepositoryEntryRuntimeController;
import org.olat.resource.OLATResource;
import org.olat.search.SearchModule;
import org.olat.search.SearchServiceUIFactory;
import org.olat.search.SearchServiceUIFactory.DisplayOption;
import org.olat.search.service.QuickSearchEvent;
import org.olat.search.ui.SearchInputController;
import org.olat.util.logging.activity.LoggingResourceable;
import org.springframework.beans.factory.annotation.Autowired;

/**
 * 
 * Initial date: 20.08.2014<br>
 * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
 *
 */
public class CourseRuntimeController extends RepositoryEntryRuntimeController implements GenericEventListener, VetoableCloseController  {
	
	private static final String JOINED = "joined";
	private static final String LEFT   = "left";
	private static final String CMD_START_GROUP_PREFIX = "cmd.group.start.ident.";
	
	private Delayed delayedClose;
	//tools
	private Link folderLink,
		courseStatisticLink, surveyStatisticLink, testStatisticLink,
		areaLink, dbLink, convertLearningPathLink,
		lecturesAdminLink, reminderLink,
		assessmentModeLink, lifeCycleChangeLink,
		efficiencyStatementsLink, noteLink, leaveLink,
		// course tools
		learningPathLink, learningPathsLink, calendarLink, chatLink, participantListLink, participantInfoLink,
uhensler's avatar
uhensler committed
		blogLink, wikiLink, forumLink, documentsLink, emailLink, searchLink,
		openGlossaryLink, enableGlossaryLink, lecturesLink;
	private Link currentUserCountLink;
	private Dropdown myCourse, glossary;

	private CloseableModalController cmc;
uhensler's avatar
uhensler committed
	private COToolController emailCtrl;
uhensler's avatar
uhensler committed
	private BlogToolController blogCtrl;
uhensler's avatar
uhensler committed
	private WikiToolController wikiCtrl;
	private FOToolController forumCtrl;
	private CourseDocumentsController documentsCtrl;
	private CourseAreasController areasCtrl;
	private ConfirmLeaveController leaveDialogBox;
	private ArchiverMainController archiverCtrl;
	private CustomDBMainController databasesCtrl;
	private FolderRunController courseFolderCtrl;
	private InfoRunController participatInfoCtrl;
	private SearchInputController searchController;
	private StatisticMainController statisticsCtrl;
	private CourseRemindersController remindersCtrl;
	private TeacherOverviewController lecturesCtrl;
	private AssessmentToolController assessmentToolCtr;
uhensler's avatar
uhensler committed
	private MembersToolRunController participatListCtrl;
	private MembersManagementMainController membersCtrl;
	private StatisticCourseNodesController statsToolCtr;
	private AssessmentModeListController assessmentModeCtrl;
	private LectureRepositoryAdminController lecturesAdminCtrl;
	private UnsupportedCourseNodesController unsupportedCourseNodesCtrl;
	private CloseableCalloutWindowController courseSearchCalloutCtr;
	protected RepositoryEntryLifeCycleChangeController lifeCycleChangeCtr;

	private Map<String, Boolean> courseRightsCache;

	@Autowired
	private CourseModule courseModule;
	private LectureModule lectureModule;
	@Autowired
	private LectureService lectureService;
	@Autowired
	private ReminderModule reminderModule;
	@Autowired
	private CalendarModule calendarModule;
	@Autowired
	private CoordinatorManager coordinatorManager;
	@Autowired
	private BusinessGroupService businessGroupService;
	@Autowired
	private AssessmentModule assessmentModule;
	@Autowired
	private InstantMessagingModule imModule;
	@Autowired
	private CourseDBManager courseDBManager;
	@Autowired
	private SearchModule searchModule;
	@Autowired
	private LearningPathService learningPathService;
	
	public CourseRuntimeController(UserRequest ureq, WindowControl wControl,
			RepositoryEntry re, RepositoryEntrySecurity reSecurity, RuntimeControllerCreator runtimeControllerCreator,
			boolean offerBookmark, boolean showCourseConfigLink) {
		super(ureq, wControl, re, reSecurity, runtimeControllerCreator, offerBookmark, showCourseConfigLink);
			ICourse course = CourseFactory.loadCourse(getRepositoryEntry());
			addLoggingResourceable(LoggingResourceable.wrap(course));
			coordinatorManager.getCoordinator().getEventBus().registerFor(this, getIdentity(), getOlatResourceable());
			// - group modification events
			coordinatorManager.getCoordinator().getEventBus().registerFor(this, getIdentity(), getRepositoryEntry());
			
			if (courseModule.displayParticipantsCount()) {
				coordinatorManager.getCoordinator().getEventBus().fireEventToListenersOf(new MultiUserEvent(JOINED), getOlatResourceable());
				updateCurrentUserCount();
			}
			
			if(enableGlossaryLink != null) {
				Preferences prefs = ureq.getUserSession().getGuiPreferences();
				String guiPrefsKey = CourseGlossaryFactory.createGuiPrefsKey(course);
				Boolean state = (Boolean) prefs.get(CourseGlossaryToolLinkController.class, guiPrefsKey);
				setGlossaryLinkTitle(ureq, state);
			}
		}
	}

	@Override
	protected boolean isCorrupted(RepositoryEntry entry) {
		try {
			return false;
		} catch (Exception e) {
			return true;
		}
	}

	@Override
	protected void onSecurityReloaded(UserRequest ureq) {
		loadRights();
		
		RunMainController runMainController = getRunMainController();
		if(runMainController != null) {
			runMainController.reloadGroupMemberships(reSecurity);
			runMainController.updateCurrentCourseNode(ureq);
		}
	}

	private void loadRights() {
		ICourse course = CourseFactory.loadCourse(getRepositoryEntry());
		CourseGroupManager cgm = course.getCourseEnvironment().getCourseGroupManager();
		// 3) all other rights are defined in the groupmanagement using the learning
		// group rights
		UserCourseEnvironmentImpl uce = getUserCourseEnvironment();
		if(uce != null) {
			uce.setUserRoles(reSecurity.isEntryAdmin() || reSecurity.isPrincipal() || reSecurity.isMasterCoach(), reSecurity.isCoach(), reSecurity.isParticipant());
			if(reSecurity.isOnlyPrincipal() || reSecurity.isOnlyMasterCoach()) {
				uce.setCourseReadOnly(Boolean.TRUE);
			} else if(reSecurity.isReadOnly()) {
				if(overrideReadOnly) {
					uce.setCourseReadOnly(Boolean.FALSE);
				} else {
					uce.setCourseReadOnly(Boolean.TRUE);
				}
			} else {
				uce.setCourseReadOnly(Boolean.FALSE);
			}
			uce.getScoreAccounting().evaluateAll(true);
		courseRightsCache = new HashMap<>();
		if(!reSecurity.isEntryAdmin() && !isGuestOnly) {
			List<String> rights = cgm.getRights(getIdentity());
			courseRightsCache.put(CourseRights.RIGHT_GROUPMANAGEMENT, Boolean.valueOf(rights.contains(CourseRights.RIGHT_GROUPMANAGEMENT)));
			courseRightsCache.put(CourseRights.RIGHT_MEMBERMANAGEMENT, Boolean.valueOf(rights.contains(CourseRights.RIGHT_MEMBERMANAGEMENT)));
			courseRightsCache.put(CourseRights.RIGHT_COURSEEDITOR, Boolean.valueOf(rights.contains(CourseRights.RIGHT_COURSEEDITOR)));
			courseRightsCache.put(CourseRights.RIGHT_ARCHIVING, Boolean.valueOf(rights.contains(CourseRights.RIGHT_ARCHIVING)));
			courseRightsCache.put(CourseRights.RIGHT_ASSESSMENT, Boolean.valueOf(rights.contains(CourseRights.RIGHT_ASSESSMENT)));
			courseRightsCache.put(CourseRights.RIGHT_ASSESSMENT_MODE, Boolean.valueOf(rights.contains(CourseRights.RIGHT_ASSESSMENT_MODE)));
			courseRightsCache.put(CourseRights.RIGHT_GLOSSARY, Boolean.valueOf(rights.contains(CourseRights.RIGHT_GLOSSARY)));
			courseRightsCache.put(CourseRights.RIGHT_STATISTICS, Boolean.valueOf(rights.contains(CourseRights.RIGHT_STATISTICS)));
			courseRightsCache.put(CourseRights.RIGHT_DB, Boolean.valueOf(rights.contains(CourseRights.RIGHT_DB)));
	}

	private boolean hasCourseRight(String right) {
		Boolean bool = courseRightsCache.get(right);
		return bool != null && bool.booleanValue();
	}
	
	private UserCourseEnvironmentImpl getUserCourseEnvironment() {
		RunMainController run = getRunMainController();
		UserCourseEnvironmentImpl uce = run == null ? null : run.getUce();
		if(uce != null && uce.isCourseReadOnly() && overrideReadOnly) {
			uce.setCourseReadOnly(Boolean.FALSE);
		}
		return uce;
	/**
	 * Refresh the cached repository entry of the course
	 * @return
	 */
	@Override
	protected RepositoryEntry loadRepositoryEntry() {
		RepositoryEntry refreshedEntry = super.loadRepositoryEntry();
		ICourse course = CourseFactory.loadCourse(getRepositoryEntry());
		course.getCourseEnvironment().updateCourseEntry(refreshedEntry);
		return refreshedEntry;
	}
	
	/**
	 * Refresh the cached repository entry of the course
	 * @return
	 */
	@Override
	protected RepositoryEntry refreshRepositoryEntry(RepositoryEntry refreshedEntry) {
		ICourse course = CourseFactory.loadCourse(refreshedEntry);
		course.getCourseEnvironment().updateCourseEntry(refreshedEntry);
		return super.refreshRepositoryEntry(refreshedEntry);
	}

	private RunMainController getRunMainController() {
		return getRuntimeController() instanceof RunMainController ?
			(RunMainController)getRuntimeController() : null;
	}
	
	private CourseNode getCurrentCourseNode() {
		RunMainController run = getRunMainController();
		return run == null ? null : run.getCurrentCourseNode();
	}
	
	private boolean isInEditor() {
		RunMainController run = getRunMainController();
		return run != null && run.isInEditor();
	}
	
	private void setIsInEditor(boolean editor) {
		RunMainController run = getRunMainController();
		if(run != null) run.setInEditor(editor);
	}
	
	private void reloadGroupMemberships() {
		RunMainController run = getRunMainController();
		if(run != null) {
			run.reloadGroupMemberships(reSecurity);
		}
	}
	
	private void toolControllerDone(UserRequest ureq) {
		RunMainController run = getRunMainController();
		if(run != null) {
			addCustomCSS(ureq);
			run.toolCtrDone(ureq, reSecurity);
		}
	}
	
	private void setTextMarkingEnabled(boolean enable) {
		RunMainController run = getRunMainController();
		if(run != null) run.setTextMarkingEnabled(enable);
	}
	
	public void setCourseCloseEnabled(boolean enabled) {
		toolbarPanel.setShowCloseLink(true, enabled);
	}

	public void setToolControllerEnabled(boolean enabled) {
		toolbarPanel.setToolbarEnabled(enabled);
	}
	
	private void addCustomCSS(UserRequest ureq) {
		ICourse course = CourseFactory.loadCourse(getRepositoryEntry());
		CustomCSS customCSS = CourseFactory.getCustomCourseCss(ureq.getUserSession(), course.getCourseEnvironment());
		ChiefController cc = getWindowControl().getWindowBackOffice().getChiefController();
		if (cc != null) {
			if(customCSS == null) {
				cc.removeCurrentCustomCSSFromView();
			} else {
				cc.addCurrentCustomCSSToView(customCSS);
			}
		}
		setCustomCSS(customCSS);
	}
	
	private void removeCustomCSS() {
		ChiefController cc = getWindowControl().getWindowBackOffice().getChiefController();
		if (cc != null) {
			cc.removeCurrentCustomCSSFromView();
		}
		setCustomCSS(null);
		setCourseClosedMessage();
	protected void initToolbar(Dropdown toolsDropdown) {
		toolsDropdown.removeAllComponents();
		ICourse course = CourseFactory.loadCourse(getRepositoryEntry());
		if(!course.getCourseConfig().isToolbarEnabled() && !reSecurity.isEntryAdmin() && !reSecurity.isCoach()
				&& !hasCourseRight(CourseRights.RIGHT_COURSEEDITOR) && !hasCourseRight(CourseRights.RIGHT_MEMBERMANAGEMENT)
				&& !hasCourseRight(CourseRights.RIGHT_GROUPMANAGEMENT) && !hasCourseRight(CourseRights.RIGHT_ARCHIVING)
					&& !hasCourseRight(CourseRights.RIGHT_STATISTICS) && !hasCourseRight(CourseRights.RIGHT_DB)
					&& !hasCourseRight(CourseRights.RIGHT_ASSESSMENT) && !hasCourseRight(CourseRights.RIGHT_ASSESSMENT_MODE)) {
			toolbarPanel.setToolbarEnabled(false);
		} else {
			toolbarPanel.setToolbarEnabled(true);
		}
		// make bread crumb disappear if not enabled
		if (!course.getCourseConfig().isBreadCrumbEnabled() && !toolbarPanel.isToolbarEnabled()) {
			// disable if toolbar also not visible
			toolbarPanel.setBreadcrumbEnabled(false);
		initToolsMenu(toolsDropdown);
		initToolsMyCourse(course);
		initGeneralTools(course);
		
		RunMainController rmc = getRunMainController();
		if(rmc != null) {
		setCourseClosedMessage();
	private void setCourseClosedMessage() {
		UserCourseEnvironment userCourseEnv = getUserCourseEnvironment();
		if(userCourseEnv != null &&  getRepositoryEntry().getEntryStatus() == RepositoryEntryStatusEnum.closed) {
			toolbarPanel.setMessage(translate("course.closed"));
			toolbarPanel.setMessageCssClass("o_warning");
		} else {
			toolbarPanel.setMessage(null);
			toolbarPanel.setMessageComponent(null);
	protected void initToolsMenu(Dropdown toolsDropdown) {
		toolsDropdown.removeAllComponents();
		toolsDropdown.setDirty(true);
		
		if(!isAssessmentLock()) {
			ICourse course = CourseFactory.loadCourse(getRepositoryEntry());
			UserCourseEnvironmentImpl uce = getUserCourseEnvironment();
			
			initToolsMenuSettings(toolsDropdown);
			initToolsMenuEditor(toolsDropdown, uce);
			initToolsMenuRuntime(toolsDropdown, uce);
			initToolsMenuStatistics(toolsDropdown, course, uce);
			initToolsMenuEdition(toolsDropdown);
			initToolsMenuDelete(toolsDropdown);
		}
	}
	
	@Override
	protected void initToolsMenuSettings(Dropdown tools) {
		// 1) administrative tools
		if (reSecurity.isEntryAdmin() || reSecurity.isPrincipal() || reSecurity.isMasterCoach() || reSecurity.isCoach()
				|| hasCourseRight(CourseRights.RIGHT_COURSEEDITOR) || hasCourseRight(CourseRights.RIGHT_MEMBERMANAGEMENT)
				|| hasCourseRight(CourseRights.RIGHT_GROUPMANAGEMENT)) {
			tools.setElementCssClass("o_sel_course_tools");
			
			if(reSecurity.isEntryAdmin() || hasCourseRight(CourseRights.RIGHT_COURSEEDITOR)) {
				settingsLink = LinkFactory.createToolLink("settings", translate("details.settings"), this, "o_sel_repo_settings");
				settingsLink.setIconLeftCSS("o_icon o_icon-fw o_icon_settings");
				settingsLink.setElementCssClass("o_sel_course_settings");
				settingsLink.setUrl(BusinessControlFactory.getInstance()
						.getAuthenticatedURLFromBusinessPathStrings(businessPathEntry, "[Settings:0]"));
				tools.addComponent(settingsLink);
			if (reSecurity.isEntryAdmin() || reSecurity.isPrincipal() || reSecurity.isMasterCoach() || hasCourseRight(CourseRights.RIGHT_GROUPMANAGEMENT) || hasCourseRight(CourseRights.RIGHT_MEMBERMANAGEMENT)) {
				membersLink = LinkFactory.createToolLink("unifiedusermngt", translate("command.opensimplegroupmngt"), this, "o_icon_membersmanagement");
				membersLink.setUrl(BusinessControlFactory.getInstance()
						.getAuthenticatedURLFromBusinessPathStrings(businessPathEntry, "[MembersMgmt:0][Members:0][All:0]"));
				membersLink.setElementCssClass("o_sel_course_members");
				tools.addComponent(membersLink);
			}
			tools.addComponent(new Spacer("first"));
		}
	}
	
	private void initToolsMenuEditor(Dropdown tools, final UserCourseEnvironmentImpl uce) {
		if(uce == null) return;
		
		if (reSecurity.isEntryAdmin() || hasCourseRight(CourseRights.RIGHT_COURSEEDITOR)) {
			boolean managed = RepositoryEntryManagedFlag.isManaged(getRepositoryEntry(), RepositoryEntryManagedFlag.editcontent);
			boolean readOnly = uce.isCourseReadOnly();
			editLink = LinkFactory.createToolLink("edit.cmd", translate("command.openeditor"), this, "o_icon_courseeditor");
			editLink.setUrl(BusinessControlFactory.getInstance()
					.getAuthenticatedURLFromBusinessPathStrings(businessPathEntry, "[Editor:0]]"));
			editLink.setElementCssClass("o_sel_course_editor");
			editLink.setEnabled(!corrupted && !managed);
			editLink.setVisible(!readOnly);
			tools.addComponent(editLink);
		}
			
		if (reSecurity.isEntryAdmin() || reSecurity.isPrincipal() || reSecurity.isMasterCoach() || hasCourseRight(CourseRights.RIGHT_COURSEEDITOR)) {
			folderLink = LinkFactory.createToolLink("cfd", translate("command.coursefolder"), this, "o_icon_coursefolder");
			folderLink.setUrl(BusinessControlFactory.getInstance()
					.getAuthenticatedURLFromBusinessPathStrings(businessPathEntry, "[Coursefolder:0]]"));
			folderLink.setElementCssClass("o_sel_course_folder");
			tools.addComponent(folderLink);
			tools.addComponent(new Spacer(""));
		}
	}
	
	private void initToolsMenuRuntime(Dropdown tools, final UserCourseEnvironmentImpl uce) {
		boolean courseAuthorRight = reSecurity.isEntryAdmin() || hasCourseRight(CourseRights.RIGHT_COURSEEDITOR);
		if (courseAuthorRight || reSecurity.isPrincipal() || reSecurity.isMasterCoach() || reSecurity.isCoach()
				|| hasCourseRight(CourseRights.RIGHT_DB)
				|| hasCourseRight(CourseRights.RIGHT_ASSESSMENT) || hasCourseRight(CourseRights.RIGHT_ASSESSMENT_MODE)) {	

			tools.addComponent(new Spacer(""));
			
			if (reSecurity.isEntryAdmin() || reSecurity.isPrincipal() || reSecurity.isMasterCoach() || reSecurity.isCoach() || hasCourseRight(CourseRights.RIGHT_ASSESSMENT)) {
				assessmentLink = LinkFactory.createToolLink("assessment", translate("command.openassessment"), this, "o_icon_assessment_tool");
				assessmentLink.setUrl(BusinessControlFactory.getInstance()
						.getAuthenticatedURLFromBusinessPathStrings(businessPathEntry, "[assessmentToolv2:0]"));
				assessmentLink.setElementCssClass("o_sel_course_assessment_tool");
			if(lectureModule.isEnabled() && (courseAuthorRight || reSecurity.isPrincipal() || reSecurity.isMasterCoach()) && isLectureEnabled()) {
				lecturesAdminLink = LinkFactory.createToolLink("lectures.admin.cmd", translate("command.options.lectures.admin"), this, "o_icon_lecture");
				lecturesAdminLink.setUrl(BusinessControlFactory.getInstance()
						.getAuthenticatedURLFromBusinessPathStrings(businessPathEntry, "[LecturesAdmin:0][LectureBlocks:0]"));
				lecturesAdminLink.setElementCssClass("o_sel_course_lectures_admin");
				tools.addComponent(lecturesAdminLink);
			}
			
			if(reminderModule.isEnabled() && courseAuthorRight) {
				reminderLink = LinkFactory.createToolLink("reminders.cmd", translate("command.options.reminders"), this, "o_icon_reminder");
				reminderLink.setUrl(BusinessControlFactory.getInstance()
						.getAuthenticatedURLFromBusinessPathStrings(businessPathEntry, "[Reminders:0]"));
				reminderLink.setElementCssClass("o_sel_course_reminders");
				reminderLink.setVisible(!uce.isCourseReadOnly());
				tools.addComponent(reminderLink);
			if (courseAuthorRight || reSecurity.isPrincipal() || reSecurity.isMasterCoach() || hasCourseRight(CourseRights.RIGHT_ASSESSMENT_MODE)) {
				//course author right or the assessment mode access right 
				boolean managed = RepositoryEntryManagedFlag.isManaged(getRepositoryEntry(), RepositoryEntryManagedFlag.editcontent);
				assessmentModeLink = LinkFactory.createToolLink("assessment.mode.cmd", translate("command.assessment.mode"), this, "o_icon_assessment_mode");
				assessmentModeLink.setUrl(BusinessControlFactory.getInstance()
						.getAuthenticatedURLFromBusinessPathStrings(businessPathEntry, "[AssessmentMode:0]"));
				assessmentModeLink.setElementCssClass("o_sel_course_assessment_mode");
				assessmentModeLink.setEnabled(!managed);
				assessmentModeLink.setVisible(assessmentModule.isAssessmentModeEnabled() && !uce.isCourseReadOnly());
				tools.addComponent(assessmentModeLink);
			}

			if (reSecurity.isEntryAdmin() || hasCourseRight(CourseRights.RIGHT_COURSEEDITOR)) {
				areaLink = LinkFactory.createToolLink("careas", translate("command.courseareas"), this, "o_icon_courseareas");
				areaLink.setUrl(BusinessControlFactory.getInstance()
						.getAuthenticatedURLFromBusinessPathStrings(businessPathEntry, "[CourseAreas:0]"));
				areaLink.setElementCssClass("o_sel_course_areas");
				tools.addComponent(areaLink);
			}
			
			if (courseDBManager.isEnabled() && (reSecurity.isEntryAdmin() || hasCourseRight(CourseRights.RIGHT_DB))) {
				dbLink = LinkFactory.createToolLink("customDb",translate("command.opendb"), this, "o_icon_coursedb");
				tools.addComponent(dbLink);
			}
		}
	}
	
	private boolean isLectureEnabled() {
		RepositoryEntryLectureConfiguration lectureConfig = lectureService.getRepositoryEntryLectureConfiguration(getRepositoryEntry());
		return lectureConfig != null && lectureConfig.isLectureEnabled();
	}
	
	private void initToolsMenuStatistics(Dropdown tools, ICourse course, final UserCourseEnvironmentImpl uce) {
		if (reSecurity.isEntryAdmin() || reSecurity.isPrincipal() || reSecurity.isMasterCoach() || reSecurity.isCoach()
				|| hasCourseRight(CourseRights.RIGHT_ARCHIVING) || hasCourseRight(CourseRights.RIGHT_STATISTICS)) {	

			tools.addComponent(new Spacer(""));
			
			if (reSecurity.isEntryAdmin() || reSecurity.isPrincipal() || reSecurity.isMasterCoach() || hasCourseRight(CourseRights.RIGHT_STATISTICS)) {
				courseStatisticLink = LinkFactory.createToolLink("statistic",translate("command.openstatistic"), this, "o_icon_statistics_tool");
				courseStatisticLink.setUrl(BusinessControlFactory.getInstance()
						.getAuthenticatedURLFromBusinessPathStrings(businessPathEntry, "[CourseStatistics:0]"));
				tools.addComponent(courseStatisticLink);
			}
			if (uce != null && (reSecurity.isEntryAdmin() || reSecurity.isPrincipal() || reSecurity.isMasterCoach() || reSecurity.isCoach() || hasCourseRight(CourseRights.RIGHT_STATISTICS))) {
				final AtomicInteger testNodes = new AtomicInteger();
				final AtomicInteger surveyNodes = new AtomicInteger();
				new TreeVisitor(node -> {
					if(((CourseNode)node).isStatisticNodeResultAvailable(uce, StatisticType.TEST)) {
						testNodes.incrementAndGet();
					} else if(((CourseNode)node).isStatisticNodeResultAvailable(uce, StatisticType.SURVEY)) {
						surveyNodes.incrementAndGet();
					}
				}, course.getRunStructure().getRootNode(), true).visitAll();
				if(testNodes.intValue() > 0) {
					testStatisticLink = LinkFactory.createToolLink("qtistatistic", translate("command.openteststatistic"), this, "o_icon_statistics_tool");
					testStatisticLink.setUrl(BusinessControlFactory.getInstance()
							.getAuthenticatedURLFromBusinessPathStrings(businessPathEntry, "[TestStatistics:0]"));
					tools.addComponent(testStatisticLink);
				}
				
				if(surveyNodes.intValue() > 0) {
					surveyStatisticLink = LinkFactory.createToolLink("qtistatistic", translate("command.opensurveystatistic"), this, "o_icon_statistics_tool");
					surveyStatisticLink.setUrl(BusinessControlFactory.getInstance()
							.getAuthenticatedURLFromBusinessPathStrings(businessPathEntry, "[SurveyStatistics:0]"));
					tools.addComponent(surveyStatisticLink);
				}
			}

			if (reSecurity.isEntryAdmin() || hasCourseRight(CourseRights.RIGHT_ARCHIVING)) {
				archiverLink = LinkFactory.createToolLink("archiver", translate("command.openarchiver"), this, "o_icon_archive_tool");
				archiverLink.setUrl(BusinessControlFactory.getInstance()
						.getAuthenticatedURLFromBusinessPathStrings(businessPathEntry, "[Archives:0]"));
				tools.addComponent(archiverLink);
			}
			
			ordersLink = LinkFactory.createToolLink("bookings", translate("details.orders"), this, "o_sel_repo_booking");
			ordersLink.setIconLeftCSS("o_icon o_icon-fw o_icon_booking");
			ordersLink.setElementCssClass("o_sel_course_ac_tool");
			boolean booking = acService.isResourceAccessControled(getRepositoryEntry().getOlatResource(), null);
			ordersLink.setVisible(!corrupted && booking);
			tools.addComponent(ordersLink);
		}
	}
	
	@Override
	protected void initToolsMenuEdition(Dropdown toolsDropdown) {
		super.initToolsMenuEdition(toolsDropdown);
		if (copyLink != null) {
			ICourse course = CourseFactory.loadCourse(getRepositoryEntry());
			if (course != null && !LearningPathNodeAccessProvider.TYPE.equals(course.getCourseConfig().getNodeAccessType().getType())) {
				Integer index = toolsDropdown.getComponentIndex(copyLink);
				if(index != null) {
					convertLearningPathLink = LinkFactory.createToolLink("convert.course.learning.path",
							translate("tools.convert.course.learning.path"), this, "o_icon o_icon-fw  o_icon_learning_path");
					toolsDropdown.addComponent(index.intValue() + 1, convertLearningPathLink);
	protected void initToolsMenuDelete(Dropdown settingsDropdown) {
		RepositoryEntry re = getRepositoryEntry();
		boolean closeManged = RepositoryEntryManagedFlag.isManaged(re, RepositoryEntryManagedFlag.close);
		
		if(reSecurity.isEntryAdmin()) {
			boolean deleteManaged = RepositoryEntryManagedFlag.isManaged(re, RepositoryEntryManagedFlag.delete);
			if(settingsDropdown.size() > 0 && !deleteManaged) {
				settingsDropdown.addComponent(new Spacer("close-delete"));
			}

			if(!closeManged || !deleteManaged) {
				// If a resource is closable (currently only course) and
				// deletable (currently all resources) we offer those two
				// actions in a separate page, unless both are managed
				// operations. In that case we don't show anything at all.				
				// If only one of the two actions are managed, we go to the
				// separate page as well and show only the relevant action
				// there.
				lifeCycleChangeLink = LinkFactory.createToolLink("lifeCycleChange", translate("details.lifecycle.change"), this, "o_icon o_icon-fw o_icon_lifecycle");
				settingsDropdown.addComponent(lifeCycleChangeLink);
			} else {				
				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);
				}
			}
		}
	}

	private void initToolsMyCourse(ICourse course) {
		boolean assessmentLock = isAssessmentLock();
		UserCourseEnvironment userCourseEnv = getUserCourseEnvironment();

		myCourse = new Dropdown("myCourse", "header.tools.mycourse", false, getTranslator());
		myCourse.setElementCssClass("dropdown-menu-right");
		myCourse.setIconCSS("o_icon o_icon_user");

		// Personal tools on right side
		CourseConfig cc = course.getCourseConfig();
		if ((cc.isEfficencyStatementEnabled() || cc.isCertificateEnabled()) && !isGuestOnly && !assessmentLock
				&& userCourseEnv != null && userCourseEnv.isParticipant()) {
			efficiencyStatementsLink = LinkFactory.createToolLink("efficiencystatement",
					translate("command.efficiencystatement"), this, "o_icon_certificate");
			myCourse.addComponent(efficiencyStatementsLink);
		if (!isGuestOnly && !assessmentLock) {
			noteLink = LinkFactory.createToolLink("personalnote",translate("command.personalnote"), this, "o_icon_notes");
			noteLink.setPopup(new LinkPopupSettings(750, 550, "notes"));
			myCourse.addComponent(noteLink);
		}
		
		if (allowBookmark && !isGuestOnly) {
			boolean marked = markManager.isMarked(getRepositoryEntry(), getIdentity(), null);
			String css = marked ? Mark.MARK_CSS_ICON : Mark.MARK_ADD_CSS_ICON;
			bookmarkLink = LinkFactory.createToolLink("bookmark",translate("command.bookmark"), this, css);
			bookmarkLink.setTitle(translate(marked ? "details.bookmark.remove" : "details.bookmark"));
			myCourse.addComponent(bookmarkLink);
		}

		if (userCourseEnv != null) {
			if(myCourse.size() > 0 && (!userCourseEnv.getCoachedGroups().isEmpty() || !userCourseEnv.getParticipatingGroups().isEmpty() || !userCourseEnv.getWaitingLists().isEmpty())) {
				myCourse.addComponent(new Spacer(""));
			}
			
			// 2) add coached groups
			if (!userCourseEnv.getCoachedGroups().isEmpty()) {
				for (BusinessGroup group: userCourseEnv.getCoachedGroups()) {
					Link link = LinkFactory.createToolLink(CMD_START_GROUP_PREFIX + group.getKey(), "group", StringHelper.escapeHtml(group.getName()), this);
					link.setIconLeftCSS("o_icon o_icon-fw o_icon_group");
					link.setUserObject(group);
					link.setEnabled(!assessmentLock);
					myCourse.addComponent(link);
					
				}
			// 3) add participating groups
			if (!userCourseEnv.getParticipatingGroups().isEmpty()) {
				for (BusinessGroup group: userCourseEnv.getParticipatingGroups()) {
					Link link = LinkFactory.createToolLink(CMD_START_GROUP_PREFIX + group.getKey(), "group", StringHelper.escapeHtml(group.getName()), this);
					link.setIconLeftCSS("o_icon o_icon-fw o_icon_group");
					link.setUserObject(group);
					link.setEnabled(!assessmentLock);
					myCourse.addComponent(link);
				}
			// 5) add waiting-list groups
			if (!userCourseEnv.getWaitingLists().isEmpty()) {
				for (BusinessGroup group: userCourseEnv.getWaitingLists()) {
					int pos = businessGroupService.getPositionInWaitingListFor(getIdentity(), group);
					String name = StringHelper.escapeHtml(group.getName()) + " (" + pos + ")";
					Link link = LinkFactory.createToolLink(CMD_START_GROUP_PREFIX + group.getKey(), "group", name, this);
					link.setIconLeftCSS("o_icon o_icon-fw o_icon_group");
					link.setUserObject(group);
					link.setEnabled(false);
					myCourse.addComponent(link);
				}
			}
			
			if(repositoryService.isParticipantAllowedToLeave(getRepositoryEntry())
					&& !assessmentLock && !roles.isGuestOnly() && !userCourseEnv.isCourseReadOnly()
					&& isAllowedToLeave(userCourseEnv)) {
				leaveLink = LinkFactory.createToolLink("sign.out", "leave", translate("sign.out"), this);
				leaveLink.setIconLeftCSS("o_icon o_icon-fw o_icon_sign_out");
				myCourse.addComponent(new Spacer("leaving-space"));
				myCourse.addComponent(leaveLink);
		if(myCourse.size() > 0) {
			toolbarPanel.addTool(myCourse, Align.right);
		}
	}
	
	private boolean isAllowedToLeave(UserCourseEnvironment userCourseEnv) {
		if(!userCourseEnv.getParticipatingGroups().isEmpty()) {
			CourseNode rootNode = userCourseEnv.getCourseEnvironment().getRunStructure().getRootNode();
			OLATResource courseResource = userCourseEnv.getCourseEnvironment().getCourseGroupManager().getCourseResource();
			
			AtomicBoolean bool = new AtomicBoolean(false);
			new TreeVisitor(node -> {
				if(!bool.get() && node instanceof ENCourseNode) {
					try {
						ENCourseNode enNode = (ENCourseNode)node;
						boolean cancelEnrollEnabled = enNode.getModuleConfiguration().getBooleanSafe(ENCourseNode.CONF_CANCEL_ENROLL_ENABLED);
						if(!cancelEnrollEnabled && enNode.isUsedForEnrollment(userCourseEnv.getParticipatingGroups(), courseResource)) {
					} catch (Exception e) {
						logError("", e);
					}
				}
			}, rootNode, true).visitAll();

			if(bool.get()) {
				return false;// is in a enrollment group
			}
		}
		return (userCourseEnv.isParticipant() || !userCourseEnv.getParticipatingGroups().isEmpty());
	private void initGeneralTools(ICourse course) {
		boolean assessmentLock = isAssessmentLock();
		UserCourseEnvironment userCourseEnv = getUserCourseEnvironment();
		CourseConfig cc = course.getCourseConfig();
		if (!assessmentLock && showDetails) {
			detailsLink = LinkFactory.createToolLink("courseconfig",translate("command.courseconfig"), this, "o_icon_details");
			detailsLink.setUrl(BusinessControlFactory.getInstance()
					.getAuthenticatedURLFromBusinessPathStrings(businessPathEntry, "[Infos:0]"));
			toolbarPanel.addTool(detailsLink);
		if (!assessmentLock && !isGuestOnly
				&& LearningPathNodeAccessProvider.TYPE.equals(cc.getNodeAccessType().getType())) {
			learningPathLink = LinkFactory.createToolLink("learningPath", translate("command.learning.path") + "-LP", this, "o_icon_learning_path");
			learningPathLink.setUrl(BusinessControlFactory.getInstance()
					.getAuthenticatedURLFromBusinessPathStrings(businessPathEntry, "[LearningPath:0]"));
			toolbarPanel.addTool(learningPathLink);
			learningPathLink.setVisible(userCourseEnv != null && userCourseEnv.isParticipant());
		}
		
		if (!assessmentLock && !isGuestOnly
				&& LearningPathNodeAccessProvider.TYPE.equals(cc.getNodeAccessType().getType())) {
			learningPathsLink = LinkFactory.createToolLink("learningPaths", translate("command.learning.paths"), this, "o_icon_learning_path");
			learningPathsLink.setUrl(BusinessControlFactory.getInstance()
					.getAuthenticatedURLFromBusinessPathStrings(businessPathEntry, "[LearningPaths:0]"));
			toolbarPanel.addTool(learningPathsLink);
		}
		if (learningPathsLink != null) {
			learningPathsLink.setVisible(userCourseEnv != null && (userCourseEnv.isCoach() || userCourseEnv.isAdmin()));
		boolean calendarIsEnabled =  !assessmentLock && !isGuestOnly && calendarModule.isEnabled()
				&& calendarModule.isEnableCourseToolCalendar() && reSecurity.canLaunch();
		if (calendarIsEnabled && userCourseEnv != null) {
			calendarLink = LinkFactory.createToolLink("calendar",translate("command.calendar"), this, "o_icon_calendar");
			calendarLink.setPopup(new LinkPopupSettings(950, 750, "cal"));
			calendarLink.setVisible(cc.isCalendarEnabled());
			toolbarPanel.addTool(calendarLink);
		}
		
		if(!assessmentLock && isLecturesLinkEnabled()) {
			lecturesLink = LinkFactory.createToolLink("command.lectures", translate("command.lectures"), this, "o_icon_lecture");
			lecturesLink.setUrl(BusinessControlFactory.getInstance()
					.getAuthenticatedURLFromBusinessPathStrings(businessPathEntry, "[Lectures:0]"));
			toolbarPanel.addTool(lecturesLink);
		}
		
		if(!assessmentLock && !isGuestOnly && userCourseEnv != null) {
			participantListLink = LinkFactory.createToolLink("participantlist", translate("command.participant.list"), this, "o_cmembers_icon");
			participantListLink.setUrl(BusinessControlFactory.getInstance()
					.getAuthenticatedURLFromBusinessPathStrings(businessPathEntry, "[ParticipantList:0]"));
			participantListLink.setVisible(cc.isParticipantListEnabled());
			toolbarPanel.addTool(participantListLink);
		}
		if(!assessmentLock && userCourseEnv != null) {
			participantInfoLink = LinkFactory.createToolLink("participantinfo", translate("command.participant.info"), this, "o_infomsg_icon");
			participantInfoLink.setUrl(BusinessControlFactory.getInstance()
					.getAuthenticatedURLFromBusinessPathStrings(businessPathEntry, "[ParticipantInfos:0]"));
			participantInfoLink.setVisible(cc.isParticipantInfoEnabled());
			toolbarPanel.addTool(participantInfoLink);
		}
		
		if(!assessmentLock && !isGuestOnly && userCourseEnv != null && !userCourseEnv.isCourseReadOnly()) {
uhensler's avatar
uhensler committed
			emailLink = LinkFactory.createToolLink("email", translate("command.email"), this, "o_co_icon");
			emailLink.setUrl(BusinessControlFactory.getInstance()
					.getAuthenticatedURLFromBusinessPathStrings(businessPathEntry, "[email:0]"));
			emailLink.setVisible(cc.isEmailEnabled());
uhensler's avatar
uhensler committed
			toolbarPanel.addTool(emailLink);
		}
		
		if(!assessmentLock && userCourseEnv != null) {
uhensler's avatar
uhensler committed
			blogLink = LinkFactory.createToolLink("blog", translate("command.blog"), this, "o_blog_icon");
			blogLink.setUrl(BusinessControlFactory.getInstance()
					.getAuthenticatedURLFromBusinessPathStrings(businessPathEntry, "[blog:0]"));
uhensler's avatar
uhensler committed
			blogLink.setVisible(cc.isBlogEnabled());
			toolbarPanel.addTool(blogLink);
		}
		
		if(!assessmentLock && userCourseEnv != null) {
uhensler's avatar
uhensler committed
			wikiLink = LinkFactory.createToolLink("wiki", translate("command.wiki"), this, "o_wiki_icon");
			wikiLink.setUrl(BusinessControlFactory.getInstance()
					.getAuthenticatedURLFromBusinessPathStrings(businessPathEntry, "[wiki:0]"));
uhensler's avatar
uhensler committed
			wikiLink.setVisible(cc.isWikiEnabled());
			toolbarPanel.addTool(wikiLink);
		}
		
		if(!assessmentLock && userCourseEnv != null) {
			forumLink = LinkFactory.createToolLink("forum", translate("command.forum"), this, "o_fo_icon");
			forumLink.setUrl(BusinessControlFactory.getInstance()
					.getAuthenticatedURLFromBusinessPathStrings(businessPathEntry, "[forum:0]"));
			forumLink.setVisible(cc.isForumEnabled());
			toolbarPanel.addTool(forumLink);
		}
		
		if(!assessmentLock && userCourseEnv != null) {
			documentsLink = LinkFactory.createToolLink("documents", translate("command.documents"), this, "o_bc_icon");
			documentsLink.setUrl(BusinessControlFactory.getInstance()
					.getAuthenticatedURLFromBusinessPathStrings(businessPathEntry, "[documents:0]"));
			documentsLink.setVisible(cc.isDocumentsEnabled());
			toolbarPanel.addTool(documentsLink);
		}
		
		if(!assessmentLock) {
			glossary = new Dropdown("glossary", "command.glossary", false, getTranslator());
			glossary.setIconCSS("o_icon o_FileResource-GLOSSARY_icon");
			glossary.setVisible(cc.hasGlossary() && cc.isGlossaryEnabled());
	
			openGlossaryLink = LinkFactory.createToolLink("command.glossary.open", translate("command.glossary.open"), this);
			openGlossaryLink.setPopup(new LinkPopupSettings(950, 750, "gloss"));
			glossary.addComponent(openGlossaryLink);
	
			enableGlossaryLink = LinkFactory.createToolLink("command.glossary.on.off", translate("command.glossary.on.alt"), this);
			glossary.addComponent(enableGlossaryLink);
			toolbarPanel.addTool(glossary);
		}
		
		//add group chat to toolbox
		boolean chatIsEnabled = !assessmentLock && !isGuestOnly && imModule.isEnabled()
				&& imModule.isCourseEnabled() && reSecurity.canLaunch();
		if(chatIsEnabled && userCourseEnv != null && !userCourseEnv.isCourseReadOnly()) {
			chatLink = LinkFactory.createToolLink("chat",translate("command.coursechat"), this, "o_icon_chat");
			chatLink.setVisible(imModule.isCourseEnabled() && cc.isChatEnabled());
			toolbarPanel.addTool(chatLink);
		}
		
		// add course search to toolbox 
		boolean isSearchEnabled = !assessmentLock && searchModule.isSearchAllowed(roles);
			searchLink = LinkFactory.createToolLink("coursesearch", translate("command.coursesearch"), this, "o_icon_search");
			searchLink.setVisible(cc.isCourseSearchEnabled());
			toolbarPanel.addTool(searchLink);
		}
	//check the configuration enable the lectures and the user is a teacher 
	private boolean isLecturesLinkEnabled() {
		if(lectureModule.isEnabled()) {
			if(reSecurity.isEntryAdmin()) {
				return lectureService.isRepositoryEntryLectureEnabled(getRepositoryEntry());
			} else {
				//check the configuration enable the lectures and the user is a teacher 
				return lectureService.hasLecturesAsTeacher(getRepositoryEntry(), getIdentity());
			}
		}
		return false;
	@Override
	public void setActiveTool(Link tool) {
		if(myCourse != null) {
			myCourse.setActiveLink(tool);
		}
		super.setActiveTool(tool);