OutputResultSet.java [tools/WepsReportData/src/usda/weru/weps/reports/query] Revision:   Date:
/*
 * 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.Date;
import java.sql.Types;
import java.text.MessageFormat;
import java.text.ParseException;
import java.util.*;
import java.util.logging.Logger;
import usda.weru.util.ConversionCalculator;
import usda.weru.util.ConversionUnit;
import usda.weru.util.Util;
import usda.weru.util.table.Column;
import usda.weru.util.table.DataAdjustment;
import usda.weru.util.table.DataLimit;
import usda.weru.util.table.WepsTableMeta;
import usda.weru.weps.RunFileData;

/**
 *
 * @author joelevin
 */
    public class OutputResultSet extends WepsResultSet {
    private static final String PATH_META = "tables/detail.xml";
    private static final Logger LOGGER = Logger.getLogger(OutputResultSet.class.getName());
    private String workingDir = "";
    public static final String FILE_NAME = RunFileData.WepsOutput;
    
    // Names of the table and columns in the SQL data model.
    public static final String NAME = "output";
    public static final String COLUMN_PREFIX = NAME + ".";
    
//    /**
//     * Index for the run.
//     */ 
//    public static final String COLUMN_RUNID = "runid";
    /**
     * Line number in the file.  0 is the header.  1 is the first line of data.  Line 0 is not included in the resultset.
     */            
    public static final String COLUMN_LINE = COLUMN_PREFIX + "line";
    
    /**
     * Line key indicates the type of record the row represents.
     */
    public static final String COLUMN_KEY = COLUMN_PREFIX + "key";
    
    private static final String COLUMN_SDEDMOYR = COLUMN_PREFIX + "sd ed mo yr";
    //these three fields are used for special handling of the "sd ed mo yr" column
    public static final String COLUMN_STARTDATE = COLUMN_PREFIX + "startdate";
    public static final String COLUMN_ENDDATE = COLUMN_PREFIX + "enddate";  
    public static final String COLUMN_PERIOD = COLUMN_PREFIX + "period";          
    
    public static final String COLUMN_OPERATION = COLUMN_PREFIX + "operation";
    public static final String COLUMN_CROP = COLUMN_PREFIX + "crop";
    public static final String COLUMN_AVE_NO_EVNT = COLUMN_PREFIX + "ave_no_evnt";
    public static final String COLUMN_TOT_NO_EVNT = COLUMN_PREFIX + "tot_no_evnt";
    public static final String COLUMN_GLOSS_PER_EVNT = COLUMN_PREFIX + "gloss_per_evnt";
    public static final String COLUMN_NLOSS_PER_EVNT = COLUMN_PREFIX + "nloss_per_evnt";
    public static final String COLUMN_GROSS_LOSS = COLUMN_PREFIX + "gross_loss";
    public static final String COLUMN_TOT_LOSS = COLUMN_PREFIX + "tot_loss";
    public static final String COLUMN_CRPSALT = COLUMN_PREFIX + "crp_salt"; //"crp+salt";
    public static final String COLUMN_SUSPEN = COLUMN_PREFIX + "suspen";
    public static final String COLUMN_PM10 = COLUMN_PREFIX + "pm10";
    public static final String COLUMN_CS1 = COLUMN_PREFIX + "cs1";
    public static final String COLUMN_CS2 = COLUMN_PREFIX + "cs2";
    public static final String COLUMN_CS3 = COLUMN_PREFIX + "cs3";
    public static final String COLUMN_CS4 = COLUMN_PREFIX + "cs4";
    public static final String COLUMN_SS1 = COLUMN_PREFIX + "ss1";
    public static final String COLUMN_SS2 = COLUMN_PREFIX + "ss2";
    public static final String COLUMN_SS3 = COLUMN_PREFIX + "ss3";
    public static final String COLUMN_SS4 = COLUMN_PREFIX + "ss4";
    public static final String COLUMN_PM1 = COLUMN_PREFIX + "pm1";
    public static final String COLUMN_PM2 = COLUMN_PREFIX + "pm2";
    public static final String COLUMN_PM3 = COLUMN_PREFIX + "pm3";
    public static final String COLUMN_PM4 = COLUMN_PREFIX + "pm4";
    public static final String COLUMN_SALT_LOSS = COLUMN_PREFIX + "salt_loss";
    public static final String COLUMN_LOSS_AREA = COLUMN_PREFIX + "loss_area";
    public static final String COLUMN_LOSS_FRAC = COLUMN_PREFIX + "loss_frac";
    public static final String COLUMN_SALT_DEP = COLUMN_PREFIX + "salt_dep";
    public static final String COLUMN_DEP_AREA = COLUMN_PREFIX + "dep_area";
    public static final String COLUMN_DEP_FRAC = COLUMN_PREFIX + "dep_frac";
    public static final String COLUMN_FLUX_RATE = COLUMN_PREFIX + "flux_rate";
    public static final String COLUMN_FLUX_AREA = COLUMN_PREFIX + "flux_area";
    public static final String COLUMN_FLUX_FRAC = COLUMN_PREFIX + "flux_frac";
    public static final String COLUMN_SHELT_AREA = COLUMN_PREFIX + "shelt_area";
    public static final String COLUMN_SHELT_FRAC = COLUMN_PREFIX + "shelt_frac";
    public static final String COLUMN_PRECIP = COLUMN_PREFIX + "precip";    
    public static final String COLUMN_W_ENERGY = COLUMN_PREFIX + "w_energy";
    public static final String COLUMN_SNOW_COVER = COLUMN_PREFIX + "snow_cover";
    public static final String COLUMN_L_CAN_COV = COLUMN_PREFIX + "l_can_cov";
    public static final String COLUMN_L_SIL_AREA = COLUMN_PREFIX + "l_sil_area";
    public static final String COLUMN_L_ST_MASS = COLUMN_PREFIX + "l_st_mass";
    public static final String COLUMN_L_RT_MASS = COLUMN_PREFIX + "l_rt_mass";
    public static final String COLUMN_L_ST_HT = COLUMN_PREFIX + "l_st_ht";
    public static final String COLUMN_L_NO_STEM = COLUMN_PREFIX + "l_no_stem";
    public static final String COLUMN_D_FL_COV = COLUMN_PREFIX + "d_fl_cov";
    public static final String COLUMN_D_ST_SIL = COLUMN_PREFIX + "d_st_sil";
    public static final String COLUMN_D_FL_MASS = COLUMN_PREFIX + "d_fl_mass";
    public static final String COLUMN_D_ST_MASS = COLUMN_PREFIX + "d_st_mass";
    public static final String COLUMN_D_BG_MASS = COLUMN_PREFIX + "d_bg_mass";
    public static final String COLUMN_D_RT_MASS = COLUMN_PREFIX + "d_rt_mass";
    public static final String COLUMN_D_ST_HT = COLUMN_PREFIX + "d_st_ht";
    public static final String COLUMN_D_NO_STEM = COLUMN_PREFIX + "d_no_stem";
    public static final String COLUMN_B_F_FL_COV = COLUMN_PREFIX + "b_f_fl_cov";
    public static final String COLUMN_B_F_ST_SIL = COLUMN_PREFIX + "b_f_st_sil";
    public static final String COLUMN_B_M_FL_COV = COLUMN_PREFIX + "b_m_fl_cov";
    public static final String COLUMN_B_M_ST_SIL = COLUMN_PREFIX + "b_m_st_sil";
    public static final String COLUMN_B_M_BG_ALL = COLUMN_PREFIX + "b_m_bg_all";
    public static final String COLUMN_RDG_OR = COLUMN_PREFIX + "rdg_or";
    public static final String COLUMN_RDG_HT = COLUMN_PREFIX + "rdg_ht";
    public static final String COLUMN_RDG_SP = COLUMN_PREFIX + "rdg_sp";
    public static final String COLUMN_RR = COLUMN_PREFIX + "rr";
    public static final String COLUMN_SURF_84 = COLUMN_PREFIX + "surf_84";
    public static final String COLUMN_SURF_AS = COLUMN_PREFIX + "surf_AS";    
    public static final String COLUMN_SURF_SURF_AG_DEN = COLUMN_PREFIX + "surf_ag_den";
    public static final String COLUMN_SURF_SURF_AG_CA = COLUMN_PREFIX + "surf_ag_CA";
    public static final String COLUMN_SURF_CRUST = COLUMN_PREFIX + "surf_crust";
    public static final String COLUMN_SURF_CRUST_AS = COLUMN_PREFIX + "crust_AS";
    public static final String COLUMN_SURF_CRUST_LM = COLUMN_PREFIX + "crust_LM";
    public static final String COLUMN_SURF_CRUST_THICK = COLUMN_PREFIX + "crust_thick";
    public static final String COLUMN_SURF_CRUST_DEN = COLUMN_PREFIX + "crust_den";
    public static final String COLUMN_SURF_CRUST_LF = COLUMN_PREFIX + "crust_LF";
    public static final String COLUMN_SURF_CRUST_CA = COLUMN_PREFIX + "crust_CA";

    
    public static final String COLUMN_LOWER_LIMIT = COLUMN_PREFIX + "_lowerlimit";
    public static final String COLUMN_UPPER_LIMIT = COLUMN_PREFIX + "_upperlimit";

//    private final WepsConnection c_con;
//    private boolean c_filled;
    private Map <String, ConversionUnit> c_siUnits;
    private Map <String, ConversionUnit> c_usUnits;

    private WepsTableMeta c_meta;

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

    public OutputResultSet(WepsConnection con, String sDirectory, String sUnits) throws Exception {
        super(con);
        m_sDirectory = sDirectory;
        m_sUnits     = sUnits;

//        c_con = con;
//        addColumn(COLUMN_RUNID, Types.INTEGER, 10, 0); 
        addColumn(COLUMN_LINE, Types.INTEGER, 10, 0);
        addColumn(COLUMN_KEY, Types.CHAR, 1, 0);    
        addColumn(COLUMN_STARTDATE, Types.DATE, 0, 0);    
        addColumn(COLUMN_ENDDATE, Types.DATE, 0, 0);   
        addColumn(COLUMN_PERIOD, Types.INTEGER, 10, 0); 
        addColumn(COLUMN_OPERATION, Types.VARCHAR, 255, 0); 
        addColumn(COLUMN_CROP, Types.VARCHAR, 255, 0); 
                
        //create the unit maps
        c_siUnits = new HashMap <String, ConversionUnit> ();
        c_usUnits = new HashMap <String, ConversionUnit> ();
        addColumn(COLUMN_GROSS_LOSS, Types.DOUBLE, 10, 3, "kg/m^2", "t/ac");        
        addColumn(COLUMN_GROSS_LOSS + COLUMN_LOWER_LIMIT, Types.INTEGER, 10, 0);
        addColumn(COLUMN_GROSS_LOSS + COLUMN_UPPER_LIMIT, Types.INTEGER, 10, 0);

        addColumn(COLUMN_TOT_LOSS, Types.DOUBLE, 10, 3, "kg/m^2", "t/ac");        
        addColumn(COLUMN_TOT_LOSS + COLUMN_LOWER_LIMIT, Types.INTEGER, 10, 0);
        addColumn(COLUMN_TOT_LOSS + COLUMN_UPPER_LIMIT, Types.INTEGER, 10, 0);

        addColumn(COLUMN_CRPSALT, Types.DOUBLE, 10, 3, "kg/m^2", "t/ac");
        addColumn(COLUMN_CRPSALT + COLUMN_LOWER_LIMIT, Types.INTEGER, 10, 0);
        addColumn(COLUMN_CRPSALT + COLUMN_UPPER_LIMIT, Types.INTEGER, 10, 0);

        addColumn(COLUMN_SUSPEN, Types.DOUBLE, 10, 3, "kg/m^2", "t/ac");        
        addColumn(COLUMN_SUSPEN + COLUMN_LOWER_LIMIT, Types.INTEGER, 10, 0);
        addColumn(COLUMN_SUSPEN + COLUMN_UPPER_LIMIT, Types.INTEGER, 10, 0);

        addColumn(COLUMN_PM10, Types.DOUBLE, 10, 3, "kg/m^2", "t/ac");        
        addColumn(COLUMN_PM10 + COLUMN_LOWER_LIMIT, Types.INTEGER, 10, 0);
        addColumn(COLUMN_PM10 + COLUMN_UPPER_LIMIT, Types.INTEGER, 10, 0);
        
       
        addColumn(COLUMN_AVE_NO_EVNT, Types.DOUBLE, 10, 3, "fraction", "fraction");        
        addColumn(COLUMN_TOT_NO_EVNT, Types.DOUBLE, 10, 3, "fraction", "fraction");
        
        addColumn(COLUMN_GLOSS_PER_EVNT, Types.DOUBLE, 10, 3, "kg/m^2", "t/ac");    
        addColumn(COLUMN_NLOSS_PER_EVNT, Types.DOUBLE, 10, 3, "kg/m^2", "t/ac");            


        addColumn(COLUMN_CS1, Types.DOUBLE, 10, 3, "kg/m", "tn/1000ft");    
        addColumn(COLUMN_CS2, Types.DOUBLE, 10, 3, "kg/m", "tn/1000ft");    
        addColumn(COLUMN_CS3, Types.DOUBLE, 10, 3, "kg/m", "tn/1000ft");    
        addColumn(COLUMN_CS4, Types.DOUBLE, 10, 3, "kg/m", "tn/1000ft");    
        
        addColumn(COLUMN_SS1, Types.DOUBLE, 10, 3, "kg/m", "tn/1000ft");    
        addColumn(COLUMN_SS2, Types.DOUBLE, 10, 3, "kg/m", "tn/1000ft");    
        addColumn(COLUMN_SS3, Types.DOUBLE, 10, 3, "kg/m", "tn/1000ft");    
        addColumn(COLUMN_SS4, Types.DOUBLE, 10, 3, "kg/m", "tn/1000ft");    
        
        addColumn(COLUMN_PM1, Types.DOUBLE, 10, 3, "kg/m", "tn/1000ft");    
        addColumn(COLUMN_PM2, Types.DOUBLE, 10, 3, "kg/m", "tn/1000ft");    
        addColumn(COLUMN_PM3, Types.DOUBLE, 10, 3, "kg/m", "tn/1000ft");    
        addColumn(COLUMN_PM4, Types.DOUBLE, 10, 3, "kg/m", "tn/1000ft");    
        
        addColumn(COLUMN_SALT_LOSS, Types.DOUBLE, 10, 3, "kg/m^2", "t/ac");  
        addColumn(COLUMN_LOSS_AREA, Types.DOUBLE, 10, 3, "ha", "ac");  
        addColumn(COLUMN_LOSS_FRAC, Types.DOUBLE, 10, 3, "fraction", "fraction");
        
        addColumn(COLUMN_SALT_DEP, Types.DOUBLE, 10, 3, "kg/m^2", "t/ac");  
        addColumn(COLUMN_DEP_AREA, Types.DOUBLE, 10, 3, "ha", "ac");  
        addColumn(COLUMN_DEP_FRAC, Types.DOUBLE, 10, 3, "fraction", "fraction");

//        addColumn(COLUMN_FLUX_RATE, Types.DOUBLE, 10, 3, "kg/m^2", "t/ac");  
        addColumn(COLUMN_FLUX_AREA, Types.DOUBLE, 10, 3, "ha", "ac");  
        addColumn(COLUMN_FLUX_FRAC, Types.DOUBLE, 10, 3, "fraction", "fraction");
//
        addColumn(COLUMN_SHELT_AREA, Types.DOUBLE, 10, 3, "ha", "ac");  
        addColumn(COLUMN_SHELT_FRAC, Types.DOUBLE, 10, 3, "fraction", "fraction");
        
        addColumn(COLUMN_PRECIP, Types.DOUBLE, 10, 3, "mm", "in");
        addColumn(COLUMN_W_ENERGY, Types.DOUBLE, 10, 3, "KJ/m^2/day", "KJ/m^2/day");
        addColumn(COLUMN_SNOW_COVER, Types.DOUBLE, 10, 3, "fraction", "fraction");
        
        addColumn(COLUMN_L_CAN_COV, Types.DOUBLE, 10, 3, "fraction", "fraction");
        addColumn(COLUMN_L_SIL_AREA, Types.DOUBLE, 10, 3, "fraction", "fraction");        
        addColumn(COLUMN_L_ST_MASS, Types.DOUBLE, 10, 3, "kg/m^2", "lb/ac");
        addColumn(COLUMN_L_RT_MASS, Types.DOUBLE, 10, 3, "kg/m^2", "lb/ac");
        addColumn(COLUMN_L_ST_HT, Types.DOUBLE, 10, 3, "mm", "in");
        addColumn(COLUMN_L_NO_STEM, Types.DOUBLE, 10, 3, "#/m^2", "#/ac");
        
        addColumn(COLUMN_D_FL_COV, Types.DOUBLE, 10, 3, "fraction", "fraction");
        addColumn(COLUMN_D_ST_SIL, Types.DOUBLE, 10, 3, "fraction", "fraction");
        addColumn(COLUMN_D_FL_MASS, Types.DOUBLE, 10, 3, "kg/m^2", "lb/ac");
        addColumn(COLUMN_D_ST_MASS, Types.DOUBLE, 10, 3, "kg/m^2", "lb/ac");
        addColumn(COLUMN_D_BG_MASS, Types.DOUBLE, 10, 3, "kg/m^2", "lb/ac");
        addColumn(COLUMN_D_RT_MASS, Types.DOUBLE, 10, 3, "kg/m^2", "lb/ac");
        addColumn(COLUMN_D_ST_HT, Types.DOUBLE, 10, 3, "mm", "in");
        addColumn(COLUMN_D_NO_STEM, Types.DOUBLE, 10, 3, "#/m^2", "#/ac");
        
        addColumn(COLUMN_B_F_FL_COV, Types.DOUBLE, 10, 3, "fraction", "fraction");
        addColumn(COLUMN_B_F_ST_SIL, Types.DOUBLE, 10, 3, "fraction", "fraction");
        addColumn(COLUMN_B_M_FL_COV, Types.DOUBLE, 10, 3, "kg/m^2", "lb/ac");
        addColumn(COLUMN_B_M_ST_SIL, Types.DOUBLE, 10, 3, "kg/m^2", "lb/ac");
        addColumn(COLUMN_B_M_BG_ALL, Types.DOUBLE, 10, 3, "kg/m^2", "lb/ac");
        
        addColumn(COLUMN_RDG_OR, Types.DOUBLE, 10, 3, "degree", "degree");
        addColumn(COLUMN_RDG_HT, Types.DOUBLE, 10, 3, "mm", "in");
        addColumn(COLUMN_RDG_SP, Types.DOUBLE, 10, 3, "mm", "in");
        addColumn(COLUMN_RR, Types.DOUBLE, 10, 3, "mm", "in");
        
        addColumn(COLUMN_SURF_84, Types.DOUBLE, 10, 3, "fraction", "fraction");
        addColumn(COLUMN_SURF_AS, Types.DOUBLE, 10, 3, "ln(J/m^2)", "ln(J/m^2)");        
        addColumn(COLUMN_SURF_SURF_AG_DEN, Types.DOUBLE, 10, 3, "Mg/m^3", "lb/ft^3");
        addColumn(COLUMN_SURF_SURF_AG_CA, Types.DOUBLE, 10, 3, "fraction", "fraction");
        addColumn(COLUMN_SURF_CRUST_AS, Types.DOUBLE, 10, 3, "ln(J/m^2)", "ln(J/m^2)");
//
        addColumn(COLUMN_SURF_CRUST, Types.DOUBLE, 10, 3, "fraction", "fraction");        
        addColumn(COLUMN_SURF_CRUST_LM, Types.DOUBLE, 10, 3, "Mg/m^3", "lb/ft^3");
        addColumn(COLUMN_SURF_CRUST_THICK, Types.DOUBLE, 10, 3, "mm", "in");
        addColumn(COLUMN_SURF_CRUST_DEN, Types.DOUBLE, 10, 3, "Mg/m^3", "lb/ft^3");
        addColumn(COLUMN_SURF_CRUST_LF, Types.DOUBLE, 10, 3, "fraction", "fraction");
        addColumn(COLUMN_SURF_CRUST_CA, Types.DOUBLE, 10, 3, "1/m", "1/ft");        
        

        
                    
    }
    
    private void addColumn(String columnName, int type, int p, int s, String si, String us) throws Exception {        
        try{
            ConversionUnit siUnit = ConversionCalculator.getUnitFromTag(si);
            ConversionUnit usUnit = ConversionCalculator.getUnitFromTag(us);
            c_siUnits.put(columnName, siUnit);
            c_usUnits.put(columnName, usUnit);
            addColumn(columnName, type, p, s);
        }
        catch(ConversionCalculator.UnitNotFoundException e){
            //fail fast
            throw new Exception("Unsupported units.");
        }
        
        
    }

    @Override
    public String getName() {
        return NAME;
    }
    
    protected boolean isUSUnits(){
        return Util.USUnits.equals(m_sUnits);
    }
    
    public void setWorkingDir(String path){
        workingDir = path;
    }
    
    public synchronized void fill() {
//        if (c_filled) {
//            return;
//        }
//
        if(c_meta == null){
            c_meta = new WepsTableMeta();
            File workDir = new File(workingDir);
            File metaFile = new File(workDir, PATH_META);
            c_meta.fromFile(metaFile);
        }

//        File[] files = c_con.getRunFiles(); 

//        for (int i = 0; i < files.length; i++) {
            File runDir = new File(m_sDirectory);
            File outputFile = new File(runDir, RunFileData.WepsOutput);

            if (outputFile.exists()){                                

                BufferedReader in = null;
                try{
                    in = new BufferedReader(new FileReader(outputFile));

                    //first line is the headers.  We create a list of the column headers so we know what column to deal with.  The order is not likely to change.  Therefore, instead of dealing with column 1, we deal with the column mapped to "sd ed mo yr";
                    List <String> columns = new LinkedList<String> ();
                    String headerLine = in.readLine();
                    if (headerLine == null){
                        return;
                    }
                    String[] headerParts = headerLine.split("\\|", -1);
                    for (String columnName : headerParts){
                        //trim and add each column to the list
                        columnName = columnName.trim();
                        columns.add(columnName);
                    }                                                          

                    int keyIndex = columns.indexOf("key"); // COLUMN_KEY without prefix
                    String line;
                    int lineIndex = 0; //0 = header, not included in resultset
                    while ((line = in.readLine()) != null ){ 
                        //blank line
                        if (line.trim().length() == 0){
                            continue;
                        }
                        //split the line into the value parts
                        String[] parts = line.split("\\|", -1);
                        if (parts.length != columns.size()){
                            //little sanity check
                            LOGGER.severe("Mismatched column count.  Line: " + lineIndex + " of file: " + outputFile.getAbsolutePath());                            
                            continue;
                        }

                        Object[] row = createNewRow(false); // From what I can tell this will always add null values to the List if true.                                                           
//                        setRowValue(row, COLUMN_RUNID, i);

                        //Add the line index for sorting convienence
                        lineIndex++;                        
                        setRowValue(row, COLUMN_LINE, lineIndex);

                        //handle the key column
                        String key = parts[keyIndex].trim();
                        setRowValue(row, COLUMN_KEY, key);

                        for(int ci = 1; ci < parts.length; ci++){
                            String columnName = columns.get(ci);
                            if (columnName.length() == 0){
                                continue;
                            }
                            String part = parts[ci].trim();
                            
                            // Generate the table column name used in the output map.
                            // This will have format table-name DOT column-name.
                            // Have to replace some characters with underscores.
                            String tableColumn = COLUMN_PREFIX + columnName.replace('+', '_');
                            handleColumn(row, key, tableColumn, columnName, part);
                        }

                        addRow(row);


                    }


                }
                catch (IOException ioe) {
                    LOGGER.severe("Error reading output file: " + outputFile.getAbsolutePath() + ioe.getMessage());                                        
                }                
                finally{
                    if (in != null){
                        try{
                            in.close();
                        }
                        catch(Exception e){
                            LOGGER.severe("Error closing output file: " + outputFile.getAbsolutePath() + e.getMessage());
                        }
                    }     
//                    c_filled = true;
                }
            }
//        }                

    }
    private static final MessageFormat FORMAT_PERIODDATES = new MessageFormat("{0}-{1}/{2}/{3}");
    private static final MessageFormat FORMAT_ROTATIONYEARPERIOD = new MessageFormat("Rot. yr:{0}");
    private static final MessageFormat FORMAT_MONTHPERIOD = new MessageFormat("Month:{0}");
    private static final MessageFormat FORMAT_YEARPERIOD = new MessageFormat("Year:{0}");
    
    private void handleColumn(Object[] row, String key, String tableColumn, String columnName, String text) {        
        assert(tableColumn.contains(".")): "error: wrong value passed into handleColumn for tableColumn.";
        if (COLUMN_SDEDMOYR.equals(tableColumn)){
            //handle the dates
            if ("P".equals(key)){
                try {
                    //Period row, sd-ed/mo/yr                    
                    Object[] parts = FORMAT_PERIODDATES.parse(text);

                    int start = Integer.valueOf(parts[0].toString().trim());
                    int end = Integer.valueOf(parts[1].toString().trim());
                    int month = Integer.valueOf(parts[2].toString().trim());
                    month--;    //java months are 0 based
                    int year = Integer.valueOf(parts[3].toString().trim());

                    Calendar cal = Calendar.getInstance();
                    cal.set(year, month, start);
                    setRowValue(row, COLUMN_STARTDATE, new Date(cal.getTimeInMillis()));

                    cal.set(year, month, end);
                    setRowValue(row, COLUMN_ENDDATE, new Date(cal.getTimeInMillis()));

                } catch (ParseException pe) {
                    LOGGER.severe("Error parsing period date: " + text + pe.getMessage());
                }

            }
            else if ("Y".equals(key)){
                //rotation year row, Rot. yr: #
                try{
                    Object[] parts = FORMAT_ROTATIONYEARPERIOD.parse(text);
                    Integer period = Integer.valueOf(parts[0].toString().trim());
                    setRowValue(row, COLUMN_PERIOD, period);
                } catch (ParseException pe) {
                    LOGGER.severe("Error parsing rotation year period: " + text + pe.getMessage());
                }
            }
            else if ("m".equals(key)){
                //month row, Month:    #
                try{
                    Object[] parts = FORMAT_MONTHPERIOD.parse(text);
                    Integer period = Integer.valueOf(parts[0].toString().trim());
                    setRowValue(row, COLUMN_PERIOD, period);
                } catch (ParseException pe) {
                    LOGGER.severe("Error parsing rotation year period: " + text + pe.getMessage());
                }
            }
            else if ("y".equals(key)){
                //year row, Year:     #
                try{
                    Object[] parts = FORMAT_YEARPERIOD.parse(text);
                    Integer period = Integer.valueOf(parts[0].toString().trim());
                    setRowValue(row, COLUMN_PERIOD, period);
                } catch (ParseException pe) {
                    LOGGER.severe("Error parsing rotation year period: " + text + pe.getMessage());
                }
            }
            //T rows do nothing                
        }
        else if (COLUMN_OPERATION.equals(tableColumn)){            
            if (text != null && text.length() > 0){
                setRowValue(row, COLUMN_OPERATION, text);
            }
            
        }
        else if (COLUMN_CROP.equals(tableColumn)){
            if (text != null && text.length() > 0){
                setRowValue(row, COLUMN_CROP, text);
            }
        }
        else{                       
            try{
                Double value = Double.valueOf(text);
                Column column = c_meta.getColumn(columnName);

                //apply adjustments, some soil loss values need to be multiplied by -1
                if(column != null && column.getAdjustmentList() != null){
                    for(DataAdjustment adjust : column.getAdjustmentList()){
                        value = (Double) adjust.adjust(value);
                    }
                }


                

                if (isUSUnits() && c_siUnits.containsKey(tableColumn)){

                    ConversionUnit siUnit = c_siUnits.get(tableColumn);
                    ConversionUnit usUnit = c_usUnits.get(tableColumn);                    
                    value = ConversionCalculator.convert(value, siUnit, usUnit);                    
                }
                if (Math.abs(value) == 0){
                    value = 0d;
                }
                setRowValue(row, tableColumn, value);
                
                //handle limits

                if(column != null){
                    DataLimit limit = column.getLimit(isUSUnits() ? Util.USUnits : Util.SIUnits);
                    if(limit != null && findColumn(tableColumn + COLUMN_LOWER_LIMIT) > 0 ){
                        if(limit.outisdeLowerBound(value)){
                            setRowValue(row, tableColumn + COLUMN_LOWER_LIMIT, 1);                          
                        }
                        else{
                            setRowValue(row, tableColumn + COLUMN_LOWER_LIMIT, 0);
                        }
                    }
                    if(limit != null && findColumn(tableColumn + COLUMN_UPPER_LIMIT) > 0 ){
                        if(limit.outisdeUpperBound(value)){
                            setRowValue(row, tableColumn + COLUMN_UPPER_LIMIT, 1);                            
                        }
                        else{
                            setRowValue(row, tableColumn + COLUMN_UPPER_LIMIT, 0);
                        }
                       
                    }
                }
                                                    
            }
            catch(NumberFormatException nfe){
                //leave as null
                return;
            }
            catch(ConversionCalculator.ConversionNotFoundException e){
                        LOGGER.severe("Error converting value." + e.getMessage());
            }
            catch(Exception e){
                //likely not a valid column
                return;
            }
        }

        
        
    }
    

    
}