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

Compare with Current View Page History

« Previous Version 3 Next »

package nl.wldelft.util.timeseries;

import nl.wldelft.util.Period;
import nl.wldelft.util.coverage.Geometry;
import nl.wldelft.util.coverage.NonGeoReferencedGridGeometry;
import nl.wldelft.util.geodatum.GeoDatum;

import java.util.TimeZone;
import java.text.SimpleDateFormat;

/**
 * The interface <code>TimeSeriesContentHandler</code> represents the classes
 * to handle the timeseries data that are supplied  by the timeseries parsers.
 */
public interface TimeSeriesContentHandler {

    /**
     * Defines time zone which should be used while importing time series.
     * If time zone is defined in the file format - this TimeZone should not be used.
     * @return
     */
    TimeZone getDefaultTimeZone();

    /**
     * Adds a value that should be recognized as missing when calling {@link #setValue(float)}, {@link #setValue(char, String)}  or {@link #setCoverageValues(float[])}
     * {@link Float#NaN} is always recognized as missing
     */
    void addMissingValue(float missingValue);

    /**
     * Adds a alpha numeric tag that should be recognized as missing when calling {@link #setValue(char, String)}
     * These alphanemeric missings are not recognized when using {@link #setValue(float)} or {@link #setCoverageValues(float[])}
     * The missings added with {@link #addMissingValue(float)}  and {@link #addMissingValueRange(float, float)}  are also recognized
     * {@link Float#NaN} is always recognized as missing
     *
     */
    void addMissingValue(String missingValue);

    /**
     * Adds a range of values that should be recognized as missing when calling {@link #setValue} or {@link #setCoverageValues(float[])}
     *  NaN, null and an empty string, string with only spaces are always recognized as missing
     */
    void addMissingValueRange(float minMissingValue, float maxMissingValue);

    /**
     * Creating an alias allows high speed switching between different headers
     * E.g. For files with multiple parameters per row, for every row multiple switches are required between different headers
     * This will not work properly without defining an alias for every column
     * The alias is ultimate fast in the range form 0 to 1000
     *
     * @param alias, integer for ultimata speed, good practice is to use the parameter column index.
     * @param header
     */
    void createTimeSeriesHeaderAlias(int alias, TimeSeriesHeader header);


    /**
     * Changes the header that will be used when calling {@link #applyCurrentFields()}
     * A call to this method will not consume any significant time
     * {@link #setTimeSeriesHeader(TimeSeriesHeader)}  is relatively time consuming
     * @see #createTimeSeriesHeaderAlias(int, TimeSeriesHeader)
     * @param alias defined with {@link #createTimeSeriesHeaderAlias (int, TimeSeriesHeader)}
     * @throws IllegalArgumentException when alias is not created before
     */
    void setTimeSeriesHeader(int alias);


    /**
     * Same as {@link #setTimeSeriesHeader(int)} , but slightly SLOWER
     * The second time this method is called for the SAME header,
     * there is NO new time series created but the first one is re-selected
     * This method is relatively time consuming.
     * When parsing multiple parameters per row use {@link #setTimeSeriesHeader (int)}
     */
    void setTimeSeriesHeader(TimeSeriesHeader header);

    /**
     * Changes the time that will be used when calling {@link #applyCurrentFields()}
     * A NEW time series is created, with a new forecast time and new ensemble member index
     * A warning is logged when this method is called twice for the same header (historical non ensemlbe time series)
     */
    void setNewTimeSeriesHeader(TimeSeriesHeader header);

    /**
     * The parser should call this method when it starts parsing time/values and has any idea of the period of the values that will come.
     * This information is only used by this content handler for OPTIMALISATION and
     * is never required and never results in an error when the real period is differs from the estimated period
     * @param period
     */
    void setEstimatedPeriod(Period period);

    /**
     * Changes the time that will be used when calling {@link #applyCurrentFields()}
     *
     * @param time Represents the number of milliseconds since January 1, 1970, 00:00:00 GMT
     */
    void setTime(long time);

    /**
     * Changes the time that will be used when calling {@link #applyCurrentFields()}
     *
     * In addition to simple date format 24h will be recognized as 0h the next day
     *
     * @param timeZone. When not known use {@link #getDefaultTimeZone()}
     * @param pattern see {@link SimpleDateFormat}, in addition for HH  24 will be recognized as 0:00 the next day
     * @param dateTime leading and trailing spaces are ignored
     */
    void setTime(TimeZone timeZone, String pattern, String dateTime);

    /**
     * Changes the time that will be used when calling {@link #applyCurrentFields()}
     *
     * In addition to simple date format 24h will be recognized as 0h the next day
     *
     * @param timeZone. When not known use {@link #getDefaultTimeZone()}
     * @param datePattern see {@link SimpleDateFormat}
     * @param date leading and trailing spaces are ignored
     * @param timePattern see {@link SimpleDateFormat}, in addition for HH  24 will be recognized as 0:00 the next day
     * @param time leading and trailing spaces are ignored
     */
    void setTime(TimeZone timeZone, String datePattern, String date, String timePattern, String time);

    /**
     * Return false if any value for the selected time series with {@link #setTimeSeriesHeader} is wanted
     * When true parsing of ALL values for this time series can be skipped
     */
    boolean isCurrentTimeSeriesHeaderForAllTimesRejected();

    /**
     * Return false if the value selected time {@link #setTimeSeriesHeader} and selected time {@link #setTime(long)}  is wanted
     * When true parsing of the time and time series can be skipped
     */
    boolean isCurrentTimeSeriesHeaderForCurrentTimeRejected();


    /**
     * Changes the flag that will be used for when calling {@link #applyCurrentFields()}
     */
    void setFlag(int flag);

    /**
     * Changes the flag that will be used for when calling {@link #applyCurrentFields()}
     */
    void setFlag(String flag);

    /**
     * Changes the sample id that will be used for when calling {@link #applyCurrentFields()}
     */
    void setSampleId(String sampleId);

    /**
     * Changes the out of detection range that will be used when calling {@link #applyCurrentFields()}
     */
    void setOutOfDetectionRangeFlag(OutOfDetectionRangeFlag flag);

    /**
     * Changes the comment that will be used when calling {@link #applyCurrentFields()}
     */
    void setComment(String comment);

    /**
     * When a overrullilng geometry is defined (in grids.xml) this geometry will overturn the geometry set with {@link #setGeometry(Geometry)}
     * When there is a overrullilng geometry the content handler will log an error when the number of rows and cols is not the same a set with {@link #setGeometry(Geometry)}
     * @return
     */
    Geometry getOverrulingGeometry();

    /**
     * Used by the parser to create a geometry when there is no geometry info available in the file
     */
    GeoDatum getDefaultGeoDatum();

    /**
     * Changes the geometry that will be used when calling {@link #applyCurrentFields()}
     *
     * When only the number of rows and cols are available use {@link NonGeoReferencedGridGeometry#create(int, int))))|
     * @see #getDefaultGeoDatum()
     */
    void setGeometry(Geometry geometry);

    /**
     * Changes the value resolution that will be used when calling {@link #applyCurrentFields()}
     * Only be used when the file format don't uses IEEE floats to store the values
     * e.g. When there are only integers parsed the value resolution is 1.0
     * e.g. When there at maximum to decimals the value resolution is 0.01;
     * e.g. When file format store the values as integers and devides the integers by 5 afterwards the value resolution is 0.2
     *
     * @param valueResolution
     */
    void setValueResolution(float valueResolution);

    /**
     * Changes the value that will be used when calling {@link #applyCurrentFields()}
     */
    void setValue(float value);

    /**
     * Changes the value that will be used when calling {@link #applyCurrentFields()}
     * When the value can not be parsed an error will be logged, no excepton is thrown
     * Add missing value tags before calling this function {@link #addMissingValue(String)}
     * e.g. addMissingValue('?')
     *
     * @param value leading and trailing spaces are ignored
     */
    void setValue(char decimalSeparator, String value);

    /**
     *  Puts the coverage values for the last set time and and last set header with the last set flag and last set geometry
     *  When {@link #getOverrulingGeometry ()} returns not null there is no need to to set the geometry
     *  When the active geometry does not have the same number of rows and cols an error message is logged.
     *  For performance reasons do not parse the values when {@link #isCurrentTimeSeriesHeaderForCurrentTimeRejected()} returns true
     *  For performance reasons do no recreate the values array for every time step again
     */
    void setCoverageValues(float[] values);

    /**
     * Saves the current fields for the current time series header and current time.
     * The current fields are not cleared so it is only required
     * to update the changed fields for the next calll to {@link #applyCurrentFields()}
     */
    void applyCurrentFields();
}
  • No labels