WaterData_CDWR.java [src/WaterData] Revision: default  Date:
package WaterData;

import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import utils.WebPageUtils;

/**
 * Last Updated: 9-April-2019
 * @author Tyler Wible
 * @since 7-July-2014
 * For more information on all of CDWR's CDSS data services, go to:
 * http://dnrweb.state.co.us/dwr/dwrapiservice/help#TechInfoHelp&#All&#gettingstarted&#jsonxml
 */
public class WaterData_CDWR implements WaterDataInterface{
    public String database = "CDWR";
    
    @Override
    public String getDataSourceCitation(){
        //Get today's date for the source reference
        DateFormat sourceDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm");
        String today = sourceDateFormat.format(new Date());
        
        //Cite CDWR CDSS web services
        String dataSource = "Stream flow data retrieved from the Colorado Division of Water Resources, CDWR. http://dnrweb.state.co.us/dwr/dwrapiservice/help#TechInfoHelp&#All&#gettingstarted&#jsonxml accessed: " + today;
        return dataSource;
    }

    @Override
    public ArrayList<String> extractFlowData_raw(String directory, String orgId, String stationId, String startDate, String endDate) throws WaterDataException {
        //Specify flow website from inputs
        //https://dwr.state.co.us/rest/GET/api/v2/telemetrystations/telemetrytimeseriesday/?format=csv&abbrev=AMYCANCO&endDate=10%2F02%2F2018&parameter=DISCHRG&startDate=05%2F16%2F2018
        String flowUrl = "https://dwr.state.co.us/rest/GET/api/v2/telemetrystations/telemetrytimeseriesday/?format=csv" +
                "&abbrev=" + stationId + "&parameter=DISCHRG";
        if(!startDate.isEmpty()){
            startDate = cdssInputDateFormat(startDate);
            flowUrl += "&startDate=" + startDate;
        }
        if(!endDate.isEmpty()){
            endDate = cdssInputDateFormat(endDate);
            flowUrl += "&endDate=" + endDate;
        }
        
        //Fetch the flow data webpage for the current CDSS station
        ArrayList<String> webpageAll = new ArrayList<>();
        try {
            webpageAll = WebPageUtils.downloadWebpage(flowUrl);
        } catch (IOException ex) {
            throw new WaterDataException("The was an issue extracting " + database + " flow data from the specified URl: " + flowUrl + ". " + ex.getMessage());
        }
        return webpageAll;
    }
    
    @Override
    public String[][] extractFlowData_formatted(String directory, String orgId, String stationId, String startDate, String endDate) throws WaterDataException{
        //Fetch flow data
        ArrayList<String> stationData = extractFlowData_raw(directory, orgId, stationId, startDate, endDate);
        
        //Check for negative flow values and remove them
        int ctr = 0;
        for(int i=3; i<stationData.size(); i++){//3 rows are header information
            String[] currentRow = stationData.get(i).split(",");
            if(Double.parseDouble(currentRow[3]) >= 0){
                ctr++;
            }
        }
        
        //Reformat data
        String[][] returnArray = new String[ctr][2];//3 rows are header information
        ctr = 0;
        for(int i=3; i<stationData.size(); i++){
            String[] currentRow = stationData.get(i).split(",");
            //Pull out only the data needed to pass between sub-functions
            if(Double.parseDouble(currentRow[3]) >= 0){
                returnArray[ctr][0] = cdssOutputDateFormat(currentRow[2], false);//date
                returnArray[ctr][1] = currentRow[3];//value
                ctr++;
            }
            
        }
        return returnArray;
    }

    @Override
    public ArrayList<String> extractWaterQualityData_raw(String directory, String orgId, String stationId, String startDate, String endDate, String wqTest) throws WaterDataException {
        throw new WaterDataException("The " + database + " database contains no water quality data.");
    }
    
    @Override
    public String[][] extractWaterQualityData_formatted(String directory, String orgId, String stationId, String startDate, String endDate, String wqTest) throws WaterDataException {
        throw new WaterDataException("The " + database + " database contains no water quality data.");
    }

    @Override
    public ArrayList<String> extractFloodData_raw(String directory, String orgId, String stationId, String startDate, String endDate) throws WaterDataException {
        throw new WaterDataException("The " + database + " database contains no flood discharge data.");
    }
    
    @Override
    public double[][] extractFloodData_formatted(String directory, String orgId, String stationId, String startDate, String endDate) throws WaterDataException {
        throw new WaterDataException("The " + database + " database contains no flood discharge data.");
    }

    @Override
    public ArrayList<String> extractInstantaneousFlowData_raw(String directory, String stationId, String startDate, String endDate) throws WaterDataException{
        //Specify flow website from inputs
        //https://dwr.state.co.us/rest/GET/api/v2/telemetrystations/telemetrytimeseriesraw/?format=csv&abbrev=AMYCANCO&endDate=09%2F27%2F2018&parameter=DISCHRG&startDate=09%2F24%2F2018
        String flowUrl = "https://dwr.state.co.us/rest/GET/api/v2/telemetrystations/telemetrytimeseriesraw/?format=csv" +
                "&abbrev=" + stationId + "&parameter=DISCHRG";
        if(!startDate.isEmpty()){
            startDate = cdssInputDateTimeFormat(startDate);
            flowUrl += "&startDate=" + startDate;//09%2F24%2F2018_14%3A15
        }
        if(!endDate.isEmpty()){
            endDate = cdssInputDateTimeFormat(endDate);
            flowUrl += "&endDate=" + endDate;//09%2F27%2F2018_04%3A00
        }
        
        //Fetch the flow data webpage for the current CDSS station
        ArrayList<String> webpageAll = new ArrayList<>();
        try {
            webpageAll = WebPageUtils.downloadWebpage(flowUrl);
        } catch (IOException ex) {
            throw new WaterDataException("The was an issue extracting " + database + " flow data from the specified URl: " + flowUrl + ". " + ex.getMessage());
        }
        return webpageAll;
    }
    
    @Override
    public String[][] extractInstantaneousFlowData_formatted(String directory, String stationId, String startDate, String endDate) throws WaterDataException{
        ArrayList<String> stationData = extractInstantaneousFlowData_raw(directory, stationId, startDate, endDate);
        
        //Reformat data
        String[][] returnArray = new String[stationData.size()-3][2];
        for(int i=3; i<stationData.size(); i++){
            String[] currentStationData = stationData.get(i).split(",");
            //Pull out only the data needed to pass between sub-functions
            returnArray[i-3][0] = cdssOutputDateFormat(currentStationData[2], true);//date
            returnArray[i-3][1] = currentStationData[3];//value
        }
        return returnArray;
    }
    
    @Override
    public ArrayList<String> extractStageDischarge_raw(String stationId) throws WaterDataException{
        //Specify shift adjusted rating table website from inputs
        //https://dwr.state.co.us/rest/GET/api/v2/telemetrystations/telemetryshiftadjustedratingtable/?abbrev=AMYCANCO&parameter=DISCHRG
        String flowUrl = "https://dwr.state.co.us/rest/GET/api/v2/telemetrystations/telemetryshiftadjustedratingtable/?format=csv" +
                "&abbrev=" + stationId + "&parameter=DISCHRG";
        
        //Fetch the stage discharge data webpage for the current CDSS station
        ArrayList<String> webpageAll = new ArrayList<>();
        try {
            webpageAll = WebPageUtils.downloadWebpage(flowUrl);
        } catch (IOException ex) {
            throw new WaterDataException("The was an issue extracting " + database + " stage discharge data from the specified URl: " + flowUrl + ". " + ex.getMessage());
        }
        return webpageAll;
    }

    @Override
    public double[][] extractStageDischarge_formatted(String stationId) throws WaterDataException {
        //Fetch rating curve data
        ArrayList<String> stationData = extractStageDischarge_raw(stationId);
        
        //Reformat data
        double[][] resultArray = new double[stationData.size()-3][2];
        for(int i=3; i<stationData.size(); i++){
            String[] currentStationData = stationData.get(i).split(",");
            resultArray[i-3][0] = Double.parseDouble(currentStationData[2]);//discharge
            resultArray[i-3][1] = Double.parseDouble(currentStationData[1]);//stage
        }
        
        return resultArray;
    }
    /**
     * Reformats date (yyyy-mm-dd) to the CDSS required mm/dd/yyyy
     * @param originalDate A string of the date in yyyy-mm-dd format
     * @return A string of the date in mm/dd/yyyy format
     */
    private String cdssInputDateFormat(String originalDate){
        String[] columns = originalDate.split("-");
        return columns[1] + "/" + columns[2] + "/" + columns[0];
    }
    /**
     * Reformats date (yyyy-MM-dd) to the CDSS required MM/dd/yyyy_HH:mm
     * @param date A string of the date in yyyy-MM-dd format or yyyy-MM-dd HH:mm
     * @return A string of the date in MM/dd/yyyy_HH:mm format
     * 09/27/2018_04:00
     */
    private String cdssInputDateTimeFormat(String originalDate){
        String newDate = originalDate;
        if(originalDate.length() == 16){
            //yyyy-MM-dd HH:mm
            String[] columns = originalDate.split(" ");
            String[] date = columns[0].split("-");
            newDate = date[1] + "/" + date[2] + "/" + date[0] + "_" + columns[1];
        }else if(originalDate.length() == 10){
            //yyyy-MM-dd
            String[] columns = originalDate.split("-");
            newDate = columns[1] + "/" + columns[2] + "/" + columns[0];
        }
        return newDate;
    }
    /**
     * Reformats the date from CDWR's "yyyy-MM-ddTHH:mm:ss.sssssss" format to yyyy-MM-dd or yyyy-MM-dd HH:mm, depending on the hourlyTF flag
     * @param date the current date in the expected yyyy-MM-ddTHH:mm:ss.sssssss
     * @param hourlyTF  flag for desiring hourly date formats instead of daily date formats
     * @return if hourlTF is true, then returns hourly formatted data (yyyy-MM-dd HH:mm)
     * otherwise it returns daily formated dates (yyyy-MM-dd)
     */
    private String cdssOutputDateFormat(String date, boolean hourlyTF){
        String newDate = date;
        String[] columns = date.split("T");
        if(hourlyTF){
            //Reformat yyyy-MM-ddTHH:mm:ss.sssssss to yyyy-MM-dd HH:mm
            String hours = columns[1].substring(0, columns[1].indexOf(".")-3);
            newDate = columns[0] + " " + hours;
        }else{
            //Reformat yyyy-MM-ddTHH:mm:ss.sssssss to yyyy-MM-dd
            newDate = columns[0];
        }
        return newDate;
    }
}