From 8de8a24c68b14723ddf9d274232276ca344be092 Mon Sep 17 00:00:00 2001
From: srosse <none@none>
Date: Wed, 8 Jul 2015 21:24:19 +0200
Subject: [PATCH] OO-1603: add after course end date rule for reminders

---
 .../reminder/manager/ReminderRuleEngine.java  |   4 -
 .../rule/AbstractLaunchDateRuleSPI.java       |   5 -
 ...ryEntryLifecycleAfterValidFromRuleSPI.java |   4 +-
 ...toryEntryLifecycleAfterValidToRuleSPI.java | 122 ++++++++++++++++++
 ...ryEntryLifecycleAfterValidRuleEditor.java} |   8 +-
 .../{repo_valid.html => repo_valid_from.html} |   0
 .../reminder/ui/_content/repo_valid_to.html   |   6 +
 .../ui/_i18n/LocalStrings_de.properties       |   2 +
 .../ui/_i18n/LocalStrings_en.properties       |   2 +
 .../manager/ReminderRuleEngineTest.java       |  86 ++++++++++++
 10 files changed, 225 insertions(+), 14 deletions(-)
 create mode 100644 src/main/java/org/olat/modules/reminder/rule/RepositoryEntryLifecycleAfterValidToRuleSPI.java
 rename src/main/java/org/olat/modules/reminder/ui/{RepositoryEntryLifecycleAfterValidFromRuleEditor.java => RepositoryEntryLifecycleAfterValidRuleEditor.java} (92%)
 rename src/main/java/org/olat/modules/reminder/ui/_content/{repo_valid.html => repo_valid_from.html} (100%)
 create mode 100644 src/main/java/org/olat/modules/reminder/ui/_content/repo_valid_to.html

diff --git a/src/main/java/org/olat/modules/reminder/manager/ReminderRuleEngine.java b/src/main/java/org/olat/modules/reminder/manager/ReminderRuleEngine.java
index ac3f48448cf..b22df840e70 100644
--- a/src/main/java/org/olat/modules/reminder/manager/ReminderRuleEngine.java
+++ b/src/main/java/org/olat/modules/reminder/manager/ReminderRuleEngine.java
@@ -65,10 +65,6 @@ public class ReminderRuleEngine {
 	private DateRuleSPI dateRuleSpi;
 	@Autowired
 	private UserPropertyRuleSPI userPropertyRuleSpi;
-	@Autowired
-	private BusinessGroupRoleRuleSPI groupRoleRuleSpi;
-	@Autowired
-	private RepositoryEntryRoleRuleSPI repoRoleRuleSpi;
 	
 	@Autowired
 	private ReminderDAO reminderDao;
diff --git a/src/main/java/org/olat/modules/reminder/rule/AbstractLaunchDateRuleSPI.java b/src/main/java/org/olat/modules/reminder/rule/AbstractLaunchDateRuleSPI.java
index 0320968df7a..62bf2d833dc 100644
--- a/src/main/java/org/olat/modules/reminder/rule/AbstractLaunchDateRuleSPI.java
+++ b/src/main/java/org/olat/modules/reminder/rule/AbstractLaunchDateRuleSPI.java
@@ -25,14 +25,12 @@ import java.util.List;
 import java.util.Map;
 
 import org.olat.core.id.Identity;
-import org.olat.course.assessment.manager.UserCourseInformationsManager;
 import org.olat.modules.reminder.FilterRuleSPI;
 import org.olat.modules.reminder.ReminderRule;
 import org.olat.modules.reminder.RuleEditorFragment;
 import org.olat.modules.reminder.model.ReminderRuleImpl;
 import org.olat.modules.reminder.ui.CourseLaunchRuleEditor;
 import org.olat.repository.RepositoryEntry;
-import org.springframework.beans.factory.annotation.Autowired;
 
 /**
  * 
@@ -41,9 +39,6 @@ import org.springframework.beans.factory.annotation.Autowired;
  *
  */
 public abstract class AbstractLaunchDateRuleSPI  implements FilterRuleSPI {
-	
-	@Autowired
-	private UserCourseInformationsManager userCourseInformationsManager;
 
 	@Override
 	public String getCategory() {
diff --git a/src/main/java/org/olat/modules/reminder/rule/RepositoryEntryLifecycleAfterValidFromRuleSPI.java b/src/main/java/org/olat/modules/reminder/rule/RepositoryEntryLifecycleAfterValidFromRuleSPI.java
index 41b19ed8629..83d5b9161e3 100644
--- a/src/main/java/org/olat/modules/reminder/rule/RepositoryEntryLifecycleAfterValidFromRuleSPI.java
+++ b/src/main/java/org/olat/modules/reminder/rule/RepositoryEntryLifecycleAfterValidFromRuleSPI.java
@@ -27,7 +27,7 @@ import org.olat.modules.reminder.ReminderRule;
 import org.olat.modules.reminder.RepositoryEntryRuleSPI;
 import org.olat.modules.reminder.RuleEditorFragment;
 import org.olat.modules.reminder.model.ReminderRuleImpl;
-import org.olat.modules.reminder.ui.RepositoryEntryLifecycleAfterValidFromRuleEditor;
+import org.olat.modules.reminder.ui.RepositoryEntryLifecycleAfterValidRuleEditor;
 import org.olat.repository.RepositoryEntry;
 import org.olat.repository.model.RepositoryEntryLifecycle;
 import org.springframework.stereotype.Service;
@@ -60,7 +60,7 @@ public class RepositoryEntryLifecycleAfterValidFromRuleSPI implements Repository
 	
 	@Override
 	public RuleEditorFragment getEditorFragment(ReminderRule rule, RepositoryEntry entry) {
-		return new RepositoryEntryLifecycleAfterValidFromRuleEditor(rule, this.getClass().getSimpleName());
+		return new RepositoryEntryLifecycleAfterValidRuleEditor(rule, this.getClass().getSimpleName(), "/repo_valid_from.html");
 	}
 
 	@Override
diff --git a/src/main/java/org/olat/modules/reminder/rule/RepositoryEntryLifecycleAfterValidToRuleSPI.java b/src/main/java/org/olat/modules/reminder/rule/RepositoryEntryLifecycleAfterValidToRuleSPI.java
new file mode 100644
index 00000000000..201208cebe7
--- /dev/null
+++ b/src/main/java/org/olat/modules/reminder/rule/RepositoryEntryLifecycleAfterValidToRuleSPI.java
@@ -0,0 +1,122 @@
+/**
+ * <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.modules.reminder.rule;
+
+import java.util.Calendar;
+import java.util.Date;
+
+import org.olat.course.export.CourseEnvironmentMapper;
+import org.olat.modules.reminder.ReminderRule;
+import org.olat.modules.reminder.RepositoryEntryRuleSPI;
+import org.olat.modules.reminder.RuleEditorFragment;
+import org.olat.modules.reminder.model.ReminderRuleImpl;
+import org.olat.modules.reminder.ui.RepositoryEntryLifecycleAfterValidRuleEditor;
+import org.olat.repository.RepositoryEntry;
+import org.olat.repository.model.RepositoryEntryLifecycle;
+import org.springframework.stereotype.Service;
+
+
+/**
+ * 
+ * Initial date: 26.05.2015<br>
+ * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
+ *
+ */
+@Service
+public class RepositoryEntryLifecycleAfterValidToRuleSPI implements RepositoryEntryRuleSPI  {
+
+
+	@Override
+	public String getLabelI18nKey() {
+		return "rule.lifecycle.validto";
+	}
+	
+	@Override
+	public String getCategory() {
+		return "course";
+	}
+	
+	@Override
+	public ReminderRule clone(ReminderRule rule, CourseEnvironmentMapper envMapper) {
+		return rule.clone();
+	}
+	
+	@Override
+	public RuleEditorFragment getEditorFragment(ReminderRule rule, RepositoryEntry entry) {
+		return new RepositoryEntryLifecycleAfterValidRuleEditor(rule, this.getClass().getSimpleName(), "/repo_valid_to.html");
+	}
+
+	@Override
+	public boolean evaluate(RepositoryEntry entry, ReminderRule rule) {
+		boolean allOk = true;
+		if(rule instanceof ReminderRuleImpl) {
+			RepositoryEntryLifecycle lifecycle = entry.getLifecycle();
+			if(lifecycle != null && lifecycle.getValidTo() != null) {
+				allOk &= evaluate(lifecycle, rule);
+			} else {
+				allOk &= false;
+			}
+		}
+		return allOk;
+	}
+	
+	public boolean evaluate(RepositoryEntryLifecycle lifecycle, ReminderRule rule) {
+		Date now = cleanNow();
+		ReminderRuleImpl r = (ReminderRuleImpl)rule;
+		int distance = Integer.parseInt(r.getRightOperand());
+		LaunchUnit unit = LaunchUnit.valueOf(r.getRightUnit());
+		Date referenceDate = getDate(lifecycle.getValidTo(), distance, unit);
+		return now.compareTo(referenceDate) >= 0;
+	}
+
+	private Date cleanNow() {
+		Calendar cal = Calendar.getInstance();
+		cal.setTime(new Date());
+		cal.set(Calendar.HOUR_OF_DAY, 0);
+		cal.set(Calendar.MINUTE, 0);
+		cal.set(Calendar.SECOND, 0);
+		cal.set(Calendar.MILLISECOND, 0);
+		return cal.getTime();
+	}
+	
+	private Date getDate(Date date, int distance, LaunchUnit unit) {
+		Calendar cal = Calendar.getInstance();
+		cal.setTime(date);
+		switch(unit) {
+			case day:
+				cal.add(Calendar.DATE, distance);
+				break;
+			case week:
+				cal.add(Calendar.DATE, 7 * distance);
+				break;
+			case month:
+				cal.add(Calendar.MONTH, distance);
+				break;
+			case year:
+				cal.add(Calendar.YEAR, distance);
+				break;
+		}
+		cal.set(Calendar.HOUR_OF_DAY, 0);
+		cal.set(Calendar.MINUTE, 0);
+		cal.set(Calendar.SECOND, 0);
+		cal.set(Calendar.MILLISECOND, 0);
+		return cal.getTime();
+	}
+}
\ No newline at end of file
diff --git a/src/main/java/org/olat/modules/reminder/ui/RepositoryEntryLifecycleAfterValidFromRuleEditor.java b/src/main/java/org/olat/modules/reminder/ui/RepositoryEntryLifecycleAfterValidRuleEditor.java
similarity index 92%
rename from src/main/java/org/olat/modules/reminder/ui/RepositoryEntryLifecycleAfterValidFromRuleEditor.java
rename to src/main/java/org/olat/modules/reminder/ui/RepositoryEntryLifecycleAfterValidRuleEditor.java
index dd2cb38f50f..e9ed6535563 100644
--- a/src/main/java/org/olat/modules/reminder/ui/RepositoryEntryLifecycleAfterValidFromRuleEditor.java
+++ b/src/main/java/org/olat/modules/reminder/ui/RepositoryEntryLifecycleAfterValidRuleEditor.java
@@ -41,7 +41,7 @@ import org.olat.modules.reminder.rule.LaunchUnit;
  * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
  *
  */
-public class RepositoryEntryLifecycleAfterValidFromRuleEditor extends RuleEditorFragment {
+public class RepositoryEntryLifecycleAfterValidRuleEditor extends RuleEditorFragment {
 	
 	private static final String[] unitKeys = new String[]{
 		LaunchUnit.day.name(), LaunchUnit.week.name(), LaunchUnit.month.name(), LaunchUnit.year.name()
@@ -51,16 +51,18 @@ public class RepositoryEntryLifecycleAfterValidFromRuleEditor extends RuleEditor
 	private SingleSelection unitEl;
 	
 	private final String ruleType;
+	private final String templateName;
 	
-	public RepositoryEntryLifecycleAfterValidFromRuleEditor(ReminderRule rule, String ruleType) {
+	public RepositoryEntryLifecycleAfterValidRuleEditor(ReminderRule rule, String ruleType, String templateName) {
 		super(rule);
 		this.ruleType = ruleType;
+		this.templateName = templateName;
 	}
 
 	@Override
 	public FormItem initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) {
 		
-		String page = Util.getPackageVelocityRoot(this.getClass()) + "/repo_valid.html";
+		String page = Util.getPackageVelocityRoot(this.getClass()) + templateName;
 		String id = Long.toString(CodeHelper.getRAMUniqueID());
 		
 		Translator trans = formLayout.getTranslator();
diff --git a/src/main/java/org/olat/modules/reminder/ui/_content/repo_valid.html b/src/main/java/org/olat/modules/reminder/ui/_content/repo_valid_from.html
similarity index 100%
rename from src/main/java/org/olat/modules/reminder/ui/_content/repo_valid.html
rename to src/main/java/org/olat/modules/reminder/ui/_content/repo_valid_from.html
diff --git a/src/main/java/org/olat/modules/reminder/ui/_content/repo_valid_to.html b/src/main/java/org/olat/modules/reminder/ui/_content/repo_valid_to.html
new file mode 100644
index 00000000000..af590c51fb5
--- /dev/null
+++ b/src/main/java/org/olat/modules/reminder/ui/_content/repo_valid_to.html
@@ -0,0 +1,6 @@
+<div class='form-inline'>
+	$r.render("launchvalue$id") $r.render("launchunit$id") <span class="form-control-static">$r.translate("after.validto")</span>
+	#if($f.hasError("launchvalue$id"))
+		<br/>$r.render("launchvalue${id}_ERROR")
+	#end
+</div>
\ No newline at end of file
diff --git a/src/main/java/org/olat/modules/reminder/ui/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/modules/reminder/ui/_i18n/LocalStrings_de.properties
index 424afa848a5..1a8ad6c4af6 100644
--- a/src/main/java/org/olat/modules/reminder/ui/_i18n/LocalStrings_de.properties
+++ b/src/main/java/org/olat/modules/reminder/ui/_i18n/LocalStrings_de.properties
@@ -2,6 +2,7 @@
 admin.menu.title=Kurserinnerungen
 admin.menu.title.alt=Kurserinnerungen
 after.validfrom=nach Beginn
+after.validto=nach End
 ago=her
 default.send.time=Standard Sendezeit f\u00FCr Erinnerungen
 enable.reminders=Kurserinnerungen einschalten
@@ -21,6 +22,7 @@ rule.course.role=Kursrolle
 rule.group.member=Gruppenteilnehmer
 rule.initial.course.launch.date=Erster Kursbesuch
 rule.lifecycle.validfrom=Beginndatum von Kurs-Durchf\u00FChrungzeitraum
+rule.lifecycle.validto=Enddatum von Kurs-Durchf\u00FChrungzeitraum
 rule.recent.course.launch.date=Letzter Kursbesuch
 rule.user.property=Benutzereigenschaft
 
diff --git a/src/main/java/org/olat/modules/reminder/ui/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/modules/reminder/ui/_i18n/LocalStrings_en.properties
index b2817fd996b..440da7cb6bd 100644
--- a/src/main/java/org/olat/modules/reminder/ui/_i18n/LocalStrings_en.properties
+++ b/src/main/java/org/olat/modules/reminder/ui/_i18n/LocalStrings_en.properties
@@ -2,6 +2,7 @@
 admin.menu.title=Course reminders
 admin.menu.title.alt=Course reminders
 after.validfrom=after begin date
+after.validto=after end date
 ago=since
 default.send.time=Default time to send reminders
 enable.reminders=Activate course reminders
@@ -21,6 +22,7 @@ rule.course.enrollment.date=Enrollment date
 rule.course.role=Course role
 rule.group.member=Group member
 rule.lifecycle.validfrom=Begin date of execution period
+rule.lifecycle.validto=End date of execution period
 rule.initial.course.launch.date=Initial course launch date
 rule.recent.course.launch.date=Recent course launch date
 rule.user.property=User property
diff --git a/src/test/java/org/olat/modules/reminder/manager/ReminderRuleEngineTest.java b/src/test/java/org/olat/modules/reminder/manager/ReminderRuleEngineTest.java
index 8cfd80217b3..8e7e9e50151 100644
--- a/src/test/java/org/olat/modules/reminder/manager/ReminderRuleEngineTest.java
+++ b/src/test/java/org/olat/modules/reminder/manager/ReminderRuleEngineTest.java
@@ -58,6 +58,7 @@ import org.olat.modules.reminder.rule.InitialCourseLaunchRuleSPI;
 import org.olat.modules.reminder.rule.LaunchUnit;
 import org.olat.modules.reminder.rule.RecentCourseLaunchRuleSPI;
 import org.olat.modules.reminder.rule.RepositoryEntryLifecycleAfterValidFromRuleSPI;
+import org.olat.modules.reminder.rule.RepositoryEntryLifecycleAfterValidToRuleSPI;
 import org.olat.modules.reminder.rule.RepositoryEntryRoleRuleSPI;
 import org.olat.modules.reminder.rule.UserPropertyRuleSPI;
 import org.olat.repository.RepositoryEntry;
@@ -744,6 +745,91 @@ public class ReminderRuleEngineTest extends OlatTestCase {
 		rules.add(rule);
 		return rules;
 	}
+
+	@Test
+	public void afterEndDate() {
+		//create a course with 3 members
+		Identity id1 = JunitTestHelper.createAndPersistIdentityAsRndUser("after-end-1");
+		Identity id2 = JunitTestHelper.createAndPersistIdentityAsRndUser("after-end-2");
+		Identity id3 = JunitTestHelper.createAndPersistIdentityAsRndUser("after-end-3");
+
+		ICourse course = CoursesWebService.createEmptyCourse(null, "initial-launch-dates", "course long name", null);
+		RepositoryEntry re = course.getCourseEnvironment().getCourseGroupManager().getCourseEntry();
+		
+		Calendar cal = Calendar.getInstance();
+		cal.setTime(new Date());//now
+		cal.add(Calendar.DATE, -25);
+		Date validFrom = cal.getTime();
+		cal.add(Calendar.DATE, 4);//- 3weeks
+		Date validTo = cal.getTime();
+		
+		RepositoryEntryLifecycle cycle = lifecycleDao.create("Cycle 2", "Cycle soft 2", false, validFrom, validTo);
+		re = repositoryManager.setDescriptionAndName(re, null, null, null, null, null, null, cycle);
+		repositoryEntryRelationDao.addRole(id1, re, GroupRoles.owner.name());
+		repositoryEntryRelationDao.addRole(id2, re, GroupRoles.coach.name());
+		repositoryEntryRelationDao.addRole(id3, re, GroupRoles.participant.name());
+		dbInstance.commit();
+		
+		{ // check after 2 days
+			List<ReminderRule> rules = getRepositoryEntryLifecycleRuleValidToRule(2, LaunchUnit.day);
+			boolean match = ruleEngine.evaluateRepositoryEntryRule(re, rules);
+			Assert.assertTrue(match);
+		}
+		
+		{ // check after 7 days (between begin and and date)
+			List<ReminderRule> rules = getRepositoryEntryLifecycleRuleValidToRule(7, LaunchUnit.day);
+			boolean match = ruleEngine.evaluateRepositoryEntryRule(re, rules);
+			Assert.assertTrue(match);
+		}
+		
+		{ // check after 2 week s
+			List<ReminderRule> rules = getRepositoryEntryLifecycleRuleValidToRule(1, LaunchUnit.week);
+			boolean match = ruleEngine.evaluateRepositoryEntryRule(re, rules);
+			Assert.assertTrue(match);
+		}
+		
+		{ // check after 21 days
+			List<ReminderRule> rules = getRepositoryEntryLifecycleRuleValidToRule(21, LaunchUnit.day);
+			boolean match = ruleEngine.evaluateRepositoryEntryRule(re, rules);
+			Assert.assertTrue(match);
+		}
+		
+		{ // check after 3 weeks
+			List<ReminderRule> rules = getRepositoryEntryLifecycleRuleValidToRule(3, LaunchUnit.week);
+			boolean match = ruleEngine.evaluateRepositoryEntryRule(re, rules);
+			Assert.assertTrue(match);
+		}
+		
+		{ // check after 22 days
+			List<ReminderRule> rules = getRepositoryEntryLifecycleRuleValidToRule(22, LaunchUnit.day);
+			boolean match = ruleEngine.evaluateRepositoryEntryRule(re, rules);
+			Assert.assertFalse(match);
+		}
+		
+		{ // check after 4 weeks
+			List<ReminderRule> rules = getRepositoryEntryLifecycleRuleValidToRule(4, LaunchUnit.week);
+			boolean match = ruleEngine.evaluateRepositoryEntryRule(re, rules);
+			Assert.assertFalse(match);
+		}
+		
+		{ // check after 1 month
+			List<ReminderRule> rules = getRepositoryEntryLifecycleRuleValidToRule(1, LaunchUnit.month);
+			boolean match = ruleEngine.evaluateRepositoryEntryRule(re, rules);
+			Assert.assertFalse(match);
+		}
+	}
+	
+	private List<ReminderRule> getRepositoryEntryLifecycleRuleValidToRule(int amount, LaunchUnit unit) {
+		ReminderRuleImpl rule = new ReminderRuleImpl();
+		rule.setType(RepositoryEntryLifecycleAfterValidToRuleSPI.class.getSimpleName());
+		rule.setOperator(">");
+		rule.setRightOperand(Integer.toString(amount));
+		rule.setRightUnit(unit.name());
+		
+		List<ReminderRule> rules = new ArrayList<>(1);
+		rules.add(rule);
+		return rules;
+	}
 	
 	@Test
 	public void score() {
-- 
GitLab