package nl.wldelft.timeseriesparsers; import nl.wldelft.lib.sipconnect.SslSipClient; import nl.wldelft.lib.sipconnect.SslSipUtils; import nl.wldelft.lib.sipconnect.SslSipWrapper; import nl.wldelft.util.DateUtils; import nl.wldelft.util.FastDateFormat; import nl.wldelft.util.Period; import nl.wldelft.util.PeriodConsumer; import nl.wldelft.util.TextUtils; import nl.wldelft.util.TimeUnit; import nl.wldelft.util.io.ServerParser; import nl.wldelft.util.timeseries.TimeSeriesContentHandler; import nl.wldelft.util.timeseries.TimeSeriesHeader; import nl.wldelft.util.timeseries.TimeSeriesHeadersConsumer; import org.apache.log4j.Logger; import java.net.URL; import java.sql.Date; import java.util.Locale; public class LmwTimeSeriesServerParser implements ServerParser, TimeSeriesHeadersConsumer, PeriodConsumer { private static final Logger log = Logger.getLogger(LmwTimeSeriesServerParser.class); private FastDateFormat dateFormat = null; private TimeSeriesHeader[] headers = null; private Period period = Period.ANY_TIME; private TimeSeriesContentHandler contentHandler = null; @SuppressWarnings({"AssignmentToCollectionOrArrayFieldFromParameter"}) @Override public void setTimeSeriesHeaders(TimeSeriesHeader[] timeSeriesHeaders) { this.headers = timeSeriesHeaders; } @Override public void setPeriod(Period period) { this.period = period; } public void parse(URL url, String username, String password, TimeSeriesContentHandler contentHandler) throws Exception { if (period == Period.ANY_TIME) { throw new IllegalStateException("period should be specified"); } if (contentHandler.getDefaultTimeZone().useDaylightTime()) throw new UnsupportedOperationException("Day light saving time zone not supported by LMW " + contentHandler.getDefaultTimeZone()); this.contentHandler = contentHandler; SslSipClient client = SslSipUtils.openConnection(SslSipWrapper.INSTANCE, url, username, password); try { dateFormat = FastDateFormat.getInstance("dd-MM-yyyy", contentHandler.getDefaultTimeZone(), Locale.getDefault(), dateFormat); for (int i = 0; i < headers.length; i++) { TimeSeriesHeader header = headers[i]; contentHandler.setNewTimeSeriesHeader(header); String locationId = header.getLocationId(); String parameterId = header.getParameterId(); if (header.getQualifierCount() > 2) { if (log.isInfoEnabled()) log.info("Only two qualifiers will be used - location/parameter: " + locationId + '/' + parameterId); } String command = header.getQualifierCount() < 1 ? "WN" : header.getQualifierId(0); // "waarneming by default" String databaseId = header.getQualifierCount() < 2 ? "LMW" : header.getQualifierId(1); // "LMW" by default since 1 july 2010; String querySuffix = TextUtils.equals(command, "AS") ? "" : ",DATA"; for (long time = period.getStartTime() - TimeUnit.DAY_MILLIS; time < period.getEndTime(); time += TimeUnit.DAY_MILLIS) { String dateString = dateFormat.format(time); String sipCommandLine = command + ' ' + databaseId + ',' + locationId + ',' + parameterId + ",+23:51," + dateString + ",23:50" + querySuffix + '\r'; String resultString = client.sendCommand(sipCommandLine); if (resultString.startsWith("?")) { log.error("Error/warning: " + resultString + " while retrieving data for " + locationId + '/' + parameterId + " - date: " + new Date(time)); continue; } long startOfDay = DateUtils.floorTime(time, -contentHandler.getDefaultTimeZone().getRawOffset(), TimeUnit.DAY_MILLIS); parse(resultString, startOfDay); } } } finally { SslSipUtils.closeConnection(client); } } private void parse(String resultString, long time) { String[] items = TextUtils.split(resultString.substring(2), ';'); long timeStep; if (items.length == 144) { timeStep = 10 * TimeUnit.MINUTE_MILLIS; } else if (items.length == 24) { timeStep = TimeUnit.HOUR_MILLIS; } else { timeStep = TimeUnit.DAY_MILLIS / items.length; } time += TimeUnit.DAY_MILLIS - timeStep; // TODO: check that this is correct with hours too String[] buffer = new String[4]; for (int i = 0; i < items.length; i++) { int count = TextUtils.split(items[i], '/', buffer); // If the array is two long, then there is a value and a flag. // Otherwise consider the value to be missing if (count == 2) { contentHandler.setValue('.', buffer[0]); contentHandler.setFlag(buffer[1]); contentHandler.setTime(time); contentHandler.applyCurrentFields(); } time += timeStep; } } }