/*
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOUSE. See the GNU
 * General Public License for more details.
 *
 * You should have recieved a copy of the GNU General Public License
 * along with this program; if not write to the Free Software
 * Foundation, inc., 59 Temple Place, Suite 330, Boston MA 02111-1307
 * USA
 */

package run.readers;

import run.Controlset;
import run.Element;
import run.Load;
import run.Material;
import run.ModifiedStreamTokenizer;
import run.Node;
import run.Reader;
import run.RplVector;
import run.Token;
import run.TrackWriter;
import run.Tracker;
import run.Writer;
import run.materials.*;
import run.Constraint;
import uka.karmi.rmi.RemoteException;

import java.io.*;

import java.text.ParseException;

import java.util.*;

import jp.lang.RemoteObject;


/**
 * Insert the type's description here. Creation date: (2001-08-20 22:51:18)
 *
 * @author: Jonas Forssell
 */
public class NastranReader extends Reader {
    private java.io.BufferedReader br, br2;
    private java.lang.String filename;
    private java.lang.String[] keywords = {
        "BEGIN", "ENDDATA"
    };
    private boolean in_block = false, in_block2 = false;
    private java.io.StreamTokenizer str, str2;
    private Node temporary_node;
    private Constraint temporary_constraint;
    private Load temporary_load;
    private boolean element_in_block = false;
    private boolean tracker_in_block = false;
    private boolean material_in_block = false;
    private java.lang.String current_element_type;
    private java.lang.String current_tracker_type;
    private java.lang.String current_constraint_type;
    private Controlset temporary_controlset;
    private boolean control_in_block;
    private boolean constraint_in_block;
    private String nextline;
    private int cnum;

    /**
     * This constructor immediately tries to open the file.
     */
    public NastranReader(String fn) {
        int i;

        // Remember this filename
        filename = new String(fn);
        cnum = 0;
    }

    /**
     * Insert the method's description here. Creation date: (2001-08-20
     * 23:00:59)
     */
    public void close() {
        try {
            br.close();
        } catch (IOException ioe) {
            System.out.println(
                "An IOException has occurred when closing the indata file"
            );

            return;
        }
    }

    /**
     * Insert the method's description here. Creation date: (2001-08-20
     * 23:00:59)
     */
    public void close2() {
        try {
            br2.close();
        } catch (IOException ioe) {
            System.out.println(
                "An IOException has occurred when closing the indata file"
            );

            return;
        }
    }


    /**
     * This method reads the next constraint, sets up all the paremeters and
     * returns a handle to the constraint. Creation date: (26/08/01 %T)
     *
     * @return krockpackage.Node
     *
     * @exception java.text.ParseException The exception description.
     */
    public void getControlSet(Controlset temporary_controlset)
        throws IllegalArgumentException
    {
		Token[] t;

		try {

			// For now, this is hardcoded default controlset
			t = new Token[5];
		
			t[0] = new Token("RUN");
			t[1] = new Token("FROM");
			t[2] = new Token("0");
			t[3] = new Token("TO");
			t[4] = new Token("1");

	        temporary_controlset.parse_Fembic(t , str.lineno() );

			t = new Token[4];

			t[0] = new Token("PRINT");
			t[1] = new Token("EVERY");
			t[2] = new Token("0.1");
			t[3] = new Token("STEP");

	        temporary_controlset.parse_Fembic(t , str.lineno() );

            // Check all required data has been filled in
            temporary_controlset.checkIndata();

            // OK, everything read now. Lets end. The data has already been filled into the controlset given as an argument
            // so there is nothing to return.
        } catch (ParseException e) {
            throw new IllegalArgumentException(
                e.getMessage() + " in line: " + (e.getErrorOffset() - 1)
            );
        } catch (IllegalArgumentException e) {
            throw new IllegalArgumentException(e.getMessage());
        }
    }

    /**
     * This method reads the next element type, sets up the paremeters and
     * returns a handle Creation date: (26/08/01 %T)
     *
     * @return krockpackage.Material
     *
     * @exception java.text.ParseException The exception description.
     */
    public Element getNextElement(RplVector materiallist, RplVector nodelist,
    		RplVector loadlist, Hashtable nodetable
)
        throws java.text.ParseException
    {
        int index;
        Element temporary_element;
        String element_type, property_type;
        Token[] t,t2;
        
        element_type = "";
        property_type = "";
        t2 = null;

        // Assume the file has been opened
        // If we are not in a node block, search until we find one.
        try {
             while (str.nextToken() != java.io.StreamTokenizer.TT_EOF) {
                   if (str.ttype == java.io.StreamTokenizer.TT_WORD) {
                        if (str.sval.toUpperCase().replaceAll(",", " ").trim().equals("CBAR")) {
                        	element_type = ("ROD_2");
                        	property_type = ("PBAR");
                            in_block = true;
                            break;
                        }
                        if (str.sval.toUpperCase().replaceAll(",", " ").trim().equals("CQUAD4")) {
                        	element_type = ("SHELL_BT_4");
                        	property_type = ("PSHELL");
                            in_block = true;
                            break;
                        }
                        if (str.sval.toUpperCase().replaceAll(",", " ").trim().equals("CTRIA3")) {
                        	element_type = ("SHELL_C0_3");
                        	property_type = ("PSHELL");
                            in_block = true;
                            break;
                        }
                        if (str.sval.toUpperCase().replaceAll(",", " ").trim().equals("CHEXA")) {
                        	element_type = ("SOLID_ISO_6");
                        	property_type = ("PSOLID");
                            in_block = true;
                            break;
                        }
                        if (str.sval.toUpperCase().replaceAll(",", " ").trim().equals("CTETRA")) {
                        	element_type = ("SOLID_ISO_4");
                        	property_type = ("PSOLID");
                            in_block = true;
                            break;
                        }
                        
                    }
                }
           
            // We should now be in a block. If not, throw an error
            if (! in_block) {
                throw new java.text.ParseException(
                    "No known element type found", str.lineno()
                );
            }

            // We have found a node.
            // Tokenize in fixed format and hand over to the node
            temporary_element = Element.getElementOfType_Fembic(element_type);

			t = tokenize(br,8,str.sval.toUpperCase().replaceAll(",", " ").trim());

			// Second field contains the property card reference. Use this to find the 
			// right property

			this.open2();
			
             while (str2.nextToken() != java.io.StreamTokenizer.TT_EOF) {
                   if (str2.ttype == java.io.StreamTokenizer.TT_WORD) {
                        if (str2.sval.toUpperCase().replaceAll(",", " ").trim().equals(property_type)) {
                        	t2 = tokenize(br2,8,property_type);
							if (t2[1].getn() == t[2].getn()) {
                            	in_block2 = true;
                            	break; 
							}          
                        }             
                    }
                }
           
            // We should now be in a block. If not, throw an error
            if (! in_block2) {
            	close2();
                throw new java.text.ParseException(
                    "No known element property type found", str.lineno()
                );
            }
			
			// The right property card should now be tokenized in t2, so close that file.
			close2();			

			// Time to parse all element data
            temporary_element.parse_Nastran(t, t2, str.lineno(), nodelist, materiallist, loadlist, nodetable);

            // Check all required data has been filled in
            temporary_element.checkIndata();
			
            return temporary_element;
            
            // 
        } catch (java.io.IOException e) {
            throw new IllegalArgumentException(e.getMessage());
        } catch (ParseException e) {
            throw new IllegalArgumentException(
                e.getMessage() + " in line: " + (e.getErrorOffset() - 1)
            );
        } catch (IllegalArgumentException e) {
            throw new IllegalArgumentException(e.getMessage());
        }
    }

    /**
     * This method reads the next tracker from the indata file, sets up all the
     * parameters and creates the corresponding tracker object. Since the
     * parameters for each tracker may vary, it makes sence to keep all that
     * varability inside the definition of the tracker. Therefore, a new
     * method called parse_Fembic is designed for each tracker where the
     * checking and parsing of the variables are taken care of. A beauty of
     * object oriented design is that the parent class is returned  from this
     * method since the functionality really is irrelevant to the program from
     * here on. Creation date: (26/08/01 %T)
     *
     * @return krockpackage.Element
     *
     * @exception java.text.ParseException The exception description.
     */
    public Tracker getNextTracker(
        RplVector nodelist, RplVector elementlist
    )
        throws java.text.ParseException
    {
        boolean tracker_type_exists;
        int index;
        Tracker temporary_tracker;
        String arg1;
        String arg2;
        String arg3;

        // Assume the file has been opened
        // If we are not in a tracker block, search until we find one.
        try {
            // Start with "cleaning" out extra lines etc.
            while (str.nextToken() == java.io.StreamTokenizer.TT_EOL) {
                ;
            }

            str.pushBack();

            // Now, assume we are reading a tracker line
            while (str.nextToken() != java.io.StreamTokenizer.TT_NUMBER) {
                str.pushBack();

                //This is not the case, so search until the next block of trackers is found
                tracker_in_block = false;

                while (str.nextToken() != java.io.StreamTokenizer.TT_EOF) {
                    if (str.ttype == java.io.StreamTokenizer.TT_WORD) {
                        if (str.sval.toUpperCase().equals("TRACKERS")) {
                            if (
                                str.nextToken() == java.io.StreamTokenizer.TT_WORD
                            ) {
                                if (str.sval.toUpperCase().equals("OF")) {
                                    ;
                                } else {
                                    throw new java.text.ParseException(
                                        "No 'OF' defined in tracker block header",
                                        str.lineno()
                                    );
                                }
                            }

                            if (
                                str.nextToken() == java.io.StreamTokenizer.TT_WORD
                            ) {
                                if (str.sval.toUpperCase().equals("TYPE")) {
                                    ;
                                } else {
                                    throw new java.text.ParseException(
                                        "No 'TYPE' defined in tracker block header",
                                        str.lineno()
                                    );
                                }
                            }

                            if (
                                str.nextToken() == java.io.StreamTokenizer.TT_WORD
                            ) {
                                current_tracker_type = new String(
                                        str.sval.toUpperCase()
                                    );
                            } else {
                                throw new java.text.ParseException(
                                    "Unknown type defined in tracker block header",
                                    str.lineno()
                                );
                            }

                            System.out.println("Tracker block found!");
                            tracker_in_block = true;

                            // Clear EOL
                            str.nextToken();

                            break;
                        }
                    }
                }
            }

            // We should now be in a block. If not, throw an error
            if (! tracker_in_block) {
                throw new java.text.ParseException(
                    "No trackers block found or missing trackers", str.lineno()
                );
            }

            // Parse the tracker number and put into the tracker object
            temporary_tracker = Tracker.getTrackerOfType_Fembic(
                    current_tracker_type
                );
            temporary_tracker.setNumber((int) str.nval);
            tracker_type_exists = true;

            // Continue and read the tracker parameters, assuming the format 'param = val'
            temporary_tracker.parse_Fembic(
                tokenize(str), str.lineno(), nodelist, elementlist
            );

            // Check all required data has been filled in
            temporary_tracker.checkIndata();

            /* Getting this far means that all parameters for the tracker is defined,
               so return the temporary tracker now
               Note the upcasting!!*/
            return (Tracker) temporary_tracker;

            // 
        } catch (java.io.IOException e) {
            throw new IllegalArgumentException(e.getMessage());
        } catch (ParseException e) {
            throw new IllegalArgumentException(
                e.getMessage() + " in line: " + (e.getErrorOffset() - 1)
            );
        } catch (IllegalArgumentException e) {
            throw new IllegalArgumentException(e.getMessage());
        }
    }

    /**
     * This method reads the next constraint, sets up all the paremeters and
     * returns a handle to the constraint. Creation date: (26/08/01 %T)
     *
     * @return krockpackage.Node
     *
     * @exception java.text.ParseException The exception description.
     */
    public Constraint getNextConstraint(RplVector nodelist)
        throws java.text.ParseException
    {
        int index;
        Constraint temporary_constraint;
        Token[] t;
 
        try {
 
            // Start examining the file and continue until end of file is reached
            while (str.nextToken() != str.TT_EOF) {

                // check token for the key word "constraints"
                     if (str.ttype == str.TT_WORD && str.sval.toUpperCase().replaceAll(",", " ").trim().equals("SPC1"))
                     {
						
						cnum++;

			            // Parse the tracker number and put into the tracker object
			            temporary_constraint = Constraint.getConstraintOfType_Nastran(str.sval.toUpperCase().replaceAll(",", " ").trim());

		    	        // Continue and read the tracker parameters. Repeat until end of parameters.

						t = tokenize(br,8,str.sval.toUpperCase().replaceAll(",", " ").trim());

			            temporary_constraint.parse_Nastran(
			                t, cnum, nodelist
						);


			            // Check all required data has been filled in
			            temporary_constraint.checkIndata();

			            /* Getting this far means that all parameters for the tracker is defined,
            			   so return the temporary tracker now
			               Note the upcasting!!*/
			            return (Constraint) temporary_constraint;
                     }
            }

		// Nothing found, return null
		return null;

        } catch (java.io.IOException e) {
            throw new IllegalArgumentException(e.getMessage());
        } catch (ParseException e) {
            throw new IllegalArgumentException(
                e.getMessage() + " in line: " + (e.getErrorOffset() - 1)
            );
        } catch (IllegalArgumentException e) {
            throw new IllegalArgumentException(e.getMessage());
        }
    }

    /**
     * This method reads the next load, sets up all the paremeters and returns
     * a handle to the load. Creation date: (26/08/01 %T)
     *
     * @return krockpackage.Node
     *
     * @exception java.text.ParseException The exception description.
     */
    public Load getNextLoad(RplVector nodelist)
        throws java.text.ParseException
    {
            // Do nothing
          return null;

    }

    /**
     * This method reads the next material type, sets up the paremeters and
     * returns a handle Creation date: (26/08/01 %T)
     *
     * @return krockpackage.Material
     *
     * @exception java.text.ParseException The exception description.
     */
    public Material getNextMaterial()
        throws java.text.ParseException
    {
        int index;
        Material temporary_material;

        // Assume the file has been opened
        // If we are not in a node block, search until we find one.
        try {
             while (str.nextToken() != java.io.StreamTokenizer.TT_EOF) {
                   if (str.ttype == java.io.StreamTokenizer.TT_WORD) {
                        if (
                            str.sval.toUpperCase().replaceAll(",", " ").trim().equals("MAT1")
                        ) {
                            in_block = true;

                            break;
                        }
                    }
                }
           
            // We should now be in a block. If not, throw an error
            if (! in_block) {
                throw new java.text.ParseException(
                    "No MAT1 found or missing materials", str.lineno()
                );
            }

            // We have found a node.
            // Tokenize in fixed format and hand over to the node
            temporary_material = Material.getMaterialOfType_Nastran(str.sval.toUpperCase().replaceAll(",", " ").trim());

            temporary_material.parse_Nastran(
                tokenize(br,8,"MAT1"), str.lineno());

            // Check all required data has been filled in
            temporary_material.checkIndata();

            return temporary_material;
            
            // 
        } catch (java.io.IOException e) {
            throw new IllegalArgumentException(e.getMessage());
        } catch (ParseException e) {
            throw new IllegalArgumentException(
                e.getMessage() + " in line: " + (e.getErrorOffset() - 1)
            );
        } catch (IllegalArgumentException e) {
            throw new IllegalArgumentException(e.getMessage());
        }
    }

    /**
     * This method reads the next node, sets up all the paremeters and returns
     * a handle to the node. Creation date: (26/08/01 %T)
     *
     * @return krockpackage.Node
     *
     * @exception java.text.ParseException The exception description.
     */
    public Node getNextNode(
    		RplVector constraintlist, RplVector loadlist
    )
        throws java.text.ParseException
    {
        int index;
        Constraint temp_constraint;
        Load temp_load;

        // Assume the file has been opened
        // If we are not in a node block, search until we find one.
        try {
             while (str.nextToken() != java.io.StreamTokenizer.TT_EOF) {
                   if (str.ttype == java.io.StreamTokenizer.TT_WORD) {
                        if (
                            str.sval.toUpperCase().replaceAll(",", " ").trim().equals("GRID")
                        ) {
                            in_block = true;

                            break;
                        }
                    }
                }
           
            // We should now be in a block. If not, throw an error
            if (! in_block) {
                throw new java.text.ParseException(
                    "No nodes block found or missing nodes", str.lineno()
                );
            }

            // We have found a node.
            // Tokenize in fixed format and hand over to the node

            temporary_node = new Node();

            temporary_node.parse_Nastran(
                tokenize(br,8,"GRID"), str.lineno(), constraintlist, loadlist
            );

            // Check all required data has been filled in
            temporary_node.checkIndata();

            return temporary_node;
 
 
        } catch (java.io.IOException e) {
            throw new IllegalArgumentException(e.getMessage());
        } catch (ParseException e) {
            throw new IllegalArgumentException(
                e.getMessage() + " in line: " + (e.getErrorOffset() - 1)
            );
        } catch (IllegalArgumentException e) {
            throw new IllegalArgumentException(e.getMessage());
        }
    }

    /**
     * Insert the method's description here. Creation date: (26/08/01 %T)
     *
     * @param param java.lang.String
     *
     * @return boolean
     */
    private boolean isAKeyword(String param) {
        int i;

        for (i = 0; i < keywords.length; i++) {
            if (keywords[i].equals(param.toUpperCase())) {
                return true;
            }
        }

        return false;
    }

    /**
     * Insert the method's description here. Creation date: (28/08/01 %T)
     *
     * @return int
     *
     * @exception java.text.ParseException The exception description.
     */
    public int numberOfConstraints()
        throws java.text.ParseException
    {
        int noc = 0;

        // Open file and start reading from beginning
        this.open();

        try {
            // Start examining the file and continue until end of file is reached
            while (str.nextToken() != str.TT_EOF) {
                // check token for the key word "constraints"
                     if (str.ttype == str.TT_WORD && str.sval.replace(',',' ').trim().equals("SPC1"))
                                noc++;               
                }

            System.out.println("Found " + noc + " constraints");
        } catch (IOException ioe) {
            System.out.println(
                "IOException when reading a constraintline from indata file"
            );
            this.close();

            return -1;
        }

        this.close();

        return noc;
    }

    /**
     * Insert the method's description here. Creation date: (28/08/01 %T)
     *
     * @return int
     *
     * @exception java.text.ParseException The exception description.
     */
    public int numberOfControls()
        throws java.text.ParseException
    {
        int noc;

		// hard coded dummy
		noc = 1;

        System.out.println("Found " + noc + " controls");


        return noc;
    }

    /**
     * This method examines the indata file to determine the number of elements
     * supplied there. Note that there may be several different types of
     * elements, each under a new headline. Example: elements of type beam 1
     * nodes=[1,2] A=5.0 ..... elements of type rod 1 nodes=[2,3] A=3.2 .....
     * Creation date: (21/08/01 %T)
     *
     * @return int
     */
    public int numberOfElements()
        throws java.text.ParseException
    {
        int noe = 0;

        // Open file and start reading from beginning
        this.open();

        try {
            // Start examining the file and continue until end of file is reached
            while (str.nextToken() != str.TT_EOF) {

                     if (str.ttype == str.TT_WORD && str.sval.replace(',',' ').trim().equals("CQUAD4"))
                                   noe++;
                     if (str.ttype == str.TT_WORD && str.sval.replace(',',' ').trim().equals("CTRIA3"))
                                   noe++;
                     if (str.ttype == str.TT_WORD && str.sval.replace(',',' ').trim().equals("CBAR"))
                                   noe++;
                     if (str.ttype == str.TT_WORD && str.sval.replace(',',' ').trim().equals("CHEXA"))
                                   noe++;
                     if (str.ttype == str.TT_WORD && str.sval.replace(',',' ').trim().equals("CTETRA"))
                        noe++;

            }

            System.out.println("Found " + noe + " elements");
        } catch (IOException ioe) {
            System.out.println(
                "IOException when reading an element line from indata file"
            );
            this.close();

            return -1;
        }

        if (noe == 0) {
            this.close();
            throw new java.text.ParseException("No elements found", 0);
        }

        this.close();

        return noe;
    }

    /**
     * This method examines the indata file to determine the number of trackers
     * supplied there. Note that there may be several different types of
     * trackers, each under a new headline. Example: trackers of type
     * sectionforce 1 nodes = [1,2,3]  filename = ..... trackers of type
     * sectionmoment 1 nodes = [2,3] filename = .....         Creation date:
     * (21/08/01 %T)
     *
     * @return int
     */
    public int numberOfTrackers()
        throws java.text.ParseException
    {
        int not = 0;

		// hard coded dummy
		not = 0;

        System.out.println("Found " + not + " trackers");

        return not;
    }

    /**
	     * Insert the method's description here. Creation date: (28/08/01 %T)
	     *
	     * @return int
	     *
	     * @exception java.text.ParseException The exception description.
	     */
	    public int numberOfGroups()
	        throws java.text.ParseException
	    {
	        int noc = 0;
	
	/*
	        // Open file and start reading from beginning
	        this.open();
	
	        try {
	            // Start examining the file and continue until end of file is reached
	            while (str.nextToken() != str.TT_EOF) {
	
	                     if (str.ttype == str.TT_WORD && str.sval.replace(',',' ').trim().equals("FORCE"))
	                                   noc++;
	            }
	
	            System.out.println("Found " + noc + " forces");
	        } catch (IOException ioe) {
	            System.out.println(
	                "IOException when reading a force line from indata file"
	            );
	            this.close();
	
	            return -1;
	        }
	*/
	
	        this.close();
	
	        return noc;
	    }

	/**
     * Insert the method's description here. Creation date: (28/08/01 %T)
     *
     * @return int
     *
     * @exception java.text.ParseException The exception description.
     */
    public int numberOfLoads()
        throws java.text.ParseException
    {
        int noc = 0;

/*
        // Open file and start reading from beginning
        this.open();

        try {
            // Start examining the file and continue until end of file is reached
            while (str.nextToken() != str.TT_EOF) {

                     if (str.ttype == str.TT_WORD && str.sval.replace(',',' ').trim().equals("FORCE"))
                                   noc++;
            }

            System.out.println("Found " + noc + " forces");
        } catch (IOException ioe) {
            System.out.println(
                "IOException when reading a force line from indata file"
            );
            this.close();

            return -1;
        }
*/

        this.close();

        return noc;
    }

    /**
     * Insert the method's description here. Creation date: (21/08/01 %T)
     *
     * @return int
     */
    public int numberOfMaterials()
        throws java.text.ParseException
    {
        int nom = 0;

        // Open file and start reading from beginning
        this.open();

        try {
            // Start examining the file and continue until end of file is reached
            while (str.nextToken() != str.TT_EOF) {

                     if (str.ttype == str.TT_WORD && str.sval.replace(',',' ').trim().equals("MAT1"))
                                   nom++;
            }

            System.out.println("Found " + nom + " materials");
        } catch (IOException ioe) {
            System.out.println(
                "IOException when reading a material line from indata file"
            );
            this.close();

            return -1;
        }

        if (nom == 0) {
            this.close();
            throw new java.text.ParseException("No materials found", 0);
        }

        this.close();

        return nom;
    }

    /**
     * Insert the method's description here. Creation date: (21/08/01 %T)
     *
     * @return int
     */
    public int numberOfNodes()
        throws java.text.ParseException
    {
        int non = 0;

        // Open file and start reading from beginning
        this.open();

        try {
            // Start examining the file and continue until end of file is reached
            while (str.nextToken() != str.TT_EOF) {

                     if (str.ttype == str.TT_WORD && str.sval.replace(',',' ').trim().equals("GRID"))
                                   non++;
            }

            System.out.println("Found " + non + " nodes");
        } catch (IOException ioe) {
            System.out.println(
                "IOException when reading a node line from indata file"
            );
            this.close();

            return -1;
        }

        if (non == 0) {
            this.close();
            throw new java.text.ParseException("No nodes found", 0);
        }

        this.close();

        return non;
    }

    /**
     * This constructor immediately tries to open the file.
     */
    public void open2() {
        FileReader fr;

        // Opening the file means that parameters should be set to zero
        in_block2 = false;

        // Try to open the indata file
        try {
            fr = new FileReader(filename);
        } catch (FileNotFoundException fnfe) {
            System.out.println("Fembic file does not exist");

            return;
        }

        try {
            br2 = new BufferedReader(fr);
        } catch (IllegalArgumentException ioe) {
            System.out.println(
                "An IllegalArgumentException has occurred when opening the indata file"
            );

            return;
        }

        str2 = new ModifiedStreamTokenizer(br2);
    }


    /**
     * This constructor immediately tries to open the file.
     */
    public void open() {
        FileReader fr;

        // Opening the file means that parameters should be set to zero
        in_block = false;
        control_in_block = false;
        constraint_in_block = false;
        element_in_block = false;

        // Try to open the indata file
        try {
            fr = new FileReader(filename);
        } catch (FileNotFoundException fnfe) {
            System.out.println("Fembic file does not exist");

            return;
        }

        try {
            br = new BufferedReader(fr);
        } catch (IllegalArgumentException ioe) {
            System.out.println(
                "An IllegalArgumentException has occurred when opening the indata file"
            );

            return;
        }

        str = new ModifiedStreamTokenizer(br);
    }


    /**
     * This method returns the writer to be used for the results
     */
    public Writer getWriter(
        RplVector nodelist, RplVector elementlist, Controlset control, RemoteObject[] cluster_nodes
    )
        throws RemoteException
    {
        Writer a;
        a = Writer.getWriterOfType_Fembic(
                control.getWriter(), nodelist, elementlist, cluster_nodes
            );

            a.checkIndata();

        return a;
    }

    /**
     * This method returns the Trackwriter to be used for the trackers
     */
    public TrackWriter getTrackWriter(RplVector trackerlist, Controlset control, RemoteObject[] cluster_nodes)
        throws RemoteException
    {
        TrackWriter a;
        a = TrackWriter.getTrackWriterOfType_Fembic(
                control.getTrackWriter(), trackerlist
            );

            a.checkIndata();

        return a;
    }

    /**
     * Overriding this routine to add some more features related to Nastran.
     */
    public Token[] tokenize(java.io.StreamTokenizer str)
        throws IOException
    {
        int i;
        double num;
        String temp;
        String temp1;
        String temp2;
        Vector v = new Vector();
        Token t;
        Token[] arr;

        // Start by reading all the words and numbers on the line into the p vector.
        while (
            (str.nextToken() != java.io.StreamTokenizer.TT_EOL) &&
            (str.ttype != java.io.StreamTokenizer.TT_EOF)
        ) {
            if (str.ttype == java.io.StreamTokenizer.TT_WORD) {
                v.add(new Token(str.sval.trim()));
            } else {
                v.add(new Token(str.nval));
            }
        }

        // Now, begin examining the vector for correct parsing.
        for (i = 0; i < v.size(); i++) {
            // Check if this token is a word.
            t = (Token) v.elementAt(i);

            if (t.is_a_word()) {
                temp = new String(t.getw());

                // This may be a beginning of a [ set. If so, search until next set if found.
                if (temp.startsWith("[") && ! temp.endsWith("]")) {
                    v.remove(i);

                    while (! temp.endsWith("]")) {
                        if (i >= v.size()) {
                            throw new IOException(
                                "IO Exception trying to find end ] of a parameter set in string\n"
                            );
                        }

                        t = (Token) v.elementAt(i);
                        v.remove(i);

                        if (t.is_a_number()) {
                            temp += new Double(t.getn()).toString();
                        } else {
                            temp += t.getw().trim();
                        }
                    }

                    v.insertElementAt(new Token(temp), i);
                } else
                // Check to see if there is an = sign in there (i.e. no spaces around the =)
                // If so, split up into three tokens and make the parser read them again.
                if ((temp.indexOf("=") != -1) && (temp.length() > 1)) {
                    v.remove(i);

                    if (temp.indexOf("=") != 0) {
                        v.insertElementAt(
                            new Token(temp.substring(0, temp.indexOf("="))), i
                        );
                    } else {
                        i--;
                    }

                    v.insertElementAt(new Token(new String("=")), i + 1);

                    if (temp.indexOf("=") != (temp.length() - 1)) {
                        v.insertElementAt(
                            new Token(
                                temp.substring(
                                    temp.indexOf("=") + 1, temp.length()
                                )
                            ), i + 2
                        );
                    }

                    i--;
                }
            } else
            // t is a number, leave it alone	
             {
            }
        }

        arr = new Token[v.size()];

        for (i = 0; i < v.size(); i++) {
            arr[i] = (Token) v.elementAt(i);
        }

        return arr;
    }

    /**
     * Overriding this routine to add some more features related to Nastran.
     */
    public Token[] tokenize(BufferedReader str, int number_of_chars, String intro)
        throws IOException
    {
        int i,j;
        String temp;
        Vector v = new Vector();
        Token[] arr;
        Token temptok;
        boolean looping = false;

		do {

    	    // Start by reading all the words and numbers on the line into the p vector.
    	    try {

   	     	temp = str.readLine().replaceAll(",", " , ");
   	     	if (looping == false)
   	     	if (temp.indexOf(",") > -1 && temp.indexOf(",") != 1) temp = intro + "," + temp;
 	     	   else temp = intro + " " + temp;
			
     		
   	     		
  	      } catch (IOException ioe) {
 	           System.out.println(
 	               "IOException when trying to generate tokens from indata file"
 	           );
   	         this.close();

  	          return null;
  	      }

			//If number_of_chars is zero, then flexible format is assumed. Comma is divider.
			if (number_of_chars == 0 || temp.indexOf(",") > -1)
			{
				j = 0;
				i = temp.indexOf(",",j);

     	 	    while (i > -1)
    		    {
    		    	temptok = new Token(temp.substring(j,i));
    	 	 	    v.add(temptok);
   	    	 	 	    
     	 	 	    j = i+1;
					i = temp.indexOf(",",j);
    		    }

				v.add(new Token(temp.substring(j,temp.length())));	
			}
			else 
			{
	        	// Fixed format requested. Chop up the string in requested sizes.
    		    for (i = 0; i < temp.length(); i+= number_of_chars) 
        		    v.add(new Token(temp.substring(i,((i+number_of_chars) <= temp.length() ? i+number_of_chars : temp.length()))));
			}

		looping = true;

		} while (((Token)v.lastElement()).is_a_word() && ((Token)v.lastElement()).getw().startsWith("+"));

		// Clean up the vector
		
        for (i = v.size()-1; i > -1; i--) {
            temptok = (Token) v.elementAt(i);
            if (temptok.is_a_word() && temptok.getw().startsWith("+")) v.removeElementAt(i);
        }

		// Convert to an array
        arr = new Token[v.size()];

        for (i = 0; i < v.size(); i++) {
            arr[i] = (Token) v.elementAt(i);
        }

        return arr;
    }
    
    /**
     * Insert the method's description here. Creation date: (2001-10-31
     * 00.46.27)
     *
     * @return int
     *
     * @exception java.text.ParseException The exception description.
     */
    public void preProcess() throws java.text.ParseException
 	{ 
	// Use this method to create whitespaces around all commas in order for the parser to
	// detect everything correctly.

	this.open2();
	
	






    }
    
}
