/**
* <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.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;
import org.apache.velocity.VelocityContext;
import org.olat.core.gui.translator.Translator;
import org.olat.core.helpers.Settings;
import org.olat.core.id.Identity;
import org.olat.core.id.User;
import org.olat.core.id.UserConstants;
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.core.util.Util;
import org.olat.core.util.i18n.I18nModule;
import org.olat.core.util.mail.ContactList;
import org.olat.core.util.mail.MailBundle;
import org.olat.core.util.mail.MailContext;
import org.olat.core.util.mail.MailContextImpl;
import org.olat.core.util.mail.MailManager;
import org.olat.core.util.mail.MailTemplate;
import org.olat.core.util.mail.MailerResult;
import org.olat.core.util.xml.XStreamHelper;
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;
import org.olat.modules.reminder.model.ReminderRules;
import org.olat.modules.reminder.rule.DateRuleSPI;
import org.olat.modules.reminder.ui.ReminderAdminController;
import org.olat.repository.RepositoryEntry;
import org.olat.repository.RepositoryEntryRef;
import org.olat.user.UserManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.thoughtworks.xstream.XStream;
/**
*
* Initial date: 08.04.2015<br>
* @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
*
*/
@Service
public class ReminderServiceImpl implements ReminderService {
private static final OLog log = Tracing.createLoggerFor(ReminderServiceImpl.class);
private static final XStream ruleXStream = XStreamHelper.createXStreamInstance();
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
private MailManager mailManager;
@Autowired
private UserManager userManager;
@Autowired
private ReminderRuleEngine ruleEngine;
@Override
public Reminder createReminder(RepositoryEntry entry, Identity creator) {
return reminderDao.createReminder(entry, creator);
}
@Override
public Reminder save(Reminder reminder) {
//start optimization
optimizeStartDate(reminder);
return reminderDao.save(reminder);
}
private void optimizeStartDate(Reminder reminder) {
Date startDate = null;
String configuration = reminder.getConfiguration();
if(StringHelper.containsNonWhitespace(configuration)) {
ReminderRules rules = toRules(configuration);
for(ReminderRule rule:rules.getRules()) {
if(rule instanceof ReminderRuleImpl && ReminderRuleEngine.DATE_RULE_TYPE.equals(rule.getType())) {
ReminderRuleImpl r = (ReminderRuleImpl)rule;
if(DateRuleSPI.AFTER.equals(r.getOperator()) && StringHelper.containsNonWhitespace(r.getRightOperand())) {
try {
Date date = Formatter.parseDatetime(r.getRightOperand());
if(startDate == null) {
startDate = date;
} else if(startDate.compareTo(date) > 0) {
startDate = date;
}
} catch (ParseException e) {
log.error("", e);
}
}
}
}
}
((ReminderImpl)reminder).setStartDate(startDate);
}
@Override
public Reminder loadByKey(Long key) {
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);
}
@Override
public Reminder duplicate(Reminder toCopy, Identity creator) {
return reminderDao.duplicate(toCopy, creator);
}
@Override
public void delete(Reminder reminder) {
reminderDao.delete(reminder);
}
@Override
public List<SentReminder> getSentReminders(Reminder reminder) {
return reminderDao.getSendReminders(reminder);
}
@Override
public List<SentReminder> getSentReminders(RepositoryEntryRef entry) {
return reminderDao.getSendReminders(entry);
}
@Override
public String toXML(ReminderRules rules) {
return ruleXStream.toXML(rules);
}
@Override
public ReminderRules toRules(String rulesXml) {
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();
List<Reminder> reminders = reminderDao.getReminders(now);
for(Reminder reminder:reminders) {
sendReminder(reminder);
}
}
@Override
public MailerResult sendReminder(Reminder reminder) {
List<Identity> identitiesToRemind = ruleEngine.evaluate(reminder, false);
return sendReminder(reminder, identitiesToRemind);
}
@Override
public MailerResult sendReminder(Reminder reminder, List<Identity> identitiesToRemind) {
RepositoryEntry entry = reminder.getEntry();
ContactList contactList = new ContactList("Infos");
contactList.addAllIdentites(identitiesToRemind);
MailContext context = new MailContextImpl("[RepositoryEntry:" + entry.getKey() + "]");
Translator trans = Util.createPackageTranslator(ReminderAdminController.class, I18nModule.getDefaultLocale());
String subject = trans.translate("reminder.subject");
String body = reminder.getEmailBody();
String metaId = UUID.randomUUID().toString();
String url = Settings.getServerContextPathURI() + "/url/RepositoryEntry/" + entry.getKey();
MailerResult overviewResult = new MailerResult();
ReminderTemplate template = new ReminderTemplate(subject, body, url, entry);
for(Identity identityToRemind:identitiesToRemind) {
String status;
MailBundle bundle = mailManager.makeMailBundle(context, identityToRemind, template, null, metaId, overviewResult);
MailerResult result = mailManager.sendMessage(bundle);
overviewResult.append(result);
List<Identity> failedIdentities = result.getFailedIdentites();
if(failedIdentities != null && failedIdentities.contains(identityToRemind)) {
status = "error";
} else {
status = "ok";
}
reminderDao.markAsSend(reminder, identityToRemind, status);
}
return overviewResult;
}
private class ReminderTemplate extends MailTemplate {
private final String url;
private final RepositoryEntry entry;
public ReminderTemplate(String subjectTemplate, String bodyTemplate, String url, RepositoryEntry entry) {
super(subjectTemplate, bodyTemplate, null);
this.url = url;
this.entry = entry;
}
@Override
public void putVariablesInMailContext(VelocityContext vContext, Identity recipient) {
User user = recipient.getUser();
vContext.put("firstname", user.getProperty(UserConstants.FIRSTNAME, null));
vContext.put(UserConstants.FIRSTNAME, user.getProperty(UserConstants.FIRSTNAME, null));
vContext.put("lastname", user.getProperty(UserConstants.LASTNAME, null));
vContext.put(UserConstants.LASTNAME, user.getProperty(UserConstants.LASTNAME, null));
String fullName = userManager.getUserDisplayName(recipient);
vContext.put("fullname", fullName);
vContext.put("fullName", fullName);
vContext.put("mail", user.getProperty(UserConstants.EMAIL, null));
vContext.put("email", user.getProperty(UserConstants.EMAIL, null));
vContext.put("username", recipient.getName());
// Put variables from greater context
if(entry != null) {
vContext.put("courseurl", url);
vContext.put("coursename", entry.getDisplayname());
vContext.put("coursedescription", entry.getDescription());
}
}
}
}