You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 2 Current »

/* ================================================================
 * 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);
    }
}  
 
  • No labels