package gov.nysenate.openleg.dao.calendar.alert; import gov.nysenate.openleg.config.Environment; import gov.nysenate.openleg.dao.base.LimitOffset; import gov.nysenate.openleg.dao.base.SqlBaseDao; import gov.nysenate.openleg.model.calendar.alert.CalendarAlertFile; import gov.nysenate.openleg.util.FileIOUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.core.RowMapper; import org.springframework.jdbc.core.namedparam.MapSqlParameterSource; import org.springframework.stereotype.Repository; import javax.annotation.PostConstruct; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; import java.util.regex.Pattern; import java.util.stream.Collectors; import static gov.nysenate.openleg.dao.calendar.alert.SqlCalendarAlertFileQuery.*; import static gov.nysenate.openleg.util.DateUtils.toDate; @Repository public class SqlFsCalendarAlertFileDao extends SqlBaseDao { private static final Logger logger = LoggerFactory.getLogger(SqlFsCalendarAlertFileDao.class); private static final Pattern calendarAlertFilePattern = Pattern.compile("^(floor_cal|active_list)_alert-\\d{4}-\\d+[A-Z]?-\\d{8}T\\d{6}.html$"); @Autowired private Environment environment; private File incomingCalendarAlertDir; private File archiveCalendarAlertDir; @PostConstruct public void init() { incomingCalendarAlertDir = new File(environment.getStagingDir(), "alerts"); archiveCalendarAlertDir = new File(environment.getArchiveDir(), "alerts"); } /** * Retrieve all calendar alert files from the incoming directory. * * @return * @throws IOException */ public List<CalendarAlertFile> getIncomingCalendarAlerts() throws IOException { List<File> files = FileIOUtils.safeListFiles(incomingCalendarAlertDir, null, false).stream() .filter(file -> calendarAlertFilePattern.matcher(file.getName()).matches()) .collect(Collectors.toList()); List<CalendarAlertFile> calendarAlertFiles = new ArrayList<>(); for (File file : files) { calendarAlertFiles.add(new CalendarAlertFile(file)); } return calendarAlertFiles; } /** * Moves the calendar alert file to the archive directory. * * @param calendarAlertFile * @return a new CalendarAlertFile with a reference to the new file location. * @throws IOException */ public CalendarAlertFile archiveCalendarAlertFile(CalendarAlertFile calendarAlertFile) throws IOException { File stagedFile = calendarAlertFile.getFile(); if (isInIncomingDirectory(stagedFile)) { calendarAlertFile = archive(stagedFile); } return calendarAlertFile; } /** * Update a CalendarAlertFile in the database, If its new, insert it instead. * @param calendarAlertFile */ public void updateCalendarAlertFile(CalendarAlertFile calendarAlertFile) { MapSqlParameterSource params = getCalanderAlertFileParams(calendarAlertFile); if (jdbcNamed.update(UPDATE_CALENDAR_ALERT_FILE.getSql(schema()), params) == 0) { jdbcNamed.update(INSERT_CALENDAR_ALERT_FILE.getSql(schema()), params); } } /** * Get all CalendarAlertFiles awaiting processing. * @param limOff * @return */ public List<CalendarAlertFile> getPendingCalendarAlertFiles(LimitOffset limOff) { return jdbcNamed.query(GET_PENDING_CALENDAR_ALERT_FILES.getSql(schema(), limOff), new CalendarAlertFileRowMapper()); } private CalendarAlertFile archive(File stagedFile) throws IOException { File archivedFile = new File(archiveCalendarAlertDir, stagedFile.getName()); moveFile(stagedFile, archivedFile); CalendarAlertFile calendarAlertFile = new CalendarAlertFile(archivedFile); calendarAlertFile.setArchived(true); return calendarAlertFile; } private boolean isInIncomingDirectory(File stagedFile) { return stagedFile.getParentFile().compareTo(incomingCalendarAlertDir) == 0; } protected class CalendarAlertFileRowMapper implements RowMapper<CalendarAlertFile> { @Override public CalendarAlertFile mapRow(ResultSet rs, int rowNum) throws SQLException { String filename = rs.getString("file_name"); boolean archived = rs.getBoolean("archived"); File file = archived ? getFileInArchivedDir(filename) : getFileInIncomingDir(filename); CalendarAlertFile calendarAlertFile = null; try { calendarAlertFile = new CalendarAlertFile(file); calendarAlertFile.setProcessedDateTime(getLocalDateTimeFromRs(rs, "processed_date_time")); calendarAlertFile.setProcessedCount(rs.getInt("processed_count")); calendarAlertFile.setStagedDateTime(getLocalDateTimeFromRs(rs, "staged_date_time")); calendarAlertFile.setPendingProcessing(rs.getBoolean("pending_processing")); calendarAlertFile.setArchived(archived); } catch (FileNotFoundException ex) { logger.error("CalendarAlert File " + filename + " was not found in the expected location.", ex); } return calendarAlertFile; } } private File getFileInArchivedDir(String filename) { return new File(archiveCalendarAlertDir, filename); } private File getFileInIncomingDir(String filename) { return new File(incomingCalendarAlertDir, filename); } private MapSqlParameterSource getCalanderAlertFileParams(CalendarAlertFile file) { MapSqlParameterSource params = new MapSqlParameterSource(); params.addValue("fileName", file.getFile().getName()); params.addValue("processedDateTime", toDate(file.getProcessedDateTime())); params.addValue("processedCount", file.getProcessedCount()); params.addValue("pendingProcessing", file.isPendingProcessing()); params.addValue("archived", file.isArchived()); return params; } }