CDSN_Data.java [src/java/m/cfa] Revision: 8270e78a57e94b386f731fcde8b76e6c9ef568d9  Date: Thu Sep 15 13:55:14 MDT 2016
package m.cfa;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import org.codehaus.jettison.json.JSONArray;
import org.codehaus.jettison.json.JSONException;
import org.codehaus.jettison.json.JSONObject;

/**
* Last Updated: 13-September-2016
* @author Tyler Wible
* @since 19-April-2016
*/
public class CDSN_Data {
    /**
     * Interfaces with the Colorado Data Sharing Network (CDSN) restful web services
     * for a set of search parameters for available stations
     * @param resultSummaryTF  a boolean flag for whether a result summary
     * should be included with the station search
     * @param minLat  the minimum latitude for the station search
     * @param maxLat  the maximum latitude for the station search
     * @param minLong  the minimum longitude the station search
     * @param maxLong  the maximum longitude for the station search
     * @return an ArrayList<String> containing the web service result(s)
     */
    private static ArrayList<String> downloadCDSNstations(boolean resultSummaryTF, 
                                                          String minLat,
                                                          String maxLat,
                                                          String minLong,
                                                          String maxLong) throws IOException{
        //Specify station search url from inputs
        //http://awqmsws.goldsystems.com/api/MonitoringLocationsVer1?ContentType=json&CountyName=BROADWATER
        String cdsnStationWebsite = "http://awqmsws.goldsystems.com/api/MonitoringLocationsVer1?ContentType=json&IncludeResultSummary="+ String.valueOf(resultSummaryTF) + 
                "&MonitoringLocationType=River%" + //Comment out this line to search for more than river/stream stations
                "&MinimumLatitude=" + minLat + "&MaximumLatitude=" + maxLat + "&MinimumLongitude=" + minLong + "&MaximumLongitude=" + maxLong;
        //ContentType (xml, json)
        //CountyName
        //Huc8
        //Huc12
        //IncludeResultSummary (true, false)
        //MinimumLatitude
        //MaximumLatitude
        //MinimumLongitude
        //MaximumLongitude
        //MonitoringLocationIdentifiersCsv
        //MonitoringLocationType (River/Stream, Landfill, and lots more)
        //OrganizationIdentifiersCsv
        //StateCode (CO)
        //WatershedManagementUnit (?)
        
        //Open the provided website
        ArrayList<String> pageData = new ArrayList<>();
        try{
            URL webpage = new URL(cdsnStationWebsite);
            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(FileNotFoundException e){
            //Leave array blank for later error messages pasted onto the user
        }

        return pageData;
    }
    /**
     * Interfaces with the Colorado Data Sharing Network (CDSN) restful web services
     * for a set of search parameters for available stations
     * @param resultSummaryTF  a boolean flag for whether a result summary
     * should be included with the station search
     * @param minLat  the minimum latitude for the station search
     * @param maxLat  the maximum latitude for the station search
     * @param minLong  the minimum longitude the station search
     * @param maxLong  the maximum longitude for the station search
     * @return JSONArray of CDSN stations within the bounding lat/long box
     * @throws IOException
     * @throws org.codehaus.jettison.json.JSONException
     */
    public static JSONArray getCDSNstations(boolean resultSummaryTF, 
                                            String minLat,
                                            String maxLat,
                                            String minLong,
                                            String maxLong) throws IOException, JSONException {
        //Get CDSN stations
        ArrayList<String> stationList = downloadCDSNstations(resultSummaryTF, minLat, maxLat, minLong, maxLong);
        
        JSONArray stations = new JSONArray("[]");
        if(stationList.size() > 0){
            //parse the json string into a JSONArray and the object(s) within it
            stations = new JSONArray(stationList.get(0));
        }
        return stations;
    }
    /**
     * Interfaces with the Colorado Data Sharing Network (CDSN) restful web services
     * for a set of search parameters for available stations
     * @param organizationID  The ID for the supervising organization for the station within STORET
     * @param stationID  station ID of the current station, used to search the STORET databes
     * @param wq_test  The word 'flow' or the formatted name for the water quality test being used, Format is: '00600 Total nitrogen, water, unfiltered, milligrams per liter -- mg/L' = '5-digit-USGS-water-quality-test-code test-name -- units'
     * @param beginDate  the used defined begin date of search (yyyy-mm-dd)
     * @param endDate  the user defined end date of search (yyyy-mm-dd)
     * @return an ArrayList<String> containing the web service result(s)
     */
    private static ArrayList<String> downloadCDSNdata(String organizationID,
                                                      String stationID,
                                                      String wq_test,
                                                      String beginDate, 
                                                      String endDate) throws IOException, ParseException{
        //If no date input, make it the maximum of available data
        if(beginDate == null || beginDate.equalsIgnoreCase("")){
            beginDate = "1900-01-01";
        }
        if(endDate == null || endDate.equalsIgnoreCase("")){
            // Pull current date for upper limit of data search
            DateFormat desiredDateFormat = new SimpleDateFormat("yyyy-MM-dd");
            Date currentDate = new Date();
            endDate = desiredDateFormat.format(currentDate);
        }
        //Reformat dates for CDSN format only
        String minDate = beginDate.substring(5,7) + "-" + beginDate.substring(8) + "-" + beginDate.substring(0,4);
        String maxDate = endDate.substring(5,7) + "-" + endDate.substring(8) + "-" + endDate.substring(0,4);
        
        //Specify data search url from inputs
        //http://awqmsws.goldsystems.com/api/ResultsVer1?ContentType=json&OrganizationIdentifiersCsv=CITYFTCO_WQX&MonitoringLocationIdentifiersCsv=1EFF&MinDate=01-01-1900&MaxDate=04-25-2016&Characteristic=Ammonia-nitrogen
        String cdsnDataWebsite = "http://awqmsws.goldsystems.com/api/ResultsVer1?ContentType=json" + 
                "&OrganizationIdentifiersCsv=" + organizationID + "&MonitoringLocationIdentifiersCsv=" + stationID + 
                "&MinDate=" + minDate + "&MaxDate=" + maxDate;
        if(!wq_test.equalsIgnoreCase("All")){
            String characteristic_name = wq_test;
            if(wq_test.length() > 5){
                //extract "Ammonia-nitrogen as N" from "00625 Ammonia-nitrogen as N -- mg/L"
                characteristic_name = wq_test.substring(6, wq_test.indexOf("--") - 1);
            }
            cdsnDataWebsite = cdsnDataWebsite + "&Characteristic=" + characteristic_name;
        }
        //ActivityType (lots)
        //Characteristic (lots)
        //ContentType (xml, json)
        //CountyName
        //Huc8
        //Huc12
        //MaxDate (mm/dd/yyyy or mm-dd-yyyy)
        //MediaName (Air, Water, Biological, Soil, Sediment, Other, Tissue, Habitat)
        //Media SubdivisionName (lots)
        //MinDate (mm/dd/yyyy or mm-dd-yyyy)
        //MonitoringLocationIdentifiersCsv ("id1, id2, id3")
        //MonitoringLocationType (lots)
        //OrganizationIdentifiersCsv ("id1, id2, id3")
        //ProjectIdentifier (lots)
        //StateCode (CO)
        //WaterBodyName (lots)
        //WatershedManagementUnit (lots)
        
        ArrayList<String> pageData = new ArrayList<>();
        
        try{
            //Open the provided website
            URL webpage = new URL(cdsnDataWebsite);
            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 (FileNotFoundException e){
            //Leave array blank for later error messages pasted onto the user
        }
        return pageData;
    }
    /**
     * Interfaces with the STORET download website and searches for the data for a specific station and 
     * read it out into a variable depending on what data was requested
     * @param organizationID  The ID for the supervising organization for the station within STORET
     * @param stationID  station ID of the current station, used to search the STORET databes
     * @param wq_test  The word 'flow' or the formatted name for the water quality test being used, Format is: '00600 Total nitrogen, water, unfiltered, milligrams per liter -- mg/L' = '5-digit-USGS-water-quality-test-code test-name -- units'
     * @param beginDate  the used defined begin date of search (yyyy-mm-dd)
     * @param endDate  the user defined end date of search (yyyy-mm-dd)
     * @return  a Object[][] containing:
     *   [0] = an ArrayList containing the data query from the web service
     *   [1] = a String[][] containing flow or water quality data: column1 = date(yyyy-mm-dd), column2 = flowValue
     *   [2] = start data of the data (yyyy-mm-dd)
     *   [3] = end data of the data (yyyy-mm-dd)
     * @throws java.io.IOException
     * @throws java.text.ParseException
     * @throws org.codehaus.jettison.json.JSONException
     */
    public static Object[] getCDSNdata(String organizationID,
                                       String stationID,
                                       String wq_test,
                                       String beginDate, 
                                       String endDate) throws IOException, ParseException, JSONException {
        //Get CDSN station data
        ArrayList<String> dataList = downloadCDSNdata(organizationID, stationID, wq_test, beginDate, endDate);
        //http://awqmsws.goldsystems.com/api/ResultsVer1?ContentType=json&OrganizationIdentifiersCsv=CITYFTCO_WQX&MonitoringLocationIdentifiersCsv=1EFF&Characteristic=Ammonia-nitrogen&MinDate=01-01-1900&MaxDate=04-25-2016
        
        //Parse results
        ArrayList<String> resultFileContents = new ArrayList<>();
        if(dataList.size() > 0){
            resultFileContents.add("OrganizationIdentifier\tMonitoringLocationIdentifier\tMediaSubdivisionName\tActivityIdentifier\tStartDate\tStartTime\tMediaName\tActivityType\tCharacteristicName\tSampleFraction\tValueType\tStatus\tResultValue\tResultUnit\tAnalyticalMethodContext\tAnalyticalMethodIdentifier\tDetectionCondition\tQualifierCode");
            //parse the json string into a JSONArray and the object(s) within it
            JSONArray cdsnResponse =  new JSONArray(dataList.get(0));
            for(int i=0; i<cdsnResponse.length(); i++){
                JSONObject currentActivity = cdsnResponse.getJSONObject(i);
                String orgID = currentActivity.getString("OrganizationIdentifier");
                //String stationID = currentActivity.getString("MonitoringLocationIdentifier");
                String mediaSubdivision = currentActivity.getString("MediaSubdivisionName");
                String activityID = currentActivity.getString("ActivityIdentifier");
                String date = currentActivity.getString("StartDate");
                String time = currentActivity.getString("StartTime");
                String mediaName = currentActivity.getString("MediaName");
                String activityType = currentActivity.getString("ActivityType");
                
                //Parse 'result' JSONArray within each 'activity' JSONObject
                JSONArray resultArray = currentActivity.getJSONArray("Results");
                for(int j=0; j<resultArray.length(); j++){
                    JSONObject currentResult = resultArray.getJSONObject(j);
                    String characteristic = currentResult.getString("CharacteristicName");
                    String fraction = currentResult.getString("SampleFraction");
                    String valueType = currentResult.getString("ValueType");
                    String status = currentResult.getString("Status");
                    String resultValue = currentResult.getString("ResultValue");
                    String units = currentResult.getString("ResultUnit");
                    String methodContext = currentResult.getString("AnalyticalMethodContext");
                    String methodIdentifier = currentResult.getString("AnalyticalMethodIdentifier");
                    String detectionCondition = currentResult.getString("DetectionCondition");
                    String QualifierCode = currentResult.getString("QualifierCode");
                    
                    //Save results
                    resultFileContents.add(orgID + "\t"+stationID+"\t"+mediaSubdivision+"\t"+activityID+"\t"+
                            date+"\t"+time+"\t"+mediaName+"\t"+activityType+"\t"+characteristic+"\t"+
                            fraction+"\t"+valueType+"\t"+status+"\t"+resultValue+"\t"+units+"\t"+
                            methodContext+"\t"+methodIdentifier+"\t"+detectionCondition+"\t"+QualifierCode);
                }
            }
        }else{
            resultFileContents.add("No " +  wq_test + " data found for CDSN Station: " + stationID + " by: " + organizationID);
        }
        
        //convert Array list into String[][] array (column1 = date, column2 = value)
        String[][] stringArray = new String[resultFileContents.size() - 1][2];
        for(int i=1; i<resultFileContents.size(); i++){
            String[] currentColumns = resultFileContents.get(i).split("\t");
            stringArray[i-1][0] = currentColumns[4]; //date
            stringArray[i-1][1] = currentColumns[12]; //value
        }
        
        //Save analysis results
        String start = "-1";
        String end = "-1";
        if(stringArray.length > 0){
            start = stringArray[0][0];
            end = stringArray[stringArray.length - 1][0];
        }
        
        Object[] returnArray = {resultFileContents, stringArray, start, end};
        return returnArray;
    }
}