package hu.sch.ejb;
import hu.sch.domain.Group;
import hu.sch.domain.user.User;
import hu.sch.domain.logging.EventType;
import hu.sch.domain.logging.Log;
import hu.sch.services.AccountManager;
import hu.sch.services.GroupManagerLocal;
import hu.sch.services.SystemManagerLocal;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import javax.ejb.Schedule;
import javax.ejb.Stateless;
import javax.inject.Inject;
import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.PersistenceContext;
import javax.persistence.TypedQuery;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
*
* @author aldaris
*/
@Stateless(mappedName = "TimerService")
public class TimerServiceBean {
private static final Logger logger = LoggerFactory.getLogger(TimerServiceBean.class);
@Inject
private MailManagerBean mailManager;
@Inject
private SystemManagerLocal systemManager;
@Inject
private GroupManagerLocal groupManager;
@Inject
private AccountManager accountManager;
@PersistenceContext
private EntityManager em;
private static final String MSG_SUBJECT = MailManagerBean.getMailString(MailManagerBean.MAIL_ADMIN_REPORT_SUBJECT);
private static final String MSG_BODY_TEMPLATE = MailManagerBean.getMailString(MailManagerBean.MAIL_ADMIN_REPORT_BODY);
@Schedule(hour = "1")
protected void dailyEvent() {
logger.info("daily event fired");
// lekérjük, hogy melyik ID volt az, amit legutoljára kiküldtünk
long lastUsedLogId = systemManager.getLastLogId();
// lekérjük a legfrisebb ID-t, ez és az előbbi közti logokat dolgozzuk fel
long lastLogId = getLastLogId();
if (lastUsedLogId == lastLogId) {
logger.info("Nincs új log, amit feldolgozhatnánk");
} else {
logger.info("A következő logokat dolgozzuk fel: (" + lastUsedLogId + ", " + lastLogId + "]");
notifyGroupLeaders(lastUsedLogId, lastLogId);
notifySvieAdmin(lastUsedLogId, lastLogId);
notifySviePresident(lastUsedLogId, lastLogId);
// elmentjük, hogy legközelebb ezeket a logokat már ne dolgozzuk fel
systemManager.setLastLogId(lastLogId);
}
logger.info("end of daily event");
}
@Schedule(dayOfWeek = "Mon", hour = "2")
public void removeExpiredLostPasswordTokens() {
long begin = System.currentTimeMillis();
logger.info("Begin to clean up expired lost password tokens");
accountManager.removeExpiredLostPasswordTokens();
logger.info("clean up end, spent time={}ms", System.currentTimeMillis() - begin);
}
/**
* Notifies the group leaders about the membership changes. The query
* returns log entries ordered by group, then event, then the last name of
* the user whom membership changed. We iterate through the log entries and
* group them by groups and events.
*
* @param lastUsedLogId
* @param lastLogId
*/
private void notifyGroupLeaders(final long lastUsedLogId, final long lastLogId) {
final EventType[] events = {EventType.JELENTKEZES, EventType.TAGSAGTORLES};
final TypedQuery<Log> q = em.createNamedQuery(Log.getFreshEventsForEventTypeByGroup,
Log.class);
q.setParameter("lastUsedLogId", lastUsedLogId);
q.setParameter("lastLogId", lastLogId);
q.setParameter("events", Arrays.asList(events));
final List<Log> logs = q.getResultList();
final Map<Group, List<Log>> logsByGroup = collectLogsByGroup(logs);
for (Group group : logsByGroup.keySet()) {
final List<Log> entries = logsByGroup.get(group);
logger.debug("group={}, entries size={}", group.getName(), entries.size());
if (!entries.isEmpty()) {
final User leader = groupManager.findLeaderForGroup(group.getId());
if (leader != null) {
final String text = String.format(MSG_BODY_TEMPLATE,
String.format("Körvezető (%s)", group.getName()),
getReportForEvents(entries));
logger.debug("send mail: {}\n{}", leader.getEmailAddress(), text);
sendEmail(leader.getEmailAddress(), text);
}
}
}
}
/**
* Iterates through the log entries and group them by groups.
*
* @param logs
* @return
*/
private Map<Group, List<Log>> collectLogsByGroup(final List<Log> logs) {
final Map<Group, List<Log>> logsByGroup = new HashMap<>(logs.size());
for (Log log : logs) {
final Group group = log.getGroup();
if (logsByGroup.get(group) == null) {
logsByGroup.put(group, new LinkedList<Log>());
}
logsByGroup.get(group).add(log);
}
return logsByGroup;
}
/**
* Generates the body of the mail from the logs. Groups the entries by the
* type of the logs and display a profile link to the users.
*
* @param entries
* @return
*/
private String getReportForEvents(final List<Log> entries) {
final StringBuilder mailBodyForUser = new StringBuilder();
Log prev = null;
for (int i = 0; i < entries.size(); i++) {
final Log current = entries.get(i);
if (prev == null || !current.getEvent().equals(prev.getEvent())) {
//display the event summary
mailBodyForUser.append(current.getEvent().toString());
prev = current;
}
mailBodyForUser.append(current.getUser().getFullName()).append(" -> ");
mailBodyForUser.append(systemManager.getShowUserLink()).append(current.getUser().getId()).append("\n");
}
return mailBodyForUser.toString();
}
/**
* Notifies the SVIE admins about SVIE state changes of users.
*
* @param lastUsedLogId
* @param lastLogId
*/
private void notifySvieAdmin(final long lastUsedLogId, final long lastLogId) {
final EventType[] events = {EventType.PARTOLOVAVALAS,
EventType.SVIE_JELENTKEZES, EventType.SVIE_TAGSAGTORLES,
EventType.RENDESTAGGAVALAS};
final TypedQuery<Log> q = em.createNamedQuery(Log.getFreshEventsForSvie,
Log.class);
q.setParameter("lastUsedLogId", lastUsedLogId);
q.setParameter("lastLogId", lastLogId);
q.setParameter("events", Arrays.asList(events));
final List<Log> entries = q.getResultList();
logger.debug("entries size={}", entries.size());
if (!entries.isEmpty()) {
final String text = String.format(MSG_BODY_TEMPLATE,
"SVIE Adminisztrátor",
getReportForEvents(entries));
logger.debug("send mail with text={}", text);
final List<User> svieAdmins = groupManager.findMembersByGroupAndPost(Group.SVIE,
"adminisztrátor");
final List<String> emailAddresses = new LinkedList<>();
final List<String> names = new LinkedList<>();
for (User u : svieAdmins) {
names.add(u.getFullName());
emailAddresses.add(u.getEmailAddress());
}
sendEmail(StringUtils.join(emailAddresses, ","), text);
logger.info("Mail sent to SVIE administrators ({}).",
StringUtils.join(names, ", "));
}
}
/**
* Notifies the SVIE president about {@link EventType#ELFOGADASALATT} events
*
* @param lastUsedLogId
* @param lastLogId
*/
private void notifySviePresident(final long lastUsedLogId, final long lastLogId) {
final TypedQuery<Log> q = em.createNamedQuery(Log.getFreshEventsForSvie, Log.class);
q.setParameter("lastUsedLogId", lastUsedLogId);
q.setParameter("lastLogId", lastLogId);
q.setParameter("events", Arrays.asList(EventType.ELFOGADASALATT));
final List<Log> entries = q.getResultList();
logger.debug("entries size={}", entries.size());
if (!entries.isEmpty()) {
final String text = String.format(MSG_BODY_TEMPLATE,
"Választmányi elnök",
getReportForEvents(entries));
logger.debug("send mail with text={}", text);
final User sviePresident = groupManager.findLeaderForGroup(Group.VALASZTMANY);
sendEmail(sviePresident.getEmailAddress(), text);
logger.info("Mail sent to SVIE president ({}).",
sviePresident.getFullName());
}
}
private void sendEmail(String emailTo, String text) {
mailManager.sendEmail(emailTo, MSG_SUBJECT, text);
}
private long getLastLogId() {
final TypedQuery<Long> q = em.createNamedQuery(Log.getLastId, Long.class);
q.setMaxResults(1);
try {
return q.getSingleResult();
} catch (NoResultException ex) {
return 0;
}
}
}