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

Java tutorial

Introduction

Here is the source code for net.audumla.climate.bom.BOMClimateObserverCatalogue.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 au.com.bytecode.opencsv.CSVReader;
import net.audumla.climate.*;
import net.audumla.bean.SafeParse;
import org.apache.commons.lang.reflect.ConstructorUtils;
import org.apache.log4j.Logger;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class BOMClimateObserverCatalogue implements ClimateObserverFactory {

    protected static final Logger LOG = Logger.getLogger(BOMClimateObserverCatalogue.class);
    protected static String BOMLatLongLookup = "http://www.bom.gov.au/jsp/ncc/cdio/weatherData/av?";
    protected static Pattern stationLookupPattern = Pattern
            .compile("(?:(\\d{4})_)?([^ ]*)\\s*((?:\\w*\\s)*)(\\w*\\s).([\\d.]*)");
    // .compile("(\\d{4})_(\\d{5})\\s*((?:\\w*\\s)*)(\\w*\\s).([\\d.]*)");
    protected static String statisticKey = "200&";
    protected static String historyKey = "201&";
    protected static String BOMStationCatalogueFile = "IDY02126.dat";

    public BOMClimateObserverCatalogue() {

    }

    protected static String generationCoordinateURL(ClimateDataSource llsource, String key) {
        // http://www.bom.gov.au/jsp/ncc/cdio/weatherData/av?p_stn_num=86071&p_display_type=nearest10_tab2&p_nccObsCode=139&p_match=50,,37.70,145.0972,,LATLON,201&sid=0.7166697874199599
        // 3079_86068 Watsonia VIC (4.5km away)
        String p_stn_num = "p_stn_num=86071&";
        String p_display_type = "p_display_type=nearest10_tab2&";
        String p_nccObsCode = "p_nccObsCode=139&";
        String p_match = "p_match=50,," + (-1 * llsource.getLatitude()) + "," + llsource.getLongitude()
                + ",,LATLON," + key;
        String sid = String.valueOf(Math.random());
        String url = BOMLatLongLookup + p_stn_num + p_display_type + p_nccObsCode + p_match + sid;
        return url;

    }

    protected static boolean loadBOMStationInfo(BOMClimateDataSource source) {
        if (source.getBOMSampleID() == null || source.getBOMSampleID().length() == 0) {
            String[] entry = BOMClimateObserverCatalogue.getStationEntry(source.getId());
            if (entry != null) {
                if (entry.length > 6) {
                    source.setBOMSampleID(entry[6].trim());
                }
                if (entry.length > 1) {
                    source.setName(entry[1].trim());
                }
                if (entry.length > 4) {
                    source.setLatitude(SafeParse.parseDouble(entry[3].trim()));
                    source.setLongitude(SafeParse.parseDouble(entry[4].trim()));
                }
                LOG.debug("Loaded BOM Station info [" + source.toString() + "]");

                return true;
            }
            return false;
        } else {
            return true;
        }
    }

    protected static List<BOMClimateDataSource> parseSources(ClimateDataSource source, int maxResults,
            String results) {
        List<BOMClimateDataSource> stationSources = new ArrayList<BOMClimateDataSource>();
        // g1 = ?, g2 = station id, g3 = Station Name, g4 = State, g5 = distance from location
        String[] rrss = results.split("\\|\\|");
        for (String result : rrss) {
            Matcher m = stationLookupPattern.matcher(result.trim());
            if (m.find()) {
                BOMClimateDataSource bomSource = ClimateDataSourceFactory.newInstance(BOMClimateDataSource.class);
                bomSource.setId(m.group(2));
                for (int i = 0; i < 6 - m.group(2).length(); ++i) {
                    bomSource.setId("0" + bomSource.getId());
                }
                bomSource.setName(m.group(3));
                if (!stationSources.contains(bomSource)) {
                    if (loadBOMStationInfo(bomSource)) {
                        stationSources.add(bomSource);
                        if (stationSources.size() == maxResults) {
                            break;
                        }
                    }
                }
            }
        }

        List<BOMClimateDataSource> decoratedStationSources = new ArrayList<BOMClimateDataSource>();
        for (BOMClimateDataSource ss : stationSources) {
            decoratedStationSources.add(ClimateDataSourceFactory.decorateInstance(source, ss));
        }
        return decoratedStationSources;
    }

    protected static ClimateObserver getClimateObserverByCoordinates(ClimateDataSource coordinateSource) {

        ClimateObserverCollection aggregateObserver = new ClimateObserverCollectionHandler(coordinateSource);
        try {
            String url = generationCoordinateURL(coordinateSource, historyKey);
            List<BOMClimateDataSource> stationSources = new ArrayList<BOMClimateDataSource>();
            InputStream is = new URL(url).openStream();
            InputStreamReader sr = new InputStreamReader(is);
            char[] buffer = new char[10240];
            int c = 0;
            if ((c = sr.read(buffer, 0, 10240)) > 0) {
                stationSources = parseSources(coordinateSource, 5, new String(buffer, 0, c));
            }

            for (BOMClimateDataSource source : stationSources) {
                aggregateObserver
                        .addClimateObserverTail(getClimateObserverById(BOMPeriodicClimateObserver.class, source));
            }
            for (BOMClimateDataSource source : stationSources) {
                aggregateObserver
                        .addClimateObserverTail(getClimateObserverById(BOMHistoricalClimateObserver.class, source));
            }
            for (BOMClimateDataSource source : stationSources) {
                aggregateObserver.addClimateObserverTail(
                        getClimateObserverById(BOMSimpleHistoricalClimateObserver.class, source));
            }
            for (BOMClimateDataSource source : stationSources) {
                aggregateObserver.addClimateObserverTail(
                        getClimateObserverById(BOMSimpleClimateForcastObserver.class, source));
            }

            url = generationCoordinateURL(coordinateSource, statisticKey);
            stationSources = new ArrayList<BOMClimateDataSource>();
            is = new URL(url).openStream();
            sr = new InputStreamReader(is);
            buffer = new char[10240];
            c = 0;
            if ((c = sr.read(buffer, 0, 10240)) > 0) {
                stationSources = parseSources(coordinateSource, 5, new String(buffer, 0, c));
            }

            for (BOMClimateDataSource source : stationSources) {
                aggregateObserver.addClimateObserverTail(
                        getClimateObserverById(BOMStatisticalClimateDataObserver.class, source));
            }
            return aggregateObserver.buildClimateObserver();

        } catch (Exception e) {
            throw new UnsupportedOperationException(e);
        }
    }

    protected static ClimateObserver getClimateObserverById(Class<?> clazz, ClimateDataSource source)
            throws Exception {
        ClimateDataSource name = ClimateDataSourceFactory.getInstance().newInstance();
        name.setId(source.getId() + ":" + clazz.getName());
        ClimateObserver station = ClimateObserverCatalogue.getInstance().getRegisteredClimateObserver(name);
        if (station == null) {
            // delegated to allow ClimateObservers to not be compiled into factory
            BOMClimateDataSource bomSource = ClimateDataSourceFactory.decorateInstance(source,
                    BOMClimateDataSource.class);
            loadBOMStationInfo(bomSource);
            station = (ClimateObserver) ConstructorUtils.invokeConstructor(clazz, bomSource);
            ClimateObserverCatalogue.getInstance().registerClimateObserver(name, station);
        }
        return station;
    }

    protected static ClimateObserver getClimateObserverById(ClimateDataSource source) throws Exception {
        ClimateObserverCollection bomstation = new ClimateObserverCollectionHandler(source);
        bomstation.addClimateObserverTail(getClimateObserverById(BOMPeriodicClimateObserver.class, source));
        bomstation.addClimateObserverTail(getClimateObserverById(BOMHistoricalClimateObserver.class, source));
        bomstation.addClimateObserverTail(getClimateObserverById(BOMSimpleHistoricalClimateObserver.class, source));
        bomstation.addClimateObserverTail(getClimateObserverById(BOMSimpleClimateForcastObserver.class, source));
        bomstation.addClimateObserverTail(getClimateObserverById(BOMStatisticalClimateDataObserver.class, source));
        return bomstation.buildClimateObserver();
    }

    protected static String generateStationCatalogueURL() {
        return BOMDataLoader.BOMBaseFTPDir + BOMDataLoader.FWO + BOMStationCatalogueFile;
    }

    protected static String[] getStationEntry(String id) {
        try {
            CSVReader csv = new CSVReader(BOMDataLoader.instance().getData(BOMDataLoader.FTP, BOMDataLoader.BOMFTP,
                    generateStationCatalogueURL()));
            String[] line;
            /* "014305","KATHERINE COUNT","AAAA",-14.4728,132.2612, 106,"94132","NT " */
            while ((line = csv.readNext()) != null) {
                if (id.equals(line[0].replace("\"", ""))) {
                    return line;
                }
            }
        } catch (IOException e) {
            LOG.error("Station Catalogue error", e);
        } catch (UnsupportedOperationException ignored) {
        }
        return null;
    }

    public boolean validateBOMConnection(ClimateDataSource llsource) throws Exception {
        InputStream is = new URL(generationCoordinateURL(llsource, statisticKey)).openStream();
        is.close();
        BOMDataLoader.instance().getData(BOMDataLoader.FTP, BOMDataLoader.BOMFTP, generateStationCatalogueURL());
        return true;
    }

    @Override
    public synchronized ClimateObserver getClimateObserver(ClimateDataSource source) {
        ClimateObserver station = null;// ClimateObserverCatalogue.getInstance().buildClimateObserver(source);
        try {
            if (station == null) {
                if (source.getId() != null && source.getId().length() > 0) {
                    station = getClimateObserverById(source);
                } else {
                    if (source.getLatitude() != 0 && source.getLongitude() != 0) {
                        station = getClimateObserverByCoordinates(source);
                    }
                }
            }
        } catch (UnsupportedOperationException e) {
            throw e;
        } catch (Exception e) {
            throw new UnsupportedOperationException(e);
        }
        return station;
    }

}