package org.gbif.ipt.task;
import org.gbif.ipt.config.DataDir;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
public abstract class ReportingTask {
protected Logger log = Logger.getLogger(this.getClass());
protected final DataDir dataDir;
private final String resourceShortname;
private final ReportHandler handler;
private List<TaskMessage> messages = new ArrayList<TaskMessage>();
private final int reportingIntervall;
private StatusReport lastReport;
protected BufferedWriter publicationLogWriter;
/**
* Constructor.
*
* @param reportingIntervall interval reporting is carried out in milliseconds
* @param resourceShortname shortname of resource
* @param handler ReportHandler
* @param dataDir DataDir
*
* @throws IOException if BufferedWriter to publication log file writer could not be created
*/
protected ReportingTask(int reportingIntervall, String resourceShortname, ReportHandler handler, DataDir dataDir)
throws IOException {
this.resourceShortname = resourceShortname;
this.handler = handler;
this.reportingIntervall = reportingIntervall;
this.dataDir = dataDir;
this.publicationLogWriter = getPublicationLogWriter(resourceShortname);
}
/**
* Logs message, and writes it to publication log file.
*
* @param lvl Log level
* @param msg message
*/
protected void addMessage(Level lvl, String msg) {
if (Level.ERROR.equals(lvl)) {
log.error(msg);
} else if (Level.WARN.equals(lvl)) {
log.warn(msg);
} else if (Level.INFO.equals(lvl)) {
log.info(msg);
} else {
log.debug(msg);
}
messages.add(new TaskMessage(lvl, msg));
// write to publication log file also
writePublicationLogMessage(msg);
}
protected abstract boolean completed();
protected abstract Exception currentException();
protected abstract String currentState();
/**
* Reports back the state of the task to the reporting handler configured.
* Call this method at least once a second inside your task if possible, so users keep updated.
*/
public StatusReport report() {
Exception e = currentException();
if (e != null) {
lastReport = new StatusReport(e, currentState(), messages);
} else {
lastReport = new StatusReport(completed(), currentState(), messages);
}
handler.report(resourceShortname, lastReport);
return lastReport;
}
/**
* Calls method report if a certain amount of time specified by reportingIntervall in milliseconds has passed since
* the last reporting.
*/
public void reportIfNeeded() {
if (lastReport == null || new Date().getTime() - lastReport.getTimestamp() > reportingIntervall) {
report();
}
}
/**
* Create new publication log writer ("publication.log") in resource directory. The method does not replace any
* existing version of the file.
*
* @param resourceShortname resource short name
*
* @return BufferedWriter
*
* @throws IOException if publication log writer could not be created
*/
private BufferedWriter getPublicationLogWriter(String resourceShortname) throws IOException {
File logFile = dataDir.resourcePublicationLogFile(resourceShortname);
return new BufferedWriter(new FileWriter(logFile));
}
/**
* Write log message to publication log file as a new line but suffocate any exception thrown.
*
* @param message message to write
*/
protected void writePublicationLogMessage(String message) {
try {
publicationLogWriter.write(message + "\n");
} catch (IOException e) {
log.error("Publication log file could not be written to by writer: " + e.getMessage(), e);
}
}
/**
* Close publication log file writer, if the writer is not null.
*/
protected void closePublicationLogWriter() {
if (publicationLogWriter != null) {
try {
publicationLogWriter.flush();
publicationLogWriter.close();
} catch (IOException e) {
log.error("Publication log file writer could not be closed: " + e.getMessage(), e);
}
}
}
}