From 89c1b60b42d8d5002e95148178203c9aa8d2adaf Mon Sep 17 00:00:00 2001
From: srosse <none@none>
Date: Thu, 17 Jan 2013 10:47:56 +0100
Subject: [PATCH] OO-502: move the groups / roles cache from the
 RunMainController to the UserCourseEnvironment to speed-up the condition
 interpreter on course with a lot of rules

---
 .../interpreter/InLearningGroupFunction.java  |  16 +--
 .../IsCourseAdministratorFunction.java        |   8 +-
 .../interpreter/IsCourseCoachFunction.java    |   9 +-
 .../IsCourseParticipantFunction.java          |   7 +-
 .../EditorUserCourseEnvironmentImpl.java      |  23 +++-
 .../org/olat/course/nodes/SPCourseNode.java   |   8 +-
 .../olat/course/nodes/sp/SPRunController.java |   7 +-
 .../olat/course/run/RunMainController.java    |  67 ++++++-----
 .../course/run/userview/NodeEvaluation.java   |   6 +-
 .../run/userview/UserCourseEnvironment.java   |  19 ++-
 .../userview/UserCourseEnvironmentImpl.java   | 108 ++++++++++++++++--
 11 files changed, 180 insertions(+), 98 deletions(-)

diff --git a/src/main/java/org/olat/course/condition/interpreter/InLearningGroupFunction.java b/src/main/java/org/olat/course/condition/interpreter/InLearningGroupFunction.java
index ae284cad230..ec23c4c5ed2 100644
--- a/src/main/java/org/olat/course/condition/interpreter/InLearningGroupFunction.java
+++ b/src/main/java/org/olat/course/condition/interpreter/InLearningGroupFunction.java
@@ -81,21 +81,17 @@ public class InLearningGroupFunction extends AbstractFunction {
 			return defaultValue();
 		}
 
-		/*
-		 * the real function evaluation which is used during run time
-		 */
-		Identity ident = getUserCourseEnv().getIdentityEnvironment().getIdentity();
-		
-		CourseGroupManager cgm = getUserCourseEnv().getCourseEnvironment().getCourseGroupManager();
-		//System.out.println("todo: check if "+(ident==null? "n/a":ident.getName())+" is in group "+groupName);
-		
+		//the real function evaluation which is used during run time
 		if(isGroupKey(groupName)) {
 			Long groupKey = Long.parseLong(groupName);
-			return cgm.isIdentityInGroup(ident, groupKey) ? ConditionInterpreter.INT_TRUE: ConditionInterpreter.INT_FALSE;
+			return getUserCourseEnv().isIdentityInCourseGroup(groupKey) ? ConditionInterpreter.INT_TRUE: ConditionInterpreter.INT_FALSE;
+			//return cgm.isIdentityInGroup(ident, groupKey) ? ConditionInterpreter.INT_TRUE: ConditionInterpreter.INT_FALSE;
 		}
-		
+
+		CourseGroupManager cgm = getUserCourseEnv().getCourseEnvironment().getCourseGroupManager();
 		List<Long> groupKeys = CoreSpringFactory.getImpl(BusinessGroupService.class).toGroupKeys(groupName, cgm.getCourseResource());
 		if(!groupKeys.isEmpty()) {
+			Identity ident = getUserCourseEnv().getIdentityEnvironment().getIdentity();
 			return cgm.isIdentityInGroup(ident, groupKeys.get(0)) ? ConditionInterpreter.INT_TRUE: ConditionInterpreter.INT_FALSE;
 		}
 		return ConditionInterpreter.INT_FALSE;
diff --git a/src/main/java/org/olat/course/condition/interpreter/IsCourseAdministratorFunction.java b/src/main/java/org/olat/course/condition/interpreter/IsCourseAdministratorFunction.java
index 1a62b862826..46c504c9ba9 100644
--- a/src/main/java/org/olat/course/condition/interpreter/IsCourseAdministratorFunction.java
+++ b/src/main/java/org/olat/course/condition/interpreter/IsCourseAdministratorFunction.java
@@ -29,7 +29,6 @@ import org.olat.core.id.Identity;
 import org.olat.core.logging.OLog;
 import org.olat.core.logging.Tracing;
 import org.olat.course.editor.CourseEditorEnv;
-import org.olat.course.groupsandrights.CourseGroupManager;
 import org.olat.course.run.userview.UserCourseEnvironment;
 
 /**
@@ -65,10 +64,11 @@ public class IsCourseAdministratorFunction extends AbstractFunction {
 			return defaultValue();
 		}
 
-		Identity ident = getUserCourseEnv().getIdentityEnvironment().getIdentity();
-		CourseGroupManager cgm = getUserCourseEnv().getCourseEnvironment().getCourseGroupManager();
-		boolean isCourseAdmin = cgm.isIdentityCourseAdministrator(ident);
+		//Identity ident = getUserCourseEnv().getIdentityEnvironment().getIdentity();
+		//CourseGroupManager cgm = getUserCourseEnv().getCourseEnvironment().getCourseGroupManager();
+		boolean isCourseAdmin = getUserCourseEnv().isAdmin();// cgm.isIdentityCourseAdministrator(ident);
 		if(log.isDebug()) {
+			Identity ident = getUserCourseEnv().getIdentityEnvironment().getIdentity();
 			log.debug("identity "+ident.getName()+", courseadministrator:"+isCourseAdmin+", in course "+getUserCourseEnv().getCourseEnvironment().getCourseResourceableId());
 		}
 		return isCourseAdmin ? ConditionInterpreter.INT_TRUE: ConditionInterpreter.INT_FALSE;
diff --git a/src/main/java/org/olat/course/condition/interpreter/IsCourseCoachFunction.java b/src/main/java/org/olat/course/condition/interpreter/IsCourseCoachFunction.java
index 25b1970c3f7..eccec7280b4 100644
--- a/src/main/java/org/olat/course/condition/interpreter/IsCourseCoachFunction.java
+++ b/src/main/java/org/olat/course/condition/interpreter/IsCourseCoachFunction.java
@@ -29,7 +29,6 @@ import org.olat.core.id.Identity;
 import org.olat.core.logging.OLog;
 import org.olat.core.logging.Tracing;
 import org.olat.course.editor.CourseEditorEnv;
-import org.olat.course.groupsandrights.CourseGroupManager;
 import org.olat.course.run.userview.UserCourseEnvironment;
 
 /**
@@ -61,18 +60,16 @@ public class IsCourseCoachFunction extends AbstractFunction {
 			return defaultValue();
 		}
 
-		Identity ident = getUserCourseEnv().getIdentityEnvironment().getIdentity();
-		CourseGroupManager cgm = getUserCourseEnv().getCourseEnvironment().getCourseGroupManager();
-		boolean isCourseCoach = cgm.isIdentityCourseCoach(ident);
+		//CourseGroupManager cgm = getUserCourseEnv().getCourseEnvironment().getCourseGroupManager();
+		boolean isCourseCoach = this.getUserCourseEnv().isCoach();// cgm.isIdentityCourseCoach(ident);
 		if (log.isDebug()) {
+			Identity ident = getUserCourseEnv().getIdentityEnvironment().getIdentity();
 			log.debug("identity "+ident.getName()+", coursecoach:"+isCourseCoach+", in course "+getUserCourseEnv().getCourseEnvironment().getCourseResourceableId());
 		}
-		
 		return isCourseCoach ? ConditionInterpreter.INT_TRUE: ConditionInterpreter.INT_FALSE;
 	}
 
 	protected Object defaultValue() {
 		return ConditionInterpreter.INT_TRUE;
 	}
-
 }
diff --git a/src/main/java/org/olat/course/condition/interpreter/IsCourseParticipantFunction.java b/src/main/java/org/olat/course/condition/interpreter/IsCourseParticipantFunction.java
index 62e093cf99e..5822f64706c 100644
--- a/src/main/java/org/olat/course/condition/interpreter/IsCourseParticipantFunction.java
+++ b/src/main/java/org/olat/course/condition/interpreter/IsCourseParticipantFunction.java
@@ -25,7 +25,6 @@ import org.olat.core.id.Identity;
 import org.olat.core.logging.OLog;
 import org.olat.core.logging.Tracing;
 import org.olat.course.editor.CourseEditorEnv;
-import org.olat.course.groupsandrights.CourseGroupManager;
 import org.olat.course.run.userview.UserCourseEnvironment;
 
 /**
@@ -63,10 +62,10 @@ public class IsCourseParticipantFunction extends AbstractFunction {
 			return defaultValue();
 		}
 
-		Identity ident = getUserCourseEnv().getIdentityEnvironment().getIdentity();
-		CourseGroupManager cgm = getUserCourseEnv().getCourseEnvironment().getCourseGroupManager();
-		boolean isParticipant = cgm.isIdentityCourseParticipant(ident);
+		//CourseGroupManager cgm = getUserCourseEnv().getCourseEnvironment().getCourseGroupManager();
+		boolean isParticipant = getUserCourseEnv().isParticipant();// cgm.isIdentityCourseParticipant(ident);
 		if (log.isDebug()) {
+			Identity ident = getUserCourseEnv().getIdentityEnvironment().getIdentity();
 			log.debug("identity "+ident.getName()+", coursecoach:"+isParticipant+", in course "+getUserCourseEnv().getCourseEnvironment().getCourseResourceableId());
 		}
 		
diff --git a/src/main/java/org/olat/course/editor/EditorUserCourseEnvironmentImpl.java b/src/main/java/org/olat/course/editor/EditorUserCourseEnvironmentImpl.java
index fb7e38f1bbe..bfeea21f1d9 100644
--- a/src/main/java/org/olat/course/editor/EditorUserCourseEnvironmentImpl.java
+++ b/src/main/java/org/olat/course/editor/EditorUserCourseEnvironmentImpl.java
@@ -25,8 +25,6 @@
 
 package org.olat.course.editor;
 
-import java.util.Map;
-
 import org.olat.core.id.IdentityEnvironment;
 import org.olat.core.logging.AssertException;
 import org.olat.course.condition.interpreter.ConditionInterpreter;
@@ -90,9 +88,24 @@ public class EditorUserCourseEnvironmentImpl implements UserCourseEnvironment {
 		return sa;
 	}
 
-	public Map getTempMap(Class owner, String key) {
-		// TODO Auto-generated method stub
-		return null;
+	@Override
+	public boolean isIdentityInCourseGroup(Long groupKey) {
+		//TODO OO-502
+		return false;
+	}
+
+	@Override
+	public boolean isAdmin() {
+		return false;
 	}
 
+	@Override
+	public boolean isCoach() {
+		return false;
+	}
+
+	@Override
+	public boolean isParticipant() {
+		return false;
+	}
 }
diff --git a/src/main/java/org/olat/course/nodes/SPCourseNode.java b/src/main/java/org/olat/course/nodes/SPCourseNode.java
index 4434a438bec..774ab1b4c5f 100644
--- a/src/main/java/org/olat/course/nodes/SPCourseNode.java
+++ b/src/main/java/org/olat/course/nodes/SPCourseNode.java
@@ -26,7 +26,6 @@
 package org.olat.course.nodes;
 
 import java.util.List;
-import java.util.Map;
 
 import org.olat.core.commons.modules.bc.vfs.OlatNamedContainerImpl;
 import org.olat.core.commons.modules.bc.vfs.OlatRootFolderImpl;
@@ -96,13 +95,8 @@ public class SPCourseNode extends AbstractAccessableCourseNode {
 			UserCourseEnvironment userCourseEnv, NodeEvaluation ne, String nodecmd) {
 		updateModuleConfigDefaults(false);
 
-		String nodeId = ne.getCourseNode().getIdent();
-		// obtain a temporary (as long as the users visits the course) map to store
-		// intermediate data
-		Map tmpstoremap = userCourseEnv.getTempMap(this.getClass(), nodeId);
-		
 		VFSContainer container = userCourseEnv.getCourseEnvironment().getCourseFolderContainer();
-		SPRunController runController = new SPRunController(wControl, ureq, tmpstoremap, userCourseEnv, this, container);
+		SPRunController runController = new SPRunController(wControl, ureq, userCourseEnv, this, container);
 		return new NodeRunConstructionResult(runController);
 	}
 
diff --git a/src/main/java/org/olat/course/nodes/sp/SPRunController.java b/src/main/java/org/olat/course/nodes/sp/SPRunController.java
index f17306aca4c..2beb5d45e5b 100644
--- a/src/main/java/org/olat/course/nodes/sp/SPRunController.java
+++ b/src/main/java/org/olat/course/nodes/sp/SPRunController.java
@@ -83,7 +83,6 @@ public class SPRunController extends BasicController {
 		
 	private VFSContainer courseFolderContainer;
 	private String fileName;
-	private final Map tempstorage;
 	
 	private boolean hasEditRights;
 	private CustomLinkTreeModel linkTreeModel;
@@ -101,9 +100,8 @@ public class SPRunController extends BasicController {
 	 * @param courseNode
 	 * @param courseFolderPath The course folder which contains the single page html file
 	 */
-	public SPRunController(WindowControl wControl, UserRequest ureq, Map tempstorage, UserCourseEnvironment userCourseEnv, SPCourseNode courseNode, VFSContainer courseFolderContainer) {
+	public SPRunController(WindowControl wControl, UserRequest ureq, UserCourseEnvironment userCourseEnv, SPCourseNode courseNode, VFSContainer courseFolderContainer) {
 		super(ureq,wControl);
-		this.tempstorage = tempstorage;
 		this.courseNode = courseNode;
 		this.config = courseNode.getModuleConfiguration();
 		this.userCourseEnv = userCourseEnv;
@@ -153,8 +151,7 @@ public class SPRunController extends BasicController {
 				// refire to listening controllers
 				fireEvent(ureq, event);
 			} else if (event instanceof NewInlineUriEvent) {
-				NewInlineUriEvent nue = (NewInlineUriEvent)event;
-				tempstorage.put(KEY_CURRENT_URI, nue.getNewUri());
+				//do nothing
 			}
 		}
 	}
diff --git a/src/main/java/org/olat/course/run/RunMainController.java b/src/main/java/org/olat/course/run/RunMainController.java
index d7cfcf8fd4f..8499b84b64e 100644
--- a/src/main/java/org/olat/course/run/RunMainController.java
+++ b/src/main/java/org/olat/course/run/RunMainController.java
@@ -110,7 +110,6 @@ import org.olat.course.run.glossary.CourseGlossaryFactory;
 import org.olat.course.run.glossary.CourseGlossaryToolLinkController;
 import org.olat.course.run.navigation.NavigationHandler;
 import org.olat.course.run.navigation.NodeClickedRef;
-import org.olat.course.run.userview.UserCourseEnvironment;
 import org.olat.course.run.userview.UserCourseEnvironmentImpl;
 import org.olat.course.statistic.StatisticMainController;
 import org.olat.group.BusinessGroup;
@@ -157,7 +156,7 @@ public class RunMainController extends MainLayoutBasicController implements Gene
 	private StackedController all;
 
 	private NavigationHandler navHandler;
-	private UserCourseEnvironment uce;
+	private UserCourseEnvironmentImpl uce;
 	private LayoutMain3ColsController columnLayoutCtr;
 
 	private Controller currentToolCtr;
@@ -170,9 +169,6 @@ public class RunMainController extends MainLayoutBasicController implements Gene
 	private Map<String, Boolean> courseRightsCache = new HashMap<String, Boolean>();
 	private boolean isCourseAdmin = false;
 	private boolean isCourseCoach = false;
-	private List<BusinessGroup> ownedGroups;
-	private List<BusinessGroup> participatedGroups;
-	private List<BusinessGroup> waitingListGroups;
 
 	private CourseNode currentCourseNode;
 	private TreeModel treeModel;
@@ -236,20 +232,19 @@ public class RunMainController extends MainLayoutBasicController implements Gene
 		luTree.setExpandSelectedNode(false);
 		contentP = new Panel("building_block_content");
 
-		// get all group memberships for this course
-		initGroupMemberships(identity);
 		// Initialize the the users roles and right for this course
 		// 1) is guest flag
 		isGuest = ureq.getUserSession().getRoles().isGuestOnly();
-		// 2) all course internal rights
-		initUserRolesAndRights(identity);
-
 		// preload user assessment data in assessmnt properties cache to speed up
 		// course loading
 		course.getCourseEnvironment().getAssessmentManager().preloadCache(identity);
 
 		// build up the running structure for this user;
-		uce = new UserCourseEnvironmentImpl(ureq.getUserSession().getIdentityEnvironment(), course.getCourseEnvironment());
+		// get all group memberships for this course
+		uce = loadUserCourseEnvironment(ureq, course);
+		// 2) all course internal rights
+		reloadUserRolesAndRights(identity);
+
 		// build score now
 		uce.getScoreAccounting().evaluateAll();
 		navHandler = new NavigationHandler(uce, false);
@@ -336,6 +331,15 @@ public class RunMainController extends MainLayoutBasicController implements Gene
 		}
 	}
 	
+	private UserCourseEnvironmentImpl loadUserCourseEnvironment(UserRequest ureq, ICourse course) {
+		CourseGroupManager cgm = course.getCourseEnvironment().getCourseGroupManager();
+		List<BusinessGroup> coachedGroups = cgm.getOwnedBusinessGroups(ureq.getIdentity());
+		List<BusinessGroup> participatedGroups = cgm.getParticipatingBusinessGroups(ureq.getIdentity());
+		List<BusinessGroup> waitingLists = cgm.getWaitingListGroups(ureq.getIdentity());
+		return new UserCourseEnvironmentImpl(ureq.getUserSession().getIdentityEnvironment(), course.getCourseEnvironment(),
+				coachedGroups, participatedGroups, waitingLists, null, null, null);
+	}
+	
 	private void setLaunchDates(final Identity identity) {
 		CoordinatorManager.getInstance().getCoordinator().getSyncer().doInSync(createOLATResourceableForLocking(identity), new SyncerExecutor(){
 			public void execute() {
@@ -365,7 +369,7 @@ public class RunMainController extends MainLayoutBasicController implements Gene
 		return extendedCourseTitle;
 	}
 
-	private void initUserRolesAndRights(final Identity identity) {
+	private void reloadUserRolesAndRights(final Identity identity) {
 		CourseGroupManager cgm = course.getCourseEnvironment().getCourseGroupManager();
 		// 1) course admins: users who are in repository entry owner group
 		// if user has the role InstitutionalResourceManager and has the same institution like author
@@ -377,6 +381,7 @@ public class RunMainController extends MainLayoutBasicController implements Gene
 		isCourseCoach = cgm.isIdentityCourseCoach(identity);
 		// 3) all other rights are defined in the groupmanagement using the learning
 		// group rights
+		uce.setUserRoles(isCourseAdmin, isCourseCoach);
 		
 		List<String> rights = cgm.getRights(identity);
 		courseRightsCache.put(CourseRights.RIGHT_GROUPMANAGEMENT, new Boolean(rights.contains(CourseRights.RIGHT_GROUPMANAGEMENT)));
@@ -548,7 +553,8 @@ public class RunMainController extends MainLayoutBasicController implements Gene
 				needsRebuildAfterPublish = false;
 				
 			  // rebuild up the running structure for this user, after publish;
-				uce = new UserCourseEnvironmentImpl(ureq.getUserSession().getIdentityEnvironment(), CourseFactory.loadCourse(course.getResourceableId()).getCourseEnvironment());
+				course = CourseFactory.loadCourse(course.getResourceableId());
+				uce = loadUserCourseEnvironment(ureq, course);
 				// build score now
 				uce.getScoreAccounting().evaluateAll();
 				navHandler = new NavigationHandler(uce, false);
@@ -667,7 +673,7 @@ public class RunMainController extends MainLayoutBasicController implements Gene
 				logAudit("User tried to launch a group but user is not owner or participant "
 						+ "of group or group doesn't exist. Hacker attack or group has been changed or deleted. group key :: " + groupKey, null);
 				// refresh toolbox that contained wrong group
-				initGroupMemberships(ureq.getIdentity());
+				reloadGroupMemberships(ureq.getIdentity());
 				removeAsListenerAndDispose(toolC);
 				toolC = initToolController(ureq.getIdentity(), ureq);
 				listenTo(toolC);
@@ -938,9 +944,9 @@ public class RunMainController extends MainLayoutBasicController implements Gene
 			// was adding or removing of the user
 			if (bgme.wasMyselfAdded(identity) || bgme.wasMyselfRemoved(identity)) {
 				// 1) reinitialize all group memberships
-				initGroupMemberships(identity);
+				reloadGroupMemberships(identity);
 				// 2) reinitialize the users roles and rights
-				initUserRolesAndRights(identity);
+				reloadUserRolesAndRights(identity);
 				// 3) rebuild toolboxes with link to groups and tools
 				removeAsListenerAndDispose(toolC);
 				toolC = initToolController(identity, null);
@@ -952,12 +958,12 @@ public class RunMainController extends MainLayoutBasicController implements Gene
 				// check if this affects a right group where the user does participate.
 				// if so, we need
 				// to rebuild the toolboxes
-				if (PersistenceHelper.listContainsObjectByKey(participatedGroups, bgme.getModifiedGroupKey()) ||
-						PersistenceHelper.listContainsObjectByKey(ownedGroups, bgme.getModifiedGroupKey())) {
+				if (PersistenceHelper.listContainsObjectByKey(uce.getParticipatingGroups(), bgme.getModifiedGroupKey()) ||
+						PersistenceHelper.listContainsObjectByKey(uce.getCoachedGroups(), bgme.getModifiedGroupKey())) {
 					// 1) reinitialize all group memberships
-					initGroupMemberships(identity);
+					reloadGroupMemberships(identity);
 					// 2) reinitialize the users roles and rights
-					initUserRolesAndRights(identity);
+					reloadUserRolesAndRights(identity);
 					// 3) rebuild toolboxes with link to groups and tools
 					removeAsListenerAndDispose(toolC);
 					toolC = initToolController(identity, null);
@@ -1033,25 +1039,25 @@ public class RunMainController extends MainLayoutBasicController implements Gene
 		}
 
 		// 2) add coached groups
-		if (ownedGroups.size() > 0) {
+		if (uce.getCoachedGroups().size() > 0) {
 			myTool.addHeader(translate("header.tools.ownerGroups"));
-			for (BusinessGroup group:ownedGroups) {
+			for (BusinessGroup group:uce.getCoachedGroups()) {
 				myTool.addLink(CMD_START_GROUP_PREFIX + group.getKey().toString(), group.getName());
 			}
 		}
 
 		// 3) add participating groups
-		if (participatedGroups.size() > 0) {
+		if (uce.getParticipatingGroups().size() > 0) {
 			myTool.addHeader(translate("header.tools.participatedGroups"));
-			for (BusinessGroup group: participatedGroups) {
+			for (BusinessGroup group: uce.getParticipatingGroups()) {
 				myTool.addLink(CMD_START_GROUP_PREFIX + group.getKey().toString(), group.getName());
 			}
 		}
 
 		// 5) add waiting-list groups
-		if (waitingListGroups.size() > 0) {
+		if (uce.getWaitingLists().size() > 0) {
 			myTool.addHeader(translate("header.tools.waitingListGroups"));
-			for (BusinessGroup group:waitingListGroups) {
+			for (BusinessGroup group:uce.getWaitingLists()) {
 				int pos = businessGroupService.getPositionInWaitingListFor(identity, group);
 				myTool.addLink(CMD_START_GROUP_PREFIX + group.getKey().toString(), group.getName() + "(" + pos + ")", group
 						.getKey().toString(), null);
@@ -1159,11 +1165,12 @@ public class RunMainController extends MainLayoutBasicController implements Gene
 	 * 
 	 * @param identity
 	 */
-	private void initGroupMemberships(Identity identity) {
+	private void reloadGroupMemberships(Identity identity) {
 		CourseGroupManager cgm = course.getCourseEnvironment().getCourseGroupManager();
-		ownedGroups = cgm.getOwnedBusinessGroups(identity);
-		participatedGroups = cgm.getParticipatingBusinessGroups(identity);
-		waitingListGroups = cgm.getWaitingListGroups(identity);
+		List<BusinessGroup> coachedGroups = cgm.getOwnedBusinessGroups(identity);
+		List<BusinessGroup> participatedGroups = cgm.getParticipatingBusinessGroups(identity);
+		List<BusinessGroup> waitingLists = cgm.getWaitingListGroups(identity);
+		uce.setGroupMemberships(coachedGroups, participatedGroups, waitingLists);
 	}
 
 	/**
diff --git a/src/main/java/org/olat/course/run/userview/NodeEvaluation.java b/src/main/java/org/olat/course/run/userview/NodeEvaluation.java
index 76835b75394..def2ee9967b 100644
--- a/src/main/java/org/olat/course/run/userview/NodeEvaluation.java
+++ b/src/main/java/org/olat/course/run/userview/NodeEvaluation.java
@@ -53,7 +53,7 @@ public class NodeEvaluation extends GenericNode {
 	private CourseNode courseNode;
 	private GenericTreeNode gtn = null;
 
-	private Map accesses = new HashMap(4);
+	private Map<String, Boolean> accesses = new HashMap<String, Boolean>(4);
 
 	private boolean visible = false;
 	private boolean atLeastOneAccessible = false;
@@ -105,8 +105,8 @@ public class NodeEvaluation extends GenericNode {
 	 */
 	public void build() {
 		// if at least one access	capability is true 
-		for (Iterator iter = accesses.values().iterator(); iter.hasNext();) {
-			Boolean entry = (Boolean) iter.next();
+		for (Iterator<Boolean> iter = accesses.values().iterator(); iter.hasNext();) {
+			Boolean entry = iter.next();
 			atLeastOneAccessible = atLeastOneAccessible || entry.booleanValue();
 		}
 
diff --git a/src/main/java/org/olat/course/run/userview/UserCourseEnvironment.java b/src/main/java/org/olat/course/run/userview/UserCourseEnvironment.java
index 1f79b83bcce..0e39622998f 100644
--- a/src/main/java/org/olat/course/run/userview/UserCourseEnvironment.java
+++ b/src/main/java/org/olat/course/run/userview/UserCourseEnvironment.java
@@ -25,8 +25,6 @@
 
 package org.olat.course.run.userview;
 
-import java.util.Map;
-
 import org.olat.core.id.IdentityEnvironment;
 import org.olat.course.condition.interpreter.ConditionInterpreter;
 import org.olat.course.editor.CourseEditorEnv;
@@ -54,16 +52,13 @@ public interface UserCourseEnvironment {
 	
 	public ScoreAccounting getScoreAccounting();
 	
-	/**
-	 * @return a temporary map (lives as long as the user is visiting the course)
-	 * @param owner the owning class
-	 * @param key the key
-	 * 
-	 * owner's classname and the key form a composite unique key / namespace
-	 */
-	public Map getTempMap(Class owner, String key);
-	
+
+	public boolean isAdmin();
 	
-	//TODO: add a method like isCourseAdmin() to be offered in a conditioninterpreter function
+	public boolean isCoach();
+
+	public boolean isParticipant();
 	
+	public boolean isIdentityInCourseGroup(Long groupKey);
+
 }
\ No newline at end of file
diff --git a/src/main/java/org/olat/course/run/userview/UserCourseEnvironmentImpl.java b/src/main/java/org/olat/course/run/userview/UserCourseEnvironmentImpl.java
index 87843f4d1ad..340cc3878cc 100644
--- a/src/main/java/org/olat/course/run/userview/UserCourseEnvironmentImpl.java
+++ b/src/main/java/org/olat/course/run/userview/UserCourseEnvironmentImpl.java
@@ -25,14 +25,16 @@
 
 package org.olat.course.run.userview;
 
-import java.util.HashMap;
-import java.util.Map;
+import java.util.List;
 
+import org.olat.core.commons.persistence.PersistenceHelper;
 import org.olat.core.id.IdentityEnvironment;
 import org.olat.course.condition.interpreter.ConditionInterpreter;
 import org.olat.course.editor.CourseEditorEnv;
+import org.olat.course.groupsandrights.CourseGroupManager;
 import org.olat.course.run.environment.CourseEnvironment;
 import org.olat.course.run.scoring.ScoreAccounting;
+import org.olat.group.BusinessGroup;
 
 /**
  * Initial Date:  Feb 6, 2004
@@ -44,48 +46,130 @@ public class UserCourseEnvironmentImpl implements UserCourseEnvironment {
 	private CourseEnvironment courseEnvironment;
 	private ConditionInterpreter conditionInterpreter;
 	private ScoreAccounting scoreAccounting;
-	private Map allTempMaps = new HashMap(4);
+	
+	private List<BusinessGroup> coachedGroups;
+	private List<BusinessGroup> participatingGroups;
+	private List<BusinessGroup> waitingLists;
+	
+	private Boolean coach;
+	private Boolean admin;
+	private Boolean participant;
 	
 	public UserCourseEnvironmentImpl(IdentityEnvironment identityEnvironment, CourseEnvironment courseEnvironment) {
+		this(identityEnvironment, courseEnvironment, null, null, null, null, null, null);
+	}
+	
+	public UserCourseEnvironmentImpl(IdentityEnvironment identityEnvironment, CourseEnvironment courseEnvironment,
+			List<BusinessGroup> coachedGroups, List<BusinessGroup> participatingGroups, List<BusinessGroup> waitingLists,
+			Boolean coach, Boolean admin, Boolean participant) {
 		this.courseEnvironment = courseEnvironment;
 		this.identityEnvironment = identityEnvironment;
 		this.scoreAccounting = new ScoreAccounting(this);
 		this.conditionInterpreter = new ConditionInterpreter(this);
+		this.coachedGroups = coachedGroups;
+		this.participatingGroups = participatingGroups;
+		this.waitingLists = waitingLists;
+		this.coach = coach;
+		this.admin = admin;
+		this.participant = participant;
 	}
 
 	/**
 	 * @return Returns the courseEnvironment.
 	 */
+	@Override
 	public CourseEnvironment getCourseEnvironment() {
 		return courseEnvironment;
 	}
-	
+
+	@Override
 	public IdentityEnvironment getIdentityEnvironment() {
 		return identityEnvironment;
 	}
 
+	@Override
 	public ConditionInterpreter getConditionInterpreter() {
 		return conditionInterpreter;
 	}
 
+	@Override
 	public ScoreAccounting getScoreAccounting() {
 		return scoreAccounting;
 	}
 
+	@Override
 	public CourseEditorEnv getCourseEditorEnv() {
 		// return null signalling this is real user environment
 		return null;
 	}
+	
+	@Override
+	public boolean isIdentityInCourseGroup(Long groupKey) {
+		if(coachedGroups != null && participatingGroups != null) {
+			return PersistenceHelper.listContainsObjectByKey(participatingGroups, groupKey)
+					|| PersistenceHelper.listContainsObjectByKey(coachedGroups, groupKey);
+		}
+		CourseGroupManager cgm = courseEnvironment.getCourseGroupManager();
+		return cgm.isIdentityInGroup(identityEnvironment.getIdentity(), groupKey);
+	}
+
+	@Override
+	public boolean isCoach() {
+		if(coach != null) {
+			return coach.booleanValue();
+		}
+		//lazy loading
+		CourseGroupManager cgm = courseEnvironment.getCourseGroupManager();
+		boolean coachLazy = cgm.isIdentityCourseCoach(identityEnvironment.getIdentity());
+		coach = new Boolean(coachLazy);
+		return coachLazy;
+	}
 
-	public Map getTempMap(Class owner, String key) {
-		// thread safe since only called by the gui dispatch thread of one user
-		String compKey = owner.getName()+":"+key;
-		Map m = (Map) allTempMaps.get(compKey);
-		if (m == null) {
-			m = new HashMap(4);
-			allTempMaps.put(compKey, m);
+	@Override
+	public boolean isAdmin() {
+		if(admin != null) {
+			return admin.booleanValue();
 		}
-		return m;
+		//lazy loading
+		CourseGroupManager cgm = courseEnvironment.getCourseGroupManager();
+		boolean admiLazy = cgm.isIdentityCourseAdministrator(identityEnvironment.getIdentity());
+		admin = new Boolean(admiLazy);
+		return admiLazy;
 	}
 
+	@Override
+	public boolean isParticipant() {
+		if(participant != null) {
+			return participant.booleanValue();
+		}
+		//lazy loading
+		CourseGroupManager cgm = courseEnvironment.getCourseGroupManager();
+		boolean partLazy = cgm.isIdentityCourseParticipant(identityEnvironment.getIdentity());
+		participant = new Boolean(partLazy);
+		return partLazy;
+	}
+
+	public List<BusinessGroup> getCoachedGroups() {
+		return coachedGroups;
+	}
+
+	public List<BusinessGroup> getParticipatingGroups() {
+		return participatingGroups;
+	}
+
+	public List<BusinessGroup> getWaitingLists() {
+		return waitingLists;
+	}
+	
+	public void setGroupMemberships(List<BusinessGroup> coachedGroups, List<BusinessGroup> participatingGroups, List<BusinessGroup> waitingLists) {
+		this.coachedGroups = coachedGroups;
+		this.participatingGroups = participatingGroups;
+		this.waitingLists = waitingLists;
+	}
+	
+	public void setUserRoles(boolean admin, boolean coach) {
+		this.admin = new Boolean(admin);
+		this.coach = new Boolean(coach);
+		this.participant = null;//reset it
+	}
 }
-- 
GitLab