/**
 * ATKIS-EDBS-Reader This part to convert from temporary to final 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
 */

/**
 * Ein Paket zum Erstellen und Laden einer Datenbank für räumliche Daten
 * @author <A href="mailto:fad@gmx.ch">Stephan Falke</A>
 */
CREATE OR REPLACE PACKAGE BODY fad AS 
	
	/**
	 * Tabellenname der temporären Tabelle der Objekte
	 */
    t_object_tn VARCHAR2(9) := 't_object';

	/**
	 * Tabellenname der temporären Tabelle der besonderen Objektinformationen
	 */
    t_object_data_tn VARCHAR2(13) := 't_object_data';

	/**
	 * Tabellenname der temporären Tabelle der Geometrienangaben der 
	 * Objektbezeichungen
	 */
    t_object_geo_tn VARCHAR2(12) := 't_object_geo';

	/**
	 * Tabellenname der temporären Tabelle der Linien
	 */
    t_line_tn VARCHAR2(6) := 't_line';

	/**
	 * Tabellenname der temporären Tabelle der Lageparameter der Linien
	 */
    t_line_data_tn VARCHAR2(11) := 't_line_data';

	/**
	 * Tabellenname der temporären Tabelle der Linienfunktionen
	 */
    t_line_function_tn VARCHAR2(15) := 't_line_function';

	/**
	 * Tabellenname der temporären Tabelle der Fachparameter der Linien
	 */
    t_line_param_tn VARCHAR2(12) := 't_line_param';

	/**
	 * Tabellenname der temporären Tabelle der Attribute
	 */
    t_attribute_tn VARCHAR2(11) := 't_attribute';
    
    /**
	 * Tabellenname des nested-tables der Geometrieangaben der 
	 * Objektbezeichungen
	 */
	name_geo_table_tn VARCHAR2(14) := 'name_geo_table';
    
	/**
	 * Tabellenname der temporären Tabelle für den Linienverfolgungsalgorithmus
	 */
	t_geo_tn VARCHAR2(5) := 't_geo';
   
    /**
	 * Nummer, mit der die Numerierung der Linien gestartet wird.
	 */
	MyCountStart NUMBER := 0;
   
    /**
	 * Nummer, mit der die Numerierung der Poygone gestartet wird.
	 */
    MyPolygonStart NUMBER := 0;
	
	/**
	 * Artnummer, die für Verbindungslinien steht
	 */
    ConnectionRace VARCHAR2(4) := '0242';

    /**
	 * Linienartnummer eines Polygonzuges
	 */
	PolygonzugID VARCHAR2(2) := '15';
    
	/**
	 * Orientierungsnummer von Linien mit Orientierung vom Grundrißkennzeichen
	 * zum Endpunkt der Linien
	 */
	NormalDirection NUMBER(1) := 0;
    
	/**
	 * Orientierungsnummer von Linien mit Orientierung vom Endpunkt der Linien
	 * zum Grundrißkennzeichen
	 */
	OtherDirection NUMBER(1) := 1;
    
    /**
	 * Zählvariable
	 */ 
	create_count NUMBER := 0;

    /**
	 * Index der erstellten Zieldatenbank
	 */
	my_index VARCHAR2(2):= '';

    /**
	 * Fehlermelung: konnte keine Tabellen anlegen
	 */
	could_not_create_tables VARCHAR2(29) := 'Konnte keine Tabellen anlegen';    

	/**
	 * Objektnummer für punktförmige Objekte
	 */
	first_object_part_str VARCHAR2(3):= '001';
	
	/**
	 * Art der Information: Name
	 */
    info_race_name_id VARCHAR2(2) := '44';
	
	/**
	 * Art der Information: Referenz auf ein untergeordnetes Objekt
	 */
    info_race_big_id VARCHAR2(2) := '42';
	
	/**
	 * Art der Information: Referenz auf ein übergeordnetes Objekt
	 */
    info_race_small_id VARCHAR2(2) := '41';
	
	/**
	 * Art der Information: Überführung
	 */
    info_race_over_id VARCHAR2(2) := '46';
	
	/**
	 * Art der Information: Unterführung
	 */
    info_race_under_id VARCHAR2(2) := '47';
    
	/**
	 * Fehlermeldung, falls ein Fehler beim Einfügen der Objektbezeichnungen
	 * auftritt.
	 */
	error_name VARCHAR2(46) := 'Fehler beim Einfügen der Objektbezeichnungen: ';
    
	/**
	 * Fehlermeldung, falls ein allgemeiner Fehler beim Einfügen der Überführungen
	 * auftritt.
	 */
    error_above_all VARCHAR2(40) := 'Fehler beim Einfügen der Überführungen: ';

	/**
	 * Fehlermeldung, falls ein Fehler beim Einfügen einer Überführung auftritt.
	 */
    error_above_one VARCHAR2(48) := 'Eine Überführung konnte nicht eingefügt werden: ';
	
	/**
	 * Fehlermeldung, falls ein Fehler beim Einfügen der komplexen Objekte 
	 * auftritt.
	 */
    error_complex VARCHAR2(45) := 'Fehler beim Einfügen der komplexen Objekte : ';

	/**
	 * Fehlermeldung, falls ein Fehler bei der Erstellung einer Linienbeschreibung
	 * auftritt.
	 */
    error_line_describe VARCHAR2(52) := 'Fehler bei der Erstellung einer Linienbeschreibung: ';

	/**
	 * Fehlermeldung, falls ein Fehler bei der Erstellung einer Flächenbeschreibung
	 * auftritt.
	 */
    error_area_describe VARCHAR2(53) := 'Fehler bei der Erstellung einer Flächenbeschreibung: ';

	/**
	 * Fehlermeldung, falls ein Fehler bei der Erstellung einer Flächenbeschreibung
	 * auftritt.
	 */
    error_bad_area_describe VARCHAR2(59) := 'Fehler bei der Erstellung einer Ersatzflächenbeschreibung: ';

	/**
	 * Fehlermeldung, falls ein Fehler bei der Linienverfolgung
	 * auftritt.
	 */
    error_line_find VARCHAR2(33) := 'Fehler bei der Linienverfolgung: ';

	/**
	 * Fehlermeldung, falls ein Fehler beim Einfügen der punktförmigen Objekte
	 * auftritt.
	 */
    error_points VARCHAR2(48) := 'Fehler beim Einfügen der punktförmigen Objekte: ';

	/**
	 * Fehlermeldung, falls ein Teil eines linienförmigen Objekts nicht 
	 * eingefügt werden konnte.
	 */
    error_line_object_part VARCHAR2(53) := 'Fehler beim Einfügen des lininenförmigen Objektteils ';

	/**
	 * Fehlermeldung, falls ein linienförmigen Objekt nicht 
	 * eingefügt werden konnte.
	 */
    error_line_object VARCHAR2(49) := 'Fehler beim Einfügen des lininenförmigen Objekts ';
		
	/**
	 * Warnmeldung, falls ein ein flächenförmiges Objektteil nicht vollständig beschrieben 
	 * werden kann.
	 */
    warn_area_object_part VARCHAR2(68) := 'Kann eine flächenförmiges Objektteil nicht vollständig beschreiben: ';
		
	/**
	 * Warnmeldung, falls ein ein flächenförmiges Objektteil nicht beschrieben 
	 * werden kann.
	 */
    warn_bad_area_object_part VARCHAR2(56) := 'Kann eine flächenförmiges Objektteil nicht beschreiben: ';
		
	/**
	 * Fehlermeldung, falls beim Einfügen ein flächenförmiges Objektteil ein Fehler
	 * auftritt.
	 */
    error_area_object_part VARCHAR2(56) := 'Fehler beim Einfügen eines flächenförmigen Objektteils: ';
		
	/**
	 * Fehlermeldung, falls beim Einfügen eines flächenförmiges Objekt ein Fehler
	 * auftritt.
	 */
    error_area_object VARCHAR2(52) := 'Fehler beim Einfügen eines flächenförmigen Objekts: ';
		
	/**
	 * Fehlermeldung, falls ein allgemeiner Fehler beim Einfügen der Objektgeometrien
	 * auftritt.
	 */
    error_geometries VARCHAR2(56) := 'Allgemeiner Fehler beim Einfügen der Objektgeometrien: ';

	/**
	 * Fehlermeldung, falls ein Fehler beim Einfügen eines Attributes
	 * auftritt.
	 */
    error_att_one VARCHAR2(39) := 'Fehler beim Zuordnen eines Attributes: ';
		
	/**
	 * Fehlermeldung, falls ein allgemeiner Fehler beim Einfügen der Attribute
	 * auftritt.
	 */
    error_att_all VARCHAR2(48) := 'Allgemeiner Fehler beim Einfügen der Attribute: ';

	/**
	 * Zählvariable, die angibt, an welche Zeichenkette angehängt wird.
	 */
	insert_no NUMBER(1) := 0;
	
	/**
	 * erste Zeichenkette der Einfügeanweisung für flächenförmige Objekte
	 */
	insert_stmt0 VARCHAR2(4000) := '';
	
	/**
	 * erste Zeichenkette der Einfügeanweisung für flächenförmige Objekte
	 */
	insert_stmt1 VARCHAR2(4000) := '';
	
	/**
	 * zweite Zeichenkette der Einfügeanweisung für flächenförmige Objekte
	 */
	insert_stmt2 VARCHAR2(4000) := '';
	
	/**
	 * dritte Zeichenkette der Einfügeanweisung für flächenförmige Objekte
	 */
	insert_stmt3 VARCHAR2(4000) := '';
	
	/**
	 * vierte Zeichenkette der Einfügeanweisung für flächenförmige Objekte
	 */
	insert_stmt4 VARCHAR2(4000) := '';
	
	/**
	 * fünfte Zeichenkette der Einfügeanweisung für flächenförmige Objekte
	 */
	insert_stmt5 VARCHAR2(4000) := '';
	
	/**
	 * sechste Zeichenkette der Einfügeanweisung für flächenförmige Objekte
	 */
	insert_stmt6 VARCHAR2(4000) := '';
	
	/**
	 * siebte Zeichenkette der Einfügeanweisung für flächenförmige Objekte
	 */
	insert_stmt7 VARCHAR2(4000) := '';
	
	/**
	 * achte Zeichenkette der Einfügeanweisung für flächenförmige Objekte
	 */
	insert_stmt8 VARCHAR2(4000) := '';
	
	/**
	 * neunte Zeichenkette der Einfügeanweisung für flächenförmige Objekte
	 */
	insert_stmt9 VARCHAR2(4000) := '';
	    
	/**
	 * löscht die Einfügeanweisung für flächenförmige Objekte
	 */
	PROCEDURE insert_clear  IS
	BEGIN
		insert_no := 0;
		insert_stmt0 := '';
		insert_stmt1 := '';
		insert_stmt2 := '';
		insert_stmt3 := '';
		insert_stmt4 := '';
		insert_stmt5 := '';
		insert_stmt6 := '';
		insert_stmt7 := '';
		insert_stmt8 := '';
		insert_stmt9 := '';
	END;
	
    /**
	 * fügt eine Zeichenkette an die Einfügeanweisung für flächenförmige 
	 * Objekte an
	 * @param new_chars die anzuhängende Zeichenkette
	 */
	PROCEDURE insert_append (new_chars VARCHAR2) IS
	BEGIN
		IF insert_no = 0 THEN insert_stmt0 := insert_stmt0||new_chars;
		ELSIF insert_no = 1 THEN insert_stmt1 := insert_stmt1||new_chars;
		ELSIF insert_no = 2 THEN insert_stmt2 := insert_stmt2||new_chars;
		ELSIF insert_no = 3 THEN insert_stmt3 := insert_stmt3||new_chars;
		ELSIF insert_no = 4 THEN insert_stmt4 := insert_stmt4||new_chars;
		ELSIF insert_no = 5 THEN insert_stmt5 := insert_stmt5||new_chars;
		ELSIF insert_no = 6 THEN insert_stmt6 := insert_stmt6||new_chars;
		ELSIF insert_no = 7 THEN insert_stmt7 := insert_stmt7||new_chars;
		ELSIF insert_no = 8 THEN insert_stmt8 := insert_stmt8||new_chars;
		ELSIF insert_no = 9 THEN insert_stmt9 := insert_stmt9||new_chars;
		END IF;
	EXCEPTION
		WHEN OTHERS THEN
			insert_no := insert_no + 1;
			insert_append(new_chars);
	END;
	
	/**
	 * erzeugt die Tabellen einer Zieldatenbank
	 * @my_no der Index in den Tabellennamen
	 */
	PROCEDURE create_tables (my_no VARCHAR2) IS
        create_stmt VARCHAR2(3000);
    BEGIN
        create_count := 0;

        create_stmt  := 'CREATE TABLE '||object_tn||my_no||' (  ObjNo VARCHAR2(7) NOT NULL CONSTRAINT pk_'||my_no||'object PRIMARY KEY,
    					LayerNo VARCHAR2(3) NOT NULL CONSTRAINT fk_'||my_no||'object_layer REFERENCES '||layer_tn||'(LayerNo),
    					ObjectRaceNo VARCHAR2(4) NOT NULL CONSTRAINT fk_'||my_no||'object_race REFERENCES '||object_race_tn||'(ObjRaceNo),
    					CoordinateX NUMBER(9) NOT NULL,
    					CoordinateY NUMBER(9) NOT NULL,
    					ModType VARCHAR2(2) NOT NULL, 
    					BuildDate DATE )';
        EXECUTE IMMEDIATE create_stmt;
        create_count := 1;
        
        create_stmt  := 'CREATE TABLE '||complex_object_tn||my_no||' ( BigNo VARCHAR2(7) NOT NULL CONSTRAINT fk_'||my_no||'comlpex_object_big REFERENCES '||object_tn||my_no||'(ObjNo),
    					SmallNo VARCHAR2(7) NOT NULL CONSTRAINT fk_'||my_no||'comlpex_object_small REFERENCES '||object_tn||my_no||'(ObjNo),
    					CONSTRAINT pk_'||my_no||'complex_object PRIMARY KEY (BigNo, SmallNo) )';
        EXECUTE IMMEDIATE create_stmt;
        create_count := 2;

        create_stmt := 'CREATE TABLE '||object_geometry_tn||my_no||' (  ObjectNo VARCHAR2(7) NOT NULL CONSTRAINT fk_'||my_no||'geo_object REFERENCES '||object_tn||my_no||'(ObjNo),
    					ObjectPartNo VARCHAR2(7) NOT NULL,
    					ObjectGeometry MDSYS.SDO_GEOMETRY,
    					CONSTRAINT pk_'||my_no||'object_geometry PRIMARY KEY (ObjectNo, ObjectPartNo) )';
        EXECUTE IMMEDIATE create_stmt;
        create_count := 3;

        create_stmt := 'CREATE TABLE '||above_tn||my_no||' (    TopNo VARCHAR2(7) NOT NULL ,
    					TopPartNo VARCHAR2(3) NOT NULL,
    					DownNo VARCHAR2(7) NOT NULL,
    					DownPartNo VARCHAR2(3) NOT NULL,
    					CONSTRAINT fk_'||my_no||'above_top FOREIGN KEY (TopNo, TopPartNo) REFERENCES '||object_geometry_tn||my_no||'(ObjectNo, ObjectPartNo), 
    					CONSTRAINT fk_'||my_no||'above_down FOREIGN KEY (DownNo, DownPartNo) REFERENCES '||object_geometry_tn||my_no||'(ObjectNo, ObjectPartNo), 
    					CONSTRAINT pk_'||my_no||'above PRIMARY KEY (TopNo, TopPartNo, DownNo, DownPartNo) )';
        EXECUTE IMMEDIATE create_stmt;
        create_count := 4;
        
        create_stmt := 'CREATE TABLE '||attribute_tn||my_no||' (    ObjectNo VARCHAR2(7) NOT NULL CONSTRAINT fk_'||my_no||'attribute_obj REFERENCES '||object_tn||my_no||'(ObjNo),
    					ObjectPartNo VARCHAR2(7) NOT NULL,
    					Type VARCHAR2(4) NOT NULL CONSTRAINT fk_'||my_no||'attribute_types REFERENCES '||attribute_types_tn||'(AttTypeNo),
    					Value VARCHAR2(7) NOT NULL,
    					CONSTRAINT pk_'||my_no||'attribute PRIMARY KEY (ObjectNo, ObjectPartNo, Type, Value) )';
        EXECUTE IMMEDIATE create_stmt;
        create_count := 5;
        
        create_stmt := 'CREATE TYPE '||name_geo_entry_typ_tn||my_no||' AS OBJECT ( CoordinateX NUMBER(9),   CoordinateY NUMBER(9) )';
        EXECUTE IMMEDIATE create_stmt;
        create_count := 6;

        create_stmt := 'CREATE TYPE '||name_geo_table_typ_tn||my_no||' AS TABLE OF '||name_geo_entry_typ_tn||my_no;
        EXECUTE IMMEDIATE create_stmt;
        create_count := 7;

        create_stmt := 'CREATE TABLE '||object_name_tn||my_no||' (  ObjectNo VARCHAR2(7) NOT NULL CONSTRAINT fk_'||my_no||'object_name REFERENCES '||object_tn||my_no||'(ObjNo),
    					Type VARCHAR2(2) NOT NULL,
    					Value VARCHAR2(31),
    					Geo '||name_geo_table_typ_tn||my_no||',
    					CONSTRAINT pk_'||my_no||'object_name PRIMARY KEY (ObjectNo, Type) )
    					NESTED TABLE Geo STORE AS '||name_geo_table_tn||my_no;
        EXECUTE IMMEDIATE create_stmt;
        create_count := 8;
        create_stmt := 'CREATE TABLE '||bad_geometries_tn||my_no||' (    ObjNo VARCHAR2(7) NOT NULL,
    					ObjPartNo VARCHAR2(3) NOT NULL,
    					CoordX NUMBER(9) NOT NULL,
    					CoordY NUMBER(9) NOT NULL,
    					MyNo NUMBER,
    					PolygonNo NUMBER,
    					CONSTRAINT pk_'||my_no||'bad_geos PRIMARY KEY (ObjNo, ObjPartNo, PolygonNo, MyNo) )';
        EXECUTE IMMEDIATE create_stmt;
        create_count := 9;

        create_stmt := 'CREATE TABLE '||t_geo_tn||my_no||' (    LineNo NUMBER NOT NULL,
    					ObjPartNo VARCHAR2(3) NOT NULL,
    					BegX NUMBER(9) NOT NULL,
    					BegY NUMBER(9) NOT NULL,
    					EndX NUMBER(9) NOT NULL,
    					EndY NUMBER(9) NOT NULL,
    					Race VARCHAR2(2) NOT NULL,
    					Direction NUMBER(1) NOT NULL,
    					MyNo NUMBER,
    					PolygonNo NUMBER,
    					CONSTRAINT pk_'||my_no||'t_geo PRIMARY KEY (LineNo, ObjPartNo) )';
        EXECUTE IMMEDIATE create_stmt;
        create_count := 10;
    END create_tables;

	/**
	 * löscht temporären Tabellen
	 * t_index der Index Tabellennamen der zu löschenden Tabellen
	 */
    PROCEDURE drop_tables (my_no VARCHAR2, last NUMBER) IS
        drop_stmt VARCHAR2(150);
    BEGIN
        IF last >= 10 THEN 
            BEGIN
                drop_stmt := 'DROP TABLE '||t_geo_tn||my_no;
                EXECUTE IMMEDIATE drop_stmt;
                EXCEPTION
                    WHEN OTHERS THEN ROLLBACK;
            END;
        END IF;
        IF last >= 9 THEN 
            BEGIN
                drop_stmt := 'DROP TABLE '||bad_geometries_tn||my_no;
                EXECUTE IMMEDIATE drop_stmt;
                EXCEPTION
                    WHEN OTHERS THEN ROLLBACK;
            END;
        END IF;
        IF last >= 8 THEN 
            BEGIN
                drop_stmt := 'DROP TABLE '||object_name_tn||my_no;
                EXECUTE IMMEDIATE drop_stmt;
                EXCEPTION
                    WHEN OTHERS THEN ROLLBACK;
            END;
        END IF;
        IF last >= 7 THEN 
            BEGIN
                drop_stmt := 'DROP TYPE '||name_geo_table_typ_tn||my_no;
                EXECUTE IMMEDIATE drop_stmt;
                EXCEPTION
                    WHEN OTHERS THEN ROLLBACK;
            END;
        END IF;
        IF last >= 6 THEN 
            BEGIN
                drop_stmt := 'DROP TYPE '||name_geo_entry_typ_tn||my_no;
                EXECUTE IMMEDIATE drop_stmt;
                EXCEPTION
                    WHEN OTHERS THEN ROLLBACK;
            END;
        END IF;
        IF last >= 5 THEN 
            BEGIN
                drop_stmt := 'DROP TABLE '||attribute_tn||my_no;
                EXECUTE IMMEDIATE drop_stmt;
                EXCEPTION
                    WHEN OTHERS THEN ROLLBACK;
            END;
        END IF;
        IF last >= 4 THEN 
            BEGIN
                drop_stmt := 'DROP TABLE '||above_tn||my_no;
                EXECUTE IMMEDIATE drop_stmt;
                EXCEPTION
                    WHEN OTHERS THEN ROLLBACK;
            END;
        END IF;
        IF last >= 3 THEN 
            BEGIN
                drop_stmt := 'DROP TABLE '||object_geometry_tn||my_no;
                EXECUTE IMMEDIATE drop_stmt;
                EXCEPTION
                    WHEN OTHERS THEN ROLLBACK;
            END;
        END IF;
        IF last >= 2 THEN 
            BEGIN
                drop_stmt := 'DROP TABLE '||complex_object_tn||my_no;
                EXECUTE IMMEDIATE drop_stmt;
                EXCEPTION
                    WHEN OTHERS THEN ROLLBACK;
            END;
        END IF;
        IF last >= 1 THEN 
            BEGIN
                drop_stmt := 'DROP TABLE '||object_tn||my_no;
                EXECUTE IMMEDIATE drop_stmt;
                EXCEPTION
                    WHEN OTHERS THEN ROLLBACK;
            END;
        END IF;
    END;
    
	PROCEDURE drop_temp_tables (t_index VARCHAR2) IS
	BEGIN
		BEGIN
			EXECUTE IMMEDIATE 'DROP TABLE '||t_attribute_tn||t_index;
		EXCEPTION
			WHEN OTHERS THEN ROLLBACK;
		END;
		BEGIN
			EXECUTE IMMEDIATE 'DROP TABLE '||t_line_data_tn||t_index;
		EXCEPTION
			WHEN OTHERS THEN ROLLBACK;
		END;
		BEGIN
			EXECUTE IMMEDIATE 'DROP TABLE '||t_line_param_tn||t_index;
		EXCEPTION
			WHEN OTHERS THEN ROLLBACK;
		END;
		BEGIN
			EXECUTE IMMEDIATE 'DROP TABLE '||t_line_function_tn||t_index;
		EXCEPTION
			WHEN OTHERS THEN ROLLBACK;
		END;
		BEGIN
			EXECUTE IMMEDIATE 'DROP TABLE '||t_line_tn||t_index;
		EXCEPTION
			WHEN OTHERS THEN ROLLBACK;
		END;
		BEGIN
			EXECUTE IMMEDIATE 'DROP TABLE '||t_object_geo_tn||t_index;
		EXCEPTION
			WHEN OTHERS THEN ROLLBACK;
		END;
		BEGIN
			EXECUTE IMMEDIATE 'DROP TABLE '||t_object_data_tn||t_index;
		EXCEPTION
			WHEN OTHERS THEN ROLLBACK;
		END;
	END;
	
	/**
	 * erzeugt eine Zieldatenbank
	 * @return der Index, mit der die Zieldatenbank erstellt wurde
	 */
    FUNCTION create_all RETURN NUMBER IS
        i NUMBER := 0;
    BEGIN
        FOR i IN 0..max_table_index LOOP
            BEGIN
				IF (i = 0) THEN
					drop_tables('',10);
				ELSE drop_tables(i,10);
				END IF;
                IF (i = 0) THEN
                    create_tables('');
                    RETURN(-1);
                ELSIF (i < max_table_index) THEN
                    create_tables(i-1);
                    RETURN(i-1);
                END IF;
                EXCEPTION
                    WHEN OTHERS THEN drop_tables(i,create_count);
            END;
        END LOOP;
        raise_application_error(-20010,could_not_create_tables);
    END create_all;

	/**
	 * lädt die Tabelle der Objekte
	 * @param t_object_name Name der temporären Tabelle der Objekte
	 * @param layer_table_name Name der Folientabelle
	 * @param object_race_table_name Name der Objektartentabelle
	 * @param object_name Name der Tabelle der Zieldatenbank der Objekte
	 */ 
    PROCEDURE load_objects (t_object_name VARCHAR2, layer_table_name VARCHAR2, object_race_table_name VARCHAR2, object_name VARCHAR2) IS
        insert_stmt VARCHAR(400);                                   
    BEGIN
        insert_stmt := 'INSERT INTO '||object_race_table_name||'    SELECT DISTINCT ObjRace, ''NN automatisch erstellt'' FROM '||t_object_name||' WHERE NOT EXISTS ( SELECT * FROM '||object_race_table_name||' WHERE ObjRace = ObjRaceNo )';
        EXECUTE IMMEDIATE insert_stmt;
        commit;
		insert_stmt := 'INSERT INTO '||layer_table_name||'  SELECT DISTINCT Layer, ''NN automatisch erstellt'' FROM '||t_object_name||' WHERE NOT EXISTS ( SELECT * FROM '||layer_table_name||' WHERE Layer = LayerNo )';
        EXECUTE IMMEDIATE insert_stmt;
        commit;
        insert_stmt := 'INSERT INTO '||object_name||'   SELECT ObjNo, Layer, ObjRace, ObjCoorX, ObjCoorY, ModType, to_date(BuildDate,''YYMMDD'') FROM '||t_object_name;
        EXECUTE IMMEDIATE insert_stmt;
        commit;
    END load_objects;
    
	/**
	 * lädt die Tabelle der Objektbezeichnungen
	 * @param object_name Name der Tabelle der Zieldatenbank der Objekte
	 * @param t_object_data_name Name der temporären Tabelle der 
	 * besonderen Objektinformationen
	 * @param t_object_geo_name Name der temporären Tabelle der Geometrieangaben
	 * der Objekte
	 * @param name_geo_table_typ_name Name des Typs der Tabelle der 
	 * Geometrieangaben der Bezeichnungen
	 */ 
    PROCEDURE load_object_names (object_name VARCHAR2, t_object_data_name VARCHAR2, t_object_geo_name VARCHAR2, name_geo_table_typ_name VARCHAR2) IS
        insert_stmt VARCHAR(400);                                   
        geo_dummy VARCHAR(40);
        TYPE GeoCursorTyp IS REF CURSOR;  -- define weak REF CURSOR type
        GeoCursor GeoCursorTyp;  -- declare cursor variable
        ObjectNo VARCHAR2(9);
        ObjectDataNo NUMBER;
        CoordinateX NUMBER(9);
        CoordinateY NUMBER(9);
        TYPE ObjDataCurTyp IS REF CURSOR;  -- define weak REF CURSOR type
        ObjDataCursor GeoCursorTyp;  -- declare cursor variable
        Race VARCHAR2(2);
    BEGIN
        geo_dummy := name_geo_table_typ_name||'()';
        insert_stmt := 'INSERT INTO '||object_name||' SELECT ObjNo, substr(Text,1,2), max(substr(Text,3)), '||geo_dummy||
    					' FROM '||t_object_data_name||' WHERE InfoRace = '||info_race_name_id||' GROUP BY ObjNo, ObjPartNo, substr(Text,1,2)';
        EXECUTE IMMEDIATE insert_stmt;
        OPEN GeoCursor FOR  -- open cursor variable
            'SELECT DISTINCT ObjNo, ObjDataNo, CoorX, CoorY FROM '||t_object_geo_name;  
        LOOP
            BEGIN
                FETCH GeoCursor INTO ObjectNo, ObjectDataNo, CoordinateX, CoordinateY;
                EXIT WHEN GeoCursor%NOTFOUND;
                OPEN ObjDataCursor FOR 
                    'SELECT substr(text,1,2) FROM '||t_object_data_name||' WHERE InfoRace = '||info_race_name_id||' AND ObjNo = '''||ObjectNo||''' AND ObjDataNo = '||ObjectDataNo;
                FETCH ObjDataCursor INTO Race;
                insert_stmt := 'INSERT INTO THE( SELECT geo FROM '||object_name||' WHERE ObjectNo = '''||ObjectNo||''' AND Type = '''||Race||''') VALUES ('||CoordinateX||', '||CoordinateY||')';
                EXECUTE IMMEDIATE insert_stmt;
            EXCEPTION
                WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE(error_name||SUBSTR(SQLERRM, 1, 100));                     
            END;
        END LOOP;
        EXCEPTION
            WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE(error_name||SUBSTR(SQLERRM, 1, 100));              
    END load_object_names;
    
	/**
	 * lädt die Tabelle der Überführungen
	 * @param t_object_data_name Name der temporären Tabelle der 
	 * besonderen Objektinformationen
	 * @param above_name Name der Tabelle der Zieldatenbank der Überführungen
	 */ 
    PROCEDURE load_above (t_object_data_name VARCHAR2, above_name VARCHAR2) IS
        TYPE AboveCursorTyp IS REF CURSOR;  -- define weak REF CURSOR type
        AboveCursor AboveCursorTyp;  -- declare cursor variable
        TopNo VARCHAR2(7);
        TopPartNo VARCHAR2(3);
        DownNo VARCHAR2(7);
        DownPartNo VARCHAR2(3);
        insert_stmt VARCHAR(400);                                   
    BEGIN
        OPEN AboveCursor FOR 
            'SELECT substr(Text,1,7) TN, substr(Text,8,3) TPN, substr(Text,11,7) DN, substr(Text,18,3) DPN FROM '||t_object_data_name||' 
    		WHERE InfoRace = '''||info_race_over_id||'''
    		UNION
    		SELECT substr(Text,11,7) TN, substr(Text,18,3) TPN, substr(Text,1,7) DN, substr(Text,8,3) DPN FROM '||t_object_data_name||' 
    		WHERE InfoRace = '''||info_race_under_id||'''';
        LOOP
            BEGIN
                FETCH AboveCursor INTO TopNo, TopPartNo, DownNo, DownPartNo;
                EXIT WHEN AboveCursor%NOTFOUND;
                insert_stmt := 'INSERT INTO '||above_name||' VALUES ('''||TopNo||''','''||TopPartNo||''','''||DownNo||''','''||DownPartNo||''')';
                EXECUTE IMMEDIATE insert_stmt;
		        commit;
            EXCEPTION
                WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE(error_above_one||TopNo||'-'||TopPartNo||' > '||DownNo||'-'||DownPartNo);                     
            END;
        END LOOP;
    EXCEPTION
        WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE(error_above_all||SUBSTR(SQLERRM, 1, 100));
    END load_above;
    
	/**
	 * lädt die Tabelle der Zuordnungen zu komplexen Objekten
	 * @param t_object_data_name Name der temporären Tabelle der 
	 * besonderen Objektinformationen
	 * @param complex_object_name Name der Tabelle der Zieldatenbank der 
	 * Zuordnungen zu komplexe Objekte
	 */ 
    PROCEDURE load_complex_object (t_object_data_name VARCHAR2, complex_object_name VARCHAR2) IS
    	TYPE ComplCursorTyp IS REF CURSOR;  -- define weak REF CURSOR type
    	ComplCursor ComplCursorTyp;  -- declare cursor variable
    	insert_stmt VARCHAR(400);                                   
    	big VARCHAR2(7);
		small VARCHAR2(7);
	BEGIN
        OPEN ComplCursor FOR 
    		'SELECT ObjNo BN, substr(Text,1,7) SN FROM '||t_object_data_name||' 
    		WHERE InfoRace = '''||info_race_big_id||'''
    		UNION
    		SELECT substr(Text,1,7) BN, ObjNo SN FROM  '||t_object_data_name||'  
    		WHERE InfoRace = '''||info_race_small_id||'''';
        LOOP
            BEGIN
	    		FETCH ComplCursor INTO big, small;
				EXIT WHEN ComplCursor%NOTFOUND;
				insert_stmt := 'INSERT INTO '||complex_object_name||' VALUES ('''||big||''','''||small||''')';
		    	EXECUTE IMMEDIATE insert_stmt;
				commit;
			EXCEPTION
				WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE(error_complex||big||'<-'||small||SUBSTR(SQLERRM, 1, 100));
 			END;
		END LOOP;
    EXCEPTION
        WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE(error_complex||SUBSTR(SQLERRM, 1, 100));
    END load_complex_object;
    
    /**
	 * erstellt eine Zeichenkette, die eine Linie beschreibt
	 * @param t_geo_name Name der temporären Tabelle mit den durch den 
	 * Linienverfolgungsalgorithmus aufbereiteten Daten
	 * @param t_line_data_name Name der temporären Tabelle der Lageparameter
	 * der Linien
	 * @param ObjPartNo Nummer des beschriebenden Objektteils
	 * return liefert Zeichenkette, die die Linie der übergebenen Objektteilummer 
	 * beschreibt und deren aufbereitete Daten in der temporären Tabelle standen. 
	 * In der Zeichenkette stehen die Informationen für die beiden Spalten 
	 * SDO_ELEM_INFO und SDO_ORDINATE
	 */
	FUNCTION describe_line (t_geo_name VARCHAR2, t_line_data_name VARCHAR2, ObjPartNo VARCHAR2) RETURN VARCHAR2 IS
        TYPE LineCursorTyp IS REF CURSOR;  -- define weak REF CURSOR type
        LineCur LineCursorTyp;  -- declare cursor variable
        LineNo NUMBER;
        BegX NUMBER(9);
        BegY NUMBER(9);
        EndX NUMBER(9);
        EndY NUMBER(9);
        CoordX NUMBER(9);
        CoordY NUMBER(9);
        Race VARCHAR2(2);
        Direction NUMBER(1);
        TYPE DataCursorTyp IS REF CURSOR;  -- define weak REF CURSOR type
        DataCur DataCursorTyp;  -- declare cursor variable
    BEGIN
		insert_clear;
		insert_append('MDSYS.SDO_ORDINATE_ARRAY(');
        OPEN LineCur FOR 
            'SELECT LineNo, BegX, BegY, EndX, EndY, Race, Direction FROM '||t_geo_name||' 
    		WHERE ObjPartNo = '''||ObjPartNo||'''
    		ORDER BY MyNo';
        LOOP
            FETCH LineCur INTO LineNo, BegX, BegY, EndX, EndY, Race, Direction;
            EXIT WHEN LineCur%NOTFOUND;
            IF Direction = NormalDirection THEN
                insert_append(BegX||','||BegY||',');
                IF Race = PolygonzugID THEN
                    OPEN DataCur FOR 
                        'SELECT CoordX, CoordY FROM '||t_line_data_name||'
    					WHERE LineNo = '''||LineNo||'''
    					ORDER BY LineDataNo';
                    LOOP
                        FETCH DataCur INTO CoordX, CoordY;
                        EXIT WHEN DataCur%NOTFOUND;
                        insert_append(CoordX||','||CoordY||',');
                    END LOOP;
                END IF;
            ELSE 
                insert_append(EndX||','||EndY||',');
                EndX := BegX;
                EndY := BegY;
                IF Race = PolygonzugID THEN
                    OPEN DataCur FOR 
                        'SELECT CoordX, CoordY FROM '||t_line_data_name||'
    					WHERE LineNo = '''||LineNo||'''
    					ORDER BY LineDataNo DESC';
                    LOOP
                        FETCH DataCur INTO CoordX, CoordY;
                        EXIT WHEN DataCur%NOTFOUND;
                        insert_append(CoordX||','||CoordY||',');
                    END LOOP;
                END IF;
            END IF;
        END LOOP;
		insert_append(EndX||','||EndY||')');
        RETURN 'MDSYS.SDO_ELEM_INFO_ARRAY(1,2,1),';
    EXCEPTION
        WHEN OTHERS THEN
            raise_application_error(-20040,error_line_describe||SUBSTR(SQLERRM, 1, 100));
    END;
    
    /**
	 * gibt die temporäre Tabelle aus. Wird nicht benutzt, kann aber 
	 * Kontrolausgaben dienen
	 */
	PROCEDURE show_t_geo (t_geo_name VARCHAR2) IS
        TYPE TestCursorTyp IS REF CURSOR;  -- define weak REF CURSOR type
        TestCur TestCursorTyp;  -- declare cursor variable
        TLineNo NUMBER;
        TObjPartNo VARCHAR2(3);
        TBegX NUMBER(9);
        TBegY NUMBER(9);
        TEndX NUMBER(9);
        TEndY NUMBER(9);
        TRace VARCHAR2(2);
        TMyNo NUMBER;
        TPolygonNo NUMBER;
        TDir NUMBER(1);
    BEGIN
        DBMS_OUTPUT.PUT_LINE('Die temporaere Tabelle sieht jetzt so aus: ');
        OPEN TestCur FOR
            'SELECT * FROM '||t_geo_name||'
    ORDER BY ObjPartNo, PolygonNo, MyNo';       
        LOOP
            FETCH TestCur INTO TLineNo, TObjPartNo, TBegX, TBegY, TEndX, TEndY, TRace, TDir, TMyNo, TPolygonNo;
            EXIT WHEN TestCur%NOTFOUND;
            DBMS_OUTPUT.PUT_LINE('TEST'||TLineNo||'<>'||TObjPartNo||'<>'||TBegX||'<>'||TBegY||'<>'||TEndX||'<>'||TEndY||'<>'||TRace||'<>'||TDir||'<>'||TMyNo||'<>'||TPolygonNo);
        END LOOP;
    EXCEPTION
        WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE('Fehler bei einer Testausgabe von t_geo');
    END;
    
    /**
	 * schreibt in eine globale Zeichenkette die Information der Spalte SDO_ORINATE
	 * eines flächeförmigen Objektteils. Die Information der Spalte SDO_ELEM_INFO
	 * werden der R"uckgabewert.
	 * @param t_geo_name Name der temporären Tabelle mit den durch den 
	 * Linienverfolgungsalgorithmus aufbereiteten Daten
	 * @param t_line_data_name Name der temporären Tabelle der Lageparameter
	 * der Linien
	 * @param ObjPartNo Nummer des beschriebenden Objektteils
	 * return liefert Zeichenkette, die Information der Spalte SDO_ELEM_INFO darstellt
	 */
    FUNCTION describe_area (t_geo_name VARCHAR2, t_line_data_name VARCHAR2, ObjPartNo VARCHAR2) RETURN VARCHAR2 IS
        TYPE LineCursorTyp IS REF CURSOR;  -- define weak REF CURSOR type
        LineCur LineCursorTyp;  -- declare cursor variable
        LineNo NUMBER;
        BegX NUMBER(9);
        BegY NUMBER(9);
        EndX NUMBER(9);
        EndY NUMBER(9);
        CoordX NUMBER(9);
        CoordY NUMBER(9);
        Race VARCHAR2(2);
        Direction NUMBER(1);
        PolygonNo VARCHAR2(3);
        infos VARCHAR2(150) := 'MDSYS.SDO_ELEM_INFO_ARRAY(';
        Cnt NUMBER := 1;
        StartCnt NUMBER := 1;
        LastNo VARCHAR2(3) := NULL;
        TYPE DataCursorTyp IS REF CURSOR;  -- define weak REF CURSOR type
        DataCur DataCursorTyp;  -- declare cursor variable
        IsNewPolygon BOOLEAN := FALSE;
		Insel VARCHAR2(25) := '';
    BEGIN
		insert_clear;
		insert_append('MDSYS.SDO_ORDINATE_ARRAY(');
        OPEN LineCur FOR 
            'SELECT LineNo, BegX, BegY, EndX, EndY, Race, Direction, PolygonNo FROM '||t_geo_name||' 
		    WHERE ObjPartNo = '''||ObjPartNo||'''
    		ORDER BY PolygonNo, MyNo';
        LOOP
            FETCH LineCur INTO LineNo, BegX, BegY, EndX, EndY, Race, Direction, PolygonNo;
            EXIT WHEN LineCur%NOTFOUND;
            IsNewPolygon := LastNo IS NOT NULL AND PolygonNo <> LastNo;
            IF IsNewPolygon THEN
                infos := infos||StartCnt||',3,1,';
				Cnt := Cnt + 2;
				insert_append(Insel);
                StartCnt := Cnt;
            END IF;
            LastNo := PolygonNo;
            Cnt := Cnt + 2;
            IF Direction = NormalDirection THEN
				insert_append(BegX||','||BegY||','); 
                IF Race = PolygonzugID THEN
                    OPEN DataCur FOR 
                        'SELECT CoordX, CoordY FROM '||t_line_data_name||'
					    WHERE LineNo = '''||LineNo||'''
    					ORDER BY LineDataNo';
                    LOOP
                        FETCH DataCur INTO CoordX, CoordY;
                        EXIT WHEN DataCur%NOTFOUND;
						insert_append(CoordX||','||CoordY||',');
                        Cnt := Cnt + 2;
                    END LOOP;
                END IF;
            ELSE 
                insert_append(EndX||','||EndY||',');
				EndX := BegX;
                EndY := BegY;
                IF Race = PolygonzugID THEN
                    OPEN DataCur FOR 
                        'SELECT CoordX, CoordY FROM '||t_line_data_name||'
    					WHERE LineNo = '''||LineNo||'''
    					ORDER BY LineDataNo DESC';
                    LOOP
                        FETCH DataCur INTO CoordX, CoordY;
                        EXIT WHEN DataCur%NOTFOUND;
 						insert_append(CoordX||','||CoordY||',');
                        Cnt := Cnt + 2;
                    END LOOP;
                END IF;
            END IF;
			insel := EndX||','||EndY||',';
        END LOOP;

        infos := infos||StartCnt||',3,1)';
		insert_append(EndX||','||EndY||')');
		RETURN infos;
    EXCEPTION
        WHEN OTHERS THEN
            raise_application_error(-20055,error_bad_area_describe||SUBSTR(SQLERRM, 1, 100));
    END;
    
    /**
	 * schreibt in eine globale Zeichenkette die Information der Spalte SDO_ORINATE
	 * eines flächeförmigen Objektteils. Die Information der Spalte SDO_ELEM_INFO
	 * werden der R"uckgabewert.
	 * @param t_geo_name Name der temporären Tabelle mit den durch den 
	 * Linienverfolgungsalgorithmus aufbereiteten Daten
	 * @param t_line_data_name Name der temporären Tabelle der Lageparameter
	 * der Linien
	 * @param ObjPartNo Nummer des beschriebenden Objektteils
	 * @param bad_geometries_name Name der TAbelle der fehlerhaften Objektheometrien
	 * @param ObjNo Nummer des beschriebenden Objekts
	 * return liefert Zeichenkette, die Information der Spalte SDO_ELEM_INFO darstellt
	 */
    FUNCTION describe_bad_area (t_geo_name VARCHAR2, t_line_data_name VARCHAR2, ObjPartNo VARCHAR2, ObjNo VARCHAR2, bad_geometries_name VARCHAR2) RETURN VARCHAR2 IS
		insert_stmt VARCHAR2(300);
        TYPE LineCursorTyp IS REF CURSOR;  -- define weak REF CURSOR type
        LineCur LineCursorTyp;  -- declare cursor variable
        LineNo NUMBER;
        BegX NUMBER(9);
        BegY NUMBER(9);
        EndX NUMBER(9);
        EndY NUMBER(9);
        CoordX NUMBER(9);
        CoordY NUMBER(9);
        Race VARCHAR2(2);
        Direction NUMBER(1);
        PolygonNo VARCHAR2(3);
        infos VARCHAR2(150) := 'MDSYS.SDO_ELEM_INFO_ARRAY(';
        Cnt NUMBER := 1;
		PCnt NUMBER := 0;
        StartCnt NUMBER := 1;
        LastNo VARCHAR2(3) := NULL;
        TYPE DataCursorTyp IS REF CURSOR;  -- define weak REF CURSOR type
        DataCur DataCursorTyp;  -- declare cursor variable
        IsNewPolygon BOOLEAN := FALSE;
		Insel VARCHAR2(25) := '';
		InselX NUMBER(9);
		InselY NUMBER(9);
    BEGIN
		insert_clear;
		insert_append('MDSYS.SDO_ORDINATE_ARRAY(');
        OPEN LineCur FOR 
            'SELECT LineNo, BegX, BegY, EndX, EndY, Race, Direction, PolygonNo FROM '||t_geo_name||' 
		    WHERE ObjPartNo = '''||ObjPartNo||'''
    		ORDER BY PolygonNo, MyNo';
        LOOP
            FETCH LineCur INTO LineNo, BegX, BegY, EndX, EndY, Race, Direction, PolygonNo;
            EXIT WHEN LineCur%NOTFOUND;
            IsNewPolygon := LastNo IS NOT NULL AND PolygonNo <> LastNo;
            IF IsNewPolygon THEN
                infos := infos||StartCnt||',3,1,';
				Cnt := Cnt + 2;
				insert_append(Insel);
				insert_stmt := 'INSERT INTO '||bad_geometries_name||' VALUES ('''||ObjNo||''','''||ObjPartNo||''','||InselX||','||InselY||','||PCnt||','||PolygonNo||')';
				EXECUTE IMMEDIATE insert_stmt;
                PCnt := PCnt + 1;
				StartCnt := Cnt;
            END IF;
            LastNo := PolygonNo;
            Cnt := Cnt + 2;
            IF Direction = NormalDirection THEN
				insert_append(BegX||','||BegY||','); 
				insert_stmt := 'INSERT INTO '||bad_geometries_name||' VALUES ('''||ObjNo||''','''||ObjPartNo||''','||BegX||','||BegY||','||PCnt||','||PolygonNo||')';
				PCnt := PCnt + 1;
				EXECUTE IMMEDIATE insert_stmt;
                IF Race = PolygonzugID THEN
                    OPEN DataCur FOR 
                        'SELECT CoordX, CoordY FROM '||t_line_data_name||'
					    WHERE LineNo = '''||LineNo||'''
    					ORDER BY LineDataNo';
                    LOOP
                        FETCH DataCur INTO CoordX, CoordY;
                        EXIT WHEN DataCur%NOTFOUND;
						insert_stmt := 'INSERT INTO '||bad_geometries_name||' VALUES ('''||ObjNo||''','''||ObjPartNo||''','||CoordX||','||CoordY||','||PCnt||','||PolygonNo||')';
						EXECUTE IMMEDIATE insert_stmt;
        				PCnt := PCnt + 1;
		            END LOOP;
                END IF;
            ELSE 
                insert_append(EndX||','||EndY||',');
				insert_stmt := 'INSERT INTO '||bad_geometries_name||' VALUES ('''||ObjNo||''','''||ObjPartNo||''','||EndX||','||EndY||','||PCnt||','||PolygonNo||')';
				EXECUTE IMMEDIATE insert_stmt;
				PCnt := PCnt + 1;
				EndX := BegX;
                EndY := BegY;
                IF Race = PolygonzugID THEN
                    OPEN DataCur FOR 
                        'SELECT CoordX, CoordY FROM '||t_line_data_name||'
    					WHERE LineNo = '''||LineNo||'''
    					ORDER BY LineDataNo DESC';
                    LOOP
                        FETCH DataCur INTO CoordX, CoordY;
                        EXIT WHEN DataCur%NOTFOUND;
						insert_stmt := 'INSERT INTO '||bad_geometries_name||' VALUES ('''||ObjNo||''','''||ObjPartNo||''','||CoordX||','||CoordY||','||PCnt||','||PolygonNo||')';
						EXECUTE IMMEDIATE insert_stmt;
						PCnt := PCnt + 1;
                    END LOOP;
                END IF;
            END IF;
			insel := EndX||','||EndY||',';
			InselX := EndX;
			InselY := EndY;
        END LOOP;

        infos := infos||StartCnt||',3,1)';
		insert_append(EndX||','||EndY||')');
		insert_stmt := 'INSERT INTO '||bad_geometries_name||' VALUES ('''||ObjNo||''','''||ObjPartNo||''','||EndX||','||EndY||','||PCnt||','||PolygonNo||')';
		EXECUTE IMMEDIATE insert_stmt;
		PCnt := PCnt + 1;
		RETURN infos;
    EXCEPTION
        WHEN OTHERS THEN
            raise_application_error(-20050,error_area_describe||SUBSTR(SQLERRM, 1, 100));
    END;
    
    /**
	 * Linienverfolgungsalgorithmus
	 * @param t_geo_name Name der temporären Tabelle, die zu sortieren ist
	 * @param PolygonCount Nummer, die in der Polygonnumerierungsspalte einzutragen ist
	 */
	PROCEDURE update_t_geo (t_geo_name VARCHAR2) IS
        TYPE LineCursorTyp IS REF CURSOR;  -- define weak REF CURSOR type
        LineCur LineCursorTyp;  -- declare cursor variable
        TYPE DirCursorTyp IS REF CURSOR;  -- define weak REF CURSOR type
        DirCur DirCursorTyp;  -- declare cursor variable
        StartCoordinateX NUMBER(9);
        StartCoordinateY NUMBER(9);
        NextCoordinateX NUMBER(9);
        NextCoordinateY NUMBER(9);
        EndCoordinateX NUMBER(9);
        EndCoordinateY NUMBER(9);
        MyCount NUMBER := MyCountStart;
        LineNo NUMBER;
        ObjPartNo VARCHAR2(3);
        PolygonCount NUMBER := MyPolygonStart;
		update_stmt VARCHAR2(200);
    BEGIN
        LOOP
            BEGIN
                MyCount := MyCountStart;
                OPEN LineCur FOR
                    'SELECT LineNo, ObjPartNo, BegX, BegY, EndX, EndY FROM '||t_geo_name||' WHERE MyNo IS NULL
    				ORDER BY ObjPartNo, BegX+EndX - ABS(BegX - EndX)';
                FETCH LineCur INTO LineNo, ObjPartNo, StartCoordinateX, StartCoordinateY, NextCoordinateX, NextCoordinateY;
                EXIT WHEN LineCur%NOTFOUND;
                
                LOOP
                    BEGIN
                        CLOSE LineCur;
                        update_stmt := 'UPDATE '||t_geo_name||'  
    									SET MyNo = '||MyCount||'
    									WHERE LineNo = '''||LineNo||'''
    									AND ObjPartNo = '''||ObjPartNo||'''';
                        EXECUTE IMMEDIATE update_stmt;
                        update_stmt := 'UPDATE '||t_geo_name||'  
    									SET PolygonNo = '||PolygonCount||'
    									WHERE LineNo = '''||LineNo||'''
    									AND ObjPartNo = '''||ObjPartNo||'''';
                        EXECUTE IMMEDIATE update_stmt;
                        MyCount := MyCount + 1;
                        OPEN LineCur FOR
                            'SELECT LineNo, BegX NextX, BegY NextY FROM '||t_geo_name||' 
    						WHERE MyNo IS NULL
    						AND ObjPartNo = '''||ObjPartNo||'''
    						AND EndX = '||NextCoordinateX||'
    						AND EndY = '||NextCoordinateY||'
    						UNION
    						SELECT LineNo, EndX NextX, EndY NextY FROM '||t_geo_name||' 
    						WHERE MyNo IS NULL
    						AND ObjPartNo = '''||ObjPartNo||'''
    						AND BegX = '||NextCoordinateX||'
    						AND BegY = '||NextCoordinateY;
                        FETCH LineCur INTO LineNo, NextCoordinateX, NextCoordinateY;
                        EXIT WHEN LineCur%NOTFOUND;
                        OPEN DirCur FOR 
                            'SELECT BegX, BegY FROM '||t_geo_name||'
    						WHERE LineNo = '''||LineNo||'''
    						AND ObjPartNo = '''||ObjPartNo||'''';
                        FETCH DirCur INTO EndCoordinateX, EndCoordinateY;
                        IF (EndCoordinateX = NextCoordinateX AND EndCoordinateY = NextCoordinateY) THEN
                            update_stmt := 'UPDATE '||t_geo_name||'  
    						SET Direction = '||OtherDirection||'
    						WHERE LineNo = '''||LineNo||'''
    						AND ObjPartNo = '''||ObjPartNo||'''';
                            EXECUTE IMMEDIATE update_stmt;
                        END IF;
                    EXCEPTION
                        WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE(error_line_find||SUBSTR(SQLERRM, 1, 100));
                    END;
                END LOOP;
                NextCoordinateX := StartCoordinateX;
                NextCoordinateY := StartCoordinateY;
                MyCount := MyCountStart - 1;
                LOOP
                    BEGIN
                        OPEN LineCur FOR
                            'SELECT LineNo, BegX NextX, BegY NextY FROM '||t_geo_name||' 
    						WHERE MyNo IS NULL
    						AND ObjPartNo = '''||ObjPartNo||'''
    						AND EndX = '||NextCoordinateX||'
    						AND EndY = '||NextCoordinateY||'
    						UNION
    						SELECT LineNo, EndX NextX, EndY NextY FROM '||t_geo_name||' 
    						WHERE MyNo IS NULL
    						AND ObjPartNo = '''||ObjPartNo||'''
    						AND BegX = '||NextCoordinateX||'
    						AND BegY = '||NextCoordinateY;
                        FETCH LineCur INTO LineNo, NextCoordinateX, NextCoordinateY;
                        EXIT WHEN LineCur%NOTFOUND;
                        CLOSE LineCur;
                        update_stmt := 'UPDATE '||t_geo_name||'  
    						SET MyNo = '||MyCount||'
    						WHERE LineNo = '''||LineNo||'''
    						AND ObjPartNo = '''||ObjPartNo||'''';
                        EXECUTE IMMEDIATE update_stmt;
                        update_stmt := 'UPDATE '||t_geo_name||'  
    						SET PolygonNo = '||PolygonCount||'
    						WHERE LineNo = '''||LineNo||'''
    						AND ObjPartNo = '''||ObjPartNo||'''';
                        EXECUTE IMMEDIATE update_stmt;
                        MyCount := MyCount - 1;
                        OPEN DirCUr FOR 
                            'SELECT EndX, EndY FROM '||t_geo_name||'
    						WHERE LineNo = '''||LineNo||'''
    						AND ObjPartNo = '''||ObjPartNo||'''';
                        FETCH DirCur INTO StartCoordinateX, StartCoordinateY;
                        IF (StartCoordinateX = NextCoordinateX AND StartCoordinateX = NextCoordinateX) THEN
                            update_stmt := 'UPDATE '||t_geo_name||'  
    						SET Direction = '||OtherDirection||'
    						WHERE LineNo = '''||LineNo||'''
    						AND ObjPartNo = '''||ObjPartNo||'''';
                            EXECUTE IMMEDIATE update_stmt;
                        END IF;
                    EXCEPTION
                        WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE('Fehler beim Linienverfolgen rueckwaerts:'||SQLCODE||'#'||SUBSTR(SQLERRM, 1, 100));
                    END;
                END LOOP;
				PolygonCount := PolygonCount + 1;
            EXCEPTION
                WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE('Probleme bei update_t_geo: Tabelle weg');
            END;
        END LOOP;
    EXCEPTION
        WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE('Fehler beim geo_cur: '||SUBSTR(SQLERRM, 1, 100));
    END;
        
	/**
	 * lädt die Tabelle der Gemetrieangaben
	 * @param t_object_name Name der temporären Tabelle der Objekte
	 * @param t_line_name Name der temporären Tabelle der Linien
	 * @param t_line_function_name Name der temporären Tabelle der Linienfunktionen
	 * @param t_line_param_name Name der temporären Tabelle der Fachparameter 
	 * der Linien
	 * @param t_line_data_name Name der temporären Tabelle der Lageparameter 
	 * der Linien
	 * @param object_gemotry_name Name der Tabelle der Zieldatenbank der
	 * Objektgeometrien
	 * @t_geo_name Name der tempoären Tabelle für den Linienverfolgungsalgorithmus
	 */ 
   PROCEDURE load_object_geometry (t_object_name VARCHAR2, t_line_name VARCHAR2, t_line_function_name VARCHAR2, t_line_param_name VARCHAR2, t_line_data_name VARCHAR2, object_gemotry_name VARCHAR2, t_geo_name VARCHAR2) IS
        insert_stmt VARCHAR2(4000);                                 
        delete_stmt VARCHAR2(100) := 'DELETE FROM '||t_geo_name;
        TYPE ObjCursorTyp IS REF CURSOR;  -- define weak REF CURSOR type
        ObjCur ObjCursorTyp;  -- declare cursor variable
        TYPE ObjPartCursorTyp IS REF CURSOR;  -- define weak REF CURSOR type
        ObjPartCur ObjPartCursorTyp;  -- declare cursor variable
        ObjectNo VARCHAR2(9);
        ObjPartNo VARCHAR2(3);
        ObjRace VARCHAR2(4);
        ObjLayer VARCHAR2(3);
        CoordinateX NUMBER(9);
        CoordinateY NUMBER(9);
        area_file UTL_FILE.FILE_TYPE;
		area_tmp_file UTL_FILE.FILE_TYPE;
		line_str VARCHAR2(4000);
    BEGIN
	-- punktförmige Objekte
        OPEN ObjCur FOR  -- open cursor variable
            'SELECT DISTINCT ObjNo, ObjCoorX, ObjCoorY FROM '||t_object_name||' WHERE ObjType = ''P'''; 
        LOOP
            BEGIN
                FETCH ObjCur INTO ObjectNo, CoordinateX, CoordinateY;
                EXIT WHEN ObjCur%NOTFOUND;
                insert_stmt := 'INSERT INTO '||object_gemotry_name||' VALUES ('''||ObjectNo||''', '''||first_object_part_str||''', MDSYS.SDO_GEOMETRY(1, NULL, MDSYS.SDO_POINT_TYPE('||CoordinateX||', '||CoordinateY||', 0), NULL, NULL))';
                EXECUTE IMMEDIATE insert_stmt;
            	commit;
			EXCEPTION
                WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE(error_points||SQLCODE||'#'||SUBSTR(SQLERRM, 1, 100));                       
            END;
        END LOOP;
        CLOSE ObjCur;

    -- linienförmige Objekte
	    OPEN ObjCur FOR  -- open cursor variable
            'SELECT DISTINCT ObjNo, ObjCoorX, ObjCoorY, Layer, ObjRace FROM '||t_object_name||' WHERE ObjType = ''L'''; 
        LOOP
            BEGIN
                FETCH ObjCur INTO ObjectNo, CoordinateX, CoordinateY, ObjLayer, ObjRace;
                EXIT WHEN ObjCur%NOTFOUND;
                insert_stmt := 'INSERT INTO '||t_geo_name||' 
    							SELECT F.LineNo, F.A,  L.CoordX, L.Coordy, L.EndPointX, L.EndPointY, L.Geometry, '||NormalDirection||', NULL, NULL FROM '||t_line_name||' L, (
    							SELECT LineNo, A FROM (
   							 	SELECT LineNo, ObjPartNoL A FROM '||t_line_function_name||'
    							WHERE ObjNoL = '''||ObjectNo||'''
    							UNION
    							SELECT LineNo, ObjPartNoR A FROM '||t_line_function_name||'
    							WHERE ObjNoR = '''||ObjectNo||''' ) ) F
    							WHERE L.LineNo = F.LineNo';
                EXECUTE IMMEDIATE insert_stmt;
    
                update_t_geo(t_geo_name);
                OPEN ObjPartCur FOR 
                    'SELECT DISTINCT ObjPartNo FROM '||t_geo_name;
                LOOP    
                    BEGIN
                        FETCH ObjPartCur INTO ObjPartNo;
                        EXIT WHEN ObjPartCur%NOTFOUND;
                        insert_stmt := 'INSERT INTO '||object_gemotry_name||' VALUES ('''||ObjectNo||''', '''||ObjPartNo||''', MDSYS.SDO_GEOMETRY(2, NULL, NULL, '||describe_line(t_geo_name, t_line_data_name, ObjPartNo);                     
						EXECUTE IMMEDIATE insert_stmt||insert_stmt0||insert_stmt1||insert_stmt2||insert_stmt3||insert_stmt4||insert_stmt5||insert_stmt6||insert_stmt7||insert_stmt8||insert_stmt9||'))';
                    EXCEPTION
                        WHEN OTHERS THEN
                            DBMS_OUTPUT.PUT_LINE(error_line_object_part||ObjectNo||'-'||ObjPartNo||': '||SUBSTR(SQLERRM, 1, 100));                     
                    END;
                END LOOP;
                EXECUTE IMMEDIATE delete_stmt;
            	commit;
            EXCEPTION
                WHEN OTHERS THEN
                    DBMS_OUTPUT.PUT_LINE(error_line_object||ObjectNo||':'||SUBSTR(SQLERRM, 1, 100));                       
                    EXECUTE IMMEDIATE delete_stmt;
            END;
        END LOOP;
        CLOSE ObjCur;
    -- flächenförmige Objekte   
		OPEN ObjCur FOR  -- open cursor variable
            'SELECT DISTINCT ObjNo, ObjCoorX, ObjCoorY, Layer, ObjRace FROM '||t_object_name||' WHERE ObjType = ''F'''; 
        LOOP
            BEGIN
                FETCH ObjCur INTO ObjectNo, CoordinateX, CoordinateY, ObjLayer, ObjRace;
                EXIT WHEN ObjCur%NOTFOUND;
                insert_stmt := 'INSERT INTO '||t_geo_name||' 
    							SELECT F.LineNo, F.A,  L.CoordX, L.Coordy, L.EndPointX, L.EndPointY, L.Geometry, '||NormalDirection||', NULL, NULL FROM '||t_line_name||' L, (
    							SELECT LineNo, A FROM (
    							SELECT LineNo, ObjPartNoL A FROM '||t_line_function_name||'
    							WHERE ObjNoL = '''||ObjectNo||'''
								AND LineRace <> '''||ConnectionRace||'''
    							UNION
    							SELECT LineNo, ObjPartNoR A FROM '||t_line_function_name||'
    							WHERE ObjNoR = '''||ObjectNo||'''
								AND LineRace <> '''||ConnectionRace||''' ) ) F
    							WHERE L.LineNo = F.LineNo';
                EXECUTE IMMEDIATE insert_stmt;
    
                update_t_geo(t_geo_name);
                OPEN ObjPartCur FOR 
                    'SELECT DISTINCT ObjPartNo FROM '||t_geo_name;
                LOOP    
                    BEGIN
                        FETCH ObjPartCur INTO ObjPartNo;
                        EXIT WHEN ObjPartCur%NOTFOUND;
                        insert_stmt := 'INSERT INTO '||object_gemotry_name||' VALUES ('''||ObjectNo||''', '''||ObjPartNo||''', MDSYS.SDO_GEOMETRY(3, NULL, NULL, '||describe_area(t_geo_name, t_line_data_name, ObjPartNo)||',';
                       EXECUTE IMMEDIATE insert_stmt||insert_stmt0||insert_stmt1||insert_stmt2||insert_stmt3||insert_stmt4||insert_stmt5||insert_stmt6||insert_stmt7||insert_stmt8||insert_stmt9||'))';
                    EXCEPTION
                        WHEN OTHERS THEN
                            DBMS_OUTPUT.PUT_LINE(warn_area_object_part||ObjectNo||'-'||ObjPartNo);                     
							BEGIN
		                        insert_stmt := 'INSERT INTO '||object_gemotry_name||' VALUES ('''||ObjectNo||''', '''||ObjPartNo||''', MDSYS.SDO_GEOMETRY(3, NULL, NULL, '||describe_bad_area(t_geo_name, t_line_data_name, ObjPartNo, ObjectNo, bad_geometries_tn)||',';
		                        EXECUTE IMMEDIATE insert_stmt||insert_stmt0||insert_stmt1||insert_stmt2||insert_stmt3||insert_stmt4||insert_stmt5||insert_stmt6||insert_stmt7||insert_stmt8||insert_stmt9||'))';
							EXCEPTION
		                        WHEN OTHERS THEN
									DBMS_OUTPUT.PUT_LINE(warn_bad_area_object_part||ObjectNo||'-'||ObjPartNo);
									BEGIN
										insert_stmt := 'INSERT INTO '||object_gemotry_name||' VALUES ('''||ObjectNo||''', '''||ObjPartNo||''', NULL)';
										EXECUTE IMMEDIATE insert_stmt;
        		                    EXCEPTION
										WHEN OTHERS THEN
											DBMS_OUTPUT.PUT_LINE(error_area_object_part||ObjectNo||'-'||ObjPartNo||': '||SUBSTR(SQLERRM, 1, 100));                     
									END;
							END;
                    END;
                END LOOP;
                EXECUTE IMMEDIATE delete_stmt;
            	commit;
            EXCEPTION
                WHEN OTHERS THEN
                    DBMS_OUTPUT.PUT_LINE(error_area_object||ObjectNo||': '||SUBSTR(SQLERRM, 1, 100));                       
            END;
        END LOOP;
        CLOSE ObjCur;
        EXCEPTION
            WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE(error_geometries||SUBSTR(SQLERRM, 1, 100));               
    END load_object_geometry;
    
	/**
	 * lädt die Tabelle der Attribute
	 * @param t_attribute Name der temporären Tabelle der Attribute
	 * @param attribute_name Name der Tabelle der Zieldatenbank der Attribute
	 * @param attribute_type_name Name der Formattabelle der Attributtypen
	 */ 
    PROCEDURE load_attribute (t_attribute_name VARCHAR2, attribute_name VARCHAR2, attribute_type_name VARCHAR2) IS
        TYPE AttCursorTyp IS REF CURSOR;  -- define weak REF CURSOR type
        AttCursor AttCursorTyp;  -- declare cursor variable
        ObjectNo VARCHAR2(7);
        ObjectPartNo VARCHAR2(3);
        AttType VARCHAR2(4);
        AttValue VARCHAR2(7);
        insert_stmt VARCHAR(400);                                   
		insert_att_stmt VARCHAR(400);
    BEGIN
		OPEN AttCursor FOR 
            'SELECT ObjNo, ObjPartNo, Type, Value FROM '||t_attribute_name;
        LOOP
            BEGIN
                FETCH AttCursor INTO ObjectNo, ObjectPartNo, AttType, AttValue;
                EXIT WHEN AttCursor%NOTFOUND;
                insert_stmt := 'INSERT INTO '||attribute_name||' VALUES ('''||ObjectNo||''','''||ObjectPartNo||''','''||AttType||''','''||AttValue||''')';
                EXECUTE IMMEDIATE insert_stmt;
            	commit;
            EXCEPTION
                WHEN OTHERS THEN 
					insert_att_stmt := 'INSERT INTO '||attribute_type_name||' VALUES ('||AttType||', ''NN automatisch erstellt'')';
					BEGIN
						EXECUTE IMMEDIATE insert_att_stmt;
						EXECUTE IMMEDIATE insert_stmt;
					EXCEPTION 
						WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE(error_att_one||ObjectNo||'-'||ObjectPartNo||' <- '||AttType||':'||AttValue||SUBSTR(SQLERRM, 1, 100));                     
					END;
			END;
        END LOOP;
    EXCEPTION
        WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE(error_att_all||SUBSTR(SQLERRM, 1, 100));
    END load_attribute; 
    
	/**
	 * erzeugt und lädt die eine Zieldatenbank
	 * @param t_index der Index der temporären Tabellennamen
	 */
    PROCEDURE create_db (t_index VARCHAR2) IS
    BEGIN
        my_index := create_all;
        IF my_index = '-1' THEN 
            my_index := '';
        END IF;
        DBMS_OUTPUT.PUT_LINE('Nun die Objekte..............................');
        load_objects(t_object_tn||t_index, layer_tn, object_race_tn, object_tn||my_index);
        DBMS_OUTPUT.PUT_LINE('Nun die Objektnamen..............................');
        load_object_names(object_name_tn||my_index, t_object_data_tn||t_index, t_object_geo_tn||t_index, name_geo_table_typ_tn||t_index);
        DBMS_OUTPUT.PUT_LINE('Nun die Objektgeometrien..............................');
        load_object_geometry(t_object_tn||t_index, t_line_tn||t_index, t_line_function_tn||t_index, t_line_param_tn||t_index, t_line_data_tn||t_index, object_geometry_tn||my_index, t_geo_tn||my_index);       DBMS_OUTPUT.PUT_LINE('Nun die komplexenObjekte..............................');
        load_complex_object(t_object_data_tn||t_index, complex_object_tn||my_index);
        DBMS_OUTPUT.PUT_LINE('Nun die Ueberfuehrungen..............................');
        load_above(t_object_data_tn||t_index, above_tn||my_index);
        DBMS_OUTPUT.PUT_LINE('Nun die Attribute..............................');
        load_attribute(t_attribute_tn||t_index, attribute_tn||my_index, attribute_types_tn);
    END create_db;
    
END fad;
/
