package usda.weru.weps;

import de.schlichtherle.io.File;
import de.schlichtherle.io.FileInputStream;
import de.schlichtherle.io.FileOutputStream;
import de.schlichtherle.io.FileReader;
import de.schlichtherle.io.FileWriter;
import java.util.*;
import javax.swing.*;
import java.beans.*;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.PrintWriter;
import java.lang.reflect.Field;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.List;
import javax.measure.unit.NonSI;
import org.apache.log4j.Logger;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.IllegalDataException;
import org.jdom.input.SAXBuilder;
import org.jdom.output.Format;
import org.jdom.output.XMLOutputter;
import org.jscience.geography.coordinates.LatLong;
import usda.weru.util.ConfigData;
import usda.weru.util.ExceptionEventQueue;
import usda.weru.util.FireAllContext;
import usda.weru.util.LoadingContext;
import usda.weru.util.PropertyStackContext;
import usda.weru.util.RelativeFileContext;
import usda.weru.util.RestoringContext;
import usda.weru.util.Util;
import usda.weru.util.WepsFileChooser;
import usda.weru.util.WepsMessage;
import usda.weru.util.WepsMessageLog;
import usda.weru.weps.location.CligenDataModel;
import usda.weru.weps.location.CligenStation;
import usda.weru.weps.location.ElevationMode;
import usda.weru.weps.location.FileStation;
import usda.weru.weps.location.InterpolatedStation;
import usda.weru.weps.location.Site.Country;
import usda.weru.weps.location.StationMode;
import usda.weru.weps.location.Station;
import usda.weru.weps.location.StationUtil;
import usda.weru.weps.location.WindgenDataModel;
import usda.weru.weps.location.WindgenStation;

/**
 * The "Run file Data" class/object manages, accesses, returns and updates data for the WEPS application
 * GUI where data modifications need to be propagated to different screens that have registered their
 * components to be recognized for any property changes that happen.
 *
 */
public class RunFileData implements PropertyChangeListener {

    private static final Logger LOGGER = Logger.getLogger(RunFileData.class);
    private WepsMessageLog c_log = new WepsMessageLog();
    protected boolean c_displayMessages = true;
    


    public static final double VERSION_WATER_EROSION = 1.01;
    public static final double VERSION_ROCK_FRAGMENTS = 1.02;
    public static final double VERSION_LOCPANEL_REWRITE = 1.03;
    public static final double VERSION_LOCPANEL_SITE = 1.04;
    public static final double VERSION_RELATIVE_PATHS = 1.05;
    //The current version is written out when a file is saved.
    public static final double VERSION_CURRENT = VERSION_RELATIVE_PATHS;
    /**
     * All the project files have this extension after the file names i:e file extension to be used.
     */
    public static final String ProjectSuffix = ".wpj";
    /**
     * All the "RUN" files have this extension after their file names i:e file extension to be used.
     */
    public static final String RunSuffix = ".wjr";
    /**
     * The wind generation file's defaullt name with a ".win" extension for the file to be recognized
     */
    public static final String DefaultWinGenName = "win_gen.win";
    /**
     * The climate generation file's defaullt name with a ".cli" extension for the file to be recognized
     */
    public static final String DefaultCliGenName = "cli_gen.cli";
    /**
     * * Default name for the daily submodel name of the Wind file to be used in MCREW.
     *
     */
    public static final String WarningsFile = "warnings.txt";
    public static final String DefaultSubDailyWindName = "none";
    /**
     * Default name for the management file to be used in MCREW.
     */
    public static final String DefaultManageFileName = "none";
    /**
     * Default name for the soil file to be used in SOIL UI.
     */
    public static final String DefaultSoilFileName = "none";
    /**
     * All the IFC Template files are placed in this directory.
     */
    public static final String IFCTemplateDir = "{IFCTemplateDir}";
    /**
     * The name of the directory where the management template files reside.
     */
    public static final String ManTemplateDir = "{ManTemplateDir}";
    /**
     * The name of "RUN" file used for the WEPS run
     */
    public static final String WepsRun = "weps.run";
    /**
     * The WEPS data file used to store all the initialization information for the GUI
     * when its first executed.
     */
    public static final String WepsData = "weps.ini";
    /**
     * A temporary output file name for the run file output to be stored.
     */
//    public static final String HCOutputFileName = "output.tmp";
    /**
     * Default name to be assigned to a new project if saved without any name.
     */
    public static final String UntitledProject = "untitled.wpj";
    /**
     * name of the Notes text file used to save management file level notes or notes
     * from the notes section provided in the WEPS screen.
     */
    public static final String NotesFileName = "notes.txt";
    /**
     * Error file name to be used for re-directing the erros codes or messages if any generated.
     */
    public static final String StdErr = "stderr.txt";
    /**
     * The text messages from the standard output such as screns dialogs which need to be saved are
     * directed to this file.
     */
    public static final String StdOut = "stdout.txt";
    /**
     * The output file for the calibration mode parameter for the harvest file.
     */
    public static final String CalibFileName = "harvest_calib_parm.out";
    /**
     * Data file name for the WEPS GUI related stored data
     */
    public static final String WepsOutput = "gui1_data.out";
    public static final String RFD = "RFD-";
    /**
     * The string used to fire the property changes using this stsndard text as one of the
     * input parameter.
     */
    public static final String FireProperty = RFD + "FireProperty";
    /**
     * The username to be used in the application
     */
    public static final String UserName = RFD + "UserName";
    /**
     * The farm identification number. Often an individual operator will have more than one
     * farm and therefore more than one farm number. It is saved as part of the WEPS Run and appears on the
     * summary and other output reports. This information is not required for a simulation run but may be
     * useful in identifying specific WEPS Runs and output
     */
    public static final String FarmId = RFD + "FarmId";
    /**
     * Often used by FSA and NRCS to identify a field. It is a unit of contiguous land that has both of the following:
     * (1) under one ownership, and (2) operated as a farm or a part of a farm. It is saved as part of a WEPS Run and
     * appears on the summary and other output reports. This information is not required for a simulation run but may
     * be useful in identifying specific WEPS Runs and output.
     */
    public static final String TractId = RFD + "TractId";
    /**
     * The "Field No." is a part of a tract that is separated by permanent boundaries, such as: (1) fences, (2) permanent waterways,
     * (3) woodlands, (4) croplines not subject to change because of farming practices, and (5) other similar features. It is saved
     * as part of the WEPS Run and appears on the summary and other output reports. This information is not required for a simulation
     * run but may be useful in identifying specific WEPS Runs and output
     */
    public static final String FieldId = RFD + "FieldId";
//    public static final String SiteState=RFD + "SiteState";  // still used for weps.run file documentation - LEW
    //public static final String SiteCounty = RFD + "SiteCounty";  // still used for weps.run file documentation - LEW
    /**
     * String that stores the text for the state name in run file data.
     */
    public static final String State = RFD + "StateUpdate";
    /**
     * String that stores the text for the site name in  run file data.
     */
    @RunFileDataBeanBridge.BeanProperty(RunFileBean.PROP_SITE)
    public static final String Site = RFD + "Site";
    /**
     * String used to compare against the latitude data usually used to set/modify latitude values.
     * @deprecated
     */
    @Deprecated
    public static final String Latitude = RFD + "Latitude";
    /**
     * String used to compare against the latitude sign and if changed is used to re-set/modify that latitude
     * sign values.
     * @deprecated
     */
    @Deprecated
    public static final String LatitudeSign = RFD + "LatitudeSign";
    /**
     * String used to coompare against the longitude data usually used to set/modify longitude values.
     * @deprecated
     */
    @Deprecated
    public static final String Longitude = RFD + "Longitude";
    /**
     * String used to coompare against the longitude sign and if changed is used to re-set/modify that longitude
     * sign values.
     * @deprecated
     */
    @Deprecated
    public static final String LongitudeSign = RFD + "LongitudeSign";
    /**
     * The latitude nad longitude signs and information for their directions.
     */
    @RunFileDataBeanBridge.BeanProperty (RunFileBean.PROP_LATLONG)
    public static final String LatLong = RFD + "LatLong";

    @RunFileDataBeanBridge.BeanProperty (RunFileBean.PROP_ELEVATION_MODE)
    public static final String RFD_ELEVATION_MODE = RFD + "elevation.mode";    


    /**
     * THe elevation above sea level for the specified station
     */
    @RunFileDataBeanBridge.BeanProperty (RunFileBean.PROP_ELEVATION)
    public static final String Elevation = RFD + "Elevation";
    /**This string will be "0" (by default) and will be "1"
     * if an alternate Climate File is used - neha
     */
    @RunFileDataBeanBridge.BeanProperty (RunFileBean.PROP_CLIGEN_STATION_MODE)
    public static final String ClimateFlag = RFD + "ClimateFlag";
    /**
     * The selected name of the climate generation station.
     * @deprecated 
     */
    @Deprecated
    public static final String CliGenStationName = RFD + "CliGenStationName";	// string
    /**
     * Name of the state in which tbis particular climate generation station exists.
     * @deprecated
     */
    @Deprecated
    public static final String CliGenState = RFD + "CliGenState";		
    /**
     * numeric id of the Climate generation station
     * @deprecated
     */
    @Deprecated
    public static final String CliGenStation = RFD + "CliGenStation";	// numeric

    
    @RunFileDataBeanBridge.BeanProperty (RunFileBean.PROP_CLIGEN_STATION)
    public static final String CligenStation = RFD + "cligen.station";	//handled by the mode
    /**
     * This string will be "0" (by default) and will be "1" if an alternate Wind File is used - neha     
     */
    @RunFileDataBeanBridge.BeanProperty (RunFileBean.PROP_WINDGEN_STATION_MODE)
    public static final String WindFlag = RFD + "WindFlag";
    /**
     * Name of the Wind generation station
     * @deprecated
     */
    @Deprecated
    public static final String WindGenStationName = RFD + "WindGenStationName";	// string
    /**
     * Numeric id of the Wind generation station
     * @deprecated 
     */
    @Deprecated
    public static final String WinGenStation = RFD + "WinGenStation";	// numeric
    @RunFileDataBeanBridge.BeanProperty (RunFileBean.PROP_WINDGEN_STATION)
    public static final String WindgenStation = RFD + "windgen.station";  //handled by the mode
    /**
     * The date from which you want the simulation to begin.
     */
    public static final String StartDate = RFD + "StartDate";
    /**
     * The date on which you want the simulation to end.
     */
    public static final String EndDate = RFD + "EndDate";
    /**
     * The number of years in which the crop cycle needs to be rotated.
     */
    public static final String RotationYears = RFD + "RotationYears";
    /**
     * The current count before the cycle is started over again.
     */
    public static final String CycleCount = RFD + "CycleCount";
    /**
     * The steps in which you can increment the time interval.
     */
    public static final String TimeSteps = RFD + "TimeSteps";
//	public static final String CliGen				= RFD + "CliGen";
//	public static final String WinGen				= RFD + "WinGen";
//	public static final String SubDaily				= RFD + "SubDaily";
    /**
     * The name of the current SOIL file selected.
     */
    public static final String SoilFile = RFD + "SoilFile";
    /**
     * The name of the current management file selected.
     */
    public static final String ManageFile = RFD + "ManageFile";
    /**
     * The name of the current output file.
     */
    public static final String OutputFile = RFD + "OutputFile";
    /**
     * The name of the report form.
     */
    public static final String ReportForm = RFD + "ReportForm";
    /**
     * Tells when the output period is.
     */
    public static final String OutputPeriod = RFD + "OutputPeriod";
    /**
     * Tells what the submodel output is.
     */
    public static final String SubmodelOutput = RFD + "SubmodelOutput";
    /**
     * Tells what the debug output is.
     */
    public static final String DebugOutput = RFD + "DebugOutput";
    /**
     * Value used for calculated SCI.
     */
    public static final String WaterErosionLoss = RFD + "WaterErosionLoss";
    /**
     * Value used to overide soil layer rock fragments
     */
    public static final String SoilRockFragments = RFD + "SoilRockFragments";
    /**
     * Indicates the simulation region angle assigned.
     */
    public static final String RegionAngle = RFD + "RegionAngle";
    private static final String SimPoint1 = RFD + "SimPoint1";
    private static final String SimPoint2 = RFD + "SimPoint2";
    private static final String Scales = RFD + "Scales";
    private static final String AccNo = RFD + "AccNo";
    private static final String AccPoint1 = RFD + "AccPoint1";
    private static final String AccPoint2 = RFD + "AccPoint2";
    private static final String SubregionNo = RFD + "SubregionNo";
    private static final String SubPoint1 = RFD + "SubPoint1";
    private static final String SubPoint2 = RFD + "SubPoint2";
    /**
     * The average slope of the field/area in study.
     */
    public static final String AverageSlope = RFD + "AverageSlope";
    private static final String BarrierNo = RFD + "BarrierNo";
//	private static final String BarrierInput		= RFD + "Barrier-";
    /**
     * The string used to compare and identify for something with barrier panel.
     */
    public static final String Barrier = RFD + "Barrier";
    /**
     * The string used to compare and identify north barrier for selection/de-selection.
     */
    public static final String BarrierN = RFD + "BarrierN";
    /**
     * The string used to compare and identify west barrier for selection/de-selection.
     */
    public static final String BarrierW = RFD + "BarrierW";
    /**
     * The string used to compare and identify south barrier for selection/de-selection.
     */
    public static final String BarrierS = RFD + "BarrierS";
    /**
     * The string used to compare and identify east barrier for selection/de-selection.
     */
    public static final String BarrierE = RFD + "BarrierE";
    /**
     * The string used to compare and identify none barrier for selection/de-selection.
     */
    public static final String BarrierD = RFD + "BarrierD";
    /**
     * Area of the simulation region in the units of measure displayed on the screen (acres or hectares)
     * based upon the "X" length and "Y" length values. X-Length happens to be the breadth of the field.
     */
    public static final String XLength = RFD + "XLength";
    /**
     * Area of the simulation region in the units of measure displayed on the screen (acres or hectares)
     * based upon the "X" length and "Y" length values. Y-Length happens to be the length of the field.
     */
    public static final String YLength = RFD + "YLength";
    /**
     * Shape of the simulation region.
     */
    public static final String Shape = RFD + "Shape";
    /**
     * Shape of the simulation region.
     */
    public static final String Radius = RFD + "Radius";
    /**
     * The name of the wind file.
     * @deprecated 
     */
    @Deprecated
    public static final String WindFile = RFD + "wind file";
    /**
     * The name of the climate file.
     * @deprecated 
     */
    @Deprecated
    public static final String ClimateFile = RFD + "climate file";
    /**
     * The name of the sub-daily file.
     */
    public static final String SubDailyFile = RFD + "sub-daily file";
    //	public static final String TotalYrsPlusCyl	= RFD + "TotalYearsPlusCycle";
    /**
     * Number of years for which the simulation needs to be carried out.
     */
    public static final String TotalYears = RFD + "TotalYears";
    /**
     * The notes files name.
     */
    public static final String NotesFile = RFD + "NotesFile";
    /**
     * The text that goes into the notes file and in the notes text area of the GUI like
     * additional information regarding the current WEPS run which the user wishes to record.
     */
    @RunFileDataBeanBridge.BeanProperty (RunFileBean.PROP_NOTES)
    public static final String NotesText = RFD + "NotesText";
    public static final String NotesReadonly = RFD + "NotesReadOnly";
    /**
     * String used to identify the run type to be displayed.
     */
    public static final String RunTypeDisp = RFD + "runtypedisp";
    /**
     * Tells the user what the last WEPS run was by storing its name.
     */
    public static final String LastRun = RFD + "lastrun";
    /**
     * Tells the location for storing runs.
     */
    public static final String RunsLocation = RFD + "runs location";
    /**
     * Most recent run attempt
     */
    public static final String LastRunAttempt = RFD + "last run attempt";
    /**
     * Used to identify the instance of data changed on the panel registerd to react.
     */
    public static final String DataChanged = "DataChanged " + RFD;
    /**
     * The data from "weps.ini" file which is the hash table containing the details of Project.
     */
    public static final String WriteRunData = "WriteRunData";
    /**
     * The  "weps.ini" file which contains the hash table containing the details of Project.
     */
    public static final String WriteRunFile = "WriteRunFile";
    /**
     * The data to be read for the WESP run usually from the weps.ini file or for m the hashtable
     * that stores it.
     */
    public static final String ReadRunData = "ReadRunData";
    /**
     * The file that contains this WEPS run data is called the readrunfile.
     */
    public static final String ReadRunFile = "ReadRunFile";
    /**
     * The WEPS run data that gets the request to be shown.
     */
    public static final String ShowRunData = "ShowRunData";
//	public static final String ClearData			= "ClearData";
    /**
     * Fired before and after fireAll().  1 = before, 2 = after
     */
    public static final String LoadData = "LoadData";


    public static final String ResetBarriers = "reset barriers";
    /**
     * Hashtable used to store weps.run file data internally
     */
    Hashtable<String, String> ht = new Hashtable<String, String>(200);
    // Jan 31 02 dkm no current man ===> zero years, ERRATA01
    // May 09 02
    private String curProj = "";
    private String NRCSRunLen = "";
    // This variable is to store the elevation of the Restore Run
    private String restoreRunElevation = "";
    public File fileObject = null;

    /**
     * This methods reads the data from the WEPS.ini file and shows it.  Errors will be shown in a WepsMessageDialog
     * @param pathName The path where this file resides on the system..
     */
    public RunFileData(String pathName) {
        this(pathName, true);
    }

    /** This methods reads the data from the WEPS.ini file and shows it.
     * @param pathName The path where this file resides on the system.
     * @param displayMessages If true, errors and warnings will be displayed in a WepsMessageDialog.
     */
    public RunFileData(String pathName, boolean displayMessages) {        
        c_displayMessages = displayMessages;
        readRunFile(pathName);
        //showRunFileData("after file read Constructor");
    }

    /**
     * Initializes the WEPS RUN data.
     */
    public RunFileData() {
        this(true);
    }

    public RunFileData(boolean initialize) {
        if(initialize){
            initialize();
        }
    }

    /**
     * Entry point for testing standalone. Used if this dialog is rum as an independent application.
     * If executed, makes the GUI for Simulation Region panel visible.
     * @param args These are the command line arguments passed to the main method.
     */
    static public void main(String args[]) {
        WepsFileChooser wfc = new WepsFileChooser(WepsFileChooser.PROJECT, "",
                WepsFileChooser.OPEN);
        wfc.setCurrentDirectory(new de.schlichtherle.io.File("h:/weps/weps.install/projects"));  // temp testing fix

        RunFileData rfd = new RunFileData();
        if (wfc.showDialog(null) == JFileChooser.APPROVE_OPTION) {
            de.schlichtherle.io.File sf = new File(wfc.getSelectedFile());
            String projectsDir = "";
            try {
                projectsDir = sf.getCanonicalPath();
            } catch (IOException e) {
            }//System.err.println(
            //      "Error getting canoncial path of projectsDir");}

            rfd.readRunData(projectsDir);
        } else {
            rfd.initialize();
        }
        rfd.showRunFileData("Standalone test");
        System.exit(1);
    }

    /**
     * This is the method where all the WEPS main GUI initialization takes place with the
     * default dataset used for intial display.
     */
    public void initialize() {



            setData(RunTypeDisp, ConfigData.getDefault().getData(ConfigData.DefaultRunMode));

            setData(UserName, "");
            setData(FarmId, "");
            setData(TractId, "");
            setData(FieldId, "");
    //		setData(SiteState, "KS");
            
            getBean().setSite(usda.weru.weps.location.Site.valueOf("fips:US00-KS-055"));    
    //		setData(SiteCounty, "FINNEY");

            setData(LatLong, "+38.00;-100.66");

            ////default to the cligen mode, only one working at the moment.
            getBean().setElevationMode(ElevationMode.Cligen);

            setData(Elevation, "801.0");
            setData(CliGenState, "");
            setData(CliGenStation, "");
            //setData(WinGenStation, "");
            setData(StartDate, "01 01 2001");
            setData(EndDate, "31 12 2001");
            setData(RotationYears, "1");
            setData(CycleCount, "50");
            setData(TotalYears, "6");
            setData(TimeSteps, "24");
            setData(SubDailyFile, DefaultSubDailyWindName);
            setData(SoilFile, DefaultSoilFileName);
            setData(ManageFile, DefaultManageFileName);
    //        setData(OutputFile, HCOutputFileName);
            setData(ReportForm, "0 0 0 0 0 0");
            setData(OutputPeriod, "2");
            setData(SubmodelOutput, "0 0 0 0 0 0");
            setData(DebugOutput, "0 0 0 0 0 0");
            setData(RegionAngle, "0");
            setData(SimPoint1, "100.0 100.0");
            setData(SimPoint2, "904.7 904.7");
            setData(Scales, "10.0 0.25");
            setData(AccNo, "1");
            setData(AccPoint1, "100.0 100.0");
            setData(AccPoint2, "904.7 904.7");
            setData(SubregionNo, "1");
            setData(SubPoint1, "100.0 100.0");
            setData(SubPoint2, "904.7 904.7");

            //A negative slope is ignored by WEPS
            setData(AverageSlope, "-1");
            changes.firePropertyChange(ResetBarriers, null, null);
            setData(BarrierNo, "0");
            setData(BarrierN, "none|0.0|0.0|0.0");
            setData(BarrierS, "none|0.0|0.0|0.0");
            setData(BarrierE, "none|0.0|0.0|0.0");
            setData(BarrierW, "none|0.0|0.0|0.0");

    //        setData(ClimateFlag, ConfigData.getDefault().getData(ConfigData.ClimateFlag));
    //        setData(WindFlag, ConfigData.getDefault().getData(ConfigData.WindFlag));
            getBean().setCligenStationMode(StationMode.NRCS);
            getBean().setWindgenStationMode(StationMode.NRCS);
            setData(CliGenStationName, "CIMARRON");
            //setData(WindGenStationName, "GARDEN CITY MUNI");
            setData(CliGenState, "14");
            setData(CliGenStation, "1522");
            //setData(WinGenStation, "724515");
            setData(NotesReadonly, "0");
            setData(NotesFile, NotesFileName);
            setData(NotesText, "", false);  // The "\n" is getting stripped off so text appended is not starting on a new line - this is a quick fix - LEW
            // setData(NotesText, "Enter WEPS Run notes here.\n", false);  //1148, added added false value so the string is not trimmed.

            setData(Shape, "rectangle");
            setData(Radius, "0");
            setData(LastRunAttempt, "");
            //Defaults to the config value
            if (!RestoringContext.isRestoring()){
                setData(RunsLocation, ConfigData.getDefault().getData(ConfigData.DefaultRunsLocation));
            }
            setData(WaterErosionLoss, "0.00");

            setData(SoilRockFragments, "0.0");

            fixUpData();
            changes.firePropertyChange(DataChanged, null, "xxx");
            
            

    }

    public String getData(String idxstr) {
        String s = (String) ht.get(idxstr);
        return s;
    }

    public void setData(final String idxstr, String newData, boolean trimNewData) {
        //String propertyName = c_rfdToBeanProp.get(idxstr);
//        Object oldBeanValue = null;
//        if (propertyName != null) {
//            oldBeanValue = getBeanValue(propertyName);
//        }

        PropertyStackContext.enter(this, idxstr);
        try{
            String oldData = "";

            if (idxstr.equals(FireProperty)) {
                oldData = (String) ht.get(newData);
                changes.firePropertyChange(newData, null, oldData);
                return;
            }


            if (newData == null) {
                oldData = ht.get(idxstr);
                ht.remove(idxstr);
            } else {
                if (trimNewData) {
                    newData = newData.trim();      //1148, only trim when told to.

                }
                oldData = (String) ht.get(idxstr);
                if (newData.equals(oldData)) {
                    return;
                }
                ht.put(idxstr, newData);
            }

    //        if (propertyName != null) {
    //            fireBeanPropertyEvent(propertyName, oldBeanValue);
    //        }

            changes.firePropertyChange(idxstr, oldData, newData);
            changes.firePropertyChange(DataChanged, null, DataChanged);
        }
        finally{
            PropertyStackContext.exit(this, idxstr);
        }

    }

//    private Object getBeanValue(String propertyName) {
//
//        try {
//            String firstCharacter = propertyName.substring(0, 1);
//            firstCharacter = firstCharacter.toUpperCase();
//
//            propertyName = firstCharacter + propertyName.substring(1);
//
//            Method m = null;
//            //try getter
//            try {
//                m = RunFileData.class.getMethod("get" + propertyName, (Class[])null);
//            } catch (NoSuchMethodException nsme) {
//                //try is
//                try {
//                    m = RunFileData.class.getMethod("is" + propertyName, (Class[]) null);
//                } catch (NoSuchMethodException nsme2) {
//                    //do nothing.
//                }
//            }
//
//
//
//            //invoke
//            if (m != null) {
//                return m.invoke(this);
//            }
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
//        return null;
//    }
//
//    private void fireBeanPropertyEvent(String propertyName, Object oldValue) {
//        Object newValue = getBeanValue(propertyName);
//        changes.firePropertyChange(propertyName, oldValue, newValue);
//    }

    //1148, overiding method to pass a default true for trimNewData
    public void setData(String idxstr, String newData) {
        setData(idxstr, newData, true);
    }



    public void fireAll() {
        FireAllContext.enter();
        try{
            Enumeration e = ht.keys();
            changes.firePropertyChange(DataChanged, null, "fireall");
            changes.firePropertyChange(LoadData, null, "1");

            while (e.hasMoreElements()) {
                Object key = e.nextElement();
                Object value = ht.get(key);

                changes.firePropertyChange((String) key, null, value);

            }

            changes.firePropertyChange(DataChanged, null, "fireall");
            changes.firePropertyChange(LoadData, null, "2");
        }
        finally{
            FireAllContext.exit();
        }

    }

    public void fireAll(PropertyChangeListener... listeners) {
        FireAllContext.enter();
        try{
            Enumeration e = ht.keys();

            for (PropertyChangeListener listener : listeners) {
                PropertyChangeEvent event1 = new PropertyChangeEvent(this, DataChanged, null, "fireall");
                PropertyChangeEvent event2 = new PropertyChangeEvent(this, LoadData, null, 1);
                listener.propertyChange(event1);
                listener.propertyChange(event2);

            }
            while (e.hasMoreElements()) {
                Object key = e.nextElement();
                Object value = ht.get(key);
                PropertyChangeEvent event = new PropertyChangeEvent(this, (String) key, null, value);
                for (PropertyChangeListener listener : listeners) {
                    listener.propertyChange(event);
                }
            }

            for (PropertyChangeListener listener : listeners) {
                PropertyChangeEvent event1 = new PropertyChangeEvent(this, DataChanged, null, "fireall");
                PropertyChangeEvent event2 = new PropertyChangeEvent(this, LoadData, null, 2);
                listener.propertyChange(event1);
                listener.propertyChange(event2);
            }
        }
        finally{
            FireAllContext.exit();
        }
    }

    private String getLine(BufferedReader in) throws IOException {
        String temp;
        while ((temp = in.readLine()) != null) {
            if (temp.length() == 0) {
                return temp;
            }
            if (temp.charAt(0) != '#') {
                return temp;
            }
        }
        return null;
    }

    /**
     * Sets the integer value to the rotation year's attribute from the management file provided
     * as an argument path where it exists on the system.
     * @param manageFile The management file that stores this integer value that is used for setting.
     */
    public void setRotationYears(String manageFile) {
        //We need to have a file to work with.
        if (manageFile == null || manageFile.equals("none") || manageFile.length() == 0) {
            return;
        }
        try {
            BufferedReader in = new BufferedReader(new FileReader(
                    new File(manageFile)));

            String temp;
            while ((temp = in.readLine()) != null) {
                if (temp.startsWith("*START")) {
                    StringTokenizer st = new StringTokenizer(temp);
                    st.nextToken();
                    String rotationYears = st.nextToken().trim();
                    in.close();
                    setData(RunFileData.RotationYears, rotationYears);
                    changes.firePropertyChange(RunFileData.RotationYears, null, rotationYears);
                    /* Value of Rotation Years in int
                    Integer rotInt = new Integer(1);
                    int rotYears = rotInt.parseInt(rotationYears);
                    //System.out.println("Value of rotYears is:"+rotYears);
                     */
                    return;
                }
            }

            //System.err.println("RFD_sRY: '*START' not found in management file");
            changes.firePropertyChange(RunFileData.RotationYears, null, "1");
            in.close();
            return;

        } catch (IOException e) {
            //System.err.println("RFD_sRY: " + e);
        }
    }

    private void readRunFileBarriers(BufferedReader in) throws java.io.IOException {
        //Awful hack to get the draw field to work.
        changes.firePropertyChange(ResetBarriers, null, null);

        //Initially set all the barrier data to "none"
        setData(BarrierN, "none|0.0|0.0|0.0");
        setData(BarrierS, "none|0.0|0.0|0.0");
        setData(BarrierE, "none|0.0|0.0|0.0");
        setData(BarrierW, "none|0.0|0.0|0.0");

        String temp = getLine(in);
        int barrierNo = (new Integer(temp.trim())).intValue();
        if (barrierNo == 0) {		// throw away dummy barrier

            for (int jdx = 0; jdx < 6; jdx++) {
                getLine(in);
            }
            return;
        }
        String temp1 = getData(SimPoint1);
        String temp2 = getData(SimPoint2);
        StringTokenizer st = new StringTokenizer(temp1, " ");
        String rx1 = st.nextToken();
        double Rx1 = Double.parseDouble(rx1);
        String ry1 = st.nextToken();
        double Ry1 = Double.parseDouble(ry1);
        st = new StringTokenizer(temp2, " ");
        String rx2 = st.nextToken();
        double Rx2 = Double.parseDouble(rx2);
        String ry2 = st.nextToken();
        double Ry2 = Double.parseDouble(ry2);

        for (int idx = 0; idx < barrierNo; idx++) {
            String line = getLine(in);
            st = new StringTokenizer(line, "| ");
            String bx1 = st.nextToken();
            double Bx1 = Double.parseDouble(bx1);
            String by1 = st.nextToken();
            double By1 = Double.parseDouble(by1);
            line = getLine(in);
            st = new StringTokenizer(line, "| ");
            String bx2 = st.nextToken();
            double Bx2 = Double.parseDouble(bx2);
            String by2 = st.nextToken();
            double By2 = Double.parseDouble(by2);
            StringBuffer sb = new StringBuffer(getLine(in).trim());
            for (int jdx = 0; jdx < 3; jdx++) {
                sb.append("|");
                sb.append(getLine(in).trim());
            }
            line = sb.toString();
            //    //System.out.println("readRunFileBarriers: Rx1:"+Rx1+"  Bx1:"+Bx1+"  Rx2:"+Rx2+"  Bx2:"+Bx2);
            //    //System.out.println("readRunFileBarriers: Ry1:"+Ry1+"  By1:"+By1+"  Ry2:"+Ry2+"  By2:"+By2);
            //		if (bx2.equals(rx1)) {
            if ((Ry1 == By1 && Ry2 == By2) || (Ry1 == By2 && Ry2 == By1)) {
                if (Rx1 == Bx1 || Rx1 == Bx2) {
                    setData(BarrierW, line);
                    //			} else if (bx1.equals(rx2)) {
                } else if (Rx2 == Bx1 || Rx2 == Bx2) {
                    setData(BarrierE, line);
                } else {
                    c_log.logMessage(WepsMessage.warningMessage("Unknown Barrier Position 1 " + line +
                            " field-bx1:" + bx1 + "   bx2:" + bx2 + "   by1:" + by1 + "  by2:" + by2 +
                            " barrier-rx1: " + rx1 + "   rx2:" + rx2 + "  ry1:" + ry1 + "  ry2:" + ry2));
//                    //System.err.println("RFD_rDFB: unknown barrier position 1 " + line +
//                            " field-bx1:" + bx1 + "   bx2:" + bx2 + "   by1:" + by1 + "  by2:" + by2 +
//                            " barrier-rx1: " + rx1 + "   rx2:" + rx2 + "  ry1:" + ry1 + "  ry2:" + ry2);
                }
            } else if ((Rx1 == Bx1 && Rx2 == Bx2) || (Rx1 == Bx2 && Rx2 == Bx1)) {
//			} else if (by2.equals(ry1)) {
                if (Ry1 == By1 || Ry1 == By2) {
                    setData(BarrierS, line);

//			} else if (by1.equals(ry2)) {
                } else if (Ry2 == By1 || Ry2 == By2) {
                    setData(BarrierN, line);
                } else {
                    c_log.logMessage(WepsMessage.warningMessage("Unknown Barrier Position 2 " + line +
                            " field-bx1:" + bx1 + "   bx2:" + bx2 + "   by1:" + by1 + "  by2:" + by2 +
                            " barrier-rx1: " + rx1 + "   rx2:" + rx2 + "  ry1:" + ry1 + "  ry2:" + ry2));

//                    //System.err.println("RFD_rDFB: unknown barrier position 2 " + line +
//                            " field-bx1:" + bx1 + "   bx2:" + bx2 + "   by1:" + by1 + "  by2:" + by2 +
//                            " barrier-rx1: " + rx1 + "   rx2:" + rx2 + "  ry1:" + ry1 + "  ry2:" + ry2);

                }
            } else {
                c_log.logMessage(WepsMessage.warningMessage("Unknown Barrier Position 3 " + line +
                        " field-bx1:" + bx1 + "   bx2:" + bx2 + "   by1:" + by1 + "  by2:" + by2 +
                        " barrier-rx1: " + rx1 + "   rx2:" + rx2 + "  ry1:" + ry1 + "  ry2:" + ry2));
//                //System.err.println("RFD_rDFB: unknown barrier position 3 " + line +
//                        " field-bx1:" + bx1 + "   bx2:" + bx2 + "   by1:" + by1 + "  by2:" + by2 +
//                        " barrier-rx1: " + rx1 + "   rx2:" + rx2 + "  ry1:" + ry1 + "  ry2:" + ry2);
            }
        }

    }

    private void readNotesFile(String runFilePathName) {
        String temp = "";
        StringBuffer sb = new StringBuffer();
        File file = new File(runFilePathName, NotesFileName);
        BufferedReader in = null;
        try {
            in = new BufferedReader(new FileReader(file));
            while ((temp = in.readLine()) != null) {
                sb.append(temp.trim() + "\n");
            }
        } catch (IOException e) {
            LOGGER.error("Error while reading notes file. " + file.getPath(), e);
        } finally {
            try {
                in.close();
            } catch (Exception e) {
                LOGGER.error("Error closing stream. " + file.getPath(), e);
            }
        }
        //}
        setData(NotesText, sb.toString());
    }
    private static final String VERSION_MARKER = "#VERSION=";

    /**
     * This method reads the data in the RUN file meant for the GUI initialization from the
     * existing set of values and makes it visible on the respective components of the interface.
     * @param runFilePathName The system path to the RUN file from where this data is retrieved.
     */
    public void readRunFile(String runFilePathName) {

        LoadingContext.enter();
        RelativeFileContext.enter(new File(runFilePathName));
        initialize();
        clearBean();
        try{


            //getBean().setLoading(true);
            c_log.clear();

            BufferedReader in = null;
            try {
                fileObject = new File(runFilePathName, WepsRun);
                if (!fileObject.exists()) {
                    LOGGER.warn("Run File \"" + fileObject.getAbsolutePath() + "\" does not exist.");
                    return;
                }
                in = new BufferedReader(new FileReader(fileObject));
                double version = 1.00;  //Default when the version of the file is not included.

                String firstLine = in.readLine();
                if (firstLine == null) {
                    return;
                }
                firstLine = firstLine.trim();
                if (firstLine.startsWith(VERSION_MARKER)) {
                    firstLine = firstLine.replace(VERSION_MARKER, "");
                    version = Double.parseDouble(firstLine);
                }

                setData(UserName, getLine(in));
                {
                    String temp = getLine(in);
                    StringTokenizer st = new StringTokenizer(temp, "|");
                    if (st.countTokens() < 3) {
                        setData(FarmId, temp);
                        setData(TractId, "");
                        setData(FieldId, "");
                        setData(RunFileData.RunTypeDisp, ConfigData.Dates);
    //					changes.firePropertyChange(RunFileData.RunTypeDisp, RunType,
    //										 ConfigData.Dates);
                    } else if (st.countTokens() == 3) {
                        setData(FarmId, st.nextToken().trim());
                        setData(TractId, st.nextToken().trim());
                        setData(FieldId, st.nextToken().trim());
                        setData(RunFileData.RunTypeDisp, ConfigData.Dates);
    //					changes.firePropertyChange(RunFileData.RunTypeDisp, RunType,
    //										 st.nextToken().trim());

    //					setData(RunFileData.RunTypeDisp, type);
                    } else {
    //					try {
                        setData(FarmId, st.nextToken().trim());
                        setData(TractId, st.nextToken().trim());
                        setData(FieldId, st.nextToken().trim());
                        String type = st.nextToken().trim();
                        setData(RunFileData.RunTypeDisp, type);
                        setData(RotationYears, st.nextToken());
                        setData(CycleCount, st.nextToken());
    //					} catch (ArrayIndexOutOfBounds e) {
    //						//System.err.println("RFD_rRF: too few tokens in id line (should be 6) " +
    //										   temp);
    //					}
                    }
                }


                    String siteString = getLine(in);
                    if(version<VERSION_LOCPANEL_SITE){
                        //old site format
                        usda.weru.weps.location.Site site = upgradeSiteString(siteString);
                        setData(Site, site != null ? site.toString() : siteString);
                    }
                    else{
                        setData(Site, siteString);
                    }



                {
    //				String temp = getLine(in);
    //				setData(LatitudeSign, temp.startsWith("-") ? "-" : "+"); // Added below code for second conditional statement 01/16/2004
    //				setData(Latitude, temp.substring(temp.startsWith("-") ? 1 : ( temp.startsWith("+") ? 1 : 0 ) ));
    //				temp = getLine(in);
    //				setData(LongitudeSign, temp.startsWith("-") ? "-" : "+"); // // Added below code for second conditional statement 01/16/2004
    //				setData(Longitude, temp.substring(temp.startsWith("-") ? 1 : ( temp.startsWith("+") ? 1 : 0 ) ));
                    String latStr = getLine(in);
                    String longStr = getLine(in);
                    setData(LatLong, latStr.trim() + ";" + longStr.trim());
                }

                // This string is used to store the value of the Run's elevation value
                restoreRunElevation = getLine(in);
                setData(Elevation, restoreRunElevation);

                if (version >= VERSION_LOCPANEL_REWRITE) {
                    //new format delegated to StationModeHandlers
                    //cligen
                    String cligenLine = getLine(in);
                    int cligenModeIndex = cligenLine.indexOf("|");
                    String cligenModeText = cligenLine.substring(0, cligenModeIndex);
                    String cligenText = cligenLine.length() > cligenModeIndex ? cligenLine.substring(cligenModeIndex + 1) : null;

                    StationMode cligenMode = StationMode.parse(cligenModeText);
                    Station cligenStation = StationUtil.deserializeStation(cligenText);


                    getBean().setCligenStationMode(cligenMode);
                    getBean().setCligenStation(cligenStation);

                    //windgen
                    String windgenLine = getLine(in);
                    int windgenModeIndex = windgenLine.indexOf("|");
                    String windgenModeText = windgenLine.substring(0, windgenModeIndex);
                    String windgenText = windgenLine.length() > windgenModeIndex ? windgenLine.substring(windgenModeIndex + 1) : null;

                    StationMode windgenMode = StationMode.parse(windgenModeText);
                    Station windgenStation = StationUtil.deserializeStation(windgenText);

                    getBean().setWindgenStationMode(windgenMode);
                    getBean().setWindgenStation(windgenStation);

                } else {                    
                    //Handle the old station format, only supports choice (0) or file (1) or interpolated for windgen
                    //cligen                    
                    try{
                        String cligenLine = getLine(in);
                        String cligenParts[] = cligenLine.split("\\|");
                        StationMode cligenMode = StationMode.parse(cligenParts[3]);

                        getBean().setCligenStationMode(cligenMode);

                        if (StationMode.Choice == cligenMode) {
                            //choice station
                            String name = cligenParts[0];
                            long id = Long.valueOf(cligenParts[1].trim());
                            long state = Long.valueOf(cligenParts[2].trim());
                            CligenStation station = CligenDataModel.getInstance().getStation(state, id);
                            if(station == null){
                                LOGGER.warn("Unable to find cligen record in database. State: " + state + ", Id: " + id );
                                station = new CligenStation(name, state, id);
                            }
                            
                            getBean().setCligenStation(station);


                        } else if (StationMode.File == cligenMode) {
                            //file station
                            String name = cligenParts[0];
                            File file = new File(runFilePathName, name);
                            FileStation station = new FileStation(file);
                            getBean().setCligenStation(station);

                        } else {
                            //really not supposed to get here.
                        }
                    }
                    catch(Exception e){
                        LOGGER.warn("Unable to read old cligen station.", e);
                        getBean().setCligenStation(null);
                    }


                    //windgen                    
                    try{
                        String windgenLine = getLine(in);
                        String windgenParts[] = windgenLine.split("\\|");
                        StationMode windgenMode = StationMode.parse(windgenParts[2]);

                        getBean().setWindgenStationMode(windgenMode);

                        if (StationMode.Choice == windgenMode) {
                            //choice station
                            String name = windgenParts[0];
                            if(windgenParts[1].startsWith("I~")){
                                //this was an interpolated station
                                getBean().setWindgenStationMode(StationMode.Interpolated);
                                getBean().setWindgenStation(new InterpolatedStation(getBean().getLatLong()));
                            }
                            else{
                                long id = Long.valueOf(windgenParts[1].trim());
                                WindgenStation station = WindgenDataModel.getInstance().getStation(id);
                                if(station == null){
                                    LOGGER.warn("Unable to find windgen record in database. Id: " + id );
                                    station = new WindgenStation(null, id, null, null, name);
                                }
                                getBean().setWindgenStation(station);
                            }

                        } else if (StationMode.File == windgenMode) {
                            //file station
                            String name = windgenParts[0];
                            name = name != null ? name.trim() : name;
                            if("Interpolated".equalsIgnoreCase(name)){
                                //handle an interpolated file
                                getBean().setWindgenStationMode(StationMode.Interpolated);
                                getBean().setWindgenStation(new InterpolatedStation(getBean().getLatLong()));
                            }
                            else{
                                File file = new File(runFilePathName, name);
                                FileStation station = new FileStation(file);
                                getBean().setWindgenStation(station);
                            }
                        } else {
                            //really not supposed to get here.
                        }
                    }
                    catch(Exception e){
                        LOGGER.warn("Unable to read old windgen station.", e);
                        getBean().setWindgenStation(null);
                    }

                }

                setData(StartDate, getLine(in));
                setData(EndDate, getLine(in));
                setData(TimeSteps, getLine(in));
                setData(ClimateFile, getLine(in));
                setData(WindFile, getLine(in));
                setData(SubDailyFile, getLine(in));
                String fileName = getLine(in);
                if (!(new File(fileName)).isAbsolute()) {
                    fileName = new File(runFilePathName, fileName).getAbsolutePath();
                }
                final File soilFile = new File(fileName);
                if(!soilFile.exists()){
                    ExceptionEventQueue.invokeLater(new Runnable() {

                        @Override
                        public void run() {
                            JOptionPane pane = new JOptionPane("The referenced soil file is missing.\n" + soilFile.getAbsolutePath(), JOptionPane.WARNING_MESSAGE){

                                @Override
                                public int getMaxCharactersPerLineCount() {
                                    return 80;
                                }

                            };

                            JDialog dialog = pane.createDialog("Loading Run");
                            dialog.setVisible(true);
                        }
                    });
                    setData(SoilFile, "");
                }
                else{
                    setData(SoilFile, fileName);
                }
                
                fileName = getLine(in);
                if (!(new File(fileName)).isAbsolute()) {
                    fileName = new File(runFilePathName, fileName).getAbsolutePath();
                }
                final File manFile = new File(fileName);
                if(!manFile.exists()){
                    ExceptionEventQueue.invokeLater(new Runnable() {

                        @Override
                        public void run() {
                            JOptionPane pane = new JOptionPane("The referenced management file is missing.\n" + manFile.getAbsolutePath(), JOptionPane.WARNING_MESSAGE){

                                @Override
                                public int getMaxCharactersPerLineCount() {
                                    return 80;
                                }

                            };

                            JDialog dialog = pane.createDialog("Loading Run");
                            dialog.setVisible(true);
                        }
                    });
                    setData(ManageFile, "");
                }
                else{
                    setData(ManageFile, fileName);
                }

                setData(OutputFile, getLine(in));
                setData(ReportForm, getLine(in));
                setData(OutputPeriod, getLine(in));
                setData(SubmodelOutput, getLine(in));
                String s = getLine(in);
                setData(DebugOutput, s);
                setData(RegionAngle, getLine(in));
                setData(SimPoint1, getLine(in));
                setData(SimPoint2, getLine(in));
                setData(Scales, getLine(in));
                setData(AccNo, getLine(in));
                setData(AccPoint1, getLine(in));
                setData(AccPoint2, getLine(in));
                setData(SubregionNo, getLine(in));
                setData(SubPoint1, getLine(in));
                setData(SubPoint2, getLine(in));
                setData(AverageSlope, getLine(in));
                readRunFileBarriers(in);

                //Shape and radius information used by the user interface to approximate a rectangular field shape.
                // Placed in try in case the run file does not have the shape fields.
                try {
                    setData(Shape, getLine(in));
                } catch (NullPointerException e) {
                    setData(Shape, "rectangle");
                }

                //consume the radius line
                getLine(in);

                //Only read the value if the correct version.
                if (version >= VERSION_WATER_EROSION) {
                    double d = 0;
                    String temp = getLine(in);
                    try{
                            temp = temp != null ? temp.trim() : null;
                            if(temp != null){
                                d = Double.parseDouble(temp);
                            }
                    }
                    catch(Exception e){
                        LOGGER.debug("Unable to parse water erosion value: " + temp);
                    }


                    setData(WaterErosionLoss, String.valueOf(d));
                } else {
                    setData(WaterErosionLoss, "0");
                }

                //Only read the value if the correct version.
                if (version >= VERSION_ROCK_FRAGMENTS) {
                    setData(SoilRockFragments, getLine(in));
                } else {
                    setData(SoilRockFragments, "0.0");
                }



            } catch (IOException e) {
                LOGGER.error("unable to read run file: \"" + runFilePathName + "\"", e);
            } catch (java.lang.NullPointerException f) {
                JOptionPane.showMessageDialog(null,
                        "Error loading run file",
                        "Error (RFD-001)",
                        JOptionPane.ERROR_MESSAGE);
                f.printStackTrace();
                return;
            } finally {
                try {
                    if (in != null) {
                        in.close();
                    }
                } catch (Exception e) {
                    LOGGER.error("Error closing file stream.", e);
                }
            }
            readNotesFile(runFilePathName);
            fixUpData();
            changes.firePropertyChange(DataChanged, null, "xxx");
            fireAll();
            setData(Elevation, restoreRunElevation);

            //fire that we have finished loading the data
            //getBean().setLoading(false);
        }
        finally{            
            RelativeFileContext.exit();
            LoadingContext.exit();
        }

    }

    private void fixUpData() {

        /* add additional factors */
        String temp1 = getData(SimPoint1);
        String temp2 = getData(SimPoint2);
        double x1 = 0.0;
        double y1 = 0.0;
        double x2 = 0.0;
        double y2 = 0.0;

        StringTokenizer st = new StringTokenizer(temp1);
        try {
            x1 = new Double(st.nextToken()).doubleValue();
            y1 = new Double(st.nextToken()).doubleValue();
            st = new StringTokenizer(temp2);
            x2 = new Double(st.nextToken()).doubleValue();
            y2 = new Double(st.nextToken()).doubleValue();
        } catch (NumberFormatException e) {
            //System.err.println("fUD: " + e);
            x1 = 0.0;
            y1 = 0.0;
            x2 = 0.0;
            y2 = 0.0;
        }
        double Xlen = Math.abs(x1 - x2);
        double Ylen = Math.abs(y1 - y2);
        
        
        NumberFormat nf = NumberFormat.getNumberInstance();
        nf.setMaximumFractionDigits(1);
        nf.setGroupingUsed(false);

        String shape = getData(Shape);
        if(shape.startsWith("circle")){
            double radius = Math.sqrt((Xlen * Ylen) / Math.PI);
            setData(Radius, nf.format(radius));
        }
        else if (shape.startsWith("half_circle_v")) {
            double radius = Math.sqrt((Xlen *  Ylen * 2) / Math.PI);
            setData(Radius, nf.format(radius));
        }
        else if (shape.startsWith("quarter_circle")) {
            double radius = Math.sqrt((Xlen *  Ylen * 4) / Math.PI);
            setData(Radius, nf.format(radius));
        }
        
        setData(XLength, nf.format(Xlen));
        setData(YLength, nf.format(Ylen));
    }

    private String makeBarrier(String barPos, String barData) {

        if (barPos.equals(BarrierD)) {
            return "0.0 0.0" + java.lang.System.getProperty("line.separator") +
                    "0.0 0.0" + java.lang.System.getProperty("line.separator") +
                    "none" + java.lang.System.getProperty("line.separator") +
                    "0.0" + java.lang.System.getProperty("line.separator") +
                    "0.0" + java.lang.System.getProperty("line.separator") +
                    "0.0";
        }

        // get points for sim region

        String temp1 = getData(SimPoint1);
        String temp2 = getData(SimPoint2);
        double x1 = 0.0;
        double y1 = 0.0;
        double x2 = 0.0;
        double y2 = 0.0;

        StringTokenizer st = new StringTokenizer(temp1);
        try {
            x1 = new Double(st.nextToken()).doubleValue();
            y1 = new Double(st.nextToken()).doubleValue();
            st = new StringTokenizer(temp2);
            x2 = new Double(st.nextToken()).doubleValue();
            y2 = new Double(st.nextToken()).doubleValue();
        } catch (NumberFormatException e) {
            //System.err.println("RFD_mB: " + e);
            x1 = 0.0;
            y1 = 0.0;
            x2 = 0.0;
            y2 = 0.0;
            return "Error in makeBarrier -- can't get field dimensions";
        }

        st = new StringTokenizer(barData, "|");
        String type = st.nextToken();
        double widthDouble = 0.0;
        String height = st.nextToken();
        String width = st.nextToken();
        try {
            widthDouble = new Double(width).doubleValue();
        } catch (NumberFormatException e) {
            //System.err.println("RFD_mB: " + e);
        }
        String porosity = st.nextToken();
        String x1s = "0.0";
        String x2s = "0.0";
        String y1s = "0.0";
        String y2s = "0.0";

        NumberFormat nf = NumberFormat.getNumberInstance();

        /* Since the fraction digits for the Simulation region co-ordinates is 2,
         ** the barrier co-ordinates SHOULD also have fraction digits of 2.
         ** Otherwise, they wont match while displaying the barriers.- added by Neha.
         */
        nf.setMaximumFractionDigits(2);
        nf.setGroupingUsed(false);

        if (barPos.equals(BarrierN)) {
            x1s = nf.format(x1);
            y1s = nf.format(y2);
            x2s = nf.format(x2);
            y2s = nf.format(y2 + widthDouble);
        } else if (barPos.equals(BarrierS)) {
            x1s = nf.format(x1);
            y1s = nf.format(y1 - widthDouble);
            x2s = nf.format(x2);
            y2s = nf.format(y1);
        } else if (barPos.equals(BarrierE)) {
            x1s = nf.format(x2);
            y1s = nf.format(y1);
            x2s = nf.format(x2 + widthDouble);
            y2s = nf.format(y2);
        } else if (barPos.equals(BarrierW)) {
            x1s = nf.format(x1 - widthDouble);
            y1s = nf.format(y1);
            x2s = nf.format(x1);
            y2s = nf.format(y2);
        }

        return x1s + " " + y1s + java.lang.System.getProperty("line.separator") +
                x2s + " " + y2s + java.lang.System.getProperty("line.separator") +
                type + java.lang.System.getProperty("line.separator") +
                height + java.lang.System.getProperty("line.separator") +
                width + java.lang.System.getProperty("line.separator") +
                porosity;
    }

    /**
     * This method writes the modifications done or text inserted to the notes text field/area in the
     * file that preserves it.
     * @param dir The system path to the directory where this file exists.
     */
    public void writeNotesFile(String dir) {


        //Disabled large note files quick fix.
        //String value = getData(NotesReadonly);
        //if (value != null && value.equals("1")) return;
        PrintWriter out = null;
        try {
            out = new PrintWriter(new BufferedWriter(new FileWriter(
                    new File(dir, RunFileData.NotesFileName))));

            String notes = getData(NotesText);
            out.println(notes);
        } catch (IOException e) {
            //System.err.println("RFD_wNF: " + e);
        } finally {
            try {
                out.close();
            } catch (Exception e) {
                LOGGER.error("Error closing file stream", e);
            }
        }
    }

    /**
     * This method updates to the newly inserted date values in the dates column of the interface.
     */
    public void updateDates() {
        String runType = getData(RunTypeDisp);
        if (runType.equals(ConfigData.Dates)) {
            String sD = getData(StartDate);
            // //System.out.println("RFD_uD: START DATE is :" + sD);  // TESTING
            String eD = getData(EndDate);
            // //System.out.println("RFD_uD: END DATE is :" + eD);  // TESTING
            StringTokenizer st = new StringTokenizer(sD);
            st.nextToken();
            st.nextToken();
            sD = st.nextToken();
            // //System.out.println("RFD_uD: START DATE after TOKEN is :" + sD); // TESTING
            st = new StringTokenizer(eD);
            st.nextToken();
            st.nextToken();
            eD = st.nextToken();
            ////System.out.println("RFD_uD: END DATE after TOKEN is :" + eD); // TESTING
            //String totYrs = "" + ( Integer.parseInt(eD) * Integer.parseInt(sD) ); ///CHANGED by MANMOHAN .. 12/31/2003
            String totYrs = "" + ((Integer.parseInt(eD) - Integer.parseInt(sD)) + 1);
            ////System.out.println("RFD_uD: Total Years are :" + totYrs); // TESTING
            setData(TotalYears, totYrs);
        } else {
            if (runType.equals(ConfigData.NRCS)) {
                setData(CycleCount, NRCSRunLen);
            }
            setData(StartDate, "01 01 01");
            String numYrs = getData(RotationYears);
            String numCyl = getData(CycleCount);
            int nY = Integer.parseInt(numYrs);
            int nC = Integer.parseInt(numCyl);
            setData(EndDate, "31 12 " + (nY * nC));
            String totYrs = "" + (nY * nC);
            setData(TotalYears, totYrs);
        }

    }

    /**
     * This method creates the "weps.run" file in the run directory.
     * @param runDirPath The system path string to this run directory.
     */
    public void writeRunFile(String runDirPath) {
        PrintWriter out = null;
        File runDir = new File(runDirPath);
        RelativeFileContext.enter(runDir);
        try {
            out = new PrintWriter(new BufferedWriter(new FileWriter(new File(runDir, WepsRun))));
            int count = 0;
            //First line is now a version line
            NumberFormat versionFormat = NumberFormat.getNumberInstance();
            versionFormat.setMaximumFractionDigits(2);
            out.println(VERSION_MARKER + versionFormat.format(VERSION_CURRENT));
            out.println("#------------ WEPS SIMULATION RUN FILE ------------");
            out.println("# Note: Lines beginning with '#' are comment lines.");
            out.println("#       Lines beginning with '#   RFD' are comments used by the interface.");
            out.println("#");
            out.println("# --USER INFORMATION");
            out.println("#   " + UserName);
            out.println(getData(UserName));
            out.println("#   " + FarmId + " " + TractId + " " + FieldId + " " + RunTypeDisp + " " + RotationYears + " " + CycleCount);
            out.println(getData(FarmId) + " | " + getData(TractId) + " | " +
                    getData(FieldId) + " | " + getData(RunTypeDisp) + " | " +
                    getData(RotationYears) + " | " + getData(CycleCount));
//            out.println("#   " + SiteCounty + ", " + SiteState);
//			out.println(getData(SiteCounty) + ", " + getData(SiteState));
            out.println("#   " + Site);
            usda.weru.weps.location.Site site = getBean().getSite();
            out.println(site != null ? site.toString() : "");
            out.println("#");
            out.println("# --SITE INFORMATION");
            //print out the parts of LatLong
            LatLong latlong = getBean().getLatLong();
            NumberFormat latlongFormat = new DecimalFormat("+0.00;-0.00");
            out.println("#   Signed Latitude");
            out.println(latlongFormat.format(latlong.latitudeValue(NonSI.DEGREE_ANGLE)));
            out.println("#   Signed Longitude");
            out.println(latlongFormat.format(latlong.longitudeValue(NonSI.DEGREE_ANGLE)));

            out.println("#   " + Elevation + "(meters)");
            out.println(getData(Elevation));

            //cligen
            out.println("#   " + ClimateFlag + "|" + CligenStation);
            //the new station mode model handles serializing the station for each mode.
            StationMode cligenMode = getBean().getCligenStationMode();
            Station cligenStation = getBean().getCligenStation();
            if(cligenStation instanceof FileStation && cligenStation != null){
                File file = ((FileStation)cligenStation).getFile();
                cligenStation = new FileStation(new File(runDir, file.getName()));
            }
            out.println(cligenMode.getName() + "|" + StationUtil.serializeStation(cligenStation));

            //windgen
            out.println("#   " + WindFlag + "|" + WindgenStation);
            //the new station mode model handles serializing the station for each mode.
            StationMode windgenMode = getBean().getWindgenStationMode();
            Station windgenStation = getBean().getWindgenStation();
            if(windgenStation instanceof FileStation && windgenStation != null){
                File file = ((FileStation)windgenStation).getFile();
                windgenStation = new FileStation(new File(runDir, file.getName()));
            }
            out.println(windgenMode.getName() + "|" + StationUtil.serializeStation(windgenStation));


            out.println("#");
            out.println("# --SIMULATION PERIOD");
            out.println("#   " + StartDate + "(day month year)");
            out.println(getData(StartDate));
            out.println("#   " + EndDate + "(day month year)");
            out.println(getData(EndDate));
            out.println("#   " + TimeSteps + "(per day)");
            out.println(getData(TimeSteps));
            out.println("#");
            out.println("# --RUN FILE FILENAMES (INPUT)");
            out.println("#   " + ClimateFile);
            if (cligenStation instanceof FileStation) {
                FileStation fileStation = (FileStation) cligenStation;
                out.println(fileStation.getFile().getName());
            } else {
                out.println(DefaultCliGenName);
            }
            out.println("#   " + WindFile);
            //if it is a file station we use the name of the file, else we use the default name            
            if (windgenStation instanceof FileStation) {
                FileStation fileStation = (FileStation) windgenStation;
                out.println(fileStation.getFile().getName());
            } else if (windgenStation instanceof InterpolatedStation) {
                out.println("interpolated.win");
            } else {
                out.println(DefaultWinGenName);
            }
            out.println("#   " + SubDailyFile);
            out.println("none");
            out.println("#   " + SoilFile);
            out.println((new File(getData(SoilFile)).getName()));
            out.println("#   " + ManageFile);
            out.println((new File(getData(ManageFile)).getName()));
            out.println("#");
            out.println("# --WEPS OUTPUT OPTIONS");
            out.println("#   " + OutputFile);
            out.println(getData(OutputFile));
            out.println("#   " + ReportForm);
            out.println(getData(ReportForm));
            out.println("#   " + OutputPeriod);
            out.println(getData(OutputPeriod));
            out.println("#   " + SubmodelOutput);
            out.println(getData(SubmodelOutput));
            out.println("#   " + DebugOutput);
            out.println(getData(DebugOutput));
            out.println("#");
            out.println("# --SIMULATION REGION INFORMATION");
            out.println("#   " + RegionAngle + "(degrees clockwise from North)");
            out.println(getData(RegionAngle));
            out.println("#   Origin coordinates of simulation region (meters)");
            out.println("0.0  0.0");
            setData(SimPoint1, "0.0 0.0");
            out.println("#    " + XLength + "(meters)" + "  " + YLength + "(meters)");
            String xLength = getData(XLength);
            String yLength = getData(YLength);
            out.println(xLength + "  " + yLength);
            setData(SimPoint2, xLength + "  " + yLength);
            out.println("#   " + Scales + "(place holder line - needed for older versions of WEPS)");
            out.println("5.5 5.5");
            out.println("#");
            out.println("#   " + AccNo);
            out.println(getData(AccNo));
            out.println("#   Accounting region coordinates (meters)");
            out.println("    0.0  0.0");
            out.println(xLength + "  " + yLength);
            out.println("#");
            out.println("#   " + SubregionNo);
            out.println(getData(SubregionNo));
            out.println("#   Subregion region coordinates (meters)");
            out.println("0.0  0.0");
            out.println(xLength + "  " + yLength);
            out.println("#   " + AverageSlope + "(ratio m/m)");
            out.println(getData(AverageSlope));
            // out.println("#   Barriers");
            int barrierCnt = 0;
            if (!getData(BarrierN).startsWith("none|")) {
                barrierCnt++;
            }
            if (!getData(BarrierS).startsWith("none|")) {
                barrierCnt++;
            }
            if (!getData(BarrierE).startsWith("none|")) {
                barrierCnt++;
            }
            if (!getData(BarrierW).startsWith("none|")) {
                barrierCnt++;
            }
            out.println("#   " + BarrierNo);
            out.println(barrierCnt);
            if (barrierCnt == 0) {
                out.println(makeBarrier(BarrierD, ""));
            } else {
                String barrier = getData(BarrierN);
                if (barrier.length() > 0 && !barrier.startsWith("none|")) {
                    out.println("#   " + BarrierN + " coordinates (meters)" + " | type" + " | height (meters)" + " | width (meters)" + " | porosity");
                    out.println(makeBarrier(BarrierN, barrier));
                }
                barrier = getData(BarrierW);
                if (barrier.length() > 0 && !barrier.startsWith("none|")) {
                    out.println("#   " + BarrierW + " coordinates (meters)" + " | type" + " | height (meters)" + " | width (meters)" + " | porosity");
                    out.println(makeBarrier(BarrierW, barrier));
                }
                barrier = getData(BarrierE);
                if (barrier.length() > 0 && !barrier.startsWith("none|")) {
                    out.println("#   " + BarrierE + " coordinates (meters)" + " | type" + " | height (meters)" + " | width (meters)" + " | porosity");
                    out.println(makeBarrier(BarrierE, barrier));
                }
                barrier = getData(BarrierS);
                if (barrier.length() > 0 && !barrier.startsWith("none|")) {
                    out.println("#   " + BarrierS + " coordinates (meters)" + " | type" + " | height (meters)" + " | width (meters)" + " | porosity");
                    out.println(makeBarrier(BarrierS, barrier));
                }
            }
            out.println("#");
            out.println("# --CIRCULAR FIELD INFORMATION");
            out.println("# Note: These fields are not used by the weps simulation.");
            out.println("#       The shape and radius values are used by the user ");
            out.println("#       interface to approximate a rectangular field.  They");
            out.println("#       are included here so the reports can display the ");
            out.println("#       correct field shape.");
            out.println("#");
            out.println("#   " + Shape);
            out.println(getData(Shape));
            out.println("#   " + Radius);
            out.println(getData(Radius));
            out.println("#   " + WaterErosionLoss);
            out.println(getData(WaterErosionLoss));
            out.println("#   " + SoilRockFragments);
            out.println(getData(SoilRockFragments));
            out.println("#---------- END OF SIMULATION RUN FILE ------------");
            writeNotesFile(runDirPath);
        } catch (IOException e) {
            //System.err.println("RunFileData: " + e);
        } finally {
            RelativeFileContext.exit();
            try {
                out.close();
            } catch (Exception e) {
                LOGGER.error("Error closing stream", e);
            }
        }
        changes.firePropertyChange(WriteRunFile, null, "xxx");
    }

    /**
     * This method reads the file "weps.ini" in the project directory specified
     *  in the path "runFilePathName" into hashtable "ht".
     * @param runFilePathName The system path string to this run file directory.
     */
    @SuppressWarnings("unchecked") // Element.getChildren is not checked
    public void readRunData(String runFilePathName) {
        fileObject = new File(runFilePathName);
        File runData = new File(runFilePathName, WepsData);
        if(!runData.exists()){
            initialize();
            writeRunDataXML(runFilePathName);
        }
        RelativeFileContext.enter(new File(runFilePathName));
        LoadingContext.enter();
        try{

            if (runFilePathName.length() == 0) {
                runFilePathName = curProj;
            }

        


            Map<String, String> temp = new HashMap<String, String> ();
            boolean write = false;
            //first try the xml
            try {
                readRunDataXML(runData, temp);
                //now set all the data
            } catch (Exception e) {
                //xml failed, maybe it's really old in the binary format?
                LOGGER.info("Could not read weps.ini file as an XML document.  Will try using old binary format.");
                try {
                    readRunDataBinary(runData, temp);
                    write = true;
                } catch (Exception ex) {
                    //oh snap, even the binary failed.
                }
            }

            //getBean().setLoading(true);
            try {
                //Handle a few cases first                
                prioritySetData(temp, RunFileData.LatLong);
                prioritySetData(temp, RunFileData.ClimateFlag);
                prioritySetData(temp, RunFileData.CligenStation);
                prioritySetData(temp, RunFileData.WindFlag);
                prioritySetData(temp, RunFileData.WindgenStation);
                


                for (Map.Entry<String, String> entry : temp.entrySet()) {
                    setData(entry.getKey(), entry.getValue());
                }
                //fixup the cligen/windgen modes
                String climateMode = temp.get(RunFileData.ClimateFlag);
                if(climateMode != null && climateMode.trim().length() == 0){
                    getBean().setCligenStationMode(null);
                }

                String windgenMode = temp.get(RunFileData.WindFlag);
                if(windgenMode != null && windgenMode.trim().length() == 0){
                    getBean().setWindgenStationMode(null);
                }
            } finally {
               // getBean().setLoading(false);
            }
            if (write) {
                writeRunDataXML(runFilePathName);
            }
        }
        finally{
            LoadingContext.exit();
            RelativeFileContext.exit();
        }

    }

    private void prioritySetData(Map<String, String> map, String property){
        String value = map.get(property);
        setData(property, value);        
    }

    private void readRunDataXML(File file, Map<String, String> temp) throws Exception {
        RelativeFileContext.enter(new File(file.getParentFile()));
        LoadingContext.enter();
        clearBean();
        try{
            SAXBuilder in = new SAXBuilder();
            Document doc;
            Element root = null;
            //use the stream so zipped files will work
            doc = in.build(new FileInputStream(file));
            if (doc != null) {
                root = doc.getRootElement();
            } else {
                throw new RuntimeException("no runFileData doc");
            }
            double version = 0;
            try {
                version = Double.valueOf(root.getAttributeValue("version"));
            } catch (Exception e) {
                //no version number;
                version = 0;
            }
            for (Element element : (List<Element>) root.getChildren("key")) {
                String key = element.getAttributeValue("name");
                String value = element.getText();
                temp.put(key, value);
            }

            //upgrade data
            upgradeData(temp, version);


            //clean data
            cleanData(temp);
        }
        finally{
            LoadingContext.exit();
            RelativeFileContext.exit();

        }

    }

    private void readRunDataBinary(File file, Map<String, String> temp) throws Exception {
        LoadingContext.enter();
        try{
            ObjectInputStream objStream = null;
            try {

                FileInputStream inStream = null;
                try {
                    inStream = new FileInputStream(file);
                } catch (java.io.FileNotFoundException fnfe) {
                    LOGGER.info("Run file data not found. " + file.getPath());
                    initialize();
                    return;
                }

                objStream = new ObjectInputStream(inStream);
                //Load the file into a temp location.

                Hashtable<String, String> tempHashtable = (Hashtable<String, String>) objStream.readObject();
                for (Map.Entry<String, String> entry : tempHashtable.entrySet()) {
                    String key = entry.getKey();
                    if (key.equals(RunsLocation)) {
                        continue;
                    }
                    String value = entry.getValue();
                    temp.put(key, value);
                }
                upgradeData(temp, 0);
                cleanData(temp);

            } finally {
                try {
                    if (objStream != null) {
                        objStream.close();
                    }
                } catch (Exception e) {
                    LOGGER.error("Error closing file stream. " + file.getPath(), e);
                }
            }
        }
        finally{
            LoadingContext.exit();
        }
    }



    private void upgradeData(Map<String, String> map, double version) {

        if (version < VERSION_LOCPANEL_REWRITE) {
            //need to upgrade the station values
            //CLIGEN
            StationMode cligenMode = StationMode.parse(map.get(ClimateFlag));

            //convert id to name
            map.put(WindFlag, cligenMode.getName());

            Station cligenStation = null;
            switch (cligenMode) {
                case Choice:
                    try {
                        long cligenId = Long.valueOf(map.get(CliGenStation));
                        long cligenState = Long.valueOf(map.get(CliGenState));
                        //try to find a station for the give id
                        cligenStation = CligenDataModel.getInstance().getStation(cligenState, cligenId);

                    } catch (Exception e) {
                        //oh snap
                    }


                    break;
                case File:
                    String cligenFilePath = map.get(WindFile);
                    if (cligenFilePath != null) {
                        cligenStation = new FileStation(new File(cligenFilePath));
                    }
                    break;
                default:
                    //unexpected old mode
                    break;
            }

            String cligenStationSer = StationUtil.serializeStation(cligenStation);
            map.put(CligenStation, cligenStationSer);
            //END CLIGEN

            //WINDGEN
            StationMode windgenMode = StationMode.parse(map.get(WindFlag));

            //convert id to name
            map.put(WindFlag, windgenMode.getName());

            Station windgenStation = null;
            switch (windgenMode) {
                case Choice:
                    try {
                        long windgenId = Long.valueOf(map.get(WinGenStation));
                        //try to find a station for the give id
                        windgenStation = WindgenDataModel.getInstance().getStation(windgenId);

                    } catch (Exception e) {
                        //oh snap
                    }


                    break;
                case File:
                    String windgenFilePath = map.get(WindFile);
                    if (windgenFilePath != null) {
                        windgenStation = new FileStation(new File(windgenFilePath));
                    }
                    break;
                default:
                    //unexpected old mode
                    break;
            }

            String windgenStationSer = StationUtil.serializeStation(windgenStation);
            map.put(WindgenStation, windgenStationSer);
            //END WINDGEN

            

        }

        if(version < VERSION_LOCPANEL_SITE){
            //site

            usda.weru.weps.location.Site site = upgradeSiteString(map.get(Site));
            if(site != null){
                map.put(Site, site.toString());
            }            
        }

        if(version < VERSION_RELATIVE_PATHS){
            File projectFile = new File(curProj);

            //need to fix up paths that might not be valid for soil and management
            String soilPath = map.get(SoilFile);
            File soilFile = new File(soilPath);

            if(!soilFile.exists()){
                soilFile = new File(projectFile, soilFile.getName());
                if(soilFile.exists()){
                    map.put(SoilFile, soilFile.getPath());
                    LOGGER.info("Resolved missing absolute soil file to relative path.");
                }
            }
            
            String managePath = map.get(ManageFile);
            File manageFile = new File(managePath);

            if(!manageFile.exists()){
                manageFile = new File(projectFile, manageFile.getName());
                if(manageFile.exists()){
                    map.put(ManageFile, manageFile.getPath());
                    LOGGER.info("Resolved missing absolute management file to relative path.");
                }
            }


        }
        else{   //Need to take the realtive paths and convert to absolute so the interface still works
            File projectFile = new File(curProj);
            String soilPath = map.get(SoilFile);
            File soilFile = new File(projectFile, soilPath);
            map.put(SoilFile, soilFile.getPath());
            
            String managePath = map.get(ManageFile);
            File manageFile = new File(projectFile, managePath);
            map.put(ManageFile, manageFile.getPath());
            
        }

    }



    private usda.weru.weps.location.Site upgradeSiteString(String oldSiteString){
            String parts[] = oldSiteString.split(",");
            String countyName = parts[0].trim();
            String stateName = parts[1].trim();

            Country usa = Country.UNITED_STATES;
            usda.weru.weps.location.Site temp = null;
            for(usda.weru.weps.location.Site state : usa.getSubDivisions()){
                if(state.getDisplayName().equalsIgnoreCase(stateName)){
                    temp = state;
                    break;
                }
            }

            if(temp != null){
                for(usda.weru.weps.location.Site county : temp.getSubDivisions()){
                    if(county.getDisplayName().equalsIgnoreCase(countyName)){
                        temp = county;
                        break;
                    }
                }
            }

            return temp;


    }

    private void cleanData(Map<String, String> map) {
        for (Field field : RunFileData.class.getFields()) {
            if (field.getType().equals(String.class) && field.isAnnotationPresent(Deprecated.class)) {
                try {
                    String key = (String) field.get(this);
                    map.remove(key);
                    LOGGER.info("Deprecated RunFileData Key: " + key);
                } catch (Exception e) {
                }
            }
        }
    }

    /**
     * Updates the data into the initialization RUN file the user modifications done on the screen
     * which is a basically a hashtable contiaining the details of the project.
     * @param runFilePathName The system path string to this run file directory where the screen data resides.
     */
    public void writeRunDataXML(String runFilePathName) {

        cleanData(ht);
//		updateDates();
        if (runFilePathName.length() == 0) {
            runFilePathName = curProj;
            /** Create file "weps.ini" in the Project directory specified in the
             * path "runFilePathName". Write into this "weps.ini" file the
             * hash table containing the details of Project.
             */
        }
        File runData = new File(runFilePathName, WepsData);
        File runFolder = new File(runFilePathName);
        RelativeFileContext.enter(runFolder);
        try{

            Element root = new Element("weps");
            //add the version number so when read in we know how to handle station values
            root.setAttribute("version", String.valueOf(VERSION_CURRENT));
            for (Map.Entry<String, String> entry : ht.entrySet()) {
                try {
                    Element param = new Element("key");
                    String key = entry.getKey();
                    param.setAttribute("name", key);
                    String value = entry.getValue();
                    if(value != null && (RunFileData.SoilFile.equals(key) || RunFileData.ManageFile.equals(key))){
                        //if soil or manage file make relative paths

                        File valueFile = new File(value);
                        valueFile = Util.resolveFileAsRelativeChildOrAbsolute(runFolder, valueFile);
                        value = valueFile.getPath();

                    }
                    param.setText(value != null ? value : "");
                    root.addContent(param);
                } catch (IllegalDataException ide) {
                    LOGGER.warn("Unable to save data element.  Some data may be missing or corrupted. " + ide.getMessage());
                }
            }
            FileOutputStream stream = null;
            try {
                XMLOutputter out = new XMLOutputter(Format.getPrettyFormat());
                stream = new FileOutputStream(runData);
                out.output(root, stream);
                stream.close();
            } catch (IOException ex) {
                LOGGER.error("Error writing run data.", ex);
            } finally {
                if (stream != null) {
                    try {
                        stream.close();
                    } catch (Exception ex) {
                    }
                }
            }
        }
        finally{
            RelativeFileContext.exit();
        }
    }

    /**
     * Removes the files/directories that contain the RUN data.
     * @param dir The directory that contains the RUN data that will be removed.
     * @return True if the directory is deleted else false.
     */
    public boolean removeRunData(File dir) {
        return Util.deleteAll(dir);
    }

    /**
     * Displays information about the object on the console for use in debugging.
     * @param msg The message to be shown/displayed.
     */
    public void showRunFileData(String msg) {
        //System.err.println("---------------------------------------------");
        //System.err.println("sRFD " + msg + " " + ht.size());
        Enumeration e = ht.keys();
        while (e.hasMoreElements()) {
            Object key = e.nextElement();
            Object value = ht.get(key);
            //System.err.println(((String) key) + "=" + ((String) value));
        }
        //System.err.println("=============================================");
    }
    /**
     * RunFileData throws a property change each time setData is called.
     * Wrapper classes listen to determine if the the event is relevant to
     * them.
     */
    private PropertyChangeSupport changes = new PropertyChangeSupport(this);
    

    /**
     * Allows the container to add or register some other components to recognize the changes that occur
     * on this component.
     * @param l The listener that listens and reacts towards the the changes to be reflected.
     */
    public void addPropertyChangeListener(PropertyChangeListener l) {
        changes.addPropertyChangeListener(l);
    }

    public void addPropertyChangeListener(String propertyName, PropertyChangeListener l) {
        changes.addPropertyChangeListener(propertyName, l);
    }

    /**
     * Allows the container to remove or de-register some other components and stop recognizing the
     * changes that occur on this component.
     * @param l The listener that does not listen and react towards the the changes to be reflected.
     */
    public void removePropertyChangeListener(PropertyChangeListener l) {
        changes.removePropertyChangeListener(l);
    }

    public void removePropertyChangeListener(String propertyName, PropertyChangeListener l) {
        changes.removePropertyChangeListener(propertyName, l);
    }
    




    /**
     * Recognizes and takes appropriate actions on registered properties from different
     * screens to update and synchronize data and GUI screens as needed.
     * @param e The event itself that is responsible for triggering the change required for registered
     * properties/components.
     */
    public void propertyChange(PropertyChangeEvent e) {

        String idxstr = e.getPropertyName();
        if (!idxstr.startsWith(RFD)) { 	// not a rfd file value

            if (idxstr.equals(WriteRunData)) {
                writeRunDataXML((String) e.getNewValue());
            } else if (idxstr.equals(WriteRunFile)) {
                writeRunFile((String) e.getNewValue());
            } else if (idxstr.equals(ReadRunData)) {
                readRunData((String) e.getNewValue());
            } else if (idxstr.equals(ReadRunFile)) {
                readRunFile((String) e.getNewValue());
            } else if (idxstr.equals(ShowRunData)) {
                showRunFileData((String) e.getNewValue());
            } else if (idxstr.equals(ConfigData.CurrentProj)) {
                curProj = Util.parse(e.getNewValue().toString());
            } else if (idxstr.equals(ConfigData.NRCSRunLen)) {
                NRCSRunLen = (String) e.getNewValue();
            } else if (idxstr.equals(ConfigData.OutputFreq)) {
                setData(OutputPeriod, (String) e.getNewValue());
            } else if (idxstr.equals(RunFileData.ClimateFlag)) {
                setData(ClimateFlag, (String) e.getNewValue());
            } else if (idxstr.equals(RunFileData.WindFlag)) {
                setData(WindFlag, (String) e.getNewValue());
            } else if (idxstr.equals(ConfigData.OPHydroDet)) {
                setDetailFlags(idxstr, (String) e.getNewValue());
            } else if (idxstr.equals(ConfigData.OPCropDet)) {
                setDetailFlags(idxstr, (String) e.getNewValue());
            } else if (idxstr.equals(ConfigData.OPDecompDet)) {
                setDetailFlags(idxstr, (String) e.getNewValue());
            } else if (idxstr.equals(ConfigData.OPErosionDet)) {
                setDetailFlags(idxstr, (String) e.getNewValue());
            } else if (idxstr.equals(ConfigData.OPManageDet)) {
                setDetailFlags(idxstr, (String) e.getNewValue());
            } else if (idxstr.equals(ConfigData.OPSoilDet)) {
                setDetailFlags(idxstr, (String) e.getNewValue());
            } else if (idxstr.equals(ConfigData.OPHydroDbg)) {
                setDebugFlags(idxstr, (String) e.getNewValue());
            } else if (idxstr.equals(ConfigData.OPCropDbg)) {
                setDebugFlags(idxstr, (String) e.getNewValue());
            } else if (idxstr.equals(ConfigData.OPDecompDbg)) {
                setDebugFlags(idxstr, (String) e.getNewValue());
            } else if (idxstr.equals(ConfigData.OPErosionDbg)) {
                setDebugFlags(idxstr, (String) e.getNewValue());
            } else if (idxstr.equals(ConfigData.OPManageDbg)) {
                setDebugFlags(idxstr, (String) e.getNewValue());
            } else if (idxstr.equals(ConfigData.OPSoilDbg)) {
                setDebugFlags(idxstr, (String) e.getNewValue());
            }

            return;
        }
        String valstr = (String) e.getNewValue();
        setData(idxstr, valstr);
        if (idxstr.equals(ManageFile)) {
            setRotationYears(valstr);
        }
    }

    private void setDebugFlags(String flag, String value) {
        int m_flag = 0;
        if (flag.equals(ConfigData.OPHydroDbg)) {
            m_flag = 0;
        } else if (flag.equals(ConfigData.OPSoilDbg)) {
            m_flag = 1;
        } else if (flag.equals(ConfigData.OPManageDbg)) {
            m_flag = 2;
        } else if (flag.equals(ConfigData.OPCropDbg)) {
            m_flag = 3;
        } else if (flag.equals(ConfigData.OPDecompDbg)) {
            m_flag = 4;
        } else if (flag.equals(ConfigData.OPErosionDbg)) {
            m_flag = 5;
        }
        String flags = getData(DebugOutput);
        flags = flags != null ? flags : "";
        String[] m_flags = flags.split("\\s");
        if (m_flags.length < 6) {
            m_flags = Arrays.copyOf(m_flags, 6);
            for (int i = 0; i < m_flags.length; i++) {
                if (m_flags[i] == null) {
                    m_flags[i] = "0";
                }
            }
        }
        m_flags[m_flag] = value;

        StringBuffer sb = new StringBuffer();
        for (String s : m_flags) {
            sb.append(s + " ");
        }
        setData(DebugOutput, sb.toString().trim());
    }

    private void setDetailFlags(String flag, String value) {
        int m_flag = 0;
        if (flag.equals(ConfigData.OPHydroDet)) {
            m_flag = 0;
        } else if (flag.equals(ConfigData.OPSoilDet)) {
            m_flag = 1;
        } else if (flag.equals(ConfigData.OPManageDet)) {
            m_flag = 2;
        } else if (flag.equals(ConfigData.OPCropDet)) {
            m_flag = 3;
        } else if (flag.equals(ConfigData.OPDecompDet)) {
            m_flag = 4;
        } else if (flag.equals(ConfigData.OPErosionDet)) {
            m_flag = 5;
        }
        String flags = getData(SubmodelOutput);
        flags = flags != null ? flags : "";
        String[] m_flags = flags.split("\\s");
        if (m_flags.length < 6) {
            m_flags = Arrays.copyOf(m_flags, 6);
            for (int i = 0; i < m_flags.length; i++) {
                if (m_flags[i] == null) {
                    m_flags[i] = "0";
                }
            }
        }
        m_flags[m_flag] = value;

        StringBuffer sb = new StringBuffer();
        for (String s : m_flags) {
            sb.append(s + " ");
        }
        setData(SubmodelOutput, sb.toString().trim());
    }

    public Set<String> keySet() {
        if (ht != null) {
            return ht.keySet();
        } else {
            return null;
        }
    }


    private RunFileBean c_bean;

    private synchronized void clearBean(){
        //getBean().clear();
    }

    public synchronized RunFileBean getBean(){
        if(c_bean == null){
            c_bean = new RunFileBean();
            //link the two together
            RunFileDataBeanBridge.bridge(this, c_bean);
        }
        return c_bean;
    }

}
