/*
 * @(#) CData.java  1.10 10/09/02
 *
 * Copyright ***,  All Rights Reserved.
 * 
 * This software is the proprietary information of ********  
 * Use is subject to license terms.
 * 
 */

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.JFileChooser;
import javax.swing.border.*;
import javax.swing.event.*;
import java.io.*;
import java.lang.*;
import java.util.*;

/**
 * This class stores all the data used
 *
 */
public class CData {
    
    //-----------------------------------------------------------------
    //
    // static data members
    //
    //-----------------------------------------------------------------

    /** 
     * an error message to be printed when an attempt to use XML features
     * is made and expat is not configured 
     */
    public static String ERR_NO_EXPAT ="To use our XML features, see the fundamentals tutorial on our website for information about configuring your enlistment.";

    /** 
     * an error message to be printed when an attempt is made to save a
     * file in XML format (this option is not supported)
     */
    public static String ERR_NO_XML_OUTPUT = "XML output is not currently suported.";

    /**
     *  an error message to indicate that the network converter could not
     *  be started
     */
    public static String ERR_CONV_NO_START = "Failed to start the network converter."; 
    
    /**
     *  an error message to indicate that the network converter was
     *  interrupted
     */
    public static String ERR_CONV_INTR = "The network converter was interrupted."; 

    /**
     *  an error message to indicate that the network converter was
     *  interrupted
     */
    public static String ERR_CONV_FAIL = "The network converter indicated failure."; 

    /**
     *  an error message to indicate that the language model file is
     * invalid
     */
    public static String ERR_CONV_INVALID = "The language model file is invalid."; 

    /** 
     * a flag which indicates whether expat is configured
     */
    public static boolean expat_is_configured = false;

    /**
     *  constants used by the application
     */
    public static String ISIP_DEVEL = "ISIP_DEVEL";
    public static String ISIP_DEFAULT_PATH = System.getProperty(ISIP_DEVEL);
    public static String ISIP_DEFINES = "ISIP_DEFINES";
    public static String HAVE_EXPAT = "HAVE_EXPAT";
    public static int STRING_NOT_FOUND = -1;

    /**
     *  constants used by the application
     */
    public static String FILE_FILTER_DESCRIPTION_NATIVE 
	= "NATIVE";
    public static String FILE_FILTER_DESCRIPTION_IHD 
	= "IHD (Text)";
    public static String FILE_FILTER_DESCRIPTION_JSGF 
	= "JSGF (Text)";
    public static String FILE_FILTER_DESCRIPTION_XML 
	= "XML (Text)";
    public static String FILE_FILTER_DESCRIPTION_BINARY 
	= "IHD (Binary)";
    public static String FILE_FILTER_DESCRIPTION_JSGF_BINARY 
	= "JSGF (Binary)";
    public static String FILE_FILTER_DESCRIPTION_XML_BINARY 
	= "XML (Binary)";
    public static String FILE_FILTER_DESCRIPTION_ABNF 
	= "ABNF (Text)"; 
    public static String FILE_FILTER_DESCRIPTION_BNF 
	= "BNF (Text)"; 
    public static String FILE_FILTER_DESCRIPTION_ABNF_BINARY 
	= "ABNF (Binary)"; 
    public static String FILE_FILTER_DESCRIPTION_BNF_BINARY
	= "BNF (Binary)"; 
    public static String FILE_FILTER_DESCRIPTION_SM 
	= "SOF";

    public static String FILE_FILTER_EXTENSION_NATIVE 
	= "text";
    public static String FILE_FILTER_EXTENSION_IHD 
	= "sof";
    public static String FILE_FILTER_EXTENSION_JSGF 
	= "sof";
    public static String FILE_FILTER_EXTENSION_XML 
	= "sof";
    public static String FILE_FILTER_EXTENSION_BINARY 
	= "sof";
    public static String FILE_FILTER_EXTENSION_ABNF 
	= "sof";
    public static String FILE_FILTER_EXTENSION_BNF 
	= "sof";
    public static String FILE_FILTER_EXTENSION_SM 
	= "sof";
    public static String des;
    
    // location of the converter
    //
    public static String OPTION_FILE = new String("./text/options.text");
    public static String ISIP_NETWORK_CONVERTER
	= "isip_network_converter";
    public static final String DEF_ISIP_NETWORK_CONVERTER
	= "isip_network_converter";
    public static final String ISIP_NETWORK_CONVERTER_TAG
	= "isip_network_converter";

    public static String DEBUG_FLAG
	= "false";
    public static final String DEF_DEBUG_FLAG
	= "false";
    public static final String DEBUG_FLAG_TAG
	= "DEBUG_FLAG";

    public static String DEFAULT_LM_FILE = "lm_model.sof";
    public static String DEFAULT_SM_FILE = "sm_model.sof";

    public static String LEVEL_TREE_ROOT_NAME = "Root";
    public static String LEVEL_TREE_TOP_GRAMMAR = "sentence";
    public static String LEVEL_TREE_TOP_NAME = "Word";
    public static String LEVEL_TREE_DEFAULT_NAME = "New Level";

    public static String SYMBOL_TYPE_NON_SPEECH = "non-speech";
    public static String SYMBOL_TYPE_DUMMY = "dummy";
    public static String SYMBOL_TYPE_NON_SPEECH_BOUNDARY = "non-speech-boundary";
    public static String SYMBOL_TYPE_NON_SPEECH_INTERNAL = "non-speech-internal";
    public static String SYMBOL_TYPE_SPENALTY_EXCLUDE = "spenalty-exclude";
    public static String SYMBOL_TYPE_SKIP = "skip";
    public static String SYMBOL_TYPE_CONTEXT_LESS = "context-less";
    public static String SYMBOL_TYPE_EXCLUDE = "exlude";
    public static String SYMBOL_TYPE_ST = "ST";
    
    /**
     *  user interface element size constants
     */
    public static int WORKAREA_WIDTH = 500;
    public static int WORKAREA_HEIGHT = 400;
    public static int HIGHLIGHT_WIDTH = 1;
    public static int MAX_RESERVED = 4;
    public static int VERTEX_MARGIN = 0;

    public static int VERTEX_WIDTH = 70;    
    public static int VERTEX_HEIGHT = 48;

    /**
     *  user interface images
     */
    public static String START_IMAGE = new String("./images/term_img.gif");
    public static String TERM_IMAGE = new String("./images/term_img.gif");
    public static String NODE_IMAGE = new String("./images/node_img.gif");
    public static String ABOUT_IMAGE = new String("./images/node_img.gif");

    public static String START_VERTEX_NAME = new String("Start");
    public static String TERM_VERTEX_NAME = new String("Stop");
    public static String NODE_VERTEX_NAME = new String("Node");

    /**
     *  action commands constants
     */
    public static final String AM_NONE = "0000";
    public static final String AM_FILE_NEW = "0101";
    public static final String AM_FILE_OPEN = "0102";
    public static final String AM_FILE_SAVE = "0103";
    public static final String AM_FILE_SAVE_AS = "0104";
    public static final String AM_FILE_SAVE_ALL = "0105";
    public static final String AM_FILE_CLOSE = "0106";
    public static final String AM_FILE_EXIT = "0107";

    public static final String AM_GRAMMAR_INSERT_START = "0201";
    public static final String AM_GRAMMAR_INSERT_STOP = "0202";
    public static final String AM_GRAMMAR_INSERT_NODE = "0203";
    public static final String AM_GRAMMAR_INSERT_ARC = "0204";
    public static final String AM_GRAMMAR_INSERT_SELF_ARC = "0205";
    public static final String AM_GRAMMAR_COPY = "0206";
    public static final String AM_GRAMMAR_CUT = "0207";
    public static final String AM_GRAMMAR_PASTE = "0208";
    public static final String AM_GRAMMAR_DELETE = "0209";
    public static final String AM_GRAMMAR_COPY_GRAPH = "0210";
    public static final String AM_GRAMMAR_PASTE_GRAPH = "0211";
    public static final String AM_GRAMMAR_ADD_GRAPH = "0212";
    public static final String AM_GRAMMAR_DELETE_GRAPH = "0213";
    public static final String AM_GRAMMAR_WEIGHT_GRAPH = "0214";

    public static final String AM_H_ADD_LEVEL = "0301";
    public static final String AM_H_DELETE_LEVEL = "0302";
    public static final String AM_H_ADD_GRAPH = "0303";
    public static final String AM_H_DELETE_GRAPH = "0304";
    public static final String AM_H_SYMBOLS = "0305";
    public static final String AM_H_CHECK_LEVEL = "0306";

    public static final String AM_HELP_ABOUT = "0401";

    public static final int FOCUS_NONE = 0;
    public static final int FOCUS_VERTEX = 1;
    public static final int FOCUS_ARC = 2;

    /**
     *  vertex type constants
     */
    public static final int NONE_VERTEX = -1;
    public static final int START_VERTEX = 0;
    public static final int TERM_VERTEX = 1;
    public static final int NODE_VERTEX = 2;
    public static final int START = 4;
    public static final int STOP = 5;
    public static final int CUSTOM = 6;

    /**
     *  different font constants
     */
    public static final int MAX_FONT_SIZE = 12;
    public static final int COEFF_FONT_SIZE = 12;
    public static final Font ARC_FONT = new Font("Helvetica", Font.BOLD, 10);
    public static final Font ARIAL_FONT 
	= new Font("Arial", Font.PLAIN, MAX_FONT_SIZE);

    /**
     *  io constants
     */
    // search level tags
    //
    public static final String IO_CDATA_LEVEL_SIZE = "level_size";

    public static final String IO_LEVEL_NAME = "_name";
    public static final String IO_LEVEL_GRAPH_SIZE = "_graph_size";
    public static final String IO_LEVEL_GRAPH_NAME = "_graph_name";
    public static final String IO_LEVEL_SYMBOL_SIZE = "_symbol_size";
    public static final String IO_LEVEL_SYMBOL = "_symbol_";
    public static final String IO_LEVEL_CONTEXT_SIZE = "_context_size";
    public static final String IO_LEVEL_CONTEXT = "_context_";
    public static final String IO_LEVEL_NON_SPEECH_SYMBOL_SIZE = "_non_speech_symbol_size";
    public static final String IO_LEVEL_NON_SPEECH_SYMBOL = "_non_speech_symbol_";
   
    public static final String IO_LEVEL_NONSPEECHBOUNDARY_SYMBOL_SIZE = "_non_speech_boundary_symbol_size";
    public static final String IO_LEVEL_NONSPEECHBOUNDARY_SYMBOL = "_non_speech_boundary_symbol_";
    
    public static final String IO_LEVEL_NONSPEECHINTERNAL_SYMBOL_SIZE = "_non_speech_internal_symbol_size";
    public static final String IO_LEVEL_NONSPEECHINTERNAL_SYMBOL = "_non_speech_internal_symbol_";

    public static final String IO_LEVEL_SPENALTYEXCLUDE_SYMBOL_SIZE = "_spenalty_exclude_symbol_size";
    public static final String IO_LEVEL_SPENALTYEXCLUDE_SYMBOL = "_spenalty_exclude_symbol_";
    
    public static final String IO_LEVEL_CONTEXTLESS_SYMBOL_SIZE = "_contextless_symbol_size";
    public static final String IO_LEVEL_CONTEXTLESS_SYMBOL = "_contextless_symbol_";
    public static final String IO_LEVEL_DUMMY_SYMBOL_SIZE = "_dummy_symbol_size";
    public static final String IO_LEVEL_DUMMY_SYMBOL = "_dummy_symbol_";
    public static final String IO_LEVEL_SKIP_SYMBOL_SIZE = "_skip_symbol_size";
    public static final String IO_LEVEL_SKIP_SYMBOL = "_skip_symbol_";
    public static final String IO_LEVEL_EXCLUDE_SYMBOL_SIZE = "_exclude_symbol_size";
    public static final String IO_LEVEL_EXCLUDE_SYMBOL = "_exclude_symbol_";
    public static final String IO_LEVEL_ST_SYMBOL_SIZE = "_ST_symbol_size";
    public static final String IO_LEVEL_ST_SYMBOL = "_ST_symbol_";

    // graph tags
    //
    public static final String IO_IHD_VERTEX_SIZE = "_vertex_size";
    public static final String IO_IHD_ARC_SIZE = "_arc_size";

    // vertex tags
    //
    public static final String IO_VERTEX_SYMBOL_SIZE = "_symbol_size";
    public static final String IO_VERTEX_NAME = "_name";
    public static final String IO_VERTEX_TYPE = "_type";
    public static final String IO_VERTEX_WIDTH = "_width";
    public static final String IO_VERTEX_HEIGHT = "_height";
    public static final String IO_VERTEX_LOC_X = "_loc_x";
    public static final String IO_VERTEX_LOC_Y = "_loc_y";
    public static final String IO_VERTEX_SYMBOL = "_S";
    
    // arc tags
    //
    public static final String IO_ARC_FROM_ID = "_from";
    public static final String IO_ARC_TO_ID = "_to";
    public static final String IO_ARC_WEIGHTS = "_weight";
    public static final String IO_ARC_EPSILON = "_epsilon";
    public static final String IO_ARC_WIDTH = "_width";
    public static final String IO_ARC_HEIGHT = "_height";
    public static final String IO_ARC_LOC_X = "_loc_x";
    public static final String IO_ARC_LOC_Y = "_loc_y";

    // prefix tags
    //
    public static final String IO_SEARCHLEVEL_PREFIX = "L";
    public static final String IO_IHD_PREFIX = "G";
    public static final String IO_VERTEX_PREFIX = "V";
    public static final String IO_ARC_PREFIX = "A";

    // prefix tags
    //
    public static final String PREFIX_INDENT = "  ";
    public static final String ERR_LEVEL_NO_SYMBOLS = "no symbols defined";
    public static final String ERR_LEVEL_NO_GRAPHS = "no graphs defined";
    public static final String ERR_GRAPH_NO_ARC = "no arc defined";
    public static final String ERR_GRAPH_NO_VERTEX = "no vertex defined";
    public static final String ERR_VERTEX_NO_SYMBOL = "no symbol defined";

    /**
     * data member about i/o
     */
    public static Properties io_d = new Properties();

    /**
     *  data members used by other classes
     */
    public static UIMainFrame main_frame_d = null;
    public static Vector<SearchLevel> search_levels_d = new Vector<SearchLevel>();
    public static EventHandler event_handler_d = new EventHandler();
    public static WorkArea work_area_d = new WorkArea();
    public static JTree level_tree_d = null;
    public static UISymbolDialog symbol_dlg_d = null;

    /**
     * data member about current status
     */
    public static DiGraph curr_graph_d = null;
    public static int curr_level_index_d;
    public static int curr_graph_index_d;

    // language model file
    //
    public static String curr_file_d = null;
    public static String temp_file_d = null;
    public static String open_lm_file_description_d = null;
    public static String lm_file_description_d = null;

    // statistical model file
    //
    public static String curr_sm_file_d = null;

    // error handling
    //
    public static String error_message_d = "";
    public static boolean err_flag_d = false;

    //-----------------------------------------------------------------
    //
    // instance data members
    //
    //-----------------------------------------------------------------

    //-----------------------------------------------------------------
    //
    // function members
    //
    //-----------------------------------------------------------------

    /**
     * sets the environment
     */
    public static void setEnvironment() {
	
	EnvProperties props = new EnvProperties();
	String devel_dir = props.run(ISIP_DEVEL);
	String isip_defines = props.run(ISIP_DEFINES);

	// prevent null reference exception
	//
	if(isip_defines != "null") {
	    
	    // check whether the environment variable "ISIP_DEFINES" 
	    // contains "HAVE_EXPAT"
	    //
	    if(isip_defines.lastIndexOf(HAVE_EXPAT) != STRING_NOT_FOUND) {
		expat_is_configured = true;
	    }
	    else {
		expat_is_configured = false;
	    }
	}

	if (devel_dir != "null") {
	    
	    String curr_path = devel_dir + "/util/speech/isip_network_builder";

	    OPTION_FILE = new String(curr_path + "/text/options.text");
	    START_IMAGE = new String(curr_path + "/images/term_img.gif");
	    TERM_IMAGE = new String(curr_path + "/images/term_img.gif");
	    NODE_IMAGE = new String( curr_path + "/images/node_img.gif");
	    ABOUT_IMAGE = new String(curr_path + "/images/node_img.gif");

	} else {

	    OPTION_FILE = new String("./text/options.text");
	    START_IMAGE = new String("./images/term_img.gif");
	    TERM_IMAGE = new String("./images/term_img.gif");
	    NODE_IMAGE = new String("./images/node_img.gif");
	    ABOUT_IMAGE = new String("./images/node_img.gif");
	}

    }

    /**
     * initializes the global data
     */
    public static void init() {
	
	// clear main frame tags
	//
	if ( main_frame_d != null ){
	    main_frame_d.jTabbedPaneLeft.removeAll();
	    main_frame_d.level_graphs_d = new Vector<String>();
	}

	search_levels_d = new Vector<SearchLevel>();

	curr_level_index_d = -1;
	curr_graph_index_d = 0;
	curr_graph_d = null;
	
	// set the size of vertex
	//
	ImageIcon icon  = new ImageIcon(CData.START_IMAGE);
	VERTEX_WIDTH = icon.getIconWidth();    
	VERTEX_HEIGHT = icon.getIconHeight();

	// check the menu
	//
	if ( main_frame_d != null ){
	    main_frame_d.checkMenu();
	}
    }

    /**
     * add a new level to the search levels 
     * 
     * @param level_index_a the index of the added level
     */
    public static void addLevel(int level_index_a) {
	
	// init a start level structure
	//
	SearchLevel curr_level = new SearchLevel();
	SearchLevel prev_level = null;

	// init current level
	//
	curr_level.init();

	if ( level_index_a  > 0 ){
	    prev_level = (SearchLevel)search_levels_d.get(level_index_a - 1);

	    // curr_level.graph_names_d = (Vector)prev_level.symbols_d.clone();
	    //
	    curr_level.graph_names_d = prev_level.symbols_d;

	    curr_level.level_name_d = LEVEL_TREE_DEFAULT_NAME;
	    curr_level.symbols_d = new Vector<String>();
	
	    // add to the search levels
	    //
	    //seaarch_levels_d.add (curr_level);

	}
	else {

	    // init a start level structure
	    //
	    curr_level.level_name_d = LEVEL_TREE_DEFAULT_NAME;
	    curr_level.graph_names_d = new Vector<String>();
	    curr_level.graph_names_d.add(LEVEL_TREE_TOP_GRAMMAR);

	    curr_level.symbols_d = new Vector<String>();

	    DiGraph top_graph = new DiGraph();
	    curr_level.graphs_d = new HashMap<String,DiGraph>();
	    curr_level.graphs_d.put(LEVEL_TREE_TOP_GRAMMAR, top_graph);
	
	    // generate a new workarea
	    //
	    //search_levels_d.add (curr_level);
	}
	
	// add this level to the main frame
	//
	search_levels_d.insertElementAt(curr_level, level_index_a);
	main_frame_d.insertLevel(curr_level, level_index_a);
	    
	// set current status
	//
	curr_level_index_d = level_index_a;
	curr_graph_index_d = 0;
	curr_graph_d = null;
	event_handler_d.curr_vertex_focus_d = null;

    }

    /**
     * add a new level to the search levels 
     * 
     * @param level_index_a the index of the added level
     */
    public static void addLevel(int level_index_a, SearchLevel curr_level_a) {
	
	// add this level to the main frame
	//
	search_levels_d.add (curr_level_a);
	main_frame_d.addLevel(curr_level_a);

	// set current status
	//
	curr_level_index_d = level_index_a;
	curr_graph_index_d = 0;
	curr_graph_d = null;
	event_handler_d.curr_vertex_focus_d = null;

    }

    /**
     * get current search level 
     * 
     * @return current search level or null if current index is negative
     */
    public static SearchLevel getCurrLevel() {

	// test curr_level_index_d
	//
	if ( curr_level_index_d < 0 ){
	    return null;
	}

	// init a start level structure
	//
	SearchLevel curr_level = (SearchLevel)
	    search_levels_d.get(curr_level_index_d);
	return curr_level;
    }

    /**
     * get current search level 
     * 
     * @param level_index_a index of level to get
     * @return search level of index
     */
    public static SearchLevel getLevel(int level_index_a) {

	// init a start level structure
	//
	SearchLevel curr_level = (SearchLevel)
	    search_levels_d.get(level_index_a);
	return curr_level;
    }

    /**
     * convert a index vector to a string vector
     * 
     * @param indices_a a vector of indices to be symbolized
     * @return a vector of string of symbols
     */
    public static Vector<String> indexToSymbols(Vector<Integer> indices_a) {
	
	Vector<String> symbols = new Vector<String>();

	for (int i = 0; i < indices_a.size(); i++) {
	    
	    int curr_index = ((Integer)indices_a.get(i)).intValue();
	    SearchLevel curr_level = getCurrLevel();
	    symbols.add(curr_level.symbols_d.get(curr_index));
	}
	 
	return symbols;
    }

    /**
     * conver a string vector to a index vector
     * 
     * @param symbols_a a vector of symbols
     * @return a vector of integers of indices of symbols
     */
    public static Vector<Integer> symbolsToIndices(Vector<String> symbols_a) {
	
	Vector<Integer> indices = new Vector<Integer>();

	for (int i = 0; i < symbols_a.size(); i++) {
	    
	    Object curr_symbol = symbols_a.get(i);
	    SearchLevel curr_level = getCurrLevel();
	    int index = curr_level.symbols_d.indexOf(curr_symbol);
	    indices.add(new Integer(index));
	}
	 
	return indices;
	
    }

    /**
     * store the data into a file
     *
     * @throws Exception if file input stream cannot be properly intialized
     */
    public static void loadOptions() {

	Properties options = new Properties();

	// read data from a file
	//
	try{	    
	    options.clear();
	    options.load(new FileInputStream(OPTION_FILE));

	} catch (Exception e){
	    e.printStackTrace(System.out);
	}

	ISIP_NETWORK_CONVERTER = 
	    options.getProperty(ISIP_NETWORK_CONVERTER_TAG, DEF_ISIP_NETWORK_CONVERTER);

	DEBUG_FLAG = 
	    options.getProperty(DEBUG_FLAG_TAG, DEF_DEBUG_FLAG);

	CData.printDebugMsg("using: " + ISIP_NETWORK_CONVERTER );

	// read data from a file
	//
	/*
	try{	    
	    options.store(new FileOutputStream(OPTION_FILE), "isip_network_builder options");

	} catch (Exception e){
	    e.printStackTrace(System.out);
	}
	*/
    }

    /**
     * check errors in the model
     * 
     * @return true if check is passed, false if otherwise
     */
    public static boolean check() {
	
	// set the inital error message
	//
	error_message_d = 
	    "Found errors in the model, cannot save in other format: \n";
	
	// check all symbols
	//
	int num_levels = search_levels_d.size();
	
	
	for (int i= 0; i < num_levels ; i++) {
	    error_message_d += 
		"checking symbols at level: " + String.valueOf(i) +"\n";
	    SearchLevel curr_level = (SearchLevel)search_levels_d.get(i);
	    if ( i == 0 ){
		curr_level.graph_names_d.setSize(1);
	    }
	    if ( i+1 >= num_levels ){
		break;
	    }
	    SearchLevel next_level = (SearchLevel)search_levels_d.get(i+1);

	    
	    
	    for ( int j = 0; j < curr_level.symbols_d.size(); j++ ){
		String curr_symbol = (String)curr_level.symbols_d.get(j);
		
		int m = 0; 
		for ( int z = 0; z < curr_level.dummy_d.size(); z++) {
		    if (curr_symbol == curr_level.dummy_d.get(z)) {
			m = m + 1;
		    }     
		}  
		if ( m == 0) {                                                
		    if (!next_level.graph_names_d.contains(curr_symbol)){
			error_message_d += 
			    "No corresponding graph for symbol: " + curr_symbol; 
			showMessageDlg("Error", error_message_d);
			return false;
		    }
		}
	    }
	     
	    //next_level.graph_names_d = curr_level.symbols_d;
	    
	}
       
	//store all levels
	//
	for (int i= 0; i < search_levels_d.size(); i++) {
	    SearchLevel curr_level = (SearchLevel)search_levels_d.get(i);
	    String message = "checking level: " + String.valueOf(i);
	    if ( !curr_level.check("", message)){
		showMessageDlg("Error", error_message_d);
		/*
		  JDialog message_pane = new JDialog();
		  message_pane.getContentPane().add(new JScrollPane
		  (new JTextArea(error_message_d)));
		  message_pane.show();
		*/
		//JOptionPane.showMessageDialog(main_frame_d, error_message_d);
		//System.out.print(error_message_d);
		//return false;
	    }
	}
	
	return true;
    }
	    
    /**
     * Hiearchy | Symbols action performed
     * 
     * @param title_a title of message dialog to be shown
     * @param message_a message of message dialog to be shown
     */
    public static void showMessageDlg(String title_a, String message_a) {
	
	UIMessageDialog dlg = 
	    new UIMessageDialog( CData.main_frame_d, title_a, message_a, true);
	Dimension dlgSize = dlg.getPreferredSize();
	Dimension frmSize = CData.main_frame_d.getSize();
	Point loc = CData.main_frame_d.getLocation();
	dlg.setLocation((frmSize.width - dlgSize.width) / 2 + loc.x, 
			(frmSize.height - dlgSize.height) / 2 + loc.y);
	dlg.setVisible(true);//show(); deprecated

    }

    /**
     * store the data into a file
     * 
     * @param save_as true if save as is necessary
     * @param save_all true if save all is necessary
     *
     * @throws Exception if file paths are wrong
     */
    public static void store2(boolean save_as, boolean save_all) {

	String sm_file;

	if(save_all)
	    sm_file = curr_sm_file_d;
	else
	    sm_file = " ";

	// set the file name
	//
	if ( (curr_file_d == null) || save_as ){
	    String file_name = chooseLMFile(curr_file_d);
	    
	    if ( file_name == null){
		return ;
	    } 
	    curr_file_d = file_name;
	}
	
	CData.printDebugMsg("storing ... " + curr_file_d);
	
	// set current description 
	//
	CData.lm_file_description_d = CData.open_lm_file_description_d;
	
	// test file name
	//
	File file = new File(curr_file_d);
	String ext = UIFileFilter.getExtension(file);
       	
	if (  ext.equals(FILE_FILTER_EXTENSION_IHD) &&
	      lm_file_description_d.equals(FILE_FILTER_DESCRIPTION_IHD)) {
	    
	    // store as a temp file first
	    //
	    String temp_file = curr_file_d;
	    try {
		curr_file_d = temp_file_d = 
		    File.createTempFile("temp", ".text").getAbsolutePath();
	    } catch ( Exception e ) {
		e.printStackTrace();
	    }
	    ///*
	    if ( !check() ){
		curr_file_d = temp_file;
		return;
	    }
	    //*/
	    store2(false, false);
	    // convert to new models
	    //
	    convertModels(curr_file_d,"NATIVE", temp_file, sm_file, "IHD", "TEXT");
	    curr_file_d = temp_file;
	    return;
	}
	else if (  ext.equals(FILE_FILTER_EXTENSION_XML) 
	      &&  des.equals(FILE_FILTER_DESCRIPTION_XML)  ) {
	    // store as a temp file first
	    //
	    String temp_file = curr_file_d;
      
	    try {
		curr_file_d = temp_file_d =
		    File.createTempFile("temp", ".text").getAbsolutePath();
		
	    } catch ( Exception e ) {
		e.printStackTrace();
	    }
	    ///*
	    if ( !check() ){
		curr_file_d = temp_file;
		return;
	    }
	    //*/
	    store2(false,false);
	    
	    // convert to new models
	    //
	    convertModels(curr_file_d,"NATIVE", temp_file, sm_file, "XML", "TEXT");
	    curr_file_d = temp_file;
	    return;

	}
	else if (  ext.equals(FILE_FILTER_EXTENSION_BINARY) 
	      &&  des.equals(FILE_FILTER_DESCRIPTION_XML_BINARY)  ) {
	    // store as a temp file first
	    //
	    String temp_file = curr_file_d;
      
	    try {
		curr_file_d = temp_file_d =
		    File.createTempFile("temp", ".text").getAbsolutePath();
		
	    } catch ( Exception e ) {
		e.printStackTrace();
	    }
	    ///*
	    if ( !check() ){
		curr_file_d = temp_file;
		return;
	    }
	    //*/
	    store2(false,false);
	    
	    // convert to new models
	    //
	    convertModels(curr_file_d,"NATIVE", temp_file, sm_file, "XML", "BINARY");
	    curr_file_d = temp_file;
	    return;
	}
	else if (  ext.equals(FILE_FILTER_EXTENSION_JSGF) &&
	      lm_file_description_d.equals(FILE_FILTER_DESCRIPTION_JSGF)) {
	    
	    // store as a temp file first
	    //
	    String temp_file = curr_file_d;
      
	    try {
		curr_file_d = temp_file_d =
		    File.createTempFile("temp", ".text").getAbsolutePath();
		
	    } catch ( Exception e ) {
		e.printStackTrace();
	    }
	    ///*
	    if ( !check() ){
		curr_file_d = temp_file;
		return;
	    }
	    //*/
	    store2(false,false);
	    
	    // convert to new models
	    //
	    convertModels(curr_file_d,"NATIVE", temp_file, sm_file, "JSGF", "TEXT");
	    curr_file_d = temp_file;
	    return;
	}
	else if ( ext.equals(FILE_FILTER_EXTENSION_BINARY) && 
	     lm_file_description_d.equals(FILE_FILTER_DESCRIPTION_BINARY)) {
	    
	    // store as a temp file first
	    //
	    String temp_file = curr_file_d;
	    try {
		curr_file_d = temp_file_d =
		    File.createTempFile("temp", ".text").getAbsolutePath();
	    } catch ( Exception e ) {
		e.printStackTrace();
	    }
	    ///*
	    if ( !check() ){
		curr_file_d = temp_file;
		return;
	    }
	    //*/
	    store2(false,false);

	    // convert to new models
	    //
	    convertModels(curr_file_d,"NATIVE", temp_file, sm_file, "IHD", "binary");
	    curr_file_d = temp_file;
	    return;
	}
	else if ( ext.equals(FILE_FILTER_EXTENSION_BINARY) && 
	     lm_file_description_d.equals(FILE_FILTER_DESCRIPTION_JSGF_BINARY)) {
	    
	    // store as a temp file first
	    //
	    String temp_file = curr_file_d;
	    try {
		curr_file_d = temp_file_d =
		    File.createTempFile("temp", ".text").getAbsolutePath();
	    } catch ( Exception e ) {
		e.printStackTrace();
	    }
	    ///*
	    if ( !check() ){
		curr_file_d = temp_file;
		return;
	    }
	    //*/
	    store2(false,false);

	    // convert to new models
	    //
	    convertModels(curr_file_d,"NATIVE", temp_file, sm_file, "JSGF", "binary");
	    curr_file_d = temp_file;
	    return;
	}
        else if ( ext.equals(FILE_FILTER_EXTENSION_ABNF) && 
	     lm_file_description_d.equals(FILE_FILTER_DESCRIPTION_ABNF)) {
	    
	    // store as a temp file first
	    //
	    String temp_file = curr_file_d;
	    try {
		curr_file_d = temp_file_d =
		    File.createTempFile("temp", ".text").getAbsolutePath();
	    } catch ( Exception e ) {
		e.printStackTrace();
	    }
	    ///*
	    if ( !check() ){
		curr_file_d = temp_file;
		return;
	    }
	    //*/
	    store2(false,false);

	    // convert to new models
	    //
	    convertModels(curr_file_d,"NATIVE", temp_file, sm_file, "ABNF", "TEXT");
	    curr_file_d = temp_file;
	    return;
	}
        else if ( ext.equals(FILE_FILTER_EXTENSION_BINARY) && 
	     lm_file_description_d.equals(FILE_FILTER_DESCRIPTION_ABNF_BINARY)) {
	    
	    // store as a temp file first
	    //
	    String temp_file = curr_file_d;
	    try {
		curr_file_d = temp_file_d =
		    File.createTempFile("temp", ".text").getAbsolutePath();
	    } catch ( Exception e ) {
		e.printStackTrace();
	    }
	    ///*
	    if ( !check() ){
		curr_file_d = temp_file;
		return;
	    }
	    //*/
	    store2(false,false);

	    // convert to new models
	    //
	    convertModels(curr_file_d,"NATIVE", temp_file, sm_file, "ABNF", "binary");
	    curr_file_d = temp_file;
	    return;
	}
        else if ( ext.equals(FILE_FILTER_EXTENSION_BNF) && 
	     lm_file_description_d.equals(FILE_FILTER_DESCRIPTION_BNF)) {
	    
	    // store as a temp file first
	    //
	    String temp_file = curr_file_d;
	    try {
		curr_file_d = temp_file_d =
		    File.createTempFile("temp", ".text").getAbsolutePath();
	    } catch ( Exception e ) {
		e.printStackTrace();
	    }
	    ///*
	    if ( !check() ){
		curr_file_d = temp_file;
		return;
	    }
	    //*/
	    store2(false,false);

	    // convert to new models
	    //
	    convertModels(curr_file_d,"NATIVE", temp_file, sm_file, "BNF", "TEXT");
	    curr_file_d = temp_file;
	    return;
	}
        else if ( ext.equals(FILE_FILTER_EXTENSION_BINARY) && 
	     lm_file_description_d.equals(FILE_FILTER_DESCRIPTION_BNF_BINARY)) {
	    
	    // store as a temp file first
	    //
	    String temp_file = curr_file_d;
	    try {
		curr_file_d = temp_file_d =
		    File.createTempFile("temp", ".text").getAbsolutePath();
	    } catch ( Exception e ) {
		e.printStackTrace();
	    }
	    ///*
	    if ( !check() ){
		curr_file_d = temp_file;
		return;
	    }
	    //*/
	    store2(false,false);

	    // convert to new models
	    //
	    convertModels(curr_file_d,"NATIVE", temp_file, sm_file, "BNF", "binary");
	    curr_file_d = temp_file;
	    return;
	}

	// tags
	//
	String level_size_tag = CData.IO_CDATA_LEVEL_SIZE;
	
	// values
	//
	String level_size = String.valueOf(search_levels_d.size());
	
	// store all data members
	//
	io_d.setProperty(level_size_tag, level_size);

	
	
	// store all levels
	// 
	for (int i= 0; i < search_levels_d.size(); i++) {
	    
	    if (i==0) {
		SearchLevel curr_level = (SearchLevel)search_levels_d.get(i);
		String prefix = CData.IO_SEARCHLEVEL_PREFIX + String.valueOf(i);
		SearchLevel prev_level = curr_level;
		curr_level.store(prefix,prev_level);
                
	    }
        
	    // we need the previous levels because we are actually
	    // saving the graphs in the order the appear in the
	    // previous levels symbol table.
	    
	    if (i >= 1) {
		
		SearchLevel curr_level = (SearchLevel)search_levels_d.get(i);
		String prefix = CData.IO_SEARCHLEVEL_PREFIX + String.valueOf(i);
		SearchLevel prev_level =(SearchLevel)search_levels_d.get(i-1);
		curr_level.store(prefix,prev_level);
	    }
	}
	
	
	
	try{
	    // store into a file
	    //
	    io_d.store(new FileOutputStream(curr_file_d), 
		       "native format models");

	} catch (Exception e){
	    e.printStackTrace(System.out);
	}
    }

     /**
     * load the data from a file
     * 
     * @param new_file_a true if file is new
     * 
     */
    public static void newModel(boolean new_file_a) {

	// do we use new file
	//
	if ( new_file_a ){
	    String file_name = chooseFile("New");
	    if ( file_name == null){
		return ;
	    } 
	    curr_file_d = file_name;
	}
	else{
	    curr_file_d = null;
	}

	// initialize 
	//
	init();

	// update UI
	//
	main_frame_d.updateAll();
    }

    /**
     * load the data from a file
     * 
     * @param load_curr_file true if loading of current file is wanted
     *  otherwise the chooseLMFile() method chooses a file to load
     *
     * @throws Exception if file paths are wrong
     */
    public static void load(boolean load_curr_file) {

	if ( ! load_curr_file ){

	    String file_name = chooseLMFile(curr_file_d);
	    
	    if ( file_name == null){
		return ;
	    } 
	    
	    File file = new File(file_name);
	    
	    if ( ! file.exists() ){
		System.out.println(file_name + "does not exist");
		return ;
	    }
	    curr_file_d = file_name;
	}

	CData.printDebugMsg("load file:" + curr_file_d);

	// find the extension of the file and call different commands
	//
	File file = new File(curr_file_d);
	String ext = UIFileFilter.getExtension(file);

        
	if (  ext.equals(FILE_FILTER_EXTENSION_IHD) &&  des.equals(FILE_FILTER_DESCRIPTION_IHD)  ) {

	    // store2as a temp file first
	    //
	    String temp_file = curr_file_d;
	    try {
		curr_file_d = temp_file_d =
		    File.createTempFile("temp", ".text").getAbsolutePath();
	    } catch ( Exception e ) {
		e.printStackTrace();
	    }

	    // convert to new models
	    //
	    convertModels(temp_file, "IHD", curr_file_d, " ", "NATIVE", "text");
	    load(true);
	    curr_file_d = temp_file;
	    return;
	}
	if (  ext.equals(FILE_FILTER_EXTENSION_JSGF) &&  des.equals(FILE_FILTER_DESCRIPTION_JSGF) ) {

	    // store as a temp file first
	    //
	    String temp_file = curr_file_d;
	    try {
		curr_file_d = temp_file_d =
		    File.createTempFile("temp", ".text").getAbsolutePath();
	    } catch ( Exception e ) {
		e.printStackTrace();
	    }

	    // convert to new models
	    //
	    convertModels(temp_file, "JSGF", curr_file_d, " ", "NATIVE", "text");
	    load(true);
	    curr_file_d = temp_file;
	    return;
	}
	if (ext.equals(FILE_FILTER_EXTENSION_XML) &&  des.equals(FILE_FILTER_DESCRIPTION_XML) ) {

	    // check whether expat is present
	    //
	    if(expat_is_configured) {
		
		// store as a temp file first
		//
		String temp_file = curr_file_d;
		
		try {
		    curr_file_d = temp_file_d =
			File.createTempFile("temp", ".text").getAbsolutePath();
		} catch ( Exception e ) {
		    e.printStackTrace();
		}
		
		// convert to new models
		//
		convertModels(temp_file, "XML", curr_file_d, " ", "NATIVE", "text");
		load(true);
		curr_file_d = temp_file;
		return;
	    }

	    // if expat is not configured, print an error message
	    // note that since we should not add the XML option to
	    // the select list when there is no expat, that we should 
	    // never get here. Print an error message just in case.
	    else {

		// error. cannot save in XML format. not currently supported.
		//
		JOptionPane.showMessageDialog(main_frame_d, 
					      ERR_NO_EXPAT, "Warning", 
					      JOptionPane.ERROR_MESSAGE);
		
		return;

	    }
	}
        if (  ext.equals(FILE_FILTER_EXTENSION_ABNF) &&  des.equals(FILE_FILTER_DESCRIPTION_ABNF) ) {

	    // store as a temp file first
	    //
	    String temp_file = curr_file_d;
	    try {
		curr_file_d = temp_file_d =
		    File.createTempFile("temp", ".text").getAbsolutePath();
	    } catch ( Exception e ) {
		e.printStackTrace();
	    }

	    // convert to new models
	    //
	    convertModels(temp_file, "ABNF", curr_file_d, " ", "NATIVE", "text");
	    load(true);
	    curr_file_d = temp_file;
	    return;
	}   
        if (  ext.equals(FILE_FILTER_EXTENSION_BNF) &&  des.equals(FILE_FILTER_DESCRIPTION_BNF) ) {

	    // store as a temp file first
	    //
	    String temp_file = curr_file_d;
	    try {
		curr_file_d = temp_file_d =
		    File.createTempFile("temp", ".text").getAbsolutePath();
	    } catch ( Exception e ) {
		e.printStackTrace();
	    }

	    // convert to new models
	    //
	    convertModels(temp_file, "BNF", curr_file_d, " ", "NATIVE", "text");
	    load(true);
	    curr_file_d = temp_file;
	    return;
	}   
	if (  ext.equals(FILE_FILTER_EXTENSION_BINARY) ) {

	    // store as a temp file first
	    //
	    String temp_file = curr_file_d;
	    try {
		curr_file_d = temp_file_d =
		    File.createTempFile("temp", ".text").getAbsolutePath();
	    } catch ( Exception e ) {
		e.printStackTrace();
	    }

	    // convert to new models
	    //
	    convertModels(temp_file, "IHD", curr_file_d, " ", "NATIVE", "text");
	    load(true);
	    curr_file_d = temp_file;
	    return;
	}

	// initialize 
	//
	init();

	// read data from a file
	//
	try{	    
	    io_d.clear();
	    CData.printDebugMsg("start loading ... ");
	    io_d.load(new FileInputStream(curr_file_d));
	    CData.printDebugMsg("end of loading ... ");

	} catch (Exception e){
	    e.printStackTrace(System.out);
	}

	// tags
	//
	String level_size_tag = CData.IO_CDATA_LEVEL_SIZE;
	
	// values
	//
	String level_size = io_d.getProperty(level_size_tag);

	// make sure the level_size_tag exists.  if not,
	// native lm file is invalid
	//
	if (level_size == null) {

	    // language model file invalid
	    // 
	    JOptionPane.showMessageDialog(main_frame_d, 
					  ERR_CONV_INVALID, "Warning", 
					  JOptionPane.ERROR_MESSAGE);
	    // return without loading
	    //
	    return;
	}

	int l_size = Integer.valueOf(level_size).intValue();
	
	search_levels_d.clear();

	// store all levels
	//
	for (int i= 0; i < l_size; i++) {
	    String prefix = CData.IO_SEARCHLEVEL_PREFIX + String.valueOf(i);
	    SearchLevel curr_level = new SearchLevel();
	    curr_level.load(prefix);
	    CData.printDebugMsg(prefix);
	    addLevel(i, curr_level);
	}

	// set current indices
	//
	curr_level_index_d = 0;
	curr_graph_index_d = 0;

	// update UI
	//
	main_frame_d.updateAll();
    }

    /**
     * Runs commands given certain String values 
     *
     * @param input_file_a     name of input file
     * @param input_format_a   value of input format
     * @param output_file_a    output file name
     * @param output_sm_file_a output sm file name
     * @param out_format_a     value of output format
     * @param out_type_a       output type
     *
     * @throws IOException if commands do not execute properly
     * @throws InterruptedException if the converter was interrupted
     */
    public static void convertModels( String input_file_a, 
				      String input_format_a,
				      String output_file_a, 
				      String output_sm_file_a, 
				      String out_format_a,
				      String out_type_a){
	
	// get the current runtime environment
	//
	Runtime environ = Runtime.getRuntime();

	// make sure we got a valid runtime environment
	//
	if (environ == null) {
	    System.out.println("Didn't get Runtime for script" );
	    return;
	}

	//output_sm_file_a = "/home/huang/temp/sm.sof";

	String[] cmdarray = new String[10];

	// launch the script with the start option
	//
	Process start_proc = (Process)null;
	try {
	    
	    cmdarray[0] = ISIP_NETWORK_CONVERTER;
	    cmdarray[1] = input_file_a;
	    cmdarray[2] = output_file_a;
	    cmdarray[3] = output_sm_file_a;
	    cmdarray[4] = "-input_format";
	    cmdarray[5] = input_format_a;
	    cmdarray[6] = "-output_format";
	    cmdarray[7] = out_format_a;
	    cmdarray[8] = "-output_type";
	    cmdarray[9] = out_type_a;
	    String command = new String(" " +cmdarray[0]
			       + " " + cmdarray[1] +  " " +cmdarray[2]
			       + " " + cmdarray[3] +  " " +cmdarray[4]
			       + " " + cmdarray[5] +  " " +cmdarray[6]
			       + " " + cmdarray[7] +  " " +cmdarray[8]
      			       + " " + cmdarray[9] );

	    start_proc = environ.exec(cmdarray);

	} catch (java.io.IOException e) {

	    // notify the user of I/O errors
	    //
	    JOptionPane.showMessageDialog(main_frame_d, 
					  ERR_CONV_NO_START, "Warning", 
					  JOptionPane.ERROR_MESSAGE);
	   
	    e.printStackTrace(System.out);
	    return;
	}

	// make sure we got a valid process
	//
	if (start_proc == null) {
	   
	    // if not, notify the user
	    //
	    JOptionPane.showMessageDialog(main_frame_d, 
					  ERR_CONV_NO_START, "Warning", 
					  JOptionPane.ERROR_MESSAGE);
	    return;
	}
	
	try{

	    CData.printDebugMsg(" " +cmdarray[0]
			       + " " + cmdarray[1] +  " " +cmdarray[2]
			       + " " + cmdarray[3] +  " " +cmdarray[4]
			       + " " + cmdarray[5] +  " " +cmdarray[6]
			       + " " + cmdarray[7] +  " " +cmdarray[8]
			       + " " + cmdarray[9] );
	    start_proc.waitFor();

	    // see whether the network converter 
	    // indicated success upon exiting
	    //
	    if(start_proc.exitValue() != 0) {
	
		// the network converter indicated failure
		// 
		JOptionPane.showMessageDialog(main_frame_d, 
					      ERR_CONV_FAIL, "Warning", 
					      JOptionPane.ERROR_MESSAGE);
	    }

	}
	catch(java.lang.InterruptedException e){
	    
	    // notify the user if the converter was interrupted
	    //
	    JOptionPane.showMessageDialog(main_frame_d, 
					  ERR_CONV_INTR, "Warning", 
					  JOptionPane.ERROR_MESSAGE);
	    return;
	}
    }

    /**
     * removes temporary file
     * 
     * @throws Exception if file cannot be found to delete
     */
    public static void removeTempFile() {

	// remove the temporary file
	//
	try {
	    if ( temp_file_d != null  ){
		File tmp = new File(temp_file_d);
		if ( tmp.exists() ){
		    tmp.delete();
		}
		temp_file_d = null;
	    }
	} catch ( Exception e ) {
	    e.printStackTrace();
	}
    }

    /**
     * load the data from a file
     * 
     * @param approve_string_a String that is passed on to a button text for
     *  user to approve by clicking
     *
     */
    public static String chooseFile(String approve_string_a) {

	String curr_dir = System.getProperty("user.dir");
	String file_name = new String();
	
	// set the file chooser
	//
	JFileChooser fc = new JFileChooser(curr_dir);
	fc.setAcceptAllFileFilterUsed(false);
	//fc.setDialogType(type_a);

	UIFileFilter sof_filter = new UIFileFilter();
	sof_filter.addExtension(FILE_FILTER_EXTENSION_IHD);
	sof_filter.setDescription(FILE_FILTER_DESCRIPTION_IHD);
	fc.addChoosableFileFilter(sof_filter);

	UIFileFilter jsgf_filter = new UIFileFilter();
	jsgf_filter.addExtension(FILE_FILTER_EXTENSION_JSGF);
	jsgf_filter.setDescription(FILE_FILTER_DESCRIPTION_JSGF);
	fc.addChoosableFileFilter(jsgf_filter);
	      
	UIFileFilter bin_filter = new UIFileFilter();
	bin_filter.addExtension(FILE_FILTER_EXTENSION_BINARY);
	bin_filter.setDescription(FILE_FILTER_DESCRIPTION_BINARY);
	fc.addChoosableFileFilter(bin_filter);

	UIFileFilter bin_jsgf_filter = new UIFileFilter();
	bin_jsgf_filter.addExtension(FILE_FILTER_EXTENSION_BINARY);
	bin_jsgf_filter.setDescription(FILE_FILTER_DESCRIPTION_JSGF_BINARY);
	fc.addChoosableFileFilter(bin_jsgf_filter);

	UIFileFilter inb_filter = new UIFileFilter();
	inb_filter.addExtension(FILE_FILTER_EXTENSION_NATIVE);
	inb_filter.setDescription( FILE_FILTER_DESCRIPTION_NATIVE );
	fc.addChoosableFileFilter(inb_filter);
        
        UIFileFilter abnf_filter = new UIFileFilter();
	abnf_filter.addExtension(FILE_FILTER_EXTENSION_ABNF);
	abnf_filter.setDescription(FILE_FILTER_DESCRIPTION_ABNF);
	fc.addChoosableFileFilter(abnf_filter);
        
       	UIFileFilter bin_abnf_filter = new UIFileFilter();
	bin_abnf_filter.addExtension(FILE_FILTER_EXTENSION_BINARY);
	bin_abnf_filter.setDescription(FILE_FILTER_DESCRIPTION_ABNF_BINARY);
	fc.addChoosableFileFilter(bin_abnf_filter);
        

        UIFileFilter bnf_filter = new UIFileFilter();
	bnf_filter.addExtension(FILE_FILTER_EXTENSION_BNF);
	bnf_filter.setDescription(FILE_FILTER_DESCRIPTION_BNF);
	fc.addChoosableFileFilter(bnf_filter);
        
       	UIFileFilter bin_bnf_filter = new UIFileFilter();
	bin_bnf_filter.addExtension(FILE_FILTER_EXTENSION_BINARY);
	bin_bnf_filter.setDescription(FILE_FILTER_DESCRIPTION_BNF_BINARY);
	fc.addChoosableFileFilter(bin_bnf_filter);
       
	// check whether expat is configured before displaying 
	// xml options
	//
	if(expat_is_configured) {

	    UIFileFilter xml_filter = new UIFileFilter();
	    xml_filter.addExtension(FILE_FILTER_EXTENSION_XML);
	    xml_filter.setDescription(FILE_FILTER_DESCRIPTION_XML);
	    fc.addChoosableFileFilter(xml_filter);
	    
	    UIFileFilter binary_xml_filter = new UIFileFilter();
	    binary_xml_filter.addExtension(FILE_FILTER_EXTENSION_BINARY);
	    binary_xml_filter.setDescription
		(FILE_FILTER_DESCRIPTION_XML_BINARY);
	    fc.addChoosableFileFilter(binary_xml_filter);
	}

	int ret = fc.showDialog(main_frame_d, approve_string_a);
	String description = fc.getFileFilter().getDescription();

	if ( ret == JFileChooser.APPROVE_OPTION ){
	    if ( description.equals(FILE_FILTER_DESCRIPTION_IHD) &&
		 (!UIFileFilter.getExtension(fc.getSelectedFile())
		  .equals(FILE_FILTER_EXTENSION_IHD)) ){
		file_name = fc.getSelectedFile().getAbsolutePath() +
		    "." + FILE_FILTER_EXTENSION_IHD;
	    }
	    else if ( description.equals(FILE_FILTER_DESCRIPTION_JSGF) &&
		 (!UIFileFilter.getExtension(fc.getSelectedFile())
		  .equals(FILE_FILTER_EXTENSION_JSGF)) ){
		file_name = fc.getSelectedFile().getAbsolutePath() +
		    "." + FILE_FILTER_EXTENSION_JSGF;
	    }  
	    else if ( description.equals(FILE_FILTER_DESCRIPTION_XML) &&
		      (!UIFileFilter.getExtension(fc.getSelectedFile())
		       .equals(FILE_FILTER_EXTENSION_XML)) ){

		// check whether expat is configured. If not, we shouldn't
		// be here. Print an error message.
		//
		if(expat_is_configured) {
		    
		    file_name = fc.getSelectedFile().getAbsolutePath() +
			"." + FILE_FILTER_EXTENSION_XML;
		} 
		else {
		    
		    // error. cannot use XML format. 
		    // not currently supported.
		    //
		    JOptionPane.showMessageDialog(main_frame_d, 
						  ERR_NO_EXPAT, "Warning", 
						  JOptionPane.ERROR_MESSAGE);
		}
	    }
	    else if ( description.equals(FILE_FILTER_DESCRIPTION_XML_BINARY) &&
		      (!UIFileFilter.getExtension(fc.getSelectedFile())
		       .equals(FILE_FILTER_EXTENSION_BINARY)) ){

		// check whether expat is configured. If not, we shouldn't
		// be here. Print an error message.
		//
		if(expat_is_configured) {

		    file_name = fc.getSelectedFile().getAbsolutePath() +
			"." + FILE_FILTER_EXTENSION_BINARY;
		}
		else {
		    
		    // error. cannot use XML format. 
		    // not currently supported.
		    //
		    JOptionPane.showMessageDialog(main_frame_d, 
						  ERR_NO_EXPAT, "Warning", 
						  JOptionPane.ERROR_MESSAGE);
		}

	    }
	    else if ( description.equals(FILE_FILTER_DESCRIPTION_NATIVE) &&
		      (!UIFileFilter.getExtension(fc.getSelectedFile())
		       .equals(FILE_FILTER_EXTENSION_NATIVE)) ){
		file_name = fc.getSelectedFile().getAbsolutePath() +
		    "." + FILE_FILTER_EXTENSION_NATIVE;
	    }
	    else if ( description.equals(FILE_FILTER_DESCRIPTION_BINARY) &&
		      (!UIFileFilter.getExtension(fc.getSelectedFile())
		       .equals(FILE_FILTER_EXTENSION_BINARY)) ){
		file_name = fc.getSelectedFile().getAbsolutePath() +
		    "." + FILE_FILTER_EXTENSION_BINARY;
	    }
	    else if ( description.equals(FILE_FILTER_DESCRIPTION_JSGF_BINARY) &&
		      (!UIFileFilter.getExtension(fc.getSelectedFile())
		       .equals(FILE_FILTER_EXTENSION_BINARY)) ){
		file_name = fc.getSelectedFile().getAbsolutePath() +
		    "." + FILE_FILTER_EXTENSION_BINARY;
	    }
            else if ( description.equals(FILE_FILTER_DESCRIPTION_ABNF) &&
		 (!UIFileFilter.getExtension(fc.getSelectedFile())
		  .equals(FILE_FILTER_EXTENSION_ABNF)) ){
		file_name = fc.getSelectedFile().getAbsolutePath() +
		    "." + FILE_FILTER_EXTENSION_ABNF;
	    }
            else if ( description.equals(FILE_FILTER_DESCRIPTION_ABNF_BINARY) &&
		 (!UIFileFilter.getExtension(fc.getSelectedFile())
		  .equals(FILE_FILTER_EXTENSION_BINARY)) ){
		file_name = fc.getSelectedFile().getAbsolutePath() +
		    "." + FILE_FILTER_EXTENSION_BINARY;
	    }
            else if ( description.equals(FILE_FILTER_DESCRIPTION_BNF) &&
		 (!UIFileFilter.getExtension(fc.getSelectedFile())
		  .equals(FILE_FILTER_EXTENSION_BNF)) ){
		file_name = fc.getSelectedFile().getAbsolutePath() +
		    "." + FILE_FILTER_EXTENSION_BNF;
	    }
            else if ( description.equals(FILE_FILTER_DESCRIPTION_BNF_BINARY) &&
		 (!UIFileFilter.getExtension(fc.getSelectedFile())
		  .equals(FILE_FILTER_EXTENSION_BINARY)) ){
		file_name = fc.getSelectedFile().getAbsolutePath() +
		    "." + FILE_FILTER_EXTENSION_BINARY;
	    }
	    else {
		file_name = fc.getSelectedFile().getAbsolutePath();
	    }
	}
	else{
	    file_name = null;
	}
	
	// exist
	//
	return file_name;
    }

    /**
     * Choose any file to load
     * 
     * @param approve_string_a String that is passed on to a button text for
     *  user to approve by clicking
     * @return file name
     */
    public static String chooseAnyFile(String approve_string_a) {

	String curr_dir = System.getProperty("user.dir");
	String file_name = new String();
	
	// set the file chooser
	//
	JFileChooser fc = new JFileChooser(curr_dir);
	fc.setAcceptAllFileFilterUsed(true);
	//fc.setDialogType(type_a);

	int ret = fc.showDialog(main_frame_d, approve_string_a);
	String description = fc.getFileFilter().getDescription();

	if ( ret == JFileChooser.APPROVE_OPTION ){
	    file_name = fc.getSelectedFile().getAbsolutePath();
	}
	else{
	    file_name = null;
	}
	
	// exist
	//
	return file_name;
    }

    /**
     * Chooses an LM File
     * 
     * @param curr_dir_a directory of file to choose
     *
     * @return file name
     */
    public static String chooseLMFile(String curr_dir_a) {

	String curr_dir = curr_dir_a;
	if ( curr_dir_a == null ){
	    curr_dir = System.getProperty("user.dir");
	}
	String file_name = new String();
	
	// set the file chooser
	//
	JFileChooser fc = new JFileChooser(curr_dir);
	fc.setAcceptAllFileFilterUsed(false);
	//fc.addActionListener(event_handler_d);
	//fc.setDialogType(JFileChooser.SAVE_DIALOG);
	//fc.setDialogType(type_a);

	UIFileFilter sof_filter = new UIFileFilter();
	sof_filter.addExtension(FILE_FILTER_EXTENSION_IHD);
	sof_filter.setDescription(FILE_FILTER_DESCRIPTION_IHD);
	fc.addChoosableFileFilter(sof_filter);

	UIFileFilter jsgf_filter = new UIFileFilter();
	jsgf_filter.addExtension(FILE_FILTER_EXTENSION_JSGF);
	jsgf_filter.setDescription(FILE_FILTER_DESCRIPTION_JSGF);
	fc.addChoosableFileFilter(jsgf_filter);

	UIFileFilter binary_filter = new UIFileFilter();
	binary_filter.addExtension(FILE_FILTER_EXTENSION_BINARY);
	binary_filter.setDescription(FILE_FILTER_DESCRIPTION_BINARY);
	fc.addChoosableFileFilter(binary_filter);
			      
	UIFileFilter binary_jsgf_filter = new UIFileFilter();
	binary_jsgf_filter.addExtension(FILE_FILTER_EXTENSION_BINARY);
	binary_jsgf_filter.setDescription(FILE_FILTER_DESCRIPTION_JSGF_BINARY);
	fc.addChoosableFileFilter(binary_jsgf_filter);

	UIFileFilter inb_filter = new UIFileFilter();
	inb_filter.addExtension(FILE_FILTER_EXTENSION_NATIVE);
	inb_filter.setDescription( FILE_FILTER_DESCRIPTION_NATIVE );
	fc.addChoosableFileFilter(inb_filter);
       
        UIFileFilter abnf_filter = new UIFileFilter();
	abnf_filter.addExtension(FILE_FILTER_EXTENSION_ABNF);
	abnf_filter.setDescription(FILE_FILTER_DESCRIPTION_ABNF);
	fc.addChoosableFileFilter(abnf_filter);
     
        UIFileFilter binary_abnf_filter = new UIFileFilter();
	binary_abnf_filter.addExtension(FILE_FILTER_EXTENSION_BINARY);
	binary_abnf_filter.setDescription(FILE_FILTER_DESCRIPTION_ABNF_BINARY);
	fc.addChoosableFileFilter(binary_abnf_filter);

        UIFileFilter bnf_filter = new UIFileFilter();
	bnf_filter.addExtension(FILE_FILTER_EXTENSION_BNF);
	bnf_filter.setDescription(FILE_FILTER_DESCRIPTION_BNF);
	fc.addChoosableFileFilter(bnf_filter);

        UIFileFilter binary_bnf_filter = new UIFileFilter();
	binary_bnf_filter.addExtension(FILE_FILTER_EXTENSION_BINARY);
	binary_bnf_filter.setDescription(FILE_FILTER_DESCRIPTION_BNF_BINARY);
	fc.addChoosableFileFilter(binary_bnf_filter);

	// check whether expat has been configured before displaying 
	// xml options
	//
	if(expat_is_configured) {
	    
	    UIFileFilter xml_filter = new UIFileFilter();
	    xml_filter.addExtension(FILE_FILTER_EXTENSION_XML);
	    xml_filter.setDescription(FILE_FILTER_DESCRIPTION_XML);
	    fc.addChoosableFileFilter(xml_filter);
	    
	    UIFileFilter binary_xml_filter = new UIFileFilter();
	    binary_xml_filter.addExtension(FILE_FILTER_EXTENSION_BINARY);
	    binary_xml_filter.setDescription(FILE_FILTER_DESCRIPTION_XML_BINARY);
	    fc.addChoosableFileFilter(binary_xml_filter);
	}
			      
	int ret = fc.showDialog(main_frame_d, "OK");
	String description = fc.getFileFilter().getDescription();
	des = description;
	open_lm_file_description_d = description;

	if ( ret == JFileChooser.APPROVE_OPTION ){
	    if ( description.equals(FILE_FILTER_DESCRIPTION_IHD) &&
		 (!UIFileFilter.getExtension(fc.getSelectedFile())
		  .equals(FILE_FILTER_EXTENSION_IHD)) ){
		file_name = fc.getSelectedFile().getAbsolutePath() +
		    "." + FILE_FILTER_EXTENSION_IHD;
	    }
	    else if ( description.equals(FILE_FILTER_DESCRIPTION_JSGF) &&
		 (!UIFileFilter.getExtension(fc.getSelectedFile())
		  .equals(FILE_FILTER_EXTENSION_JSGF)) ){
		file_name = fc.getSelectedFile().getAbsolutePath() +
		    "." + FILE_FILTER_EXTENSION_JSGF;
	    }
	    else if ( description.equals(FILE_FILTER_DESCRIPTION_XML) &&
		 (!UIFileFilter.getExtension(fc.getSelectedFile())
		  .equals(FILE_FILTER_EXTENSION_XML)) ){
		
		// check for expat. If it is not configured, we shouldn't be
		// here. Error out.
		//
		if(expat_is_configured) {
		
		    file_name = fc.getSelectedFile().getAbsolutePath() +
			"." + FILE_FILTER_EXTENSION_XML;
		}
		else {
		  
		    // error. cannot use XML format. 
		    // not currently supported.
		    //
		    JOptionPane.showMessageDialog(main_frame_d, 
						  ERR_NO_EXPAT, "Warning", 
						  JOptionPane.ERROR_MESSAGE);
		}

	    }
	    else if ( description.equals(FILE_FILTER_DESCRIPTION_XML_BINARY) &&
		      (!UIFileFilter.getExtension(fc.getSelectedFile())
		       .equals(FILE_FILTER_EXTENSION_BINARY)) ){

		// check for expat. If it is not configured, we shouldn't be
		// here. Error out.
		//
		if(expat_is_configured) {

		    file_name = fc.getSelectedFile().getAbsolutePath() +
			"." + FILE_FILTER_EXTENSION_BINARY;
		}
		else {
		 
		    // error. cannot use XML format. 
		    // not currently supported.
		    //
		    JOptionPane.showMessageDialog(main_frame_d, 
						  ERR_NO_EXPAT, "Warning", 
						  JOptionPane.ERROR_MESSAGE);
		}

	    }
	    else if ( description.equals(FILE_FILTER_DESCRIPTION_BINARY) &&
		 (!UIFileFilter.getExtension(fc.getSelectedFile())
		  .equals(FILE_FILTER_EXTENSION_BINARY)) ){
		
		file_name = fc.getSelectedFile().getAbsolutePath() +
		    "." + FILE_FILTER_EXTENSION_BINARY;

	    }
	    else if ( description.equals(FILE_FILTER_DESCRIPTION_JSGF_BINARY)&&
		 (!UIFileFilter.getExtension(fc.getSelectedFile())
		  .equals(FILE_FILTER_EXTENSION_BINARY)) ){
		file_name = fc.getSelectedFile().getAbsolutePath() +
		    "." + FILE_FILTER_EXTENSION_BINARY;
	    }
	    else if ( description.equals(FILE_FILTER_DESCRIPTION_NATIVE) &&
		 (!UIFileFilter.getExtension(fc.getSelectedFile())
		  .equals(FILE_FILTER_EXTENSION_NATIVE)) ){
		file_name = fc.getSelectedFile().getAbsolutePath() +
		    "." + FILE_FILTER_EXTENSION_NATIVE;
	    }
            else if ( description.equals(FILE_FILTER_DESCRIPTION_ABNF) &&
		 (!UIFileFilter.getExtension(fc.getSelectedFile())
		  .equals(FILE_FILTER_EXTENSION_ABNF)) ){
		file_name = fc.getSelectedFile().getAbsolutePath() +
		    "." + FILE_FILTER_EXTENSION_ABNF;
	    }

            else if ( description.equals(FILE_FILTER_DESCRIPTION_ABNF_BINARY)&&
		 (!UIFileFilter.getExtension(fc.getSelectedFile())
		  .equals(FILE_FILTER_EXTENSION_BINARY)) ){
		file_name = fc.getSelectedFile().getAbsolutePath() +
		    "." + FILE_FILTER_EXTENSION_BINARY;
	    }
            else if ( description.equals(FILE_FILTER_DESCRIPTION_BNF) &&
		 (!UIFileFilter.getExtension(fc.getSelectedFile())
		  .equals(FILE_FILTER_EXTENSION_BNF)) ){
		file_name = fc.getSelectedFile().getAbsolutePath() +
		    "." + FILE_FILTER_EXTENSION_BNF;
	    }
            else if ( description.equals(FILE_FILTER_DESCRIPTION_BNF_BINARY)&&
		 (!UIFileFilter.getExtension(fc.getSelectedFile())
		  .equals(FILE_FILTER_EXTENSION_BINARY)) ){
		file_name = fc.getSelectedFile().getAbsolutePath() +
		    "." + FILE_FILTER_EXTENSION_BINARY;
	    }
	    else {
		file_name = fc.getSelectedFile().getAbsolutePath();
	    }
	}
	else{
	    file_name = null;
	}
	
	// exist
	//
	return file_name;
    }

    /**
     * Choose SM File
     * 
     * @param curr_dir_a directory of file to choose
     *
     * @return file name
     */
    public static String chooseSMFile(String curr_dir_a) {

	String curr_dir = curr_dir_a;
	if ( curr_dir_a == null ){
	    curr_dir = System.getProperty("user.dir");
	}
	String file_name = new String();
	
	// set the file chooser
	//
	JFileChooser fc = new JFileChooser(curr_dir);
	fc.setAcceptAllFileFilterUsed(false);
	//fc.setDialogType(type_a);

	UIFileFilter sof_filter = new UIFileFilter();
	sof_filter.addExtension(FILE_FILTER_EXTENSION_SM);
	sof_filter.setDescription(FILE_FILTER_DESCRIPTION_SM);
	fc.addChoosableFileFilter(sof_filter);

	int ret = fc.showDialog(main_frame_d, "OK");
	String description = fc.getFileFilter().getDescription();

	if ( ret == JFileChooser.APPROVE_OPTION ){
	    if ( description.equals(FILE_FILTER_DESCRIPTION_SM) &&
		 (!UIFileFilter.getExtension(fc.getSelectedFile())
		  .equals(FILE_FILTER_EXTENSION_SM)) ){
		file_name = fc.getSelectedFile().getAbsolutePath() +
		    "." + FILE_FILTER_EXTENSION_SM;
	    }
	    else {
		file_name = fc.getSelectedFile().getAbsolutePath();
	    }
	}
	else{
	    file_name = null;
	}
	
	// exist
	//
	return file_name;
    }

    /**
     * Stores symbols using hastable put method via Properties.setProperty 
     * method
     *
     * @param symbols_a       symbols to be stored
     * @param size_prefix_a   String value of numeric size
     * @param symbol_prefix_a String to placed as a prefix
     */
    public static void storeSymbols(Vector<String> symbols_a, String size_prefix_a, String symbol_prefix_a) {
	// get the io to set properties
	//
	Properties io = CData.io_d;
	
	// store all data members
	//
	String symbol_size = String.valueOf(symbols_a.size());
	io.setProperty(size_prefix_a, symbol_size);

	// store all symbols
	//
	for (int i= 0; i < symbols_a.size(); i++) {
	    String curr_symbol = (String)symbols_a.get(i);
	    String prefix = symbol_prefix_a + String.valueOf(i);
	    io.setProperty(prefix, curr_symbol);
	}
    }

    /**
     * Loads symbols given key prefix
     * 
     * @param symbols_a        symbols loaded
     * @param size_prefix_a    String value of numeric size
     * @param symbol_prefix_a  prefix to search
     */
    public static void loadSymbols(Vector<String> symbols_a, String size_prefix_a, String symbol_prefix_a) {
	// get the io to set properties
	//
	Properties io = CData.io_d;
	
	// load all data members
	//
	String symbol_size = io.getProperty(size_prefix_a);
	int s_size = 0;

	if ( symbol_size != null ){
	    s_size = Integer.valueOf(symbol_size).intValue();
	}
	
	//System.out.println(symbol_size);

	// load all symbols
	//
	for (int i= 0; i < s_size; i++) {
	    String key = symbol_prefix_a + String.valueOf(i);
	    String curr_symbol = io.getProperty(key);
	    symbols_a.add(curr_symbol);
	    //System.out.println(key + " " + curr_symbol);
	}
    }

    /**
     * the repeated elements will not be occured in the new list
     * 
     * @param symbols_a the list of symbols to be sorted
     *
     * @return true
     */
    public static boolean sortSymbols(Vector<String> symbols_a) {

	Object[] symbols = symbols_a.toArray();
	Arrays.sort(symbols);
	symbols_a.clear();
	for ( int i = 0; i < symbols.length; i++ ){
	    String last;
	    if ( symbols_a.size() > 0 ){
		last = (String)symbols_a.lastElement();
		if (!last.equals((String)symbols[i])) {
		    symbols_a.add((String)symbols[i]);
		}
	    }
	    else {
		symbols_a.add((String)symbols[i]);
	    }
	}
	return true;
    }

    /**
     * prints messages for debugging purposes
     * 
     * @param msg_a message to be printed to the System
     */
    public static void printDebugMsg(String msg_a){
	
	if ( DEBUG_FLAG.equals("true") ){
	    System.out.println(msg_a);
	}
    }

    /**
     * Gives the distance between to x and y value pairs
     * 
     * @param x1 x-value of the first point
     * @param y1 y-value of the first point
     * @param x2 x-value of the second point
     * @param y2 y-value of the second point
     * @return distance between two points
     */
    static public double distance(int x1, int y1, int x2, int y2) {

        double distance = 0.0;

        // claculate the euclidean distance
        //
        double deltaX = x2 - x1;
        double deltaY = y2 - y1;
        double sqrX = deltaX * deltaX;
        double sqrY = deltaY * deltaY;

        distance = Math.sqrt((double)sqrX + (double)sqrY);

        // return the distance
        //
        return distance;
    }

}




















