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

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;

/**
* Last Updated: 20-November-2018
* @author Tyler Wible
* @since 12-July-2012
*/
public class UserData {
    /**
     * Parses the supplied string of user data
     * @param wqTest  the water quality test desired "00600 Total nitrogen, water, unfiltered, milligrams per liter -- mg/L" (format: "5-digit test-name -- units") or "flow"
     * @param startDate  the user specified begin date, used to minimize the data returned
     * @param endDate  the user specified end date, used to minimize the data returned
     * @return  a string[][] with the contents of the user uploaded file formatted as: column1 = dates (yyyy-mm-dd), 
     * column2 = values (expected to be daily average flow values in cfs or water quality concentrations in the units of the current water quality test)
     * if there is not a value for column2 (blank, null, not a number, etc.) then no data will be kept for that date
     * @throws WaterDataException
     */
    public static ArrayList<String> parseUserDataRaw(String userDataRaw, String startDate, String endDate, String wqTest) throws WaterDataException{
        //Get today's date
        DateFormat desiredDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        Date currentDate = new Date();
        String todaysDate = desiredDateFormat.format(currentDate);
        
        //Get the wqCode out of wqTest
        String wqCode = wqTest;
        if(wqTest.length() > 5){
            wqCode = wqTest.substring(0,5);
        }
        
        //Get the headers and find the desired column of data
        String[] userData_rows = userDataRaw.split("\n");
        String[] headers = userData_rows[0].split("\t");
        int headerIndex = -1;
        for(int i=0; i<headers.length; i++){
            if(headers[i].equalsIgnoreCase(wqCode)){
                headerIndex = i;
            }
        }
        
        //Check for lack of data
        if(headerIndex == -1){
            throw new WaterDataException("There is no uploaded data for water quality test:" + wqTest);
        }
        
        //Parse the user data
        ArrayList<String> stationData = new ArrayList<>();
        for(int i=1; i<userData_rows.length; i++){//Skip first row header
            //Check for date format problems
            String[] currentColumns = userData_rows[i].split("\t");
            String correctedDate = fixDateFormat(currentColumns[0]);
            //currentColumns[0] = date
            //currentColumns[1] = value
            
            //Only keep the data if the value column is not null
            boolean valueExists = true;
            try{
                double value = Double.parseDouble(currentColumns[headerIndex]);
            }catch(NullPointerException | NumberFormatException | ArrayIndexOutOfBoundsException e){
                valueExists = false;
            }
            
            //If the date conversion does not hit an error keep this date
            if(!correctedDate.equalsIgnoreCase("error") && valueExists){
                //Check if the date is within the range the user desires
                if(todaysDate.equals(endDate)){
                    //If the end limit is today, keep future forcasted data as well
                    if((correctedDate.compareTo(startDate) >= 0)){
                        stationData.add(correctedDate + "\t" + currentColumns[headerIndex]);
                    }
                }else{
                    //Check if the current data is within the date range, if so keep it
                    if((correctedDate.compareTo(startDate) >= 0) && (correctedDate.compareTo(endDate) <= 0)){
                        stationData.add(correctedDate + "\t" + currentColumns[headerIndex]);
                    }
                }
                
            }
        }
        return stationData;
        
    }
    /**
     * Converts the provided date format into a new date format of yyyy-mm-dd which is expected by all of the java functions (supported input formats are:
     *  yyyy-mm-dd, 
     *  yyyy-mm-d, 
     *  yyyy-m-dd, 
     *  yyyy-m-d, 
     *  yyyy/mm/dd, 
     *  yyyy/mm/d, 
     *  yyyy/m/dd, 
     *  yyyy/m/d)
     * @param date  the original date format to be converted into yyyy-mm-dd
     * @return  the original date converted to the yyyy-mm-dd format or "error" if the date wasn't able to be converted
     */
    public static String fixDateFormat(String date){
        //This allows the user to upload a greater number of date formats that will be converted into the expected format for all the java interfaces
        
        //Convert Determine the deliminator the current date format
        String[] dateColumns = date.split("-");
        String deliminator = "";
        String day = "01", month = "01", year = "1900";

        if(dateColumns.length != 1){
            deliminator = "-";
        }else{
            //Not a "-" separated date, so try a "/" separated date
            dateColumns = date.split("/");
            if(dateColumns.length != 1){
                deliminator = "/";
            }else{
                //Not a "/" separated date, so assume that it is a number and not parse-able as a date,
                //return an error so this date can be skipped
                return "error";
            }
        }

        //Substring the date
        String[] datePieces = date.split(deliminator);
        year = datePieces[0];
        month = datePieces[1];
        day = datePieces[2];
        
        //Check if user uploaded yyyy-MM-dd HH:mm data so shorted "day" accordingly
        if(day.length() > 2){
            day = day.substring(0,2);
        }

        //Check if the date pieces are the proper sizes (a 4 digit year, 2 digit month, and 2 digit day)
        if(year.length() < 4 || year.length() > 4 || month.length() > 2 || day.length() > 2){
            return "error";
        }

        //Check for a single digit month, if so make it a 2 digit month starting with a zero
        if(month.length() < 2){
            month = "0" + month;
        }

        //Check for a single digit day, if so make it a 2 digit day starting with a zero
        if(day.length() < 2){
            day = "0" + day;
        }

        //Assemble and return the newly formatted date
        String newDate = year + "-" + month + "-" + day;

        return newDate;
    }
}