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();
}
|