/*******************************************************************************
* Australian National University Data Commons
* Copyright (C) 2013 The Australian National University
*
* This file is part of Australian National University Data Commons.
*
* Australian National University Data Commons is free software: you
* can redistribute it and/or modify it under the terms of the GNU
* General Public License as published by the Free Software Foundation,
* either version 3 of the License, or (at your option) any later
* version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package au.edu.anu.datacommons.report;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import javax.annotation.Resource;
import javax.servlet.ServletContext;
import javax.ws.rs.core.Context;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import au.edu.anu.datacommons.data.db.dao.GenericDAO;
import au.edu.anu.datacommons.data.db.dao.GenericDAOImpl;
import au.edu.anu.datacommons.data.db.model.Groups;
import au.edu.anu.datacommons.data.db.model.Report;
import au.edu.anu.datacommons.data.db.model.ReportAuto;
import au.edu.anu.datacommons.data.db.model.ReportAutoParam;
import au.edu.anu.datacommons.data.db.model.ReportAutoParamPK;
import au.edu.anu.datacommons.data.db.model.ReportParam;
import au.edu.anu.datacommons.exception.ValidateException;
import au.edu.anu.datacommons.report.schedule.ReportSchedulerManager;
import au.edu.anu.datacommons.report.schedule.ScheduledReport;
import au.edu.anu.datacommons.security.service.GroupService;
/**
* ReportServiceImpl
*
* Australian National University Data Commons
*
* Implementation class for the report service
*
* JUnit coverage:
* ReportServiceTest
*
* @author Genevieve Turner
*
*/
@Service("reportServiceImpl")
public class ReportServiceImpl implements ReportService {
static final Logger LOGGER = LoggerFactory.getLogger(ReportServiceImpl.class);
@Resource(name="groupServiceImpl")
GroupService groupService;
@Context
ServletContext context;
private static final Map<String, String> dayOfWeekMap;
static {
Map<String, String> aMap = new HashMap<String, String>();
aMap.put("MON", "Monday");
aMap.put("TUE", "Tuesday");
aMap.put("WED", "Wednesday");
aMap.put("THU", "Thursday");
aMap.put("FRI", "Friday");
aMap.put("SAT", "Saturday");
aMap.put("SUN", "Sunday");
dayOfWeekMap = Collections.unmodifiableMap(aMap);
}
@Override
public List<Report> getAllReports() {
GenericDAO<Report, Long> reportDAO = new GenericDAOImpl<Report, Long>(Report.class);
List<Report> reports = reportDAO.getAll();
return reports;
}
@Override
public List<ReportParam> getReportParameters(Long reportId) {
GenericDAO<Report, Long> reportDAO = new GenericDAOImpl<Report, Long>(Report.class);
Report report = reportDAO.getSingleById(reportId);
return report.getReportParams();
}
@Override
public List<Groups> getGroups() {
return groupService.getAll();
}
@Override
public String generateCronString(String dayOfWeek, String hour, String minute) {
try {
int hourInt = Integer.parseInt(hour);
if (hourInt < 0 || hourInt > 23) {
throw new ValidateException("Hour is not valid");
}
}
catch (NumberFormatException e) {
throw new ValidateException("Hour is not valid");
}
try {
int minuteInt = Integer.parseInt(minute);
if (minuteInt < 0 || minuteInt > 59) {
throw new ValidateException("Minute is not valid");
}
}
catch (NumberFormatException e) {
throw new ValidateException("Minute is not valid");
}
if (!dayOfWeekMap.containsKey(dayOfWeek)) {
throw new ValidateException("The day of week is not valid");
}
String cron = "0 " + minute + " " + hour + " * * " + dayOfWeek;
return cron;
}
@Override
public ReportAuto schedule(Long reportId, String email, String cron, String format,
Map<String, String[]> parameterMap) {
List<ReportParam> reportParameters = getReportParameters(reportId);
ReportAuto reportAuto = new ReportAuto();
reportAuto.setReportId(reportId);
reportAuto.setEmail(email);
reportAuto.setCron(cron);
reportAuto.setFormat(format);
GenericDAO<ReportAuto, Long> reportAutoDAO = new GenericDAOImpl<ReportAuto, Long>(ReportAuto.class);
reportAuto = reportAutoDAO.create(reportAuto);
GenericDAO<ReportAutoParam, ReportAutoParamPK> reportAutoParamDAO = new GenericDAOImpl<ReportAutoParam, ReportAutoParamPK>(ReportAutoParam.class);
int counter = 0;
for (ReportParam reportParam : reportParameters) {
LOGGER.info("Report Param: {}", reportParam.getParamName());
String[] parameterValues = parameterMap.get(reportParam.getParamName());
if (parameterValues != null && parameterValues.length > 0) {
for (String value : parameterValues) {
ReportAutoParam param = new ReportAutoParam();
ReportAutoParamPK pk = new ReportAutoParamPK();
pk.setReportAutoId(reportAuto.getId());
pk.setSeqNum(counter);
param.setId(pk);
param.setParam(reportParam.getParamName());
param.setParamVal(value);
reportAutoParamDAO.create(param);
}
}
};
reportAuto = reportAutoDAO.getSingleById(reportAuto.getId());
scheduleAll();
return reportAuto;
}
/**
* Scheduled all the reports to run
*/
public void scheduleAll() {
ReportSchedulerManager.getInstance().getReportScheduler().scheduleAll();
}
@Override
public List<ScheduledReport> getScheduledReports() {
GenericDAO<ReportAuto, Long> reportAutoDAO = new GenericDAOImpl<ReportAuto, Long>(ReportAuto.class);
List<ReportAuto> autoReports = reportAutoDAO.getAll();
List<ScheduledReport> scheduledReports = new ArrayList<ScheduledReport>();
GenericDAO<Report, Long> reportDAO = new GenericDAOImpl<Report,Long>(Report.class);
for (ReportAuto reportAuto : autoReports) {
Map<String, String> cronMap = mapCronString(reportAuto.getCron());
Report report = reportDAO.getSingleById(reportAuto.getReportId());
ScheduledReport scheduledReport = new ScheduledReport(reportAuto.getId(), report.getReportName(), reportAuto.getEmail(), reportAuto.getFormat(), cronMap);
scheduledReports.add(scheduledReport);
}
return scheduledReports;
}
@Override
public void deleteScheduledReport(Long reportAutoId) {
GenericDAO<ReportAuto, Long> reportAutoDAO = new GenericDAOImpl<ReportAuto, Long>(ReportAuto.class);
ReportAuto reportAuto = reportAutoDAO.getSingleById(reportAutoId);
if (reportAuto.getReportAutoParams() != null && reportAuto.getReportAutoParams().size() > 0) {
GenericDAO<ReportAutoParam, ReportAutoParamPK> reportAutoParamDAO = new GenericDAOImpl<ReportAutoParam, ReportAutoParamPK>(ReportAutoParam.class);
for (ReportAutoParam param : reportAuto.getReportAutoParams()) {
reportAutoParamDAO.delete(param.getId());
}
}
reportAutoDAO.delete(reportAutoId);
scheduleAll();
}
@Override
public Map<String, String> mapCronString(String cron) {
Map<String, String> cronMap = new HashMap<String, String>();
String[] splitCron = cron.split(" ");
if (!splitCron[0].equals("*")) {
cronMap.put("second", splitCron[0]);
}
if (!splitCron[1].equals("*")) {
cronMap.put("minute", splitCron[1]);
}
if (!splitCron[2].equals("*")) {
cronMap.put("hour", splitCron[2]);
}
if (!splitCron[3].equals("*")) {
cronMap.put("dayOfMonth", splitCron[3]);
}
if (!splitCron[4].equals("*")) {
cronMap.put("dayOfYear", splitCron[4]);
}
if (!splitCron[5].equals("*")) {
String dayOfWeek = getDaysOfWeek(splitCron[5]);
cronMap.put("dayOfWeek", dayOfWeek);
}
return cronMap;
}
/**
* Replace the shortened day of week from the cron with a full day of week name. e.g. change 'FRI' to 'Friday'.
*
* @param dayOfWeek The day of week
* @return The full day of week
*/
private String getDaysOfWeek(String dayOfWeek) {
for (Entry<String, String> entry : dayOfWeekMap.entrySet()) {
dayOfWeek = dayOfWeek.replace(entry.getKey(), entry.getValue());
}
return dayOfWeek;
}
}