From 15aa987e07aa2a53bf0fcc5f6208dde81cc702d7 Mon Sep 17 00:00:00 2001 From: srosse <none@none> Date: Tue, 12 May 2015 11:15:42 +0200 Subject: [PATCH] OO-1494: implements copy/import/export of reminders --- .../org/olat/course/PersistingCourseImpl.java | 6 ++ .../nodes/gta/rule/AssignTaskRuleSPI.java | 7 ++ .../nodes/gta/rule/SubmissionTaskRuleSPI.java | 7 ++ .../course/reminder/rule/AttemptsRuleSPI.java | 7 ++ .../reminder/rule/InitialAttemptsRuleSPI.java | 6 ++ .../course/reminder/rule/PassedRuleSPI.java | 6 ++ .../course/reminder/rule/ScoreRuleSPI.java | 6 ++ .../ui/CourseReminderEditController.java | 3 +- .../qti/repository/handlers/QTIHandler.java | 2 +- .../olat/modules/reminder/ReminderRule.java | 5 +- .../modules/reminder/ReminderService.java | 15 ++++ .../org/olat/modules/reminder/RuleSPI.java | 3 + .../reminder/manager/ReminderServiceImpl.java | 55 ++++++++++++++ .../reminder/model/ImportExportReminder.java | 74 +++++++++++++++++++ .../reminder/model/ImportExportReminders.java | 51 +++++++++++++ .../reminder/model/ReminderRuleImpl.java | 11 +++ .../rule/BusinessGroupRoleRuleSPI.java | 21 ++++++ .../rule/CourseEnrollmentDateRuleSPI.java | 6 ++ .../modules/reminder/rule/DateRuleSPI.java | 6 ++ .../rule/InitialCourseLaunchRuleSPI.java | 6 ++ .../rule/RecentCourseLaunchRuleSPI.java | 6 ++ .../rule/RepositoryEntryRoleRuleSPI.java | 6 ++ .../reminder/rule/UserPropertyRuleSPI.java | 8 +- .../olat/repository/handlers/BlogHandler.java | 2 +- .../repository/handlers/CourseHandler.java | 62 +++++++++++++++- .../repository/handlers/GlossaryHandler.java | 2 +- .../repository/handlers/ImsCPHandler.java | 2 +- .../repository/handlers/PodcastHandler.java | 2 +- .../repository/handlers/PortfolioHandler.java | 2 +- .../handlers/RepositoryHandler.java | 2 +- .../repository/handlers/SCORMCPHandler.java | 2 +- .../handlers/SharedFolderHandler.java | 2 +- .../handlers/WebDocumentHandler.java | 2 +- .../olat/repository/handlers/WikiHandler.java | 2 +- .../manager/RepositoryServiceImpl.java | 2 +- .../repository/course/CoursesWebService.java | 2 +- 36 files changed, 391 insertions(+), 18 deletions(-) create mode 100644 src/main/java/org/olat/modules/reminder/model/ImportExportReminder.java create mode 100644 src/main/java/org/olat/modules/reminder/model/ImportExportReminders.java diff --git a/src/main/java/org/olat/course/PersistingCourseImpl.java b/src/main/java/org/olat/course/PersistingCourseImpl.java index 942e107b88d..e711d18d0d5 100644 --- a/src/main/java/org/olat/course/PersistingCourseImpl.java +++ b/src/main/java/org/olat/course/PersistingCourseImpl.java @@ -29,6 +29,7 @@ import java.io.File; import java.io.Serializable; import org.olat.admin.quota.QuotaConstants; +import org.olat.core.CoreSpringFactory; import org.olat.core.commons.modules.bc.vfs.OlatRootFolderImpl; import org.olat.core.commons.persistence.DBFactory; import org.olat.core.id.IdentityEnvironment; @@ -63,6 +64,7 @@ import org.olat.course.run.environment.CourseEnvironmentImpl; import org.olat.course.tree.CourseEditorTreeModel; import org.olat.course.tree.CourseEditorTreeNode; import org.olat.modules.glossary.GlossaryManager; +import org.olat.modules.reminder.ReminderService; import org.olat.modules.sharedfolder.SharedFolderManager; import org.olat.repository.RepositoryEntry; import org.olat.repository.RepositoryEntryImportExport; @@ -375,6 +377,10 @@ public class PersistingCourseImpl implements ICourse, OLATResourceable, Serializ // pro increased transaction timeout: would fix OLAT-5368 but only move the problem //@TODO OLAT-2597: real solution is a long-running background-task concept... DBFactory.getInstance().intermediateCommit(); + + //export reminders + CoreSpringFactory.getImpl(ReminderService.class) + .exportReminders(myRE, fExportedDataDir); log.info("exportToFilesystem: exporting course "+this+" to "+exportDirectory+" done."); log.info("finished export course '"+getCourseTitle()+"' in t="+Long.toString(System.currentTimeMillis()-s)); diff --git a/src/main/java/org/olat/course/nodes/gta/rule/AssignTaskRuleSPI.java b/src/main/java/org/olat/course/nodes/gta/rule/AssignTaskRuleSPI.java index 6d8feebbe27..03716a7e7f2 100644 --- a/src/main/java/org/olat/course/nodes/gta/rule/AssignTaskRuleSPI.java +++ b/src/main/java/org/olat/course/nodes/gta/rule/AssignTaskRuleSPI.java @@ -24,6 +24,7 @@ import java.util.List; import org.olat.core.id.Identity; import org.olat.core.util.StringHelper; +import org.olat.course.export.CourseEnvironmentMapper; import org.olat.course.nodes.GTACourseNode; import org.olat.course.nodes.gta.ui.BeforeDateTaskRuleEditor; import org.olat.modules.ModuleConfiguration; @@ -56,6 +57,12 @@ public class AssignTaskRuleSPI extends AbstractDueDateTaskRuleSPI { public RuleEditorFragment getEditorFragment(ReminderRule rule, RepositoryEntry entry) { return new BeforeDateTaskRuleEditor(rule, entry, AssignTaskRuleSPI.class.getSimpleName()); } + + @Override + public ReminderRule clone(ReminderRule rule, CourseEnvironmentMapper envMapper) { + //node ident must be the same + return rule.clone(); + } @Override protected Date getDueDate(GTACourseNode gtaNode) { diff --git a/src/main/java/org/olat/course/nodes/gta/rule/SubmissionTaskRuleSPI.java b/src/main/java/org/olat/course/nodes/gta/rule/SubmissionTaskRuleSPI.java index 326c05d16b1..65fc25feb01 100644 --- a/src/main/java/org/olat/course/nodes/gta/rule/SubmissionTaskRuleSPI.java +++ b/src/main/java/org/olat/course/nodes/gta/rule/SubmissionTaskRuleSPI.java @@ -24,6 +24,7 @@ import java.util.List; import org.olat.core.id.Identity; import org.olat.core.util.StringHelper; +import org.olat.course.export.CourseEnvironmentMapper; import org.olat.course.nodes.GTACourseNode; import org.olat.course.nodes.gta.GTAManager; import org.olat.course.nodes.gta.ui.BeforeDateTaskRuleEditor; @@ -67,6 +68,12 @@ public class SubmissionTaskRuleSPI extends AbstractDueDateTaskRuleSPI { public RuleEditorFragment getEditorFragment(ReminderRule rule, RepositoryEntry entry) { return new BeforeDateTaskRuleEditor(rule, entry, SubmissionTaskRuleSPI.class.getSimpleName()); } + + @Override + public ReminderRule clone(ReminderRule rule, CourseEnvironmentMapper envMapper) { + // node ident must be the same + return rule.clone(); + } @Override protected Date getDueDate(GTACourseNode gtaNode) { diff --git a/src/main/java/org/olat/course/reminder/rule/AttemptsRuleSPI.java b/src/main/java/org/olat/course/reminder/rule/AttemptsRuleSPI.java index ee603df759c..bc7d744c91d 100644 --- a/src/main/java/org/olat/course/reminder/rule/AttemptsRuleSPI.java +++ b/src/main/java/org/olat/course/reminder/rule/AttemptsRuleSPI.java @@ -26,6 +26,7 @@ import java.util.Map; import org.olat.core.id.Identity; import org.olat.course.CourseFactory; import org.olat.course.ICourse; +import org.olat.course.export.CourseEnvironmentMapper; import org.olat.course.nodes.CourseNode; import org.olat.course.reminder.manager.ReminderRuleDAO; import org.olat.course.reminder.ui.AttemptsRuleEditor; @@ -63,6 +64,12 @@ public class AttemptsRuleSPI implements FilterRuleSPI { public RuleEditorFragment getEditorFragment(ReminderRule rule, RepositoryEntry entry) { return new AttemptsRuleEditor(rule, entry); } + + @Override + public ReminderRule clone(ReminderRule rule, CourseEnvironmentMapper envMapper) { + //the node ident must be the same + return rule.clone(); + } @Override public void filter(RepositoryEntry entry, List<Identity> identities, ReminderRule rule) { diff --git a/src/main/java/org/olat/course/reminder/rule/InitialAttemptsRuleSPI.java b/src/main/java/org/olat/course/reminder/rule/InitialAttemptsRuleSPI.java index aa0645bde87..eb8c5e1640c 100644 --- a/src/main/java/org/olat/course/reminder/rule/InitialAttemptsRuleSPI.java +++ b/src/main/java/org/olat/course/reminder/rule/InitialAttemptsRuleSPI.java @@ -26,6 +26,7 @@ import java.util.Map; import org.olat.core.id.Identity; import org.olat.course.CourseFactory; import org.olat.course.ICourse; +import org.olat.course.export.CourseEnvironmentMapper; import org.olat.course.nodes.CourseNode; import org.olat.course.reminder.manager.ReminderRuleDAO; import org.olat.course.reminder.ui.InitialAttemptsRuleEditor; @@ -63,6 +64,11 @@ public class InitialAttemptsRuleSPI extends AbstractLaunchDateRuleSPI { public RuleEditorFragment getEditorFragment(ReminderRule rule, RepositoryEntry entry) { return new InitialAttemptsRuleEditor(rule, entry); } + + @Override + public ReminderRule clone(ReminderRule rule, CourseEnvironmentMapper envMapper) { + return rule.clone(); + } @Override protected Map<Long, Date> getLaunchDates(ReminderRule rule, RepositoryEntry entry, List<Identity> identities) { diff --git a/src/main/java/org/olat/course/reminder/rule/PassedRuleSPI.java b/src/main/java/org/olat/course/reminder/rule/PassedRuleSPI.java index 49672fdb526..d365bbe40e0 100644 --- a/src/main/java/org/olat/course/reminder/rule/PassedRuleSPI.java +++ b/src/main/java/org/olat/course/reminder/rule/PassedRuleSPI.java @@ -26,6 +26,7 @@ import java.util.Map; import org.olat.core.id.Identity; import org.olat.course.CourseFactory; import org.olat.course.ICourse; +import org.olat.course.export.CourseEnvironmentMapper; import org.olat.course.nodes.CourseNode; import org.olat.course.reminder.manager.ReminderRuleDAO; import org.olat.course.reminder.ui.PassedRuleEditor; @@ -63,6 +64,11 @@ public class PassedRuleSPI implements FilterRuleSPI { public RuleEditorFragment getEditorFragment(ReminderRule rule, RepositoryEntry entry) { return new PassedRuleEditor(rule, entry); } + + @Override + public ReminderRule clone(ReminderRule rule, CourseEnvironmentMapper envMapper) { + return rule.clone(); + } @Override public void filter(RepositoryEntry entry, List<Identity> identities, ReminderRule rule) { diff --git a/src/main/java/org/olat/course/reminder/rule/ScoreRuleSPI.java b/src/main/java/org/olat/course/reminder/rule/ScoreRuleSPI.java index 5e3d53b8ced..bf1290ccefd 100644 --- a/src/main/java/org/olat/course/reminder/rule/ScoreRuleSPI.java +++ b/src/main/java/org/olat/course/reminder/rule/ScoreRuleSPI.java @@ -26,6 +26,7 @@ import java.util.Map; import org.olat.core.id.Identity; import org.olat.course.CourseFactory; import org.olat.course.ICourse; +import org.olat.course.export.CourseEnvironmentMapper; import org.olat.course.nodes.CourseNode; import org.olat.course.reminder.manager.ReminderRuleDAO; import org.olat.course.reminder.ui.ScoreRuleEditor; @@ -65,6 +66,11 @@ public class ScoreRuleSPI implements FilterRuleSPI { public RuleEditorFragment getEditorFragment(ReminderRule rule, RepositoryEntry entry) { return new ScoreRuleEditor(rule, entry); } + + @Override + public ReminderRule clone(ReminderRule rule, CourseEnvironmentMapper envMapper) { + return rule.clone(); + } @Override public void filter(RepositoryEntry entry, List<Identity> identities, ReminderRule rule) { diff --git a/src/main/java/org/olat/course/reminder/ui/CourseReminderEditController.java b/src/main/java/org/olat/course/reminder/ui/CourseReminderEditController.java index 46dd6dfec49..8ec2df8c735 100644 --- a/src/main/java/org/olat/course/reminder/ui/CourseReminderEditController.java +++ b/src/main/java/org/olat/course/reminder/ui/CourseReminderEditController.java @@ -145,8 +145,7 @@ public class CourseReminderEditController extends FormBasicController { formLayout.add(contentCont); String emailContent = reminder == null ? null : reminder.getEmailBody(); - //TODO - if(StringHelper.containsNonWhitespace(emailContent)) { + if(!StringHelper.containsNonWhitespace(emailContent)) { emailContent = translate("reminder.def.body"); } emailEl = uifactory.addRichTextElementForStringDataMinimalistic("email.content", "email.content", emailContent, 10, 60, contentCont, getWindowControl()); diff --git a/src/main/java/org/olat/ims/qti/repository/handlers/QTIHandler.java b/src/main/java/org/olat/ims/qti/repository/handlers/QTIHandler.java index d03b6785982..bc687eb2cc5 100644 --- a/src/main/java/org/olat/ims/qti/repository/handlers/QTIHandler.java +++ b/src/main/java/org/olat/ims/qti/repository/handlers/QTIHandler.java @@ -107,7 +107,7 @@ public abstract class QTIHandler extends FileHandler { } @Override - public RepositoryEntry copy(RepositoryEntry source, RepositoryEntry target) { + public RepositoryEntry copy(Identity author, RepositoryEntry source, RepositoryEntry target) { OLATResource sourceResource = source.getOlatResource(); OLATResource targetResource = target.getOlatResource(); //getFileResource search the first zip diff --git a/src/main/java/org/olat/modules/reminder/ReminderRule.java b/src/main/java/org/olat/modules/reminder/ReminderRule.java index 63c5596224c..9f9c2204822 100644 --- a/src/main/java/org/olat/modules/reminder/ReminderRule.java +++ b/src/main/java/org/olat/modules/reminder/ReminderRule.java @@ -19,14 +19,17 @@ */ package org.olat.modules.reminder; + /** * * Initial date: 07.04.2015<br> * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com * */ -public interface ReminderRule { +public interface ReminderRule extends Cloneable { public String getType(); + + public ReminderRule clone(); } diff --git a/src/main/java/org/olat/modules/reminder/ReminderService.java b/src/main/java/org/olat/modules/reminder/ReminderService.java index d268025f776..e6c2cb964b5 100644 --- a/src/main/java/org/olat/modules/reminder/ReminderService.java +++ b/src/main/java/org/olat/modules/reminder/ReminderService.java @@ -19,6 +19,7 @@ */ package org.olat.modules.reminder; +import java.io.File; import java.util.List; import org.olat.core.id.Identity; @@ -35,6 +36,8 @@ import org.olat.repository.RepositoryEntryRef; * */ public interface ReminderService { + + public static final String REMINDERS_XML = "Reminders.xml"; /** * Create a non-persisted reminder. @@ -47,6 +50,8 @@ public interface ReminderService { public Reminder loadByKey(Long key); + public List<Reminder> getReminders(RepositoryEntryRef entry); + public List<ReminderInfos> getReminderInfos(RepositoryEntryRef entry); public Reminder duplicate(Reminder toCopy); @@ -80,5 +85,15 @@ public interface ReminderService { public String toXML(ReminderRules rules); public ReminderRules toRules(String rulesXml); + + public void exportReminders(RepositoryEntry entry, File fExportedDataDir); + + /** + * The reminders are not persisted and not converted to any new course, group... + * + * @param fExportedDataDir + * @return + */ + public List<Reminder> importRawReminders(Identity creator, RepositoryEntry newEntry, File fExportedDataDir); } diff --git a/src/main/java/org/olat/modules/reminder/RuleSPI.java b/src/main/java/org/olat/modules/reminder/RuleSPI.java index 97d522d70b2..8f876da9955 100644 --- a/src/main/java/org/olat/modules/reminder/RuleSPI.java +++ b/src/main/java/org/olat/modules/reminder/RuleSPI.java @@ -19,6 +19,7 @@ */ package org.olat.modules.reminder; +import org.olat.course.export.CourseEnvironmentMapper; import org.olat.repository.RepositoryEntry; /** @@ -33,6 +34,8 @@ public interface RuleSPI { public String getCategory(); + public ReminderRule clone(ReminderRule rule, CourseEnvironmentMapper envMapper); + public RuleEditorFragment getEditorFragment(ReminderRule rule, RepositoryEntry entry); } diff --git a/src/main/java/org/olat/modules/reminder/manager/ReminderServiceImpl.java b/src/main/java/org/olat/modules/reminder/manager/ReminderServiceImpl.java index f43194ba37b..b4edfa7e325 100644 --- a/src/main/java/org/olat/modules/reminder/manager/ReminderServiceImpl.java +++ b/src/main/java/org/olat/modules/reminder/manager/ReminderServiceImpl.java @@ -19,7 +19,13 @@ */ package org.olat.modules.reminder.manager; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.InputStream; +import java.io.OutputStream; import java.text.ParseException; +import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.UUID; @@ -45,6 +51,8 @@ import org.olat.modules.reminder.Reminder; import org.olat.modules.reminder.ReminderRule; import org.olat.modules.reminder.ReminderService; import org.olat.modules.reminder.SentReminder; +import org.olat.modules.reminder.model.ImportExportReminder; +import org.olat.modules.reminder.model.ImportExportReminders; import org.olat.modules.reminder.model.ReminderImpl; import org.olat.modules.reminder.model.ReminderInfos; import org.olat.modules.reminder.model.ReminderRuleImpl; @@ -72,8 +80,11 @@ public class ReminderServiceImpl implements ReminderService { static { ruleXStream.alias("rule", org.olat.modules.reminder.model.ReminderRuleImpl.class); ruleXStream.alias("rules", org.olat.modules.reminder.model.ReminderRules.class); + ruleXStream.alias("reminders", org.olat.modules.reminder.model.ImportExportReminders.class); + ruleXStream.alias("reminder", org.olat.modules.reminder.model.ImportExportReminder.class); } + @Autowired private ReminderDAO reminderDao; @Autowired @@ -126,6 +137,11 @@ public class ReminderServiceImpl implements ReminderService { return reminderDao.loadByKey(key); } + @Override + public List<Reminder> getReminders(RepositoryEntryRef entry) { + return reminderDao.getReminders(entry); + } + @Override public List<ReminderInfos> getReminderInfos(RepositoryEntryRef entry) { return reminderDao.getReminderInfos(entry); @@ -161,6 +177,45 @@ public class ReminderServiceImpl implements ReminderService { return (ReminderRules)ruleXStream.fromXML(rulesXml); } + @Override + public void exportReminders(RepositoryEntry entry, File fExportedDataDir) { + List<Reminder> reminders = reminderDao.getReminders(entry); + if(reminders.size() > 0) { + try (OutputStream fOut = new FileOutputStream(new File(fExportedDataDir, REMINDERS_XML))) { + ImportExportReminders exportReminders = new ImportExportReminders(); + for(Reminder reminder:reminders) { + ImportExportReminder exportReminder = new ImportExportReminder(reminder); + exportReminders.getReminders().add(exportReminder); + } + ruleXStream.toXML(exportReminders, fOut); + } catch(Exception e) { + log.error("", e); + } + } + } + + @Override + public List<Reminder> importRawReminders(Identity creator, RepositoryEntry newEntry, File fExportedDataDir) { + File reminderFile = new File(fExportedDataDir, REMINDERS_XML); + List<Reminder> reminders = new ArrayList<>(); + if(reminderFile.exists()) { + try(InputStream in = new FileInputStream(reminderFile)) { + ImportExportReminders importReminders = (ImportExportReminders)ruleXStream.fromXML(in); + List<ImportExportReminder> importReminderList = importReminders.getReminders(); + for(ImportExportReminder importReminder:importReminderList) { + Reminder reminder = reminderDao.createReminder(newEntry, creator); + reminder.setDescription(importReminder.getDescription()); + reminder.setEmailBody(importReminder.getEmailBody()); + reminder.setConfiguration(importReminder.getConfiguration()); + reminders.add(reminder); + } + } catch(Exception e) { + log.error("", e); + } + } + return reminders; + } + @Override public void remindAll() { Date now = new Date(); diff --git a/src/main/java/org/olat/modules/reminder/model/ImportExportReminder.java b/src/main/java/org/olat/modules/reminder/model/ImportExportReminder.java new file mode 100644 index 00000000000..48b21dc3937 --- /dev/null +++ b/src/main/java/org/olat/modules/reminder/model/ImportExportReminder.java @@ -0,0 +1,74 @@ +/** + * <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.model; + +import java.io.Serializable; + +import org.olat.modules.reminder.Reminder; + +/** + * + * Initial date: 12.05.2015<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public class ImportExportReminder implements Serializable { + + private static final long serialVersionUID = -6548172969534189234L; + + private String description; + private String configuration; + private String emailBody; + + public ImportExportReminder() { + // + } + + public ImportExportReminder(Reminder reminder) { + description = reminder.getDescription(); + configuration = reminder.getConfiguration(); + emailBody = reminder.getEmailBody(); + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public String getConfiguration() { + return configuration; + } + + public void setConfiguration(String configuration) { + this.configuration = configuration; + } + + public String getEmailBody() { + return emailBody; + } + + public void setEmailBody(String emailBody) { + this.emailBody = emailBody; + } + +} diff --git a/src/main/java/org/olat/modules/reminder/model/ImportExportReminders.java b/src/main/java/org/olat/modules/reminder/model/ImportExportReminders.java new file mode 100644 index 00000000000..434e29af01c --- /dev/null +++ b/src/main/java/org/olat/modules/reminder/model/ImportExportReminders.java @@ -0,0 +1,51 @@ +/** + * <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.model; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +/** + * + * Initial date: 12.05.2015<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public class ImportExportReminders implements Serializable { + + private static final long serialVersionUID = -7591298715271752339L; + private List<ImportExportReminder> reminders; + + public ImportExportReminders() { + // + } + + public List<ImportExportReminder> getReminders() { + if(reminders == null) { + reminders = new ArrayList<>(); + } + return reminders; + } + + public void setReminders(List<ImportExportReminder> reminders) { + this.reminders = reminders; + } +} diff --git a/src/main/java/org/olat/modules/reminder/model/ReminderRuleImpl.java b/src/main/java/org/olat/modules/reminder/model/ReminderRuleImpl.java index 78f30480e5b..96050d9e65c 100644 --- a/src/main/java/org/olat/modules/reminder/model/ReminderRuleImpl.java +++ b/src/main/java/org/olat/modules/reminder/model/ReminderRuleImpl.java @@ -75,4 +75,15 @@ public class ReminderRuleImpl implements ReminderRule { public void setRightUnit(String rightUnit) { this.rightUnit = rightUnit; } + + @Override + public ReminderRule clone() { + ReminderRuleImpl clone = new ReminderRuleImpl(); + clone.type = type; + clone.leftOperand = leftOperand; + clone.operator = operator; + clone.rightOperand = rightOperand; + clone.rightUnit = rightUnit; + return clone; + } } diff --git a/src/main/java/org/olat/modules/reminder/rule/BusinessGroupRoleRuleSPI.java b/src/main/java/org/olat/modules/reminder/rule/BusinessGroupRoleRuleSPI.java index c869ec73b6a..f2fbcbb696c 100644 --- a/src/main/java/org/olat/modules/reminder/rule/BusinessGroupRoleRuleSPI.java +++ b/src/main/java/org/olat/modules/reminder/rule/BusinessGroupRoleRuleSPI.java @@ -25,9 +25,11 @@ import java.util.List; import org.olat.basesecurity.GroupRoles; import org.olat.core.id.Identity; import org.olat.core.util.StringHelper; +import org.olat.course.export.CourseEnvironmentMapper; import org.olat.group.BusinessGroupRef; import org.olat.group.manager.BusinessGroupRelationDAO; import org.olat.group.model.BusinessGroupRefImpl; +import org.olat.group.model.BusinessGroupReference; import org.olat.modules.reminder.IdentitiesProviderRuleSPI; import org.olat.modules.reminder.ReminderRule; import org.olat.modules.reminder.RuleEditorFragment; @@ -63,6 +65,25 @@ public class BusinessGroupRoleRuleSPI implements IdentitiesProviderRuleSPI { public RuleEditorFragment getEditorFragment(ReminderRule rule, RepositoryEntry entry) { return new BusinessGroupRoleEditor(rule, entry); } + + @Override + public ReminderRule clone(ReminderRule rule, CourseEnvironmentMapper envMapper) { + ReminderRuleImpl clone = (ReminderRuleImpl)rule.clone(); + String groupKey = clone.getRightOperand(); + + boolean found = false; + if(StringHelper.isLong(groupKey)) { + Long key = Long.parseLong(groupKey); + for(BusinessGroupReference ref:envMapper.getGroups()) { + if(key.equals(ref.getOriginalKey()) && ref.getKey() != null) { + clone.setRightOperand(ref.getKey().toString()); + found = true; + } + } + } + + return found ? clone : null; + } @Override public List<Identity> evaluate(RepositoryEntry entry, ReminderRule rule) { diff --git a/src/main/java/org/olat/modules/reminder/rule/CourseEnrollmentDateRuleSPI.java b/src/main/java/org/olat/modules/reminder/rule/CourseEnrollmentDateRuleSPI.java index aa8915d60b2..42913e8d344 100644 --- a/src/main/java/org/olat/modules/reminder/rule/CourseEnrollmentDateRuleSPI.java +++ b/src/main/java/org/olat/modules/reminder/rule/CourseEnrollmentDateRuleSPI.java @@ -24,6 +24,7 @@ import java.util.List; import java.util.Map; import org.olat.core.id.Identity; +import org.olat.course.export.CourseEnvironmentMapper; import org.olat.modules.reminder.ReminderRule; import org.olat.modules.reminder.manager.ReminderDAO; import org.olat.repository.RepositoryEntry; @@ -46,6 +47,11 @@ public class CourseEnrollmentDateRuleSPI extends AbstractLaunchDateRuleSPI { public String getLabelI18nKey() { return "rule.course.enrollment.date"; } + + @Override + public ReminderRule clone(ReminderRule rule, CourseEnvironmentMapper envMapper) { + return rule.clone(); + } @Override protected Map<Long, Date> getLaunchDates(ReminderRule rule, RepositoryEntry entry, List<Identity> identities) { diff --git a/src/main/java/org/olat/modules/reminder/rule/DateRuleSPI.java b/src/main/java/org/olat/modules/reminder/rule/DateRuleSPI.java index 40cdf3c009b..f2f72b8f2f4 100644 --- a/src/main/java/org/olat/modules/reminder/rule/DateRuleSPI.java +++ b/src/main/java/org/olat/modules/reminder/rule/DateRuleSPI.java @@ -26,6 +26,7 @@ import org.olat.core.logging.OLog; import org.olat.core.logging.Tracing; import org.olat.core.util.Formatter; import org.olat.core.util.StringHelper; +import org.olat.course.export.CourseEnvironmentMapper; import org.olat.modules.reminder.ReminderRule; import org.olat.modules.reminder.RuleEditorFragment; import org.olat.modules.reminder.RuleSPI; @@ -62,6 +63,11 @@ public class DateRuleSPI implements RuleSPI { return new DateRuleEditor(rule); } + @Override + public ReminderRule clone(ReminderRule rule, CourseEnvironmentMapper envMapper) { + return rule.clone(); + } + public boolean evaluate(ReminderRule rule) { boolean allOk = true; diff --git a/src/main/java/org/olat/modules/reminder/rule/InitialCourseLaunchRuleSPI.java b/src/main/java/org/olat/modules/reminder/rule/InitialCourseLaunchRuleSPI.java index 33a8951b8d9..49c7ae72149 100644 --- a/src/main/java/org/olat/modules/reminder/rule/InitialCourseLaunchRuleSPI.java +++ b/src/main/java/org/olat/modules/reminder/rule/InitialCourseLaunchRuleSPI.java @@ -25,6 +25,7 @@ import java.util.Map; import org.olat.core.id.Identity; import org.olat.course.assessment.manager.UserCourseInformationsManager; +import org.olat.course.export.CourseEnvironmentMapper; import org.olat.modules.reminder.ReminderRule; import org.olat.repository.RepositoryEntry; import org.springframework.beans.factory.annotation.Autowired; @@ -46,6 +47,11 @@ public class InitialCourseLaunchRuleSPI extends AbstractLaunchDateRuleSPI { public String getLabelI18nKey() { return "rule.initial.course.launch.date"; } + + @Override + public ReminderRule clone(ReminderRule rule, CourseEnvironmentMapper envMapper) { + return rule.clone(); + } @Override protected Map<Long, Date> getLaunchDates(ReminderRule rule, RepositoryEntry entry, List<Identity> identities) { diff --git a/src/main/java/org/olat/modules/reminder/rule/RecentCourseLaunchRuleSPI.java b/src/main/java/org/olat/modules/reminder/rule/RecentCourseLaunchRuleSPI.java index 52754bfc237..ac2944ef155 100644 --- a/src/main/java/org/olat/modules/reminder/rule/RecentCourseLaunchRuleSPI.java +++ b/src/main/java/org/olat/modules/reminder/rule/RecentCourseLaunchRuleSPI.java @@ -25,6 +25,7 @@ import java.util.Map; import org.olat.core.id.Identity; import org.olat.course.assessment.manager.UserCourseInformationsManager; +import org.olat.course.export.CourseEnvironmentMapper; import org.olat.modules.reminder.ReminderRule; import org.olat.repository.RepositoryEntry; import org.springframework.beans.factory.annotation.Autowired; @@ -51,6 +52,11 @@ public class RecentCourseLaunchRuleSPI extends AbstractLaunchDateRuleSPI { public String getCategory() { return "general"; } + + @Override + public ReminderRule clone(ReminderRule rule, CourseEnvironmentMapper envMapper) { + return rule.clone(); + } @Override protected Map<Long, Date> getLaunchDates(ReminderRule rule, RepositoryEntry entry, List<Identity> identities) { diff --git a/src/main/java/org/olat/modules/reminder/rule/RepositoryEntryRoleRuleSPI.java b/src/main/java/org/olat/modules/reminder/rule/RepositoryEntryRoleRuleSPI.java index 236ef2f3f0d..86c52908a81 100644 --- a/src/main/java/org/olat/modules/reminder/rule/RepositoryEntryRoleRuleSPI.java +++ b/src/main/java/org/olat/modules/reminder/rule/RepositoryEntryRoleRuleSPI.java @@ -25,6 +25,7 @@ import java.util.List; import org.olat.basesecurity.GroupRoles; import org.olat.core.id.Identity; import org.olat.core.util.StringHelper; +import org.olat.course.export.CourseEnvironmentMapper; import org.olat.modules.reminder.IdentitiesProviderRuleSPI; import org.olat.modules.reminder.ReminderRule; import org.olat.modules.reminder.RuleEditorFragment; @@ -62,6 +63,11 @@ public class RepositoryEntryRoleRuleSPI implements IdentitiesProviderRuleSPI { public RuleEditorFragment getEditorFragment(ReminderRule rule, RepositoryEntry entry) { return new RepositoryEntryRoleEditor(rule); } + + @Override + public ReminderRule clone(ReminderRule rule, CourseEnvironmentMapper envMapper) { + return rule.clone(); + } @Override public List<Identity> evaluate(RepositoryEntry entry, ReminderRule rule) { diff --git a/src/main/java/org/olat/modules/reminder/rule/UserPropertyRuleSPI.java b/src/main/java/org/olat/modules/reminder/rule/UserPropertyRuleSPI.java index de037aea84f..69017853fb3 100644 --- a/src/main/java/org/olat/modules/reminder/rule/UserPropertyRuleSPI.java +++ b/src/main/java/org/olat/modules/reminder/rule/UserPropertyRuleSPI.java @@ -20,6 +20,7 @@ package org.olat.modules.reminder.rule; import org.olat.core.id.Identity; +import org.olat.course.export.CourseEnvironmentMapper; import org.olat.modules.reminder.ReminderRule; import org.olat.modules.reminder.RuleEditorFragment; import org.olat.modules.reminder.RuleSPI; @@ -53,7 +54,12 @@ public class UserPropertyRuleSPI implements RuleSPI { public RuleEditorFragment getEditorFragment(ReminderRule rule, RepositoryEntry entry) { return new UserPropertyEditor(rule); } - + + @Override + public ReminderRule clone(ReminderRule rule, CourseEnvironmentMapper envMapper) { + return rule.clone(); + } + public boolean accept(ReminderRule rule, Identity identity) { boolean allOk = false; if(rule instanceof ReminderRuleImpl) { diff --git a/src/main/java/org/olat/repository/handlers/BlogHandler.java b/src/main/java/org/olat/repository/handlers/BlogHandler.java index 5aad2425bea..989d07fd05c 100644 --- a/src/main/java/org/olat/repository/handlers/BlogHandler.java +++ b/src/main/java/org/olat/repository/handlers/BlogHandler.java @@ -118,7 +118,7 @@ public class BlogHandler implements RepositoryHandler { } @Override - public RepositoryEntry copy(RepositoryEntry source, RepositoryEntry target) { + public RepositoryEntry copy(Identity author, RepositoryEntry source, RepositoryEntry target) { OLATResource sourceResource = source.getOlatResource(); OLATResource targetResource = target.getOlatResource(); FeedManager.getInstance().copy(sourceResource, targetResource); diff --git a/src/main/java/org/olat/repository/handlers/CourseHandler.java b/src/main/java/org/olat/repository/handlers/CourseHandler.java index e7859d63f0d..66d898da5f0 100644 --- a/src/main/java/org/olat/repository/handlers/CourseHandler.java +++ b/src/main/java/org/olat/repository/handlers/CourseHandler.java @@ -33,6 +33,7 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.SimpleFileVisitor; import java.nio.file.attribute.BasicFileAttributes; +import java.util.List; import java.util.Locale; import java.util.UUID; @@ -94,6 +95,12 @@ import org.olat.fileresource.types.GlossaryResource; import org.olat.fileresource.types.ResourceEvaluation; import org.olat.fileresource.types.SharedFolderFileResource; import org.olat.modules.glossary.GlossaryManager; +import org.olat.modules.reminder.Reminder; +import org.olat.modules.reminder.ReminderModule; +import org.olat.modules.reminder.ReminderRule; +import org.olat.modules.reminder.ReminderService; +import org.olat.modules.reminder.RuleSPI; +import org.olat.modules.reminder.model.ReminderRules; import org.olat.modules.sharedfolder.SharedFolderManager; import org.olat.repository.ErrorList; import org.olat.repository.RepositoryEntry; @@ -290,6 +297,9 @@ public class CourseHandler implements RepositoryHandler { re = imp.importContent(re, getMediaContainer(re)); } + //import reminders + importReminders(re, fImportBaseDirectory, envMapper, initialAuthor); + //clean up export folder cleanExportAfterImport(fImportBaseDirectory); @@ -380,6 +390,29 @@ public class CourseHandler implements RepositoryHandler { } } + private void importReminders(RepositoryEntry re, File fImportBaseDirectory, CourseEnvironmentMapper envMapper, Identity initialAuthor) { + ReminderModule reminderModule = CoreSpringFactory.getImpl(ReminderModule.class); + ReminderService reminderService = CoreSpringFactory.getImpl(ReminderService.class); + List<Reminder> reminders = reminderService.importRawReminders(initialAuthor, re, fImportBaseDirectory); + if(reminders.size() > 0) { + for(Reminder reminder:reminders) { + ReminderRules clonedRules = new ReminderRules(); + String configuration = reminder.getConfiguration(); + ReminderRules rules = reminderService.toRules(configuration); + for(ReminderRule rule:rules.getRules()) { + RuleSPI ruleSpi = reminderModule.getRuleSPIByType(rule.getType()); + if(ruleSpi != null) { + ReminderRule clonedRule = ruleSpi.clone(rule, envMapper); + clonedRules.getRules().add(clonedRule); + } + } + String convertedConfiguration = reminderService.toXML(clonedRules); + reminder.setConfiguration(convertedConfiguration); + reminderService.save(reminder); + } + } + } + private void markDirtyNewRecursively(CourseEditorTreeNode editorRootNode) { editorRootNode.setDirty(true); editorRootNode.setNewnode(true); @@ -391,7 +424,7 @@ public class CourseHandler implements RepositoryHandler { } @Override - public RepositoryEntry copy(RepositoryEntry source, RepositoryEntry target) { + public RepositoryEntry copy(Identity author, RepositoryEntry source, RepositoryEntry target) { final OLATResource sourceResource = source.getOlatResource(); final OLATResource targetResource = target.getOlatResource(); @@ -414,8 +447,35 @@ public class CourseHandler implements RepositoryHandler { course = CourseFactory.loadCourse(cgm.getCourseResource()); course.postCopy(envMapper, sourceCourse); + cloneReminders(author, envMapper, source, target); + return target; } + + private void cloneReminders(Identity author, CourseEnvironmentMapper envMapper, RepositoryEntry source, RepositoryEntry target) { + ReminderModule reminderModule = CoreSpringFactory.getImpl(ReminderModule.class); + ReminderService reminderService = CoreSpringFactory.getImpl(ReminderService.class); + List<Reminder> reminders = reminderService.getReminders(source); + + for(Reminder reminder:reminders) { + String configuration = reminder.getConfiguration(); + ReminderRules rules = reminderService.toRules(configuration); + ReminderRules clonedRules = new ReminderRules(); + for(ReminderRule rule:rules.getRules()) { + RuleSPI ruleSpi = reminderModule.getRuleSPIByType(rule.getType()); + if(ruleSpi != null) { + ReminderRule clonedRule = ruleSpi.clone(rule, envMapper); + clonedRules.getRules().add(clonedRule); + } + } + + Reminder clonedReminder = reminderService.createReminder(target, author); + clonedReminder.setDescription(reminder.getDescription()); + clonedReminder.setEmailBody(reminder.getEmailBody()); + clonedReminder.setConfiguration(reminderService.toXML(clonedRules)); + reminderService.save(clonedReminder); + } + } @Override public String getSupportedType() { diff --git a/src/main/java/org/olat/repository/handlers/GlossaryHandler.java b/src/main/java/org/olat/repository/handlers/GlossaryHandler.java index bcd22dfa07b..c864bdce077 100644 --- a/src/main/java/org/olat/repository/handlers/GlossaryHandler.java +++ b/src/main/java/org/olat/repository/handlers/GlossaryHandler.java @@ -130,7 +130,7 @@ public class GlossaryHandler implements RepositoryHandler { } @Override - public RepositoryEntry copy(RepositoryEntry source, RepositoryEntry target) { + public RepositoryEntry copy(Identity author, RepositoryEntry source, RepositoryEntry target) { OLATResource sourceResource = source.getOlatResource(); OLATResource targetResource = target.getOlatResource(); File sourceFileroot = FileResourceManager.getInstance().getFileResourceRootImpl(sourceResource).getBasefile(); diff --git a/src/main/java/org/olat/repository/handlers/ImsCPHandler.java b/src/main/java/org/olat/repository/handlers/ImsCPHandler.java index bf28e2e1097..952e8cc7640 100644 --- a/src/main/java/org/olat/repository/handlers/ImsCPHandler.java +++ b/src/main/java/org/olat/repository/handlers/ImsCPHandler.java @@ -138,7 +138,7 @@ public class ImsCPHandler extends FileHandler { } @Override - public RepositoryEntry copy(RepositoryEntry source, RepositoryEntry target) { + public RepositoryEntry copy(Identity author, RepositoryEntry source, RepositoryEntry target) { final CPManager cpManager = CPManager.getInstance(); OLATResource sourceResource = source.getOlatResource(); OLATResource targetResource = target.getOlatResource(); diff --git a/src/main/java/org/olat/repository/handlers/PodcastHandler.java b/src/main/java/org/olat/repository/handlers/PodcastHandler.java index 2d29046bc89..6513dc7dc23 100644 --- a/src/main/java/org/olat/repository/handlers/PodcastHandler.java +++ b/src/main/java/org/olat/repository/handlers/PodcastHandler.java @@ -118,7 +118,7 @@ public class PodcastHandler implements RepositoryHandler { } @Override - public RepositoryEntry copy(RepositoryEntry source, RepositoryEntry target) { + public RepositoryEntry copy(Identity author, RepositoryEntry source, RepositoryEntry target) { OLATResource sourceResource = source.getOlatResource(); OLATResource targetResource = target.getOlatResource(); FeedManager.getInstance().copy(sourceResource, targetResource); diff --git a/src/main/java/org/olat/repository/handlers/PortfolioHandler.java b/src/main/java/org/olat/repository/handlers/PortfolioHandler.java index 7031582cb6a..fcf427f7e3c 100644 --- a/src/main/java/org/olat/repository/handlers/PortfolioHandler.java +++ b/src/main/java/org/olat/repository/handlers/PortfolioHandler.java @@ -139,7 +139,7 @@ public class PortfolioHandler implements RepositoryHandler { } @Override - public RepositoryEntry copy(RepositoryEntry source, RepositoryEntry target) { + public RepositoryEntry copy(Identity author, RepositoryEntry source, RepositoryEntry target) { OLATResource sourceResource = source.getOlatResource(); OLATResource targetResource = target.getOlatResource(); diff --git a/src/main/java/org/olat/repository/handlers/RepositoryHandler.java b/src/main/java/org/olat/repository/handlers/RepositoryHandler.java index 199b61c23b4..daeda3195e9 100644 --- a/src/main/java/org/olat/repository/handlers/RepositoryHandler.java +++ b/src/main/java/org/olat/repository/handlers/RepositoryHandler.java @@ -106,7 +106,7 @@ public interface RepositoryHandler { * @param target * @return */ - public RepositoryEntry copy(RepositoryEntry source, RepositoryEntry target); + public RepositoryEntry copy(Identity author, RepositoryEntry source, RepositoryEntry target); diff --git a/src/main/java/org/olat/repository/handlers/SCORMCPHandler.java b/src/main/java/org/olat/repository/handlers/SCORMCPHandler.java index f70b8ce78d8..2db8c9c36e4 100644 --- a/src/main/java/org/olat/repository/handlers/SCORMCPHandler.java +++ b/src/main/java/org/olat/repository/handlers/SCORMCPHandler.java @@ -114,7 +114,7 @@ public class SCORMCPHandler extends FileHandler { } @Override - public RepositoryEntry copy(RepositoryEntry source, RepositoryEntry target) { + public RepositoryEntry copy(Identity author, RepositoryEntry source, RepositoryEntry target) { final ScormMainManager scormManager = ScormMainManager.getInstance(); OLATResource sourceResource = source.getOlatResource(); OLATResource targetResource = target.getOlatResource(); diff --git a/src/main/java/org/olat/repository/handlers/SharedFolderHandler.java b/src/main/java/org/olat/repository/handlers/SharedFolderHandler.java index 2c10db3e568..c03463f473a 100644 --- a/src/main/java/org/olat/repository/handlers/SharedFolderHandler.java +++ b/src/main/java/org/olat/repository/handlers/SharedFolderHandler.java @@ -116,7 +116,7 @@ public class SharedFolderHandler implements RepositoryHandler { } @Override - public RepositoryEntry copy(RepositoryEntry source, RepositoryEntry target) { + public RepositoryEntry copy(Identity author, RepositoryEntry source, RepositoryEntry target) { OLATResource sourceResource = source.getOlatResource(); OLATResource targetResource = target.getOlatResource(); File sourceFileroot = FileResourceManager.getInstance().getFileResourceRootImpl(sourceResource).getBasefile(); diff --git a/src/main/java/org/olat/repository/handlers/WebDocumentHandler.java b/src/main/java/org/olat/repository/handlers/WebDocumentHandler.java index 65a896caf26..f211701ca36 100644 --- a/src/main/java/org/olat/repository/handlers/WebDocumentHandler.java +++ b/src/main/java/org/olat/repository/handlers/WebDocumentHandler.java @@ -179,7 +179,7 @@ public class WebDocumentHandler extends FileHandler { } @Override - public RepositoryEntry copy(RepositoryEntry source, RepositoryEntry target) { + public RepositoryEntry copy(Identity author, RepositoryEntry source, RepositoryEntry target) { OLATResource sourceResource = source.getOlatResource(); OLATResource targetResource = target.getOlatResource(); File sourceFileroot = FileResourceManager.getInstance().getFileResourceRootImpl(sourceResource).getBasefile(); diff --git a/src/main/java/org/olat/repository/handlers/WikiHandler.java b/src/main/java/org/olat/repository/handlers/WikiHandler.java index e3d6d179eb5..92d0869acf7 100644 --- a/src/main/java/org/olat/repository/handlers/WikiHandler.java +++ b/src/main/java/org/olat/repository/handlers/WikiHandler.java @@ -145,7 +145,7 @@ public class WikiHandler implements RepositoryHandler { } @Override - public RepositoryEntry copy(RepositoryEntry source, RepositoryEntry target) { + public RepositoryEntry copy(Identity author, RepositoryEntry source, RepositoryEntry target) { final OLATResource sourceResource = source.getOlatResource(); final OLATResource targetResource = target.getOlatResource(); final FileResourceManager frm = FileResourceManager.getInstance(); diff --git a/src/main/java/org/olat/repository/manager/RepositoryServiceImpl.java b/src/main/java/org/olat/repository/manager/RepositoryServiceImpl.java index 3978977bff0..dc38e93f0a8 100644 --- a/src/main/java/org/olat/repository/manager/RepositoryServiceImpl.java +++ b/src/main/java/org/olat/repository/manager/RepositoryServiceImpl.java @@ -214,7 +214,7 @@ public class RepositoryServiceImpl implements RepositoryService { copyEntry = dbInstance.getCurrentEntityManager().merge(copyEntry); RepositoryHandler handler = RepositoryHandlerFactory.getInstance().getRepositoryHandler(sourceEntry); - copyEntry = handler.copy(sourceEntry, copyEntry); + copyEntry = handler.copy(author, sourceEntry, copyEntry); //copy the image diff --git a/src/main/java/org/olat/restapi/repository/course/CoursesWebService.java b/src/main/java/org/olat/restapi/repository/course/CoursesWebService.java index 13654edc543..6e546dd560e 100644 --- a/src/main/java/org/olat/restapi/repository/course/CoursesWebService.java +++ b/src/main/java/org/olat/restapi/repository/course/CoursesWebService.java @@ -425,7 +425,7 @@ public class CoursesWebService { description, copyResource, RepositoryEntry.ACC_OWNERS); RepositoryHandler handler = RepositoryHandlerFactory.getInstance().getRepositoryHandler(src); - preparedEntry = handler.copy(src, preparedEntry); + preparedEntry = handler.copy(ureq.getIdentity(), src, preparedEntry); preparedEntry.setCanDownload(src.getCanDownload()); if(StringHelper.containsNonWhitespace(softKey)) { -- GitLab