From ea29a0d79e423e5ebb103885a3e7937461fe1116 Mon Sep 17 00:00:00 2001
From: srosse <none@none>
Date: Mon, 9 Feb 2015 11:58:43 +0100
Subject: [PATCH] OO-1349: filter the tree to select the start course element,
 use the runstructure instead of the editortreemodel, remove the lockMode ( as
 security ), ips and keys mandatory if options checked

---
 .../fullWebApp/BaseFullWebappController.java  |  1 +
 .../ui/AssessmentModeEditController.java      | 25 +++++++--
 .../ui/ChooseElementsController.java          | 12 ++---
 .../ui/ChooseStartElementController.java      | 48 +++++++++++++----
 .../ui/CourseNodeSelectionTreeModel.java      | 53 +++++++++++++++++++
 5 files changed, 121 insertions(+), 18 deletions(-)
 create mode 100644 src/main/java/org/olat/course/assessment/ui/CourseNodeSelectionTreeModel.java

diff --git a/src/main/java/org/olat/core/commons/fullWebApp/BaseFullWebappController.java b/src/main/java/org/olat/core/commons/fullWebApp/BaseFullWebappController.java
index f394d38ad91..ed8fbbb35d7 100644
--- a/src/main/java/org/olat/core/commons/fullWebApp/BaseFullWebappController.java
+++ b/src/main/java/org/olat/core/commons/fullWebApp/BaseFullWebappController.java
@@ -671,6 +671,7 @@ public class BaseFullWebappController extends BasicController implements ChiefCo
 				removeAsListenerAndDispose(assessmentGuardCtrl);
 				assessmentGuardCtrl = null;
 				lockStatus = null;
+				lockMode = null;
 			}
 		} else {
 			int tabIndex = dtabsControllers.indexOf(source);
diff --git a/src/main/java/org/olat/course/assessment/ui/AssessmentModeEditController.java b/src/main/java/org/olat/course/assessment/ui/AssessmentModeEditController.java
index 2af72551347..d0b161837c9 100644
--- a/src/main/java/org/olat/course/assessment/ui/AssessmentModeEditController.java
+++ b/src/main/java/org/olat/course/assessment/ui/AssessmentModeEditController.java
@@ -439,7 +439,24 @@ public class AssessmentModeEditController extends FormBasicController {
 			targetEl.setErrorKey("form.legende.mandatory", null);
 			allOk &= false;
 		}
-
+		
+		safeExamBrowserKeyEl.clearError();
+		if(safeExamBrowserEl.isAtLeastSelected(1)) {
+			String value = safeExamBrowserKeyEl.getValue();
+			if(!StringHelper.containsNonWhitespace(value)) {
+				safeExamBrowserKeyEl.setErrorKey("form.legende.mandatory", null);
+				allOk &= false;
+			}
+		}
+		
+		ipListEl.clearError();
+		if(ipsEl.isAtLeastSelected(1)) {
+			String value = ipListEl.getValue();
+			if(!StringHelper.containsNonWhitespace(value)) {
+				ipListEl.setErrorKey("form.legende.mandatory", null);
+				allOk &= false;
+			}
+		}
 		return allOk & super.validateFormLogic(ureq);
 	}
 
@@ -643,8 +660,10 @@ public class AssessmentModeEditController extends FormBasicController {
 	
 	private void doChooseStartElement(UserRequest ureq) {
 		if(chooseElementsCtrl != null) return;
-
-		chooseStartElementCtrl = new ChooseStartElementController(ureq, getWindowControl(), startElementKey, courseOres);
+		
+		List<String> allowedKeys = courseElementsRestrictionEl.isAtLeastSelected(1)
+				? new ArrayList<>(elementKeys) : null;
+		chooseStartElementCtrl = new ChooseStartElementController(ureq, getWindowControl(), startElementKey, allowedKeys, courseOres);
 		listenTo(chooseStartElementCtrl);
 		
 		cmc = new CloseableModalController(getWindowControl(), null, chooseStartElementCtrl.getInitialComponent(),
diff --git a/src/main/java/org/olat/course/assessment/ui/ChooseElementsController.java b/src/main/java/org/olat/course/assessment/ui/ChooseElementsController.java
index ae298eb5425..34e37e4139f 100644
--- a/src/main/java/org/olat/course/assessment/ui/ChooseElementsController.java
+++ b/src/main/java/org/olat/course/assessment/ui/ChooseElementsController.java
@@ -31,6 +31,8 @@ import org.olat.core.gui.components.form.flexible.impl.FormBasicController;
 import org.olat.core.gui.components.form.flexible.impl.FormEvent;
 import org.olat.core.gui.components.link.Link;
 import org.olat.core.gui.components.tree.MenuTreeItem;
+import org.olat.core.gui.components.tree.TreeModel;
+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;
@@ -38,8 +40,6 @@ import org.olat.core.id.OLATResourceable;
 import org.olat.core.util.resource.OresHelper;
 import org.olat.course.CourseFactory;
 import org.olat.course.ICourse;
-import org.olat.course.nodes.CourseNode;
-import org.olat.course.tree.CourseEditorTreeModel;
 
 /**
  * 
@@ -50,7 +50,7 @@ import org.olat.course.tree.CourseEditorTreeModel;
 public class ChooseElementsController extends FormBasicController {
 
 	private MenuTreeItem selectTree;
-	private CourseEditorTreeModel treeModel;
+	private TreeModel treeModel;
 	private FormLink selectAll, deselectAll;
 
 	private final OLATResourceable ores;
@@ -71,7 +71,7 @@ public class ChooseElementsController extends FormBasicController {
 	@Override
 	protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) {
 		ICourse course = CourseFactory.loadCourse(ores);
-		treeModel = course.getEditorTreeModel();
+		treeModel = new CourseNodeSelectionTreeModel(course);
 		selectTree = uifactory.addTreeMultiselect("elements", null, formLayout, treeModel, this);
 		selectTree.setMultiSelect(true);
 		selectTree.setSelectedKeys(preSelectedKeys);
@@ -93,11 +93,11 @@ public class ChooseElementsController extends FormBasicController {
 		List<String> names = new ArrayList<>(selectedKeys.size());
 		for(String selectedKey:selectedKeys) {
 			
-			CourseNode node = treeModel.getCourseNode(selectedKey);
+			TreeNode node = treeModel.getNodeById(selectedKey);
 			if(node == null) {
 				//not published??
 			} else {
-				names.add(node.getShortTitle());
+				names.add(node.getTitle());
 			}
 		}
 		
diff --git a/src/main/java/org/olat/course/assessment/ui/ChooseStartElementController.java b/src/main/java/org/olat/course/assessment/ui/ChooseStartElementController.java
index a682c7e1f6a..7391a04c21a 100644
--- a/src/main/java/org/olat/course/assessment/ui/ChooseStartElementController.java
+++ b/src/main/java/org/olat/course/assessment/ui/ChooseStartElementController.java
@@ -19,21 +19,25 @@
  */
 package org.olat.course.assessment.ui;
 
-import java.util.Collections;
+import java.util.ArrayList;
+import java.util.List;
 
 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.tree.GenericTreeModel;
 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.util.nodes.INode;
 import org.olat.core.util.resource.OresHelper;
+import org.olat.core.util.tree.INodeFilter;
 import org.olat.course.CourseFactory;
 import org.olat.course.ICourse;
-import org.olat.course.nodes.CourseNode;
-import org.olat.course.tree.CourseEditorTreeModel;
+import org.olat.course.Structure;
 
 /**
  * 
@@ -44,15 +48,18 @@ import org.olat.course.tree.CourseEditorTreeModel;
 public class ChooseStartElementController extends FormBasicController {
 
 	private MenuTreeItem selectTree;
-	private CourseEditorTreeModel treeModel;
+	private GenericTreeModel treeModel;
 
 	private final OLATResourceable ores;
 	private final String preSelectedKey;
+	private final List<String> elementKeys;
 
-	public ChooseStartElementController(UserRequest ureq, WindowControl wControl, String selectedKey, OLATResourceable ores) {
+	public ChooseStartElementController(UserRequest ureq, WindowControl wControl,
+			String selectedKey, List<String> elementKeys, OLATResourceable ores) {
 		super(ureq, wControl, "course_element");
 		this.ores = OresHelper.clone(ores);
 		preSelectedKey = selectedKey;
+		this.elementKeys = elementKeys;
 		initForm(ureq);
 	}
 	
@@ -64,10 +71,13 @@ public class ChooseStartElementController extends FormBasicController {
 	@Override
 	protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) {
 		ICourse course = CourseFactory.loadCourse(ores);
-		treeModel = course.getEditorTreeModel();
+		treeModel = new CourseNodeSelectionTreeModel(course);
 		selectTree = uifactory.addTreeMultiselect("elements", null, formLayout, treeModel, this);
-		selectTree.setSelectedKeys(Collections.singletonList(preSelectedKey));
+		selectTree.setSelectedNodeId(preSelectedKey);
 		selectTree.setNoDirtyCheckOnClick(true);
+		if(elementKeys != null) {
+			selectTree.setFilter(new RestionctionsFilter(elementKeys, course));
+		}
 		
 		uifactory.addFormCancelButton("cancel", formLayout, ureq, getWindowControl());
 		uifactory.addFormSubmitButton("ok", formLayout);
@@ -81,11 +91,11 @@ public class ChooseStartElementController extends FormBasicController {
 		String selectedKey = getSelectedKey();
 		String name = null;
 
-		CourseNode node = treeModel.getCourseNode(selectedKey);
+		TreeNode node = treeModel.getNodeById(selectedKey);
 		if(node == null) {
 			//not published??
 		} else {
-			name = node.getShortTitle();
+			name = node.getTitle();
 		}
 		return name;
 	}
@@ -99,4 +109,24 @@ public class ChooseStartElementController extends FormBasicController {
 	protected void formCancelled(UserRequest ureq) {
 		fireEvent(ureq, Event.CANCELLED_EVENT);
 	}
+	
+	private class RestionctionsFilter implements INodeFilter {
+		
+		private final List<String> keysAndParents = new ArrayList<>();
+		
+		public RestionctionsFilter(List<String> keys, ICourse course) {
+			Structure runstructure = course.getRunStructure();
+			for(String nodeId:keys) {
+				//allow the parent line
+				for(INode courseNode = runstructure.getNode(nodeId); courseNode != null; courseNode = courseNode.getParent()) {
+					keysAndParents.add(courseNode.getIdent());
+				}
+			}
+		}
+
+		@Override
+		public boolean isVisible(INode node) {
+			return keysAndParents.contains(node.getIdent());
+		}	
+	}
 }
\ No newline at end of file
diff --git a/src/main/java/org/olat/course/assessment/ui/CourseNodeSelectionTreeModel.java b/src/main/java/org/olat/course/assessment/ui/CourseNodeSelectionTreeModel.java
new file mode 100644
index 00000000000..b3ce1b3f80e
--- /dev/null
+++ b/src/main/java/org/olat/course/assessment/ui/CourseNodeSelectionTreeModel.java
@@ -0,0 +1,53 @@
+/**
+ * <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.assessment.ui;
+
+import org.olat.core.gui.components.tree.GenericTreeModel;
+import org.olat.core.gui.components.tree.GenericTreeNode;
+import org.olat.core.gui.components.tree.TreeNode;
+import org.olat.course.ICourse;
+import org.olat.course.nodes.CourseNode;
+
+/**
+ * 
+ * Initial date: 09.02.2015<br>
+ * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
+ *
+ */
+public class CourseNodeSelectionTreeModel extends GenericTreeModel {
+
+	private static final long serialVersionUID = 7708592865968524515L;
+
+	public CourseNodeSelectionTreeModel(ICourse course) {
+		TreeNode rootNode = buildTree(course.getRunStructure().getRootNode());
+		setRootNode(rootNode);
+	}
+
+	private TreeNode buildTree(CourseNode courseNode) {
+		GenericTreeNode node = new GenericTreeNode(courseNode.getIdent(), courseNode.getShortTitle(), courseNode);
+		node.setIconCssClass(("o_icon o_" + courseNode.getType() + "_icon").intern());
+		node.setAltText(courseNode.getLongTitle());
+		for (int i = 0; i < courseNode.getChildCount(); i++) {
+			CourseNode childNode = (CourseNode)courseNode.getChildAt(i);
+			node.addChild(buildTree(childNode));
+		}
+		return node;
+	}
+}
\ No newline at end of file
-- 
GitLab