// Copyright © 2015 HSL <https://www.hsl.fi>
// This program is dual-licensed under the EUPL v1.2 and AGPLv3 licenses.
package fi.hsl.parkandride.core.service.reporting;
import fi.hsl.parkandride.core.back.RequestLogRepository;
import fi.hsl.parkandride.core.domain.Permission;
import fi.hsl.parkandride.core.domain.RequestLogEntry;
import fi.hsl.parkandride.core.domain.RequestLogKey;
import fi.hsl.parkandride.core.domain.User;
import org.apache.poi.ss.usermodel.CellStyle;
import org.joda.time.DateTime;
import org.joda.time.LocalDate;
import javax.inject.Inject;
import java.util.List;
import java.util.Optional;
import static fi.hsl.parkandride.core.service.AuthenticationService.authorize;
import static fi.hsl.parkandride.util.ArgumentValidator.validate;
import static java.util.Arrays.asList;
import static java.util.Comparator.comparing;
import static java.util.stream.Collectors.*;
public class RequestLogReportService implements ReportService {
private static final String REPORT_NAME = "RequestLog";
@Inject
ExcelUtil excelUtil;
@Inject
RequestLogRepository requestLogRepository;
@Override
public byte[] generateReport(User currentUser, ReportParameters reportParameters) {
authorize(currentUser, Permission.REPORT_GENERATE);
Excel excel = new Excel();
final RequestLogInterval interval = Optional.ofNullable(reportParameters.requestLogInterval).orElse(RequestLogInterval.DAY);
addRequestLogSheet(excel, getRowsForDates(
validate(reportParameters.startDate).notNull(),
validate(reportParameters.endDate).notNull(),
interval
), interval);
excel.addSheet(excelUtil.getMessage("reports.requestlog.sheets.legend"),
excelUtil.getMessage("reports.requestlog.legend").split("\n"));
return excel.toBytes();
}
private List<RequestLogEntry> getRowsForDates(LocalDate startDate, LocalDate endDate, RequestLogInterval interval) {
final DateTime start = startDate.toDateTimeAtStartOfDay();
final DateTime end = endDate.toDateTimeAtStartOfDay().millisOfDay().withMaximumValue();
validate(start).lte(end);
final List<RequestLogEntry> logEntriesBetween = requestLogRepository.getLogEntriesBetween(start, end);
return logEntriesBetween.stream()
.collect(groupingBy(entry -> interval.apply(entry.key)))
.entrySet().stream()
.map(groupedEntry -> {
final RequestLogKey key = groupedEntry.getKey();
final Long totalCount = groupedEntry.getValue().stream().collect(summingLong(entry -> entry.count));
return new RequestLogEntry(key, totalCount);
})
.sorted(comparing(entry -> entry.key))
.collect(toList());
}
@Override
public String reportName() {
return REPORT_NAME;
}
private void addRequestLogSheet(Excel excel, List<RequestLogEntry> logRows, RequestLogInterval interval) {
final String unknownSource = excelUtil.getMessage("reports.requestlog.unknownSource");
excel.addSheet(excelUtil.getMessage("reports.requestlog.sheets.log"), logRows, asList(
excelUtil.tcol("reports.requestlog.col.timestamp." + interval, (RequestLogEntry entry) -> entry.key.timestamp, cellStyleFor(excel, interval)),
excelUtil.tcol("reports.requestlog.col.source", (RequestLogEntry entry) -> Optional.ofNullable(entry.key.source).orElse(unknownSource)),
excelUtil.tcol("reports.requestlog.col.url", (RequestLogEntry entry) -> entry.key.urlPattern),
excelUtil.tcol("reports.requestlog.col.count", (RequestLogEntry entry) -> entry.count.intValue())
));
}
private CellStyle cellStyleFor(Excel excel, RequestLogInterval interval) {
if (interval == RequestLogInterval.HOUR) {
return excel.datetime;
} else if (interval == RequestLogInterval.DAY) {
return excel.date;
} else {
return excel.month;
}
}
}