/* ================================================================
* Delft FEWS
* ================================================================
*
* Project Info: http://www.wldelft.nl/soft/fews/index.html
* Project Lead: Karel Heynert (karel.heynert@wldelft.nl)
*
* (C) Copyright 2003, by WL | Delft Hydraulics
* P.O. Box 177
* 2600 MH Delft
* The Netherlands
* http://www.wldelft.nl
*
* DELFT-FEWS is a sophisticated collection of modules designed
* for building a FEWS customised to the specific requirements
* of individual agencies. An open modelling approach allows users
* to add their own modules in an efficient way.
*
* ----------------------------------------------------------------
* TsdTimeSeriesWriter.java
* ----------------------------------------------------------------
* (C) Copyright 2003, by WL | Delft Hydraulics
*
* Original Author: Micha Werner
* Contributor(s):
*
* Changes:
* --------
* 6-dec-2006 : Version 1 ();
*
*
*/
package nl.wldelft.fews.system.plugin.dataExport;
import nl.wldelft.util.FastDateFormat;
import nl.wldelft.util.Period;
import nl.wldelft.util.TextUtils;
import nl.wldelft.util.io.LineWriter;
import nl.wldelft.util.io.TextSerializer;
import nl.wldelft.util.timeseries.TimeSeriesContent;
import nl.wldelft.util.timeseries.TimeSeriesHeader;
import nl.wldelft.util.timeseries.TimeStep;
import org.apache.log4j.Logger;
import java.io.IOException;
import java.util.Date;
import java.util.Locale;
/**
* <p>The class <code>ShefTimeSeriesWriter</code> exports the time series from Fews system
* in SHEF formatted export file(s). See the description of the SHEF format for more information.
* </p>
*/
public class ShefTimeSeriesSerializer implements TextSerializer<TimeSeriesContent> {
private static final Logger log = Logger.getLogger(ShefTimeSeriesSerializer.class);
// location, missingValue, values
//ToDo Use configured precision of the parameters to print the values
private static final byte[] MISSING_VALUE = " M".getBytes();
private final long timeZero;
private FastDateFormat dateFormat = null;
private FastDateFormat dateFormatCreation = null;
private FastDateFormat obsTimeFormat = null;
private TimeSeriesContent content = null;
private LineWriter writer = null;
private byte[] charBuffer = new byte[30];
private TimeSeriesHeader header;
public ShefTimeSeriesSerializer(long timeZero) {
this.timeZero = timeZero;
}
@Override
public void serialize(TimeSeriesContent content, LineWriter writer, String virtualFileName) throws Exception {
dateFormat = FastDateFormat.getInstance("yyyyMMdd", content.getDefaultTimeZone(), Locale.US, dateFormat);
dateFormatCreation = FastDateFormat.getInstance("yyyyMMddHHmm", content.getDefaultTimeZone(), Locale.US, dateFormatCreation);
obsTimeFormat = FastDateFormat.getInstance("HH", content.getDefaultTimeZone(), Locale.US, obsTimeFormat);
this.content = content;
this.writer = writer;
writeHeader();
for (int i = 0, n = content.getTimeSeriesCount(); i < n; i++) {
content.setTimeSeriesIndex(i);
header = content.getTimeSeriesHeader();
if (!header.getTimeStep().isRegular()) {
log.error("Cannot write nonEquidistant data to SHEF (.E) format for " + header);
}else{
writeHeaderLine();
writeDataLine();
}
}
}
private void writeHeader() throws IOException {
writer.writeLine(": Delft-FEWS - exported SHEF file");
String timeZeroText = this.dateFormat.format(new Date(this.timeZero));
writer.writeLine(": Date/time forecast: " + timeZeroText);
}
private void writeHeaderLine() throws Exception {
if(content.getTimeSeriesPeriod() == Period.NEVER){
if (log.isInfoEnabled()) log.info("No data found for " + header);
return;
}
long currentTime = System.currentTimeMillis();
writer.newLine();
writer.write(".ER ");
writer.write(header.getLocationId());
writer.write(' ') ;
Date startDate = content.getTimeSeriesPeriod().getStartDate();
writer.write(this.dateFormat.format(startDate));
writer.write(getTimeZoneShefCode(content.getDefaultTimeZone().getID()));
writer.write("DH" + obsTimeFormat.format(startDate));
writer.write("/DC") ;
writer.write(this.dateFormatCreation.format(currentTime));
writer.write('/') ;
writer.write(TextUtils.padRight(header.getParameterId(), 7)) ;
writer.write('/') ;
writeTimeStep();
writer.newLine();
}
private void writeDataLine() throws Exception {
//Determine width of column with line number (e.g. .E37)
int lineCountColWidth = 5; // default .E + 2 places for line nr + one space
int ndig = TextUtils.getNumberOfDigits(content.getContentTimeCount() / 8); //8 = number of values per line
if (ndig > 2) lineCountColWidth = ndig + 3; // .E + ndig places for line nr + one space
int linecount = 1;
int count = 0;
for (int i = 0, n = content.getContentTimeCount(); i < n; i++) {
content.setContentTimeIndex(i);
if (!content.isTimeAvailable()) continue;
if (count == 0) {
writer.write(TextUtils.padRight(".E"+linecount, lineCountColWidth));
}
if (content.isValueMissing() && Float.isNaN(content.getDefaultMissingValue())) {
writer.write(MISSING_VALUE, 0, 8);
} else {
writer.write(content.getValue('.')); //get formatted value
}
writer.write('/');
count++;
if (count == 8 || i == n - 1) {
linecount++;
writer.newLine();
count = 0;
}
}
}
private void writeTimeStep() throws Exception {
TimeStep timeStep = header.getTimeStep();
long dtime = timeStep.getMaximumStepMillis()/ 1000;
writer.write("DI");
if (dtime < 60) {
writer.write("I" + dtime);
} else if (dtime < 3600) {
writer.write("N" + dtime / 60);
} else if (dtime < 36000) {
writer.write("H0" + dtime / 3600);
} else if (dtime < 86400) {
writer.write("H" + dtime / 3600);
} else {
writer.write("D" + dtime / 86400);
}
}
private static String getTimeZoneShefCode(String timeZoneId) throws IOException {
//Documented in http://www.nws.noaa.gov/om/water/resources/SHEF_CodeManual_5July2012.pdf , Table 8
if (timeZoneId.equals("GMT")) return " Z ";
if (timeZoneId.equals("CNT")) return " N ";
if (timeZoneId.equals("CNT")) return " N ";
if (timeZoneId.equals("PRT")) return " A ";
if (timeZoneId.equals("EST")) return " E ";
if (timeZoneId.equals("IET")) return " E ";
if (timeZoneId.equals("CST")) return " C ";
if (timeZoneId.equals("MST")) return " M ";
if (timeZoneId.equals("PST")) return " P ";
if (timeZoneId.equals("HST")) return " H ";
if (timeZoneId.equals("AST")) return " L ";
throw new IOException("SHEF export does not supported time zone Id " + timeZoneId);
}
}
|