net.audumla.climate.bom.BOMHistoricalClimateObserver.java Source code

Java tutorial

Introduction

Here is the source code for net.audumla.climate.bom.BOMHistoricalClimateObserver.java

Source

package net.audumla.climate.bom;

/*
 * *********************************************************************
 *  ORGANIZATION : audumla.net
 *  More information about this project can be found at the following locations:
 *  http://www.audumla.net/
 *  http://audumla.googlecode.com/
 * *********************************************************************
 *  Copyright (C) 2012 - 2013 Audumla.net
 *  Licensed under the Creative Commons Attribution-NonCommercial-NoDerivs 3.0 Unported License.
 *  You may not use this file except in compliance with the License located at http://creativecommons.org/licenses/by-nc-nd/3.0/
 *
 *  Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an
 *  "AS I BASIS", WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and limitations under the License.
 */

import net.audumla.bean.SupportedFunction;
import net.audumla.climate.*;
import net.audumla.bean.SafeParse;
import net.audumla.Time;
import org.apache.commons.lang.time.DateUtils;
import org.apache.log4j.Logger;

import java.io.BufferedReader;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class BOMHistoricalClimateObserver implements ClimateDataFactory, ClimateObserver {
    private static final Logger logger = Logger.getLogger(BOMHistoricalClimateObserver.class);
    private static final String indexFile = "stations_db.txt";
    private static final String productID = "IDCKWCDEA0";
    private static final String subDir = BOMDataLoader.CLIMATE + productID + "/tables/";
    private static final Pattern indexPattern = Pattern
            .compile("(.{6})\\s*(.{3})\\s*(.{4})\\s*((?:\\D*[' '])*)\\s*(.{12})\\s*(.{8})\\s*(.{8})");
    private static final SimpleDateFormat yearMonth = new SimpleDateFormat("yyyyMM");// 201301
    private static final SimpleDateFormat yearMonthDay = new SimpleDateFormat("dd/MM/yyyy");// 12/01/2013
    private static final int MAX_ENTRIES = 100;
    private Set<Date> invalidMonths = new LinkedHashSet<Date>();
    //    boolean active = true;
    private ClimateDataSource source;
    private String lastLoadedFile = null;
    private LinkedHashMap<Date, ClimateData> historicalData;
    // private String stationDataFilename = null;
    private String stationDataSubDir = null;
    private String stationName = null;

    @SuppressWarnings("serial")
    public BOMHistoricalClimateObserver(ClimateDataSource source) {
        this.source = source;
        this.source.setType(ClimateDataSource.ClimateDataSourceType.DAILY_OBSERVATION);
        historicalData = new LinkedHashMap<Date, ClimateData>(MAX_ENTRIES + 1, .75F, true) {
            // This method is called just after a new entry has been added
            public boolean removeEldestEntry(Map.Entry<Date, ClimateData> eldest) {
                return size() > MAX_ENTRIES;
            }
        };
    }

    protected boolean loadStationDataFile(String stationSubDir, String fileName, String stationName) {
        try {
            String fn = stationSubDir + fileName;
            if (!fn.equals(lastLoadedFile)) {
                BufferedReader br = BOMDataLoader.instance().getData(BOMDataLoader.FTP, BOMDataLoader.BOMFTP,
                        BOMDataLoader.BOMBaseFTPDir + fn);
                String line;
                while ((line = br.readLine()) != null) {
                    try {
                        String[] data = line.split(",");
                        if (data[0].toLowerCase().equals(stationName)) {
                            // Station Name,JulianDate,EvapoTranspiration,Rain,Pan Evaporation,Maximum Temp,Minimum Temp,Max
                            // Relative Hum,Min Relative Hum,Avg 10m Wind Sp,Solar Radiation
                            // VIEWBANK,12/01/2013,4.5,0.0, ,25.2,15.7,77,43,3.53,16.10
                            Date date = yearMonthDay.parse(data[1].trim());
                            Date dateM1 = DateUtils.addDays(date, -1);
                            WritableClimateData cdNow = ClimateDataFactory
                                    .convertToWritableClimateData(historicalData.get(date));
                            if (cdNow == null) {
                                cdNow = ClimateDataFactory.newWritableClimateData(this, getSource()); // now
                                cdNow.setTime(date);
                                historicalData.put(date, ClimateDataFactory.convertToReadOnlyClimateData(cdNow));
                            }
                            WritableClimateData cdNowM1 = ClimateDataFactory
                                    .convertToWritableClimateData(historicalData.get(dateM1));
                            if (cdNowM1 == null) {
                                cdNowM1 = ClimateDataFactory.newWritableClimateData(this, getSource()); // now
                                cdNowM1.setTime(dateM1);
                                historicalData.put(dateM1,
                                        ClimateDataFactory.convertToReadOnlyClimateData(cdNowM1));
                            }

                            try {
                                cdNow.setEvapotranspiration(SafeParse.parseDouble(data[2].trim()));
                            } catch (Exception ignored) {
                            }
                            try {
                                Double rain = SafeParse.parseDouble(data[3]);
                                if (rain != null) {
                                    cdNowM1.setRainfall(rain);
                                    cdNowM1.setRainfallProbability(cdNowM1.getRainfall() > 0 ? 100d : 0d);
                                }
                            } catch (Exception ignored) {
                            }
                            try {
                                cdNow.setEvaporation(SafeParse.parseDouble(data[4].trim()));
                            } catch (Exception ignored) {
                            }
                            try {
                                cdNow.setMaximumTemperature(SafeParse.parseDouble(data[5].trim()));
                            } catch (Exception ignored) {
                            }
                            try {
                                cdNow.setMinimumTemperature(SafeParse.parseDouble(data[6].trim()));
                            } catch (Exception ignored) {
                            }
                            try {
                                cdNow.setMaximumHumidity(SafeParse.parseDouble(data[7].trim()));
                            } catch (Exception ignored) {
                            }
                            try {
                                cdNow.setMinimumHumidity(SafeParse.parseDouble(data[8].trim()));
                            } catch (Exception ignored) {
                            }
                            try {
                                cdNow.setAverageWindSpeed(SafeParse.parseDouble(data[9].trim()));
                                cdNow.setWindSpeedHeight(10.0);
                            } catch (Exception ignored) {
                            }
                            try {
                                cdNow.setSolarRadiation(SafeParse.parseDouble(data[10].trim()));
                            } catch (Exception ignored) {
                            }

                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
                lastLoadedFile = fn;
            }

        } catch (UnsupportedOperationException ex) {
            // cannot load the csv file.
            return false;
        } catch (Exception ex) {
            logger.error(ex);
        }
        return true;
    }

    protected boolean loadStationData(String stationid, Date date) {
        String stationDataFilename = null;
        if (stationName == null || stationDataSubDir == null) {
            // ftp://ftp2.bom.gov.au/anon/gen/clim_data/IDCKWCDEA0/tables/
            try {
                BufferedReader br = BOMDataLoader.instance().getData(BOMDataLoader.FTP, BOMDataLoader.BOMFTP,
                        BOMDataLoader.BOMBaseFTPDir + subDir + indexFile);
                while (stationName == null) {
                    String line = br.readLine();
                    if (line != null) {
                        Matcher m = indexPattern.matcher(line);
                        if (m.find()) {
                            String id = m.group(1).trim();
                            if (stationid.equals(id)) {
                                String state = m.group(2).trim().toLowerCase();
                                stationName = m.group(4).trim().toLowerCase().replace("aws", "").trim();
                                stationDataSubDir = (subDir + state + "/" + stationName + "/").replace(' ', '_');
                            }
                        }
                    } else {
                        break;
                    }
                }

            } catch (Exception ex) {
                ex.printStackTrace();
            }
        }

        if (stationDataSubDir != null && stationName != null) {
            stationDataFilename = (stationName + "-" + yearMonth.format(date) + ".csv").replace(' ', '_');
            return loadStationDataFile(stationDataSubDir, stationDataFilename, stationName);
        } else {
            //            logger.warn("Cannot locate historical data " + yearMonthDay.format(date) + " for station - " + stationid);
            return false;
        }
    }

    synchronized public ClimateData getClimateData(Date date) {
        if (!invalidMonths.contains(Time.getMonthAndYear(date))) {
            if (!date.before(Time.getToday())) {
                throw new UnsupportedOperationException("JulianDate requested is in the future");
            }
            try {
                if (date.after(source.getLastRecord())) {
                    throw new UnsupportedOperationException("JulianDate requested is after the last record");
                }
            } catch (Exception ignored) {

            }
            ClimateData data = null;
            try {
                Date dayDate = yearMonthDay.parse(yearMonthDay.format(date));
                data = historicalData.get(dayDate);
                if (data == null) {
                    if (loadStationData(source.getId(), date)) {
                        data = historicalData.get(dayDate);
                    }
                }
            } catch (ParseException ignored) {
            }
            if (data != null) {
                return data;
            }
        }
        invalidMonths.add(Time.getMonthAndYear(date));
        throw new UnsupportedOperationException("Cannot locate historical data " + yearMonthDay.format(date)
                + " for for station - " + source.getId());
    }

    public Class<? extends ClimateData> getClimateDataClass() {
        return BOMHistoricalClimateData.class;
    }

    public Class<? extends ClimateObservation> getClimateObservationClass() {
        return null;
    }

    public ClimateDataSource getSource() {
        return source;
    }

    public boolean supportsDate(Date date) {
        return !invalidMonths.contains(Time.getMonthAndYear(date)) && date.before(Time.getToday());
    }

    private static interface BOMHistoricalClimateData extends ClimateData {
        @SupportedFunction(supported = true)
        double getMinimumTemperature();

        @SupportedFunction(supported = true)
        double getMaximumTemperature();

        @SupportedFunction(supported = true)
        double getRainfall();

        @SupportedFunction(supported = true)
        double getRainfallProbability();

        @SupportedFunction(supported = true)
        double getSunshineHours();

        @SupportedFunction(supported = true)
        double getEvaporation();

        @SupportedFunction(supported = true)
        double getEvapotranspiration();

        @SupportedFunction(supported = true)
        double getMaximumHumidity();

        @SupportedFunction(supported = true)
        double getMinimumHumidity();

        @SupportedFunction(supported = true)
        double getMaximumSaturationVapourPressure(); //kPA

        @SupportedFunction(supported = true)
        double getMinimumSaturationVapourPressure(); //kPA

        @SupportedFunction(supported = true)
        double getMaximumVapourPressure();

        @SupportedFunction(supported = true)
        double getMinimumVapourPressure();

        @SupportedFunction(supported = true)
        double getAverageWindSpeed();

        @SupportedFunction(supported = true)
        double getSolarRadiation();

        @SupportedFunction(supported = true)
        Date getTime();

        @SupportedFunction(supported = true)
        double getWindSpeedHeight();

        @SupportedFunction(supported = true)
        ClimateDataSource getDataSource();

        @SupportedFunction(supported = true)
        double getAtmosphericPressure();

        @SupportedFunction(supported = true)
        double getDaylightHours();

    }
}