From 40d08e8664533ca975f8b0cb2f95e40ec8c28bdb Mon Sep 17 00:00:00 2001
From: gnaegi <none@none>
Date: Wed, 9 Oct 2013 13:47:17 +0200
Subject: [PATCH] OO-808 allow do not count self-references as cyclic
 dependencies for most cases

---
 .../score/GetOnyxTestOutcomeAnumFunction.java          |  7 +++++--
 .../score/GetOnyxTestOutcomeNumFunction.java           |  7 +++++--
 .../condition/interpreter/ConditionInterpreter.java    |  1 +
 .../condition/interpreter/GetAttemptsFunction.java     |  7 +++++--
 .../interpreter/GetInitialEnrollmentDateFunction.java  |  7 +++++--
 .../interpreter/GetRecentEnrollmentDateFunction.java   |  7 +++++--
 .../condition/interpreter/score/GetPassedFunction.java | 10 ++++++++--
 .../condition/interpreter/score/GetScoreFunction.java  | 10 ++++++++--
 8 files changed, 42 insertions(+), 14 deletions(-)

diff --git a/src/main/java/de/bps/course/condition/interpreter/score/GetOnyxTestOutcomeAnumFunction.java b/src/main/java/de/bps/course/condition/interpreter/score/GetOnyxTestOutcomeAnumFunction.java
index b7d4242b2ea..b9cebaa3ddd 100644
--- a/src/main/java/de/bps/course/condition/interpreter/score/GetOnyxTestOutcomeAnumFunction.java
+++ b/src/main/java/de/bps/course/condition/interpreter/score/GetOnyxTestOutcomeAnumFunction.java
@@ -91,8 +91,11 @@ public class GetOnyxTestOutcomeAnumFunction extends AbstractFunction {
 					"error.notfound.coursenodeid", "solution.copypastenodeid")); }
 			if (!cev.isAssessable(nodeId)) { return handleException(new ArgumentParseException(ArgumentParseException.REFERENCE_NOT_FOUND, name,
 					nodeId, "error.notassessable.coursenodid", "solution.takeassessablenode")); }
-			// remember the reference to the node id for this condtion
-			cev.addSoftReference("courseNodeId", nodeId);
+			// Remember the reference to the node id for this condition for cycle testing. 
+			// Allow self-referencing but do not allow dependencies to parents as they create cycles.
+			if (!nodeId.equals(cev.getCurrentCourseNodeId())) {
+				cev.addSoftReference("courseNodeId", nodeId);				
+			}
 		}
 		
 
diff --git a/src/main/java/de/bps/course/condition/interpreter/score/GetOnyxTestOutcomeNumFunction.java b/src/main/java/de/bps/course/condition/interpreter/score/GetOnyxTestOutcomeNumFunction.java
index bda29c9925e..22021db0099 100644
--- a/src/main/java/de/bps/course/condition/interpreter/score/GetOnyxTestOutcomeNumFunction.java
+++ b/src/main/java/de/bps/course/condition/interpreter/score/GetOnyxTestOutcomeNumFunction.java
@@ -91,8 +91,11 @@ public class GetOnyxTestOutcomeNumFunction extends AbstractFunction {
 					"error.notfound.coursenodeid", "solution.copypastenodeid")); }
 			if (!cev.isAssessable(nodeId)) { return handleException(new ArgumentParseException(ArgumentParseException.REFERENCE_NOT_FOUND, name,
 					nodeId, "error.notassessable.coursenodid", "solution.takeassessablenode")); }
-			// remember the reference to the node id for this condtion
-			cev.addSoftReference("courseNodeId", nodeId);
+			// Remember the reference to the node id for this condition for cycle testing. 
+			// Allow self-referencing but do not allow dependencies to parents as they create cycles.
+			if (!nodeId.equals(cev.getCurrentCourseNodeId())) {
+				cev.addSoftReference("courseNodeId", nodeId);				
+			}
 		}
 		
 		//<OLATCE-1088>
diff --git a/src/main/java/org/olat/course/condition/interpreter/ConditionInterpreter.java b/src/main/java/org/olat/course/condition/interpreter/ConditionInterpreter.java
index 914ecca680f..1ab0227e5e5 100644
--- a/src/main/java/org/olat/course/condition/interpreter/ConditionInterpreter.java
+++ b/src/main/java/org/olat/course/condition/interpreter/ConditionInterpreter.java
@@ -137,6 +137,7 @@ public class ConditionInterpreter {
 		env.addFunction(GetRecentCourseLaunchDateFunction.name, new GetRecentCourseLaunchDateFunction(userCourseEnv));
 
 		env.addFunction(GetAttemptsFunction.name, new GetAttemptsFunction(userCourseEnv));
+		env.addFunction(GetLastAttemptDateFunction.name, new GetLastAttemptDateFunction(userCourseEnv));
 
 		// enrollment building block specific functions
 		env.addFunction(GetInitialEnrollmentDateFunction.name, new GetInitialEnrollmentDateFunction(userCourseEnv));
diff --git a/src/main/java/org/olat/course/condition/interpreter/GetAttemptsFunction.java b/src/main/java/org/olat/course/condition/interpreter/GetAttemptsFunction.java
index 2bf81aefecf..191bcb60651 100644
--- a/src/main/java/org/olat/course/condition/interpreter/GetAttemptsFunction.java
+++ b/src/main/java/org/olat/course/condition/interpreter/GetAttemptsFunction.java
@@ -80,8 +80,11 @@ public class GetAttemptsFunction extends AbstractFunction {
 		if (cev != null) {
 			if (!cev.existsNode(nodeId)) { return handleException(new ArgumentParseException(ArgumentParseException.REFERENCE_NOT_FOUND, name,
 					nodeId, "error.notfound.coursenodeid", "solution.copypastenodeid")); }
-			// remember the reference to the node id for this condtion
-			cev.addSoftReference("courseNodeId", nodeId);
+			// Remember the reference to the node id for this condition for cycle testing. 
+			// Allow self-referencing but do not allow dependencies to parents as they create cycles.
+			if (!nodeId.equals(cev.getCurrentCourseNodeId())) {
+				cev.addSoftReference("courseNodeId", nodeId);				
+			}
 			// return a valid value to continue with condition evaluation test
 			return defaultValue();
 		}
diff --git a/src/main/java/org/olat/course/condition/interpreter/GetInitialEnrollmentDateFunction.java b/src/main/java/org/olat/course/condition/interpreter/GetInitialEnrollmentDateFunction.java
index 1ea3c949260..ddf254b322e 100644
--- a/src/main/java/org/olat/course/condition/interpreter/GetInitialEnrollmentDateFunction.java
+++ b/src/main/java/org/olat/course/condition/interpreter/GetInitialEnrollmentDateFunction.java
@@ -82,8 +82,11 @@ public class GetInitialEnrollmentDateFunction extends AbstractFunction {
 					nodeId, "error.notfound.coursenodeid", "solution.copypastenodeid")); }
 			if (!cev.isEnrollmentNode(nodeId)) { return handleException(new ArgumentParseException(ArgumentParseException.REFERENCE_NOT_FOUND, name,
 					nodeId, "error.notenrollment.coursenodeid", "solution.chooseenrollment")); }
-			// remember the reference to the node id for this condtion
-			cev.addSoftReference("courseNodeId", nodeId);
+			// Remember the reference to the node id for this condition for cycle testing. 
+			// Allow self-referencing but do not allow dependencies to parents as they create cycles.
+			if (!nodeId.equals(cev.getCurrentCourseNodeId())) {
+				cev.addSoftReference("courseNodeId", nodeId);				
+			}
 			// return a valid value to continue with condition evaluation test
 			return defaultValue();
 		}
diff --git a/src/main/java/org/olat/course/condition/interpreter/GetRecentEnrollmentDateFunction.java b/src/main/java/org/olat/course/condition/interpreter/GetRecentEnrollmentDateFunction.java
index 77cc46a4c0d..9613b8699ab 100644
--- a/src/main/java/org/olat/course/condition/interpreter/GetRecentEnrollmentDateFunction.java
+++ b/src/main/java/org/olat/course/condition/interpreter/GetRecentEnrollmentDateFunction.java
@@ -81,8 +81,11 @@ public class GetRecentEnrollmentDateFunction extends AbstractFunction {
 					"error.notfound.coursenodeid", "solution.copypastenodeid")); }
 			if (!cev.isEnrollmentNode(nodeId)) { return handleException(new ArgumentParseException(ArgumentParseException.REFERENCE_NOT_FOUND, name,
 					nodeId, "error.notenrollment.coursenodeid", "solution.chooseenrollment")); }
-			// remember the reference to the node id for this condtion
-			cev.addSoftReference("courseNodeId", nodeId);
+			// Remember the reference to the node id for this condition for cycle testing. 
+			// Allow self-referencing but do not allow dependencies to parents as they create cycles.
+			if (!nodeId.equals(cev.getCurrentCourseNodeId())) {
+				cev.addSoftReference("courseNodeId", nodeId);				
+			}
 			// return a valid value to continue with condition evaluation test
 			return defaultValue();
 		}
diff --git a/src/main/java/org/olat/course/condition/interpreter/score/GetPassedFunction.java b/src/main/java/org/olat/course/condition/interpreter/score/GetPassedFunction.java
index df9088608c4..15d56759d9e 100644
--- a/src/main/java/org/olat/course/condition/interpreter/score/GetPassedFunction.java
+++ b/src/main/java/org/olat/course/condition/interpreter/score/GetPassedFunction.java
@@ -29,6 +29,7 @@ import org.olat.course.condition.interpreter.AbstractFunction;
 import org.olat.course.condition.interpreter.ArgumentParseException;
 import org.olat.course.condition.interpreter.ConditionInterpreter;
 import org.olat.course.editor.CourseEditorEnv;
+import org.olat.course.nodes.STCourseNode;
 import org.olat.course.run.scoring.ScoreAccounting;
 import org.olat.course.run.userview.UserCourseEnvironment;
 
@@ -76,8 +77,13 @@ public class GetPassedFunction extends AbstractFunction {
 					"error.notfound.coursenodeid", "solution.copypastenodeid")); }
 			if (!cev.isAssessable(childId)) { return handleException(new ArgumentParseException(ArgumentParseException.REFERENCE_NOT_FOUND, name,
 					childId, "error.notassessable.coursenodid", "solution.takeassessablenode")); }
-			// remember the reference to the node id for this condtion
-			cev.addSoftReference("courseNodeId", childId);
+			// Remember the reference to the node id for this condition for cycle testing. 
+			// Allow testing against own passed (self-referencing) except for ST
+			// course nodes as passed is calculated on these node. Do not allow
+			// dependencies to parents as they create cycles.
+			if (!childId.equals(cev.getCurrentCourseNodeId()) || cev.getNode(cev.getCurrentCourseNodeId()) instanceof STCourseNode) {
+				cev.addSoftReference("courseNodeId", childId);				
+			}
 			// return a valid value to continue with condition evaluation test
 			return defaultValue();
 		}
diff --git a/src/main/java/org/olat/course/condition/interpreter/score/GetScoreFunction.java b/src/main/java/org/olat/course/condition/interpreter/score/GetScoreFunction.java
index b50eaea5a08..e599c657b31 100644
--- a/src/main/java/org/olat/course/condition/interpreter/score/GetScoreFunction.java
+++ b/src/main/java/org/olat/course/condition/interpreter/score/GetScoreFunction.java
@@ -28,6 +28,7 @@ package org.olat.course.condition.interpreter.score;
 import org.olat.course.condition.interpreter.AbstractFunction;
 import org.olat.course.condition.interpreter.ArgumentParseException;
 import org.olat.course.editor.CourseEditorEnv;
+import org.olat.course.nodes.STCourseNode;
 import org.olat.course.run.scoring.ScoreAccounting;
 import org.olat.course.run.userview.UserCourseEnvironment;
 
@@ -74,8 +75,13 @@ public class GetScoreFunction extends AbstractFunction {
 					"error.notfound.coursenodeid", "solution.copypastenodeid")); }
 			if (!cev.isAssessable(childId)) { return handleException(new ArgumentParseException(ArgumentParseException.REFERENCE_NOT_FOUND, name,
 					childId, "error.notassessable.coursenodid", "solution.takeassessablenode")); }
-			// remember the reference to the node id for this condtion
-			cev.addSoftReference("courseNodeId", childId);
+			// Remember the reference to the node id for this condition for cycle testing. 
+			// Allow testing against own score (self-referencing) except for ST
+			// course nodes as score is calculated on these node. Do not allow
+			// dependencies to parents as they create cycles.
+			if (!childId.equals(cev.getCurrentCourseNodeId()) || cev.getNode(cev.getCurrentCourseNodeId()) instanceof STCourseNode) {
+				cev.addSoftReference("courseNodeId", childId);				
+			}
 			// return a valid value to continue with condition evaluation test
 			return defaultValue();
 		}
-- 
GitLab