WaterLocations_USGS.java [src/WaterLocations] Revision: default  Date:
package WaterLocations;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;

/**
 * Last Updated: 27-June-2019
 * @author robert, Rumpal Sidhu, Tyler Wible
 * @since April-2017
 */
public class WaterLocations_USGS implements WaterLocationsInterface {
    String database = "USGS";
    
    @Override
    public ArrayList<String> downloadStations(String minLat, String maxLat, String minLong, String maxLong, boolean keepHistoricTF) throws WaterLocationsException {
        //Specify station search url from inputs
        //String stationUrl = "https://waterdata.usgs.gov/nwis/inventory?nw_longitude_va=-105.016200050561&nw_latitude_va=40.6972465847942&se_longitude_va=-105.204340919673&se_latitude_va=40.4500296208208&coordinate_format=decimal_degrees&group_key=NONE&format=sitefile_output&sitefile_output_format=rdb&column_name=agency_cd&column_name=site_no&column_name=station_nm&column_name=site_tp_cd&column_name=dec_lat_va&column_name=dec_long_va&column_name=dec_coord_datum_cd&column_name=state_cd&column_name=county_cd&column_name=country_cd&column_name=alt_va&column_name=alt_datum_cd&column_name=huc_cd&column_name=drain_area_va&column_name=rt_bol&column_name=peak_begin_date&column_name=peak_end_date&column_name=peak_count_nu&column_name=qw_begin_date&column_name=qw_end_date&column_name=qw_count_nu&list_of_search_criteria=lat_long_bounding_box";
        String stationUrl = "https://waterdata.usgs.gov/nwis/inventory?" +
                "nw_longitude_va=" + maxLong +
                "&nw_latitude_va=" + maxLat +
                "&se_longitude_va=" + minLong +
                "&se_latitude_va=" + minLat + 
                "&coordinate_format=decimal_degrees&group_key=NONE&format=sitefile_output&sitefile_output_format=rdb&column_name=agency_cd&column_name=site_no&column_name=station_nm&column_name=site_tp_cd&column_name=dec_lat_va&column_name=dec_long_va&column_name=dec_coord_datum_cd&column_name=state_cd&column_name=county_cd&column_name=country_cd&column_name=alt_va&column_name=alt_datum_cd&column_name=huc_cd&column_name=drain_area_va&column_name=rt_bol&column_name=peak_begin_date&column_name=peak_end_date&column_name=peak_count_nu&column_name=qw_begin_date&column_name=qw_end_date&column_name=qw_count_nu&list_of_search_criteria=lat_long_bounding_box";
        //NOTE: The product of the ranges of lat & lon cannot exceed 25°
        
        ArrayList<String> pageData = new ArrayList<>();
        try {
            //Open the provided website
            URL webpage = new URL(stationUrl);
            URLConnection yc = webpage.openConnection();
            BufferedReader in = new BufferedReader(new InputStreamReader(yc.getInputStream()));
            //Read out all of the webpage out into an ArrayList<String>
            String inputLine;

            while ((inputLine = in.readLine()) != null) {
                pageData.add(inputLine);
            }

            in.close();
        } catch (IOException ex) {
            throw new WaterLocationsException("The was an issue extracting " + database + " station locations from the specified URl: " + stationUrl + ". " + ex.getMessage());
        }

        return pageData;
    }

    @Override
    public ArrayList<Station> getStations(String minLat, String maxLat, String minLong, String maxLong, boolean keepHistoricTF) throws WaterLocationsException {
        //Fetch monitoring stations web page for current bounding box
        ArrayList<String> webpageAll = downloadStations(minLat, maxLat, minLong, maxLong, keepHistoricTF);
        
        ArrayList<Station> stations = new ArrayList();
        for(int i=0; i<webpageAll.size(); i++){
            String[] columns = webpageAll.get(i).split("\t");
            if (columns.length >= 23 && "USGS".equals(columns[0])) {
                //Keep out only the desired data
                //columns[0] = database
                //columns[1] = Station ID
                //columns[2] = Station Name
                //columns[3] = Station Type (LK, ST)
                //columns[4] = Latitude
                //columns[5] = Longitude
                //columns[7] = Horizontal Datum
                //columns[8] = state code
                //columns[9] = county code
                //columns[10] = country code
                //columns[11] = Elevation
                //columns[13] = Elevation datum
                //columns[14] = hydrologic unit code (HUC)
                //columns[11] = Drainage Area
                //columns[] = Drainage Area Units
                //columns[16] = real time data flag (instantaneous)
                //columns[17] = peak begin date
                //columns[18] = peak end date
                //columns[19] = peak count
                //columns[20] = water quality begin date
                //columns[21] = water quality end date
                //columns[22] = water quality count
                Station currentStation = new Station(database + "-" + columns[1]);
                currentStation.SetOrgName(columns[0]);
                currentStation.SetStationId(columns[1]);
                currentStation.SetStationName(columns[2]);
                currentStation.SetStationType(columns[3]);
                currentStation.SetLatitude(columns[4]);
                currentStation.SetLongitude(columns[5]);
                currentStation.SetHorizontalDatum(columns[7]);
                currentStation.SetElevation(columns[11]);
                currentStation.SetElevationDatum(columns[13]);
                currentStation.SetHUC(columns[14]);
                currentStation.SetDrainageArea(columns[11]);
                currentStation.SetPeakStartDate(columns[17]);
                currentStation.SetPeakEndDate(columns[18]);
                currentStation.SetPeakCount(columns[19]);
                currentStation.SetWaterQualityStartDate(columns[20]);
                currentStation.SetWaterQualityEndDate(columns[21]);
                currentStation.SetWaterQualityCount(columns[22]);
                boolean realTimeDataFlag = false;
                if(!columns[16].isEmpty() && !columns[16].equalsIgnoreCase("0")){
                    realTimeDataFlag = true;
                }
                currentStation.SetRealTimeDataFlag(realTimeDataFlag);

                if(realTimeDataFlag){
                    //Keep active stations
                    stations.add(currentStation);
                }else if(keepHistoricTF){
                    //Keep historic sites if requested
                    stations.add(currentStation);
                }
                
            }
        }
        return stations;
    }
}