1 Entwicklung einer interaktiven Ingenieuranwendung für die Bemessung von Industriehallen als plattformunabhängiger Web-Dienst Diplomarbeit vorgelegt von Rolf Alexander Schüler im Februar 2003 Ruhr-Universität Bochum Fakultät für Bauingenieurwesen 2 3 Inhaltsverzeichnis 0 Einleitung.........................................................................................................5 1 Analyse der vorliegenden Clientkomponente...................................................7 1.1 Grundlegende Bedienungsabläufe...........................................................7 1.2 Vorstellung der einzelnen Dialoge............................................................9 1.2.1 Menü „File“.........................................................................................9 1.2.2 Menü „General“................................................................................10 1.2.3 Menü „Loads“...................................................................................10 1.2.4 Menü „Main building“.......................................................................11 1.2.5 Menü „Annexes“...............................................................................12 1.2.6 Menü „Specifications“......................................................................13 1.2.7 Menü „Dimensioning“.......................................................................14 1.2.8 Menü „Register“...............................................................................14 1.2.9 Menü „Help“.....................................................................................15 1.3 Zusammenfassung..................................................................................15 2 Analyse der Serversoftware...........................................................................16 2.1 Anforderungen an die Clientkomponente...............................................16 2.2 Vorstellung der Serversoftware...............................................................17 2.3 Anwendungsentwicklung unter Lotus Notes/Domino..............................19 2.4 Domino Objects for Java.........................................................................19 2.5 Lokale und nicht lokale Java-Programme...............................................20 2.6 Applets unter Lotus Domino....................................................................21 2.7 Zugriff auf Domino Datenbanken mit Java-Programmen........................22 2.8 Zusammenfassung..................................................................................25 3 Entwurf der Clientkomponente als Applet......................................................26 3.1 Analyse...................................................................................................26 3.1.1 Verwaltung.......................................................................................27 Klasse DimFrame.................................................................................27 3.1.2 Kommunikation................................................................................27 Klasse EZApplet...................................................................................27 Agenten................................................................................................27 3.1.3 Benutzerschnittstelle........................................................................28 4 Dialoge.................................................................................................28 3.1.4 Hilfesystem......................................................................................28 JavaHelp...............................................................................................28 3.2 Modell......................................................................................................28 3.3 Programmierung......................................................................................29 3.3.1 Verwaltung.......................................................................................29 DimFrame - Temporäre Verwaltung der Eingabedaten........................29 3.3.2 Kommunikation - Anwendung von Domino Objects for Java...........30 EZApplet...............................................................................................30 Agents...................................................................................................31 3.3.3 Benutzerschnittstelle - Einsatz von Swing-Komponenten...............35 Textfelder..............................................................................................35 Tabellen................................................................................................42 Auswahlelemente.................................................................................49 Kontrollfelder....................................................................................49 Optionsfelder....................................................................................49 Auswahlmenüs.................................................................................50 Sortieren der Anbauten, Zwischengeschosse und Dachüberstände....51 3.3.4 Das Hilfesystem...............................................................................52 Einführung............................................................................................52 Aufbau des Hilfesystems......................................................................54 Einbindung des Hilfesystems in das Applet..........................................58 3.4 Zusammenfassung..................................................................................60 4 Fazit................................................................................................................61 5 Literaturverzeichnis........................................................................................63 5 0 Einleitung Aufgrund von immer stärkerem Konkurrenzdruck und dem sich daraus ergebendem Zwang Kosten bei der Planung und Errichtung von Bauwerken zu senken, erweisen sich Programme zur Strukturoptimierung immer größerer Beliebtheit. Ein weiterer Aspekt bei der Entwicklung einer solchen Anwendung, liegt in dem Wunsch vieler Kunden den Vorgang der Berechnung auszugliedern, um ihn dann von anderen als Dienstleistung in Anspruch zu nehmen. Da die Rechenkapazität der Computer vieler Kunden in Osteuropa für diese Berechnungen nicht ausreicht, bietet ihnen diese Vorgehensweise den besonderen Vorteil, rechenintensive Anwendungen auf leistungsfähigeren Computern des Softwareanbieters ausführen zu lassen. Ein solches Programm stellt Dr. Galffy dem Lehrstuhl für Ingenieurinformatik im Bauwesen an der Ruhr-Universität Bochum zur Verfügung. Mit dieser ClientServer-Anwendung „Dimensioning V. 1.01“ lassen sich Industriehallen in Stahlbauweise interaktiv modellieren, berechnen und nach EC 3 bemessen. Die für die Dimensionierung zuständige Komponente der zweigeteilten Anwendung läuft auf der Serverseite und soll an dieser Stelle nicht genauer untersucht werden. Die unter dem Betriebssystem Microsoft Windows zu installierende Clientkomponente Benutzeroberfläche zur stellt dem Anwender Verfügung, über die er die eine graphische entsprechenden Projektdaten eingeben kann. Die gesamte Kommunikation zwischen Client und Server erfolgt bisher in Form von E-mail-Anhängen unter Nutzung des Protokolls SMTP. Die Projektdaten werden auf der Serverseite manuell der 6 Dimensionierungssoftware zugeführt und von dieser ausgewertet. Um diesen Prozess zu beschleunigen und die Anwendung auf verschieden Möglichkeit bereitzustellen, diese Betriebssystemen auszuführen, soll die Clientkomponente grundlegend umstrukturiert und als Java-Applet realisiert werden. Dabei soll die vorhandene Anbindung an den Server durch ein geeignetes Übertragungsprotokoll ersetzt werden. In Kapitel eins erfolgt eine Einführung in die Architektur der vorliegenden Anwendung und eine Analyse der Clientkomponente. Kapitel zwei stellt Möglichkeiten vor, wie ein Java-Applet mit der auf dem Server eingesetzten Software Lotus Domino kommunizieren kann und welche Einschränkungen dabei zu beachten sind. Die detailierte Umsetzung der neu entwickelten Clientkomponente wird in Kapitel drei vorgestellt. Eine Bewertung dieser Arbeit und einen Ausblick über mögliche Ergänzungen findet der Leser in Kapitel vier. 7 1 Analyse der vorliegenden Clientkomponente Im ersten Abschnitt des vorliegenden Kapitels wird der Einsatzbereich der Anwendung „Dimensioning V 1.01“ und das eingesetzte Bemessungsverfahren vorgestellt. Der Leser bekommt hier einen Einblick in die Installationsvorgang und die grundlegenden Bedienungsabläufe. Auch der Registrierungsprozess und die Kommunikation zwischen Client und Server werden in diesem Abschnitt analysiert. Der zweite Abschnitt dieses Kapitels behandelt dann die einzelnen Menüpunkte dieser Anwendung. 1.1 Grundlegende Bedienungsabläufe Wie eingangs bereits erwähnt, handelt es sich bei „Dimensioning V. 1.01“ um eine Client-Server-Anwendung, die der Dimensionierung von Industriehallen in Stahlbauweise nach der europäischen Stahlbau-Normung Eurocode 3 dient. Bestehen können die Stahlhallen dabei aus mehrereren Modulen mit Zwischengeschossen und Nebengebäuden. Abbildung 1 zeigt als mögliches Beispiel eine Industriehalle, die sich in der Breite über ein Modul erstreckt. Sie verfügt über ein Zwischengeschoß in der Mitte der Halle und zwei Nebengebäude an der vorderen und der rechten Seite. Die Serverkomponente führt die statische Berechnung am räumlichen System nach Theorie I. Ordnung durch. In die Berechnung der Profilausnutzung fließen neben der Normal- und der Schubspannung auch Biegeknicken und Biegedrillknicken des Primärtragwerkes ein. Ebenfalls berücksichtigt wird die Stabilität der Tragrahmen gegen Knicken in der eigenen Ebene. Zu den eingegebenen Lasten fügt das Programm automatisch die Eigengewichte von 8 Stahlkonstruktion und Dacheindeckung hinzu. Für das Primärtragwerk ist zwischen Walzprofilen mit versteiften Rahmenecken nach dem LindabVerfahren oder geschweißten I-Profilen nach Butler oder Astron zu wählen. Das Sekundärtragwerk besteht immer aus Z-Profilen. Beiden Strukturen gemeinsam sind die eingesetzten Werkstoffe. Hier kann der Anwender zwischen Fe 360 und Fe 510 wählen. Abbildung 1Prinzipielle Struktur einer Stahlhalle Die in der Programmiersprache C entwickelte Clientkomponente muß einmalig von einer Webseite des Softwareanbieters heruntergeladen und unter dem Betriebssystem Microsoft Windows installiert werden. Nach dem Starten des Programmes durch die ausführbare Datei dimensn.exe erscheint auf dem Bildschirm ein Anwendungsfenster mit einer Menüzeile am oberen Rand. Unterhalb dieser Menüzeile befindet sich ein Anzeigebereich, in dem die zu bemessende Industriehalle dreidimensional dargestellt werden kann. Über eine Vielzahl von Menüeinträgen gelangt man zu Dialogfenstern, in denen der Benutzer die entsprechenden Projektdaten eingeben kann. In der Regel stellen diese Dialogfenster jeweils einen „Ok“- und einen „Cancel“-Knopf zur Verfügung. Bei der Betätigung des „Ok“-Knopfes übernimmt das Programm Änderungen an den Eingabewerten und das Dialogfenster wird geschlossen. Wählt der Benutzer den „Cancel“-Knopf, wird das Dialogfenster ebenfalls geschlossen und das Programm rechnet mit den ursprünglichen Daten weiter. Eventuelle Änderungen an den Eingabewerten gehen in diesem Fall verloren. 9 Bevor die ersten Berechnungen ausgeführt werden können, muß die Clientkomponente bei dem Softwareanbieter registriert werden. Nach der Installation der Anwendung füllt der Kunde ein mitgeliefertes Registrierungsformular mit einem einfachen Texteditor aus und sendet dieses durch Anwahl des Menüpunktes „Send registration form“ als E-mail-Anhang zurück an den Hersteller. Daraufhin erhält der Anwender eine E-mail mit der erforderlichen Seriennummer, die mit einem separaten E-mail-Programm zu öffnen ist. Die Seriennummer ist über die Anwahl des Menüeintrages „Send serial number“ wiederum an den Hersteller zu senden. Als Bestätigung für die erfolgte Freischaltung der Dimensionierungssoftware erhält der Benutzer dann eine weitere E-mail. Der Versand der Dateien in Form eines E-mail-Anhanges erfolgt für den Benutzer im Verborgenen mit dem Übertragungsprotokoll SMTP (Simple Mail Transfer Protocol). Da bislang weder der E-mail-Eingang noch der E-mail-Ausgang auf der Serverseite automatisiert ablaufen, die ein- und ausgehenden E-mails also manuell von Mitarbeitern des Softwareanbieters bearbeitet werden, ist der Kunde auf dessen Bürozeiten angewiesen. 1.2 Vorstellung der einzelnen Dialoge 1.2.1 Menü „File“ Dieses Menü umfasst die üblichen Befehle zum Umgang mit der Projektdatei. Möchte der Anwender über den Menüeintrag „New project“ ein neues Projekt öffnen, wird automatisch zunächst das vorher geöffnete Projekt gespeichert und beendet. Sofern dem neuen Projekt kein individueller Dateiname gegeben wird, weist das Programm dem Projekt den Standarddateinamen project0 zu. Alle Projektdateien erhalten die Dateiendung .prj. Bereits vorhandene Projektdateien, die sich auf dem lokalen Dateisystem des Client-Rechners befinden, kann der Benutzer über den Menüeintrag „Open project“ öffnen. Das aktuelle Projekt wird durch Anwahl der Option „Save project“ unter dem aktuellen Dateinamen oder der Option „Save project as“ unter einem anderen Dateinamen ebenfalls auf dem lokalen Dateisystem gespeichert. Über den Menüeintrag „Plot“ lässt sich die im Anzeigebereich dargestellte Industriehalle 10 auf ein Blatt im DIN A4-Format drucken. Beendet wird das gesamte Programm durch Anwahl von „Quit“. Ist eventuell noch ein Projekt geöffnet, wird diese nach Rückfrage in diesem Zuge abgespeichert. 1.2.2 Menü „General“ Hier findet der Anwender die Menüeinträge „Project“ und „Materials“. Bei Anwahl des Eintrages „Project“ öffnet sich ein Dialogfenster, in dem allgemeine Projektdaten einzugeben sind. Darunter fallen zum Beispiel Angaben wie Datum, Name und Lage des zu errichtenden Projektes und dessen Aktenzeichen. Um eine Optimierung des Bauwerks hinsichtlich der Materialkosten zu Abbildung 2Dialogfenster "Materials' list" ermöglichen, kann der Benutzer unter dem Menüpunkt „Materials“ Preise für die Baustoffe der primären und sekundären Tragwerksstruktur, sowie der Dach- und Wandpaneele eintragen. Die Listen für Dach- und Wandpaneele können um zusätzliche Einträge ergänzt werden. Bei Bedarf können auch vorhandene Materialien aus den Listen entfernt werden. 1.2.3 Menü „Loads“ Bei Anwahl des Menüs „Loads“ erscheint ein Dialogfenster, in das die anzunehmenden Schnee-, Wind- und Gebrauchslasten einzugeben sind. Außerdem ist dort die maximale Temperaturschwankung bezogen auf die 11 Aufstelltemperatur anzugeben. 1.2.4 Menü „Main building“ Die Länge, Breite und Höhe des Hauptgebäudes, sowie dessen Dachneigung gibt der Anwender in dem Dialogfenster ein, das sich hinter diesem Menü verbirgt. Abbildung 3 erläutert anhand einer Hallendraufsicht die charakteristischen Abmessungen. Abbildung 3Erläuterung der Abmessungen Nach Eingabe der gewünschten Anzahl an Feldern und Modulen, errechnet das Programm automatisch die arithmetisch gemittelte Feldlänge bzw. Modulbreite. Wünscht der Anwender jedoch individuelle Feldlängen oder Modulbreiten, so muß er die entsprechende „Equal frame/col. spacing“Checkbox abwählen und gelangt nach Betätigung des „Lengths“- oder „Widths“-Knopfes zu einem weiteren Dialogfenster, in dem er die passenden Werte eingeben kann. 12 Abbildung 4Dialogfenster "Bay lengths" Die Giebelwandstützen werden immer gleichmäßig über die Modulbreite verteilt. Gibt der Anwender einen minimalen und einen maximalen Abstand der Stützen ein, versucht das Programm die Stützenanzahl zu errechnen. Sollte es nicht möglich sein, die Stützenanzahl anhand der eingegeben Werte zu berechnen, paßt die Anwendung das vorgegebene Intervall automatisch an. Die Höhe des Gebäudes wird über die Eingabe der Traufhöhe oder der lichten Höhe definiert. Die Dachneigung kann als Steigungsverhältnis oder alternativ in Dezimalgrad angegeben werden. Zudem ist auszuwählen, ob es sich bei der Dachform um ein Satteldach oder um ein Pultdach mit nach links oder nach rechts geneigter Dachfläche handelt. 1.2.5 Menü „Annexes“ In diesem Menü sind alle Dialoge zusammengefaßt, die zur Definition der Nebengebäude nötig sind. Die Anwendung unterstützt derzeit die Möglichkeit bis zu neun Nebengebäude zu definieren. Für jedes dieser Nebengebäude steht ein Menüeintrag der Art „No.1“ bereit. Standardmäßig steht zunächst nur die Option „No. 1“ für das erste Nebengebäude zur Verfügung, egal ob der Anwender ein Nebengebäude erstellt oder nicht. Wählt er diesen Menüpunkt an, öffnet sich ein neues Dialogfenster. Dort kann der Benutzer durch anklicken der „Yes“- oder „No“-Option entscheiden, ob er ein Nebengebäude definieren möchte. Entscheidet er sich für „Yes“, kann er mit der Eingabe der Abmessungen und der Lage des Nebengebäudes beginnen. Solange die 13 zulässige Anzahl an Nebengebäuden noch nicht erreicht ist, erscheint nach Bestätigung der Eingabewerte des letzten Nebengebäudes mit „Ok“ ein neuer Menüeintrag (z.B. „No. 2“) für ein weiteres Nebengebäude. Der Menüeintrag „List all“ führt zu einem Dialogfenster, in dem die Parameter aller existierenden Nebengebäude aufgelistet werden. 1.2.6 Menü „Specifications“ Wenn die grundlegende Hallenstruktur definiert wurde, kann der Benutzer in diesem Menü zusätzliche Details und Ausstattungsmerkmale der Halle eingeben. Unter dem Menüeintrag „Structural system“ können im dazugehörigen Dialogfenster genauere Angaben zur primären und sekundären Struktur gemacht werden. Darunter fallen unter anderem die Art der Ausführung der Stützenfußpunkte, die Ausbildungsform der Rahmenecken, die Berücksichtigung zukünftiger Hallenverlängerungen an den Giebelseiten und die Auswahl des grundlegenden Materials für die jeweilige Struktur. Die Eingabe von Zwischengeschossen erfolgt unter der Option „1st Mezzanine“. Dazu sind Angaben über die Abmessungen, die Position innerhalb der Halle und die zu erwartenden Lasten zu machen. Das Verhalten dieser Menüeinträge entspricht weitgehend dem Verhalten der Menüeinträge der Nebengebäude. Abbildung 5Dialogfenster "Crane" Sollen in der Halle Krane installiert werden, kann der Anwender unter dem 14 Menüpunkt „Crane“ deren Position und Kapazität sowie den Krantyp spezifizieren. Die intern und extern einzusetzenden Paneltypen für Dach und Wand sind in „Roof system“ beziehungsweise „Wall system“ auszuwählen. Nach Anwahl von „Roof/wall accessories“ erscheint ein Dialogfenster, in dem die Lage der Dachrinnen, die Beschaffenheit der Fallrohre und die durchschnittliche Niederschlagsmenge einzugeben sind. Über den Menüeintrag „Canopies/Overhangs“ gelangt der Benutzer zu einem Untermenü mit den Optionen „No.1“ und „List all“. Unter „List all“ zeigt das Programm die Auflistung der Parameter aller bislang eingegeben Dachüberstände. Nach Anwahl des Menüpunktes „No. 1“ erscheint ein Dialogfenster, welches dem Anwender die Möglichkeit gibt, die individuellen Angaben zum ersten Dachüberstand einzutragen. Bestätigt er seine Eingabe, so wird dem Untermenü „Canopies/Overhangs“ ein weiterer Menüeintrag („No. 2“) hinzugefügt. Dieses Menüverhalten wird wie bei den Nebengebäuden bis zum Erreichen des Menüeintrages „No. 9“ beibehalten. 1.2.7 Menü „Dimensioning“ Nach der Eingabe aller erforderlichen Hallenparameter kann sich der Anwender unter dem Menüpunkt „View input“ noch einmal die Eingabewerte zusammengefaßt anzeigen lassen. Stimmen diese Werte mit seinen Vorstellungen überein, kann er die Projektdatei mit der Anwahl von „Send data“ an den Server des Softwareanbieters übertragen. Dort beginnt der Dimensionierungsprozess. Nach der Berechnung werden die Ergebnisse dem Benutzer per E-mail-Anhang zugestellt, die er sich dann nach Abspeichern der angehängten Datei im Arbeitsverzeichnis unter dem Menüeintrag „View results“ betrachten kann. 1.2.8 Menü „Register“ Dieses Menü stellt alle Optionen bereit, die für den Registrierungsvorgang benötigt werden. Durch Anwählen des Menüeintrages „Send registration form“ wird das Formular Register.txt, welches zuvor vom Benutzer mit einem herkömmlichen Editor ausgefüllt werden muß, automatisch an den Software- 15 anbieter übertragen. Per e-mail erhält der Kunde seine Seriennummer zugesandt, die er unter dem Menüpunkt „Send serial number“ eingeben und an den Softwareanbieter übermitteln muß, um für die Bemessung von Industriehallen freigeschaltet zu werden. 1.2.9 Menü „Help“ Hat ein Anwender Fragen zur Bedienung und Funktionsweise dieses Programmes, so findet er unter dem Menüeintrag „Help“ die passende Antwort. Der Menüpunkt „About“ zeigt Informationen über den Anbieter dieser Software und die aktuelle Versionsnummer an. 1.3 Zusammenfassung Die Analyse der Clientkomponente hat noch einmal aufgezeigt, daß die dringende Notwendigkeit besteht, den Kommunikationsprozess zwischen Client und Server und damit einhergehend auch die Verfügbarkeit der gesamten Anwendung grundlegend zu überarbeiten. Das Ziel einer solchen Überarbeitung sollte vor allem eine Automatisierung des Datenaustausches mit sich bringen. Ein weiteres Ziel ist die Plattformunabhängigkeit der Clientkomponente, um somit einen größeren Kundenkreis erschließen zu können. 16 2 Analyse der Serversoftware Im vorliegenden Kapitel wird zunächst einmal auf die Anforderungen an die künftige Clientkomponente eingegangen, bevor dann untersucht wird in welcher Umgebung die neu zu realisierende Clientkomponente eingesetzt werden soll. Besonderes Interesse gilt dabei dem Datenaustausch zwischen Clientkomponente und Serverkomponente und den dabei eingesetzten Übertragungsverfahren. Dazu wird eine grundlegende Analyse der Serversoftware durchgeführt und das eingesetzte Datenbankmodell vorgestellt. Abschließend werden mögliche Schnittstellen dieser Datenbank zu JavaProgrammen untersucht. 2.1 Anforderungen an die Clientkomponente Die künftige Clientkomponente soll als Web-Dienst in einer HTML-basierten Umgebung ablauffähig sein, um somit eine höhere Verfügbarkeit und zugleich eine größere Plattformunabhängigkeit als bisher zu gewährleisten. Durch eine Ausführung der Clientkomponente als Java-Applet erhofft sich der Softwareanbieter durch die Vermarktung von Anzeigenflächen auf der gleichen Webseite die Erschließung zusätzlicher Einnahmequellen. Zudem soll die Clientkomponente die bekannten Eingabemasken für die Projektdaten bereitstellen und eine graphische Darstellung der Industriehalle ermöglichen. Das zu entwickelnde Java-Programm soll ferner die Projektdaten in eine Datenbank stellen und den Dimensionierungsprozess starten. Die Serverkomponente der Anwendung liest dann die Projektdaten aus der Datenbank ein, führt die Berechnung durch und schreibt die Ergebnisse 17 ebenfalls in diese Datenbank. Es wird im folgenden untersucht, welche Software für die Bereitstellung von Datenbanken und Webseiten auf dem Server eingesetzt wird und welche Möglichkeiten diese bietet, das zuvor geschilderte Szenario zu realisieren. 2.2 Vorstellung der Serversoftware Der Softwareanbieter setzt Lotus Domino in der Version R5 als Web- und Datenbankserver ein. Die Software Lotus Notes/Domino hat ihren Ursprung in einem Programm namens PLATO Notes, das in den frühen neunzehnhundertsiebziger Jahren an der Universität von Illinois am Computerbased Education Research Laboratory (CERL) entwickelt worden ist, um Fehlerberichte zu verwalten. Inzwischen ist die Kombination aus Lotus Notes als Clientkomponente und Lotus Domino als Serverkomponente zu einem umfangreichen Groupware-System herangewachsen, dessen Aufagbe im wesentlichen darin besteht, in einem Team arbeitende Personen bei ihrer elektronischen Kommunikation, Kooperation und Koordination zu unterstützen. 18 Abbildung 6Konnektoren des Domino Application Servers, aus [EH2003] Die hier eingesetzten Varianten Domino Application Server oder Domino Enterprise Server verfügen im Gegensatz zu der einfacheren Variante Domino Mail Server mit dem Entwicklungsumgebung zur Domino Designer Erstellung von über Domino eine integrierte Anwendungen. Desweiteren stellen sie Werkzeuge zur Anbindung externer Datenbanken bereit. Abbildung 6 zeigt auf, welche Schnittstellen und Bindeglieder bei einem Webzugriff auf eine Datenbank zum Einsatz kommen. Für den Zugriff auf Domino Anwendungen und andere Datenbanken stellt Lotus den Notes Client bereit. Dieser bietet in etwa dieselben Funktionen wie das allseits bekannte Microsoft Outlook, erweitert um Funktionen zur Navigation in Datenbanken und zur Darstellung von deren Inhalten. Durch die Integration von CORBA (Common Object Request Broker Architecture) und IIOP (Internet Inter-ORB Protocol) in den Domino Server können Zugriffe auf Domino Anwendungen und externe Datenbanken auch mit einem herkömmlichen Webbrowser erfolgen. Beide Klienten greifen dabei auf die gleiche Struktur einer Datenbank zurück und unterscheiden sich im Bezug 19 auf die Darstellung nur in einigen optischen Feinheiten. Da beide Klienten den gleichen Funktionsumfang aufweisen, soll im folgenden der Einsatz eines Webbrowsers genauer betrachtet werden. Der Notes Client hingegen wird aufgrund seiner geringen Verbreitung nicht näher untersucht. 20 2.3 Anwendungsentwicklung unter Lotus Notes/Domino Spricht man im Zusammenhang von Lotus Domino über Anwendungen, bezeichnet man damit in der Regel Domino Datenbanken. Diese an der Endung *.nsf (Notes Storage Facility) zu erkennenden Dateien enthalten die Daten und Gestaltungselemente sowie die Zugriffsverwaltung und Programmlogik der Domino Anwendung. Desweiteren enthält eine Domino Datenbank die im Laufe ihrer Nutzung entstandenen Dokumente welche ebenfalls durch Gestaltungselemente gegliedert werden. Abbildung 7 stellt diesen Aufbau noch einmal anschaulich dar. Unter Gestaltungselementen versteht man unter anderem Seiten (Pages), Masken (Forms) und Ansichten (Views). Abbildung 7Aufbau einer Domino Datenbank, aus [DTJava] 2.4 Domino Objects for Java Für den Zugriff mit Java-Programmen auf Domino-Daten, Domino-Dienste oder auch auf Daten in Datenbank-Management-Systemen anderer Anbieter stellt Lotus die „Domino Objects For Java“ bereit. Diese Hilfsklassen stellen Methoden zur Darstellung und Manipulation von Domino-Daten zur Verfügung. 21 Die Klassen-Architektur der Domino Objects baut auf einem Container- oder auch Behälter-Modell auf. Das bedeutet, daß ein Domino Object in der Regel weitere Domino Objects enthält und für den Zugriff auf diese genutzt werden kann. Oft kann ein Domino Object auch untergeordnete Objekte erzeugen. Abbildung 8 zeigt die wichtigsten Beziehungen zwischen den Domino Objects auf. Abbildung 8Beziehungen zwischen den Domino Objects Alle Container-Objekte die Inhalt eines übergeordneten Objektes sind werden automatisch geschlossen, wenn das übergeordnete Objekt geschlossen wird, oder es seinen Geltungsbereich verliert. Um Datenverlusten vorzubeugen sollten zum Beispiel Änderungen an Dokumenten möglichst sofort gespeichert werden, bevor die übergeordnete Datenbank geschlossen wird. 22 2.5 Lokale und nicht lokale Java-Programme Verfügt ein Anwender nicht über einen Notes Client, ermöglichen ihm nicht lokale Java-Programme den Zugriff auf Daten und Dienste, die auf einem Domino Server abgelegt sind. Als nicht lokale oder in der Ferne ausgeführte (remote) Java-Programme bezeichnet man Java-Programme, die in einer Umgebung ausgeführt werden, in der weder ein Notes Client noch ein Domino Server installiert sind. Lokale Java-Programme bieten denselben Funktionsumfang wie nicht lokale, sind aber auf die Zugang zu einer Notesoder Domino-Installation am Ort ihrer Ausführung angewiesen. Wenn ein Java-Programm nicht lokal ausgeführt wird, kommen zwei Arten von Domino Objects zum Einsatz. Auf der Client-Seite agieren stellvertretende Domino Objects, sogenannte „Stubs“, die sich aus der Sicht des JavaProgrammes wie echte Domino Objects verhalten. Sie dienen jedoch nur der Kommunikation mit dem Server. Dort befinden sich die echten Domino Objects, die die Aufträge der Stellvertreter annehmen und in der gewohnten Umgebung auf dem Domino Server ausführen. Da Domino Objects auf der Grundlage der Common Object Request Broker Architecture (CORBA) entwickelt wurden, können die stellvertretenden Objekte über eine vorhandene TCP/IP Verbindung mit dem Domino Server unter Nutzung des Internet Inter-ORB Protocol (IIOP) kommunizieren. Läuft ein Java-Programm dagegen lokal ab, also auf einem Rechner mit direktem Zugriff auf einen Notes Client oder Domino Server, entfällt diese Verbinung. Zur Kommuniktation mit anderen Servern nutzt das Programm dann die üblichen Notes/Domino-Mechanismen. In nahezu allen Beziehungen verhalten sich die stellvertretenden Objekte eines nicht lokal ausgeführten Programmes wie die echten Objekte von lokal ausgeführten Programmen. Daher kann man in beiden Fällen bis auf einige wenige Ausnahmen den gleichen Code einsetzen. 2.6 Applets unter Lotus Domino Bei der Entwicklung von Applets für den Einsatz unter Lotus Domino sind eine 23 ganze Reihe von Besonderheiten zu beachten. Im Gegensatz zu den bekannten, von Sun Microsystems entwickelten Applets leitet man sie nicht aus der Superklasse Applet sondern aus der Superklasse AppletBase ab. Die Methoden notesAppletInit, notesAppletStart und notesAppletStop ersetzen die sonst während des Lebenszyklus eines Applets aufgerufenen Methoden init, start und stop. Wie bereits erwähnt, muß für einen großen Teil des Applet-Codes nicht zwischen lokalem und nicht lokalem Zugriff auf eine Domino Datenbank unterschieden werden. Läuft das Applet in einem Notes Client, tätigt AppletBase lokale Aufrufe, läuft es hingegen nicht lokal in einem Webbrowser, so vollzieht AppletBase über das standardisierte Protokoll IIOP Aufrufe an den Domino Server, von dem das Applet geladen wurde. Zum Vergleich: Eigenständige Java-Anwendungen erzeugen lokale Aufrufe, wenn die Bibliothek Notes.jar in ihren Klassenpfad aufgenommen worden ist und sie Zugriff auf den Notes Client haben. Beinhaltet der Klassenpfad die Bibliotheken NCSO.jar oder NCSOC.jar und besteht kein Zugang zu einem Notes Client, so erfolgen nicht lokale Aufrufe an den Server ebenfalls unter Nutzung von IIOP. Die soeben erwähnten Bibliotheken kann der Entwickler entweder dem Installationsverzeichnis eines Domino Servers oder dem Lotus Domino Toolkit for Java/CORBA entnehmen. 2.7 Zugriff auf Domino Datenbanken mit Java-Programmen Für den Zugriff auf Domino Datenbanken eignen sich vier grundlegende Arten von Java-Programmen: Agenten – Spezielle Entwicklungsumgebung Domino „Domino Programme, Designer“ die erzeugt mit und der in Lotus Domino- Datenbanken gespeichert werden. Sie können als Anwort auf spezielle Ereignisse, von einem vorgegeben Zeitplan oder manuell aufgerufen werden und führen dann vordefinierte Aktionen, sogenannte @function formulas, LotusScript, oder Java Anweisungen auf einem Notes-Client oder einem Domino-Server aus. Anwendungen - Eigenständige Java Programme, die über die Kommandozeile 24 oder in einer integrierten Java Entwicklungsumgebung ausgeführt werden. Die einzige Systemvoraussetzung für diese Anwendungen ist die Installation einer Java Runtime Environment (JRE). Ebenso wie die anderen hier vorgestellten Java Programme, können diese Anwendungen auf Daten und Dienste von Domino zugreifen. Applets – Diese Art von Java Programmen stellt in der Regel eine graphische Benutzungsoberfläche zur Verfügung. Sie werden von einem Webserver heruntergeladen und werden in der Regel in einer von dem Webbrowser bereitgestellten Java-Laufzeitumgebung auf dem Computer des Benutzers ausgeführt. Im bezug auf die Domino-Umgebung ist es ebenso möglich, die Applets in einer Notes-Datenbank abzulegen und sie in einem Notes-Client auszuführen. Servlets – Auf dem Webserver ausgeführte Java Programme, die in der Regel von einem Webbrowser gestartet werden und anschließend Daten auf HTMLSeiten in diesem anzeigen. Ähnlich wie Applets werden Servlets ausgeführt, wenn ein Benutzer eine URL in einem Webbrowser eingibt oder auf einer HTML-Seite einen entsprechenden Link anklickt. Im Gegensatz zu Applets, deren Code vom Server auf den Client-Rechner heruntergeladen und dort ausgeführt wird, verbleiben die Servlets auf dem Server und werden auch dort ausgeführt. Die Anforderungen an die zu entwickelnde Clientkomponente können Servlets nicht erfüllen, da ihnen die notwendigen Fähigkeiten zur graphischen Darstellung der Industriehalle fehlen. Agenten können allenfalls als Hilfsprogramme für den direkten Datenbankzugriff eingesetzt werden. Im folgenden sollen nun die Eignung von Applets und Anwendungen sowie deren Voraussetzungen genauer untersucht werden. Nach Krüger [GK2002] unterscheiden sich Applets und Anwendungen nur in wenigen Bereichen voneinander. Ein Applet muß demnach aus der Klasse Applet bzw. JApplet abgeleitet werden. Durch den Aufruf der Methoden init und start führt dann ein Webbrowser das Applet aus. Die Anwendung 25 kann aus nahezu jeder beliebigen Hauptklasse abgeleitet werden. Gestartet wird sie durch den Aufruf der Methode main vom Java-Interpreter. Horstmann und Cornell [HOCO2001] stellen dazu folgendes Vererbungsdiagramm bereit: Abbildung 9Vererbungsdiagramm für Applets Den größten Unterschied zwischen Anwendungen und Applets stellen ohne Zweifel die Sicherheitsrestriktionen der Applets dar. Die Java Virtual Machine (JVM) untersagt Applets das Ausführen von lokalen Programmen und gewährt ihnen im lokalen Dateisystem weder Lese- noch Schreibzugriffsrechte. Von dem lokalen Computer erhalten Applets lediglich Informationen über die verwendete Java-Version, den Namen und die Version des Betriebssystems und Informationen über die dort verwendeten Trennzeichen für Dateien, Pfade und Zeilen. Applets können zudem ausschließlich mit dem Host-Server kommunizieren, von dem sie heruntergeladen wurden. Alle vom Applet erzeugten Popup-Fenster erhalten einen zusätzlichen Rahmen mit einer Warnmeldung, die den Benutzer davon in Kenntnis setzt, daß es sich bei dem 26 Fenster um ein Applet und nicht etwa um ein lokal installiertes Programm handelt. Die Lese- und Schreibzugriffsrechte auf das lokale Dateisystem des ClientRechners werden für die zu implementierende Clientkomponente nicht zwangsläufig benötigt, da die Projektdaten in der Domino Datenbank auf dem Server gespeichert werden können. Bei der Umsetzung der Clientkomponente als Anwendung hätte der Benutzer allerdings wie bisher die Möglichkeit die Projektdaten auch lokal abzuspeichern. Für die graphische Darstellung der Industriehalle soll unter anderem die Klassenbibliothek umfangreicheren Swing und eingesetzt komfortableren werden, Satz von die einen wesentlich Komponenten für die Benutzeroberfläche bereitstellt, als die Klassenbibliothek AWT. Voraussetzung für die Nutzung von Swing ist eine Java-Laufzeitumgebung der Java-Version 1.1 oder höher, dem AWT hingegen genügt die Java-Version 1.0. Ältere und auch einige neuere Browser unterstützen mit der browsereigenen JavaLaufzeitumgebung allerdings in vollem Umfang nur die Java-Version 1.0 und nur in Teilen die Java-Version 1.1, die für den Einsatz von SwingKomponenten benötigt wird. Ein sogenanntes „Java Plug-In“ von Sun stellt nahezu allen aktuellen Browsern eine externe Java-Laufzeitumgebung zur Verfügung, mit deren Hilfe Java-Applets ausgeführt werden können. Für die einmalige Installation dieses Plug-Ins sind allerdings Administratorrechte auf dem Client-Rechner nötig. Wenn man bedenkt, daß auch für eine Anwendung eine Java-Laufzeitumgebung mit aktueller JavaVersion installiert werden muß, sollte diese Einschränkung allerdings keine allzu große Hürde darstellen. 2.8 Zusammenfassung Ein Lotus Domino Application Server erweist sich aufgrund seiner umfangreichen Einsatzmöglichkeiten für diesen Zweck als besonders geeignet. Er ist in der Lage Webseiten bereit zu stellen und verfügt über ein Datenbanksystem. Über die integrierten Java-Schnittstellen kann man entweder mit einem Applet oder einer Anwendung auf diese Datenbank zugreifen. Durch den 27 Einsatz eines Domino Servers kann der Kommunikationsprozess beschleunigt und komfortabler gestaltet werden. Gelingt es dann noch, die für die Dimensionierung zuständige Serverkomponente vom Applet aus zu starten, so kann diese Anwendung rund um die Uhr zur Verfügung gestellt werden. 28 3 Entwurf der Clientkomponente als Applet Im ersten Abschnitt dieses Kapitels wird eine objektorientierte Analyse der Problemstellung durchgeführt. Der zweite Teil des Kapitels stellt das daraus entwickelte Gesamtmodell der Clientkomponente vor. Bevor dann im letzten Abschnitt die Umsetzung dieses Modells in der objektorientierten Programmiersprache Java anhand von einigen detailierten Beispielen zum Einsatz von Agenten und Swing-Komponenten aufgezeigt wird. Zum Abschluß dieses Kapitels wird der Leser in die Erstellung eines Hilfesystems und dessen Einbindung in das Applet eingeführt. 3.1 Analyse Ziel dieser Arbeit ist die Entwicklung einer Clientkomponente zur Erfassung der Projektdaten einer Industriehalle in Stahlbauweise. Die Clientkomponente soll als Java-Applet ausgeführt werden und die Projektdaten in einer Datenbank auf einem Lotus Domino Server ablegen. Daraus ergibt sich eine Gliederung der Aufgabenstellung in vier Teilbereiche. Die zentrale Verwaltung der Eingabedaten beschreibt den ersten Teilbereich. Der zweite Abschnitt widmet sich der Kommunikation zwischen der Clientkomponente und dem Domino Server. Als drittes ist eine Benutzerschnittstelle zur Eingabe der Projektdaten bereitzustellen, um das Hallenmodell definieren zu können. Abschließend soll noch ein Hilfesystem eingebunden werden, Funktionsweise der Anwendung zu erläutern. um dem Benutzer die 29 3.1.1 Verwaltung Klasse DimFrame Die Klasse DimFrame bildet das Kernstück der Clientkomponente. Sie dient als Schnittstelle zwischen den Benutzereingaben und dem Versand der Projektdaten an den Domino Server und stellt zu diesem Zweck einen zentralen Zwischenspeicher zur Verfügung. Des weiteren ermöglicht sie die Einbindung eines weitgehend eigenständigen Hilfesystems. Sie beinhaltet demnach Referenzen zu Kommunikationselementen, zu den Benutzerschnittstellen und zum Hilfesystem. 3.1.2 Kommunikation Klasse EZApplet Nach dem Aufruf der Webseite, in welcher diese Clientkomponente eingebunden ist, erzeugt die Klasse EZApplet ein Objekt der Klasse DimFrame und initialisiert dieses. Sie besitz folglich eine Beziehung zu der Klasse DimFrame. Zudem öffnet und schließt sie die Sitzung mit dem Domino Server. Ersetzt man diese Klasse durch eine Klasse mit einer main-Methode, kann man ohne weiteres dieses Applet in eine Anwendung umwandeln. Agenten Für den direkten Zugriff auf Domino Datenbanken empfiehlt Lotus den Einsatz von Agenten. Dazu sind in einer ersten Gruppe zwei Agenten für das Öffnen und Speichern der Projektdaten in der Datenbank vorzusehen. Die Klasse OpenDocumentAgent liest die Daten eines bereits existierenden Projektes aus der Datenbank und schreibt sie in den zentralen Zwischenspeicher. Die Klasse SaveAsDocumentAgent beschreitet genau den entgegengesetzten Weg. Sie liest die Projektdaten aus dem zentralen Zwischenspeicher und schreibt sie anschließend in die Domino Datenbank. In einer zweiten Gruppe dienen zwei Agenten zur Darstellung der Eingabebeziehungsweise Ergebnisdaten. Die Klasse ShowInputAgent liest dazu die aktuellen Projektdaten aus dem zentralen Zwischenspeicher und zeigt diese in einem separaten Browserfenster an. Die Klasse ShowResultsAgent öffnet 30 ein entsprechendes Ergebnisdokument in der Datenbank und zeigt dessen Inhalt ebenfalls in einem separaten Browserfenster an. Zusätzlich zu diesen beiden Gruppen wird die Klasse RunEngineAgent benötigt, um den Dimensionierungsprozess zu starten. 3.1.3 Benutzerschnittstelle Dialoge Zur Eingabe der Projektdaten werden viele, relativ unterschiedliche Dialoge benötigt. Sie wurden bereits in Kapitel eins näher vorgestellt. Ihre Gemeinsamkeiten bestehen darin, daß sie bei der Klasse DimFrame angemeldet werden können, bei ihrem Aufruf Daten aus einem Speicher lesen und bei ihrer Beendung Daten in diesen hinein schreiben. 3.1.4 Hilfesystem JavaHelp Für das Hilfesystem kommen bereits entwickelte Klassen aus der JavaHelp API zum Einsatz. Hier sind lediglich die vier Dateien helpset.hs, index.xml, map.xml und toc.xml sowie die eigentlichen Hilfeseiten zu entwickeln. 3.2 Modell Die im vorausgegangenen Abschnitt eingeführten Klassen und deren Beziehungen untereinander werden an dieser Stelle zu einem Gesamtmodell zusammengefügt. 31 3.3 Abbildung 10Gesamtmodell der Clientkomponente Programmierung 3.3.1 Verwaltung DimFrame - Temporäre Verwaltung der Eingabedaten Von der Klasse DimFrame aus erfolgen die Aktionen „neues Projekt erzeugen“, „Projekt öffnen“ und „Projekt speichern“. Lokale Variablen, die eventuell vom Anwender wieder verworfen werden könnten, treten hier nicht auf. Es liegt also nahe, die Projektdaten zentral in dieser Klasse zu verwalten und den anderen Klassen den Zugriff auf diese Daten zu ermöglichen. Für diese Aufgabe bietet sich die Klasse Hashtable an, ein assoziativer Speicher, der Schlüssel mit Werten verknüpft. Sie wird aus der abstrakten Klasse Dictionary abgeleitet und verhält sich dementsprechend wie ein Wörterbuch und ermöglicht über den Schlüsselbegriff (Variablenname) einen effizienten Zugriff auf den Wert (Wert der Variable). Lesende und schreibende Zugriffe erfolgen mit den Methoden getValue und setValue die hier für die gebräuchlichen Datentypen Object, Boolean, String, Double und Integer bereitgestellt werden. Damit kann der enorme Aufwand, für jede Variable eigene get- und 32 set-Methoden zu schreiben, umgangen werden. Unmittelbar nach dem Öffnen eines Dialogfensters durch die Anwahl eines entsprechenden Menüeintrages wird in der Regel die Methode getParameter des Dialog-Objektes aufgerufen. Diese initialisiert die lokalen Variablen mit den zugehörigen Werten aus der Hashtable. Möchte der Anwender neue oder geänderte Eingabewerte übernehmen, ruft er mit Betätigung des „OK“-Knopfes die Methode setParameter auf, welche die lokalen Werte dann in die Hashtable einträgt. Alte Einträge werden dabei überschrieben. Wählt der Benutzer stattdessen den „Cancel“-Knopf, erfolgt kein Eintrag in die Hashtable. 3.3.2 Kommunikation - Anwendung von Domino Objects for Java EZApplet Die bereits in Kapitel zwei vorgestellten Domino Objects for Java dienen in erster Linie der Anbindung des Applets an den Domino Server. Bei der Initialisierung des Applets durch den Webbrowser erzeugt die Methode notesAppletInit zunächst einmal ein DimFrame-Objekt also eine Instanz des Popup-Fensters mit der Menüleiste. Die Methode notesAppletStart, die nach der Methode notesAppletInit und bei jedem erneuten Besuch der Webseite aufgerufen wird, öffnet durch den Aufruf der Methode openSession die Verbindung zum Domino Server und zeigt durch Aufruf der Methode showFrame das Hauptfenster an. ... import java.net.*; import lotus.domino.*; public class EZApplet extends JAppletBase { ... //Initialize the applet public void notesAppletInit() { try { jbInit(); } catch(Exception e) { e.printStackTrace(); } } //Component initialization 33 private void jbInit() throws Exception { frame = new DimFrame(); } public void notesAppletStart() { Session s = null; try { // Can also do openSession(user, pwd) s = this.openSession(); //if we were not able to make the connection, warn user if (s == null) { JOptionPane.showMessageDialog(null, "Unable to create a session with the server!", "Connection error", JOptionPane.ERROR_MESSAGE); return; } frame.setAppletSession(s); showFrame(); } catch (NotesException e) { System.err.println(e.getClass().getName() + ": " + e.text); e.printStackTrace(); } finally { try {this.closeSession(s);} catch(NotesException e) {e.printStackTrace();} } } /* notesAppletStart */ private void showFrame() { ... frame.setLocation((screenSize.width - frameSize.width) / 2, (screenSize.height - frameSize.height) / 2); frame.setVisible(true); } ... } Wenn der Anwender nach Eingabe und Versand der Projektdaten das zugehörige Browserfenster schließt, sorgt die Methode closeSession, die in einen finally-Block eingebunden ist, automatisch für einen korrekten Abbruch der Verbindung zum Server. Da es sich bei einer Session um ein Domino Object handelt, kommt bei der Übertragung der Daten wie bereits erläutert das IIOP zum Einsatz. Agents Sämtliche Zugriffe auf die Domino-Datenbank erfolgen mit den Lotus 34 spezifischen JavaAgents. Sie greifen auf die vom Applet geöffnete Session zurück, um mit der Datenbank zu kommunizieren. Stellvertretend für die erste Gruppe von Agenten soll zunächst einmal die Klasse OpenDocumentAgent vorgestellt werden. Aufgrund der Sicherheitsrestriktionen eines Applet kann zur Auswahl des gewünschten Dokumentes kein Dateiauswähler wie der aus der Klassenbibliothek bekannte JFileChooser eingesetzt werden. Der Einsatz der Lotus-spezifischen Navigatoren erscheint hier auch unpassend, da sie entweder die Umgebung eines Notes Clients benötigen oder für Webbrowser direkt in eine Html-Seite eingebunden werden. Daher soll hier ein einfaches Dialogfenster eingesetzt werden, das alle zur Auswahl erhältlichen Dokumente in einer Tabelle anzeigt. Aus dieser Tabelle kann der Anwender dann einen Eintrag auswählen und durch Druck auf den „Ok“-Knopf öffnen. ... import lotus.domino.*; public class OpenDocumentAgent extends AgentBase { ... class OpenDocumentDialog extends JDialog implements ActionListener { ... private void createEntriesList() { try { ac = s.getAgentContext(); db = ac.getCurrentDatabase(); view = db.getView("By Name"); vec = view.getAllEntries(); nEntries = vec.getCount(); entries = new Object[nEntries]; int i=0; entry = vec.getFirstEntry(); while (entry != null) { entries[i] = (String)entry.getDocument().getItemValueString("Name"); entry = vec.getNextEntry(); i++; } //create table model TableModel tm = new AbstractTableModel() { public int getRowCount() { return nEntries; } public int getColumnCount() { return 1; } public String getColumnName(int columnIndex) { 35 return colHeads[columnIndex]; } public boolean isCellEditable(int rowIndex, int columnIndex) { return false; } public Object getValueAt(int rowIndex, int columnIndex) { return entries[rowIndex]; } }; //Tabelle erzeugen entriesListJT = new JTable(tm); tableJP.add(new JScrollPane(entriesListJT), BorderLayout.CENTER); } catch (NotesException e) { e.printStackTrace(); } } ... void approveJB_actionPerformed(ActionEvent e) { try { int rowIndex = entriesListJT.getSelectedRow(); docName = (String)entriesListJT.getValueAt(rowIndex, 0); doc = vec.getNthEntry(rowIndex+1).getDocument(); df.setDocumentName(docName); df.setDocument(doc); entriesListJT.clearSelection(); OK_OPTION = true; cancel(); } catch (ArrayIndexOutOfBoundsException ex) { Toolkit.getDefaultToolkit().beep(); // Error message JOptionPane.showMessageDialog(null, "There is no project selected!", "Open project error", JOptionPane.ERROR_MESSAGE); } catch (NotesException nex) { Toolkit.getDefaultToolkit().beep(); } } ... } } Wenn das entsprechende Dokument geöffnet worden ist, liest der Agent dessen Elemente (Items) aus und schreibt die Werte in die Hashtable. Die Schlüsselworte für die Elemente und die Einträge in die Hashtable werden dabei so gewählt, das sie übereinstimmen. ... import lotus.domino.*; public class OpenDocumentAgent extends AgentBase { ... public void NotesMain() { 36 try { //get session this.s = df.getAppletSession(); //open dialog OpenDocumentDialog odd = new OpenDocumentDialog(df); if (OK_OPTION) { // Headline Item headlineItem = doc.getFirstItem("headline"); try { df.setStringValue("headline", headlineItem.getValueString()); } catch(Exception ex) { //error message } // Project Item[] prjInpItem = new Item[df.getIntValue("prjInpSize")]; for (int i=1; i<=13; i++) { prjInpItem[i] = doc.getFirstItem("PrjInp"+i); try { df.setStringValue("PrjInp"+i, prjInpItem[i].getValueString()); } catch(Exception ex) { //error message } } ... // Save the document doc.save(true, true); } } catch(Exception e) { e.printStackTrace(); } } ... } Hat der Agent alle Elemente ausgelesen, so sorgt er wie in Kapitel zwei beschrieben dafür, daß das Dokument sofort wieder geschlossen wird. Aus der zweiten Gruppe soll hier die Klasse ShowInputAgent vorgestellt werden. Zur Darstellung der Eingabedaten ist eigentlich kein Datenbankzugriff erforderlich, da die benötigten Daten im zentralen Zwischenspeicher zur Verfügung stehen. Dieser Agent greift dennoch auf die vom Applet geöffnete Session und die aktuelle Datenbank zurück, um ein Object der Klasse Document zu erzeugen. In dieses Dokument schreibt der Agent mit einem Object der Klasse PrintWriter den zur Darstellung erforderlichen HTMLCode. ... import lotus.domino.*; import java.io.*; 37 import java.util.*; public class ShowInputAgent extends AgentBase { ... public void NotesMain() { try { //SETUP MAIN OBJECTS //get session this.s = df.getAppletSession(); AgentContext ac = s.getAgentContext(); Database db = ac.getCurrentDatabase(); //CREATE AGENT OUTPUT CLASS PrintWriter pw = getAgentOutput(); //GET WEB DOCUMENT Document wdoc = ac.getDocumentContext(); //VARIABLES String vHTML = new String(""); //CREATE HTML TEXT vHTML = vHTML + "<FONT Face=verdana SIZE=4><B>Input Data</B></FONT><BR><BR>"; vHTML = vHTML + "<TABLE STYLE=\"font:8ptVerdana\">"; vHTML = vHTML + "<H1>PROJECT INFORMATION:</H1>"; vHTML = vHTML + "<TABLE BORDER=0>"; vHTML = vHTML + "<TR><TD>To:</TD><TD>" + df.getStringValue("PrjInp1") + "</TD></TR>"; vHTML = vHTML + "<TR><TD>E-mail:</TD><TD>" + df.getStringValue("PrjInp12") + "</TD></TR>"; vHTML = vHTML + "</TABLE><BR>"; ... vHTML = vHTML + "<H1>WALL SYSTEM:</H1>"; String extwp =""; String intwp = ""; vHTML = vHTML + "<TABLE BORDER=0>"; vHTML = vHTML + "<TR><TD>External wall panel type:</TD><TD>" + extwp + "</TD></TR>"; vHTML = vHTML + "<TR><TD>Internal wall panel type:</TD><TD>" + intwp + "</TD></TR>"; vHTML = vHTML + "</TABLE><BR>"; //PRINT HTML TEXT TO THE WEBDOCUMENT pw.println(vHTML); } catch(Exception e) { e.printStackTrace(); } } } 3.3.3 Benutzerschnittstelle - Einsatz von Swing-Komponenten Textfelder Dieses Applet nutzt die Swing-Komponente JTextField wenn es darum geht, 38 einzeln auftretende Projektdaten numerischer oder literarischer Art aufzunehmen. Eingaben literarischer Art kommen ausschließlich in dem Dialogfenster „Project information“ vor und sollen bis auf wenige Ausnahmen im folgenden nicht genauer untersucht werden. Abbildung 11Dialogfenster "Project information" Von Interesse sind hier lediglich die Eingabefelder für die Telefon- und Faxnummern, da in diesen ausser Ziffern nur einige Sonderzeichen wie „+,-, /,(,)“ erlaubt sind. Zur Gültigkeitsüberprüfung der Benutzereingaben kann für die betroffenen Textfelder ein Tastaturereignisempfänger, ein sogenannter KeyListener, installiert werden. Dieser kann alle Tastaturereignisse, die zu unerwünschten Zeichen führen würden, konsumieren. Überlisten könnte man diese Überprüfung lediglich durch die Eingabe einer sinnlosen Zeichenkombination oder das Einfügen von Text aus der Zwischenablage mit der Tastenkombination „Strg + v“. 39 ... public class ProjectInfo extends JDialog implements ActionListener, KeyListener { ... private JTextField faxNoJTF = new JTextField(); private JTextField phoneJTF = new JTextField(); private JTextField faxJTF = new JTextField(); ... //Component initialization private void jbInit() throws Exception { ... faxNoJTF.setMinimumSize(jtfSize3); faxNoJTF.setPreferredSize(jtfSize3); faxNoJTF.addKeyListener(this); phoneJTF.setMinimumSize(jtfSize3); phoneJTF.setPreferredSize(jtfSize3); phoneJTF.addKeyListener(this); faxJTF.setMinimumSize(jtfSize3); faxJTF.setPreferredSize(jtfSize3); faxJTF.addKeyListener(this); ... } ... public void keyPressed(KeyEvent e) { } public void keyReleased(KeyEvent e) { } public void keyTyped(KeyEvent e) { char ch = e.getKeyChar(); if (Character.isDigit(ch)) { //accept } else if (ch == '-') { //accept } else if (ch == '+') { //accept } else if (ch == '.') { //accept } else if (ch == '(') { //accept } else if (ch == ')') { //accept } else if (ch == KeyEvent.VK_SLASH) { //accept } else if (ch == KeyEvent.VK_SPACE) { //accept } else if (ch == KeyEvent.VK_BACK_SPACE) { //accept } else if (ch == KeyEvent.VK_F1) { //accept } else { e.consume(); } } } Die Swing-Architektur „Modell – Ansicht – Steuerung“ bietet noch ein anderes 40 Verfahren an. Die Steuerung von Swing-Komponenten sammelt die Benutzerereignisse und übersetzt sie in Befehle. Erhält die Steuerung einen Befehl zum Einfügen von einzelnen Zeichen oder dem Inhalt des Zwischenspeichers in das Dokument, ruft sie die Methode insertString der Klasse Document auf und weist diese an, einen String an der Position des Carets einzufügen. Um bei diesem Einfügevorgang nur Werte vom Typ Integer oder Double zuzulassen, führt man die Subklassen IntegerField und DoubleField von JTextField ein. Durch Überschreiben der Methode createDefaultDocument erzeugen IntegerField und DoubleField wiederum Subklassen von Document. IntegerDocument und DoubleDocument überschreiben die Methode insertString, die wie eben erläutert zum Einfügen von Zeichenketten oder einzelnen Zeichen genutzt wird. Die Methode insertString der Klasse IntegerDocument zerlegt dabei einzufügende Zeichenketten in einzelne Zeichen und überprüft jedes einzelne mit der Methode isDigit der Klasse Character. Handelt es sich bei dem Zeichen um eine Ziffer, läßt das Dokument den Einfügevorgang zu. Andernfalls erzeugt die Methode einen Piepton als Fehlermeldung. Da das Entfernen einer Ziffer aus einem Integer nicht zu einem ungültigen Ergebnis führen kann, übernimmt diese Klasse die Standardimplementierung der Methode remove aus Document. public class IntegerField extends JTextField { ... public IntegerField(int columns) { super(columns); toolkit = Toolkit.getDefaultToolkit(); integerFormatter = NumberFormat.getNumberInstance(Locale.US); integerFormatter.setParseIntegerOnly(true); } ... public int getValue() { int retVal = 0; try { retVal = integerFormatter.parse(getText()).intValue(); } catch (ParseException e) { // This should never happen because insertString allows // only properly formatted data to get in the field. toolkit.beep(); } return retVal; } public void setValue(int value) { 41 setText(integerFormatter.format(value)); } protected Document createDefaultModel() { return new IntegerDocument(); } protected class IntegerDocument extends PlainDocument { public void insertString(int offs, String str, AttributeSet a) throws BadLocationException { char[] source = str.toCharArray(); char[] result = new char[source.length]; int j = 0; for (int i = 0; i < result.length; i++) { if (Character.isDigit(source[i])) result[j++] = source[i]; else { toolkit.beep(); } } super.insertString(offs, new String(result, 0, j), a); } } } DoubleDocument hingegen ist auf die Methode remove angewiesen, da beispielsweise ein verbleibender Dezimalpunkt keine gültige reelle Zahl darstellt. Die für diesen Zweck angepasste Methode remove untersucht, ob aus der verbleibenden Zeichenkette ein Double erzeugt werden kann. Führt dieser Versuch zu keinem gültigen Ergebnis, informiert die Methode den Anwender durch einen Piepton über seinen Fehler. Verbleibt eine gültige reelle Zahl, so entfernt das Dokument die markierten Zeichen. Die Analyse der Zeichenketten erfolgt auch bei der Methode insertString durch Aufruf der Methode parseDouble der Klasse Double. Eine Untersuchung jedes einzelnen Zeichens kann daher entfallen. public void remove(int offs, int len) throws BadLocationException { String currentText = getText(0, getLength()); String beforeOffset = currentText.substring(0, offs); String afterOffset = currentText.substring(len + offs, currentText.length()); String proposedResult = beforeOffset + afterOffset; try { if (proposedResult.length() != 0) Double.parseDouble(proposedResult); super.remove(offs, len); } catch (NumberFormatException e) { Toolkit.getDefaultToolkit().beep(); } 42 } Der ursprüngliche Ansatz, die Eingabedaten in Form von Zeichenketten an den Server zu übermitteln, machte eine Formattierung der numerischen Werte erforderlich, um Verwechslungen durch länderspezifische Eigenschaften der Tausender- und Dezimaltrennzeichen auszuschließen. Die Zeichenketten „1,000“ und „1.000“ stellen in Deutschland die Zahlen eins und eintausend dar, in den Vereinigten Staaten von Amerika würden sie aber als eintausend und eins interpretiert. Aus Gründen der Internationalisierung kommen hier die USamerikanischen Ländereinstellungen zum Einsatz. Übergibt entsprechendes, vordefiniertes getNumberInstance der an Locale-Object Klasse die erhält NumberFormat, man ein Methode man einen Standardformatierer der sich an die amerikanischen Regeln für Zahlenformate hält. Die aus NumberFormat abgeleitete Klasse DecimalFormat regelt die Anzeige von Trennzeichen, Vorzeichen sowie führenden und nachfolgenden Nullen. Die Methode applyPattern weist dem DecimalFormat-Objekt in diesem Fall die Musterzeichenkette „###.###“ zu. Diese unterbindet die Anzeige des Tausendertrennzeichens und sorgt dafür, daß die zu formatierende reelle Zahl auf drei Nachkommastellen gerundet wird. //Constructor for TableCells public DoubleField() { loc = new Locale("en", "US"); nFormat = NumberFormat.getNumberInstance(loc); dFormat = (DecimalFormat)nFormat; dFormat.applyPattern("###.###"); dFormat.setMaximumFractionDigits(3); } Das Dialogfenster „Crane“ hält noch zwei weitere Textfelder bereit, die einer genaueren Betrachtung bedürfen. Zur genauen Positionsbestimmung der Krane in der Industriehalle dürfen hier ganzzahlige Feld- beziehungsweise Modulnummern eingegeben werden. Liegen die entsprechenden Felder/Module nicht direkt nebeneinander, so sind sie durch Kommata getrennt einzugeben. Überspannen die Kranbahnen meherere unmittelbar aneinander grenzende Felder/Module, braucht der Benutzer lediglich die Anfangs- und Endposition getrennt durch ein Minuszeichen einzugeben. 43 Abbildung 12Dialogfenster "Crane" Die so erzeugte Zeichenkette ist im folgenden auf Gültigkeit zu überprüfen. Jede betroffene Feld- beziehungsweise Modulnummer ist explizit als ganzzahliger Wert zu bestimmen und vorübergehend in einem Array abzuspeichern. Dazu überprüft ein KeyListener schon bei der Eingabe der Positionsnummern durch die Tastatur, ob es sich um gültige Zeichen handelt. Die Methode convertStringToIntArray zerlegt dann mit Hilfe eines StringTokenizers die eingegebene Zeichenkette in durch Kommata abgegrenzte Teilabschnitte. Enthalten die jeweiligen Teilabschnitte ein Minuszeichen, durchlaufen sie einen weiteren StringTokenizer mit dem Minuszeichen als Abgrenzer, um die Anfangs- und die Endposition der zusammenhängenden Felder beziehungsweise Module zu bestimmen. Eine for-Schleife arbeitet dann alle Positionsnummern des zusammenhängenden Bereiches heraus und speichert diese in den temporären Array, sofern sie sich bei einer Überprüfung mit der Methode parseInt der Klasse Integer als gültiger ganzzahliger Wert erweisen. Die verbliebenen Teilabschnitte des ersten StringTokenizers, die kein Minuszeichen enthielten, unterziehen sich ebenfalls dem Test mit der Methode parseInt, bevor sie in dem temporären Array gespeichert werden. Abschließend bringt die Methode sort der Klasse Arrays die Positionsnummern in eine geordnete Reihenfolge. private int[] convertStringToIntArray(String s, int arraySize) { int[] intArray = new int[arraySize]; StringTokenizer stComma = new StringTokenizer(s, ",", false); int i=0; 44 while ((stComma.hasMoreTokens()) && (i<arraySize)) { String str = stComma.nextToken().trim(); int minus = str.indexOf('-'); if (minus > 0) { StringTokenizer stMinus = new StringTokenizer(str, "-", false); if (stMinus.countTokens() == 2) { int[] intMinus = new int[2]; int j=0; while (stMinus.hasMoreTokens()) { String strMinus = stMinus.nextToken().trim(); try { intMinus[j] = Integer.parseInt(strMinus); j++; } catch (NumberFormatException ex) { Toolkit.getDefaultToolkit().beep(); } } for (int k=intMinus[0]; k<=intMinus[1]; k++) { intArray[i] = k; i++; } } } else { try { intArray[i] = Integer.parseInt(str); i++; } catch (NumberFormatException ex) { Toolkit.getDefaultToolkit().beep(); } } } Arrays.sort(intArray); return intArray; } Auch bei der Methode convertIntArrayToString kommen zwei StringTokenizer zum Einsatz. Ihre Fähigkeiten dienen hier dazu, zusammenhängende Feld- beziehungsweise Modulnummern zu erkennen und diese als zusammenhängenden Bereich, sprich Anfangs- und Endposition getrennt durch ein Minuszeichen, darzustellen. Wohingegen einzelne Felder/Module wie gewohnt durch Kommata voneinander getrennt darzustellen sind. Tabellen In vielen Dialogfenstern dieser Clientkomponente bietet sich die SwingKomponente JTable für die mehrzeilige und mehrspaltige Darstellung von 45 Projektdaten an. Die Anforderungen an die Tabellen sind jedoch relativ unterschiedlich. So dienen sie in den Dialogfenstern „Annexes list“, „Mezzanines list“ und „Canopies list“ ausschließlich der Auflistung der einzelnen Objekte. Eine Editiermöglichkeit ist hier nicht vorgesehen, wohl aber die Möglichkeit ein Objekt auszuwählen und dieses auf Knopfdruck in einem weiteren Dialogfenster zu bearbeiten. Abbildung 13Dialogfenster "Materials' list" Die Auflistung der Materialien für die primäre und die sekundäre Struktur in dem Dialogfenster „Materials list“ sowie die Darstellung der Abmessungen einzelner Module in den Dialogfenstern „Bays list“ und „Modules list“ bilden eine zweite Gruppe von Tabellen. Da der Anwender die Materialpreise und die Abmessungen frei wählen darf, ist für die rechte Spalte dieser Tabellen eine Editiermöglichkeit mit einer entsprechender Eingabeüberprüfung auf reelle Zahlen vorzusehen. Für die letzte Gruppe, die Darstellung der Dach- und Wandpaneele in dem Dialogfenster „Materials list“ gelten deutlich umfangreichere Anforderungen. Diese Tabellen sollen in allen Tabellenzellen editierbar sein, in der linken Spalte doppelte Einträge unterbinden und in der rechten Spalte nur Werte vom Typ Double zulassen. Ausgewählte Dach- bzw. 46 Wandpaneele können auf Knopfdruck aus der Tabelle entfernt werden. Durch einen Mausklick auf den Tabellenkopf kann der Benutzer den Tabelleninhalt lexikographisch nach der ersten Spalte sortieren lassen. Auch Tabellen folgen dem Swing-Entwurfsmuster „Modell – Ansicht – Steuerung“. Die Daten werden im Modell durch die Schnittstelle TableModel beschrieben, Ansicht und Steuerung übernimmt die Klasse JTable. Abbildung 14Entwurfsmuster für eine JTable Für die eben erwähnten Anwendungen reicht es nicht mehr aus, mit den automatisch erzeugten Tabellenmodellen zu arbeiten. Stattdessen ist es sinnvoll eigene, aus der Klasse AbstractTableModel abgeleitete Tabllenmodelle zu entwickeln. Das AbstractTableModel stellt dazu eine Reihe nützlicher Hilfsmethoden bereit, die von JTable aufgerufen werden, um Informationen zur Darstellung der Tabelle zu erhalten. Um die Editierbarkeit von Tabellenzellen zu regeln, paßt man die Hilfsmethode isCellEditable an die eigenen Bedürfnisse an. Der folgende Auszug aus dem Quellcode einer zweispaltigen Tabelle zum Beispiel untersagt das Editieren von Tabellenzellen in der ersten Spalte, lässt dieses aber in der zweiten Spalte zu: public boolean isCellEditable(int rowIndex, int columnIndex) { if (columnIndex == 0) return false; else return true; } Bei der Eingabe neuer Materialien für die Dach- und Wandpaneele soll überprüft werden, ob bereits ein Material dieses Namens existiert. Ist dieses der Fall, soll der Anwender mit einer Warnmeldung darauf hingewiesen und die Änderungen in der Materialliste verworfen werden. Dazu wird die Standardimplementierung der Methode setValueAt um den Vergleich des neuen Materialnamens mit allen bereits genutzten Materialnamen ergänzt. Ein 47 Eintrag in die Materialliste soll nur dann vorgenommen werden, wenn der neue Name noch nicht vergeben wurde. Für den Vergleich der Materialbezeichnungen wird die Methode compareTo der Klasse String genutzt. public void setValueAt(Object aValue, int rowIndex, int columnIndex) { ... else {//check if the new panel type already exists String newValue = (String)aValue; boolean newValueExists = false; if (newValue.length() != 0) { for (int i=0; i<rowIndex; i++) { int result = newValue.compareTo((String)roofStr[i][columnIndex]); if (result == 0) { //error message String msg = new String("Roof panel already exists! Please choose a different term."); String title = new String("Add roof panel error"); JOptionPane.showMessageDialog(null, msg, title, JOptionPane.ERROR_MESSAGE); //set default value newValueExists = true; break; } } ... if (newValueExists) newValue = ""; } roofStr[rowIndex][columnIndex] = newValue; } fireTableCellUpdated(rowIndex, columnIndex); } Eine JTable verfügt neben dem Tabellenmodell noch über ein weiteres Modell, das die Eigenschaften der Spalten verwaltet. Es kommt zum Einsatz, sobald neben ihrem Namen weitere Eigenschaften der Spalte ausgenutzt werden sollen. Als Spaltenmodell DefaultTableColumnModel wird eingesetzt, in der die Regel das die Klasse Interface TableColumnModel implementiert. Das DefaultTableColumnModel stellt Methoden zur Verfügung mit denen Spaltenobjekte vom Typ TableColumn hinzugefügt oder entfernt werden können. Bei diesem Applet werden TableColumns dazu genutzt, die Position und die anfängliche Breite der Spalten explizit festzulegen. private void createRoofJT() { //create column model DefaultTableColumnModel cm = new DefaultTableColumnModel(); for (int i = 0; i < colHeadsRoofStruct.length; ++i) { TableColumn col = new TableColumn(i, i == 1 ? 64 : 94); 48 col.setHeaderValue(colHeadsRoofStruct[i]); cm.addColumn(col); } ... //create table RoofTableModel roofTableModel = new RoofTableModel(); roofJT = new JTable(roofTableModel, cm); setUpDoubleEditor(roofJT); ... } Auch bei der Überprüfung der Eingaben vom Benutzer wird auf das Spaltenmodell zurückgegriffen. Durch den Einsatz eines DefaultCellEditors wird in diesem Fall den Tabellenzellen einer Spalte die Funktionsweise eines zuvor beschriebenen DoubleFields zugewiesen. private void setUpDoubleEditor(JTable jt) { //Set up the editor for the double cells. TableColumnModel tcm = jt.getColumnModel(); TableColumn tc = tcm.getColumn(1); final DoubleField doubleField = new DoubleField(); DefaultCellEditor doubleEditor = new DefaultCellEditor(doubleField) { //Override DefaultCellEditor's getCellEditorValue method //to return an Double, not a String: public Object getCellEditorValue() { return new String(doubleField.getText()); } }; tc.setCellEditor(doubleEditor); } Eine Möglichkeit Datenmanipulationen wie zum Beispiel das alphabetische Sortieren der Paneele durchzuführen besteht darin, ein oder mehrere spezialisierte Tabellenmodelle zusätzlich zu dem Datenmodell anzuwenden. Ein solches Sortierfiltermodell sollte zwischen das Datenmodell (TableModel) und die Ansicht (JTable) geschaltet werden. Manipulationen an der Ansicht, wie das Verschieben von Spalten oder das Sortieren der Zeilen fängt das Sortierfiltermodell ab und übersetzt die Anfragen an das unveränderte Datenmodell. Hier allerdings soll der Sortiervorgang nicht nur die Ansicht betreffen, sondern dementsprechend auch auf das Datenmodell wirken. Als ein Problem bei dem Sortieren der Dach- und Wandpaneele stellt sich heraus, daß die Zuordnung, ob ein Paneel in den Dialogen „Roof system“ oder „Wall system“ ausgewählt ist oder nicht, nicht verloren gehen darf. Diese Zuordnung erfolgt anhand der Position des ausgewählten Paneels in der Materialliste. Sie 49 hat allerdings keinen direkten Bezug zu den Variablen Materialname und Preis, auf denen das Datenmodell der Tabelle aufbaut. Eigens für den Sortiervorgang wird an dieser Stelle eine Hilfsklasse SortPanel entwickelt, die aus der Klasse Comparable abgeleitet ist. Sie stellt die Variablen Materialname, Preis, ausgewählt als internes Paneel und ausgewählt als externes Paneel sowie die Methode compareTo bereit, die es ermöglicht Objekte vom Typ SortPanel alphabetisch anhand ihres Materialnamens zu vergleichen. Um leere Tabellenzellen an das Tabellenende und nicht an den Tabellenanfang zu stellen, wie es bei der Anwendung der lexikographischen Sortiermethode der Fall ist, wird dem Vergleich der Materialnamen mit der Methode compareTo der Klasse String noch eine Betrachtung der Länge der einzelnen Strings vorgeschoben. public class SortPanel implements Comparable { private String material; private String price; private boolean intPanelType; private boolean extPanelType; public SortPanel(String material, String price, boolean extPanelType, boolean intPanelType) { this.material = material; this.price = price; this.extPanelType = extPanelType; this.intPanelType = intPanelType; } public int compareTo(Object o) { SortPanel p = (SortPanel)o; //place empty cells at the end int result; int length1 = material.length(); int length2 = p.material.length(); if ((length1 > 0) && (length2 == 0)) { result = -1; } else if ((length1 == 0) && (length2 > 0)) { result = 1; } else if ((length1 == 0) && (length2 == 0)) { result = 0; } else { result = material.compareTo(p.material); } //compare if (result < 0) { return -1; } else if (result > 0) { return 1; } else { return 0; 50 } } } Aus dem Datenmodell der Tabelle und den bekannten Informationen über den Selektionszustand der paneele werden Objekte vom Typ SortPanel erzeugt und diese einer Liste hinzugefügt. Mit der Methode sort der Klasse Collections lassen sich die Elemente dieser Liste wie zuvor beschrieben nach den Materialnamen sortieren. Nach dem Sortiervorgang werden das Datenmodell und die Ansicht der Tabelle aktualisiert. public void sortRoofPanel() { SortPanel[] panelArray = new SortPanel[nmater]; for (int i=0; i<nmater; i++) { String material = (String)roofStr[i][0]; String price = (String)roofStr[i][1]; boolean extPT = roofPT[i][0]; boolean intPT = roofPT[i][1]; panelArray[i] = new SortPanel(material, price, extPT, intPT); } //sort roofpanels List l = Arrays.asList(panelArray); Collections.sort(l); Object[] sortedPanels = l.toArray(); //refresh data model for (int i=0; i<nmater; i++) { SortPanel sPanel = (SortPanel)sortedPanels[i]; roofStr[i][0] = new String(sPanel.material); roofStr[i][1] = new String(sPanel.price); roofPT[i][0] = sPanel.extPanelType; roofPT[i][1] = sPanel.intPanelType; } //refresh view model tableChanged(new TableModelEvent(this)); } In der Regel werden die Tabelle und ihr Modell automatisch darüber informiert, wenn ein Benutzer die Daten der Tabelle bearbeitet. Sollten sich die Daten allerdings aus einem anderen Grund ändern, wie zum Beispiel dem eben erläuterten Sortiervorgang, so sind besondere Vorkehrungen zu treffen, um die Ansicht und das Datenmodell über die Veränderungen zu informieren. Zu diesem Zweck implementieren die Tabellenmodelle der Dach- und Wandpaneele einen Ereignisbehandler der Klasse TableModelListener. Dieser wird von den Methoden sortRoofPanel beziehungsweise sortWallPanel durch den Aufruf der Methode tableChanged über den Sortiervorgang unterrichtet und teilt dem Tabellenmodell und der Ansicht dieses Ereignis mit. 51 private void createRoofJT() { ... class RoofTableModel extends AbstractTableModel implements TableModelListener { ... public void tableChanged(TableModelEvent e) { fireTableChanged(e); } public void sortRoofPanel() { ... //refresh view model tableChanged(new TableModelEvent(this)); } ... }; ... } Auswahlelemente Kontrollfelder Zur Auswahl einzeln auftretender Optionen dienen Swing-Komponenten der Klasse JCheckbox. Sie stellen auf der graphischen Benutzeroberfläche neben dem Bezeichnungsfeld ein rechteckiges Kontrollkästchen zur Verfügung, das vom Benutzer angewählt oder abgewählt werden kann. Soll auf die Zustandsänderung des Kontrollfeldes eine unmittelbare Reaktion folgen, muß der von ihr generierte ItemEvent abgefangen werden. Dazu registriert man bei dem Kontrollfeld mit der Methode addItemListener ein Ereignisempfänger-Objekt, das die Schnittstelle ItemListener implementiert. Erhält dieses Ereignisempfänger-Objekt einen ItemEvent, führt es automatisch die Methode itemStateChanged und damit die Anweisungen, wie in diesem Fall zu verfahren ist, aus. Drei Kontrollfelder aus dem Dialogfenster „Main building“ nutzen diesen Mechanismus zur Aktivierung beziehungsweise Deaktivierung von anderen Komponenten. Optionsfelder Soll der Anwender hingegen nur eine einzige von mehreren möglichen Optionen auswählen können, kommen Objekte vom Typ JRadioButton zum Einsatz. Ähnlich wie Objekte vom Typ JCheckBox stellen sie neben einem Bezeichnungsfeld ein rundes Kontrollfeld bereit. Um nun mehrere 52 Auswahlfelder in einer logischen Einheit zusammenzufassen, erzeugt man ein Objekt vom Typ Buttongroup und fügt die entsprechenden Objekte vom Typ JRadioButton hinzu. Trifft ein Anwender innerhalb dieser Gruppe eine neue Auswahl, sorgt das ButtonGroup-Objekt für dieAbwahl des zuvor ausgewählten JRadioButton-Objektes. In diesem Applet gehört jedes Optionsfeld einer ButtonGroup an. Nahezu alle sind bei Ereignisempfängern registriert, um wie bei den Kontrollfeldern beschrieben auf Zustandsänderungen reagieren zu können. Auswahlmenüs Auswahlmenüs bieten sich an, wenn der Benutzer unter einer großen Anzahl von Alternativen wählen soll. Da sie im Ausgangszustand in etwa nur die Größe eines Textfeldes vorweisen stellen sie eine platzsparende Alternative zu zahllosen Kontroll- oder Optionsfeldern dar. Durch einen Mausklick auf die Komponente öffnet sich das Auswahlmenü und der Anwender kann einen der Einträge aus dem Dropdown-Listenfeld auswählen. Für den Einsatz in den Dialogfenstern „Roof system“ und „Wall system“, wo aus bis zu fünfzig verschiedenen Materialien zu wählen ist, sind sie also geradezu prädestiniert. Abbildung 15Dialogfenster "Wall system" Die Klasse JComboBox stellt dazu die erforderliche Swing-Komponente bereit. 53 Bevor die Materialbezeichnung und der Materialpreis mit der Methode addItem der Liste als ein Auswahlelement hinzugefügt werden können, sind sie zu einem String-Objekt zusammenzufassen. Verlässt der Benutzer das Dialogfenster durch betätigen des „OK“-Knopfes, ruft das Programm automatisch die Methode getSelectedItem auf, um zu bestimmen, welche Paneele ausgewählt worden sind. Sortieren der Anbauten, Zwischengeschosse und Dachüberstände Aus Gründen der Übersichtlichkeit soll sich die Nummerierung der Anbauten und Dachüberstände nicht an der Reihenfolge ihrer Erstellung sondern an ihrer Lage im Bezug auf die Halle orientieren. Die Höhe gilt bei den Zwischengeschossen als wichtigstes Sotierkriterium. Bestätigt der Anwender beispielsweise den Dialog zur Eingabe eines Anbaus mit „OK“, ruft das Programm nach dem Speichern der Eingabedaten automatisch die Methode sortAnnexes auf. Diese entnimmt der Hashtable die kennzeichnenden Werte Breite, Dachneigung, Länge, Position und Hallenseite jedes möglichen Anbaus und erzeugt daraus Instanzen der Hilfsklasse SortWX. Die Hilfsklasse SortWX, abgeleitet aus der Klasse Comparable, stellt neben den bereits erwähnten Variablen auch die Methode compareTo zur Verfügung, die es ermöglicht, Objekte dieses Typs nach selbst gewählten Kriterien zu vergleichen. Mit der Methode sort der Klasse Collections können die in einem Array gespeicherten SortWX-Objekte entsprechend geordnet werden. Nach dem Sortiervorgang werden sämtliche Variablen in der neuen Reihenfolge zurück in die Hashtable geschrieben. public void sortAnnexes() { SortWX[] wxArray = new SortWX[wxSize-2]; for (int i=0; i<wxSize-2; i++) { boolean annex = getBooleanValue("WX"+(i+1)); Integer wx; if(annex) wx = new Integer(0); else wx = new Integer(1); Double wxWidth = new Double(getDoubleValue("WXWidth"+(i+1))); Double wxSlope = new Double(getDoubleValue("WXSlope"+(i+1))); Integer wxLen = new Integer(getIntValue("WXLen"+(i+1))); Integer wxPos = new Integer(getIntValue("WXPos"+(i+1))); Integer wxSide = new Integer(getIntValue("WXSide"+(i+1))); wxArray[i] = new SortWX(wx, wxWidth, wxSlope, wxLen, wxPos, 54 wxSide); } List l = Arrays.asList(wxArray); Collections.sort(l); Object[] sortedWX = l.toArray(); for (int i=0; i<wxSize-2; i++) { SortWX swx = (SortWX)sortedWX[i]; int wx = swx.wx.intValue(); boolean annex; if(wx == 0) annex = true; else annex = false; setBooleanValue("WX"+(i+1), annex); setDoubleValue("WXWidth"+(i+1), swx.wxWidth); setDoubleValue("WXSlope"+(i+1), swx.wxSlope); setIntValue("WXLen"+(i+1), swx.wxLen); setIntValue("WXPos"+(i+1), swx.wxPos); setIntValue("WXSide"+(i+1), swx.wxSide); annArray[i] = new Annex(this, this, i); } annListDialog = new AnnexesList(this, this); } public class SortWX implements Comparable { private Integer wx; private Double wxWidth; private Double wxSlope; private Integer wxLen; private Integer wxPos; private Integer wxSide; public SortWX(Integer wx, Double wxWidth, Double wxSlope, Integer wxLen, Integer wxPos, Integer wxSide) { this.wx = wx; this.wxWidth = wxWidth; this.wxSlope = wxSlope; this.wxLen = wxLen; this.wxPos = wxPos; this.wxSide = wxSide; } public int compareTo(Object o) { SortWX w = (SortWX)o; int wxCmp = wx.compareTo(w.wx); int wxSideCmp = wxSide.compareTo(w.wxSide); int wxPosCmp = wxPos.compareTo(w.wxPos); return (wxCmp!=0 ? wxCmp : wxSideCmp!=0 ? wxSideCmp : wxPosCmp); } } Dieser Vorgang erfolgt bei den Dachüberständen in analoger Weise. Zwischengeschossen und den 55 3.3.4 Das Hilfesystem Einführung Bei der Entwicklung von Java-Applets gilt es, einige wichtige Punkte im Bezug auf den Einsatz von JavaHelp zu beachten. Im vorliegenden Szenario sendet das Applet von einer HTML-Seite aus eine Anfrage an das JavaHelp-System, um Hilfethemen angezeigt zu bekommen. Da es sich bei dem JavaHelp-System um ein optionales Java-Paket handelt, kann man davon ausgehen, daß es trotz aktuellem Java-PlugIn nicht auf dem Client-Rechner installiert ist. Angesichts der Tatsache, das die benötigten Bibliotheken nur einen kleinen Umfang haben, bietet es sich an, diese zusätzlich zu den Applet-Dateien vom Server herunterzuladen. Abbildung 16Platzierung der Bibliotheken 56 Die aktuelle Version der JavaHelp-Software kann der Entwickler von der Webseite http://java.sun.com/products/javahelp/ des Java-Anbieters Sun Microsystems herunterladen und anschließend installieren. Die Bibliotheken des Hilfesystems sind bei der Kompilierung der Applet-Quelldateien ebenso in den Klassenpfad aufzunehmen, wie das Jar-Archiv ezhelp.jar der noch zu generierenden Hilfeseiten. Aufbau des Hilfesystems JavaSoft hat mit der JavaHelp API ein plattformunabhängiges, ausbaufähiges Hilfesystem entwickelt, das bei dem vorliegenden Applet eingesetzt werden soll, um dem Anwender eine Online-Hilfe zur Verfügung zu stellen. JavaHelp beinhaltet einen Benutzeroberfläche eigenen Swing Betrachter, basiert. Dieser der auf Betrachter der graphischen stellt in einer Werkzeugleiste zwei Schaltflächen mit den Funktionen „vor“ und „zurück“ zur Navigation in den Hilfeseiten bereit. Unterhalb dieser Werkzeugleiste befindet sich ein zweigeteiltes Fenster in dessen linker Hälfte ein Registerbereich drei Karteireiter zu den Themen Inhalt, Index und Suche anbietet. In der rechten Hälfte wird das gerade ausgewählte Hilfethema in Form eines HTMLDokumentes angezeigt. 57 Abbildung 17Der Hilfebetrachter Für den Einsatz von JavaHelp in Anwendungen und Applets sind neben den Seiten mit den Hilfethemen vier weitere Dateien im XML-Format vorzubereiten, die im folgenden näher vorgestellt werden sollen. Die Systemdatei helpset.hs liefert Informationen über andere Hilfekomponenten und Dateien. <?xml version='1.0' encoding='ISO-8859-1'?> <!DOCTYPE helpset PUBLIC "-//Sun Microsystems Inc.//DTD JavaHelp HelpSet Version 1.0//EN" "http://java.sun.com/products/javahelp/helpset_1_0.dtd"> <helpset version="1.0"> <title>ezhelp</title> <maps> <homeID>Intro</homeID> <mapref location="map.xml"/> </maps> <view> <name>TOC</name> <label>Inhaltsverzeichnis</label> <type>javax.help.TOCView</type> <data>toc.xml</data> </view> 58 <view> <name>Index</name> <label>Index</label> <type>javax.help.IndexView</type> <data>index.xml</data> </view> <view> <name>Search</name> <label>Suche</label> <type>javax.help.SearchView</type> <data engine="com.sun.java.help.search.DefaultSearchEngine"> JavaHelpSearch</data> </view> </helpset> Eine Übersicht über die Schlüsselpaare „ID des Hilfethemas“ und „Adresse der zugehörigen HTML-Seite“ stellt die Datei map.xml bereit. <?xml version='1.0' encoding='ISO-8859-1'?> <!DOCTYPE map PUBLIC "-//Sun Microsystems Inc.//DTD JavaHelp Map Version 1.0//EN" "http://java.sun.com/products/javahelp/map_1_0.dtd"> <map version="1.0"> <mapID target="MenuAnnex" url="ezHTML/commands/annex/MenuAnnex.html"/> <mapID target="MenuAnnex_dialog" url="ezHTML/commands/annex/MenuAnnex_dialog.html"/> <mapID target="Commands" url="ezHTML/commands/Commands.html"/> <mapID target="Dialogs" url="ezHTML/commands/dialogs/Dialogs.html"/> <mapID target="MenuDim" url="ezHTML/commands/dim/MenuDim.html"/> <mapID target="MenuDim_engine" url="ezHTML/commands/dim/MenuDim_engine.html"/> <mapID target="MenuDim_input" url="ezHTML/commands/dim/MenuDim_input.html"/> <mapID target="MenuDim_results" url="ezHTML/commands/dim/MenuDim_results.html"/> <mapID target="MenuFile" url="ezHTML/commands/file/MenuFile.html"/> <mapID target="MenuFile_new" url="ezHTML/commands/file/MenuFile_new.html"/> <mapID target="MenuFile_open" url="ezHTML/commands/file/MenuFile_open.html"/> <mapID target="MenuFile_plot" url="ezHTML/commands/file/MenuFile_plot.html"/> <mapID target="MenuFile_quit" url="ezHTML/commands/file/MenuFile_quit.html"/> <mapID target="MenuFile_save" url="ezHTML/commands/file/MenuFile_save.html"/> <mapID target="MenuFile_saveas" url="ezHTML/commands/file/MenuFile_saveas.html"/> <mapID target="MenuGeneral" url="ezHTML/commands/general/MenuGeneral.html"/> 59 <mapID target="MenuGeneral_materials" url="ezHTML/commands/general/MenuGeneral_materials.html"/> <mapID target="MenuGeneral_project" url="ezHTML/commands/general/MenuGeneral_project.html"/> <mapID target="MenuLoads" url="ezHTML/commands/loads/MenuLoads.html"/> <mapID target="MenuLoads_edit" url="ezHTML/commands/loads/MenuLoads_edit.html"/> <mapID target="MenuMainB" url="ezHTML/commands/mainb/MenuMainB.html"/> <mapID target="MenuMainB_edit" url="ezHTML/commands/mainb/MenuMainB_edit.html"/> <mapID target="MenuSpec" url="ezHTML/commands/spec/MenuSpec.html"/> <mapID target="MenuSpec_roof" url="ezHTML/commands/spec/MenuSpec_roof.html"/> <mapID target="MenuSpec_structural" url="ezHTML/commands/spec/MenuSpec_structural.html"/> <mapID target="MenuSpec_wall" url="ezHTML/commands/spec/MenuSpec_wall.html"/> <mapID target="Intro" url="ezHTML/intro/Intro.html"/> <mapID target="Intro_general" url="ezHTML/intro/Intro_general.html"/> <mapID target="Intro_method" url="ezHTML/intro/Intro_method.html"/> </map> Informationen über den Inhaltsverzeichnis der Hilfethemen liefert die Systemdatei toc.xml. Sie gewährt einen Einblick in die Beziehungen zwischen den sichtbaren Einträgen in dem Inhaltsverzeichnis und den zugehörigen „IDs der Hilfethemen“. <?xml version='1.0' encoding='ISO-8859-1'?> <!DOCTYPE toc PUBLIC "-//Sun Microsystems Inc.//DTD JavaHelp TOC Version 1.0//EN" "http://java.sun.com/products/javahelp/toc_1_0.dtd"> <toc version="1.0"> <tocitem text="Introduction" target="Intro"> <tocitem text="General features" target="Intro_general" /> <tocitem text="Dimensioning method" target="Intro_method" /> </tocitem> <tocitem text="Menu Commands" target="Commands"> <tocitem text="The dialogs" target="Dialogs" /> <tocitem text="Menu File" target="MenuFile"> <tocitem text="New project" target="MenuFile_new" /> <tocitem text="Open project" target="MenuFile_open" /> <tocitem text="Save project" target="MenuFile_save" /> <tocitem text="Save project as" target="MenuFile_saveas" /> <tocitem text="Plot" target="MenuFile_plot" /> <tocitem text="Quit" target="MenuFile_quit" /> </tocitem> <tocitem text="Menu General" target="MenuGeneral"> 60 <tocitem text="Project" target="MenuGeneral_project" /> <tocitem text="Materials" target="MenuGeneral_materials" /> </tocitem> <tocitem text="Menu Loads" target="MenuLoads"> <tocitem text="Edit" target="MenuLoads_edit" /> </tocitem> <tocitem text="Menu Main Building" target="MenuMainB"> <tocitem text="Edit" target="MenuMainB_edit" /> </tocitem> <tocitem text="Menu Annexes" target="MenuAnnex"> <tocitem text="The annexes dialog" target="MenuAnnex_dialog" /> </tocitem> <tocitem text="Menu Specifications" target="MenuSpec"> <tocitem text="Structural system" target="MenuSpec_structural" /> <tocitem text="Roof system" target="MenuSpec_roof" /> <tocitem text="Wall system" target="MenuSpec_wall" /> </tocitem> <tocitem text="Menu Dimensioning" target="MenuDim"> <tocitem text="View input" target="MenuDim_input" /> <tocitem text="Run engine" target="MenuDim_engine" /> <tocitem text="View results" target="MenuDim_results" /> </tocitem> </tocitem> </toc> Die Datei index.xml ähnelt im Bezug auf ihren Inhalt sehr der Datei map.xml. Im Gegensatz zu ihr gruppiert sie ihre Einträge nicht nach Themen, sondern sortiert sie in alphabetischer Reihenfolge. <?xml version='1.0' encoding='ISO-8859-1'?> <!DOCTYPE index PUBLIC "-//Sun Microsystems Inc.//DTD JavaHelp Index Version 1.0//EN" "http://java.sun.com/products/javahelp/index_1_0.dtd"> <index version="1.0"> <indexitem text="Annexes" target="MenuAnnex" /> <indexitem text="Annexes - The annexes dialog" target="MenuAnnex_dialog" /> <indexitem text="Commands" target="Commands" /> <indexitem text="Commands - The dialogs" target="Dialogs" /> <indexitem text="Dimensioning" target="MenuDim" /> <indexitem text="Dimensioning - Send data" target="MenuDim_engine" /> <indexitem text="Dimensioning - View input" target="MenuDim_input" /> <indexitem text="Dimensioning - View results" target="MenuDim_results" /> <indexitem text="File" target="MenuFile" /> <indexitem text="File - New project" target="MenuFile_new" /> <indexitem text="File - Open project" target="MenuFile_open" /> <indexitem text="File - Plot" target="MenuFile_plot" /> <indexitem text="File - Quit" target="MenuFile_quit" /> 61 <indexitem text="File - Save project" target="MenuFile_save" /> <indexitem text="File - Save project as" target="MenuFile_saveas" /> <indexitem text="General" target="MenuGeneral" /> <indexitem text="General - Materials" target="MenuGeneral_materials" /> <indexitem text="General - Project" target="MenuGeneral_project"/> <indexitem text="Introduction" target="Intro" /> <indexitem text="Introduction - Dimensioning method" target="Intro_method" /> <indexitem text="Introduction - General features" target="Intro_general" /> <indexitem text="Loads" target="MenuLoads" /> <indexitem text="Loads - Edit" target="MenuLoads_edit" /> <indexitem text="Main Building" target="MenuMainB" /> <indexitem text="Main Building - Edit" target="MenuMainB_edit" /> <indexitem text="Specifications" target="MenuSpec" /> <indexitem text="Specifications - Roof system" target="MenuSpec_roof" /> <indexitem text="Specifications - Structural system" target="MenuSpec_structural" /> <indexitem text="Specifications - Wall system" target="MenuSpec_wall" /> </index> Zur Anzeige der Hilfethemen setzt JavaHelp Dateien im HTML-Format ein. Durch die Bereitstellung der üblichen Schriften, die Möglichkeit der Einbindung von Graphiken und vor allem durch ihre Fähigkeit untereinander verlinkt zu werden eignen sie sich besonders gut für den Einsatz in einem effizienten Hilfesystem. Einbindung des Hilfesystems in das Applet Die Einbindung der Hilfedateien soll anhand des nun folgenden Auszuges aus dem Quellcode kurz erläutert werden: <?xml version='1.0' encoding='ISO-8859-1'?> <!DOCTYPE helpset PUBLIC "-//Sun Microsystems Inc.//DTD JavaHelp HelpSet Version 1.0//EN" "http://java.sun.com/products/javahelp/helpset_1_0.dtd"> <helpset version="1.0"> <title>ezhelp</title> <maps> <homeID>Intro</homeID> <mapref location="map.xml"/> </maps> <view> <name>TOC</name> <label>Inhaltsverzeichnis</label> 62 <type>javax.help.TOCView</type> <data>toc.xml</data> </view> <view> <name>Index</name> <label>Index</label> <type>javax.help.IndexView</type> <data>index.xml</data> </view> <view> <name>Search</name> <label>Suche</label> <type>javax.help.SearchView</type> <data engine="com.sun.java.help.search.DefaultSearchEngine"> JavaHelpSearch</data> </view> </helpset> Die ClassLoader-Instanz dient dazu, alle vom Betrachter benötigten Klassen zu lokalisieren. Die URL gibt den Ort an, wo sich die die Datei helpset.hs befindet. Mit diesen beiden Parametern kann man eine HelpSet-Instanz erzeugen, die als eine Sammlung aus den bereits vorgestellten Dateien helpset, map, toc und index zu verstehen ist. Für die Darstellung der Hilfe und die Reaktion auf Benutzereingaben dient die Schnittstelle HelpBroker. Wird die Methode enableHelpKey auf eine Komponente, wie das Hauptfenster oder eines der Dialogfenster, und die ID des gewünschten Hilfethemas angewendet, kann der Benutzer durch drücken der Taste „F1“ den Hilfebetrachter mit dem entsprechenden Hilfethema öffnen. Vorausgesetzt, die Komponente hat zu diesem Zeitpunkt den Fokus. 3.4 Zusammenfassung Das Gesamtmodell der neu realisierten Clientkomponente zeigt auf, daß das Applet leicht durch neue Module, wie zum Beispiel die Visualisierung ergänzt werden kann. Im alltäglichen Einsatz kann diese Modularisierung allerdings schnell an ihre Grenzen stossen. Da in dem Haupteinsatzgebiet dieser Software – Osteuropa – vor allem langsamere Modems für die Anbindung an das Internet genutzt werden, stößt das bereits zu diesem Zeitpunkt zu übertragende Datenvolumen aus Klassendateien des Applets und Bibliotheken 63 (Domino, Hilfesystem) von circa zwei MegaByte an die Grenze der Alltagstauglichkeit. Von seinem Bedienkomfort her knüpft das neue Applet nahtlos an die ursprüngliche Clientkomponente an. In einigen Punkten, wie zum Beispiel dem Einsatz von Tabellen oder der Einbindung des komfortablen Hilfesystems, bietet die neu entwickelte Clientkomponente sogar spürbare Verbesserungen. 64 4 Fazit Auf der Grundlage der objektorientierten Modellierung wurde im Rahmen dieser Arbeit eine Clientkomponente zur interaktiven Eingabe von Projektdaten einer Industriehalle entwickelt und realisiert. Dabei ist eine graphische Benutzeroberfläche entstanden, die alle notwendigen Eingabemasken bietet, um ein Hallenmodell komfortabel zu erzeugen und zu manipulieren. Des weiteren wurde dem Anwender ein umfangreiches und leicht zu bedienendes Hilfesystem an die Hand gegeben, das es ihm ermöglicht, schnell einen Überblick über die Funktionsweise des Applets zu erhalten. Durch die Ausführung des Clients als Applet hat der Softwareanbieter die Möglichkeit Flächen auf der entsprechenden Webseite für Werbezwecke zu vermarkten und somit zusätzliche Einnahmen zu erzielen. Der direkte Zugriff vom Applet auf die serverseitige Datenbank gewährleistet bei entsprechender Anpassung und Automatisierung Verfügbarkeit der Programmiersprache der Serverkomponente Anwendung. Java und Der die Einsatz Möglichkeit eine uneingeschränkte der objektorientierten der Ausführung der Clientkomponente in einem beliebigen Webbrowser garantiert zudem ein hohes Maß an Plattformunabhängigkeit. Die Architektur des Clients dürfte die spätere Einbindung eines Visualisierungsmoduls ermöglichen. Die Software konnte in Ermangelung einer einsatzbereiten Serverumgebung nur bedingt getestet werden. Die Anbindung an die Domino-Datenbank ist implementiert worden und gab bei der Kompilierung keine Fehler mehr aus. Bei einem Testlauf auf dem Server des Softwareanbieters in Ungarn kam es allerdings zu einem Fehler, dessen Ursache bis zum Abschluß dieser Arbeit noch nicht 65 geklärt werden konnte. Vor einem Einsatz in der Praxis ist dieser Teil also noch einmal zu überarbeiten. Alternativ zu diesem Applet wären noch zwei andere Lösungen denkbar: Man gestaltet die Clientkomponente wie bisher als Anwendung, erweitert um die hier entwickelten Methoden zum direkten Datenbankzugriff. Der Anwender hätte dann wieder die Möglichkeit seine Projekte offline einzugeben und lokal abzuspeichern. Er könnte dadurch seine Online-Zeit deutlich reduzieren und somit Kosten sparen. Der Softwareanbieter kann einen Teil der Oberfläche des Clients abgrenzen und als Anzeigefläche nutzen. Die Werbung kann dann bei jeder Verbindung mit dem Server aktualisiert werden. Als Beispiel aus der Praxis sei hier zum Beispiel eine Freeware-Version des Webbrowsers Opera genannt. Die zweite Möglichkeit besteht darin, lediglich die Visualisierung der Halle in einem Applet auszuführen. Dieses könnte dann in eine Webseite auf dem Domino Server eingebettet werden. Setzt man als Gestaltungselement zusätzlich Frames ein, können weitere Bereiche zur Eingabe der Projektdaten und zur Darstellung von Werbung abgegrenzt werden. Die von Lotus zur Anzeige von Datenbankinhalten bereitgestellten Gestaltungselemente könnten dabei die Aufgabe der Dialogfenster übernehmen. 66 5 Literaturverzeichnis [EH2003] Heimann, Erik Lotus Notes/Domino: Die Einführung Addison-Wesley Verlag, 2003 ISBN 3-8273-1847-5 [DTJava] Lotus Development Corporation Lotus Domino Toolkit for Java/CORBA Version 2.1 2000 [GK2002] Krüger, Guido Handbuch der Java-Programmierung Addison-Wesley Verlag, 3. Auflage, 2002 ISBN 3-8273-1949-8 [HOCO2001] Horstmann, Cay S.; Cornell, Gary core JAVA2 Band 1 – Grundlagen Markt + Technik Verlag, 2001 ISBN 3-8272-6016-7