ConfidenceIntervalResultSet.java [tools/WepsReportData/src/usda/weru/weps/reports/query] Revision: b8b8e4a5cd41a856202b3cdee2c61875d789d2b8  Date: Thu May 24 15:59:17 MDT 2018
/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package usda.weru.weps.reports.query;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.sql.Types;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.log4j.Logger;
import usda.weru.util.ConversionCalculator;
import usda.weru.util.Util;

/**
 *
 * @author joelevin
 */
public class ConfidenceIntervalResultSet extends WepsResultSet {
    private static final Logger LOGGER = Logger.getLogger(ConfidenceIntervalResultSet.class);
    public static final String FILE_NAME = "ci.out";

    // Names of the table and columns in the SQL data model.
    public static final String NAME = "ci";
    public static final String COLUMN_PREFIX = NAME + ".";
//    public static final String COLUMN_RUNID = "runid";
    
    public static final String COLUMN_ROT_YEARS = COLUMN_PREFIX + "rot_years";    
    public static final String COLUMN_CYCLE = COLUMN_PREFIX + "cycle";
    public static final String COLUMN_YEAR = COLUMN_PREFIX + "year";    
    public static final String COLUMN_EVENT_COUNT = COLUMN_PREFIX + "event_count";
    
    public static final String COLUMN_TOTAL = COLUMN_PREFIX + "total";        
    public static final String COLUMN_LOW = COLUMN_PREFIX + "low";
    public static final String COLUMN_RUNNING = COLUMN_PREFIX + "running";
    public static final String COLUMN_HIGH = COLUMN_PREFIX + "high";

    
//    private final WepsConnection c_con;
//    private boolean c_filled;

    // New member variables
    public String m_sDirectory;
    public String m_sUnits;

    public ConfidenceIntervalResultSet(WepsConnection con, String sDirectory, String sUnits) {
        super(con);
        m_sDirectory = sDirectory;
        m_sUnits     = sUnits;
        
//        c_con = con;
//        addColumn(COLUMN_RUNID, Types.INTEGER, 10, 0);        
        addColumn(COLUMN_ROT_YEARS, Types.INTEGER, 10, 0);     
        addColumn(COLUMN_CYCLE, Types.INTEGER, 10, 0);     
        addColumn(COLUMN_YEAR, Types.INTEGER, 10, 0);                     
        addColumn(COLUMN_EVENT_COUNT, Types.DOUBLE, 10, 3);
        
        
        addColumn(COLUMN_TOTAL, Types.DOUBLE, 10, 3);                        
        addColumn(COLUMN_LOW, Types.DOUBLE, 10, 3);        
        addColumn(COLUMN_RUNNING, Types.DOUBLE, 10, 3);
        addColumn(COLUMN_HIGH, Types.DOUBLE, 10, 3);
        
        
    }

    @Override
    public String getName() {
        return NAME;
    }
    
    protected boolean isUSUnits(){
        return Util.USUnits.equals(m_sUnits);
    }

    @Override
    public synchronized void fill() {
        int columnCount; // some columns are missing due to bad counting on the first row.
//        if (c_filled) {
//            return;
//        }
//        File[] files = c_con.getRunFiles();         
        
//        for (int runIndex = 0; runIndex < files.length; runIndex++) {
            File runDir = new File(m_sDirectory);
            
            File ciFile = new File(runDir, FILE_NAME);
            
            if (ciFile.exists()){     
                BufferedReader in = null;
                try{
                    in = new BufferedReader(new FileReader(ciFile));
                    
                    //first line is the header
                    String headerLine = getLine(in);
                    
                    if(headerLine == null || headerLine.trim().isEmpty()){
                        LOGGER.warn("Confidence interval file is empty: " + ciFile.getAbsolutePath());   
//                        break;
                    }
                    
                    // list to hold the headers in order
                    List<String> headers = new ArrayList<String>();
                    
                    //parse the header
                    String[] headerParts = headerLine.trim().split("\\|", 0);
                    columnCount = headerParts.length;
                    for(String rawHeader : headerParts){
                        //trim, lower and replaces inner spaces with underbar
                        rawHeader = rawHeader.trim().toLowerCase().replace(" ", "_");
                        if(rawHeader.startsWith("low")){
                            rawHeader = "low";
                        }
                        else if (rawHeader.startsWith("high")){
                            rawHeader = "high";
                        }
                        headers.add(rawHeader);
                    }
                                   
                    boolean priming = true;
                    
                    String line;
                    while ((line = getLine(in)) != null ){
                        //each line is a new row
                        
                        String[] parts = line.split("\\|", 0);
                        
                        Map<String, String> rowValues = new HashMap<String, String>();
                        for(int i = 0; i < columnCount; i++){
                            if(i<parts.length)
                                rowValues.put(headers.get(i), parts[i]);
                            else
                                rowValues.put(headers.get(i), null);
                        }
                        
                        
                        Object[] row = createNewRow(false);
//                        setRowValue(row, COLUMN_RUNID, runIndex);
                        
                        if(priming && rowValues.containsKey("yrly_ave") && rowValues.get("yrly_ave") != null){
                            priming = false;
                        }
                                                
                        
                        // parse the values out of the row
                        parseInteger(row, rowValues, "nrot_yrs", COLUMN_ROT_YEARS);
                        parseInteger(row, rowValues, "ncycles", COLUMN_CYCLE);                                                
                        parseInteger(row, rowValues, "yr", COLUMN_YEAR);
                        
                        //fixup the priming cycles
                        if(priming){
                            fixupCycle(row);
                        }
                        
                        parseDouble(row, rowValues, "#events", COLUMN_EVENT_COUNT);
                        
                        parseDouble(row, rowValues, "yr_total", COLUMN_TOTAL);
                        parseDouble(row, rowValues, "yrly_ave", COLUMN_RUNNING);
                        parseDouble(row, rowValues, "low", COLUMN_LOW);
                        parseDouble(row, rowValues, "high", COLUMN_HIGH);
                        
                        if(isUSUnits()){
                            fixupUnits(row, COLUMN_TOTAL);
                            fixupUnits(row, COLUMN_LOW);
                            fixupUnits(row, COLUMN_RUNNING);
                            fixupUnits(row, COLUMN_HIGH);
                        }
                        addRow(row);                                     
                    }
                    
                    
                }
                catch (IOException ioe) {
                    LOGGER.error("Error reading ci file: " + ciFile.getAbsolutePath(), ioe);                    
                }                
                finally{
                    if (in != null){
                        try{
                            in.close();
                        }
                        catch(Exception e){
                            LOGGER.error("Error closing ci file: " + ciFile.getAbsolutePath(), e);
                        }
                    }                    
                }
            }

                     
//        }                

//        c_filled = true;
    }
    
    private void fixupCycle(Object[] row){
        Integer year = getRowValue(row, COLUMN_YEAR);      
        Integer rots = getRowValue(row, COLUMN_ROT_YEARS);
        
        int cycle = year / rots + (year % rots == 0 ? 0 : 1);
        setRowValue(row, COLUMN_CYCLE, cycle);
        
    }
    
    private void fixupUnits(Object[] row, String column){
         Double value = getRowValue(row, column);
         if(value != null){
             
             try{
                value = ConversionCalculator.convert(value, "kg/m^2", "t/ac");                 
                setRowValue(row, column, value);
             }
             catch(Exception e){
//                 throw new SQLException(e);
             }
         }
    }
    
    private void parseInteger(Object[] row, Map<String, String> values, String header, String column){
        String value = values.get(header);
        if(value == null || value.trim().isEmpty()){
            setRowValue(row, column, null);
            return;
        }
        try{
            int i = Integer.parseInt(value.trim());
            setRowValue(row, column, i);
        }
        catch(NumberFormatException nfe){
            LOGGER.error("Error parsing " + header + ".", nfe);
        }
    }
       
    
    private void parseDouble(Object[] row, Map<String, String> values, String header, String column){
        String value = values.get(header);
        if(value == null || value.trim().isEmpty()){
            setRowValue(row, column, null);
            return;
        }
        try{
            double i = Double.parseDouble(value.trim());
            setRowValue(row, column, i);
        }
        catch(NumberFormatException nfe){
            LOGGER.error("Error parsing " + header + ".", nfe);
        }
    }
    
    //Skip comments and blank lines
    private String getLine(BufferedReader in) throws IOException {
        String temp;
        while ((temp = in.readLine()) != null) {
            temp = temp.trim();
            if (temp.length() == 0) {
                //blank line
                continue;
            }
            if (temp.charAt(0) != '#') {
                //not a comment
                return temp;
            }
        }
        return null;
    }

    
}