
/**
 * ATKIS-EDBS-Reader to read EDBS-File, convert and write it to an Oracle database
 * Copyright (C) 2000  Stephan Falke, Carsten Kleiner, University of Hannover
 * 
 * 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 PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received 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 parser;

import java.awt.geom.*;
import GaussKruegerTrafo;
import java.lang.*;
import javax.swing.*;
import java.io.*;
import java.awt.*;
import java.util.*;

/**
 * Diese Klasse sorgt daf&uuml;r , da&szlig; eine Datei mit <it>ATKIS</it>-Daten
 * gelesen wird. Es wird eine Datei erstellt, die von einem <tt>SQL*loader</tt>
 * gelesen werden kann. Dieser erstellt dann eine erste Datenbank, in der die Daten
 * zwischengespeichert werden k&ouml;nnen.
 * @author <A href="mailto:fad@gmx.ch">Stephan Falke</A>
 */
class ReadIt {
	/**
	 * Der Vektor, in dem die Eintr&auml;ge gespeichert werden, die in eine Datei
	 * f&uuml;r den <tt>SQL*loader</tt> geschrieben werden.
	 */
	private static Vector tupel = new Vector();

	/**
	 *  ein Z&auml;hler der Linien. Die Linien werden &uuml;ber diese Nummer identifiziert.
	 */
	private static long lineCount = 0; 

	/**
	 * die Koordinaten der aktuellen Grundri&szlig;datei
	 */
	private static long[] coordinate = new long[2];
	
	/**
	 * die Dateien f&uuml;r den <tt>SQL*loader</tt>, in die die  Tupel geschrieben
	 * werden.
	 */
	private static MyFileOutputStream loadFile[] = new MyFileOutputStream[Constants.LOAD_FILE_COUNTER];	
 
	/**
	 * die Dateinamen der Loaderdateien
	 */
	private static String loadFileName[] = new String[Constants.LOAD_FILE_COUNTER];
	/**
	 * versucht eine Datei zum Schreiben zu &ouml;ffnen. Ist dies mit den angegebenen 
	 * Namen nocht m&ouml;glich, so wird ein zus&auml;tzlicher Index angeh&auml;ngt.
	 * @param name Dateiname ohne Index und Endung
	 * @param ending Dateinamenendung
	 */
	public static MyFileOutputStream createFile (String name, String ending) throws Exception {
		MyFileOutputStream fOS;
		for (int i = -1; i < Constants.MAX_FILENAME_INDEX; i++) {
			try {
				fOS = new MyFileOutputStream(i < 0 ? name + ending: name + i + ending);
				return(fOS);
			}
			catch (FileNotFoundException f) {
			}
		}
		throw new Exception(Constants.COULDNOT_CREATE_FILE + name + ending);
	}
	
	/**
	 * schreibt ein Datentupel in eine Datei f&uuml; den <tt>SQL*loader</tt>
	 * @param file die Datei, in die eine Zeile eingef&uuml;gt wird
	 */
	private static void writeDataTupel (FileOutputStream file) {
		String str = new String();
		try {
			if (!tupel.isEmpty()) {
				str = tupel.get(0).toString();
			}
			for (int i = 1; i < tupel.size(); i++) {
				str += Constants.TUPEL_DIVIDER + tupel.get(i).toString();
			}	
			str += "\n";
			file.write(str.getBytes());
		}
		catch (Exception e) {
			if (Constants.LOG) {
				System.out.println(Constants.COULDNOT_WRITE_TUPEL + str);
			}
		}
	}
	
	/**
	 * liest einen Numerierungsbezirk und Relativkoordinaten aus
	 * @return Koordinaten des Punktes
	 * @param ch die Zeichen der Zeile mit den Koordinaten am Anfang
	 */
    private static long[] readCoordinates (char[] ch) throws ParsingException {
                try {
                        long x[] = new long[2];
                        char[] coordinate1 = {ch[0], ch[1], ch[4], ch[8], ch[9], ch[10], ch[11], ch[12], ch[13]};
                        x[0] = Long.parseLong(new String(coordinate1));
                        char[] coordinate2 = {ch[2], ch[3], ch[6], ch[14], ch[15], ch[16], ch[17], ch[18], ch[19]};
                        x[1] = Long.parseLong(new String(coordinate2));
                        if (ch[0]!='3') {
                                //                              System.out.println(" Achtung: Unterschiedliche Meridianstreifen, Konversion erforderlich !");
                                Point2D.Double gaussalt = new Point2D.Double(((double)x[0])/100,((double)x[1])/100);
                                Point2D.Double philambda = new Point2D.Double();
                                GaussKruegerTrafo.gaussKruegerToGeograpisch(gaussalt, philambda);
                                Point2D.Double gaussneu = new Point2D.Double();
                                GaussKruegerTrafo.geographischToGaussKrueger(philambda, gaussneu, 9.0);
                                // in Germany always transform to 3rd meridian-stripe !!!
                                x[0] = (new Double(100*gaussneu.getX())).longValue();
                                x[1] = (new Double(100*gaussneu.getY())).longValue();
                        }
                        //System.out.println(" Koordinaten: ("+x[0]+", "+x[1]+")");
                        return(x);
                }
                catch (NumberFormatException n) {
                        throw new ParsingException(Constants.WRONG_COORDINATES, (new String(ch)).substring(0, Constants.COORDINATES_LENGTH));
                }
        }
	/*
	private static long[] readCoordinates (char[] ch) throws ParsingException {
		try {
			long x[] = new long[2];
			char[] coordinate1 = {ch[0], ch[1], ch[4], ch[8], ch[9], ch[10], ch[11], ch[12], ch[13]};
			x[0] = Long.parseLong(new String(coordinate1));
			char[] coordinate2 = {ch[2], ch[3], ch[6], ch[14], ch[15], ch[16], ch[17], ch[18], ch[19]};
			x[1] = Long.parseLong(new String(coordinate2));
			return(x);
		}
		catch (NumberFormatException n) {
			throw new ParsingException(Constants.WRONG_COORDINATES, (new String(ch)).substring(0, Constants.COORDINATES_LENGTH));
		}
	}
	*/
	/**
	 * liest aus einer bestimmten Anzahl von Zeichen einen <tt>int</tt>-Wert aus
	 */
	private static int readCount (String str) throws ParsingException, IndexOutOfBoundsException {
		try {
			int i;
			if (str.length() == Constants.COUNT_LENGTH)  {
					i = Integer.parseInt(str,10);
			}
			else {
				i = Integer.parseInt(str.substring(0,Constants.COUNT_LENGTH),10);
			}
			return(i);		
		}
		catch (NumberFormatException n) {
			throw new ParsingException(Constants.WRONG_COUNTER_FORMAT, str.substring(0,Constants.COUNT_LENGTH));
		}
	}
	
	/**
	 * liest einen Fachparameter einer Linienfunktion ein
	 * @param str die Zeile mit den Daten
	 */
	private static void readLineParam (String str) {
		int i = 0;
		tupel.insertElementAt(str.substring(i, i+= Constants.LINE_PARAM_RACE_LENGTH),tupel.size());
		tupel.insertElementAt(str.substring(i, i+= Constants.LINE_PARAM_TYPE_LENGTH),tupel.size());
		tupel.insertElementAt(str.substring(i, i+= Constants.LINE_PARAM_VALUE_LENGTH),tupel.size());
		writeDataTupel(loadFile[Constants.LFP_LINE_PARAM]);
		tupel.removeElementAt(tupel.size() - 1);//Wert des Fachparameters			
		tupel.removeElementAt(tupel.size() - 1);//Kennung des Fachparameters			
		tupel.removeElementAt(tupel.size() - 1);//Fachparameter		
	}
	
	/**
	 * liest einen Lageparameter einer Linie ein
	 * @param str die Zeile mit den Daten
	 */
	private static void readLineData (String str) throws ParsingException, IndexOutOfBoundsException {
		int i = 0;
		long[] point = readCoordinates(str.substring(i, i+= Constants.COORDINATES_LENGTH).toCharArray());
		tupel.insertElementAt(new Long(point[0]), tupel.size());
		tupel.insertElementAt(new Long(point[1]), tupel.size());
		writeDataTupel(loadFile[Constants.LFP_LINE_DATA]);
		tupel.removeElementAt(tupel.size() - 1);//Koordinate 2			
		tupel.removeElementAt(tupel.size() - 1);//Koordinate 1		
	}
	
	/**
	 * liest eine Linienfunktion ein
	 * @param str die Zeile mit den Daten
	 */
	private static int readLineFunction (String str) throws ParsingException, IndexOutOfBoundsException {
		int i = 0;
		if (str.substring(i,i += Constants.COUNT_LENGTH).compareTo(Constants.STD_ONE)!= 0) {
			throw new ParsingException(Constants.WRONG_COUNTER_FORMAT + Constants.COUNT_OF_LINE_FUNCTIONS + str.substring(0, Constants.COUNT_LENGTH), str);
		}
		else {
			tupel.insertElementAt(str.substring(i, i+= Constants.LAYER_LENGTH),tupel.size());
			tupel.insertElementAt(str.substring(i, i+= Constants.LINE_FUNCTION_RACE_LENGTH),tupel.size());
			String o = str.substring(i, i+= Constants.OBJECT_NO_LENGTH);
			boolean noObjectR = false;
			if (o.compareTo(Constants.NO_OBJECT_NO) == 0) {
				o = Constants.NULL_STRING;
				noObjectR = true;
			}
			tupel.insertElementAt(o,tupel.size());
			o = str.substring(i, i+= Constants.OBJECT_NO_LENGTH);
			boolean noObjectL = false;
			if (o.compareTo(Constants.NO_OBJECT_NO) == 0) {
				o = Constants.NULL_STRING;
				noObjectL = true;
			}
			tupel.insertElementAt(o,tupel.size());
			o = str.substring(i, i+= Constants.OBJECT_PART_NO_LENGTH);
			if (noObjectR) {
				o = Constants.NULL_STRING;
			}
			tupel.insertElementAt(o,tupel.size());
			o = str.substring(i, i+= Constants.OBJECT_PART_NO_LENGTH);
			if (noObjectL) {
				o = Constants.NULL_STRING;
			}
			tupel.insertElementAt(o,tupel.size());
			o = str.substring(i, i+= Constants.LINE_FUNCTION_DIV_LENGTH);
			if (noObjectR) {
				o = Constants.NULL_STRING;
			}
			tupel.insertElementAt(o,tupel.size());
			o = str.substring(i, i+= Constants.LINE_FUNCTION_DIV_LENGTH);
			if (noObjectL) {
				o = Constants.TUPEL_DIVIDER;
			}
			tupel.insertElementAt(o,tupel.size());
			writeDataTupel(loadFile[Constants.LFP_LINE_FUNC]);
			tupel.removeElementAt(tupel.size() - 1);//Linienteilung 2			
			tupel.removeElementAt(tupel.size() - 1);//Linienteilung 1			
			tupel.removeElementAt(tupel.size() - 1);//Objektteilnummer 2			
			tupel.removeElementAt(tupel.size() - 1);//Objektteilnummer 1			
			tupel.removeElementAt(tupel.size() - 1);//Objektnummer 2			
			tupel.removeElementAt(tupel.size() - 1);//Objektnummer 1			
			tupel.removeElementAt(tupel.size() - 1);//Linienart			
			tupel.removeElementAt(tupel.size() - 1);//Folie			
			int params = readCount(str.substring(i, i += Constants.COUNT_LENGTH));
			for (int t = 0; t < params; t++) {
				tupel.insertElementAt(new Integer(t), tupel.size());
				readLineParam(str.substring(i, i += Constants.LINE_PARAM_LENGTH));
				tupel.removeElementAt(tupel.size() - 1);//Parameternummer		
			}
			return(i);
		}
	}
	
	/**
	 * liest die Informationen zu einer Linie ein
	 * @param str die Zeile mit den Daten
	 */
	private static int readLine (String str) throws ParsingException, IndexOutOfBoundsException {
		int i = 0;
		if (str.substring(i,i += Constants.COUNT_LENGTH).compareTo(Constants.STD_ONE)!= 0) {
			throw new ParsingException(Constants.WRONG_COUNTER_FORMAT + Constants.COUNT_OF_LINES + str.substring(0, Constants.COUNT_LENGTH), str);
		}
		else {
			tupel.insertElementAt(new Long(lineCount), tupel.size());
			tupel.insertElementAt(new Long(coordinate[0]), tupel.size());
			tupel.insertElementAt(new Long(coordinate[1]), tupel.size());
			long[] endPoint = readCoordinates(str.substring(i, i+= Constants.COORDINATES_LENGTH).toCharArray());
			tupel.insertElementAt(new Long(endPoint[0]), tupel.size());
			tupel.insertElementAt(new Long(endPoint[1]), tupel.size());
			tupel.insertElementAt(str.substring(i, i+= Constants.LINE_GEOMETRY_LENGTH), tupel.size());
			writeDataTupel(loadFile[Constants.LFP_LINE]);
			tupel.removeElementAt(tupel.size() - 1);//Liniengeometrie
			tupel.removeElementAt(tupel.size() - 1);//Enpunktkopordinate
			tupel.removeElementAt(tupel.size() - 1);//Enpunktkopordinate
			tupel.removeElementAt(tupel.size() - 1);//Koordinate 2
			tupel.removeElementAt(tupel.size() - 1);//Koordinate 1
			int functions = readCount(str.substring(i, i += Constants.COUNT_LENGTH));
			for (int s = 0; s < functions; s++) {
				tupel.insertElementAt(new Integer(s), tupel.size());
				i += readLineFunction(str.substring(i));
				tupel.removeElementAt(tupel.size() - 1);//Funktionsnummer		
			}	
			int datas = readCount(str.substring(i, i += Constants.COUNT_LENGTH));
			for (int s = 0; s < datas; s++) {
				tupel.insertElementAt(new Integer(s), tupel.size());
				readLineData(str.substring(i, i+= Constants.LINE_DATA_LENGTH));
				tupel.removeElementAt(tupel.size() - 1);//Lageparameternummer		
			}	
			lineCount++;
			tupel.clear();	
			return(i);		
		}
	}
	
	/**
	 * liest Geometrieangaben zu einem Objekt ein
	 * @param str die Zeile mit den Daten
	 */
	private static void readObjectGeo (String str) throws ParsingException, IndexOutOfBoundsException {
		long[] coor = readCoordinates(str.toCharArray());
		tupel.insertElementAt(new Long(coor[0]), tupel.size());
		tupel.insertElementAt(new Long(coor[1]), tupel.size());
		writeDataTupel(loadFile[Constants.LFP_OBJ_GEO]);
		tupel.removeElementAt(tupel.size() - 1);//Koordinate 2
		tupel.removeElementAt(tupel.size() - 1);//Koordinate 1		
	}
	

	/**
	 * liest Informationen zu einem Objekt ein
	 * @param str die Zeile mit den Daten
	 */
	private static int readObjectData (String str) throws ParsingException, IndexOutOfBoundsException {
		int i = 0;
		if (str.substring(i,i += Constants.COUNT_LENGTH).compareTo(Constants.STD_ONE)!= 0) {
			throw new ParsingException(Constants.WRONG_COUNTER_FORMAT + Constants.COUNT_OF_OBJECT_DATAS + str.substring(0, Constants.COUNT_LENGTH), str);
		}
		else {
			tupel.insertElementAt(str.substring(i, i += Constants.OBJECT_DATA_INFO_RACE_LENGTH), tupel.size());
			tupel.insertElementAt(str.substring(i, i += Constants.OBJECT_DATA_MAP_TYPE_LENGTH), tupel.size());
			tupel.insertElementAt(str.substring(i, i += Constants.OBJECT_DATA_SIG_LENGTH), tupel.size());
			tupel.insertElementAt(str.substring(i, i += Constants.OBJECT_DATA_TEXT_LENGTH).replace(Constants.TUPEL_DIVIDER.charAt(0), Constants.REPLACE_TUPEL_DIVIDER), tupel.size());
			tupel.insertElementAt(str.substring(i, i += Constants.OBJECT_DATA_GEO_RACE_LENGTH), tupel.size());
			tupel.insertElementAt(str.substring(i, i += Constants.OBJECT_PART_NO_LENGTH), tupel.size());
			writeDataTupel(loadFile[Constants.LFP_OBJ_DATA]);
			tupel.removeElementAt(tupel.size() - 1);//Objektteilnummer
			tupel.removeElementAt(tupel.size() - 1);//Art der Geometrieangabe
			tupel.removeElementAt(tupel.size() - 1);//Text
			tupel.removeElementAt(tupel.size() - 1);//Signaturteilnummer
			tupel.removeElementAt(tupel.size() - 1);//Kartentyp
			tupel.removeElementAt(tupel.size() - 1);//Informationsart			
			int datas = readCount(str.substring(i, i += Constants.COUNT_LENGTH));
			for (int s = 0; s < datas; s++) {
				tupel.insertElementAt(new Integer(s), tupel.size());
				readObjectGeo(str.substring(i, i+= Constants.OBJECT_GEO_LENGTH));
				tupel.removeElementAt(tupel.size() - 1);//Nummer der Geometrieangabe
			}		
			return(i);
		}
	}
	
	/**
	 * liest ein Objekt ein
	 * @param str die Zeile mit den Daten
	 */
	private static int readObject (String str) throws ParsingException, IndexOutOfBoundsException {
		int i = 0;
		if (str.substring(i,i += Constants.COUNT_LENGTH).compareTo(Constants.STD_ONE)!= 0) {
			throw new ParsingException(Constants.WRONG_COUNTER_FORMAT + Constants.COUNT_OF_OBJECTS + str.substring(0, Constants.COUNT_LENGTH), str);
		}
		else {
			tupel.insertElementAt(new Long(coordinate[0]), tupel.size());
			tupel.insertElementAt(new Long(coordinate[1]), tupel.size());
			tupel.insertElementAt(str.substring(i, i += Constants.LAYER_LENGTH), tupel.size());
			tupel.insertElementAt(str.substring(i, i += Constants.OBJECT_RACE_LENGTH), tupel.size());
			tupel.insertElementAt(str.substring(i, i += Constants.OBJECT_ACT_LENGTH), tupel.size());
			tupel.insertElementAt(str.substring(i, i += Constants.OBJECT_TYPE_LENGTH), tupel.size());
			tupel.insertElementAt(str.substring(i, i += Constants.OBJECT_NO_LENGTH), 0);
			tupel.insertElementAt(str.substring(i, i += Constants.OBJECT_MODEL_TYPE_LENGTH), tupel.size());
			tupel.insertElementAt(str.substring(i, i += Constants.OBJECT_DATE_LENGTH), tupel.size());
			tupel.insertElementAt(str.substring(i, i += Constants.OBJECT_DIFF_LENGTH), tupel.size());
			writeDataTupel(loadFile[Constants.LFP_OBJ]);
			tupel.removeElementAt(tupel.size() - 1);//Ver&auml;derungskennung
			tupel.removeElementAt(tupel.size() - 1);//Datum
			tupel.removeElementAt(tupel.size() - 1);//Modelltyp
			tupel.removeElementAt(tupel.size() - 1);//Objekttyp
			tupel.removeElementAt(tupel.size() - 1);//Aktualit&auml;t
			tupel.removeElementAt(tupel.size() - 1);//Objektart
			tupel.removeElementAt(tupel.size() - 1);//Folie
			tupel.removeElementAt(tupel.size() - 1);//Koordinate 2
			tupel.removeElementAt(tupel.size() - 1);//Koordinate 1
			int datas = readCount(str.substring(i, i += Constants.COUNT_LENGTH));
			for (int s = 0; s < datas; s++) {
				tupel.insertElementAt(new Integer(s), tupel.size());
				i += readObjectData(str.substring(i));
				tupel.removeElementAt(tupel.size() - 1);//Nummer der Information
			}	
			tupel.clear();
			return(i);	
		}
	}

				
	/**
	 * bearbeitet eine Grundri&szlig;datei
	 * @param str die Zeile ohne den Header
	 */
	private static void readGround (String str) throws ParsingException, IndexOutOfBoundsException {
		int i = 0;
		if (str.substring(i,i += Constants.COUNT_LENGTH * 2).compareTo(Constants.STD_ONE + Constants.STD_ONE)!= 0) {
			throw new ParsingException(Constants.WRONG_COUNTER_FORMAT + Constants.COUNT_OF_ALL + str.substring(0, Constants.COUNT_LENGTH), str);
		}
		else {
			coordinate = readCoordinates(str.substring(i, i += Constants.COORDINATES_LENGTH + Constants.GROUND_CHECK_LENGTH).toCharArray());
			int lines = readCount(str.substring(i, i += Constants.COUNT_LENGTH));
			for (int r = 0; r < lines; r++) {
				i += readLine(str.substring(i));
			}
			int objects = readCount(str.substring(i, i += Constants.COUNT_LENGTH));
			for (int r = 0; r < objects; r++) {
				i += readObject(str.substring(i));
			}
		}
	}
	
	/**
	 * Bearbeitet eine Attributdatei
	 * @param str die Zeile ohne den Header
	 */
	private static void readAttribute (String str) throws ParsingException, IndexOutOfBoundsException {		
		int i = 0;
		if (str.substring(i,i += Constants.COUNT_LENGTH * 2).compareTo(Constants.STD_ONE + Constants.STD_ONE)!= 0) {
			throw new ParsingException(Constants.WRONG_COUNTER_FORMAT + Constants.COUNT_OF_ATTRRIBUTES + str.substring(0, Constants.COUNT_LENGTH), str);
		}
		String objNo = str.substring(i, i+= Constants.OBJECT_NO_LENGTH);
		String objPartNo = str.substring(i, i+= Constants.OBJECT_PART_NO_LENGTH);
		try {
			tupel.insertElementAt(objNo, tupel.size());
			tupel.insertElementAt(objPartNo, tupel.size());
		}
		catch (ArrayIndexOutOfBoundsException a) {
			throw new ParsingException(Constants.TUPEL_ERROR + objNo + Constants.TUPEL_DIVIDER + objPartNo, str);
		}
		i += Constants.ATTRIBUTE_CHECK_LENGTH;
		int count = readCount(str.substring(i, i+= Constants.COUNT_LENGTH));
		for (int r = 1; r <= count; r++) { 
			String type = str.substring(i, i+= Constants.ATTRIBUTE_TYPE_LENGTH);
			String value = str.substring(i, i+= Constants.ATTRIBUTE_VALUE_LENGTH);
			try {
				tupel.insertElementAt(type, tupel.size());
				tupel.insertElementAt(value, tupel.size());
				writeDataTupel(loadFile[Constants.LFP_ATT]);
				tupel.removeElementAt(tupel.size() - 1);// Attribut Wert
				tupel.removeElementAt(tupel.size() - 1);// Abtribut Typ
			}
			catch (ArrayIndexOutOfBoundsException a) {
				if (Constants.LOG) {
					System.out.println(Constants.TUPEL_ERROR + objNo + Constants.TUPEL_DIVIDER + objPartNo + Constants.TUPEL_DIVIDER + type + Constants.TUPEL_DIVIDER + value);
				}
			}
			catch (Exception e) {
			}
		}
		tupel.clear();
	}
	
	/**
	 * bearbeitet die angegebene Zeile
	 * @param str die zu bearbeitende Zeile
	 */
	private static void readOneLine (String str) throws ParsingException {
		if (str.length() == -1) throw new ParsingException(Constants.EMPTY_LINE, str);
		int i = 0;
		try {
			if (str.substring(i, i + Constants.KEY_WORD.length()).compareTo(Constants.KEY_WORD) != 0) {
				throw new ParsingException(Constants.NO_KEY_WORD + str.substring(i, i + Constants.KEY_WORD.length()), str);
			}
			i = Constants.HEADER_LEGTH;
			if (str.substring(i, i + Constants.GROUND_DATA.length()).compareTo(Constants.GROUND_DATA) == 0) {
				i += Constants.GROUND_DATA.length();
				readGround(str.substring(i));
			}
			else if (str.substring(i, i + Constants.SPECIAL_DATA.length()).compareTo(Constants.SPECIAL_DATA) == 0) {
				i += Constants.GROUND_DATA.length();
				readAttribute(str.substring(i));
			}
			else {
				throw new ParsingException(Constants.CANNOT_SPECIFY_DATA + (str.substring(i, i + Constants.SPECIAL_DATA.length())), str);
			}
		}
		catch (ArrayIndexOutOfBoundsException a) {
			throw new ParsingException(Constants.TUPEL_ERROR, str);
		}
		catch (IndexOutOfBoundsException b) {
			throw new ParsingException(Constants.LINE_TO_SHORT, str);
		}
	}
		
	/**
	 * bearbeitet die angegebene Datei
	 * @param file die zu &ouml;ffnende Datei
	 */
	private static void parseIt (File file) throws Exception {
		FileInputStream fIS;
		try {
			fIS = new FileInputStream(file);
		}
		catch (FileNotFoundException f) {
			if (Constants.LOG) {
				System.out.println(Constants.FILE_NOT_FOUND);
			}
			throw new Exception(Constants.FILE_NOT_FOUND);
		}
		for (int i = 0; i < Constants.LOAD_FILE_COUNTER; i++) {
			try {
				loadFile[i] = createFile (Constants.TABLE_NAMES[i], Constants.LOAD_FILE_ENDING);
			}
			catch (Exception e) {
				if (Constants.LOG) {
					System.out.println(Constants.COULDNOT_CREATE_FILE + Constants.TABLE_NAMES[i] + Constants.LOAD_FILE_ENDING);
				}
				throw new Exception(Constants.COULDNOT_CREATE_FILE + Constants.TABLE_NAMES[i] + Constants.LOAD_FILE_ENDING);
			}
		}
		StringWriter strW = new StringWriter();
		String line = new String();
		int c;
		try {
			while ((c = fIS.read()) != -1) {
				if ((c == 13) || (c == 10)) {
					if (strW.toString().length() != 0) {
						if (line.length() == 0) {
							line = strW.toString();
						}
						else {
							line += strW.toString().substring(Constants.HEADER_NEXT_LENGTH);
						}
						strW = new StringWriter(Constants.MAX_EDBS_LINE_LENGTH);
					}
				}
				else {
					strW.write(c);
					if (strW.toString().length() == Constants.HEADER_CONTROL_LENGTH) {
						if (strW.toString().endsWith(Constants.STD_ONE.concat(Constants.STD_ONE))) {
							try {
								readOneLine(line);
								line = new String();
							}
							catch (ParsingException p) {
								line = new String();
								tupel.clear();
								lineCount++;
								if (Constants.LOG) {
									System.out.println(p.getMessage());
									System.out.println(p.originalLine);
								}
							}
						}
					}
				}
			}
			try {
				readOneLine(line);
			}
			catch (ParsingException p) {
				System.out.println(p.getMessage());
				System.out.println(p.originalLine);
			}

		}
		catch (IOException i) {
			if (Constants.LOG) System.out.println(Constants.LOST_FILE);
			throw new Exception(Constants.LOST_FILE);
		}
		for (int i = 0; i < Constants.LOAD_FILE_COUNTER; i++) {
			try {
				loadFileName[i] = loadFile[i].getFilename();
				loadFile[i].close();
			}
			catch (Exception e) {
				if (Constants.LOG) {
					System.out.println(Constants.COULDNOT_CLOSE_FILE + loadFile[i].getFilename());
				}
				throw new Exception(Constants.COULDNOT_CLOSE_FILE + loadFile[i].getFilename());
			}
		}
	}

    /**
	 * &ouml;ffnet einen Dialog, in dem der Benutzer ausw&auml;hlt, welche Datei er 
	 * einlesen m&ouml;chte
	 * @return die ausgew&auml;hlte Datei
	 */
	private static File selectFile () throws Exception {
		javax.swing.filechooser.FileFilter filter = new MyFileFilter();
		JFileChooser chooser = new JFileChooser();
		chooser.setFileFilter(filter);
		Component parent = new Container();
		parent.setVisible(true);
		chooser.setVisible(true);
		int returnVal = chooser.showOpenDialog(parent);
		if(returnVal == JFileChooser.APPROVE_OPTION) {
	    	if (Constants.LOG) {
				System.out.println(Constants.FILE_CHOSEN + chooser.getSelectedFile().getName());
	    	}
			return (chooser.getSelectedFile());
		}
		else throw new Exception(Constants.CANNOT_OPEN_FILE + chooser.getSelectedFile().getName());
		}

	/**
	 * f&uuml;r den Aufruf des Parsers
	 */
    public static void main (String[] args) {
		File file;
		try {
			if (args.length >= 3 && args[2] != null) {
				try {
					file = new File(args[2]);
				}
				catch (Exception e) {
					file = selectFile();
				}
			}
			else {
		    	file = selectFile();
			}
			parseIt(file);
			int i = TempTables.createTempTables(args);
			Loader.startLoader(i, loadFileName);
		}
		catch (Exception e) {
		    System.out.println(e.getMessage());
			System.exit(0);
		}
		System.exit(0);
    }
}
