Universität Hannover Fachgebiet Datenbanksysteme Institut für Informationssysteme Fachbereich Informatik Studienarbeit im Studiengang Mathematik mit Studienrichtung Informatik bei Prof. Dr. Lipeck Betreuer: Sascha Klopp Implementierung einer graphischen Benutzerschnittstelle für SQL-Anfragen an eine Datenbank als Java-Applet 10. Oktober 2003 Mathis Dirksen-Thedens Matr.-Nr. 2037068 INHALTSVERZEICHNIS 1 Inhaltsverzeichnis 1 Einleitung 1.1 Aufgabenstellung . . . . . . 1.2 Überblick über diese Arbeit 1.3 Anwendungsszenario . . . . 1.4 Vorbereitungen . . . . . . . . . . . 2 2 3 3 3 2 Anforderungen 2.1 Funktionalität . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.2 Architektur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.3 GUI-Design und Intuitivität . . . . . . . . . . . . . . . . . . . . . 5 5 6 6 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3 Realisierung 3.1 Prinzip eines Applets . . . . . . . . . . . . . . . . 3.2 Prinzip von SQuiggLe . . . . . . . . . . . . . . . 3.3 Der DESCRIBE Befehl . . . . . . . . . . . . . . . 3.4 Der EXPLAIN PLAN Befehl . . . . . . . . . . . . 3.5 Tests . . . . . . . . . . . . . . . . . . . . . . . . . 3.6 Installation des Applets auf einem Server . . . . . 3.7 Weitere Anwendungsmöglichkeiten für RMI-JDBC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8 8 8 10 10 12 13 15 4 Benutzerhandbuch 4.1 Voraussetzungen 4.2 Login . . . . . . . 4.3 Benutzung . . . . 4.4 Beschränkungen . 4.5 Support . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 16 16 17 22 22 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 Quellenverzeichnis 23 6 JavaDoc Dokumentation 25 2 Kapitel 1 Einleitung 1.1 Aufgabenstellung Meine Aufgabe bestand darin, ein Java-Applet zu erstellen, mit dem SQL-Anfragen an eine Datenbank (z. B. Oracle 9i) gestellt werden können. Das Applet Dato [vH98], welches eine ähnliche Funktionalität wie die gewünschte besitzt, existierte schon, diente aber nicht als Vorlage, weil mir die Struktur zu umständlich erschien und das Tool zur Darstellung das veraltete Abstract Window Toolkit [awt] benutzt. Die Frage, wie die graphische Benutzerschnittstelle zu gestalten ist, war ein Hauptthema, denn jeder Benutzer soll möglichst ohne Einarbeitungszeit oder langes Lesen eines Manuals sofort das Applet benutzen können. Auch war wichtig, dass die Benutzer des Applets den explain plan Befehl so nutzen können, dass sie eine Baumstruktur angezeigt bekommen, und dass der describe Befehl funktioniert. Es wurde angenommen, dass die primären Benutzer die Teilnehmer der Übung zum SQL-Kurs der Fachgruppe Datenbanksysteme sein würden. Besondere Aufmerksamkeit galt auch der Frage, wie man die Datenbankverbindung des Applets so einrichten kann, dass der Endbenutzer keine Eigenschaften seiner Java-Laufzeitumgebung umstellen muss – das war bisher nötig, denn die Java-Standardeinstellungen erlauben einem Applet lediglich eine Verbindung zu dem Server, von dem es stammt; der Datenbankserver ist allerdings nicht immer gleich dem Webserver. Ich habe das zu schreibende Applet “SQuiggLe ” genannt, in Anlehnung an engl. to squiggle, zu deutsch verschnörkeln, da es im Gegensatz zu SQL*Plus doch um einiges schöner aussieht und die Bedienung insofern einfacher und komfortabler ist, als dass SQuiggLe eine Befehlszeilen-History bietet (was bei SQL*Plus bis heute rudimentär blieb). Außerdem musste die Studienarbeit in LATEX [Lam94] [GMS95] gesetzt werden. 1.2. ÜBERBLICK ÜBER DIESE ARBEIT 1.2 3 Überblick über diese Arbeit Im restlichen Kapitel 1 werden die vorbereitenden Arbeiten und Grundlagen beschrieben, im Kapitel 2 die konkreten Vorbereitungen darauf, SQuiggLe in Java zu realisieren. Die Implementierungsphase ist in Kapitel 3 dokumentiert, und in Kapitel 4 ist das Benutzerhandbuch, das man auch separat an Benutzer von SQuiggLe weitergeben kann. Schließlich sind noch die Quellen angegeben und die JavaDoc-Dokumentation eingefügt worden. 1.3 Anwendungsszenario Die Rollen der Rechner sind momentan folgendermaßen verteilt (Ausgangslage, nur die maßgeblichen Daten): leo.dbs.uni-hannover.de Webserver und Datenbankserver für eine Instanz von Oracle (Production) herkules.dbs.uni-hannover.de Datenbankserver für eine weitere Instanz von Oracle (Development) cip-s.kbs.uni-hannover.de Oracle-Datenbankserver für den SQL-Kurs Dabei ist die Instanz auf CIP-S diejenige, die von den primären Benutzern wahrscheinlich am häufigsten genutzt werden wird. 1.4 Vorbereitungen Zuerst wurde eine Materialsammlung im Internet gemacht. Dabei hat sich gezeigt, dass der RMI-JDBC-Treiber (mit seiner zugehörigen Serverapplikation) [rmib] sich für die Verwendung am Institut geradezu anbot – damit ist es möglich, die Verbindungen zu allen Datenbanken über Leo als RMI-Server [rmia] laufen zu lassen. Somit wäre das Problem, dass bisher jeder Benutzer die Einstellungen seiner Java-Laufzeitumgebung anpassen musste, erledigt, denn ein Applet darf nach den Standardeinstellungen Verbindungen zu dem Server herstellen, von dem es geladen wurde, und zwar auch zu einem anderen Port als zu dem, von dem es geladen wurde. Dann stellte sich natürlich die Frage, welche Befehle über die von gängigen Datenbank-Management-Systemen implementierte Untermenge des SQL-Befehlssatzes nach ISO 9075 (siehe [II99a], [II99b], [II99c], [II99d], [II99e] für mehr Informationen zu diesem Standard) hinaus unterstützt werden sollten. Abhängig vom Datenbank Management System (DBMS) sind über JDBC [Ree97] einige herstellerspezifische Befehle verfügbar, aber z. B. der describe-Befehl ist nicht im Oracle-Server, sondern nur in SQL*Plus verfügbar. Dieser Befehl sollte auf 1.4. VORBEREITUNGEN 4 jeden Fall nachgebildet werden, wobei erst einmal geklärt werden musste, was er eigentlich für die verschiedenen Datenbank-Objekte zurückgibt. [Ora99] 5 Kapitel 2 Anforderungen 2.1 Funktionalität Die geforderten Funktionen des Applets sind: Es soll eine möglichst große Untermenge des Standards SQL99 unterstützen (siehe [II99a]ff). Wie groß diese Menge überhaupt sein kann, hängt auch vom verwendeten DBMS ab. Es soll leicht bedienbar sein. Es soll das Oracle-Paket DBMS OUTPUT unterstützen und außerdem den describe-Befehl verstehen. Es soll das Ergebnis eines explain plan Befehles als Baum anzeigen können. Es soll allgemein Ergebnisse tabellarisch formatiert anzeigen können. Das Applet wird in naher Zukunft nur innerhalb des FG Datenbanksysteme benutzt, darum wurden bisher nur zwei Treiber in die RMI-JDBC-Anwendung auf Leo eingebunden, und zwar der Oracle-Thin-Driver und der MySQL-Driver. Siehe dazu auch 3.5. 2.2. ARCHITEKTUR 2.2 6 Architektur Der bisherige Aufbau bzw. die Hierarchie sah folgendermaßen aus: Es wird durch das Einbauen des RMIJDBC-Treibers eine weitere Abstraktionsebene eingezogen, sodass der Aufbau nachher so aussieht: Bei dem neuen Aufbau wird RMI-JDBC vom Applet als JDBC-Treiber verwendet; dieser baut dann eine Verbindung zur RMI-Serveranwendung auf. RMI (Remote Method Invocation) bildet die Klassen der Serverapplikation über das Netzwerk für das Applet nach, sodass dieses nicht einmal merkt, dass die Instanzen der Klassen, mit denen es arbeitet, nicht auf demselben Rechner liegen. 2.3 GUI-Design und Intuitivität Die graphische Benutzeroberfläche (GUI) muss so beschaffen sein, dass es eine klare Benutzerführung gibt. Unübersichtlichkeit sollte vermieden werden, dafür 2.3. GUI-DESIGN UND INTUITIVITÄT 7 lieber einige unwichtigere Funktionen weglassen. Man sollte auf den ersten Blick sehen, worum es bei dem Programm geht, und dazu gehört bei SQuiggLe besonders die Trennung von Eingabe- und Ausgabebereich. Echte Intuitivität bedeutet, dass ein Programm eine sinnvolle Benutzerführung aufweist. Ohne größeres Nachdenken ist jedem Benutzer unmittelbar klar, welches Element der GUI wofür zuständig ist. Auch wenn ein Benutzer das Programm zum ersten Mal benutzt (und in etwa weiß, wofür es gut ist), kann er es sofort benutzen. Diese Anforderungen sind ziemlich hoch gesteckte Ziele, aber das Resultat rechtfertigt den Aufwand. Ein Anwender ist sehr viel zufriedener, wenn er nicht erst seitenweise Dokumentation lesen muss, um ein Programm zu bedienen! 8 Kapitel 3 Realisierung 3.1 Prinzip eines Applets Ein Applet ist eine Ansammlung von Klassen, die nicht über den normalen JavaBytecode-Interpreter java ausgeführt werden, sondern über ein Plug-In, welches in einen Web-Browser integriert ist. Außerdem gibt es im Java 2 Software Development Kit (auch J2SDK oder JDK genannt) einen appletviewer, der zum Testen von Applets gedacht ist. Für ausfühliche Informationen und Anleitungen siehe [app]. 3.2 Prinzip von SQuiggLe SQuiggLe (das Applet) öffnet standardmäßig eine GUI für Benutzereingaben. Mit den im Applet enthaltenen Buttons kann man neue GUIs öffnen (z. B. für die Kommunikation mit anderen Datenbanken) und auch alle GUIs schließen. Im Schließvorgang enthalten ist, dass jede noch offene Verbindung zur Datenbank ordnungsgemäß geschlossen wird, genau wie es auch passiert, wenn man eine GUI einzeln schließt. Im Folgenden gelte die Bezeichnung SQuiggLe für eine einzelne GUI, nicht mehr für das Applet als Ganzes. SQuiggLe handelt nach den Eingaben des Benutzers, die sinnvollerweise in folgender Reihenfolge kommen: (Login bei der Datenbank) SQL-Anfrage (falls der Benutzer noch nicht eingeloggt ist, wird automatisch davor ein Login durchgeführt) SQL-Anfrage ... 3.2. PRINZIP VON SQUIGGLE 9 Jede SQL-Anfrage liefert ein Ergebnis, welches in einem besonderen Bereich angezeigt wird, zusammen mit der Anfrage, die dieses Ergebnis hervorgerufen hat. Der Benutzer hat die Möglichkeit, bei einem aus einer Tabelle bestehenden Ergebniss eine alternative Nur-Text-Fassung aufzurufen. Diese kann z. B. in eine Mail kopiert werden. Ebenso kann, falls die Anfrage dies ausgelöst hat, der Text angeschaut werden, der vom Oracle-Package DBMS OUTPUT ausgegeben wurde. Hier ein Beispiel: Man kann einzelne Anfragen bzw. deren Tabs auch über ein Kontextmenü wieder löschen. Das macht natürlich die Auswirkungen auf die Datenbank nicht rückgängig! Alles bleibt erhalten, falls Auto-Commit eingeschaltet ist, oder alles wird dauerhaft gemacht beim nächsten manuellen Commit. Wenn SQuiggLe beendet wird, ohne dass ein Commit ausgeführt wurde und Auto-Commit ausgeschaltet war, wird beim Beenden automatisch ein Commit ausgeführt. Während einzelne Anfragen ausgeführt werden, kann der Benutzer das Einlesen von Ergebnisdatensätzen abbrechen. Am unteren Fensterrand wird die Nummer des Datensatzes angezeigt, der gerade eingelesen wird, und ein “Anfrage abbrechen”-Button. 3.3. DER DESCRIBE BEFEHL 3.3 10 Der DESCRIBE Befehl Für die Realisierung dieses Befehls musste, wie in 1.4 erwähnt, geklärt bzw. festgelegt werden, was für die einzelnen Objekte als wichtige Daten angesehen wird. In dieser Frage waren die “Catalog Views / Data Dictionary Views” aus der Oracle Dokumentation maßgeblich. Für jeden Objekttyp <NAME>, der unterstützt werden sollte, wurden aus dem View ALL <NAME>S die jeweils wichtigen Felder herausgesucht. Eine describe <objectname> Anfrage wird innerhalb von SQuiggLe folgendermaßen verarbeitet: 1. Es wird eine Anfrage an die Datenbank gesendet, von welchem Typ das zu beschreibende Objekt ist. Dazu wird ALL USER OBJECTS und ALL OBJECTS verwendet. 2. Zu jedem Objekttyp gibt es einen eigenen View. Dieser wird angefragt, um die passenden Daten zu erhalten. 3. Im Server-Output wird der Objekttyp ausgegeben. Das ist wichtig, wenn die Auflösung von Synonymen in der Klasse dbis.squiggle.GUI aktiviert ist, denn sonst merkt man nicht, dass man nur mit einem Synonym arbeitet! Standardmäßig ist die Synonymauflösung aktiviert. 4. Das Anfrageergebnis wird als Tabelle und als Nur-Text-Fassung dargestellt. 3.4 Der EXPLAIN PLAN Befehl Diesen Befehl gibt es z. B. in Oracle und in PostgreSQL. Der explain plan Befehl hat die Funktion, den Anfrageplan, den die Datenbank zur Ausführung einer bestimmten Anfrage benutzen würde, in eine (entsprechend formatierte) Tabelle zu schreiben. Standardeinstellung in Oracle ist hierfür die Tabelle plan table; allerdings wird nur hinzugefügt, das heißt, alle alten Anfragepläne, die nicht explizit gelöscht wurde, sind auch noch in dieser Tabelle enthalten. Dieser Befehl erzeugt keine Ausgabe, also keine Tabelle aus Rückgabewert, sondern schreibt lediglich den Plan in die dafür vorgesehene Tabelle. Dabei gibt es die Spalten “ID” und “PARENT ID”, die eine Struktur definieren. Diese Struktur kann man z. B. mit der folgenden Anfrage etwas schöner als in reiner Tabellenform darstellen: select substr (lpad(’ ’, level-1) || operation || ’ (’ || options || ’)’,1,30 ) "Operation", object_name "Object" from plan_table 3.4. DER EXPLAIN PLAN BEFEHL 11 start with id = 0 connect by prior id=parent_id; Diese Methode ist aber immer noch nicht ausreichend. Um die Benutzung von explain plan einfach und graphisch ansprechend zu machen, wird der Befehl von SQuiggLe intern umgewandelt in mehrere Befehle: zuerst werden alte Ergebnisse gelöscht, dann wird der eigentliche Befehl ausgeführt, und dann wird das Ergebnis aus plan table gelesen. Ansonsten würde der Befehl keine Tabelle zurückgeben, und es würde das Ergebnis erst nach einer weiteren Anfrage ausgegeben werden. SQuiggLe wandelt die empfangenen Tabellenzeilen um in eine Baumstruktur, damit der Benutzer leicht sehen kann, wie die Anfrage abgearbeitet werden würde. Diese Funktionalität war in Dato grundsätzlich schon vorhanden, aber in SQuiggLe kann man auch Zusatzinformationen wie Kosten, Optimierung usw. durch Klicken auf die jeweiligen Knoten des generierten Baumes anzeigen lassen. Für diesen Befehl muss die Tabelle plan table bereits existieren. Sie wird, falls sie noch nicht existiert, beim Datenbanklogin automatisch versucht anzulegen. Dabei wird eine evtl. vorhandene plan table vorher gelöscht, falls sie nicht die erforderliche Spaltenzahl und die richtigen Spalten-Datentypen hat. Ein Beispiel: Falls es in Oracle die Tabellen dept und emp gibt und sie mit den Anweisungen CREATE TABLE DEPT ( DEPTNO NUMBER(2) NOT NULL, DNAME VARCHAR2(14), LOC VARCHAR2(13), CONSTRAINT DEPT_PRIMARY_KEY PRIMARY KEY (DEPTNO)) und CREATE TABLE EMP ( EMPNO ENAME JOB MGR NUMBER(4) NOT NULL, VARCHAR2(10), VARCHAR2(9), NUMBER(4) CONSTRAINT EMP_MGR_FK REFERENCES EMP (EMPNO), HIREDATE DATE, SAL NUMBER(7,2), COMM NUMBER(7,2), DEPTNO NUMBER(2) NOT NULL, CONSTRAINT EMP_DEPTNO_FK FOREIGN KEY (DEPTNO) REFERENCES DEPT (DEPTNO), CONSTRAINT EMP_EMPNO_PK PRIMARY KEY (EMPNO)) 3.5. TESTS 12 erstellt wurden, gibt die Anfrage explain plan for select deptno, sum(sal) salarysum from emp natural join dept group by deptno folgendes graphisch strukturierte Ergebnis aus: In SQuiggLe kann man, wie oben erwähnt, durch einen Klick Informationen über die einzelnen Knoten des Baums abrufen. 3.5 Tests SQuiggLe wurde mit den Browsern Internet Explorer 6.0 (Windows), Mozilla 1.3 und 1.4 (Windows und Linux), Opera 7.11 (Linux) und Netscape 6.2 (Linux) erfolgreich getestet. Dabei kamen die JREs 1.3 und 1.4 zum Einsatz. Auf der Serverseite wurde SQuiggLe mit RMI-JDBC 2.5, Oracle 9.2 und MySQL 4.0 getestet. Dabei wurde die Zusammenarbeit von RMI-JDBC mit den beiden Datenbanken ebenso wie die jeder Datenbank einzeln mit SQuiggLe geprüft. Zur Performance muss man leider sagen, dass SQuiggLe große Datenmengen nicht in akzeptabler Zeit darstellen bzw. über das Netzwerk transportieren kann. Folgende Kombinationen wurden innerhalb des Instituts-Netzwerkes unter Mozilla 1.4 (mit dem Plug-In des JRE 1.4) ausprobiert mit der Anfrage select title, year from moviedb.movie where title like ’%res’ (gibt 982 Zeilen zurück): 3.6. INSTALLATION DES APPLETS AUF EINEM SERVER Umgebung alle Datensätze angezeigt nach SQL*Plus: 2 Sekunden SQuiggLe mit Oracle-Thin-Treiber: 35 Sekunden SQuiggLe mit RMI-JDBC-Treiber: 40 Sekunden Dato mit Oracle-Thin-Treiber: mehr als 1 Minute 3.6 Installation des Applets auf einem Server Das Programmmpaket besteht aus: 1. Java-Quelltext-Dateien: dbis/squiggle/AnswerPanel.java dbis/squiggle/DBMS OUTPTUT.java dbis/squiggle/GUI.java dbis/squiggle/HelpViewer.java dbis/squiggle/Node.java dbis/squiggle/ServerOutputArea.java dbis/squiggle/SquiggleApplet.java dbis/squiggle/TreePane.java dbis/squiggle/TreeView.java dbis/sql/JLoginDialog.java dbis/sql/TnsLoader.java dbis/util/PropertyDisplayApplet.java dbis/util/RBLoad.java 2. Makefile 3. README 4. API-Dokumentation (Verzeichnis api/) 5. LATEX-Sourcen der Arbeit (Verzeichnis tex/) 6. WWW-Verzeichnis: HTML-Dateien: – index.html – jdk13.html – jdk13-thin.html 13 3.6. INSTALLATION DES APPLETS AUF EINEM SERVER 14 – jdk14.html – jdk14-thin.html – alles.html Java-Archive: – – – – – – – squiggle.jar RmiJdbc.jar thin-jdk1.1.zip mysql-connector.jar jcert.jar jnet.jar jsse.jar Online-Hilfe-Dateien (Verzeichnis help/) Ressourcen (Verzeichnis res/) Das Paket ist in sich abgeschlossen und muss lediglich an einen Ort kopiert werden, von dem aus ein Webserver es zur Verfügung stellen kann. Falls das Applet lauffähig sein soll, ohne dass jeder Benutzer sein Java Runtime Environment anpassen muss, sollte die RMI-JDBC-Serverapplikation auf demselben Rechner laufen, auf dem der Webserver läuft; außerdem muss der RMI-JDBC-Rechner bzw. Webserver in die von dbis.sql.JLoginDialogNew benutzte Properties-Datei eingetragen werden. Da das Applet SQuiggLe für das FG DBS erstellt wurde, ist in der Klasse dbis.sql.JLoginDialogNew (in den Variablen RBDir und RBFile) der Ort der Properties-Datei fest verankert, von dem Treibereinstellungen geladen werden. Wenn dieser Ort geändert werden soll, muss die Klasse JLoginDialogNew neu kompiliert werden (ein Makefile liegt dem Programmpaket bei, dieses muss gegebenenfalls angepasst werden). Bei einer Neuinstallation müssen folgende Dateien angepasst werden (ausgehend vom abgegebenen Paket): www/help/index.html (der Tag <BASE> muss angepasst werden) dbis/squiggle/GUI.java (die Variable rootPath muss angepasst werden; ansonsten wird der weiße Pfeil in der GUI nicht angezeigt, sondern stattdesen nur ein Text) Wenn neue Treiber hinzugefügt werden sollen, so muss dies sowohl in der Properties-Datei als auch in der HTML-Datei getan werden, von der das Applet SQuiggLe gestartet wird. Dabei muss der Ort bekannt sein, von dem die JARDatei geladen werden kann, die den neuen Treiber enthält. 3.7. WEITERE ANWENDUNGSMÖGLICHKEITEN FÜR RMI-JDBC 3.7 15 Weitere Anwendungsmöglichkeiten für RMI-JDBC Aufgrund des erstaunlich geringen Ladezeit-Unterschiedes zwischen Oracle-Thinund RMI-JDBC-Treiber ist es nicht so abwegig, andere Applikationen und Applets wie z. B. GISVisual auch mit dem RMI-JDBC-Treiber laufen zu lassen. Die einzige Hürde dabei ist, dass einige Klassen, die vom Oracle-Thin-Treiber standardmäßig benutzt werden, um bestimmte Datenbankobjekte in Java zu kapseln, nicht serialisierbar sind, was allerdings für RMI Voraussetzung ist [rmib]. Dies Problem könnte man dadurch vermeiden, dass man die RMI-JDBCServerapplikation, die auf Leo läuft, so anpasst, dass andere (serialisierbare) Klassen verwendet werden. Das ist mit der im Interface java.sql.Connection definierten Methode setTypeMap(java.util.Map) möglich. Bei Bedarf kann auch SSL für die Datenübertragung aktiviert werden, RMIJDBC unterstützt diesen Standard. 16 Kapitel 4 Benutzerhandbuch 4.1 Voraussetzungen Da das Programm SQuiggLe ein Applet ist, braucht man nur einen Browser, der Java 1.3.0 oder höher versteht. Außerdem ist eine schnelle Internetverbindung nicht schlecht, da für das Applet 660 kB bis 2,3 MB geladen werden müssen, abhängig von der Java-Version und auch abhängig davon, ob man nur mit RMIJDBC (ausreichend für fast alle Anwendungen), mit dem Oracle-Thin-Treiber oder mit dem MySQL-Treiber arbeiten möchte. 4.2 Login Man braucht, um mit dem Applet arbeiten zu können, einen Login (bestehend aus Benutzername und Passwort) für eine Datenbank. Wenn man das Applet SQuiggLe startet, öffnet es erst einmal ein Eingabefenster für Benutzeranfragen, eine GUI (Graphical User Interface). In einer GUI (im Folgenden wird der Einfachheit halber eine GUI als SQuiggLe bezeichnet) ist zunächst keine Verbindung vorhanden, darum sollte man als erstes in einer Sitzung sich auf der Datenbank einloggen. Das geht im Menü Verbindung, Eintrag Verbinden. . .. Man bekommt dann die DBS-Standard-Login-Aufforderung zu sehen: 4.3. BENUTZUNG 17 Die Standardeinstellung für den Treiber ist “RmiJdbc”, für die Datenbankinstanz (bzw. URL) “DBIS”. Das sind korrekte Einstellungen, um auf die Entwicklungsdatenbank des FG DBS zuzugreifen. Jetzt müssen nur noch Benutzer und Passwort eingegeben werden. Wenn im Passwortfeld die Eingabetaste betätigt wird, sieht das Programm dies als Login-Aufforderung an, so als ob auf “Verbinden” geklickt worden wäre. Es gibt Kombinationen von Treiber und URL, die nicht funktionieren, nämlich dann, wenn versucht wird, mit einem nicht passenden nativen Treiber auf eine Datenbank zuzugreifen (beispielsweise falls man mit dem MySQL-Treiber auf eine Oracle-Datenbank zugreifen wollte). Außerdem gelten die Login-Daten meistens nur für eine bestimmte Datenbank. 4.3 Benutzung Wenn man sich eingeloggt hat, dann hat man das Hauptfenster vor sich. Es besteht aus den Bereichen Menü (ganz oben), Eingabe (oben), Ausgabe (unten; ist am Anfang leer) und Status (ganz unten): 4.3. BENUTZUNG 18 Im Eingabebereich kann man SQL-Anfragen eintippen (hier gezeigt: eine schon fertig ausgeführte select * from emp Anfrage). Außer select funktionieren auch die Befehle delete create drop insert update execute bzw. die Abkürzung exec begin ... end explain plan describe bzw. die Abkürzung desc commit savepoint rollback 4.3. BENUTZUNG 19 Einige Befehle aus der obigen Liste sind Oracle-spezifisch. Man muss Anfragen nicht mit einem Semikolon abschließen. Die Möglichkeit, mehrere Anfragen auf einmal zu stellen, wird nicht unterstützt. Man kann jedoch mehrere Anfragen nacheinander stellen, und das sogar, während vorige Anfragen noch laufen. Es ist auch möglich, laufende Anfragen abzubrechen: Dabei wird der gerade im Verarbeitungsprozess befindliche Datensatz noch zu Ende eingelesen und dann die Generierung der Nur-Text-Version begonnen (die man dann auch noch abbrechen kann): Wenn eine Anfrage zu Ende gelaufen ist, gibt es außer der normalen Tabellenansicht (wie auf Seite 17 gezeigt) noch eine Nur-Text-Fassung derselben Daten, die man allerdings besser per Copy&Paste weitergeben kann: 4.3. BENUTZUNG 20 Darüberhinaus gibt es noch die Möglichkeit, dass bei einer Oracle-Datenbank ein Trigger ausgelöst wurde, der Text über das Package DBMS OUTPUT ausgegeben hat, oder es wurde das describe-Kommando ausgeführt, welches auch eine Textausgabe erzeugt; dieser Text ist dann im Dropdown-Feld unter “Server-Output” einzusehen: Und falls ein entsprechender Trigger in der Datenbank existiert, der das Package DBMS OUTPUT nutzt, kann es auch eine solche Ausgabe geben: Der describe-Befehl ist nur für Oracle-Datenbanken verfügbar und kann auf Objekte vom Typ Table, View, Trigger, Synonym, Procedure, Function, Package, Index, Sequence oder Type angewendet werden. Er versteht die “schema.name” 4.3. BENUTZUNG 21 Benennungsschreibweise, aber keine Database-Links. Der einzige nennenswerte Unterschied zum SQL*Plus-Befehl describe ist, dass bei Views als zu beschreibendem Objekt der den View generierende SQL-Befehl zurückgegeben wird und nicht die Spalten der resultierenden Tabelle. Zusätzlich ist in Oracle der explain plan-Befehl verfügbar, allerdings noch ein wenig verbessert: Man braucht keine zusätzliche select-Anfrage mehr an PLAN TABLE stellen. Das Ergebnis wird sofort dargestellt. Eine weitere Verbesserung ist die graphische Baumdarstellung des zurückgegebenen Anfrage-Planes. Wenn man auf einzelne Knoten des Baumes klickt, werden auf der rechten Seite Details zu diesem Element angezeigt (hier werden gerade die Daten des Knotens “TABLE ACCESS” angezeigt): Dort, wo zu jedem Anfrageergebnis die gestellte Anfrage steht, wird bei einem explain plan Befehl eine Besonderheit deutlich: Es werden die Befehle 4.4. BESCHRÄNKUNGEN 22 dargestellt, die wirklich ausgeführt wurden, nicht nur der eine, der vom Benutzer eingegeben wurde. Wenn eine Anfrage, die schon einmal so oder ähnlich gestellt wurde, ausgeführt werden soll, dann kann man die Anfrage in den Eingabebereich kopieren, indem man im Ausgabebereich den Button mit dem weißen Pfeil anklickt. Dabei wird eventuell im Eingabebereich befindlicher Text überschrieben! Wenn Anfragen überflüssig werden, kann man sie über das Kontextmenü der Tabs (auch manchmal Karteireiter genannt) schließen. Auf vielen Systemen öffnet man dieses Kontextmenü, indem man mit der rechten Maustaste auf einen Karteireiter klickt. Bei Benutzung des explain plan-Befehls wird im Ausgabebereich der tatsächlich ausgeführte Code angezeigt. Jedoch wird nur die vom Benutzer eingegebene Anfrage in den Eingabebereich zurückkopiert, wenn der Button rechts neben der Anfrage-Anzeige (weißer Pfeil) geklickt wird. 4.4 Beschränkungen SQuiggLe hat die typische Performance eines Java-Applets: Es ist nicht für die Verarbeitung großer Datenmengen geeignet. Ein grober Richtwert: Falls man mehr als 2000 Datensätze selektieren möchte (oder wenige, aber große Datensätze), benutze man ein der Datenbank beiliegendes Client-Programm! Außerdem wird nicht die Befehlsvielfalt von SQL*Plus erreicht, welches Oracle beiliegt, andererseits ist SQuiggLe auch nicht von einem bestimmten DBMS abhängig. 4.5 Support Bitte haben Sie Verständnis dafür, dass Supportanfragen nur per Email entgegengenommen und beantwortet werden können! Schreiben Sie an [email protected], falls Sie Probleme bei der Benutzung von SQuiggLe haben oder neue Features vorschlagen möchten. 23 Kapitel 5 Quellenverzeichnis [app] How to Make Applets. http://java.sun.com/docs/books/tutorial/ uiswing/components/applet.html (Link vom 22.09.2003). [awt] Abstract Window Toolkit (AWT). http://java.sun.com/j2se/1.3/ docs/guide/awt/ (Link vom 22.09.2003). [GMS95] M. Goossens, F. Mittelbach, A. Samarin: Addison-Wesley, Bonn, 1995. Der LaTeX Begleiter. [II99a] ISO, IEC: ISO/IEC 9075-1: SQL/Framework, 1999. [II99b] ISO, IEC: ISO/IEC 9075-2: SQL/Foundation, 1999. [II99c] ISO, IEC: ISO/IEC 9075-3: Call Level Interface (SQL/CLI), 1999. [II99d] ISO, IEC: ISO/IEC 9075-4: Persistent Stored Modules (SQL/PSM), 1999. [II99e] ISO, IEC: ISO/IEC 9075-5: Host Language Bindings (SQL/Bindings), 1999. [Lam94] L. Lamport: LATEX– A Document Preparation System. Addison-Wesley, 1994. [Ora99] Oracle Corporation: Dokumentation zu Oracle 8i: SQL*Plus User’s Guide and Reference Part No. A82950-01, 1999. [Ree97] G. Reese: Database Programming with JDBC and Java. O’Reilly & Associates, 1997. [rmia] Remote Method Invocation (RMI). http://java.sun.com/products/ jdk/rmi/ (Link vom 22.09.2003). 24 [rmib] RMI-JDBC-Treiber von ObjectWeb. org/ (Link vom 22.09.2003). http://rmijdbc.objectweb. [vH98] A. von Helmolt. Implementierung eines Datenbank-AdministrationsTools in Java. 1998. http://www.dbs.uni-hannover.de/ ftp/studienarbeiten/von_helmolt/von_helmolt.ps.gz (Link vom 22.09.2003). 25 Kapitel 6 JavaDoc Dokumentation Die JavaDoc-Dokumentation wird mit eingebunden, weil so alles wichtige auf einen Blick ersichtlich ist. Außerdem können so interessierte Programmierer viel leichter Änderungen am Sourcecode vornehmen, da sie nachvollziehen können, welche Klassen und Methoden zu welchen Zwecken dienen. 26 dbis.squiggle.AnswerPanel dbis.squiggle Class AnswerPanel java.lang.Object | +-java.awt.Component | +-java.awt.Container | +-javax.swing.JComponent | +-javax.swing.JSplitPane | +-dbis.squiggle.AnswerPanel All Implemented interfaces: java.lang.Runnable, java.awt.event.ItemListener, java.awt.event.ActionListener, java.io.Serializable, java.awt.MenuContainer, java.awt.image.ImageObserver, java.io.Serializable, javax.accessibility.Accessible public class AnswerPanel extends javax.swing.JSplitPane implements javax.accessibility.Accessible, java.io.Serializable, java.awt.image.ImageObserver, java.awt.MenuContainer, java.io.Serializable, java.awt.event.ActionListener, java.awt.event.ItemListener , java.lang.Runnable JPanel, welches ein fertig ausgeführtes Statement mit Anfrage annimmt und die Ergebnisse anzeigt. Dabei wird für's Einlesen der Datensätze ein neuer Thread generiert, damit man auch das Lesen abbrechen kann. Author: Mathis Dirksen-Thedens ([email protected]) Constructors AnswerPanel public AnswerPanel(java.sql.Statement stmnt, java.lang.String sql, java.lang.String anzeigesql, DBMS_OUTPUT serveroutput, java.lang.String beforeserveroutput, GUI gui, javax.swing.JButton cancelbutton, javax.swing.JLabel statusfield) Konstruktor für's AnswerPanel Parameters: stmnt Statement mit fertig [ per stmnt.execute(string)] ausgeführter Anfrage sql ausgeführte Anfrage gui übergeordnete GUI anzeigesql String, der angezeigt, aber nicht unbedingt genau so ausgeführt wurde serveroutput DBMS_OUTPUT-Objekt, woher der Server-Output gelesen werden soll beforeserveroutput Vor den Serveroutput einzufügender Text (continued on next page) Page 2 27 dbis.squiggle.AnswerPanel (continued from last page) Methods run public void run() actionPerformed public void actionPerformed(java.awt.event.ActionEvent e) Aktionsbehandlung Parameters: e ein ActionEvent itemStateChanged public void itemStateChanged(java.awt.event.ItemEvent evt) Aktionsbehandlung Parameters: evt ein ItemEvent Page 3 28 dbis.squiggle.DBMS_OUTPUT dbis.squiggle Class DBMS_OUTPUT java.lang.Object | +-dbis.squiggle.DBMS_OUTPUT public class DBMS_OUTPUT extends java.lang.Object Klasse, um mit DBMS_OUTPUT.put() bzw. DBMS_OUTPUT.put_line() geschriebenen Text über JDBC auslesen zu können. Siehe Thread "Usefulness of DBMS_OUTPUT.PUT_LINE?" in comp.databases.oracle.server vom Juli 2002 für nähere Einzelheiten! Author: Thomas Kyte ([email protected]), Mathis Dirksen-Thedens ([email protected]) Constructors DBMS_OUTPUT public DBMS_OUTPUT(java.sql.Connection conn) our constructor simply prepares the three statements we plan on executing. the statement we prepare for SHOW is a block of code to return a String of dbms_output output. Normally, you might bind to a PLSQL table type but the jdbc drivers don't support PLSQL table types -- hence we get the output and concatenate it into a string. We will retrieve at least one line of output -- so we may exceed your MAXBYTES parameter below. If you set MAXBYTES to 10 and the first line is 100 bytes long, you will get the 100 bytes. MAXBYTES will stop us from getting yet another line but it will not chunk up a line. Parameters: conn Datenbank-Verbindung Exceptions: SQLException Ausführungsfehler Methods enable public void enable(int size) throws java.sql.SQLException enable simply sets your size and executes the dbms_output.enable call Parameters: size Größe Exceptions: SQLException Fehler Page 4 29 dbis.squiggle.DBMS_OUTPUT (continued from last page) disable public void disable() throws java.sql.SQLException disable only has to execute the dbms_output.disable call Exceptions: SQLException Fehler show public void show() throws java.sql.SQLException show does most of the work. It loops over all of the dbms_output data, fetching it in this case 32,000 bytes at a time (give or take 255 bytes). It will print this output on stdout by default (just reset what System.out is to change or redirect this output). Exceptions: SQLException Fehler show_output public void show_output() throws java.sql.SQLException Andere Methode, um den Serveroutput auszulesen (mit Hilfe von Joseph Weinstein, siehe Thread "DBMS_OUTPUT.PUT_LINE and JDBC" in comp.databases.oracle vom Juli 2002). Exceptions: SQLException Fehler get_output public java.lang.String get_output() throws java.sql.SQLException Zweite andere Methode, um den Serveroutput auszulesen, aber jetzt als Rückgabewert und nicht auf System.out! Returns: der Server-Output Exceptions: SQLException Fehler close public void close() throws java.sql.SQLException close closes the callable statements associated with the DbmsOutput class. Call this if you allocate a DbmsOutput statement on the stack and it is going to go out of scope -- just as you would with any callable statement, result set and so on. Exceptions: SQLException Fehler Page 5 30 dbis.squiggle.GUI dbis.squiggle Class GUI java.lang.Object | +-java.awt.Component | +-java.awt.Container | +-java.awt.Window | +-java.awt.Frame | +-javax.swing.JFrame | +-dbis.squiggle.GUI All Implemented interfaces: java.awt.event.WindowListener, java.awt.event.MouseListener, java.awt.event.ActionListener, java.io.Serializable, java.awt.MenuContainer, java.awt.image.ImageObserver, javax.accessibility.Accessible, java.awt.MenuContainer, javax.swing.RootPaneContainer, javax.accessibility.Accessible, javax.swing.WindowConstants public class GUI extends javax.swing.JFrame implements javax.swing.WindowConstants, javax.accessibility.Accessible, javax.swing.RootPaneContainer, java.awt.MenuContainer, javax.accessibility.Accessible, java.awt.image.ImageObserver, java.awt.MenuContainer, java.io.Serializable, java.awt.event.ActionListener, java.awt.event.MouseListener, java.awt.event.WindowListener GUI für SQuiggLe Author: Mathis Dirksen-Thedens ([email protected]) Fields resolveSynonymsForDescribe public boolean resolveSynonymsForDescribe Ob Synonyme aufgelöst werden sollen, wenn per Describe darauf zugegriffen wird. Auflösen kostet Rechenzeit!!! Constructors GUI public GUI() Konstruktor für die GUI Methods mouseClicked public void mouseClicked(java.awt.event.MouseEvent e) MouseListener-Implementation Page 6 31 dbis.squiggle.GUI (continued from last page) Parameters: e Parameter mouseEntered public void mouseEntered(java.awt.event.MouseEvent e) MouseListener-Implementation Parameters: e Parameter mouseExited public void mouseExited(java.awt.event.MouseEvent e) MouseListener-Implementation Parameters: e Parameter mousePressed public void mousePressed(java.awt.event.MouseEvent e) MouseListener-Implementation Parameters: e Parameter mouseReleased public void mouseReleased(java.awt.event.MouseEvent e) MouseListener-Implementation Parameters: e Parameter actionPerformed public void actionPerformed(java.awt.event.ActionEvent e) Aktionsbehandlung Parameters: e ein ActionEvent substituteCRLF public static java.lang.String substituteCRLF(java.lang.String string, char c) Allgemeine Hilfsmethode: Ersetzt CRLF. Mit Hilfe aus dem Internet geschrieben! Parameters: Page 7 32 dbis.squiggle.GUI (continued from last page) string Eingabestring c Buchstabe, der eingesetzt werden soll Returns: den fertigen String cleanup public void cleanup() Aufräumen... Diese Methode wird vom Applet beim STOP benötigt; aufgerufen wird sie über close(). close public void close() Schließer errorHandler protected void errorHandler(java.lang.Throwable ex) Fehlerbehandlung (auch für andere darstellende Klassen). Der Fehler wird der Liste für showFailures() hinzugefügt und dann dem Benutzer angezeigt. Parameters: ex der Fehler setSqlText public void setSqlText(java.lang.String sql) Setzt das SQL-Eingabefeld. Diese Methode wird vom AnswerPanel aufgerufen. Parameters: sql Neuer Wert für das Eingabefeld setAPNotDisplayable public void setAPNotDisplayable() Sagt der GUI, dass das letzte AnswerPanel nicht angezeigt werden kann, weil ein Fehler aufgetreten ist. replace public static java.lang.String replace(java.lang.String in, java.lang.String toreplace, java.lang.String replacewith) Ersetzt in einem String etwas durch etwas anderes. Parameters: in Eingabe toreplace zu ersetzen replacewith womit ersetzen Returns: Page 8 33 dbis.squiggle.GUI (continued from last page) Ausgabe windowActivated public void windowActivated(java.awt.event.WindowEvent e) WindowListener-Implementation Parameters: e Parameter windowClosed public void windowClosed(java.awt.event.WindowEvent e) WindowListener-Implementation Parameters: e Parameter windowClosing public void windowClosing(java.awt.event.WindowEvent e) WindowListener-Implementation Parameters: e Parameter windowDeactivated public void windowDeactivated(java.awt.event.WindowEvent e) WindowListener-Implementation Parameters: e Parameter windowDeiconified public void windowDeiconified(java.awt.event.WindowEvent e) WindowListener-Implementation Parameters: e Parameter windowIconified public void windowIconified(java.awt.event.WindowEvent e) WindowListener-Implementation Parameters: e Parameter Page 9 34 dbis.squiggle.GUI (continued from last page) windowOpened public void windowOpened(java.awt.event.WindowEvent e) WindowListener-Implementation Parameters: e Parameter Page 10 35 dbis.squiggle.HelpViewer dbis.squiggle Class HelpViewer java.lang.Object | +-java.awt.Component | +-java.awt.Container | +-java.awt.Window | +-java.awt.Frame | +-javax.swing.JFrame | +-dbis.squiggle.HelpViewer All Implemented interfaces: java.awt.event.ActionListener, java.io.Serializable, java.awt.MenuContainer, java.awt.image.ImageObserver, javax.accessibility.Accessible, java.awt.MenuContainer, javax.swing.RootPaneContainer, javax.accessibility.Accessible, javax.swing.WindowConstants public class HelpViewer extends javax.swing.JFrame implements javax.swing.WindowConstants, javax.accessibility.Accessible, javax.swing.RootPaneContainer, java.awt.MenuContainer, javax.accessibility.Accessible, java.awt.image.ImageObserver, java.awt.MenuContainer, java.io.Serializable, java.awt.event.ActionListener Betrachter für eine HTML-Datei Author: Mathis Dirksen-Thedens ([email protected]) Constructors HelpViewer public HelpViewer(GUI parent, java.lang.String helpfile) Konstruktor für HelpViewer Parameters: helpfile Datei parent aufrufende GUI Methods actionPerformed public void actionPerformed(java.awt.event.ActionEvent e) ActionListener-Implementierung Parameters: Page 11 36 dbis.squiggle.HelpViewer (continued from last page) e Parameter Page 12 37 dbis.squiggle.Node dbis.squiggle Class Node java.lang.Object | +-java.awt.Component | +-java.awt.Container | +-javax.swing.JComponent | +-javax.swing.JLabel | +-dbis.squiggle.Node public class Node extends javax.swing.JLabel allgemeiner Knoten; wird für die Baumdarstellung eines Plans benutzt Author: Mathis Dirksen-Thedens ([email protected]) Constructors Node public Node() Default-Konstruktor für Node Node public Node(int attached_data_count) Konstruktor für Node Parameters: attached_data_count Wie viele einzelne Daten (Objects) an den Knoten angeheftet werden können sollen Node public Node(java.lang.String int id, java.lang.Object java.lang.String java.lang.String Konstruktor für Node name, attached_data, attached_data_names, attached_data_hints) Parameters: name Name des Knotens attached_data die Daten, die an den Knoten angeheftet werden sollen attached_data_names die Namen zu den angehefteten Daten attached_data_hints Beschreibungen zu den angehefteten Daten Page 13 38 dbis.squiggle.Node (continued from last page) id ID Methods setAttachedData public void setAttachedData(int i, java.lang.Object datum) Setzt ein angeheftetes Datum. Parameters: i Index datum Neuer Wert getAttachedData public java.lang.Object getAttachedData(int i) Holt ein angeheftetes Datum. Parameters: i Index Returns: ein Object setAttachedDataName public void setAttachedDataName(int i, java.lang.String name) Setzt den Namen eines angehefteten Datums. Parameters: i Index name Neuer Wert getAttachedDataName public java.lang.String getAttachedDataName(int i) Holt den Namen eines angehefteten Datums. Parameters: i Index Returns: ein Name setAttachedDataHint public void setAttachedDataHint(int i, java.lang.String hint) Page 14 39 dbis.squiggle.Node (continued from last page) Setzt den Hint eines angehefteten Datums. Parameters: i Index hint Neuer Wert getAttachedDataHint public java.lang.String getAttachedDataHint(int i) Holt den Hint eines angehefteten Datums. Parameters: i Index Returns: ein Hint addChild public void addChild(Node child) Unterknoten hinzufügen Parameters: child der Unterknoten getChildByID public Node getChildByID(int id) Sucht den passenden Node aus den Unter-Nodes per Depth-First-Suche heraus. Parameters: id ID Returns: ein Node oder null getChildAt public Node getChildAt(int i) Holt einen Unter-Node Parameters: i Index Returns: Unter-Node getChildCount public int getChildCount() Page 15 40 dbis.squiggle.Node (continued from last page) Holt die Unter-Node-Anzahl Returns: Unter-Node-Anzahl getID public int getID() Holt die ID von diesem Node Returns: ID getName public java.lang.String getName() Holt das Attribut name von Node Returns: Wert von name getAttachedDataCount public int getAttachedDataCount() Holt das Attribut attachedDataCount von Node Returns: Wert von attachedDataCount setID public void setID(int id) Setzt die ID von diesem Node Parameters: id Neue ID toString public java.lang.String toString() Standardmethode (gut zum Debuggen) Returns: der String toString public java.lang.String toString(java.lang.String padding) Standardmethode (gut zum Debuggen) Parameters: Page 16 41 dbis.squiggle.Node (continued from last page) padding Einrückung Returns: der String Page 17 42 dbis.squiggle.ServerOutputArea dbis.squiggle Class ServerOutputArea java.lang.Object | +-java.awt.Component | +-java.awt.Container | +-javax.swing.JComponent | +-javax.swing.text.JTextComponent | +-javax.swing.JTextArea | +-dbis.squiggle.ServerOutputArea public class ServerOutputArea extends javax.swing.JTextArea TextArea für ServerOuput von DBMS_OUTPUT Author: Mathis Dirksen-Thedens ([email protected]) Constructors ServerOutputArea public ServerOutputArea(java.lang.String content) Konstruktor für ServerOutputArea Parameters: content Inhalt des neuen Textfeldes Page 18 43 dbis.squiggle.SquiggleApplet dbis.squiggle Class SquiggleApplet java.lang.Object | +-java.awt.Component | +-java.awt.Container | +-java.awt.Panel | +-java.applet.Applet | +-javax.swing.JApplet | +-dbis.squiggle.SquiggleApplet All Implemented interfaces: java.awt.event.ActionListener, java.io.Serializable, java.awt.MenuContainer, java.awt.image.ImageObserver, javax.accessibility.Accessible, javax.swing.RootPaneContainer, javax.accessibility.Accessible public class SquiggleApplet extends javax.swing.JApplet implements javax.accessibility.Accessible, javax.swing.RootPaneContainer, javax.accessibility.Accessible , java.awt.image.ImageObserver, java.awt.MenuContainer, java.io.Serializable, java.awt.event.ActionListener Applet, welches SQuiggLe startet. Author: Mathis Dirksen-Thedens ([email protected]) Constructors SquiggleApplet public SquiggleApplet() Konstruktor fürs SquiggleApplet Methods actionPerformed public void actionPerformed(java.awt.event.ActionEvent e) Aktionsbehandlung Parameters: e Parameter init public void init() INIT des Applets Page 19 44 dbis.squiggle.SquiggleApplet start public void start() START des Applets stop public void stop() STOP des Applets paint public void paint(java.awt.Graphics g) Überschreibt die PAINT-Methode, um Rahmen und Text hinzuzufügen. Parameters: g Parameter Page 20 45 dbis.squiggle.TreePane dbis.squiggle Class TreePane java.lang.Object | +-java.awt.Component | +-java.awt.Container | +-javax.swing.JComponent | +-javax.swing.JSplitPane | +-dbis.squiggle.TreePane public class TreePane extends javax.swing.JSplitPane Klasse, um 1. einen Baum aus dbis.squiggle.Node-Objekten mit AWT/Swing darzustellen und 2. Informationen zu den Objekten anzuzeigen, die angeklickt werden. Author: Mathis Dirksen-Thedens ([email protected]) Constructors TreePane public TreePane(TreeView myTreeView) Konstruktor für TreePane Parameters: myTreeView TreeView-Objekt, das dargestellt werden soll Methods nodeClicked public void nodeClicked(Node clickedNode) Wird vom TreeView aus aufgerufen, um Infos anzuzeigen. Parameters: clickedNode die Node, um die es geht Page 22 46 dbis.squiggle.TreeView dbis.squiggle Class TreeView java.lang.Object | +-java.awt.Component | +-java.awt.Container | +-javax.swing.JComponent | +-javax.swing.JPanel | +-dbis.squiggle.TreeView All Implemented interfaces: java.awt.event.MouseListener, java.io.Serializable, java.awt.MenuContainer, java.awt.image.ImageObserver, java.io.Serializable, javax.accessibility.Accessible public class TreeView extends javax.swing.JPanel implements javax.accessibility.Accessible, java.io.Serializable, java.awt.image.ImageObserver, java.awt.MenuContainer, java.io.Serializable, java.awt.event.MouseListener Klasse, um einen Baum aus dbis.squiggle.Node-Objekten mit AWT/Swing darzustellen Author: Mathis Dirksen-Thedens ([email protected]) Constructors TreeView public TreeView(Node rootnode) Konstruktor für TreeView Parameters: rootnode Baum bzw. Rootnode des Baums Methods paintComponent public void paintComponent(java.awt.Graphics g) Linien zeichnen Parameters: g ein Graphics Objekt getRootNode public Node getRootNode() Holt die rootNode Page 23 47 dbis.squiggle.TreeView (continued from last page) Returns: die rootNode mouseClicked public void mouseClicked(java.awt.event.MouseEvent e) Interface-Implementierung Parameters: e ein MouseEvent mousePressed public void mousePressed(java.awt.event.MouseEvent e) Interface-Implementierung Parameters: e ein MouseEvent mouseReleased public void mouseReleased(java.awt.event.MouseEvent e) Interface-Implementierung Parameters: e ein MouseEvent mouseEntered public void mouseEntered(java.awt.event.MouseEvent e) Interface-Implementierung Parameters: e ein MouseEvent mouseExited public void mouseExited(java.awt.event.MouseEvent e) Interface-Implementierung Parameters: e ein MouseEvent setListener public void setListener(TreePane listener) Setzt den Listener Parameters: listener Neuer Wert von listener Page 24