/** * OLAT - Online Learning and Training<br> * http://www.olat.org * <p> * Licensed under the Apache License, Version 2.0 (the "License"); <br> * you may not use this file except in compliance with the License.<br> * You may obtain a copy of the License at * <p> * http://www.apache.org/licenses/LICENSE-2.0 * <p> * Unless required by applicable law or agreed to in writing,<br> * software distributed under the License is distributed on an "AS IS" BASIS, <br> * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> * See the License for the specific language governing permissions and <br> * limitations under the License. * <p> * Copyright (c) since 2004 at Multimedia- & E-Learning Services (MELS),<br> * University of Zurich, Switzerland. * <hr> * <a href="http://www.openolat.org"> * OpenOLAT - Online Learning and Training</a><br> * This file has been modified by the OpenOLAT community. Changes are licensed * under the Apache 2.0 license as the original file. */ package org.olat.course.run.calendar; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.List; import org.olat.commons.calendar.CalendarManager; import org.olat.commons.calendar.model.KalendarEvent; import org.olat.commons.calendar.model.KalendarEventLink; import org.olat.commons.calendar.ui.LinkProvider; import org.olat.core.gui.UserRequest; import org.olat.core.gui.components.form.flexible.FormItemContainer; import org.olat.core.gui.components.form.flexible.impl.FormBasicController; import org.olat.core.gui.components.form.flexible.impl.elements.FormSubmit; import org.olat.core.gui.components.tree.GenericTreeModel; import org.olat.core.gui.components.tree.GenericTreeNode; import org.olat.core.gui.components.tree.MenuTreeItem; import org.olat.core.gui.components.tree.TreeNode; 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.id.OLATResourceable; import org.olat.core.id.context.BusinessControlFactory; import org.olat.core.id.context.ContextEntry; import org.olat.core.util.Util; import org.olat.core.util.nodes.INode; import org.olat.core.util.resource.OresHelper; import org.olat.course.ICourse; import org.olat.course.nodes.CourseNode; import org.olat.repository.RepositoryEntry; import org.olat.repository.RepositoryManager; import org.springframework.beans.factory.annotation.Autowired; public class CourseLinkProviderController extends FormBasicController implements LinkProvider { private static final String COURSE_LINK_PROVIDER = "COURSE"; private KalendarEvent kalendarEvent; private FormSubmit saveButton; private final OLATResourceable ores; private final List<ICourse> availableCourses; private MenuTreeItem multiSelectTree; private final CourseNodeSelectionTreeModel courseNodeTreeModel; @Autowired private CalendarManager calendarManager; public CourseLinkProviderController(ICourse course, List<ICourse> courses, UserRequest ureq, WindowControl wControl) { super(ureq, wControl, "course_elements"); setTranslator(Util.createPackageTranslator(CalendarManager.class, ureq.getLocale(), getTranslator())); this.ores = course; availableCourses = new ArrayList<>(courses); courseNodeTreeModel = new CourseNodeSelectionTreeModel(courses); initForm(ureq); } @Override protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) { multiSelectTree = uifactory.addTreeMultiselect("seltree", null, formLayout, courseNodeTreeModel, this); multiSelectTree.setRootVisible(availableCourses.size() == 1); multiSelectTree.setMultiSelect(true); saveButton = uifactory.addFormSubmitButton("ok", "cal.links.submit", formLayout); } @Override protected void doDispose() { // } @Override protected void formOK(UserRequest ureq) { List<KalendarEventLink> kalendarEventLinks = kalendarEvent.getKalendarEventLinks(); TreeNode rootNode = courseNodeTreeModel.getRootNode(); for(Iterator<KalendarEventLink> linkIt = kalendarEventLinks.iterator(); linkIt.hasNext(); ) { KalendarEventLink link = linkIt.next(); if(COURSE_LINK_PROVIDER.equals(link.getProvider())) { linkIt.remove(); } } clearSelection(rootNode); Collection<String> nodeIds = multiSelectTree.getSelectedKeys(); rebuildKalendarEventLinks(rootNode, nodeIds, kalendarEventLinks); // if the calendarevent is already associated with a calendar, save the modifications. // otherwise, the modifications will be saver, when the user saves // the calendar event. if (kalendarEvent.getCalendar() != null) { calendarManager.updateEventFrom(kalendarEvent.getCalendar(), kalendarEvent); } fireEvent(ureq, Event.DONE_EVENT); } public Long getCourseId() { return ores.getResourceableId(); } private void rebuildKalendarEventLinks(INode node, Collection<String> selectedNodeIDs, List<KalendarEventLink> kalendarEventLinks) { if (selectedNodeIDs.contains(node.getIdent()) && node instanceof LinkTreeNode) { // assemble link LinkTreeNode treeNode = (LinkTreeNode)node; OLATResourceable courseOres = treeNode.getCourse(); if(courseOres != null) { RepositoryEntry re = RepositoryManager.getInstance().lookupRepositoryEntry(courseOres, true); List<ContextEntry> ces = new ArrayList<ContextEntry>(); ces.add(BusinessControlFactory.getInstance().createContextEntry(re)); if(treeNode.getCourseNode() != null) { String courseNodeId = treeNode.getCourseNode().getIdent(); OLATResourceable oresNode = OresHelper.createOLATResourceableInstance("CourseNode", Long.valueOf(courseNodeId)); ces.add(BusinessControlFactory.getInstance().createContextEntry(oresNode)); } String extLink = BusinessControlFactory.getInstance().getAsURIString(ces, false); KalendarEventLink link = new KalendarEventLink(COURSE_LINK_PROVIDER, node.getIdent(), treeNode.getTitle(), extLink, treeNode.getIconCssClass()); kalendarEventLinks.add(link); treeNode.setSelected(true); } } for (int i = 0; i < node.getChildCount(); i++) { rebuildKalendarEventLinks(node.getChildAt(i), selectedNodeIDs, kalendarEventLinks); } } @Override public CourseLinkProviderController getControler() { return this; } @Override public void setKalendarEvent(KalendarEvent kalendarEvent) { this.kalendarEvent = kalendarEvent; //clear all selections clearSelection(courseNodeTreeModel.getRootNode()); multiSelectTree.deselectAll(); for (KalendarEventLink link: kalendarEvent.getKalendarEventLinks()) { if (link.getProvider().equals(COURSE_LINK_PROVIDER)) { String nodeId = link.getId(); TreeNode node = courseNodeTreeModel.getNodeById(nodeId); if(node == null) { String fallBackNodeId = availableCourses.get(0).getResourceableId() + "_" + nodeId; node = courseNodeTreeModel.getNodeById(fallBackNodeId); } if(node == null && nodeId.indexOf("_") < 0) { //course selected -> map to root node for(ICourse course: availableCourses) { if(nodeId.equals(course.getResourceableId().toString())) { String fallBackNodeId = course.getResourceableId() + "_" + course.getRunStructure().getRootNode().getIdent(); node = courseNodeTreeModel.getNodeById(fallBackNodeId); } } } if (node != null) { node.setSelected(true); multiSelectTree.select(node.getIdent(), true); multiSelectTree.open(node); } } } } @Override public void setDisplayOnly(boolean displayOnly) { multiSelectTree.setEnabled(!displayOnly); multiSelectTree.reset(); saveButton.setVisible(!displayOnly); } private void clearSelection(TreeNode node) { node.setSelected(false); for (int i = 0; i < node.getChildCount(); i++) { TreeNode childNode = (TreeNode)node.getChildAt(i); clearSelection(childNode); } } private static class CourseNodeSelectionTreeModel extends GenericTreeModel { private static final long serialVersionUID = -7863033366847344767L; public CourseNodeSelectionTreeModel(List<ICourse> courses) { if(courses.size() == 1) { ICourse course = courses.get(0); setRootNode(buildCourseTree(course)); } else { LinkTreeNode rootNode = new LinkTreeNode("", null, null); for(ICourse course:courses) { rootNode.addChild(buildCourseTree(course)); } setRootNode(rootNode); } } private LinkTreeNode buildCourseTree(ICourse course) { return buildTree(course, course.getRunStructure().getRootNode()); } private LinkTreeNode buildTree(ICourse course, CourseNode courseNode) { LinkTreeNode node = new LinkTreeNode(courseNode.getShortTitle(), course, courseNode); node.setAltText(courseNode.getLongTitle()); node.setIdent(course.getResourceableId() + "_" + courseNode.getIdent()); if(courseNode == course.getRunStructure().getRootNode()) { node.setIconCssClass("o_CourseModule_icon"); } else { node.setIconCssClass(("o_icon o_" + courseNode.getType() + "_icon").intern()); } node.setUserObject(course); for (int i = 0; i < courseNode.getChildCount(); i++) { CourseNode childNode = (CourseNode)courseNode.getChildAt(i); node.addChild(buildTree(course, childNode)); } return node; } } private static class LinkTreeNode extends GenericTreeNode { private static final long serialVersionUID = -6043669089871217496L; private final ICourse course; private final CourseNode courseNode; public LinkTreeNode(String title, ICourse course, CourseNode courseNode) { super(title, null); this.course = course; this.courseNode = courseNode; } public ICourse getCourse() { return course; } public CourseNode getCourseNode() { return courseNode; } } }