/* Title: ConfigData.java
 * author : Sada, Manmohan
 * date : Feb 2003
 * recently modified on: Aug 2003
 */
package usda.weru.mcrew;

import com.klg.jclass.cell.JCCellEditor;
import com.klg.jclass.cell.JCCellRenderer;
import com.klg.jclass.table.*;
import com.klg.jclass.cell.renderers.*;
import com.klg.jclass.cell.editors.*;
import de.schlichtherle.truezip.file.TFile;
import de.schlichtherle.truezip.file.TFileReader;
import java.awt.Color;
import java.awt.Font;
import java.beans.*;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.UTFDataFormatException;
import java.util.*;

//import org.apache.xerces.parsers.DOMParser;
import org.w3c.dom.*;
import org.w3c.dom.traversal.*;

//XML
import javax.xml.xpath.*;
import org.xml.sax.*;

//Font
import java.text.*;
import java.util.Map.Entry;
import org.apache.log4j.Logger;
import org.jdom2.JDOMException;
import org.jdom2.input.SAXBuilder;
import usda.weru.util.Caster;
import usda.weru.util.ConfigData;
import usda.weru.util.Util;

/**
 * This class holds the configuration data. It holds information from
 * 'mcrewconfig.xml'. It also has the list of operation and crop meta
 * objects constructed from operation_defn, croo_defn.. file
 */
public class MCREWConfig {

    private static final Logger logger = Logger.getLogger(MCREWConfig.class);
    private static final String IS_LISTENING = "MCREW_DATA_IS_LISTENING";
    private static boolean listeningTest = false;
    //public static String sDefaultStartfile = "weps_mcrew_cfg";
    /**
     * Default configuration file that defines the basic outline of the MCREW
     * table and the files it refers for organizing the data.
     */
    public static final String sDefaultXMLConfigFile = "dataconfig.xml";

    /**
     *
     */
    public static final String sDefaultSKEL_LOG = "unknown_ops_crops.log";
    private static boolean debugFlg = false;
    /**
     * Used to determine whether mcrewconfig & tableconfig files exist and if so
     * have been read in the model or not.
     */
    private static boolean returnFlg = false;

    /**
     *
     * @return
     */
    public static boolean getReturnFlag() {
        return returnFlg;
    }
    private static String c_operationDateFormat = "MMM DD, YYYY";
    /**
     * Tells what units are used in displaying the data. Could be either primary or
     * alternate. English or Metric for example.
     */
    private static int kDisplayUnit = XMLConstants.kPrimaryUnit;

    /**
     *
     * @return
     */
    public static int getDisplayUnit() {
        return kDisplayUnit;
    }
    /**
     * The maximum number of fraction digits that will be displayed.
     */
    public static int kMaximumFractionDigits = 6;
    /**
     * Number of fixed columns in the MCREW table.
     */
    private static int kFixedColumns = 2;
    
    static boolean overzealousWrapping = true;
    public static boolean autosort = true;

    /**
     *
     * @return
     */
    public static int getFixedColumnsCount() {
        return kFixedColumns;
    }
    /**
     * Tells the number of dataObjectDefns created for storing the relevant data
     * from the .MAN files in a format defined by various XML files containing
     * the dataobject elements. e:g check dataconfig.xml
     */
    public static int kNumDataObjectDefns;
    /**
     * Vector object containing the ColumnDefn objects.
     * to store the contents of each columndefn from mcrewconfig.xml
     */
    private static Vector<ColumnDefn> colDefVec;
    //to store the cell style objects as defined in dataconfig.xml
    private static Hashtable<String, CellStyle> mCellStyleTable;
    //to store the choice lists used for comboboxes in the table
    private static Hashtable<String, ChoiceList> mChoiceListTable;
    //to store the contents of each DataObjectDefn from mcrewconfig.xml
    private static Hashtable<String, DataObjectDefn> mDataObjectDefnTable;
    // to store all defn about each object from the defn lang and display xml file
    private static Hashtable<String, ObjectMeta> mObjectMetaTable;
    // to store the format informationa about each action from man_fileformat.xml.
    private static Hashtable<Identity, ActionFormat> mManFileFormatTable;
    //This information is used while reading and writing from .man management file
    // This table holds the database directories for each data object (Operations, crop and Management(skel, template)
    private static Hashtable<String, String> mDBDirTable;

    private static String DATACONFIG_FILE = sDefaultXMLConfigFile, DATACONFIG_FILE_PATH, SKELTRANSLATION_FILE_PATH,
            TABLE_FILE, MANFORMAT_FILE, VIEW_FILE, WORKING_DIR, USUnits = "US", SIUnits = "SI",
            PrimaryUnits = "Primary", AlternateUnits = "Alternate";
    private static boolean display = true;
    /**
     * Tells us what's the initial state of the Calibration columns is when we
     * run the MCREW application.
     * False - Columns are invisisble
     * True - Columns are visisble
     */
    private static boolean initCalibColumnState = false;

    /*
     *Default cell styles.  The first style defined in the xml file is used unless another is set as a default.
     *
     */
    /**
     *
     * @return
     */
    public static Vector<ColumnDefn> getColumns() {
        return colDefVec;
    }
    /**
     * Default CellStyle object for use with header cells in the table.
     * @see CellStyle
     */
    private static CellStyle mDefaultHeaderCellStyle;

    /**
     *
     * @return
     */
    public static CellStyle getDefaultHeaderCellStyle() {
        return mDefaultHeaderCellStyle;
    }
    /**
     * Default CellStyle object for use with data cells in the table.
     * @see CellStyle
     */
    private static CellStyle mDefaultDataCellStyle;

    /**
     *
     * @return
     */
    public static CellStyle getDefaultDataCellStyle() {
        return mDefaultDataCellStyle;
    }

    /**
     * Initializes the vectors and hashtables with the configuration data.
     * It uses weps_mcrew_cfg as a startup file to intialize the directory
     * structure & has information about the other files used in running the
     * application with MCREW table data.
     */
    public static void initialize() {
        colDefVec = new Vector<ColumnDefn>();
        mDataObjectDefnTable = new Hashtable<>();
        mManFileFormatTable = new Hashtable<>();
        mCellStyleTable = new Hashtable<>();
        mChoiceListTable = new Hashtable<>();
        mDBDirTable = new Hashtable<>();

        readMcrewStartFile();//"weps_mcrew_cfg");

        readMcrewDataConfig();
        readTableColumn();
        readTableViews();
        readObjectMetas();
        kNumDataObjectDefns = mDataObjectDefnTable.size();
        //System.out.println("Configdata:" + "Constructor :No args Numdata object Defns : "+ kNumDataObjectDefns);
        readManFileFormat();
    }

    /**
     * Initializes the vectors and hashtables with the configuration data.
     * It uses the argument as a startup file to intialize the directory
     * structure & has information about the other files used in running the
     * application with MCREW table data.
     * @param pStartupFile Startup file that has the information about all other files
     */
    public static void initialize(String pStartupFile) {
        colDefVec = new Vector<ColumnDefn>();
        mDataObjectDefnTable = new Hashtable<>();
        mManFileFormatTable = new Hashtable<>();
        mCellStyleTable = new Hashtable<>();
        mChoiceListTable = new Hashtable<>();
        mDBDirTable = new Hashtable<>();

        readMcrewStartFile(pStartupFile);//"weps_mcrew_cfg");
        readMcrewDataConfig();

        if (returnFlg == false) {
            readTableColumn();
            readTableViews();
            readObjectMetas();
            kNumDataObjectDefns = mDataObjectDefnTable.size();
            //System.out.println("Configdata:" + "Constructor :One args Numdata object Defns : "+ kNumDataObjectDefns);
            readManFileFormat();
        }
    }

    /**
     * Initializes the vectors and hashtables with the configuration data.
     * It uses the argument as a startup file to intialize the directory
     * structure & has information about the other files used in running the
     * application with MCREW table data.
     * @param extraConfigs      
     */
    public static void initialize(Hashtable<String, String> extraConfigs) {
        colDefVec = new Vector<ColumnDefn>();
        mDataObjectDefnTable = new Hashtable<>();
        mManFileFormatTable = new Hashtable<>();
        mCellStyleTable = new Hashtable<>();
        mChoiceListTable = new Hashtable<>();
        mDBDirTable = new Hashtable<>();

        WORKING_DIR = System.getProperty("user.dir");
        //Load settings from the passed hashtable

        for (Entry<String, String> entry : extraConfigs.entrySet()) {
            //for (String key : extraConfigs.keySet()) {
            String key = entry.getKey();
            String value = entry.getValue();
            switch (key) {
                case "CD-MCREW":
                    DATACONFIG_FILE_PATH = WORKING_DIR + TFile.separator + value;
                    //System.out.println("readMCrewStart " + "DataConfigFilePth " + DATACONFIG_FILE_PATH);
                    break;
                case "CD-mcrew data config file name":
                    DATACONFIG_FILE = value;
                    //System.out.println("readMCrewStart " + "DataConfigFileName " + DATACONFIG_FILE);
                    break;
                case "CD-management template":
                    // store it w.r.t internal name as spec'd in dataconfig.xml
                    mDBDirTable.put(XMLConstants.smanagement_template, value);
                    mDBDirTable.put(XMLConstants.smanagement, value);
                    break;
                case "CD-management skeleton":
                    // store it w.r.t internal name as spec'd in dataconfig.xml
                    mDBDirTable.put(XMLConstants.smanagement_skeleton, value);
                    break;
                case "CD-manoperdb":
                    mDBDirTable.put(XMLConstants.soperation, value);
                    break;
                case "CD-cropdb":
                    mDBDirTable.put(XMLConstants.scrop, value);
                    break;
                case "CD-measurement":
                    if (value.equals(USUnits)) {
                        kDisplayUnit = XMLConstants.kAlternateUnit;
                    } else if (value.equals(SIUnits)) {
                        kDisplayUnit = XMLConstants.kPrimaryUnit;
                    }
                    break;
                case "CD-operation date format":
                    c_operationDateFormat = value;
                    break;
            }
        }

        readMcrewDataConfig();

        if (returnFlg == false) {
            readTableColumn();
            readTableViews();
            readObjectMetas();
            kNumDataObjectDefns = mDataObjectDefnTable.size();
            //System.out.println("Configdata:" + "Constructor :One args Numdata object Defns : "+ kNumDataObjectDefns);
            readManFileFormat();
        }
    }

    /**
     * Initializes the vectors and hashtables with the configuration data.
     * It uses cd as a startup file to initialize the directory
     * structure & has information about the other files used in running the
     * application with MCREW table data.
     * @param cd
     */
    public static void initialize(usda.weru.util.ConfigData cd) {
        logger.info("Initializing MCREW data model.");
        //Passes the events to the static listening method of config data.
        //This allows mcrew to listen to all of the weps config.
        PropertyChangeListener listener = new PropertyChangeListener() {

            @Override
            public void propertyChange(PropertyChangeEvent event) {
                MCREWConfig.propertyChange(event);
            }
        };

        autosort = cd.getData(ConfigData.MCREWAutosort).trim().equals("1");
        colDefVec = new Vector<ColumnDefn>();
        mDataObjectDefnTable = new Hashtable<>();
        mManFileFormatTable = new Hashtable<>();
        mCellStyleTable = new Hashtable<>();
        mChoiceListTable = new Hashtable<>();
        mDBDirTable = new Hashtable<>();

        //Test if we are already listening to this config data.  Prevents multiple event calls.
        cd.setData(IS_LISTENING, "ARE YOU THERE?");//What is sent does not mater.

        if (!listeningTest) {
            //This is a new config data to listen to.
            cd.addPropertyChangeListener(listener);
        }

        WORKING_DIR = System.getProperty("user.dir");

        //Send all the data over.
        cd.fireAll(listener);

        readMcrewDataConfig();

        if (returnFlg == false) {
            readTableColumn();
            readTableViews();
            readObjectMetas();
            kNumDataObjectDefns = mDataObjectDefnTable.size();
            //System.out.println("Configdata:" + "Constructor :One args Numdata object Defns : "+ kNumDataObjectDefns);
            readManFileFormat();
        }
    }

    /**
     * Responds to propertychanges firing from code:  most likely other files.
     * @param e
     */
    public static void propertyChange(PropertyChangeEvent e) {
        String value = e.getNewValue() != null ? e.getNewValue().toString() : null;
        switch (e.getPropertyName()) {
            case IS_LISTENING:
                listeningTest = true;
                break;
            case usda.weru.util.ConfigData.MCREW:
                DATACONFIG_FILE_PATH = WORKING_DIR + TFile.separator + value;
                break;
            case usda.weru.util.ConfigData.McrewDataConfigFile:
                DATACONFIG_FILE = value;
                break;
            case usda.weru.util.ConfigData.ManTemp:
                // store it w.r.t internal name as spec'd in dataconfig.xml
                mDBDirTable.put(XMLConstants.smanagement_template, value);
                mDBDirTable.put(XMLConstants.smanagement, value);
                break;
            case usda.weru.util.ConfigData.ManTempSaveAs:
                mDBDirTable.put(usda.weru.util.ConfigData.ManTempSaveAs, value);
                if (value != null && value.length() > 0) {
                    hasManTempSaveAsDir = true;
                } else {
                    hasManTempSaveAsDir = false;
                }
                break;
            case usda.weru.util.ConfigData.ManSkel:
                // store it w.r.t internal name as spec'd in dataconfig.xml
                mDBDirTable.put(XMLConstants.smanagement_skeleton, value);
                break;
            case usda.weru.util.ConfigData.ManDB: {
                mDBDirTable.put(XMLConstants.soperation, value);
                TFile dir = new TFile(getDirectoryName(XMLConstants.soperation));
                getOpFileList().setFile(dir);
                break;
            }
            case usda.weru.util.ConfigData.CropDB: {
                mDBDirTable.put(XMLConstants.scrop, value);
                TFile dir = new TFile(getDirectoryName(XMLConstants.scrop));
                getCropFileList().setFile(dir);
                //getCropFileList().refreshFiles();
                break;
            }
            case usda.weru.util.ConfigData.Units:
                if (value.equals(USUnits)) {
                    kDisplayUnit = XMLConstants.kAlternateUnit;
                } else if (value.equals(SIUnits)) {
                    kDisplayUnit = XMLConstants.kPrimaryUnit;
                }
                break;
            case usda.weru.util.ConfigData.FormatOperationDate:
                c_operationDateFormat = value;
                break;
            case usda.weru.util.ConfigData.SkelTranslationFile:
                TFile tempFile = new TFile(Util.parse((String) e.getNewValue()));
                if (tempFile == null || tempFile.getName().trim().length() == 0) {
                    SKELTRANSLATION_FILE_PATH = null;
                } else if (tempFile.isAbsolute()) {
                    SKELTRANSLATION_FILE_PATH = tempFile.getAbsolutePath();
                } else {
                    SKELTRANSLATION_FILE_PATH = new TFile(WORKING_DIR, tempFile.getPath()).getAbsolutePath();
                }
                break;
        }
    }
    private static boolean hasManTempSaveAsDir = false;

    /**
     *
     * @return
     */
    public static boolean getHasManTempSaveAsDir() {
        return hasManTempSaveAsDir;
    }

    /**
     *  Reads the etxt startup file in order to get the information about all other files
     * @param pFileName The path where this file exists.
     */
    public static void readMcrewStartFile(String pFileName) {
        BufferedReader br = null;
        try {
            br = new BufferedReader(new TFileReader(new TFile(pFileName)));
            String dataLine;

            //WORKING_DIR = (new File(pFileName)).getCanonicalFile().getParent();
            // Changed by Neha - The Mcrew Config File need not be in the working directory.
            WORKING_DIR = System.getProperty("user.dir");
            // //System.out.println("readMcrewStartFile" + "Opening file :" + pFileName+"  WORKING_DIR:"+WORKING_DIR);

            dataLine = br.readLine();
            while (dataLine != null) {
                StringTokenizer tokenizer = new StringTokenizer(dataLine, "=");

                String tokenLeft = tokenizer.nextToken();
                String tokenRight = tokenizer.nextToken();

//				//System.out.println("readMcrewStart: " + tokenLeft + "--" + tokenRight);
                if (tokenRight == null) {
                    //System.err.println("Configdata:" + "Theres no value for tag: "+ tokenLeft);
                    dataLine = br.readLine();
                    continue;

                }

                String valueId = tokenLeft;
                String value = tokenRight;
                switch (valueId) {
                    case "CD-MCREW":
                        DATACONFIG_FILE_PATH = WORKING_DIR + TFile.separator + value;
                        ////System.out.println("readMCrewStart " + "DataConfigFilePth " + DATACONFIG_FILE_PATH);
                        break;
                    case "CD-mcrew data config file name":
                        DATACONFIG_FILE = value;
                        ////System.out.println("readMCrewStart " + "DataConfigFileName " + DATACONFIG_FILE);
                        break;
                    case "CD-management template":
                        // store it w.r.t internal name as spec'd in dataconfig.xml
                        mDBDirTable.put(XMLConstants.smanagement_template, value);
                        mDBDirTable.put(XMLConstants.smanagement, value);
                        break;
                    case "CD-management skeleton":
                        // store it w.r.t internal name as spec'd in dataconfig.xml
                        mDBDirTable.put(XMLConstants.smanagement_skeleton, value);
                        break;
                    case "CD-manoperdb":
                        mDBDirTable.put(XMLConstants.soperation, value);
                        break;
                    case "CD-cropdb":
                        mDBDirTable.put(XMLConstants.scrop, value);
                        break;
                    case "CD-measurement":
                        if (value.equals(USUnits)) {
                            kDisplayUnit = XMLConstants.kAlternateUnit;
                        } else if (value.equals(SIUnits)) {
                            kDisplayUnit = XMLConstants.kPrimaryUnit;
                        }
                        break;
                    case "CD-operation date format":
                        c_operationDateFormat = value;
                        break;
                }

                dataLine = br.readLine();

            }
        } catch (IOException | NoSuchElementException e) {
            //System.err.println("ConfigData:readMcrewStartFile" + " IOException, Probably file is missing");
        } finally {
            try {
                br.close();
            } catch (IOException e) {
                logger.error("Error reading mcrew start file.", e);
            }
        }

    }

    /**
     * Reads the etxt startup file in order to get the information about all
     * other files. The default start file is mcrew_start.xml
     */
    public static void readMcrewStartFile() {
        Document doc = XMLDoc.getDocument("mcrew_start.xml");
        if (doc == null) {
            //System.err.println("ConfigData:" + " Cannot locate the file mcrew_start.xml");
            return;
        }

        doc.normalize();

        try {
            WORKING_DIR = (new TFile("mcrew_system.xml")).getCanonicalFile().getParent();
        } catch (IOException e) {
            //System.err.println("ConfigData:readmcreStartFile"+  "IOException " + "mcrew_start.xml");
        }

        DocumentTraversal traversable = (DocumentTraversal) doc;
        TreeWalker walker = traversable.createTreeWalker(doc.getDocumentElement(), NodeFilter.SHOW_ALL, null, false);

        Node node = walker.firstChild();

        while (node != null) {
            String nodeName = node.getNodeName();
            String nodeData = XMLDoc.getTextData(node);

            if (nodeData == null) {
                node = walker.nextSibling();
                continue; // empty node
            }
            switch (nodeName) {
                case XMLConstants.sDATACONFIG_FILE:
                    DATACONFIG_FILE = nodeData;
                    break;
                case XMLConstants.sDATACONFIG_FILE_PATH:
                    DATACONFIG_FILE_PATH = WORKING_DIR + TFile.separator + nodeData;
                    break;
                case XMLConstants.smanagement_template:
                    // store it w.r.t internal name as spec'd in dataconfig.xml
                    mDBDirTable.put(XMLConstants.smanagement_template, nodeData);
                    break;
                case XMLConstants.smanagement_skeleton:
                    // store it w.r.t internal name as spec'd in dataconfig.xml
                    mDBDirTable.put(XMLConstants.smanagement_skeleton, nodeData);
                    break;
                case XMLConstants.smanoperdb:
                    mDBDirTable.put(XMLConstants.soperation, nodeData);
                    break;
                case XMLConstants.scropdb:
                    mDBDirTable.put(XMLConstants.scrop, nodeData);
                    break;
                case XMLConstants.sunits:
                    String units = XMLDoc.getTextData(node);
                    if ((units.equals(USUnits)) || (units.equals(PrimaryUnits))) {
                        kDisplayUnit = XMLConstants.kAlternateUnit;
                    } else if ((units.equals(SIUnits)) || (units.equals(AlternateUnits))) {
                        kDisplayUnit = XMLConstants.kPrimaryUnit;
                        //System.out.println("ConfigData:readMcrewStartFile: " + "Display Units-" + kDisplayUnit + units);
                    }
                    break;
            }
            node = walker.nextSibling();
        }
    }

    /* Parses the XML document mcrewconfig.cxml to determine the various DataObjectDefns and columnobjects
     * This is one of the 2 functions which reads the XML file directly as the file mcrewconfig.xml has two different objects,
     * dataobjedctdefn and columndefn. Also, dataObjectdefn and columnDefn are private classes, so the reading
     * is handled here instead of through ReadData class which handles all XML file processing.
     */
    /**
     * Reads the XML data configuration file in order to get the information
     * about all other XML files. The default dataconfig file is dataconfig.xml
     */
    public static void readMcrewDataConfig() {
        Document doc = XMLDoc.getDocument(DATACONFIG_FILE_PATH + TFile.separator + DATACONFIG_FILE);
        //System.out.println("readMcrewDataConfig : DataConfig Filename is :" + DATACONFIG_FILE_PATH + File.separator
        //+ DATACONFIG_FILE);
        if (doc != null) {
            doc.normalize();
        } else {
            //System.err.println("No McrewConfig file - Exiting");
            returnFlg = true;
            return;
            //	System.exit(0);
        }

        //Import Cell Styles.
        try {

            XPath xpath = XPathFactory.newInstance().newXPath();
            InputSource inputSource = new InputSource(DATACONFIG_FILE_PATH + TFile.separator + DATACONFIG_FILE);
            NodeList nodes = (NodeList) xpath.evaluate("/dataconfig/cellstyle", inputSource, XPathConstants.NODESET);
            Node tmpNode;
            CellStyle tmpCellStyle;
            int nodeIndex;
            for (nodeIndex = 0; nodeIndex < nodes.getLength(); nodeIndex++) {
                tmpNode = nodes.item(nodeIndex);
                tmpCellStyle = new CellStyle(tmpNode);
                if (tmpCellStyle.isValid()) {
                    mCellStyleTable.put(tmpCellStyle.getStyleTag(), tmpCellStyle);
                    if (mDefaultHeaderCellStyle == null || tmpCellStyle.isDefaultHeader()) {
                        mDefaultHeaderCellStyle = tmpCellStyle;
                    }
                    if (mDefaultDataCellStyle == null || tmpCellStyle.isDefaultData()) {
                        mDefaultDataCellStyle = tmpCellStyle;
                    }
                    if(tmpCellStyle.getStyleTag().equals("opdata") || 
                            tmpCellStyle.getStyleTag().equals("cropdata") ||
                            tmpCellStyle.getStyleTag().equals("fueldata") ||
                            tmpCellStyle.getStyleTag().equals("datadefault"))
                    {
                        tmpCellStyle = new CellStyle(tmpNode, InputLimits.TableStatus.OKAY);
                        mCellStyleTable.put(tmpCellStyle.getStyleTag() + 
                                InputLimits.TableStatus.OKAY, tmpCellStyle);
                        tmpCellStyle = new CellStyle(tmpNode, InputLimits.TableStatus.WARNSAVE);
                        mCellStyleTable.put(tmpCellStyle.getStyleTag() + 
                                InputLimits.TableStatus.WARNSAVE, tmpCellStyle);
                        tmpCellStyle = new CellStyle(tmpNode, InputLimits.TableStatus.NOSAVE);
                        mCellStyleTable.put(tmpCellStyle.getStyleTag() + 
                                InputLimits.TableStatus.NOSAVE, tmpCellStyle);
                        tmpCellStyle = new CellStyle(tmpNode, InputLimits.TableStatus.INIT);
                        mCellStyleTable.put(tmpCellStyle.getStyleTag() + 
                                InputLimits.TableStatus.INIT, tmpCellStyle);
                    }
                }

            }
            //Clean Up
            tmpNode = null;
            tmpCellStyle = null;
        } catch (XPathExpressionException e) {
            //System.out.println("XML X-Path Expression Error");
            e.printStackTrace();
        }

        //End Cell Style Import
        //Import ChoiceLists
        try {

            XPath xpath = XPathFactory.newInstance().newXPath();
            InputSource inputSource = new InputSource(DATACONFIG_FILE_PATH + TFile.separator + DATACONFIG_FILE);
            NodeList nodes = (NodeList) xpath.evaluate("/dataconfig/choicelist", inputSource, XPathConstants.NODESET);
            Node tmpNode;
            int nodeIndex;
            for (nodeIndex = 0; nodeIndex < nodes.getLength(); nodeIndex++) {
                tmpNode = nodes.item(nodeIndex);
                ChoiceList tmpChoiceList = new ChoiceList(tmpNode);
                if (tmpChoiceList.isValid()) {
                    mChoiceListTable.put(tmpChoiceList.getTag(), tmpChoiceList);
                }

            }
            //Clean Up
            tmpNode = null;
        } catch (XPathExpressionException e) {
            //System.out.println("XML X-Path Expression Error");
            e.printStackTrace();
        }

        //End ChoiceList Import
        DocumentTraversal traversable = (DocumentTraversal) doc;

        // TreeWalker are better for tasks in which the structure of the document around selected nodes will be manipulated.
        // Create a new TreeWalker over the subtree rooted at the specified node.
        TreeWalker walker = traversable.createTreeWalker(doc.getDocumentElement(), NodeFilter.SHOW_ALL, null, false);

        // Moves the TreeWalker to the first visible child of the current node, and returns the new node.
        Node node = walker.firstChild();
        // the node can be DataObjectDefn or coldefn depending on what comes first on mcrewconfig.xml
        // the node is passed to the appropriate object to extract the data.
        // Only the objects themselves know the format of their data in XML files.

        while (node != null) {
            String nodeName = node.getNodeName();

            // although it doesn't matter on adding or removing elements from the XML file,
            // it is required that the element names be consistent with the name son XMLConstant.java
            // since its the dataObjectDefn element (from mcrewconfig.xml)
            if (nodeName.equals(XMLConstants.sdataobjectdefn)) {
                DataObjectDefn dataobjectdefn = new DataObjectDefn();

                dataobjectdefn.initialize(node);
                String key = dataobjectdefn.get(XMLConstants.sobjectname);
                if (key != null) {
                    mDataObjectDefnTable.put(key, dataobjectdefn);
                    // i.e objects are stored w.r.t to their object names
                }

            } else if (nodeName.equals(XMLConstants.scolumndefn)) { // from dataconfig.xml

                ColumnDefn coldefn = new ColumnDefn();

                coldefn.initialize(node);
                int colidx = Integer.parseInt(coldefn.get(XMLConstants.scolumnnum));
                try {
                    colDefVec.add(colidx, coldefn);
                } catch (ArrayIndexOutOfBoundsException e) {
                    for (int idx = colDefVec.size(); idx < colidx; idx++) {
                        colDefVec.add(null);
                    }
                    colDefVec.add(coldefn);
                }
            } else if (nodeName.equals(XMLConstants.smisc)) {
                Node childNode = walker.firstChild();
                while (childNode != null) {
                    String childName = childNode.getNodeName();
                    switch (childName) {
                        case XMLConstants.stable_file:
                            TABLE_FILE = XMLDoc.getTextData(childNode);
                            break;
                        case XMLConstants.smanformat_file:
                            MANFORMAT_FILE = XMLDoc.getTextData(childNode);
                            //System.out.println("====== CONFIGDATA ====== : readMcrewDataConfig : MANFORMAT_FILE Filename is :"
                            //+ MANFORMAT_FILE + " ============= ");
                            break;
                        case XMLConstants.sview_file:
                            VIEW_FILE = XMLDoc.getTextData(childNode);
                            break;
                    }

                    childNode = walker.nextSibling();
                }

            }
            node = walker.nextSibling();
        }
        //walker.parentNode();
        kFixedColumns = colDefVec.size();

    }

    /**
     * Read all the data from the configuration file (tablecolumn.xml) such as
     * the table column headers & object type (crops & operations), tagname for
     * crops to be displayed, the group they belong to & whether they are
     * visible or not along with other characteristics.
     */
    public static void readTableColumn() {        //display = toggle;
        // boolean display = false; //default display value

        Document doc = XMLDoc.getDocument(DATACONFIG_FILE_PATH + TFile.separator + TABLE_FILE);
        //System.out.println("DataConfig..Macoo Filename is :" + DATACONFIG_FILE_PATH + File.separator + TABLE_FILE);
        if (doc != null) {
            doc.normalize();
        } else {
            //System.err.println("No TableConfig file - Exiting");
            returnFlg = true;
            return;
            // System.exit(0);
        }

        DocumentTraversal traversable = (DocumentTraversal) doc;
        TreeWalker walker = traversable.createTreeWalker(doc.getDocumentElement(), NodeFilter.SHOW_ALL, null, false);

        // the node can be DataObjectDefn or coldefn depending on what comes first on mcrewconfig.xml
        Node node = walker.firstChild();
        // the node is passed to the appropriate object to extract the data.
        // Only the objects themselves know the format of their data in XML files.

        while (node != null) {        //default display value
            String nodeName = node.getNodeName();

            // In tablecolumn.xml
            if ((nodeName.equals(XMLConstants.scolumndefn)))// && (display == true) )
            {
                ColumnDefn colDefn = new ColumnDefn();
                colDefn.initialize(node);

                //int colidx = Integer.parseInt(coldefn.get(XMLConstants.scolumnnum));
                int colidx = colDefVec.size(); // Add the new colDefn to the end of Vector

                try {
                    colDefVec.add(colidx, colDefn);
                } catch (ArrayIndexOutOfBoundsException e) {

                    for (int idx = colDefVec.size(); idx < colidx; idx++) {
                        colDefVec.add(null);
                    }
                    colDefVec.add(colDefn);
                }
            }

            node = walker.nextSibling();
        }
    }
    private static Map<String, TableView> c_views;

    /**
     * Read all the data from the configuration file (tablecolumn.xml) such as
     * the table column headers & object type (crops & operations), tagname for
     * crops to be displayed, the group they belong to & whether they are
     * visible or not along with other characteristics.
     */
    public static void readTableViews() {
        c_views = new LinkedHashMap<String, TableView>();
        TFile file = new TFile(DATACONFIG_FILE_PATH, VIEW_FILE);
        try {
            if (!file.exists()) {
                throw new FileNotFoundException(file.getAbsolutePath());
            }
            SAXBuilder builder = new SAXBuilder();
            org.jdom2.Document document = builder.build(file);
            org.jdom2.Element root = document.getRootElement();
            List<org.jdom2.Element> viewElements = root.getChildren("view");

            for (org.jdom2.Element element : viewElements) {
                TableView view = new TableView();
                view.initilize(element);
                c_views.put(view.getName(), view);
            }

        } catch (UTFDataFormatException udfe) {
            //udfe.printStackTrace();
        } catch (JDOMException | IOException jde) {
            //jde.printStackTrace();
        }
    }

    /**
     *
     * @return
     */
    public static TableView[] getTableViews() {
        return c_views.values().toArray(new TableView[c_views.size()]);
    }

    /**
     * returns the table view tied to the key that is the input name.
     * @param name
     * @return
     */
    public static TableView getTableView(String name) {
        return c_views.get(name);
    }

    /**
     * Gets the initial state of the calibration columns(Visisble/invisible) on
     * MCREW table screen.
     * @return Returns true if columns are visible otherwise false
     */
    public static boolean getInitCalibColumnState() {
        return initCalibColumnState;
    }

    /**
     * Reads all the meta data for operation/crop objects from defn, display,
     * lang, XML files and adds a new Meta object to the hashtable containing
     * other similar group of objects.
     */
    private static void readObjectMetas() {
        Document doc;

        mObjectMetaTable = new Hashtable<>();

        Enumeration<DataObjectDefn> elements = mDataObjectDefnTable.elements();
        while (elements.hasMoreElements()) {
            DataObjectDefn dataObjectDefn = elements.nextElement();
            //DataObjectMeta operationMeta;
            ObjectMeta objectMeta = null;

            // Presently, objectane is either 'operation' or 'crop'
            String objectName = dataObjectDefn.get(XMLConstants.sobjectname);
            String fileName, fullPathName;

            String defnfile = dataObjectDefn.get(XMLConstants.sdefnfile);
            if ((defnfile == null) || (defnfile.equals(""))) {
                continue;
            }
            fullPathName = DATACONFIG_FILE_PATH + TFile.separator + defnfile;
            //System.out.println( " ConfigData : readObjectMeta() : firstFile : " + fullPathName);
            doc = XMLDoc.getDocument(fullPathName);
            if (doc == null) {
                continue;
            }
            doc.normalize();

            if (objectName.equals(XMLConstants.soperation)) {
                objectMeta = new OperationMeta(objectName);
            } else if (objectName.equals(XMLConstants.scrop)) {
                objectMeta = new CropMeta(objectName);
            }
            if (objectMeta != null) {
                objectMeta.initialize(doc.getDocumentElement()); // returns the root NODE of XML Tree structure	and then
                // initializes the objectMeta of type Operation/Crop Metas
            /* Now read the lang and display files.
                 * The processing is done separately from the defn file to reduce the
                 * many if and else conditions which arises upon combining the processing of all files together
                 */
            }
            // 1 for defnfile which is already processed above
            for (int file = 1; file < XMLConstants.kTotalDescriptionfiles; file++) {
                fileName = XMLConstants.getXMLDescriptionfiles()[file];
                fullPathName = DATACONFIG_FILE_PATH + TFile.separator + dataObjectDefn.get(fileName);
                //System.out.println( " ConfigData : readObjectMeta() : SecondOrThird_File : " + fullPathName);
                doc = XMLDoc.getDocument(fullPathName);
                if (doc == null) {
                    return;
                }
                doc.normalize();

                objectMeta.update(doc.getDocumentElement());
                //updateMeta(objectMeta, CONFIG_FILE_PATH + File.separator + dataObjectDefn.get(fileName));
            }

            mObjectMetaTable.put(objectName, objectMeta); // adding the new Meta object to the hashtable of objects

        } // end while elements.hasmoreElements()

    }

    // Above function taken from ReadData

    /**
     * Get the Meta object whose object name is pObjectName i:e the argument
     * being passed to method.
     * @param pObjectName The object name whose meta data is requested.
     * @return Returns the Meta object for the pObjectName.
     */
    public static ObjectMeta getObjectMeta(String pObjectName) {
        if (mObjectMetaTable != null) {
            return mObjectMetaTable.get(pObjectName);
        }
        return null;
    }

    /**
     * Get the meta object associated with the action object whose identity is
     * pIdentity.
     * @param pIdentity Identity of the action object whose meta object is being
     * requested. Identity object consists of code & value parts.
     * @return Returns the action meta object that stores the values
     * corresponding to action object.
     */
    public static ActionMeta getActionMeta(Identity pIdentity) {
        ActionMeta actionMeta;
        /* Search for the corresponding actionMeta in all ObjectMetas
         */
        Enumeration<ObjectMeta> e = mObjectMetaTable.elements();
        while (e.hasMoreElements()) {
            ObjectMeta objectMeta = e.nextElement();
            actionMeta = objectMeta.getActionMeta(pIdentity);
            if (actionMeta != null) {
                return actionMeta;
            }
        }
        return null;

    }

    /**
     * This method returns the name definition file for the corresponding object
     * (operation or crop)
     * @param pObjectName The Object name whose definition file is requested.
     * @return The name of the definition file containing the details of
     * operations or crops for which it is requested.
     */
    public String getDefnFile(String pObjectName) {
        DataObjectDefn tempObjectDefn;

        tempObjectDefn = mDataObjectDefnTable.get(pObjectName);
        //System.out.println("ConfigData : getDefnFile : Name of the Definition File is : "
        //+ tempObjectDefn.get(XMLConstants.sdefnfile) );
        return tempObjectDefn.get(XMLConstants.sdefnfile);
    }

    /**
     * This method returns the name display XML file for the corresponding object
     * (operation or crop)
     * @param pObjectName The Object name whose display XML file is requested.
     * @return The name of the display XML file containing the details of
     * operations or crops for which it is requested.
     */
    public String getDisplayFile(String pObjectName) {
        DataObjectDefn tempObjectDefn;

        tempObjectDefn = mDataObjectDefnTable.get(pObjectName);
        //System.out.println("ConfigData : getDisplayFile : Name of the Display File is : "
        //+ tempObjectDefn.get(XMLConstants.sdisplayfile) );
        return tempObjectDefn.get(XMLConstants.sdisplayfile);
    }

    /**
     * This method returns the name lang XML file for the corresponding object
     * (operation or crop)
     * @param pObjectName The Object name whose lang XML file is requested.
     * @return The name of the lang XML file containing the details of
     * operations or crops for which it is requested.
     */
    public String getLangFile(String pObjectName) {
        DataObjectDefn tempObjectDefn;

        tempObjectDefn = mDataObjectDefnTable.get(pObjectName);
        //System.out.println("ConfigData : getLangFile : Name of the LangFile is : "
        //+ tempObjectDefn.get(XMLConstants.slangfile) );
        return tempObjectDefn.get(XMLConstants.slangfile);
    }

    /**
     * This method returns the name & path of the database directory where the
     * object exists.
     * @param pObjectName The name of the object whose database directory is being seeked
     * @return The directory name where the crop/operation data resides.
     */
    public String getDBdir(String pObjectName) {
        DataObjectDefn tempObjectDefn;

        tempObjectDefn = mDataObjectDefnTable.get(pObjectName);
        //System.out.println("ConfigData : getDBdir : Name of the database directory is : "
        //+ tempObjectDefn.get(XMLConstants.sDBdir) );
        return tempObjectDefn.get(XMLConstants.sDBdir);
    }

    /**
     * Get the name of the data value to be displayed in the given column
     * @param pColNum The column number in the table whose tagname(header) value
     * is being requested
     * @return The parameter whose operation/crop data will be pulled to populate
     * the multiple rows of that column variable which is the value of tagname element
     * in tablecolumn XML file.
     */
    public static String getTagName(int pColNum) {
        ColumnDefn tempColumnDefn;

        tempColumnDefn = colDefVec.get(pColNum);
        if (tempColumnDefn != null) {
            String tagName = tempColumnDefn.get(XMLConstants.stagname);
            usda.weru.util.Util.debugPrint(debugFlg, "ConfigData : getTagName : --- " + tagName);
            return tagName;
        }

        return null;
    }

    /**
     * Gets the object name(operation/crop) for the column number pColNum of
     * table being referred
     * @param pColNum The column number whose object name is being asked.
     * @return The object name associated with the column
     */
    public static String getObjectName(int pColNum) {
        ColumnDefn tempColumnDefn;
        if (pColNum < 0 || pColNum >= colDefVec.size()) {
            return null;
        }
        tempColumnDefn = colDefVec.get(pColNum);

        if (tempColumnDefn != null) {

            String objectName = tempColumnDefn.get(XMLConstants.scolumndataobject);
            //usda.weru.util.Util.debugPrint(debugFlg, "ConfigData : getObjectName : --- " + objectName );
            return objectName;
        }

        return null;
    }

    /**
     * Gets the name of the column i:e the column header
     * @param pColNum The column number whose label is being sought.
     * @return The column header itself.
     */
    public static String getColumnLabel(int pColNum) {
        ColumnDefn tempColumnDefn;

        tempColumnDefn = colDefVec.get(pColNum);

        if (tempColumnDefn != null) {
            return tempColumnDefn.get(XMLConstants.scolumnlabel);
        }
        return null;
    }

    /*
     * Determines column in the mcrew table to freeze.
     * The column with the largest col num and frozen property set to true is used.
     *@return The largest column index marked as frozen.
     */
    /**
     * Returns the column the table should be frozen at.
     * @return int The column at which to freeze the scroll bars of the table.
     */
    static public int getFrozenColumn() {
        int tempFrozenColumnIndex = 0;
        ColumnDefn tempColumnDefn;
        for (int i = 1; i < colDefVec.size(); i++) {
            tempColumnDefn = colDefVec.get(i);
            if (tempColumnDefn.isFrozen() && i + 1 > tempFrozenColumnIndex) {
                tempFrozenColumnIndex = i + 1;
            }
        }
        return tempFrozenColumnIndex;
    }
    private static List<String> c_columnLabels;

    /**
     * Gets the names of all the columns i:e the column header
     * @return Retruns the vector containing all the column headers of the table.
     */
    public synchronized static List<String> getColumnLabels() {
        if (c_columnLabels == null) {
            c_columnLabels = new ArrayList<String>();
            for (ColumnDefn tempColumnDefn : colDefVec) {
                if (tempColumnDefn != null) {
                    String label = tempColumnDefn.get(XMLConstants.scolumnlabel);

                    String paramName = tempColumnDefn.get(XMLConstants.stagname);
                    String colDataObject = tempColumnDefn.get(XMLConstants.scolumndataobject);
                    String gname = tempColumnDefn.get(XMLConstants.sgroupname);
                    usda.weru.util.Util.debugPrint(debugFlg, " -- getColumnLabels -----gname ------ " + gname);

                    String units = null;

                    ObjectMeta objectMeta = mObjectMetaTable.get(colDataObject);

                    if ((objectMeta != null) && (paramName != null)) {
                        units = objectMeta.getValue(paramName, XMLConstants.sparamunit);
                        if (MCREWConfig.kDisplayUnit == XMLConstants.kAlternateUnit) {
                            String alternateUnit = objectMeta.getValue(paramName, XMLConstants.sparamaltunit);
                            if (alternateUnit != null) {
                                units = alternateUnit;
                            }
                        }
                    }
                    if (paramName != null && paramName.equals("Date")) {
                        units = MCREWConfig.getOperationDateFormat();
                    }

                    if (units != null) {
                        label = label.concat("\n(" + units + ")");
                    }
                    c_columnLabels.add(label);
                }
            }
        }

        return c_columnLabels;

    }
    private static List<String> c_columnNames;

    /**
     * Returns a List of the column names.
     * @return
     */
    public synchronized static List<String> getColumnNames() {
        if (c_columnNames == null) {
            c_columnNames = new ArrayList<String>();

            for (ColumnDefn column : colDefVec) {
                c_columnNames.add(column.get(XMLConstants.stagname));
            }
        }
        return c_columnNames;
    }

    /**
     * Gets the extension of the file the object pObjectName is associated with.
     * @param pObjectName The name of the object
     * @return The extension of the file e:g (.man, .xml, etc)
     */
    public static String getFileExtension(String pObjectName) {
        DataObjectDefn tempObjectDefn = null;

        tempObjectDefn = mDataObjectDefnTable.get(pObjectName);
        if (tempObjectDefn != null) {
            return tempObjectDefn.get(XMLConstants.sfileextension);
        }

        return null;
    }

    /**
     * Gets the name/path of the directory that exists under the current working
     * directory where object with name pObjectName resides.
     * @param pObjectName The object name whose parent directory is being sought.
     * @return Returns the parent directory path if different from working
     * directory otherwise returns the working directory.
     */
    public static String getDirectoryName(String pObjectName) {
        String dirName;

        dirName = mDBDirTable.get(pObjectName);

        if (dirName == null) {
            return Util.parse(WORKING_DIR);
        }
        TFile dir = new TFile(WORKING_DIR, dirName);
        if (dir.exists()) {
            return Util.parse(dir.getAbsolutePath());
        } else {
            return Util.parse(dirName);
        }

    }

    /**
     * Gets the path of the directory where configuration files resides.
     * @return The configuration directory path.
     */
    public static String getConfigDir() {
        return DATACONFIG_FILE_PATH;
    }

    /**
     * Gets the path of the file where skel translations are stored.
     * @return The configuration directory path.
     */
    public static String getSkelTranslationPath() {
        return SKELTRANSLATION_FILE_PATH;
    }

    /**
     * Reads the data from the manFileFormat XML file from data configuration file
     * directory populating the action elements with the meta data from this file
     * helping us store & organize it accordingly.
     */
    public static void readManFileFormat() {
        usda.weru.util.Util.debugPrint(debugFlg, "readManFileFormat()"
                + DATACONFIG_FILE_PATH + TFile.separator + MANFORMAT_FILE);
        Document doc = XMLDoc.getDocument(DATACONFIG_FILE_PATH + TFile.separator + MANFORMAT_FILE);
        if (doc != null) {
            doc.normalize();
        } else {
            //System.err.println("No man_format file - Exiting");
            System.exit(0);
        }

        DocumentTraversal traversable = (DocumentTraversal) doc;
        TreeWalker walker = traversable.createTreeWalker(doc.getDocumentElement(), NodeFilter.SHOW_ALL, null, false);

        Node node = walker.firstChild(); // the node can be DataObjectDefn or coldefn depending 
        //on what comes first on mcrewconfig.xml
        // the node is passed to the appropriate object to extract the data.
        // Only the objects themselves know the format of their data in XML files.

        while (node != null) {
            String nodeName = node.getNodeName();
            if (nodeName.equals(XMLConstants.sactionformat)) {
                ActionFormat actionFormat = new ActionFormat();
                actionFormat.initialize(node);

                mManFileFormatTable.put(actionFormat.getIdentity(), actionFormat);

            } // end of if
            node = walker.nextSibling();
        }
    }

    /**
     * Gets all the parameter names of various paramformatline elements associated
     * with the action format element (of action with identity pActionID) in the .man
     * file. (refer man_fileformat.xml)
     * @param pActionId The identity of the action format element whose parameter
     * names are being requested from the .man file.
     * @param pLineNum The line number where this data sits in the .man file.
     * @return Returns the vector containing all the parameter format line info such as
     * their attribute names, values, etc.
     */
    public static Vector<String> getManFileFormat(Identity pActionId, int pLineNum) {
        ActionFormat actionFormat = mManFileFormatTable.get(pActionId);
        if (actionFormat != null) {
            Vector<Vector<String>> paramFormatVec = actionFormat.getParamFormatVector();
            return paramFormatVec.get(pLineNum);
        }
        return null;
    }

    /**
     * Gets all the parameter format line information associated with the attributes like 'symbol' etc
     * contained in all the parameter format lines associated with the action format element
     * (for the action with the identity passed) in the .man file  parameters
     * @param pActionId The identity of the action format element whose parameter
     * is being requested from the .man file.
     * @param pLineNum The line number where this data sits in the .man file.
     * @return Returns the vector containing all the parameter format line info such as
     * their attribute names, values, etc
     */
    public static Vector<Vector<String>> getManFileFormatInfo(Identity pActionId, int pLineNum) {
        ActionFormat actionFormat = mManFileFormatTable.get(pActionId);
        if (actionFormat != null) {
            Vector<Vector<Vector<String>>> paramFormatVecDetails = actionFormat.getParamFormatVectorDetails();
            return paramFormatVecDetails.get(pLineNum);
        }
        return null;
    }

    /**
     * Gets the size(number) of parameter names associated with the action format
     * element.
     * @param pActionId The identity of the Action object whose total number of
     * parameters are being sought.
     * @return Returns the size (number of parameter names) associated with
     * the action format element of action object having identity
     * pActionId
     */
    public static int getManFormatNumLines(Identity pActionId) {
        ActionFormat actionFormat = mManFileFormatTable.get(pActionId);
        if (actionFormat != null) {
            Vector<Vector<String>> paramFormatVec = actionFormat.getParamFormatVector();
            return paramFormatVec.size();
        }
        return 0;
    }

    /**
     * Get ths number of fixed columns for the MCREW initial screen table stated
     * in the mcrewconfig.xml file under columndefn element.
     * @return Returns the total number of such fixed columns.
     */
    public static int getNumCols() {
        return colDefVec.size();
    }

    /**
     * Gets the values of the calibration column that help to decide whether
     * to make it visible or hidden.
     * @return The string containing that value('v' -> visible / 'h' -> hidden)
     */
    public static String getColDefVecCalibValue() {
        String s = "";
        Enumeration<ColumnDefn> e = colDefVec.elements();
        while (e.hasMoreElements()) {
            ColumnDefn c = e.nextElement();
            if (c.get(XMLConstants.sgroupname).equals("calibrate")) {
                s = c.get(XMLConstants.sdisplay);
                break;
            }
        }
        return s;
    }

    /**
     * Sets the value of the calibration column that will help decide whether
     * to make it visible or hidden.
     * @param flag The string containing that value to be set
     * ('v' -> visible / 'h' -> hidden)
     */
    public static void setColDefVecCalibValue(boolean flag) {

        Enumeration<ColumnDefn> e = colDefVec.elements();
        while (e.hasMoreElements()) {
            ColumnDefn c = e.nextElement();
            if (c.get(XMLConstants.sgroupname).equals("calibrate")) {
                c.put(XMLConstants.sdisplay, (flag + ""));
            }
        }
    }

    /* DataObjectDefn and ColumnDefn classes are made private because they are used only from within this class.
     * All other classes call the appropriate function in McrewConfig.
     */
    private static class DataObjectDefn {

        Hashtable<String, String> mObjectData;

        public DataObjectDefn() {
            mObjectData = new Hashtable<String, String>();
        }

        public String get(String pFieldName) {
            return mObjectData.get(pFieldName);
        }

        public void initialize(Node pNode) {
            DocumentTraversal traversable;

            if (pNode.getOwnerDocument() == null) {
                traversable = (DocumentTraversal) pNode;
            } else {
                traversable = (DocumentTraversal) pNode.getOwnerDocument();
            }
            TreeWalker walker = traversable.createTreeWalker(pNode, NodeFilter.SHOW_ALL, null, false);

            Node nodeChild = walker.firstChild(); // nodeChild is DataObjectDefn from mcrewconfig.xml

            while (nodeChild != null) {

                String dataName = "", dataValue = "";

                dataName = nodeChild.getNodeName();
                Node dataNode = walker.firstChild();

                if ((dataNode != null) && (dataNode.getNodeType() == Node.TEXT_NODE)) {
                    dataValue = dataNode.getNodeValue();
                    mObjectData.put(dataName, dataValue);
                    //usda.weru.util.Util.debugPrint(debugFlg, "ConfigData : DataObjectDefn : DataName is :"
                    //+ dataName + " DataValue is :" + dataValue);

                } else {
                    mObjectData.put(dataName, XMLConstants.sNovalue);
                }
                walker.parentNode();
                nodeChild = walker.nextSibling();

            }

        }
    }// end of class

    static class ColumnDefn {

        private JCCellStyle format;
        
        Hashtable<String, String> mObjectData;

        public ColumnDefn() {
            //mColumnNum = kNoColumn;
            //mColumnDataObject = sNoObject;
            //mColumnLabel = sNoLabel;
            mObjectData = new Hashtable<>();
        }

        public String get(String pFieldName) {
            return mObjectData.get(pFieldName);
        }

        public int getMinWidth() {
            Object tempObject = mObjectData.get("columnminwidth");
            if (tempObject != null) {
                return Integer.parseInt((String) tempObject);
            } else {
                return 1;
            }
        }

        public int getWidth() {
            Object tempObject = mObjectData.get("columnwidth");
            if (tempObject != null) {
                return Integer.parseInt((String) tempObject);
            } else {
                return 80;
            }
        }

        public int getMaxWidth() {
            Object tempObject = mObjectData.get("columnmaxwidth");
            if (tempObject != null) {
                return Integer.parseInt((String) tempObject);
            } else {
                return 1000;
            }
        }

        public boolean isFrozen() {
            Object tempObject = mObjectData.get("frozen");
            if (tempObject != null) {
                return Boolean.parseBoolean((String) tempObject);
            } else {
                return false;
            }
        }

        public void put(String name, String val) {
            mObjectData.put(name, val);
        }

        public CellStyle getDataCellStyle() {
            Object tempObject = mObjectData.get("datacellstyle");
            if (tempObject != null) {
                CellStyle tempCellStyle = MCREWConfig.mCellStyleTable.get((String) tempObject);
                if (tempCellStyle != null) {
                    return tempCellStyle;
                }
            }
            return null;
        }
        
        public CellStyle getDataCellStyle(InputLimits.TableStatus limits) {
            Object tempObject = mObjectData.get("datacellstyle");
            if (tempObject != null) {
                String input = (String) tempObject;
                if(input.equals("readonlydata") || input.equals("readonlycheckboxdata")
                        || input.equals("checkboxData") || input.equals("multicheckdata"))
                {
                    return getDataCellStyle();
                }
                input += limits;
               CellStyle tempCellStyle = MCREWConfig.mCellStyleTable.get(input);
                if (tempCellStyle != null) {
                tempCellStyle.getJCCellStyle().setBackground(
                    tempCellStyle.getCellColor(limits));
                    return tempCellStyle;
                }
            }
            else
            {
                String input = "datadefault" + limits;
                CellStyle tempCellStyle = MCREWConfig.mCellStyleTable.get(input);
                if (tempCellStyle != null) {
                tempCellStyle.getJCCellStyle().setBackground(
                    tempCellStyle.getCellColor(limits));
                    return tempCellStyle;
                }
            }
            return null;
        }
        
        public JCCellStyle getSubCellStyle(InputLimits.TableStatus limits) {
            Object tempObject = mObjectData.get("subcellstyle");
            if (tempObject != null) {
                String input = (String) tempObject;
                if(input.equals("readonlydata") || input.equals("readonlycheckboxdata")
                        || input.equals("checkboxdata") || input.equals("multicheckdata"))
                {
                    CellStyle tempCellStyle = MCREWConfig.mCellStyleTable.get((String) tempObject);
                    if (tempCellStyle != null) {
                        return tempCellStyle.getJCCellStyle();
                    }
                }
                input += limits;
                CellStyle tempCellStyle = MCREWConfig.mCellStyleTable.get(input);
                if (tempCellStyle != null) {
                tempCellStyle.getJCCellStyle().setBackground(
                    tempCellStyle.getCellColor(limits));
                    return tempCellStyle.getJCCellStyle();
                }
            }
            tempObject = getNumberFormat();
            JCCellStyle temp = getDataCellStyle(limits).getJCCellStyle();
            if (tempObject != null && temp != null) 
            {
                if(format == null)
                {
                    format = new JCCellStyle();
                    format.setCellRenderer(new MyFormattedCellRenderer(getNumberFormat()));
                    format.setCellEditor(new MyFormattedCellEditor());
                    format.setFont(temp.getFont());
                    format.setEditable(temp.isEditable());
                    format.setBackground(temp.getBackground());
                    format.setForeground(temp.getForeground());
                    format.setCellBorder(temp.getCellBorder());
                    format.setCellBorderSides(temp.getCellBorderSides());
                    format.setCellBorderColorMode(temp.getCellBorderColorMode());
                    format.setCellBorderColor(temp.getCellBorderColor());
                }
                format.setBackground(temp.getBackground());
                return format;
            }
            else
            {
                return temp;
            }
        }

        public CellStyle getHeaderCellStyle() {
            Object tempObject = mObjectData.get("headercellstyle");
            if (tempObject != null) {
                CellStyle tempCellStyle = MCREWConfig.mCellStyleTable.get((String) tempObject);
                if (tempCellStyle != null) {
                    return tempCellStyle;
                }
            }
            return null;
        }

        public String getNumberFormat() {
            Object tempObject = mObjectData.get("numberformat");
            if (tempObject != null) {
                String numberFormat = (String) tempObject;
                return numberFormat;
            }
            return null;
        }

        public String getEditFormat() {
            Object tempObject = mObjectData.get("editformat");
            if (tempObject != null) {
                String editformat = (String) tempObject;
                return editformat;
            }
            return null;
        }

        public void initialize(Node pNode) {
            DocumentTraversal traversable;

            if (pNode.getOwnerDocument() == null) // if in case pNode is Document itself
            {
                traversable = (DocumentTraversal) pNode;
            } else {
                traversable = (DocumentTraversal) pNode.getOwnerDocument();
            }
            TreeWalker walker = traversable.createTreeWalker(pNode, NodeFilter.SHOW_ALL, null, false);
            Node node = walker.firstChild();
            Node myNode = pNode.getParentNode();
            while (node != null) {
                String dataName = "", dataValue = "";

                dataName = node.getNodeName();
                dataValue = XMLDoc.getTextData(node);

//                usda.weru.util.Util.debugPrint(debugFlg, "ConfigData:ColumnDefn : Dataname is : "+ dataName
                //+ " Data Value is : " + dataValue);
                //usda.weru.util.Util.debugPrint(debugFlg, "ConfigData:----------ColumnDefn----------- : Dataname is : "
                //+ dataName + " Data Value is : " + dataValue);
                if (dataValue != null) {
                    // for cellstyle
                    mObjectData.put(dataName, dataValue);
                }

                //walker.parentNode();
                node = walker.nextSibling();
            }
            if ((myNode.getNodeName()).equals(XMLConstants.scolumngroup)) {
                Node firstSibling = myNode.getFirstChild();
                String dataName1 = firstSibling.getNodeName();
                String dataValue1 = XMLDoc.getTextData(firstSibling);
                usda.weru.util.Util.debugPrint(debugFlg, "ColumnDefn : Dataname1 is : " + dataName1
                        + " Data Value1 is : " + dataValue1);
                if (dataValue1 != null) {
                    mObjectData.put(dataName1, dataValue1);
                }
                Node nextSibling = firstSibling.getNextSibling();
                String dataName2 = nextSibling.getNodeName();
                String dataValue2 = XMLDoc.getTextData(nextSibling);
                usda.weru.util.Util.debugPrint(debugFlg, "ColumnDefn : Dataname2 is : " + dataName2
                        + " Data Value2 is : " + dataValue2);
                if (dataValue1 != null) {
                    mObjectData.put(dataName2, dataValue2);
                }
            }

            /*if( (pNnode.getOwnerDocument().getDocType().getName()).equals("tablecolumn") ){
             Node parPrevSibling = node.getParentNode().getPreviousSibling();
             String dataName1 = parPrevSibling.getNodeName();
             String dataValue1 = XMLDoc.getTextData(parPrevSibling);
             if(dataValue1 != null)
             {
             mObjectData.put(dataName1,dataValue1);
             }
             Node prevSibling = parPrevSibling.getPreviousSibling();
             String dataName2 = prevSibling.getNodeName();
             String dataValue2 = XMLDoc.getTextData(prevSibling);
             if(dataValue1 != null)
             {
             mObjectData.put(dataName2,dataValue2);
             }
             /// }*/
            Enumeration<String> e = mObjectData.keys();
//                            while( e.hasMoreElements() ) {
//                                 usda.weru.util.Util.debugPrint(debugFlg, "ConfigData :---- ColumnDefn----- ALL INSIDE ---- : "
            //+e.nextElement().toString());
//                            }
        } // end of initialize()
    }

    static class TableView {

        private String c_name;
        private String c_menuText;
        private String c_toolbarImage;
        private boolean c_auto;
        private String[] c_columns;
        private int[] c_numbers;

        public String getName() {
            return c_name;
        }

        public boolean isAuto() {
            return c_auto;
        }

        public String getMenuText() {
            return c_menuText;
        }

        public String getToolbarImage() {
            return c_toolbarImage;
        }

        public String[] getColumnNames() {
            return c_columns;
        }

        public int[] getColumnIndexes() {
            if (c_numbers == null) {
                initColumnIndexes();
            }
            return c_numbers;
        }

        private void initColumnIndexes() {
            List<Integer> temp = new ArrayList<Integer>();
            for (String name : getColumnNames()) {
                int index = MCREWConfig.getColumnNames().indexOf(name);
                if (index >= 0) {
                    temp.add(index);
                }
            }
            c_numbers = new int[temp.size()];
            for (int i = 0; i < c_numbers.length; i++) {
                c_numbers[i] = temp.get(i);
            }

        }

        public void initilize(org.jdom2.Element node) {
            c_name = node.getChildTextTrim("name");
            String autoTemp = node.getChildTextTrim("auto");
            c_auto = autoTemp != null && autoTemp.equals("true");
            c_menuText = node.getChildTextTrim("menu");
            c_toolbarImage = node.getChildTextTrim("toolbar");

            List<org.jdom2.Element> columnElements = node.getChildren("column");
            List<String> temp = new ArrayList<String>();
            for (org.jdom2.Element element : columnElements) {
                temp.add(element.getTextTrim());
            }
            c_columns = temp.toArray(new String[temp.size()]);

        }
    }

    private static class ActionFormat {

        /** mParamFormatVec consists of inner Vector which in turn consists of param names whcih are printed in a single
         * line.
         */
        private Vector<Vector<String>> mParamFormatVec;
        // type can be either Vector<Vector<Vector<String>>>> or Vector<Vector<String>>>
        private Vector<Vector<Vector<String>>> mParamFormatVecDetails;
        //private String attrValue = "";
        //private Vector<String> paramFormatLineInfo;

        private Identity mIdentity;

        public ActionFormat() {
            mParamFormatVec = new Vector<>();
            mParamFormatVecDetails = new Vector<>();
        }

        public Identity getIdentity() {
            return mIdentity;
        }

        public void initialize(Node pNode) {
            DocumentTraversal traversable;

            if (pNode.getOwnerDocument() == null) // if in case pNode is Document itself
            {
                traversable = (DocumentTraversal) pNode;
            } else {
                traversable = (DocumentTraversal) pNode.getOwnerDocument();
            }
            TreeWalker walker = traversable.createTreeWalker(pNode, NodeFilter.SHOW_ALL, null, false);
            Node nodeChild = walker.firstChild(); // nodeChild is paramformatLine
            while (nodeChild != null) {
                String nodeChildName = nodeChild.getNodeName();
                //usda.weru.util.Util.debugPrint(debugFlg, " ConfigData : ActionFormat :---  NodeChildName is ---- : "
                //+ nodeChildName );
                if (nodeChildName.equals(XMLConstants.sidentity)) {
                    mIdentity = new Identity();
                    mIdentity.initialize(nodeChild);
                } else if (nodeChildName.equals(XMLConstants.sparamformatline)) {
                    Vector<String> paramFormatLine = new Vector<>();

                    Vector<Vector<String>> paramFormatLineInfo = new Vector<>();

                    // Modified from HERE -- DELETE Later -- Just for Testing purpose
                    //Node n2 = walker.getCurrentNode();
                    String s2 = nodeChild.getNodeName();
                    //System.out.println("CONFIGDATA : ActionFormat : initialize() :  ____MMMMM====== Name of the NODE is : "
                    //+ s2 );
                    NamedNodeMap nodeAttributes = nodeChild.getAttributes();

                    int attrLength = nodeAttributes.getLength();
                    String attrValue = "";
                    for (int i = 0; i < attrLength; i++) {
                        attrValue = nodeAttributes.getNamedItem("symbol").getNodeValue();
                        //System.out.println("CONFIGDATA : ActionFormat : initialize() :  ____MMMMM====== "
                        //+ "Name of Attributes are :==== " + attrLength + " -- Value is : " + attrValue );
                    }

                    // Modified till HERE -- DELETE Later -- Just for Testing purpose
                    Node paramNode = walker.firstChild();
                    while (paramNode != null) {
                        String paramName = XMLDoc.getTextData(paramNode);
                        paramFormatLine.add(paramName);

                        paramNode = walker.nextSibling();
                    }

                    Vector<String> temp = new Vector<>();
                    temp.add(attrValue);
                    paramFormatLineInfo.add(temp);
                    paramFormatLineInfo.add(paramFormatLine);
                    mParamFormatVecDetails.add(paramFormatLineInfo);
                    mParamFormatVec.add(paramFormatLine);
                    walker.parentNode(); // go back to the level of paramformat or identity
                }
                nodeChild = walker.nextSibling();
            } //end while(nodeChild != null)
        }

        public Vector<Vector<String>> getParamFormatVector() {
            return mParamFormatVec;
        }

        public Vector<Vector<Vector<String>>> getParamFormatVectorDetails() {
            return mParamFormatVecDetails;
        }
    } // end of Actionformat class
    static MyDateCellRenderer c_dateRenderer;
    static MyDateCellEditor c_dateEditor;
    static JCCellRenderer c_wrapRenderer;
    static JCCellRenderer c_multilineRenderer;
    static JCCellRenderer c_multicheckRenderer;
    static JCCellRenderer c_checkBoxRenderer;
    static MyCheckBoxCellEditor c_checkBoxEditor;
    static FileDropDown c_renFileList;
    static FileDropDown c_opFileList;
    static FileDropDown c_cropFileList;
    static FuelComboBoxRenderer c_fuelRenderer;
    static FuelComboBoxEditor c_fuelEditor;

    /**
     *
     * @return
     */
    protected static MyDateCellRenderer getDateRenderer() {
        if (c_dateRenderer == null) {
            c_dateRenderer = new MyDateCellRenderer(true);
        }
        return c_dateRenderer;
    }

    /**
     *
     * @return
     */
    protected static MyDateCellEditor getDateEditor() {
        if (c_dateEditor == null) {
            c_dateEditor = new MyDateCellEditor();
        }
        return c_dateEditor;
    }

    /**
     *
     * @return
     */
    protected static JCCellRenderer getWrapRenderer() {
        if (c_wrapRenderer == null) {
            c_wrapRenderer = MyArrayRenderer.wrap(new JCWordWrapCellRenderer());
        }
        return c_wrapRenderer;
    }

    /**
     *
     * @return
     */
    protected static JCCellRenderer getMultilineRenderer() {
        if (c_multilineRenderer == null) {
            c_multilineRenderer = MyArrayRenderer.wrap(new MyMultilineCellRenderer());
        }
        return c_multilineRenderer;
    }
    
    protected static JCCellRenderer getMultiCheckRenderer() 
    {
        if(c_multicheckRenderer == null) c_multicheckRenderer = MyArrayRenderer.wrap(mCellStyleTable.get("checkboxdata"));
        return c_multicheckRenderer;
    }

    /**
     *
     * @return
     */
    protected static JCCellRenderer getCheckBoxRenderer() {
        if (c_checkBoxRenderer == null) {
            c_checkBoxRenderer = new MyCheckBoxCellRenderer();
        }
        return c_checkBoxRenderer;
    }

    /**
     *
     * @return
     */
    protected static MyCheckBoxCellEditor getCheckBoxEditor() {
        if (c_checkBoxEditor == null) {
            c_checkBoxEditor = new MyCheckBoxCellEditor();
        }
        return c_checkBoxEditor;
    }

    /**
     *
     * @return
     */
    protected static FileDropDown getCropFileList() {
        if (c_cropFileList == null) {
            c_cropFileList = new FileDropDown(FileDropDown.FileType.Crop);
            TFile dir = new TFile(getDirectoryName(XMLConstants.scrop));
            c_cropFileList.setFile(dir);
        }
        return c_cropFileList;
    }

    /**
     *
     * @return
     */
    protected static FileDropDown getOpFileList() {
        if (c_opFileList == null) {
            c_opFileList = new FileDropDown(FileDropDown.FileType.Operation);
            TFile dir = new TFile(getDirectoryName(XMLConstants.soperation));
            c_opFileList.setFile(dir);
        }
        return c_opFileList;
    }

    /**
     *
     * @return
     */
    protected static FuelComboBoxRenderer getFuelComboRenderer() {
        if (c_fuelRenderer == null) {
            c_fuelRenderer = new FuelComboBoxRenderer();
        }
        return c_fuelRenderer;
    }

    /**
     *
     * @return
     */
    protected static FuelComboBoxEditor getFuelComboEditor() {
        if (c_fuelEditor == null) {
            c_fuelEditor = new FuelComboBoxEditor();
        }
        return c_fuelEditor;
    }

    /**
     *
     */
    public static void cleanup() {
        hackFileListThingies(null, null);

        c_dateRenderer = null;
        c_dateEditor = null;
        c_wrapRenderer = null;
        c_multilineRenderer = null;
        c_checkBoxRenderer = null;
        c_checkBoxEditor = null;
        c_renFileList = null;
        c_opFileList = null;
        c_cropFileList = null;

        c_formattedRenderer = null;
        c_formattedEditor = null;
    }

    /**
     *
     * @return
     */
    protected static FileDropDown getFileListRenderer() {
        if (c_renFileList == null) {
            c_renFileList = new FileDropDown(null);
        }
        return c_renFileList;
    }
    private static JCCellRenderer c_formattedRenderer;
    private static JCCellEditor c_formattedEditor;
    private static JCCellEditor c_multicheckEditor;

    /**
     *
     * @return
     */
    protected static JCCellRenderer getFormattedRenderer() {
        if (c_formattedRenderer == null) {
            c_formattedRenderer = MyArrayRenderer.wrap(new MyFormattedCellRenderer());
        }
        return c_formattedRenderer;
    }

    /**
     *
     * @return
     */
    protected static JCCellEditor getFormattedEditor() {
        if (c_formattedEditor == null) {
            c_formattedEditor = MyArrayEditor.wrap(new MyFormattedCellRenderer(), new MyFormattedCellEditor());
        }
        return c_formattedEditor;
    }
    
    /**
     *
     * @return
     */
    protected static JCCellEditor getMultiCheckEditor() 
    {
        if (c_multicheckEditor == null) c_multicheckEditor = MyArrayEditor.wrap(
                getMultiCheckRenderer(), new MyCheckBoxCellEditor());
        return c_multicheckEditor;
    }
    
    private static Map<String, Format> c_formats;

    /**
     *
     * @param format
     * @return
     */
    public static Format getFormat(String format) {
        if (format == null) {
            return null;
        }
        if (c_formats == null) {
            c_formats = new HashMap<String, Format>();
        }
        Format renderer = c_formats.get(format);
        if (renderer == null) {
            renderer = new DecimalFormat(format);
            c_formats.put(format, renderer);
        }
        return renderer;
    }

    /**
     *
     * @param table
     * @param adapter
     */
    public static void hackFileListThingies(Table table, Table.MyMouseAdapter adapter) {
        getFileListRenderer().setTable(table);
        getFileListRenderer().setMouseAdapter(adapter);

        getOpFileList().setTable(table);
        getOpFileList().setMouseAdapter(adapter);

        getCropFileList().setTable(table);
        getCropFileList().setMouseAdapter(adapter);
    }

    static class CellStyle extends XMLModeledObject {

        protected final String OBJECT_TAG = "styletag";
        protected final String OBJECT_BASE = "basestyle";
        /*
         *Local class variables
         */
        private JCCellStyle c_localStyle;

        CellStyle(Node node) {
            super(node);
            getJCCellStyle().setFont(new Font(getFontName(), getFontStyle(), getFontSize()));
            getJCCellStyle().setEditable(!isReadOnly());
            getJCCellStyle().setBackground(getCellColor());
            getJCCellStyle().setForeground(getFontColor());
            getJCCellStyle().setCellBorder(new JCCellBorder(getBorder()));
            getJCCellStyle().setCellBorderSides(getBorderSide());
            getJCCellStyle().setCellBorderColorMode(getBorderColorMode());
            getJCCellStyle().setCellBorderColor(getBorderColor());
            //Add special cell renderers
            switch (getCellRenderer()) {
                case "date":
                    getJCCellStyle().setCellRenderer(getDateRenderer());
                    getJCCellStyle().setCellEditor(getDateEditor());
                    break;
                case "wordwrap":
                    getJCCellStyle().setCellRenderer(getWrapRenderer());
                    break;
                case "multiline":
                    getJCCellStyle().setCellRenderer(getMultilineRenderer());
                    break;
                case "multicheck":
                    getJCCellStyle().setCellRenderer(getMultiCheckRenderer());
                    getJCCellStyle().setCellEditor(getMultiCheckEditor());
                    break;
                case "checkbox":
                    getJCCellStyle().setCellRenderer(getCheckBoxRenderer());
                    getJCCellStyle().setCellEditor(getCheckBoxEditor());
                    break;
                case "combobox":
                    break;
                case "opfilelist":
                    getJCCellStyle().setCellRenderer(getFileListRenderer());
                    getJCCellStyle().setCellEditor(getOpFileList());
                    break;
                case "cropfilelist":
                    getJCCellStyle().setCellRenderer(getFileListRenderer());
                    getJCCellStyle().setCellEditor(getCropFileList());
                    break;
                case "fuelcombobox":
                    getJCCellStyle().setCellRenderer(getFuelComboRenderer());
                    getJCCellStyle().setCellEditor(getFuelComboEditor());
                    break;
                default:
                    //aka "formatted"
                    getJCCellStyle().setCellRenderer(getFormattedRenderer());
                    getJCCellStyle().setCellEditor(getFormattedEditor());
                    break;
            }

        }
        
        CellStyle(Node node, InputLimits.TableStatus limit) {
            super(node);
            getJCCellStyle().setFont(new Font(getFontName(), getFontStyle(), getFontSize()));
            getJCCellStyle().setEditable(!isReadOnly());
            getJCCellStyle().setBackground(getCellColor(limit));
            getJCCellStyle().setForeground(getFontColor());
            getJCCellStyle().setCellBorder(new JCCellBorder(getBorder()));
            getJCCellStyle().setCellBorderSides(getBorderSide());
            getJCCellStyle().setCellBorderColorMode(getBorderColorMode());
            getJCCellStyle().setCellBorderColor(getBorderColor());
            //Add special cell renderers
            switch (getCellRenderer()) {
                case "date":
                    getJCCellStyle().setCellRenderer(getDateRenderer());
                    getJCCellStyle().setCellEditor(getDateEditor());
                    break;
                case "wordwrap":
                    getJCCellStyle().setCellRenderer(getWrapRenderer());
                    break;
                case "multiline":
                    getJCCellStyle().setCellRenderer(getMultilineRenderer());
                    break;
                case "checkbox":
                    getJCCellStyle().setCellRenderer(getCheckBoxRenderer());
                    getJCCellStyle().setCellEditor(getCheckBoxEditor());
                    break;
                case "combobox":
                    break;
                case "opfilelist":
                    getJCCellStyle().setCellRenderer(getFileListRenderer());
                    getJCCellStyle().setCellEditor(getOpFileList());
                    break;
                case "cropfilelist":
                    getJCCellStyle().setCellRenderer(getFileListRenderer());
                    getJCCellStyle().setCellEditor(getCropFileList());
                    break;
                case "fuelcombobox":
                    getJCCellStyle().setCellRenderer(getFuelComboRenderer());
                    getJCCellStyle().setCellEditor(getFuelComboEditor());
                    break;
                default:
                    //aka "formatted"
                    getJCCellStyle().setCellRenderer(getFormattedRenderer());
                    getJCCellStyle().setCellEditor(getFormattedEditor());
                    break;
            }

        }

        @Override
        protected void removeNonInheritableObjectData() {
            //Remove the default data tags
            c_ObjectData.remove("defaultdata");
            c_ObjectData.remove("defaultheader");
        }

        @Override
        protected String getObjectTag() {
            return OBJECT_TAG;
        }

        @Override
        protected String getObjectBase() {
            return OBJECT_BASE;
        }

        @Override
        protected void intilize() {
            super.intilize();
            sRootElement = "cellstyle";
            getJCCellStyle().setCellEditor(new JCStringCellEditor());
        }

        public String getStyleTag() {
            return (String) getObjectData("styletag");

        }

        private String getFontName() {
            return (String) getObjectData("fontname");
        }

        private int getFontStyle() {
            int style = Font.PLAIN;
            if (isFontBold() == true) {
                style = Font.BOLD;
            }
            return style;
        }

        private boolean isFontBold() {
            Object tempObject = getObjectData("fontbold");
            if (tempObject != null) {
                return (Boolean) tempObject;
            } else {
                return false;
            }
        }

        private boolean isReadOnly() {
            Object tempObject = getObjectData("readonly");
            if (tempObject != null) {
                return (Boolean) tempObject;
            } else {
                return false;
            }
        }

        private boolean isDefaultHeader() {
            Object tempObject = getObjectData("defaultheader");
            if (tempObject != null) {
                return (Boolean) tempObject;
            } else {
                return false;
            }
        }

        private boolean isDefaultData() {
            Object tempObject = getObjectData("defaultdata");
            if (tempObject != null) {
                return (Boolean) tempObject;
            } else {
                return false;
            }
        }
        
        private boolean isOpData()
        {
            Object tempObject = getObjectData("datacellstyle");
            if(tempObject != null)
            {
                return (Boolean) tempObject;
            }
            else
            {
                return false;
            }
        }

        private int getFontSize() {
            Integer tempObject = (Integer) getObjectData("fontsize");
            if (tempObject != null) {
                return tempObject;
            } else {
                return 12;
            }
        }

        private Color getCellColor() {
            Object tempObject = getObjectData("cellcolor");
            if (tempObject != null) {
                String hexValue = (String) tempObject;
                hexValue = hexValue.replace("#", "");
                Color tempColor = new Color(Integer.parseInt(hexValue, 16));
                return tempColor;
            } else {
                return Color.WHITE;
            }
        }
        
        private Color getCellColor(InputLimits.TableStatus limit) {
            switch(limit)
            {
                case OKAY:
                    Object tempObject = getObjectData("cellcolor");
                    if (tempObject != null) {
                        String hexValue = (String) tempObject;
                        hexValue = hexValue.replace("#", "");
                        Color tempColor = new Color(Integer.parseInt(hexValue, 16));
                        return tempColor;
                    } else {
                        return Color.WHITE;
                    }
                case WARNSAVE:
                    tempObject = getObjectData("softcolor");
                    if (tempObject != null) {
                        String hexValue = (String) tempObject;
                        hexValue = hexValue.replace("#", "");
                        Color tempColor = new Color(Integer.parseInt(hexValue, 16));
                        return tempColor;
                    } else {
                        return Color.WHITE;
                    }
                case NOSAVE:
                    tempObject = getObjectData("hardcolor");
                    if (tempObject != null) {
                        String hexValue = (String) tempObject;
                        hexValue = hexValue.replace("#", "");
                        Color tempColor = new Color(Integer.parseInt(hexValue, 16));
                        return tempColor;
                    } else {
                        return Color.WHITE;
                    }
                case INIT:
                    tempObject = getObjectData("initcolor");
                    if(tempObject != null)
                    {
                        Color tempColor = Color.decode((String) tempObject);
                        return tempColor;
                    }
                    else 
                    {
                        return Color.WHITE;
                    }
                default:
                    tempObject = getObjectData("cellcolor");
                    if (tempObject != null) {
                        String hexValue = (String) tempObject;
                        hexValue = hexValue.replace("#", "");
                        Color tempColor = new Color(Integer.parseInt(hexValue, 16));
                        return tempColor;
                    } else {
                        return Color.WHITE;
                    }
            }
        }

        private Color getFontColor() {
            Object tempObject = getObjectData("fontcolor");
            if (tempObject != null) {
                String hexValue = (String) tempObject;
                hexValue = hexValue.replace("#", "");
                Color tempColor = new Color(Integer.parseInt(hexValue, 16));
                return tempColor;
            } else {
                return Color.BLACK;
            }
        }

        private int getBorder() {
            Object tempObject = getObjectData("border");
            if (tempObject != null) {
                return ((Integer) tempObject);
            } else {
                return JCTableEnum.BORDER_PLAIN;
            }
        }

        private int getBorderSide() {
            Object tempObject = getObjectData("borderside");
            if (tempObject != null) {
                return ((Integer) tempObject);
            } else {
                return JCTableEnum.BORDERSIDE_ALL;
            }
        }

        private Color getBorderColor() {
            Object tempObject = getObjectData("bordercolor");
            if (tempObject != null) {
                String hexValue = (String) tempObject;
                hexValue = hexValue.replace("#", "");
                Color tempColor = new Color(Integer.parseInt(hexValue, 16));
                return tempColor;
            } else {
                return Color.BLACK;
            }

        }

        private int getBorderColorMode() {
            Object tempObject = getObjectData("bordercolormode");
            if (tempObject != null) {
                return ((Integer) tempObject);
            } else {
                return JCTableEnum.BASE_ON_BACKGROUND;
            }
        }

        public synchronized JCCellStyle getJCCellStyle() {
            if (c_localStyle == null) {
                c_localStyle = new JCCellStyle();
            }
            return c_localStyle;
        }

        public int getRowMinHeight() {
            Object tempObject = getObjectData("rowminheight");
            if (tempObject != null) {
                return ((Integer) tempObject);
            } else {
                return 1;
            }
        }

        public int getRowHeight() {
            Object tempObject = getObjectData("rowheight");
            if (tempObject != null) {
                return ((Integer) tempObject);
            } else {
                return 25;
            }
        }

        public int getRowMaxHeight() {
            Object tempObject = getObjectData("rowmaxheight");
            if (tempObject != null) {
                return ((Integer) tempObject);
            } else {
                return 1000;
            }
        }

        public String getCellRenderer() {
            Object tempObject = getObjectData("cellrenderer");
            if (tempObject != null) {
                return (String) tempObject;
            } else {
                return "normal";
            }
        }

        public boolean isValid() {
            //Check for required data
            if (getStyleTag() == null) {
                return false;
            }
            if (getStyleTag().length() == 0) {
                return false;
            }
            return true;
        }

        @Override
        Object catchSetObjectData(String elementName, String elementValue, NamedNodeMap attributes) {
            //Eventually plan to have data type detection in the super class based on XML schema.
            //This method will be for special cases of changing data.
            switch (elementName) {
                case "readonly":
                    return Boolean.parseBoolean(elementValue);
                case "defaultheader":
                    return Boolean.parseBoolean(elementValue);
                case "defaultdata":
                    return Boolean.parseBoolean(elementValue);
                case "fontbold":
                    return Boolean.parseBoolean(elementValue);
                case "fontsize":
                    return Integer.parseInt(elementValue);
                case "rowminheight":
                    return Integer.parseInt(elementValue);
                case "rowheight":
                    return Integer.parseInt(elementValue);
                case "rowmaxheight":
                    return Integer.parseInt(elementValue);            //Border Styles
                case "border":
                    if (elementValue.equalsIgnoreCase("out")) {
                        return JCTableEnum.BORDER_OUT;
                    } else if (elementValue.equalsIgnoreCase("in")) {
                        return JCTableEnum.BORDER_IN;
                    } else if (elementValue.equalsIgnoreCase("none")) {
                        return JCTableEnum.BORDER_NONE;
                    } else if (elementValue.equalsIgnoreCase("thin")) {
                        return JCTableEnum.BORDER_THIN;
                    } else if (elementValue.equalsIgnoreCase("plain")) {
                        return JCTableEnum.BORDER_PLAIN;
                    } else if (elementValue.equalsIgnoreCase("etched_in")) {
                        return JCTableEnum.BORDER_ETCHED_IN;
                    } else if (elementValue.equalsIgnoreCase("etched_out")) {
                        return JCTableEnum.BORDER_ETCHED_OUT;
                    } else if (elementValue.equalsIgnoreCase("frame_in")) {
                        return JCTableEnum.BORDER_FRAME_IN;
                    } else if (elementValue.equalsIgnoreCase("frame_out")) {
                        return JCTableEnum.BORDER_FRAME_OUT;
                    } else {
                        return 0;
                    }
                case "borderside":
                    int currentBorderSide;
                    Object tempObject = getObjectData("bordersides");
                    if (tempObject != null) {
                        //We have an exsiting border side value.  Keep adding them up.
                        currentBorderSide = (Integer) tempObject;
                    } else {
                        currentBorderSide = 0;
                    }

                    if (elementValue.equalsIgnoreCase("all")) {
                        return currentBorderSide + JCTableEnum.BORDERSIDE_ALL;
                    } else if (elementValue.equalsIgnoreCase("bottom")) {
                        return currentBorderSide + JCTableEnum.BORDERSIDE_BOTTOM;
                    } else if (elementValue.equalsIgnoreCase("left")) {
                        return currentBorderSide + JCTableEnum.BORDERSIDE_LEFT;
                    } else if (elementValue.equalsIgnoreCase("right")) {
                        return currentBorderSide + JCTableEnum.BORDERSIDE_RIGHT;
                    } else if (elementValue.equalsIgnoreCase("top")) {
                        return currentBorderSide + JCTableEnum.BORDERSIDE_TOP;
                    } else if (elementValue.equalsIgnoreCase("none")) {
                        return currentBorderSide + JCTableEnum.BORDERSIDE_NONE;
                    } else {
                        return currentBorderSide + 0;
                    }
                case "bordercolormode":
                    if (elementValue.equalsIgnoreCase("base_on_background")) {
                        return JCTableEnum.BASE_ON_BACKGROUND;
                    } else if (elementValue.equalsIgnoreCase("base_on_foreground")) {
                        return JCTableEnum.BASE_ON_FOREGROUND;
                    } else {
                        return 0;
                    }
            }
            return super.catchSetObjectData(elementName, elementValue, attributes);
        }

        @Override
        protected Hashtable<String, CellStyle> getBaseObjectTable() {
            return MCREWConfig.mCellStyleTable;
        }
    }

    /**
     * Returns an ArrayList object that can be then used in a combobox JCCell editor or renderer.
     * The tag argument must correspond to an exsiting ChoiceList.  Otherwise an empty ArrayList is
     * returned.  Null is not returned.
     *
     * @param tag a string specifying the
     * @return the ChoiceList as an ArrayList
     * @see Hashtable
     */
    static public Vector<String> getChoiceVector(String tag) {
        ChoiceList choiceList = mChoiceListTable.get(tag);
        Enumeration<String> enumChoices = choiceList.getChoices().elements();
        Vector<String> tmpChoiceList = new Vector<>();
        while (enumChoices.hasMoreElements()) {
            String choice = enumChoices.nextElement();
            tmpChoiceList.add(choice);
        }
        return tmpChoiceList;
    }

    /**
     *
     * @param tag
     * @return
     */
    static public Hashtable<String, String> getChoiceHash(String tag) {
        ChoiceList choiceList = mChoiceListTable.get(tag);
        return choiceList.getChoices();
    }

    static class ChoiceList extends XMLModeledObject {

        private String c_tag;
        private Hashtable<String, String> c_choices;

        ChoiceList(Node node) {
            super(node);
        }

        public Hashtable<String, String> getChoices() {
            return c_choices;
        }

        @Override
        protected void intilize() {
            super.intilize();
            c_choices = new Hashtable<>();
        }

        @Override
        protected Hashtable<String, ? extends XMLModeledObject> getBaseObjectTable() {
            return null;
        }

        public boolean isValid() {
            if (c_tag != null) {
                return true;
            } else {
                return false;
            }
        }

        public String getTag() {
            return c_tag;
        }

        @Override
        Object catchSetObjectData(String elementName, String elementValue, NamedNodeMap attributes) {
            if (elementName.equals("choicelisttag")) {
                c_tag = elementValue;
            } else if (elementName.equals("choice")) {
                String value = null;
                if (attributes != null) {
                    try {
                        value = attributes.getNamedItem("value").getNodeValue();
                    } catch (Exception e) {
                        //Error
                    }
                    if (value != null && elementValue != null) {
                        c_choices.put(value, elementValue);
                    }
                }
            }
            return elementValue;
        }

        @Override
        protected void removeNonInheritableObjectData() {
        }

        @Override
        protected String getObjectTag() {
            return null;
        }

        @Override
        protected String getObjectBase() {
            return null;
        }
    }

    /**
     * XMLModeledObject class is used as the base of other objects that are stored in xml files.
     * This class handles the XML parsing through the Java xml package.  Data is stored in a hashtable
     * but an overidable method is called first to allow child classes to changed the data before it is
     * stored.
     * @author Joseph Levin
     */
    abstract static class XMLModeledObject {

        /**
         * Hashtable used to store all the data loaded from the xml node.
         */
        protected Hashtable<String, Object> c_ObjectData;
        /**
         * String value indicating the base xml element name.  This is used for debug print outs.
         */
        protected String sRootElement;

        /**
         * Creates a new XMLModeledObject.  This object will do very little because no node is passed.
         */
        XMLModeledObject() {
            intilize();
            //We can not do much without a node to load data from
        }

        /**
         * Creates a new XMLModeledObject from a given xml node.  All first level child nodes are parsed.
         * @param node Node object used for parsing.
         */
        XMLModeledObject(Node node) {
            this(node, "*");
        }

        /**
         * Creates a new XMLModeledObject from a passed node and an xpath expression indicating which child nodes to parse.
         * @param node Node object used for parsing.
         * @param xpathExpression String value repersenting which child nodes to load.  Only first level nodes can be used.
         */
        XMLModeledObject(Node node, String xpathExpression) {
            intilize();
            loadObjectFromNode(node, xpathExpression);
        }

        /**
         * Loads the objects data from the xml node.  Child nodes found in the xpath expression will be parsed.
         * @param node Node object to parse
         * @xpathexpression String value representing child nodes to use.
         */
        protected void loadObjectFromNode(Node node, String xpathExpression) {
            //System.out.println("Loading " + sRootElement + " object from XML node.");
            try {
                NodeList selectedNodes = getChildNodes(node, xpathExpression);
                if (selectedNodes.getLength() > 0) {
                    Node childNode;
                    for (childNode = selectedNodes.item(0); childNode != null; childNode = childNode.getNextSibling()) {
                        if (childNode.getNodeName().equals("#text") == false) {
                            setObjectData(childNode.getNodeName(), getElementValue(childNode), childNode.getAttributes());
                        }
                    }
                    //Clean Up
                    childNode = null;
                }

            } catch (DOMException e) {
                //Error loaded the xml node into the object
                //System.out.println("Error loading a node value");
                e.printStackTrace();
            }
            //System.out.println("Finished Loading " + sRootElement + " object from XML node.");
        }

        /**
         * Returns the xml node objects which match the xPath Expression in the context of the given node.
         * @param node Node object to parse.
         * @param xpathExpression XPath Expression to match against.
         * @return NodeList containing child nodes matching the xpath against the node.
         */
        protected NodeList getChildNodes(Node node, String xpathExpression) {
            XPath xpath = XPathFactory.newInstance().newXPath();
            try {
                return (NodeList) xpath.evaluate(xpathExpression, node, XPathConstants.NODESET);
            } catch (XPathExpressionException e) {
                return null;
            }

        }

        /**
         * Returns the xml node objects which match the "*" xPath Expression in the context of the given node.
         * @param node Node object to parse.
         * @return NodeList containing child nodes matching the xpath against the node.
         */
        protected NodeList getChildNodes(Node node) {
            return getChildNodes(node, "*");
        }

        /**
         * Returns the text representation of the xml node.
         * @param node Node object to evaluate
         * @return String String evaluation of the node.
         */
        private String getElementValue(Node node) {
            Node childNode;
            if (node != null) {
                if (node.hasChildNodes()) {
                    for (childNode = node.getFirstChild(); childNode != null; childNode.getNextSibling()) {
                        if (childNode.getNodeType() == Node.TEXT_NODE) {
                            return childNode.getNodeValue();
                        }
                    }

                }
            }
            return "";
        }

        /**
         * Saves a data value to the local hashtable.  catchSetObjectData is called before
         * the data is saved to allow an inheriting class to override the method and modify the
         * data before it is saved.
         * @param elementName Name of the element being saved.
         * @param elementValue Value of the element being saved.
         * @attributes NamedNodeMap of the attributes associated with the node.
         *
         */
        protected void setObjectData(String elementName, String elementValue, NamedNodeMap attributes) {
            //Catch the special 'base' tag.  Load the elements from the base object
            if (elementName.equals(getObjectBase())) {
                //Load style
                String objectTag = (String) getObjectData(getObjectTag());
                Hashtable<String, XMLModeledObject> loadedXMLObjects
                        = Caster.<Hashtable<String, XMLModeledObject>>cast(getBaseObjectTable());
                XMLModeledObject baseObject = loadedXMLObjects.get(elementValue);
                c_ObjectData = Caster.<Hashtable<String, Object>>cast(baseObject.getObjectDataTable().clone());
                //Put the correct tag in the hashtable
                c_ObjectData.put(getObjectTag(), objectTag);
                removeNonInheritableObjectData();
                c_ObjectData.put("datacellstyle", "datadefault");
                //System.out.println("XML Object Loaded From Base Object");
            } else {
                Object elementValueObject = catchSetObjectData(elementName, elementValue, attributes);
                c_ObjectData.put(elementName, elementValueObject);
                //System.out.println("XML Element Loaded: " + elementName + " = '" + elementValueObject.toString() + "'");
            }

        }

        /**
         * Intended to be overiden by inheriting classes, this method returns the name of
         * the xml tag that idetifies the object.  This tag is used by the object inheriting
         * logic to prevent the identifier from being inherited.
         * @return String the identifier tag
         */
        abstract protected String getObjectTag();

        /**
         * Intended to be overiden by inheriting classes, this method returns the name of
         * the xml tag that indetifies parent object to be inherited.  This tag is used by the object inheriting
         * logic to understand it needs to inherit something.
         * @return String the base indetifier tag
         */
        abstract protected String getObjectBase();

        /**
         * Intended to be overriden by inheriting classes, this purges data from the hashtable
         * which the developer does not want to be inherited
         */
        abstract protected void removeNonInheritableObjectData();

        /**
         * Intended to be overiden by inheriting classes, this method returns a hashtable which contains
         * previously loaded XMLModeledObjects.  This is used by the inheritance logic to find a parent.
         * @return Hashtable containing possible parents.
         */
        abstract protected Hashtable<String, ? extends XMLModeledObject> getBaseObjectTable();

        /**
         * Returns the value of the specified element.
         * @param elementName Element to return the value of.
         * @return Object value store in the hashtable against the elementname.
         */
        protected Object getObjectData(String elementName) {
            Object temp = c_ObjectData.get(elementName);
            return temp;
        }

        /**
         * Returns the entire object data hashtable
         * return Hashtable conataing all the loaded data of the object.
         */
        public Hashtable<String, Object> getObjectDataTable() {
            return c_ObjectData;
        }

        /**
         * This method is intened to be overiden by an inheriting class so data may be changed before being saved.
         * @param elementName Name of the element being saved.
         * @param elementValue Value of the element being saved.
         * @attributes NamedNodeMap of the attributes associated with the node.
         */
        Object catchSetObjectData(String elementName, String elementValue, NamedNodeMap attributes) {
            return elementValue;
        }

        /**
         * Intilizes variables unaffected by the constructors
         */
        protected void intilize() {
            sRootElement = "undefined";
            c_ObjectData = new Hashtable<>();
        }
    }

    /**
     *
     * @return
     */
    public static String getOperationDateFormat() {
        return c_operationDateFormat;
    }

    private static final Color COLOR_DISABLED = new Color(230, 230, 230);

    /**
     *
     * @return
     */
    public static Color getDisabledColor() {
        return COLOR_DISABLED;
    }
}
