/**
* Parser for Diver *.mon files
*/
public class DiverMonTimeSeriesParser implements TextParser<TimeSeriesContentHandler> {
private static final Logger log = Logger.getLogger(DiverMonTimeSeriesParser.class);
/* headers are written in dutch and english */
private enum DiverHeaderConstants {
DUTCH_HEADER_CONSTANTS("Instrument info",
================================================================
* 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.
*
* ----------------------------------------------------------------
* DiverMonTimeSeriesParser.java
* ----------------------------------------------------------------
* (C) Copyright 2003, by WL | Delft Hydraulics
*
* Original Author: Stephan Zuiderwijk
*/
package nl.wldelft.timeseriesparsers;
import nl.wldelft.util.StringArrayUtils;
import nl.wldelft.util.TextUtils;
import nl.wldelft.util.io.IniFile;
import nl.wldelft.util.io.LineReader;
import nl.wldelft.util.io.TextParser;
import nl.wldelft.util.timeseries.DefaultTimeSeriesHeader;
import nl.wldelft.util.timeseries.TimeSeriesContentHandler;
import org.apache.log4j.Logger;
import java.io.BufferedReader;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.List;
/**
* Parser for Diver *.mon files
*/
public class DiverMonTimeSeriesParser implements TextParser<TimeSeriesContentHandler> {
private static final Logger log = Logger.getLogger(DiverMonTimeSeriesParser.class);
/* headers are written in dutch and english */
private enum DiverHeaderConstants {
DUTCH_HEADER_CONSTANTS("Instrument info",
"Instrument info from data header", "Kanaal", "Locatie", "Identificatie", "Bereik", "Data"),
ENGLISH_HEADER_CONSTANTS("Instrument info",
"Instrument info from data header", "Channel", "Location", "Identification", "Range", "Data"),
LOGGER_HEADER_CONSTANTS("Logger settings",
"Series settings", "Channel", "Location", "Identification", "Range", "Data"),
MIXED_HEADER_CONSTANTS("Instrument info",
"Instrument info from data header", "Kanaal", "Location", "Identification", "Range", "Data"),
ENGLISH_MIXED_HEADER_CONSTANTS("Instrument info",
"Instrument info from data header", "Channel", "Location", "Identification", "Range", "Data"),
INCOMPLETE_HEADER_CONSTANTS("Instrument info",
"Instrument info from data header", "Kanaal", "Locatie", "Identificatie", "Bereik", "Data");
String loggerSettings;
String seriesSettings;
String channel;
String location;
String chnlId;
String chnlRange;
String data;
DiverHeaderConstants(String loggerSettings, String seriesSettings, String channel,
String location, String chnlId, String chnlRange, String data) {
"Instrument info from data header", "Kanaal", "Locatie", "Identificatie", "Bereik", "Data"),
this.location = location;
ENGLISH_HEADER_CONSTANTS("Instrument info",
this.seriesSettings = seriesSettings;
this.chnlId = chnlId;
"Instrument info from data header", "Channel", "Location", "Identification", "Range", "Data"),
this.chnlRange = chnlRange;
LOGGER_HEADER_CONSTANTS("Logger settings",
this.loggerSettings = loggerSettings;
this.channel = channel;
"Series settings", "Channel", "Location", "Identification", "Range", "Data"),
this.data = data;
MIXED_HEADER_CONSTANTS("Instrument info", }
}
private LineReader reader = null;
"Instrumentprivate infoString fromvirtualFileName data header", "Kanaal", "Location", "Identification", "Range", "Data"),= null;
private TimeSeriesContentHandler contentHandler MIXED_HEADER_CONSTANTSNEW("Instrument info",= null;
private int channelCount = -1;
@Override
"Instrumentpublic infovoid from data header", "Kanaal", "Location", "Identification", "Range", "Data"),
INCOMPLETE_HEADER_CONSTANTS("Instrument info",
parse(LineReader reader, String virtualFileName, TimeSeriesContentHandler contentHandler) throws Exception {
this.reader = reader;
this.virtualFileName = virtualFileName;
"Instrument info from data header", "Kanaal", "Locatie", "Identificatie", "Bereik", "Data");
this.contentHandler = contentHandler;
String loggerSettingsthis.contentHandler.addMissingValue(99999f);
String seriesSettingsreader.setSkipEmptyLines(true);
String channelparseHeaders();
String location;
parseData();
}
/**
* StringParses chnlId;
the datarows of the diver file. Data is Stringwritten chnlRange;
as a timestamp, followed by a number of String data;
columns. Each
* column refers DiverHeaderConstants(String loggerSettings, String seriesSettings, String channel,
to a channel that is declared in the Series settings
*
String location,*/
String chnlId, String chnlRange,private Stringvoid dataparseData() throws Exception {
int nrOfLines this.location = location;
= Integer.parseInt(reader.readLine().trim());
this.seriesSettingslong lineCounter = seriesSettings0;
this.chnlIdchar columnSeparator = chnlId'\0';
String[] buffer = this.chnlRange = chnlRangenew String[channelCount + 2];
for (String line; (line = this.loggerSettings reader.readLine()) != loggerSettingsnull;) {
if this.channel(columnSeparator == channel;
'\0') {
this.data = data;
columnSeparator = line.indexOf('\t') == -1 ? ' }
' }
: '\t';
private LineReader reader = null;
private String virtualFileName = null; }
private TimeSeriesContentHandler contentHandler = null;
private int channelCount = -1;
if (line.startsWith("END OF DATA")) break;
@Override
public void parse(LineReader reader, String virtualFileName, TimeSeriesContentHandler contentHandler) throws Exception {
TextUtils.split(line, columnSeparator, buffer);
contentHandler.setTime(contentHandler.getDefaultTimeZone(), this.reader = reader"yyyy/MM/dd", buffer[0], "HH:mm:ss", buffer[1]);
this.virtualFileName = virtualFileName;
for (int i = 0; i this.contentHandler = contentHandler;
< channelCount; i++) {
this.contentHandler.addMissingValue(99999f);
reader.setSkipEmptyLines(true);
String valueText = parseHeaders()buffer[i + 2];
parseData();
}
/**
* Parses the datarows of the diver file. Data is written as a timestamp, followed by a number of columns. Eachif (valueText == null) continue;
valueText = valueText.replace(',', '.');
* column refers to a channel that is declared in the Series settings contentHandler.setTimeSeriesHeader(i);
*
*/
private void parseData() throws Exception {
contentHandler.setValue('.', valueText);
int nrOfLines = Integer.parseInt(reader.readLine().trim()contentHandler.applyCurrentFields();
long lineCounter = 0;}
char columnSeparator = '\0' lineCounter++;
String[] buffer = new String[channelCount + 2];
}
if (log.isDebugEnabled())
for (String line; (line = readerlog.readLine()) != null;) {
if (columnSeparator == '\0') {
debug("Number of expected values: " + nrOfLines + " Found values: " + lineCounter);
}
/**
* Parses the available channels from the *.mon file. columnSeparatorMultiple = line.indexOf('\t') == -1 ? ' ' : '\t';channels can exist in a file. Typically the number
* of channels will be 2 }
but files with 1 channel do exist.
*/
private ifvoid (line.startsWith("END OF DATA")) break;parseHeaders() throws Exception {
IniFile iniFile = TextUtils.splitString(line, columnSeparator, bufferparseHeaderIniFile();
DiverHeaderConstants headerConstants = contentHandler.setTime(contentHandler.getDefaultTimeZone(), "yyyy/MM/dd", buffer[0], "HH:mm:ss", buffer[1]);
determineLanguage(iniFile);
String loc = for (int i = 0; i < channelCount; i++) {
iniFile.getValue(headerConstants.loggerSettings, headerConstants.location);
if (TextUtils.trimToNull(loc) == null) {
String valueTextthrow = buffer[i + 2]new Exception("No location found");
}
ifDefaultTimeSeriesHeader (valueTextheader == new nullDefaultTimeSeriesHeader() continue;
String[] subjects = iniFile.getSubjects();
valueTextchannelCount = valueText.replace(',', '.');0;
//loop over all subjects contentHandler.setTimeSeriesHeader(i);
of the form "Channel" + i + " from data header",
contentHandler.setValue('.', valueText);
//i.e. loop over the headers for all parameters.
for contentHandler.applyCurrentFields();
(int i = 1; ; i++) {
}
String subject = headerConstants.channel.toLowerCase() + ' ' lineCounter+ i +;
" from data header";
}
if (logStringArrayUtils.isDebugEnabledindexOfIgnoreCase(subjects, subject) == -1) {
if log.debug("Number of expected values: " + nrOfLines + " Found values: " + lineCounter);
(this.channelCount == 0) {
}
/**
throw new Exception("No *channel Parses the available channels from the *.mon file. Multiple channels can exist in a file. Typically the number
identification found");
}
* of channels will be 2 but files with 1 channel do exist.return;
*/
private void parseHeaders() throws}
Exception {
IniFile iniFile = parseHeaderIniFile();
DiverHeaderConstants headerConstants = determineLanguage(iniFile);
// subject is found, get id and range
String locid = iniFile.getValue(headerConstants.loggerSettingssubject, headerConstants.locationchnlId);
if (TextUtilsid.trimToNulllength(loc) == null0) {
throw new Exception("No location found");
}
DefaultTimeSeriesHeader header = new DefaultTimeSeriesHeader();
log.warn("Identification for channel: '" + subject + "' is not set in File: " + virtualFileName);
// String[] subjectsset = iniFile.getSubjects();
dummy parameter
channelCount = 0;
id = "Not Defined";
for (int i = 1; ; i++) {
}
String subject = headerConstantsheader.channel.toLowerCase() + ' ' + i + " from data header"setParameterId(id);
header.setLocationId(loc);
if (StringArrayUtils.indexOfIgnoreCase(subjectscontentHandler.createTimeSeriesHeaderAlias(channelCount, subjectheader) == -1) {
;
channelCount++;
}
}
private ifIniFile parseHeaderIniFile(this.channelCount == 0)) throws Exception {
List<String> headerLines = new ArrayList<String>();
for throw(String newline; Exception("No channel identification found");
line = reader.readLine()) != null;) {
if (line.trim().equalsIgnoreCase("[Data]")) {
}
BufferedReader reader = new BufferedReader(new returnStringReader(TextUtils.join(headerLines, '\n')));
}
return new IniFile(reader, virtualFileName);
// subject is found, get id and range}
String id = iniFile.getValue(subject, headerConstants.chnlIdheaderLines.add(line);
}
throw ifnew (id.length() == 0) {Exception("No data found");
}
private static DiverHeaderConstants log.warn("Identification for channel: '" + subject + "' is not set in File: " + virtualFileName);
//determineLanguage(IniFile iniFile) throws Exception {
String[] subjects = iniFile.getSubjects();
if (subjects.length > 0 && set dummy parameter
subjects[0].equalsIgnoreCase("Logger settings")) return DiverHeaderConstants.LOGGER_HEADER_CONSTANTS;
String subject2 = subjects.length < 2 ? "" : subjects[1];
id =if (subject2.equalsIgnoreCase("Notchannel Defined"1")) return DiverHeaderConstants.ENGLISH_HEADER_CONSTANTS;
if (subject2.equalsIgnoreCase("kanaal 1")) }
return DiverHeaderConstants.DUTCH_HEADER_CONSTANTS;
if header(subject2.setParameterId(id);
header.setLocationId(loc)equalsIgnoreCase("channel 1 from data header")) return DiverHeaderConstants.ENGLISH_HEADER_CONSTANTS;
if (subject2.equalsIgnoreCase("kanaal 1 contentHandler.createTimeSeriesHeaderAlias(channelCount,from data header);
channelCount++;")) return DiverHeaderConstants.DUTCH_HEADER_CONSTANTS;
}
}
if (subjects.length > 5) {
private IniFile parseHeaderIniFile() throws Exception {
if (subjects[4].equalsIgnoreCase("kanaal 1 from data List<String> headerLines = new ArrayList<String>()header")) return DiverHeaderConstants.MIXED_HEADER_CONSTANTS;
for (String line; (line = reader.readLine(if (subjects[4].equalsIgnoreCase("kanaal1 from data header")) != null;) {return DiverHeaderConstants.MIXED_HEADER_CONSTANTS;
if (line.trim()subjects[4].equalsIgnoreCase("[Data]")) {
"channel 1 from data header")) return DiverHeaderConstants.ENGLISH_MIXED_HEADER_CONSTANTS;
BufferedReader reader = newif BufferedReader(new StringReader(TextUtils.join(headerLines, '\n')))(subjects[4].equalsIgnoreCase("channel1 from data header")) return DiverHeaderConstants.ENGLISH_MIXED_HEADER_CONSTANTS;
}
return new IniFile(reader, virtualFileName);
if (subjects.length > 3) {
if }(subjects[2].equalsIgnoreCase("kanaal 1 from data header")) return DiverHeaderConstants.INCOMPLETE_HEADER_CONSTANTS;
}
headerLines.add(line);
// the file }
format is corrupt
throw new Exception("No data found");
}
private static DiverHeaderConstants determineLanguage(IniFile iniFile) throws Exception {
log.error("\n" + subjects.length + " strings read from the header : " + composeMessage(subjects) +
String[] subjects = iniFile.getSubjects();
if (subjects.length > 0 && subjects[0].equalsIgnoreCase("Logger settings")) return DiverHeaderConstants.LOGGER_HEADER_CONSTANTS;
String subject2 = subjects.length < 2 ? "" : subjects[1];
"\nexpected in string nr.2: 'channel 1' or 'kanaal 1' or 'channel 1 from data header' or 'kanaal 1 from data header' or" +
if (subject2.equalsIgnoreCase("channel 1")) return DiverHeaderConstants.ENGLISH_HEADER_CONSTANTS;
if (subject2.equalsIgnoreCase("kanaal 1")) return DiverHeaderConstants.DUTCH_HEADER_CONSTANTS;
"\nexpected in string nr.3: 'kanaal 1 from data header' or" +
if (subject2.equalsIgnoreCase("channel 1 from data header")) return DiverHeaderConstants.ENGLISH_HEADER_CONSTANTS;
if (subject2.equalsIgnoreCase("kanaal 1"\nexpected in string nr.5: 'kanaal 1 from data header' or 'kanaal1 from data header'")) return DiverHeaderConstants.DUTCH_HEADER_CONSTANTS;
throw ifnew Exception(subjects.length > 5) {
if (subjects[4].equalsIgnoreCase("kanaal 1 from data header")) return DiverHeaderConstants.MIXED_HEADER_CONSTANTS"File format not recognized as a valid diver (.mon) file, check the headers");
}
private static String if composeMessage(subjectsString[4].equalsIgnoreCase("kanaal1 from data header")) return DiverHeaderConstants.MIXED_HEADER_CONSTANTSNEW;
substr) {
StringBuffer buffer }= new StringBuffer();
iffor (subjectsint i = 0; i < substr.length > 3; i++) {
if (subjects[2].equalsIgnoreCase("kanaal 1 from data header")) return DiverHeaderConstants.INCOMPLETE_HEADER_CONSTANTSbuffer.append("'");
}
buffer.append(substr[i]);
// the file format is corrupt
buffer.append("' ");
throw new Exception("File format not recognized}
as a valid diver (.mon) file, check the headers"return buffer.toString();
}
}
|