Datenaustausch mit XML Entwicklung eines generischen Vermittlungs-Werkzeuges zwischen XML Schemas und Datenbanken Diplomarbeit im Fach Informatik an der Universität Fribourg 1. Referent: Prof. Andreas Meier 2. Referent: Prof. Pius Hättenschwiler Betreuer: Ass. Stefan Hüsemann Eingereicht am: 30.8.2002 Vorgelegt von: Thomas Schädler Rue de l'Industrie 2 1700 Fribourg [email protected] Kurzfassung Kurzfassung Diese Diplomarbeit befasst sich mit der Erstellung eines Vermittlungswerkzeuges zwischen XML Schemas und Datenbanken. XML Schemas werden heute immer mehr eingesetzt um Daten zwischen verschiedenen Systemen auszutauschen. Als Beispiel wird die Verwendung des AIDA IDML Schemas genauer erläutert. Dieses XML Schema wird von Organisationen im Bereich der Entwicklungsarbeit ausgearbeitet und eingesetzt. Ein noch ungelöstes Problem ist es aber, wie man die in diversen Datenbanken vorhandenen Informationen ohne grossen Aufwand in das gewünschte Format konvertieren kann. Die bisherige Praxis geht davon aus, dass man eine Datenbank besitzt, die selbst in der Lage ist dies zu bewerkstelligen oder aber man beauftragt einen Experten der diese Arbeit durch eine speziell zugeschnittene, neu zu erstellende Software erledigt. Dies setzt meist grosse Geldmittel voraus, was aber genau in dieser Branche nicht unbedingt gegeben ist, oder die anderweitig besser verwendet werden könnten. Hier setzt diese Diplomarbeit an und versucht diese Nachteile durch ein generisches Vermittlungs werkzeug zu beseitigen. Es ist detailliert beschrieben welche Grundkonzepte hinter einem solchen Werkzeug stehen. Die verschiedenen Ansätze um die Daten von einem Modell (Datenbank) in ein anderes Modell (XML Schema) zu konvertieren werden vertiefend erklärt. In einem weiteren Teil werden die genauen Anforderungen an das zu erstellenden Werkzeug aufgelistet und schliesslich wird genauer auf die Implementation eingegangen. Das Werkzeug wird dabei schrittweise - nach anfallender Komplexität des jeweiligen Modells - implementiert. Der aufmerksame Leser kann somit den Entstehungsprozess besser verfolgen und durch den modularen Aufbau ist eine mögliche Erweiterung dieses Werkzeuges nicht auszuschliessen. In einem letzten Teil wird die Arbeit mit dem neu erstellen Werkzeug für den Anwender erläutert. Da dieses Werkzeug nicht auf ein einzelnes XML Schema fixiert ist, sind viele Anwendungsmöglichkeiten denkbar und der Autor hofft, dass sein Werkzeug - da Open Source und damit absolut lizenzfrei - vielen Entwicklern aber auch normalen Anwendern gute Dienste leistet. Keywords XML - XML Schema - Mapping - Datenbanken - Vermittlungswerkzeug Autor: Thomas Schädler i Inhaltsverzeichnis Inhaltsverzeichnis 1 Einleitung............................................................................................................................... 1 1.1 Problemstellung .................................................................................................................. 1 1.2 Zielsetzung ......................................................................................................................... 2 1.3 Vorgehensweise ................................................................................................................. 3 2 Datenaustausch mit XML ........................................................................................................ 4 2.1 Grundlagen von XML........................................................................................................... 4 2.1.1 XML allgemein ................................................................................................................. 4 2.1.2 XML Schema und Namensräume...................................................................................... 5 2.1.3 DOM und SA X ................................................................................................................. 9 2.2 Vor- und Nachteile von XML ...............................................................................................11 2.3 Alternative Möglichkeiten zum Datenaustausch....................................................................12 2.4 IDML Schema....................................................................................................................13 2.5 Client/Server- oder Dreischichtenarchitektur ........................................................................17 3 Datenbanken.........................................................................................................................19 3.1 Grundlegende Anforderungen.............................................................................................19 3.2 Schnittstellen .....................................................................................................................19 3.3 Beziehung zwischen Datenbanken und XML........................................................................20 3.4 Mapping ............................................................................................................................21 3.4.1 Tabellen-basiertes Mapping.............................................................................................21 3.4.2 Vorlagen-gesteuertes Mapping ........................................................................................22 3.4.3 Objekt-relationales Mapping ............................................................................................22 4 Erstellung eines Modells ........................................................................................................25 4.1 Anforderungen an das Modell .............................................................................................25 4.2 Konstruktion des Modells ....................................................................................................25 4.3 Festlegung des Modells ......................................................................................................27 4.3.1 Der Konfigurator .............................................................................................................27 4.3.2 Die Serverkomponente....................................................................................................29 4.3.3 Die Mappingmodule ........................................................................................................29 5 Auswahl der Software / Programmiersprache ..........................................................................31 5.1 Anforderungen ...................................................................................................................31 5.2 Auswahl der Programmiersprache.......................................................................................31 5.3 Auswahl der Werkzeuge.....................................................................................................31 5.4 Auswahl der Bibliotheken....................................................................................................32 6 Implementation des Modells ...................................................................................................33 6.1 Speicherungshierarchie der Projektdaten.............................................................................33 6.2 Implementation des Konfigurators .......................................................................................33 6.2.1 Implementation des Moduls «Simple DB Export» ..............................................................36 6.2.2 Implementation des Moduls «Database to XML»...............................................................39 Autor: Thomas Schädler ii Inhaltsverzeichnis 6.3 Implementation des Servers ................................................................................................44 6.4 Erfahrungsbericht ...............................................................................................................45 7 Informationen für Anwender ...................................................................................................46 7.1 Einführung.........................................................................................................................46 7.2 Systemvoraussetzungen und Installation .............................................................................46 7.3 Handbuch: <xmlizer> configurator .......................................................................................47 7.3.1 Startparameter................................................................................................................47 7.3.2 Anleitung........................................................................................................................48 7.4 Handbuch: <xmlizer> server ...............................................................................................51 7.4.1 Startparameter................................................................................................................51 7.4.2 Anleitung........................................................................................................................52 7.4.3 Anpassung an Ihre Bedürfnisse .......................................................................................55 8 Schlussfolgerungen ...............................................................................................................56 9 Quellenangaben und Literaturverzeichnis................................................................................57 Anhang A: Quelltext <xmlizer> configurator....................................................................................60 Anhang B: Quelltext <xmlizer> server .......................................................................................... 239 Ehrenwörtliche Erklärung ............................................................................................................ 299 Autor: Thomas Schädler iii Abkürzungsverzeichnis Abkürzungsverzeichnis AIDA Accessible Information on Development Activities API Application Programming Interface (Programmierschnittstelle zu einer Applikation) ASP Active Server Pages (Proprietäre Internet-Technologie von Microsoft) DOM Document Object Model DTD Document Type Definition EDI Electronic Data/Document Interchange EDIFACT Electronic Data Interchange for Administration, Commerce and Transport HTML Hypertext Markup Language HTTP Hypertext Transfer Protocol IDE Integrated Development Environment IDML International Development Markup Language ISO International Standardization Organization (Internationales Normierungsgremium für den technischen Bereich) JDBC Java Database Connectivity JDOM Java-based Document Object Model NPO Non-Profit Organization ODBC Open Data Base Connectivity (Microsoft) PHP PHP Hypertext Preprocessor (rekursives Akronym) RDF Resource Description Framework (Standard für Metadaten-Formate) RFC Request for Comments (Vorschlag für eine Norm im TCP/IP-Bereich) RSS Rich Site Summary / RDF Site Summary / Really Simple Syndication SAX Simple API for XML SGML Standard Generalized Markup Language SQL Structured Query Language TCP/IP Transmission Control Protocol / Internet Protocol (Kommunikationsstandard) UML Unified Modeling Language URI Uniform/Universal Resource Identifier (Generische Menge an Zeichenketten um Ressourcen zu referenzieren) URL Universal/Uniform Resource Locator (Term für populäre URI's: http, ftp, etc…) URN Universal Resource Name (nach RFC 2141 definierter, eindeutiger Identifizierer) W3C World Wide Web Consortium (Vereinigung die sich um WWW-Standards kümmert) WWW World Wide Web XML Extensible Markup Language XOR Exclusive Or (Logischer Operator) Autor: Thomas Schädler iv Abbildungsverzeichnis Abbildungsverzeichnis Abbildung 1 : AIDA Projects Development Gateway Website ................................................... 2 Abbildung 2 : Beispieldokument garage.xml (XML Dokument).................................................. 4 Abbildung 3 : Bedeutung der Namensräume in XML................................................................ 6 Abbildung 4 : Beispieldokument garage.xsd (XML Schema)..................................................... 8 Abbildung 5 : Baumstruktur des Beispielschemas [XMLSPY 01] .............................................. 9 Abbildung 6 : Konzeption von DOM (Document Object Model)................................................. 9 Abbildung 7 : Gegenüberstellung von DOM und SAX.............................................................11 Abbildung 8 : Site Description Schema: Beispiel von idmlInfo.xml ...........................................13 Abbildung 9 : IDML Core Activity Schema (Baum) [XMLSPY 01] .............................................14 Abbildung 10 : Core Activity Schema: Beispiel von activities.xml ...............................................16 Abbildung 11 : IDML Datenaustausch (Standardprozedur)........................................................17 Abbildung 12 : IDML Datenaustausch (mit Vermittlungswerkzeug) ............................................18 Abbildung 13 : Beispiel für Tabellen-basiertes Mapping [Bourret 02] ..........................................22 Abbildung 14 : Beispiel für Vorlagen-gesteuertes Mapping .......................................................22 Abbildung 15 : XML Dokument aus Abbildung 2 als Objekt-Schema..........................................23 Abbildung 16 : XML Dokument aus Abbildung 2 als Objekt-Baum, DOM-Baum und Klassenhierarchie .............................................................................................24 Abbildung 17 : Architektur des Vermittlungswerkzeugs in der Übersicht.....................................26 Abbildung 18 : xmlizer.project.config.xsd (Baum, kein Mapping) [XMLSPY 01] ...........................28 Abbildung 19 : Beispiel einer Konfigurationsdatei ohne Mappinginformationen ...........................29 Abbildung 20 : UML Klassen-Diagramm des Konfigurators (User Interface) [JVision 02] .............34 Abbildung 21 : UML Klassen-Diagramm des Konfigurators (Daten) [JVision 02] .........................35 Abbildung 22 : Beispielausgabe des Moduls «Simple DB Export» (simple) ................................36 Abbildung 23 : xmlizer.smdbe.verbose.dtd...............................................................................37 Abbildung 24 : Beispielausgabe des Moduls «Simple DB Export» (verbose) ..............................38 Abbildung 25 : Beispiel der Mappingdaten für das Modul «Simple DB Export» (gekürzt).............38 Abbildung 26 : xmlizer.project.config.xsd (Baum, nur Mapping) [XMLSPY 01] ............................39 Abbildung 27 : Beispiel der Mappingdaten für das Modul «Database to XML» ...........................40 Abbildung 28 : UML Klassen-Diagramm des Servers (Komplett) [JVision 02] .............................44 Abbildung 29 : Der Konfigurator in Aktion ................................................................................48 Abbildung 30 : Das Module «Simple DB Export» in Aktion ........................................................49 Abbildung 31 : Das Modul «Database to XML» in Aktion : Der Datenbankbrowser .....................50 Abbildung 32 : Das Modul «Database to XML» in Aktion: Drag und Drop einer Abfrage ..............51 Abbildung 33 : Beispiel zweier URL's für das Modul «Simple DB Export» ..................................53 Abbildung 34 : Beispiel einer URL für das Modul «Database to XML» .......................................53 Abbildung 35 : Auflistung der Projekte des Servers (index.html) ................................................53 Abbildung 36 : Projektdetails für das Modul «Database to XML»...............................................54 Abbildung 37 : Beispiel einer HTML-formatierten Ausgabe der XML Daten ................................54 Autor: Thomas Schädler v 1 Einleitung 1 Einleitung 1.1 Problemstellung Humanitäre Organisationen haben ein grosses Bedürfnis nach Kommunikation innerhalb der Organisation selber, aber auch gegenüber ihren Partnern, die im folgenden als Stakeholder bezeichnet werden. Die internationale Arbeit von humanitären Organisationen stellt eine weitere Hürde für eine gute Kommunikation und Information aller Stakeholder dar. Humanitäre Projekte müssen geplant, durchgeführt und anschliessend evaluiert werden. Diese Arbeit generiert eine grosse Menge von Daten bei allen Beteiligten. Das Medium Internet kann dabei eine grosse Hilfe sein, da dessen Einsatz relativ billig und ortsunabhängig ist. Das Problem ist allerdings die Menge an Daten und die verschiedenen Datenformate die bei den verschiedenen Stakeholdern eingesetzt werden. Um an die Daten zu kommen müssen die Stakeholder viele verschiedene Quellen finden und analysieren. Besser wäre es ein definiertes Datenformat zu haben, das dezentral gespeichert, aber von einer zent ralen Stelle aus (z.B. von einer Website) durchsucht werden kann. Weitere Ansprüche an eine solche Webapplikation sind v.a. aus der Sicht von NPO's (Non-Profit Organisationen) der Einsatz von lizenzfreier Software und offenen Standards. Ausserdem sollten die eingesetzten Standards zukunftssicher sein, damit die angehäuften Daten nicht in kürze wieder neu aufbereitet werden müssen. Eine Lösung für den Datenaustausch von Projektinformationen in Bezug auf Entwicklungsprojekte wird momentan in Form eines XML Schemas ausgearbeitet [IDML 01]. Dieses Schema ist auch Grundlage dieser Arbeit. Wie in Abbildung 1 zu sehen ist hat das AIDA Projekt hat schon eine WebApplikation entwickelt um weltweit nach Entwicklungsprojekten zu suchen. Ein noch ungelöstes Problem ist auch die Speicherung von (XML-) Projektdaten in einer (schon vorhandenen) Datenbank und das Auslesen der Datensätze um das Austauchformat zu erhalten. Eine mögliche Lösung ist das Programmieren eines Filters, der die richtigen Daten automatisch aus der Datenbank auslesen und in das gewünschte XML Schema umwandeln oder vorhandene XML Daten in die Datenbank aufnehmen kann. Besser wäre es ein generisches Werkzeug zu haben, das zwischen Datenbank und XML Schema vermitteln kann. Autor: Thomas Schädler 1 1 Einleitung Abbildung 1 : AIDA Projects Development Gateway Website Es gibt drei Grundlegende Szenarien: 1. Es ist keine Datenbank vorhanden (Die XML Daten werden in einer neu angelegten Datenbank gespeichert.) 2. Es ist kein XML Schema vorhanden (Die Daten aus der Datenbank werden in einem neu generierten XML Format ausgegeben.) 3. Datenbank und Schema sind vorhanden, aber die Abbildung in beide Richtungen ist noch nicht erledigt.) Am häufigsten wird wohl der dritte Fall vorkommen, da alle Stakeholder normalerweise schon Datenbanken besitzen und nur die Daten nach einem ebenfalls schon vorhandenen XM L Schema ex - bzw. importieren wollen. Diese Arbeit benötigt genau Kenntnisse der Datenbank und des zu verwendenden XML Schemas. Beim ersten und zweiten Fall gibt es Möglichkeiten automatisch aus der Datenbank ein XML Schema zu generieren oder umgekehrt. 1.2 Zielsetzung Die Zielsetzung dieser Diplomarbeit ist es ein Werkzeug zu entwickeln, das beliebige Datenbanken auf beliebige XML Schemas abbilden kann, vorausgesetzt natürlich die Datenbank stellt alle Informationen zur Verfügung die benötigt werden. Primär ist jedoch die Funktion um XML Daten aus beliebigen Datenbanken auszulesen und in das IDML Schema zu konvertieren, um damit die schnelle Anbindung vieler neuer Datenbanken für das AIDA Projekt zu ermöglichen [AIDA 01]. Einmal für die Autor: Thomas Schädler 2 1 Einleitung jeweilige Datenbank und das benutzte XML Schema konfiguriert, vermittelt dieses Werkzeug automatisch zwischen Datenbank und XML Schema. Es ist nachher möglich, Daten aus der Datenbank als gültige XML Datei auszulesen, die nachher verschickt oder bearbeitet werden können. Auch die Aufnahme einer XML Datei in die Datenbank ist möglich. Dies würde auch bei Änderungen in der Anordnung (Datenbank oder XML Schema) eine einfache Möglichkeit darstellen auf die neue Situation zu reagieren. 1.3 Vorgehensweise In einem ersten Teil der Arbeit werden grundsätzliche Fragen zu XML (Extendend Markup Language) geklärt. Vor- und Nachteile von XML werden analysiert und ein Überblick über die momentan verwendeten Technologien zum Austausch von Informationen über das Internet wird verschafft. Hauptaugenmerk liegt dabei auf den verwendeten Standards (XML allgemein, XML Schema, DOM und SAX), da diese Standards im weiteren Verlauf dieser Arbeit exzessiv verwendet und analysiert werden. An einem kleinen Beispiel wird die Verwendung von XML und XML Schema erklärt. In einem zweiten Teil wird auf die Anforderungen an die zu verwendenden Datenbanken eingegangen. Da es Ziel der Arbeit ist mit möglichst vielen verschiedenen Datenbanken zusammenzuarbeiten ist eine Suche nach der offensten Programmierschnittstelle (API: Application Programming Interface) nötig. Dieses Kriterium schränkt schon früh ein, welche Programmiersprache sich für die künftige Implementation verwenden lässt. Nach der Festlegung der Grundlagen wird in einem dritten Teil ein Modell aufgestellt, dass dann für die Implementation als Grundlage dienen wird. Alle bisher gesammelten Anforderungen müssen in dem Modell vereinigt werden und werden detailliert beschrieben. Die Anforderungen an die Benutzerschnittstelle müssen auch abgeklärt werden. Es gibt eine Unmenge an möglichen Standards, Sprachen und Softwarekomponenten, mit dem so ein Modell implementiert werden kann. Im vierten Teil werden diese Möglichkeiten und Kombinationen kurz analysiert und bewertet. Im fünften Teil dieser Arbeit wird das aufgestellte Modell mit der am besten bewerteten Software implementiert und die dabei auftretenden positiven und negativen Erfahrungen erläutert. Die Basis für die Implementation wird mit Hilfe von UML Klassen-Diagrammen erstellt. Das daraus erstellte CodeGerüst wird anschliessen nach dem Top-Down-Verfahren implementiert und je nach Notwendigkeit erweitert. Im sechsten und letzten Teil dieser Arbeit wird die Arbeit mit der nun erstellten Software für den zukünftigen Anwender in der Art eines Handbuchs erklärt um ein produktives Arbeiten zu erleichtern. Autor: Thomas Schädler 3 2 Datenaustausch mit XML 2 Datenaustausch mit XML 2.1 Grundlagen von XML Das WWW (World Wide Web) bietet heute mehr als nur statische Inhalte. Leider ist HTML (Hypertext Markup Language) nur bedingt nützlich um neue Anwendungen im Internet abrufbar zu machen. HTML wurde als Auszeichnungssprache konzipiert und beschreibt wie ein Dokument in einem Webbrowser darzustellen ist. Bei HTML ist die Semantik der Auszeichnungselemente (engl.: tag) fest definiert und die Menge an Auszeichnungselementen ist genau definiert und somit limitiert. Diese Einschränkung ist genau das Problem, wenn man Daten über das Internet austauschen oder eigene Strukturen definieren möchte. 2.1.1 XML allgemein XML (Extended Markup Language) ist keine Markupsprache wie HTML, sondern eine Metasprache 1 zur Definition von Markupsprachen. XML wurde vom W3C (World Wide Web Consortium ) definiert welches auch HTML definierte. HTML ist eine Untermenge von XML, und XML ist wiederum eine Untermenge von SGML (Standard Generalized Markup Language) welches schon 1986 vom W3C als ISO-Standard (ISO 8879) definiert wurde. Da SGML nicht direkt für das WWW definiert wurde und eine sehr komplexe Sprache ist wurde XML entwickelt um diese Lücke zu schliessen. Um die Syntax von XML besser zu verstehen folgt ein kurzes Beispieldokument. In der erste Zeile jedes XML Dokuments muss der Prolog stehen. Im Prolog stehen Versionsnummer, Codierung und eine Anweisung ob das Dokument auf eine externe DTD (Document Type Definition) oder ein XML Schema (Alternative einer DTD) verweist oder ohne auskommt. Im Wurzelelement (<garage>) werden die benötigten Namensräume definiert. Leere Elemente darf man in XML auch wie im Beispiel das Optionen-Element abkürzen (<option/>), es kann aber auch weiterhin die aus HTML bekannte Form (<option></option>) verwendet werden. <?xml version="1.0" encoding="ISO8859-1" standalone="no"?> Prolog <!-- Dies ist ein Kommentar --> <garage xmlns="http://www.e-freak.ch/xml/garage" xmlns:xsi="http://www.w3.org/2000/10/XMLSchema-instance" Namens- xsi:schemaLocation="http://www.e-freak.ch/xml/garage garage.xsd"> raum <motorrad> definitionen <marke>Yamaha</marke> <typ herstellungsjahr="1984" zylinder="1">XT 550</typ> <farbe>Schwarz</farbe> <option/> MotorradElement </motorrad> </garage> Abbildung 2 1 : Beispieldokument garage.xml (XML Dokument) World Wide Web Consortium http://www.w3.org/ Autor: Thomas Schädler 4 2 Datenaustausch mit XML Auszeichnungselement können auch Attribute verwenden, um zusätzliche Daten aufzunehmen. Im konkreten Beispiel hat das Auszeichnungselement «typ» ein Attribut «herstellungsjahr» und ein Attribut «zylinder». Ob man ein Attribut oder ein neues Auszeichnungselement benutzt hängt von der Art der Daten ab. Es gibt keine allgemeingültigen Regeln, aber als Faustregeln kann man folgende Hinweise zu Rate ziehen [XMLS 01]: • Daten die wiederum in Unterkategorien gegliedert werden, die andere Auszeichnungselemente enthalten, müssen als eigenes Auszeichnungselement definiert werden (in Attributen kann man keine Auszeichnungselemente speichern, sondern nur simplen Text). • Wenn Daten mehrere Zeilen lang sein können, muss auch ein eigenes Auszeichnungselement verwendet werden. (Man könnte auch ein Attribut verwenden, allerdings wird der Code dann sehr unleserlich.) • Wenn Daten oft ändern sollte man auch eigene Auszeichnungselemente definieren. (Mit heutigen XML-Editoren sind Auszeichnungselemente einfacher zu finden und zu ändern als Attribute). • Kurze und kaum zu ändernde Daten werden bevorzugt als Attribut gespeichert. • Sind bei den Daten eine limitierte Anzahl von Möglichkeiten vorgesehen (Auswahl), dann benutzt man bevorzugt Attribute (XML Editoren können dann z.B. die Auswahl das DropdownListe anzeigen und es können dann nur die Daten eingetragen werden die dafür in dem XML Schema definiert wurden). Damit ein XML Dokument syntaktisch korrekt ist (engl.: well-formed) muss sich ein XML Dokument strikt an folgende Regeln halten (ein komplette Liste aller Regeln und damit verbundne Fragen kann man bei [UUC 01] nachlesen): • ein XML Dokument muss mindestens ein Element enthalten • es darf nur ein Wurzel-Element enthalten, welches alle anderen Elemente umschliesst • Elemente müssen sich immer komplett umschliessen und dürfen sich nicht überlappen Durch das Einhalten aller Regeln wird der Austausch von XML Dokumenten erst möglich und es müssen keine speziellen Programme geschrieben werden um Fehler zu erkennen. Ein XML Dokument alleine hat aber noch keine Aussagekraft (für eine Maschine). Das Dokument kann zwar von einem Menschen gelesen und verstanden werden, eine Maschine braucht aber mehr Informationen zu den benutzten Auszeichnungselementen, da diese ja frei erfunden wurden. Damit ein XML Dokument gültig (engl.: valid) ist muss es eine DTD oder ein XML Schema assoziiert haben. 2.1.2 XML Schema und Namensräume Im folgenden wird nur auf den XML Schema Standard eingegangen, da die DTD’s in Zukunft von XML Schema abgelöst werden sollten. Am 3. Mai 2001 hat das World Wide Web Consortium XML Schema als «Recommendation» herausgegeben und dieser Standard wird jetzt als stabil bezeichnet [W3CS 01]. XML Schema bietet im Vergleich zu einer DTD bessere Lesbarkeit (XML Syntax), über 40 vordefinierte Datentypen, Möglichkeit der Gruppierung von Elementen, Möglichkeit der objektorientierten Autor: Thomas Schädler 5 2 Datenaustausch mit XML Programmierung (Vererbung, Erweiterbarkeit und Restriktion), Gebrauch von Namensräumen und Reguläre Ausdrücke um eigene Typen genau zu definieren. Ein XML Dokument kann in unterschiedlichen Anwendungsgebieten verwendet werden. Namensräume (engl.: namespaces) werden definiert, damit die es keine Konflikte zwischen den Elementnamen verschiedener XML Schemas geben kann. Namensräume werden mittels einer einmaligen, fiktiven URI (Uniform Resource Identifier) oder URN (Universal Resource Name) voneinander unterschieden. Das XML Schema muss also nicht – kann aber – unter dieser URI erreichbar sein. Nach [Castro 00] wurden URI's gewählt, da die Namensgebung von URI's von Natur aus einmalig ist (jeder Domainnamen kann nur einmal ve rgeben werden). Jedes Schema hat seinen eigenen Namensraum, kann aber auch zu einem bestehenden Namensraum hinzugefügt werden, falls es keine Kollisionen der verwendeten Element- und Attributnamen geben kann (engl.: sharing). Abbildung 3 verdeutlicht die Wichtigkeit von Namensräumen und zeigt auf, in welcher Verbindung die verschiedenen Namensräume stehen. ... ... schemaLocation="A xmlns:xsd="B" garage.xsd" ... B: «schema-of-schemas» targetNamespace="A" (definiert die Elemente ... des Namensraumes B, um damit eigene Schemen zu definieren) garage.xml garage.xsd XMLSchema.xsd Ÿ benutzt Elemente aus Ÿ definiert Elemente des Ÿ benutzt Elemente aus dem Namensraum A Namensraumes A dem Namensraum B Ÿ benutzt Elemente des (URL des Schemas der Namensraumes B Schemen: W3C-Vorgabe) ...validiert das Ausgangsdokument nach den Regeln des übergeordneten Dokuments Abbildung 3 : Bedeutung der Namensräume in XML Definiert man für die Namensräume ein Präfix (z.B. «xmlns:xsd» mit Präfix «xsd»), muss man bei Gebrauch eines Elementes aus diesem Namensraum das Präfix verwenden. Der Bezeichner «xmlns» für Namensräume ist reserviert, wie alle Bezeichner, die mit «xml» beginnen. Ohne Präfix sind die Elemente global definiert und dürfen daher ohne Präfix verwendet werden. Es gibt daher drei unterschiedliche Varianten um mit Namensräumen zu arbeiten: • Man definiert den Namensraum des Schemas der Schemen global und die eigenen Elemente müssen mit einem Präfix gekennzeichnet werden. • Man definiert den eigenen Namensraum global und den Namensraum des Schemas der Schemen mit einem Präfix oder • man kann auch beiden Namensräumen ein Präfix vergeben. Autor: Thomas Schädler 6 2 Datenaustausch mit XML Im folgenden wird die zweite - besser lesbare - Variante verwendet: Alle Elemente aus dem Namensraum des Schemas der Schemen müssen also mit Präfix deklariert werden, eigene Elemente nicht. Ein XML Schema ist ein Dokument das die erlaubte Syntax eines XML Dokuments definiert. Um XML Schema besser zu verstehen, folgt ein kurzes Beispieldokument, dass ein XML Schema für das in Abbildung 2 verwendete XML Dokument sein könnte. Wie schon erwähnt, steht im Prolog des XML Dokuments aus Abbildung 2 «standalone=no» und in der sechsten Zeile wird auf eine Datei «garage.xsd» verwiesen. Dieses bedeutet, das dem XML Dokument ein XML Schema zugeordnet werden kann und das XML Dokument also nur zusammen mit diesem XML Schema gültig sein kann. In der ersten Zeile in Abbildung 4 steht wiederum der bekannte XML Prolog, da es sich um ein normales XML Dokument handelt. Als Wurzelelement jedes XML Schemas steht das schema-Element, welches das ganze Schema umschliesst. In ihm werden auch die Namensräume definiert. Die erste Zeile dient dazu, die im Dokument definierten Elemente (garage, marke, type etc.) einem eigenen Zielnamensraum zuzuordnen (engl.: targetNamespace). Zeile zwei importiert die benötigten Elemente um ein Schema aufzubauen aus dem Namensraum des Schemas der Schemen (z.B. element, complexType, simpleType, restriction, string, integer etc.) und definiert gleichzeitig das Präfix, das benötigt wird um auf Elemente aus dessen Namensraum zuzugreifen («xsd»). Die nächste Zeile definiert den Standard-Namensraum für dieses Dokument - in diesem Beispiel den Zielnamensraum. Autor: Thomas Schädler 7 2 Datenaustausch mit XML <?xml version="1.0"?> <xsd:schema targetNamespace="http://www.e-freak.ch/xml/garage" xmlns:xsd="http://www.w3.org/2000/10/XMLSchema" xmlns="http://www.e-freak.ch/xml/garage" Das Garagen-Element enthält elementFormDefault="qualified"> eine Sequenz von Motorrad- <xsd:element name="garage"> Elementen (0 bis unendlich) <xsd:complexType> <xsd:sequence> <xsd:element ref="motorrad" minOccurs="0" maxOccurs="unbounded"/> </xsd:sequence> </xsd:complexType> </xsd:element> Das Typ-Element besteht <xsd:element name="motorrad"> aus einem komplexen Typ, <xsd:complexType> der lokal definiert ist (eng. <xsd:sequence> anonymous type): <xsd:element name="marke" type="xsd:string"/> Inhalt ist ein String (Typ- <xsd:element name="typ"> Bezeichnung) und zwei <xsd:complexType> Attribute (herstellungsjahr <xsd:simpleContent> und zylinder) <xsd:extension base="xsd:string"> <xsd:attribute name="herstellungsjahr" type="xsd:year" use="optional"/> <xsd:attribute name="zylinder" type="zylinderType" use="required"/> </xsd:extension> </xsd:simpleContent> Das Zylinder-Attribut hat </xsd:complexType> einen weiter unten selbst </xsd:element> definierten Typ (engl. <xsd:element name="farbe" type="xsd:string"/> named type) <xsd:element name="option" type="xsd:string" minOccurs="0" maxOccurs="unbounded"/> </xsd:sequence> minOccurs und maxOccurs </xsd:complexType> sind standardmässig immer </xsd:element> <xsd:simpleType name="zylinderType"> auf 1 gesetzt. <xsd:restriction base="xsd:integer"> <xsd:minInclusive value="1"/> Definition des Types für das <xsd:maxInclusive value="8"/> Zylinder-Element: </xsd:restriction> </xsd:simpleType> Basistyp: Integer akzeptiert als Min. 1, Max. 8 </xsd:schema> Abbildung 4 : Beispieldokument garage.xsd (XML Schema) Wie schon erwähnt, müssen Elemente aus dem Standard-Namensraum nicht mit einem Präfix qualifiziert werden. Die letzte Zeile im schema-Element bedeutet, dass Instanzen die dieses Schema benut zen, den Namensraum der in «targetNamespace» angegeben ist deklarieren müssen, damit sie die neu definierten Elemente benutzen können. Ausserdem fügt es lokal deklarierte Elemente und Attribute zum Zielnamensraum hinzu. Wie in Abbildung 5 zu sehen ist, definiert das in Abbildung 4 aufgeführte XML Schema einen Baum, der die Struktur der XML Dokumente festlegt, die sich an dieses XML Schema halten. Die Wurzel des Baumes ist das Garagen-Element. Innerhalb dieses Elementes kann es eine unbestimmte Anzahl an Autor: Thomas Schädler 8 2 Datenaustausch mit XML Motorrad-Elementen haben - keines bis unendlich viele. Ein Motorrad-Element wiederum besteht aus einem Marken-Element, einem Typ-Element, einem Farben-Element und einem oder mehreren, optionalen Optionen-Elementen. Unten sind noch die Attribute des Typ-Elements aufgeführt. Jedes TypElement muss also ein Zylinder-Attribut haben, das Herstellungsjahr-Attribut ist jedoch optional. Abbildung 5 : Baumstruktur des Beispielschemas [XMLSPY 01] 2.1.3 DOM und SAX Um XML Dokumente weiterzuverarbeiten, muss eine einfache, standardisierte Schnittstelle vorhanden sein, um auf die interne Struktur eines XML Dokuments zugreifen zu können. Dazu wurde vom World Wide Web Consortium DOM (Document Object Model) und SAX (Simple API for XML) entworfen. DOM uns SAX sind plattformunabhängige Schnittstellen die den Zugriff auf XML Dokumente standardisieren. Abbildung 6 verdeutlicht das Konzept von DOM. Um mit DOM auf ein XML Dokument zuzugreifen, muss das XML Dokument zuerst geparst werden. Sind keine syntaktischen Fehler vorhanden, wird das XML Dokument gegen das XML Schema validiert. Ist das XML Dokument korrekt, wird das Dokument auf eine Baumstruktur (siehe Abbildung 5) abgebildet. DOM definiert nun verschiedene Methoden, mit denen man diesen Baum komfortabel bearbeiten kann. Es besteht die Möglichkeit, den <tag></tag> «ta ... DOM A Parser P Programme I beispiel.xml DOM Baum Abbildung 6 Autor: Thomas Schädler : Konzeption von DOM (Document Object Model) 9 2 Datenaustausch mit XML Baum zu ändern, im Baum zu suchen, Elemente (Blätter des Baumes) zu ändern, löschen und hinzufügen etc. Eine genaue Beschreibung des Standards findet man in [W3CD 01] oder in [Morrison 00]. Obwohl DOM noch als junger Standard bezeichnet werden kann, finden sich eine Menge verschiedener Implementation. Eine der bekanntesten, weil auch schon früh verfügbaren DOM Implementationen ist die Microsoft DOM Engine. Dadurch ist auch der Microsoft Internet Explorer (ab Version 5) der einzige verbreitete Browser mit einer DOM Anbindung. Nach [Morrison 00] ist die MS DOM Engine recht gut implementiert, hat aber ein paar nicht dem Standard entsprechende Ausnahmen. IBM hat auch eine eigene DOM Implementation (in Java oder C). Viele Programmiersprachen bringen aber heute schon ihre eigene DOM Implementation mit, oder mindestens eine Schnittstelle zu einer frei verfügbaren DOM Implementation. Unter anderem Java, C++, VisualBasic, ASP, PHP, Perl, etc. Einen etwas anderen Weg um XML Dokumente weiterzuverarbeiten ist SAX (Simple API for XML, API = Application Programming Interface (deutsch: Programmierschnittstelle). SAX ist kein Standard des World Wide Web Consortiums, sondern ein sog. De-facto-Standard. Wie der Name schon sagt, ist SAX nicht so komplex wie DOM. Allerdings kann man SAX nur begrenzt einsetzen. Ein SAX Parser kann nur Daten aus XML Dokumenten auslesen, nicht aber die Struktur verändern. Dadurch ist ein SAX Parser schnell, flexibel und leichter zu implementieren und zu benutzen. SAX ist im Gegensatz zu DOM ereignisbasiert (engl.: event-based). Beim parsen eines XML Dokuments werden beim Antreffen eines bestimmten Elements (Anfangs-Tag, End-Tag, etc.) die Daten an die Anwendung weitergeleitet und dort verarbeitet. Verfügbare SAX Implementationen gibt es zur Zeit für Java, Python, Perl und PHP. Autor: Thomas Schädler 10 2 Datenaustausch mit XML DOM (Document Object Model): Ÿ für komplexe Dokumente Ÿ für Dokumente die von verschiedenen Datenquellen stammen Ÿ bildet eine Baumstruktur des Dokumentes Ÿ für Dokumente die komplexe Bearbeitung benötigen Ÿ objektbasiert Ÿ freier Zugriff (engl.: random-access) auf die Elemente eines Dokuments Ÿ Lese- und Schreibzugriff möglich SAX (Simple API for XML): Ÿ für einfache Dokumente Ÿ für grosse Dokumente (physikalische Dateigrösse) Ÿ Ereignisbasierte Programmierung Ÿ für Dokumente die keine Änderung der Dokumentenstruktur benötigen Ÿ sequentieller Zugriff auf die Elemente eines Dokuments Ÿ nur Lesezugriff möglich Abbildung 7 : Gegenüberstellung von DOM und SAX Ob DOM oder SAX in einer Anwendung verwendet wird (oder häufig eine Kombination davon), hängt von der Art der Anwendung ab. Abbildung 7 soll dabei helfen, die Entscheidung ob DOM oder SAX verwendet wird zu erleichtern (aus [Vanoirbeek/Aboukhaled 00]). Das hier aufgeführte Beispiel wurde mit Hilfe von XMLSpy [XMLSPY 01] entworfen und validiert. XMLSpy ist ein kommerzielles Produkt, das praktisch alle Aspekte rund um XML berücksichtigt und übersichtliches Arbeiten mit XML, XML Schema, DTD's, XSL und weiteren XML Dialekten erlaubt. 2.2 Vor- und Nachteile von XML Die Bedeutung von XML nimmt immer mehr zu. Der wichtigste Grund dürfte sein, dass es ein offener und plattformunabhängiger Standard ist. Dies sind auch die grossen Vorteile von XML gegenüber ähnlichen Lösungen. Ein offener Standard hat aber noch mehr Vorteile: Er ist absolut lizenzfrei und wird durch immer neue Applikationen und Erweiterungen weltweit weiterentwickelt. Allerdings kann das auch als Nachteil gewertet werden, da viel Entwicklungswerkzeuge noch nicht fertiggestellt sind und sich in der Entwicklung befinden. Ein weiterer grosser Vorteil von XML ist, dass ein XML Dok ument ein normales Textdokument darstellt, das ganz einfach weiterverarbeitet werden kann und ausserdem noch für einen Menschen lesbar ist (engl.: human-readable). Damit kann eine Information über längere Zeit ohne Konvertierungsprobleme gespeichert werden und auch in der schnelllebigen Softwareindustrie (alle paar Jahre eine neuer Standard) bleibt die Aussagekraft eines XML Dokuments immer gleich. [Bellanet 01] Autor: Thomas Schädler 11 2 Datenaustausch mit XML Weitere Vorteile sind auch die einfache Kommunikationsinfrastruktur. Um XML Dokumente zu verschicken kann jedes herkömmliche Netzwerk verwendet werden, wobei hauptsächlich auf HTTP (Hypertext Transfer Protocol) über TCP/IP (Transmission Control Protocol / Internet Protocol) zurückgegriffen wird – dem Standard im Internet. Die dabei verwendete Bandbreite ist relativ klein, kann aber durch speziellere Protokolle (vgl. EDI) noch kleiner gehalten werden. Als negativ wird dabei der grosse Overhead von XML angesehen – ein grosser Teil eines XML Dokuments nimmt allein die Tag-Struktur ein, die Daten eher den kleineren Teil. Konkrete Zahlen sind schwer zu bekommen und hängen von dem verwendeten Schema (oder DTD) ab. Dies ist jedoch auf der anderen Seite wieder ein Vorteil: die XML Dokumente sind besser lesbar. Ausserdem kann ein XML Dokument beim Austausch komprimiert werden um die Bandbreite bei der Übertragung zu schonen. Als Nachteile sind aufzuführen, dass es nicht immer leicht ist ein passendes XML Schema oder eine DTD zu entwerfen. Auch das gesamte String-Handling (XML Daten sind ja nur Textdateien) in der Entwicklung von XML Applikationen wird als negativ erachtet. Jedoch ist es jedem Entwickler selbst überlassen, welche Programmiersprachen er verwendet um XML Dokumente zu verarbeiten. Es sollte also eine passende Verarbeitungssprache gesucht werden, die die Verarbeitung von Strings gut unterstützt. 2.3 Alternative Möglichkeiten zum Datenaustausch Bisher benutzen die meisten Applikationen kein spezielles Format um Daten auszutauschen, da keine Notwendigkeit gesehen wurde, diese Daten anderswo zu benutzen als in eigenen Applikationen die untereinander natürlich das Austauschformat kannten, und somit kein Problem mit der Kodierung und Entkodierung dieser Daten hatten. Durch die heutigen Möglichkeiten der Kommunikation wurde es aber immer interessanter Daten auch mit Geschäftspartnern auszutauschen die nicht die gleichen technischen Voraussetzungen erfüllten. Diese also z.B. eine andere Software einsetzten, eine andere Plattform (Hardware, Betriebssystem), oder auch nur ein anderes Datenbank Management System. Mit der Zeit wurden für viele Standardapplikationen und Programmiersprachen Schnittstellen und Protokolle geschaffen, mit denen es möglich ist, trotz allem miteinander zu kommunizieren. Dies löst aber noch nicht das Problem des Datenformates. Eine Lösung verspricht EDI [EDI 01]. Electronic Data Interchange ist eine Lösung für Business-toBusiness Kommunikation, entwickelt durch das "EDIFACT Standard Messages Directory" der Vereinten Nationen (Electronic Data Interchange for Administration, Commerce and Transport) [UNEDI 01]. EDI hat ein paar Fähigkeiten die jetzt auch mit XML möglich wären und wird deshalb auch als XML/EDI weiterentwickelt. Als Hauptpunkt sind die hohen Kosten zu vermerken die EDI bei der Einführung verursacht. Da EDI hauptsächlich für den betriebswirtschaftlichen und organisatorischen Datenverkehr innerhalb einer Unternehmung oder zwischen einzelnen Unternehmen entwickelt worden ist, benutzt man häufig ein eigenes VAN (Value Added Network), für welches Benutzungsgebühren entstehen. Ausserdem muss immer noch die benutzte Datenbank eine EDI-Schnittstelle besitzen, da man sonst mit weiteren Softwarekosten rechnen muss. [EDIAT 01] Autor: Thomas Schädler 12 2 Datenaustausch mit XML 2.4 IDML Schema Das IDML Schema ist ein speziell entwickeltes XML Schema um Daten über Entwicklungsprojekte zu speichern und auszutauschen. Da dieses Schema noch dauernd geändert wird sind die hier erklärten Sachverhalte mit Vorsicht zu geniessen. Die Grundstruktur wird sich aber nicht mehr gross ändern, da das IDML Schema schon bei Version 0.9 angelangt ist. Die Grundlagen um mit Hilfe von IDML Schema Daten bereitzustellen sollen hier aufgezeigt werden. Das Vermittlungswerkzeug muss sich genau an dieses Schema halten, da die Daten sonst beim weiterverarbeiten nicht validiert werden können und für ungültig erklärt werden müssen. Es werden mindestens zwei Dateien benötigt: • idmlInfo.xml Æ die Beschreibung (engl: site description) basiert auf dem «Site Description Schema» • activities.xml Æ die Daten (engl: activity information) Æ basiert auf dem «Core Activity Schema» und dem «Extended Schema» Die Beschreibung kann statisch generiert werden, da dieses XML Dokument nur wenige Daten beinhalten muss und erst auf die eigentlichen Projektdaten verweist. Die Beschreibung muss immer im root-Verzeichnis (Oberste Ebene: /) des Webserver stehen, auf dem auch die Daten abgelegt sind (oder zumindest auf dem die Daten auch gezogen werden können). Es beinhaltet die Version des verwendeten IDML Schemas, das Datum der letzten Änderung, eine Kontaktadresse (Email) dessen der sich bei dieser Organisation um die Bereitstellung der IDML Daten kümmert und einen Link auf die Daten selbst (Beispiel siehe Abbildung 8). Dieser Link kann auf eine statische XML Datei ve rweisen <?xml version="1.0"?> IDML Versionsnummer <idmlInfo> <idmlVersion>0.9</idmlVersion> <dataLink> URL zu den Aktivitäten, kann auch ein Skript sein. (dyna- <dataType>activity</dataType> misch oder statisch) <url>http://www.some.org/activities.xml</url> <format>xml</format> <updated>2001-01-01</updated> Datum des letzten updates </dataLink> <contactEmail>[email protected]</contactEmail> </idmlInfo> Kontaktadresse des Datenpflegers </xml> Abbildung 8 : Site Description Schema: Beispiel von idmlInfo.xml oder aber auf ein Skript, das die Daten dort dynamisch zur Verfügung stellt. Momentan wird zu Testzwecken häufig die statische Variante bevorzugt, da die Daten noch nicht dynamisch generiert werden können. Autor: Thomas Schädler 13 2 Datenaustausch mit XML Abbildung 9 Autor: Thomas Schädler : IDML Core Activity Schema (Baum) [XMLSPY 01] 14 2 Datenaustausch mit XML Der Vorteil dieses geteilten Ansatzes ist ganz eindeutig die Möglichkeit eine Standarddatei (idmlInfo.xml) zu konsultieren, in der dann steht, wo genau die Daten bezogen werden können und welche Version des IDML Schemas zu verwenden ist. Dadurch ist der Datenteil völlig unabhängig von der Infrastruktur des Servers und dessen Möglichkeiten. Jede auf dem Server verfügbare Schnittstelle kann verwendet werden um die Daten bereitzustellen. Das IDML Schema besteht aus drei getrennten - aber nicht unabhängigen - Schemas: • Site Description Schema Æ Beschreibung der angebotenen Informationen • Core Activity Schema Æ Enthält die Daten (Aktivitäten) • Extended Schema Æ Erweitertes «Core Activity Schema» Wie schon erwähnt wir das «Site Description Schema» nur benötigt um eine Verknüpfung mit den Aktivitäten über eine Standarddatei (gleicher Name und Zugriffspfad) zu gewährleisten. Deshalb ist dieses Schema klein und hat keinen komplizierten Aufbau. Das «Core Activity Schema» beinhaltet die Aktivitäten selbst und ist eine Teilmenge des «Extended Schemas». Der Unterschied der beiden letzt genannten Schemas liegt darin, dass das «Core Activity Schema» alle unbedingt benötigten Daten enthält. Das «Extended Schema» bietet die Möglichkeit noch weitere (nicht unmittelbar benötigte) Informationen zur Verfügung zu stellen. [IDMLDraft 01] Eine Übersicht über die Elemente des «Core Activity Schema» bietet Abbildung 9. Allerdings sind in dieser Abbildung nur die Elemente aufgeführt und keine Attribute. Die einzelnen «activities» sind untereinander aufgelistet (Sequenz) und jede «activity» selbst beinhaltet weiterführende Informationen. Abbildung 10 zeigt ein Beispiel einer gültigen XML Datei im «Core Activity Schema»-Format. Um das Beispiel zu verkürzen enthält diese Datei nur eine Aktivität. Diese muss durch einen eindeutigen Schlüssel (dbkey) gekennzeichnet sein und sollte mit dem Datum der letzten Änderung versehen sein um alle Aktivitäten garantiert unterscheiden zu können. Jede weitere Referenz auf diese Aktivität muss dann diesen Schlüssel benutzen. Mit Ausnahme des Datums, der URL und des Schlüssels sind die Formate der eingegebenen Daten nicht vorgegeben (jeder Text ist erlaubt). Damit in diesem offenen System aber die kein Chaos entsteht, da jede Organisation z.B. im «location»-Element ihre eigenen Länderkürzel verwendet, werden von der AIDA [AIDAAuth 02] sogenannte «Authority»-Dateien zur Verfügung gestellt welche nichts anderes als Tabellen mit gültigen Werten für bestimmte Elemente sind. Somit wird gewährleistet, dass die Daten konsistent und für die automatische Weiterverarbeitung verständlich bleiben. Auch an Mehrsprachigkeit wurde gedacht und es ist bei den meisten beschreibenden Elementen möglich ein «lang»-Attribut hinzuzufügen. Im angegebenen Beispiel kommt das «sector»-Element zweifach vor: einmal in englisch (en) und einmal in französisch (fr). Autor: Thomas Schädler 15 2 Datenaustausch mit XML <?xml version="1.0" encoding="ISO-8859-1"?> <activities> <activity dbKey="1-0-745001" date="1996-02-09"> <ID> <assigningOrg refKey="OECD DAC"/> <uniqID>1-0-745001</uniqID> </ID> <title lang="en">AGRICULTURAL WATER RESOURCES</title> <location locationCode="CUB"/> <startDate>0</startDate> <status statusCode="6"/> <sector lang="en">AGRICULTURAL WATER RESOURCES</sector> <sector lang="fr">Ressources en eau à usage agricole</sector> <notes>IRRIGATION PUMPS</notes> <funding> <fundingOrg>XAUT</fundingOrg> <yearly> <yearStarting date="1974-01-01"/> <amount amount="3745338.4" currency="usd"/> </yearly> <termsAssist terms="2"/> <total amount="3745338.4" currency="usd"/> </funding> <relatedLink> <label>OECD DAC Creditor Reporting System</label> <url>http://www.oecd.org/dac/htm/crs.htm</url> </relatedLink> <forMoreInfo>[email protected]</forMoreInfo> </activity> </activities> Abbildung 10 : Core Activity Schema: Beispiel von activities.xml Da solche Projektdaten auch zwischen verschiedenen Stakeholdern ausgetauscht werden können ist es wichtig verfolgen zu können, welche Organisation welche Änderungen an den Daten vornimmt. Das «Extended Schema» erlaubt es zusätzliche Informationen hinzuzufügen, welche die Herkunft der enthaltenen Daten genau verfolgen lassen (welche Information wurde wo von wem hinzugefügt oder geändert (engl.: audit trail)). Diese Informationen sind für Daten-Aggregatoren (engl.: data aggregators) allerdings auch zwingend anzugeben. Ausserdem erweitert das «Extended Schema» einige Elemente dahingehend, dass diese auch ausserhalb einer «activity» Gültigkeit besitzen und als eigenständige Elemente bestehen können. In Abbildung 11 ist schematisch die Standardprozedur aufgezeigt, die angewendet wird um die IDML Daten auszutauschen. Es sind zwei HTTP (Hypertext Transfer Protocol) Anfragen an den Webserver nötig. In der Standardprozedur wird angenommen, dass entweder die Datenbank als Resultat XML Daten liefert oder aber der Webserver die Daten vor der Endauslieferung konvertiert. Autor: Thomas Schädler 16 2 Datenaustausch mit XML 2.5 Client/Server- oder Dreischichtenarchitektur Wie schon erwähnt, erfolgt der Dokumentenaustausch durch zwei HTTP Anfragen. Das Vermittlungswerkzeug sollte sich in eine solche Architektur gut einfügen lassen und nicht zuviel Mehraufwand verlangen. Dies wird wie in Abbildung 12 dargestellt mit einem einfachen Umleiten der zweiten HTTP Anfrage erreicht. Diese wird jetzt nicht mehr an den Webserver geschickt, sondern direkt auf einen 2. Rechner, der dann die Abfrage der Datenbank und die Konvertierung in XML übernimmt und somit den Webserver entlastet. (1) (4) Data Data START (2) Data (3) (5) (6) END Webserver Internet (1) HTTP Anfrage (GET /IdmlInfo.xml) (2) HTTP Resultat => IdmlInfo.xml (3) HTTP Anfrage (GET /<link_to_idml> [und event. weitere Daten: Query]) (4) SQL Anfrage(n) (5) DB Resultat - wenn XML (XML-DB, XML-enabled-DB) => weiter - wenn SQL Resultat, dann Konvertierung in XML (meist Skriptsprache) (6) HTTP Antwort (IDML XML) Abbildung 11 : IDML Datenaustausch (Standardprozedur) Natürlich kann das Vermittlungswerkzeug auch auf dem selben Rechner laufen, und muss nicht physikalisch vom Webserver getrennt sein. Dies kann je nach Hard- und Softwareausstattung aber durchaus sinnvoll sein und muss für jeden Einsatzort einzeln abgeklärt werden. Die Umleitung der zweiten HTTP Anfrage kann wie in Kapitel 2.4 erklärt einfach durch ersetzen des url-Eintrages in der "IdmlInfo.xml" Datei erzwungen werden. Diese Änderung der Architektur bringt aber keinen Mehraufwand (engl.: overhead) beim Transport und der Abfrage der Daten. Durch das Einfügen einer weiteren Abstraktionsebene (Vermittlungswerkzeug), ändert die traditionelle Client/Server Architektur in eine Dreischichtenarchitektur (Vergleiche Abbildung 11 und Abbildung 12). Anstelle einer Standardabfrage von der Applikation direkt auf die Datenbank wird die Abfrage von einer Middleware (Vermittlungswerkzeug) verarbeitet, die die Logik beinhaltet um das Resultat der Datenbankabfrage in eine für die Applikation verständliche Form zu bringen. Autor: Thomas Schädler 17 2 Datenaustausch mit XML (1) Data Data START (2) Data END Webserver (4) (3) (6) (5) Internet Vermittlungswerkzeug (1) HTTP Anfrage (GET /IdmlInfo.xml) (2) HTTP Resultat => IdmlInfo.xml (3) HTTP Anfrage (GET /<link_to_idml> [und event. weitere Daten: Query]) (4) SQL Anfrage(n) - Generiert aus der Konfigurationsdatei (5) DB Resultat (SQL Resultat) - Konvertierung nach den definierten Regeln (Konfigurationsdatei) (6) HTTP Antwort (IDML XML) Abbildung 12 Autor: Thomas Schädler : IDML Datenaustausch (mit Vermittlungswerkzeug) 18 3 Datenbanken 3 Datenbanken 3.1 Grundlegende Anforderungen In unserem Falle sind die grundlegenden Anforderungen an die Datenbanken nicht sehr gross. Wichtig ist vor allem, dass das Vermittlungswerkzeug mit einer Vielzahl von Datenbanken zuverlässig arbeiten kann, da ja im Voraus nicht bekannt ist, wo welche Datenbank verwendet wird. Heute bieten viele Programmiersprachen eine grosse Fülle an verschiedenen Schnittstellen. Allen gemeinsam ist dabei, dass nur relationale Datenbanken unterstützt werden. Diese Einschränkung ist aber nicht weiter wichtig, da eigentlich alle heute verwendeten Datenbank Management Systeme (DBMS) relational DBMS sind. Die wichtigsten sind wohl ODBC und JDBC. Die Architektur beider Schnittstellen wurden aus der SQL Call Level Interface (CLI) Spezifikation von der Open Group abgeleitet [SCLS 01]. Diese Spezifikation regelt wie man standardisiert mittels SQL auf eine Vielzahl von Datenbanken zugreifen kann und bildet somit eine Abstraktionsschicht zwischen den Programmiersprachen und den Datenbanken. Diese werden im Folgenden Abschnitt genauer erläutert. Weiterhin wird im zweiten und dritten Teil auf die Konvertierung der Daten von einer Datenbank in XML und umgekehrt eingegangen. 3.2 Schnittstellen ODBC (Open Database Connectivity) wurde von Microsoft entwickelt und etablierte sich schnell als De-facto-Standard, da von Anfang an eine Menge Datenbanksysteme unterstützt wurden. Die gute Treiberversorgung und Marktabdeckung von ODBC ist der grösste Vorteil. Ein Nachteil ist, dass der Treibermanager und die Treiber bei jedem Client installiert werden müssen. JDBC (Java Database Connectivity) wurde etwas später - mit der Notwendigkeit einer Datenbankschnittstelle für Java – umgesetzt. Die Architektur wurde im Grossen und Ganzen von ODBC übernommen, allerdings wurde JDBC natürlich objektorientiert entwickelt. ODBC dagegen in C. Einer der Unterschiede beider Schnittstellen ist z.B., dass JDBC als Resultat ein Resultat-Objekt liefert, wohingegen ODBC nur einen Pointer zurückgibt. Vor allem in Blickpunkt für eine Migration wurde für JDBC auch eine JDBC-ODBC Bridge entwickelt die es ermöglicht vorhandene ODBC Treiber weiter zu verwenden. Wenn also eine Datenbank keine JDBC Schnittstelle hat, kann man mit der JDBC-ODBC Bridge trotzdem mit dieser Datenbank arbeiten. Wie schon erwähnt ist die Architektur bei beiden Schnittstellen (ungefähr) die gleiche. Ein Treibermanager kümmert sich um die Verbindungen und deren Verwaltung. Der Datenbanktreiber selbst kümmert sich dann um die (herstellerabhängige) Kommunikation mit der Datenbank und liefert auf Anfragen das Resultat. Autor: Thomas Schädler 19 3 Datenbanken 3.3 Beziehung zwischen Datenbanken und XML Das Vermittlungswerkzeug wird ja eine Verbindung zwischen einer Datenbank und einem XML Dokument herstellen. Wie in Abschnitt 1.1 auf Seite 1 erwähnt, gibt es folgende drei grundlegenden Szenarien: 1. Es ist keine Datenbank vorhanden (Die XML Daten werden in einer neu angelegten Datenbank gespeichert.) 2. Es ist kein XML Schema vorhanden (Die Daten aus der Datenbank werden in einem neu generierten XML Format ausgegeben.) 3. Datenbank und Schema sind vorhanden, aber die Abbildung in beide Richtungen ist noch nicht erledigt.) Das erste Szenario ist interessant wenn man daran interessiert ist XML Daten von anderen Stakeholdern in einer eigenen Datenbank zu speichern. Dies ist im Falle von IDML nicht das Hauptinteresse, da dort ja keine zentrale Datenbank verwendet wird und die Daten ja auch immer auf dem aktuellen Stand gehalten werden müssen. Es ist aber nicht auszuschliessen, dass andere Anwendungen auf dieses Problem stossen. Auch das zweite Szenario ist nicht sehr häufig zu finden, da die Daten meist in einem fest definierten Format (z.B. einem XML Schema) ausgegeben werden müssen und nicht einfach in einem automatisch generierten Format, dass sich an dem Datenbanklayout orientiert. Richtig interessant wird erst das dritte Szenario, in welchem die Daten nach festen Regeln abgebildet werden müssen, da ja die Datenbank und das Ausgabeformat (XML Schema) fixiert sind. Hierzu gibt es aber keine automatischen Konvertierungen und somit muss hier von Hand eine Abbildung vorgenommen werden, die dann aber automatisch wiederholt werden kann. Um ein XML Dokument, das einem XML Schema genügt, also ein gültiges (engl.: valid) XML Dok ument darstellt, in einer noch nicht vorhandenen Datenbank zu speichern, muss man erst einmal die Strukturen des verwendeten XML Dokuments kennen. XML Dokumente kann man in zwei Lager einteilen. Erstens sind dies Daten-zentrische (engl.: datacentric) Dokumente die vereinfacht einen Datencontainer darstellen. Zweitens sind dies Dokumentenzentrische Dokumente, welche hauptsächlich für den Menschen lesbar sein sollten. Es ist nicht immer einfach zwischen diesen Kategorien zu unterscheiden, das es viele Dokumente gibt, die Merkmale beider Kategorien vereinen. Als Faustregel wird aber vorgeschlagen, dass man Daten-zentrische Dokumente in einer normalen (relationalen) Datenbank abspeichert und Dokumenten-zentrische Dokumente in einer nativen XML Datenbank um die Vorteile von XML nicht zu verlieren. Ausserdem ist es nicht ganz trivial Dokumenten-zentrische Daten in einer relationalen Datenbank zu speichern. Autor: Thomas Schädler 20 3 Datenbanken Im Folgenden werden nun diese drei Szenarien genauer untersucht, damit im darauf folgenden Schritt das Modell festgelegt werden kann und der theoretische Hintergrund für die Implementation schon gegeben ist. Welche dieser drei Szenarien schliesslich verwendet wird ist noch nicht genau abgeklärt. Das primäre Ziel – Projektdaten über das World Wide Web in IDML zur Verfügung zu stellen – bedeutet allerdings, dass zumindest eine Abbildung von der Datenbank in XML (IDML Schema) erfolgen muss. Da diese Szenarien sich teilweise in der Theorie überschneiden werden im nächsten Abschnitt zuerst die verschiedenen Mapping-Methoden genauer untersucht. Weitere Bedürfnisse werden in einem späteren Teil abgeklärt. 3.4 Mapping Es gibt zwei unterschiedliche Ansätze um ein Mapping vorzunehmen. Die erste ist das Vorlagengesteuerte (engl.: template-driven) Mapping und die zweite das Modell-gesteuerte (engl.: modeldriven) Mapping. Das Vorlagen-gesteuerte Mapping wird vorzugsweise für die Abbildung von der Datenbank in ein XML Dokument verwendet, kann aber auch für den umgekehrten Weg benutzt werden. Beim Modell-gesteuerten Mapping gibt es zwei Ansätze: Tabellen-basiertes (engl.: table-based) und Objekt-relationales (engl. object-relational) Mapping. Das Tabellen-basierte Mapping ist der einfachste Fall, kann aber nur angewendet werden, wenn die Daten in einem festegelegten Format vorliegen. So wird es vorzugsweise für die Serialisierung von Daten aus einer Datenbank verwendet. Das Objektrelationale Mapping ist immer anwendbar, aber auch komplizierter zu verwenden. Dabei werden die Daten in einem XML Dokument als Baumstruktur aus Objekten beschrieben. Diese Struktur ist aber nicht zu verwechseln mit einem DOM-Baum. Die Baumstruktur kann für jedes Dokument unterschiedlich sein. Die einzelnen Objekte werden als Klassen modelliert uns somit entsteht ein objektorientiertes Modell. Dieses Modell wird anschliessend auf die Datenbank abgebildet. [Bourret 02] 3.4.1 Tabellen-basiertes Mapping Tabellen-basiertes Mapping kann nur auf wenige XML Schemas angewendet werden, da eine bestimmte Struktur vorausgesetzt wird. Häufig wird Tabellen-basiertes Mapping verwendet um das Resultat einer Abfrage an eine relationale Datenbank in XML umzuwandeln oder um Daten zwischen zwei relationalen Datenbanken auszutauschen. Der Aufbau beim Tabellen-basierten Mapping ist sehr einfach. Das XML Dokument bildet einfach die Tabellenstruktur der Datenbank ab (siehe Abbildung 13). Diese Operation kann ohne Mehraufwand in beide Richtungen durchgeführt werden. Da in den meisten Fällen das XML Dokument aber keine solche Struktur aufweist, wird von einer genaueren Untersuchung abgesehen. Sollte diese Funktionalität dennoch in diesem Projekt verwendet werden ist es dank des einfachen Aufbaus kein Problem einen solchen Datenimport bzw. –export dennoch zu implementieren, da nur eine Seite angepasst werden muss (die andere ist fixiert). Autor: Thomas Schädler 21 3 Datenbanken <?xml version="1.0"?> database <database> <tables> <table_1> <row> table <column_1>...</column_1> row </row> </table_1> <table_2> column ... </table_2> </tables> </database> Abbildung 13 : Beispiel für Tabellen-basiertes Mapping [Bourret 02] 3.4.2 Vorlagen-gesteuertes Mapping Vorlagen-gesteuertes Mapping wird vorwiegend benutzt um Daten aus Datenbanken in ein XML Format zu konvertieren. Dabei werden SQL Statements in eine XML Vorlage eingebettet, die dann von der verarbeitenden Middleware ausgeführt und in den angegeben Stellen in der XML Datei eingefügt (substituiert) werden. Diese Variante eignet sich auch sehr gut für den IDML-Export, da kein komplexes objekt-rationales Mapping ausgeführt werden muss und alle anderen Voraussetzungen zur Genüge erfüllt werden. Es ist in der Verarbeitung ähnlich dem Tabellen-basierten Mapping mit dem grossen Unterschied, dass der Output sehr flexibel angepasst werden kann. Abbildung 14 zeigt ein Beispiel für Vorlagen-gesteuertes Mapping. Dieses Beispiel zeigt nur die Idee die dahintersteckt und eine Implementation kann davon abweichen. <?xml version="1.0"?> <garage> <select>SELECT marke, jahr, zylinder, typ, farbe FROM bikes</select> <motorrad> substituiert <marke>$marke</marke> <typ herstellungsjahr="$jahr" zylinder="$zylinder">$typ</typ> <farbe>$farbe</farbe> </motorrad> </garage> Abbildung 14 : Beispiel für Vorlagen-gesteuertes Mapping 3.4.3 Objekt-relationales Mapping Objekt-relationales Mapping wird in zwei Schritten ausgeführt. XML Schemas werden über ein ObjektSchema in ein relationales Schema abgebildet. Die umgekehrte Richtung ist auch möglich, wird aber nicht weiter berücksichtigt, da in den meisten Fällen ein XML Schema schon vorhanden ist. Damit ist das zweite Szenario (siehe oben) aber nicht ausgeschlossen, da in einem solchen Fall für die Serialisierung der Daten ein einfacher Export mit Tabellen-basiertem Mapping gewählt werden kann. Autor: Thomas Schädler 22 3 Datenbanken Ein XML Dokument wird erst in ein Objekt-Schema abgebildet, welches wiederum in DatenbankTabellen gemappt werden kann. Abbildung 15 zeigt das Objekt-Schema für das Beispiel-Dokument aus Abbildung 2. objekt garage { objekt motorrad { motorrad = Æmotorrad } Legende: marke = "Yamaha", typ = "XT 550", typ = Ætyp, herst.jahr = "1984", farbe = "schwarz", zylinder = "1" option = "" Æ = Zeiger auf Objekt objekt typ { } } Abbildung 15 : XML Dokument aus Abbildung 2 als Objekt-Schema Da dieses Objekt-Schema nun alle benötigten Informationen enthält, kann es auf Datenbank-Tabellen abgebildet werden. Aus jedem Objekt wird eine Tabelle und die Eigenschaften ergeben die benötigten Spalten. Im Beispiel aus Abbildung 15 werden also drei Tabellen benötigt. Dieses Mapping kann jetzt auch auf XML Schemas (nicht auf einzelne XML Dokumente) oder DTD's angewendet werden. Dabei werden die verschiedenen XML Schema-Komponenten (Sequenz, Auswahl, etc.) nach bestimmten Regeln in Klassen abgebildet (Details folgen weiter unten). Den ersten Schritt – vom XML Schema zum Objekt-Schema – nennt man auch XML Daten-Bindung (engl.: XML data binding). Wie schon erwähnt, haben Objekt-Schemas zwar auch eine Baumstruktur, sind aber grundlegend anders ausgelegt als DOM-Bäume. DOM-Bäume modellieren das Dokument und ein Objekt-Schema (oder Objekt-Baum) modelliert die Daten in dem Dokument. Abbildung 16 erklärt anhand eines Beispiels den Unterschied zwischen einem Objekt-Baum und einem DOM-Baum. Für ein bestimmtes XML Schema haben alle davon abgeleiteten XML Dokumente den gleichen DOMBaum. Objekt-Schemas dagegen sind bei jedem XML Dokument unterschiedlich. Das Objekt-Schema lässt sich leicht nachvollziehen, wenn man das XML Dokument durchliest und seine Struktur betrachtet. Als Resultat erhält man einen einfachen Baum, der die Struktur der Auszeichnungselemente (engl.: tags) aufzeigt. Der DOM-Baum hingegen modelliert einen anderen Baum, der jedoch für alle Instanzen eines XML Schemas gleich ist. Dieser Baum stellt die Struktur des XML Dokumentes anhand der XML Elemente dar. Die Knoten des Baumes sind Elemente oder Attribute, welche wiederum Text beinhalten (die Daten). Die Wurzel eines DOM-Baumes ist immer das Dokument. Objekt-Schemas werden aber normalerweise nicht als Baum gezeichnet, sondern in einer abstrahierten – an Klassen (für Java-Programmierer) oder Strukturen (für C-Programmierer) erinnernde – Schreibweise (siehe Abbildung 15). Eine zweite Darstellungsmöglichkeit für Objekt-Schemas ist eine Klassenhierarchie, welche dann auf eine relationale Datenbank abgebildet werden kann. Die Klassen haben verschiedene Eigenschaften, aber keine Methoden. Die Eigenschaften selbst können weiter eingeschränkt werden. Beispielsweise Autor: Thomas Schädler 23 3 Datenbanken kann eine Eigenschaft mehrfach vorkommen oder auch das NULL-Element beinhalten (im Beispiel die Auszeichnungselemente «motorrad», «option» und «herstellungsjahr»). Legende: [] Dokument = Array (1 und mehr) ∅ = Nullable (Null oder 1) klasse: garage § motorrad [] ∅ Element Element garage klasse: motorrad Element Text Element Text § marke motorrad § typ § farbe marke typ farbe option Objekt-Baum Abbildung 16 § option [] ∅ Element Text Element Text klasse: typ Attribut Text § typ Attribut Text § herstellungsjahr ∅ DOM-Baum § zylinder Klassenhierarchie : XML Dokument aus Abbildung 2 als Objekt-Baum, DOM-Baum und Klassenhierarchie Autor: Thomas Schädler 24 4 Erstellung eines Modells 4 Erstellung eines Modells In diesem Kapitel werden alle vorangegangen Konzepte vereint um schliesslich das zu implementierende Modell zu erhalten. Dabei wird abgewägt, welchen Anforderungen das Modell standhalten soll, wie es konkret aussieht, welche Benutzerschnittstelle gewählt wird und mit welcher Software das Modell anschliessend implementiert werden soll. 4.1 Anforderungen an das Modell Was in den vorangegangenen Kapiteln schon ausformuliert wurde soll hier noch zusammengefasst werden um den Gesamtkatalog an Anforderungen zu erstellen. Gefordert wird ein Werkzeug welches sich in viele Architekturen einfach einbetten lässt und welches mit möglichst vielen verschiedenen Datenbanken zusammenarbeiten kann. Dies setzt eine offenen Architektur voraus. Da das Werkzeug frei zur Verfügung stehen soll muss ausserdem eine Architektur und Sprache gewählt werden, die ohne Lizenzgebühren und sonstigen Abgaben eingesetzt werden kann. Das Werkzeug muss sich an die verwendeten Spezifikationen sehr genau halten (XML, XML Schema). Es sollte bei der Anwendung möglichst einfach zu bedienen sein und praktisch wartungsfrei seinen Dienst erfüllen. Als Minimalanforderung wird vorausgesetzt, dass das Werkzeug XML Daten aus der eigenen Datenbank auslesen und in das IDML Format konvertieren kann. Das Werkzeug muss drei verschiedene Aufgaben erledigen: 1. Eine grafische Oberfläche für das Mapping bereitstellen. 2. Mit vielen verschiedenen relationalen Datenbanken kommunizieren. 3. Einen Service bereitstellen, um die generierten Daten abzurufen. Durch die sehr unterschiedliche Aufgabenstellung (Desktop-Applikation und Serverkomponente) stellt sich auch die Frage ob nicht zwei einfachere Werkzeuge diese Arbeit besser erledigen könnten. Eine Aufteilung vermindert die Komplexität beider Anwendungen. 4.2 Konstruktion des Modells Das Werkzeug muss die oben genannten Anforderungen erfüllen. Abbildung 12 zeigt noch mal genau die Situation in der Übersicht. Durch eine Aufteilung in zwei oder drei Komponenten wird die Applikation besser wartbar und die Serverkomponente wird nicht unnötig aufgebläht. Allerdings findet noch eine Kommunikation zwischen dem Server und dem Konfigurationswerkzeug statt. Dies ist aber mit einer Konfigurationsdatei schnell erledigt. Eine mögliche dritte Komponente – ein Überwachungswerkzeug – muss auch mit der Serverkomponente kommunizieren können. Hier reichen jedoch drei oder vier Befehle (Start, Stopp, Reload und Status). Dabei kann man noch einmal von XML profitieren. Da die Serverkomponente sowieso mit XML umgehen kann (Datentransformation als Hauptaufgabe), kann die Konfigurationsdatei alle benötigten Daten Autor: Thomas Schädler 25 4 Erstellung eines Modells in einer einfachen XML Struktur beinhalten. Diese wird dann eingelesen und der Server kann seinen Betrieb aufnehmen. Dadurch ist auch gewährleistet, das die Serverkomponente einmal in Betrieb für Änderungen nicht mehr gestoppt werden muss. Diese Architektur ist auch von Webservern bekannt (z.B. Apache), welcher im laufenden Betrieb einfach die Konfigurationsdatei einliest. Dadurch dass die Mappingaufgabe für die Serverkomponente entfällt kann auch auf eine grafische Benutzeroberfläche verzichtet werden und der Server als unabhängige Kommandozeilenapplikation entwickelt werden. Das spart Platz und Komplexität. Damit dadurch die Kontrolle des Servers nicht zu kompliziert wird kann in das Konfigurationswerkzeug eine Steuerungseinheit für den Server eingebaut, ein kleines unabhängiges Steuerungs- und Überwachungsfrontend entwickelt werden oder der Server stellt ein Web-Frontend für seine Steuerung bereit Alternativ wird der Server natürlich über die Kommandozeile gesteuert. Für die dritte Variante spricht eine nochmalige Verringerung der Komplexität, da der Server unabhängig vom Standort gewartet werden kann und die ganze Logik der Administration im Server enthalten bleibt. Bei einer Remote-Administration darf der Sicherheitsaspekt aber nicht vergessen werden, da eine solche Funktionalität eine grosse Angriffsfläche für allfällige Attacken darstellt. Konfigurationsdatei (XML) Kommandozeile Clients HTTP Administration liest Anfrage (HTTP) schreibt und liest Internet Server Antwort (HTTP) Format: XML JDBC/ODBC Data JDBC/ODBC Data Konfigurator Data Vermittlungswerkzeug Abbildung 17 : Architektur des Vermittlungswerkzeugs in der Übersicht Das Konfigurationswerkzeug für das Mapping – im folgenden einfach Konfigurator genannt – muss eine grosse Konnektivität in Bezug auf Datenbanken besitzen und mit XML umgehen können. Das heisst, der Konfigurator muss XML Schemas parsen und mit Datenbanken kommunizieren können. Dazu muss eine Oberfläche entwickelt werden, die es erlaubt, ein Mapping zwischen der Datenbank und dem XML Schema vorzunehmen. Die Struktur eines erstellten Mappings muss dann in einer XML Konfigurationsdatei gesichert werden können. Autor: Thomas Schädler 26 4 Erstellung eines Modells Die Funktionalität um den Server zu steuern begrenzt sich auf zwei Funktionen. Ein Kommando muss den Server dazu bringen die Konfigurationsdatei neu einzulesen und als zweite Funktion muss der Server gestartet und gestoppt werden können. Ausserdem ist es noch von Vorteil wenn man den Status des Servers abfragen kann. Bei der Architektur des Servers kann man sich zwei verschiedene Architekturen vorstellen. Entweder ist der Server fähig mehrere Konfigurationen gleichzeitig zu verwalten oder es wird für jede Aufgabe ein eigener Server gestartet. In der Funktionalität ist dabei kein Unterschied feststellbar, nur die Kontrolle der einzelnen Server wird dem Benutzer überlassen, wohingegen bei der ersten Variante der Server seine verschiedenen Aufgaben selbst verwaltet. Abbildung 17 zeigt die Architektur des Vermittlungswerkzeuges in der Übersicht. Zusammenfassend noch einmal die Funktionen der einzelnen Komponenten. Konfigurator: • Datenbanken einlesen und den Zugriff darauf verwalten • XML Schema einlesen und grafisch darstellen • Kontrollansicht für generiertes XML oder die Datenbankeinträge • Mappingkomponenten (z.B. per Drag und Drop) • Speichermöglichkeit in einer Konfigurationsdatei zur Verfügung stellen Serverkomponente: 4.3 • Annahme von Abfragen (ähnlich einem Webserver) • Einlesen einer Konfigurationsdatei • automatisches Mapping nach den Regeln in der Konfigurationsdatei • Server neu starten, stoppen und die Konfigurationsdatei neu einlesen • Steuerung über ein Web-Frontend, eine dritte Komponente oder über die Kommandozeile Festlegung des Modells In diesem Abschnitt soll nun festgelegt werden wie die beiden Komponenten genau implementiert werden. Dabei wird aus den vorangegangenen möglichen Varianten eine ausgewählt und mit allen Details beschrieben, damit sich die Implementation auf dieses Modell stützen kann. Das Modell wird in zwei Komponenten gegliedert die jetzt genauer untersucht werden. 4.3.1 Der Konfigurator Der Konfigurator stellt die Benutzerschnittstelle für die Hauptaufgabe der Benutzer (Mappings vorzunehmen) dar und muss sich deshalb um die Erstellung und Speicherung der Projektdaten kümmern. Die Projektdaten werden in einer XML Datei gesichert welche alle zum Projekt gehörenden Informationen speichert. Dies ist der Name des Projekts und das von diesem Projekt benutzte Mappingmodul. Zusätzlich werden hier die Daten der verschiedenen Datenbankverbindungen und alle benötigten XML Dateien (Schemas) gespeichert. Die einzelnen Module müssen natürlich ihre Daten (vom Benutzer generierte Mappingaufgaben) auch speichern können. Diese Daten werden in der Konfigurationsdatei Autor: Thomas Schädler 27 4 Erstellung eines Modells als vierter Punkt – abhängig vom verwendeten Mappingmodul - gespeichert. In einem XML Schema ist dies das Element «Mapping» welches eine Auswahl der möglichen Module zulässt. Abbildung 18 zeigt das XML Schema einer Projektkonfiguration in der Baumansicht ohne aufgeklapptes «Mapping»Element und Abbildung 19 zeigt ein Beispieldokument mit den enthaltenen Informationen. Abbildung 18 : xmlizer.project.config.xsd (Baum, kein Mapping) [XMLSPY 01] Solche Informationen wie in Abbildung 19 werden vom Konfigurator erzeugt, gelesen und natürlich stellt er eine Möglichkeit zur Verfügung diese neu erzeugten Daten in einer Datei zu speichern. Mit Hilfe dieser Daten kann dann das gewählte Modul auf die Datenbanken zugreifen und die XML Dateien öffnen und bearbeiten. Um ein neues Projekt zu erzeugen stellt der Konfigurator einen Dialog bereit, der diese Daten abfragt. Dabei ist zu beachten, dass jedes Projekt mindestens eine Datenbankverbindung benötigt. Um den Modulen die Arbeit zu vereinfachen, testet der Konfigurator jede Datenbankverbindung auf Konnektivität und jede XML Datei auf ihre Richtigkeit (mindestens «wellformed»). Autor: Thomas Schädler 28 4 Erstellung eines Modells <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE xmlizerprojectconfig SYSTEM "xmlizer.project.config.dtd"> <xmlizerprojectconfig> <initialsetup> Ist mit einer DTD verknüpft, wird beim einlesen validiert. <inititem key="name">testproject</inititem> <inititem key="module">Simple DB Export</inititem> </initialsetup> <databasesetup> <dbitem> <name>someconnectionname</name> <driver>org.gjt.mm.mysql.Driver</driver> <url>jdbc:mysql://localhost:3306/xml</url> <timeout>20</timeout> Beispiel: DB Konfiguration, <username>root</username> kann mehrmals vorkommen. <password>20:30:71:88:</password> </dbitem> </databasesetup> <schemasetup> <xmlitem> <name>somefilename</name> Beispiel: XML Datei <file>somefile.xml</file> </xmlitem> </schemasetup> </xmlizerprojectconfig> Abbildung 19 : Beispiel einer Konfigurationsdatei ohne Mappinginformationen Ist alles korrekt startet der Konfigurator das Modul welches dann die eigentliche Mappingaufgabe erledigt und mit Hilfe der Konfigurationsinformationen sofort mit den Datenbanken und den XML Dateien arbeiten kann. 4.3.2 Die Serverkomponente Die Serverkomponente ist im Grunde genommen ein auf die speziellen Bedürfnisse angepasster Webserver. Sie erledigt die in den Konfigurationsdateien gespeicherten Mappingaufgaben und liefert die Ergebnisse nach einer Anfrage aus. Um den Server zu steuern wird die Kommandozeile benutzt, da diese alle Anforderungen erfüllt und die einfachste Architektur darstellt (es wird keinen dritte Komponente benötigt). Um an die Daten heranzukommen ist die genaue Kenntnis der URL erforderlich. Um dies zu vereinfachen wird ein Web-Frontend implementiert, welches die angebotenen Projekte auflistet und einfach mit Hilfe eines Webbrowsers navigiert werden kann. Die Serverkomponente wird so implementiert, dass sie verschiedene Mappingaufgaben parallel verwalten und verarbeiten kann. Es können alternativ auch verschiedene Server auf verschiedenen Ports arbeiten, wobei jedem Server ein anderes (oder auch das gleiche) Projektverzeichnis zugeteilt werden kann. 4.3.3 Die Mappingmodule Als erstes Modul wird das in Abschnitt 3.4.1 erläuterte Tabellen-basierte Mapping implementiert. Es ist die einfachste Variante und benutzt nur Datenbankverbindungen, aber keine Manipulation von XML Dateien. Dieses Modul wird im folgenden als «Simple DB Export» Modul bezeichnet, was auch gleich Autor: Thomas Schädler 29 4 Erstellung eines Modells den Zweck dieses Moduls verdeutlicht. Der Benutzer hat keinen grossen Einfluss auf das Format der Ausgabe und kann eventuell nur einige Variablen beeinflussen oder aus verschiedenen vorher festgelegten Outputformaten aussuchen. Da dieses Modul eher als Implementationstest gedacht ist und nicht für den produktiven Einsatz prädestiniert ist, wird es nur in eine Richtung implementiert: eine Datenbank als Input und XML aus Outputformat. Das zweite Modul wird mit dem in Abschnitt 3.4.2 erklärten Vorlagen-gesteuerten Mapping implementiert und ermöglicht es dem Benutzer Daten aus verschiedenen Datenbanken in ein selbst definiertes XML Format zu bringen. Es ersetzt somit auch gleich das erste Modul, da mit diesem Funktionsumfang auch einfach das Exportformat des ersten Moduls «nachgebaut» werden kann. Aber auch dieses Modul beschränkt sich auf den Export aus einer Datenbank und greift nur lesend auf diese zu. Eine gelungene Implementation dieses Moduls genügt dann auch den in Abschnitt 1.2 und 4.1 definierten Minimalanforderungen für dieses Projekt. Dieses Modul trägt den Namen «Database to XML». Ein drittes Modul implementiert dann eventuell das in Abschnitt 3.4.3 erläuterte Objekt-relationale Mapping, welches dann einer Generalisierung aller möglichen Mappings gleichkommt und es ermöglichen würde Daten in beide Richtungen transparent auszutauschen. Für eine allfällige Implementation dieses Moduls befindet sich der Autor noch immer auf der Suche nach einer (freien) Bibliothek, da der Programmieraufwand ansonsten sehr hoch ist, da es sich um ein sehr komplexes Themengebiet handelt. Autor: Thomas Schädler 30 5 Auswahl der Software / Programmiersprache 5 Auswahl der Software / Programmiersprache 5.1 Anforderungen Die gestellten Anforderungen an eine Programmiersprache sind vor allem eine hohe Datenbankkonnektivität, damit das Endprodukt mit einer möglichst grossen Vielfalt von Datenbanken genutzt werden kann (höchste Priorität). Ausserdem sollten es geeignete Bibliotheken für den Umgang mit XML vo rhanden sein. Als dritter Punkt ist sehr wichtig, dass das Endprodukt ohne Lizenzabgaben verbreitet werden kann und es sollte auf möglichst vielen Plattformen ohne Anpassungen ausführbar sein. Allein diese wenigen Punkte schränken die Wahl der Programmiersprache schon beträchtlich ein. 5.2 Auswahl der Programmiersprache Möglich wäre eine Implementation mit den verschiedensten heute erhältlichen Programmiersprachen. Der Autor entscheidet sich jedoch für Java, da Java alle Anforderungen mit Bravour erfüllt und er schon einige Erfahrung mit dieser Programmiersprache vorweisen kann. Die Datenbankkonnektivität ist mit JDBC (Java Database Connectivity) praktisch unbegrenzt (jeder grosse Datenbankhersteller stellt einen Treiber bereit und viele Treiber sind selbst Open Source) und die Datenbanktreiber können während der Laufzeit spezifiziert werden (müssen also nicht fest einprogrammiert werden), was die Flexibilität stark erhöht. Auch gibt es eine grosse XML Unterstützung die jedoch noch immer nicht vollständig ist, aber ständig erweitert wird. Java ist auch absolut lizenzfrei und fast als einzige Sprache völlig plattformunabhängig [Java 02]. 5.3 Auswahl der Werkzeuge Ein weiterer Vorteil von Java ist die grosse Verfügbarkeit an freien Entwicklungsoberflächen. Der Autor hat sich nach genauerer Untersuchung für «Forte for Java» von Sun entschieden, das in einer «Community Edition» frei erhältlich ist und hervorragend auf Java zugeschnitten wurde [Forte 02]. Als weiterer Kandidat war noch die freie Version von Borland's «JBuilder», welche sich jedoch durch zu grosse Eingeschränktheit der freien Version im Hinblick auf Datenbanken selbst disqualifiziert hat [Borland 02]. Die XML Unterstützung beider IDE's (engl.: Integrated Development Environment) ist jedoch noch sehr rudimentär und erfordert noch immer einen Menge Handarbeit. Um die DTD's und die XML Schemas zu entwickeln verwendet der Autor XMLSpy von Altova Inc., welches jedoch nur als 30Tage-Testversion zur Verfügung steht, was aber völlig ausreicht [XMLSPY 01]. Ansonsten greift der Autor auf konventionelle Texteditoren zurück. Für die Architektur der Programme selbst benutzt der Autor JVision von Object-Insight. Dieses Werkzeug erlaubt es UML Diagramme (Unified Modelling Language) zu zeichnen und daraus ein JavaCodegerüst zu erzeugen. Aber auch der umgekehrte Weg ist möglich: Aus vorhandenen Java-Klassen kann UML erzeugt werden [JVision 02]. JVision ist nicht frei verfügbar, es ist jedoch möglich eine freie Autor: Thomas Schädler 31 5 Auswahl der Software / Programmiersprache akademische Lizenz zu bekommen. Auch hier hat der Autor noch ein Konkurrenzprodukt ausprobiert, das sich ausgezeichnet in «Forte for Java» integrierte, jedoch dauern Abstürze produzierte und die gespeicherten Daten korrumpierte (Poseidon Community Edition von Gentleware). 5.4 Auswahl der Bibliotheken Um auf Basis von Java zu programmieren werden – abgesehen von der standardisierten JavaBibliothek – noch weitere Bibliotheken (engl.: libraries, packages, oder API's) benutzt. Vor allem im Bezug auf XML kommt man nicht darum herum externe Bibliotheken zu verwenden, da erst in der neuesten Java-Version eine XML Bibliothek enthalten ist (ab Version 1.4). Die vom Autor verwendete Version ist Java 1.3.1, da die benutzte IDE diese Version verlangt. Um diese Bibliotheken zu benutzen reicht es sie in den Ordner «lib/ext» im Installationsverzeichnis der verwendeten Java Runtime (JRE) zu kopieren oder sie alternativ im «classpath» anzugeben. Die erste und wichtigste Bibliothek ist die «Xerces-J» vom Apache Projekt [XERCES 02]. Diese Bibliothek beinhaltet alles nötige um mit XML zu arbeiten. Das heisst Xerces implementiert die XML 1.0 Spezifikation (recommendation) vom W3C mit erweiterten Parserfunktionen. Ausserdem implementiert diese Bibliothek noch die XML Schema recommendation 1.0, DOM Level 2 Version 1.0, SAX Version 2 und natürlich auch DOM Level 1 und SAX Version 1. Diese Bibliothek stellt also verschiedenen Parser bereit (DOM und SAX), hat aber nur wenige komfortable Methoden um XML Daten zu manipulieren. Der Zugriff auf den DOM-Baum ist z.B. recht kompliziert und benutzt eigene und nicht die von Java propagierten Design-Patterns. Dies ist auch der grösste Schwachpunkt von «Xerces-J». (Dateien: xercesImpl.jar, xmlParserAPIs.jar). Um diese Schwäche auszumerzen wird eine weitere Bibliothek verwendet. «JDOM» vom JDOM Projekt [JDOM 02]. Diese Bibliothek unterstützt in etwa eine vergleichbare Funktionalität wie «Xerces-J» ist aber nicht als Aufsatz auf diese Parser-Bibliothek zu verstehen sondern sie stellt ein Java-basiertes «Document Object Model» für XML Daten bereit. JDOM benutzt aber einen XML-Parser um dieses Dokumenten-Modell zu erstellen (in unserem Fall «Xerces-J»). Für den weiteren Zugriff auf die Baumstruktur verwendet JDOM die von Java bekannten Design-Patterns (Iterations, Enumerations, etc.) und erleichtert dem Programmierer dadurch die Arbeit enorm. Es müssen keine Java-Interfaces implementiert werden sondern alle Klassen können einfach instantiiert werden. (Dateien: jdom.jar) Für die Funktionalität aus DTD's XML Schemas zu generieren wird auf die frei verfügbare Java-Klasse «dtd2xs» von Simon Hölzer und Ralf Schweiger zurückgegriffen [DTD2XS 02]. Diese Java-Klasse kommt mit zwei angepassten kleinen Bibliotheken und lässt sich leicht in vorhandene Projekte einbinden. Natürlich ist der Quellcode auch frei verfügbar. (Dateien: xml.jar, xt.jar) Autor: Thomas Schädler 32 6 Implementation des Modells 6 Implementation des Modells Als erstes wird der in Abschnitt 4.3.1 beschriebene Konfigurator implementiert, der als Grundlage für die einzelnen Mappingmodule fungiert. Da der Konfigurator und der Server auf die gleichen Daten zugreifen wird als erster Punkt jedoch die verwendete Speicherungshierarchie erläutert. Darauf aufbauend werden die Module aufsteigend nach Komplexität implementiert und erst anschliessend wird die in Abschnitt 4.3.2 definierte Serverkomponente implementiert um das Projekt zu vervollständigen und die Daten schlussendlich automatisch auf Anfrage generieren zu können. 6.1 Speicherungshierarchie der Projektdaten Die von beiden Applikationen benutzten Projektdaten werden in einem Projektverzeichnis gespeichert. Dieses Verzeichnis wiederum enthält verschiedene Unterverzeichnisse, welche je ein Projekt beinhalten. Der Name eines Projekts ist zugleich der Name des Unterverzeichnisses. In diesem Unterverzeichnis werden alle von diesem Projekt abhängigen Daten abgelegt. Dies ist je eine Datei mit Namen «xmlizer.xml» welche alle für das Projekt benötigten Grunddaten und die Mappingdaten enthält. Genauere Hinweise zu diesen Daten folgen in Abschnitt 6.2. Auch die von einem Projekt verwendeten XML Schemas werden hier als Kopie gespeichert, wobei in den Projektdaten selbst nur relative Pfade verwendet werden. Dies hat den Vorteil, dass ein Projektverzeichnis - ohne die Abhängigkeiten zu zerstören - verschoben werden kann. Da die verwendeten XML Schemas nur Kopien darstellen muss sich ein Anwender keine Gedanken um die Sicherheit seiner Daten machen, da auf die Originaldateien und die verwendeten Datenbanken nur lesend zugegriffen wird. Ein weiterer Vorteil einer solchen Speicherungshierarchie ist, dass beim starten einer Applikationen dieser ein Projektverzeichnis zugewiesen werden kann, mit welchem dann gearbeitet wird. Dies bedeutet, dass z.B. verschiedene Anwender ihre eigenen Projektdaten getrennt ablegen können. 6.2 Implementation des Konfigur ators Eine Übersicht über die Klassen welche für die Benutzerschnittstelle (engl.: User Interface) bedeutend sind verschafft Abbildung 20. Das Hauptfenster des Konfigurators - die Klasse «configurator» - stellt einen Container für die Module dar und kümmert sich gleichzeitig um die Ausgaben, den Aufbau und die Speicherung der Projektdaten. Um die Module darzustellen wurde eine «JDesktopPane» gewählt, wobei alle weiteren Fenster als innere Fenster («JInternalFrame») dargestellt werden. Dies erhöht die Übersichtlichkeit und stellt eine gewohnte Arbeitsoberfläche zur Verfügung. Alle inneren Fenster müssen die Klasse «MyInternalFrame» implementieren welche wiederum eine Unterklasse von «JInternalFrame» ist und um eine «update» Funktion erweitert wurde. Dies wird benötigt um den Inhalt eines Fensters aktualisieren zu können, falls in einem anderen Fenster die zugrundeliegenden Daten geändert wurden (Feedback). Autor: Thomas Schädler 33 6 Implementation des Modells Um die internen Fenster zu verwalten wurde ein einfacher Fenstermanager entwickelt, welcher sich um die Verwaltung der geöffneten Fenster kümmert. Gleichzeitig erstellt er auch die Einträge im Fenster-Menü (für den schnellen Wechsel zwischen verschiedenen Fenstern) und aktiviert oder deaktiviert verschiedene Menü- und Toolbareinträge abhängig vom Programmzustand praktisch automatisch. Abbildung 20 : UML Klassen-Diagramm des Konfigurators (User Interface) [JVision 02] Das Konzept für die Ausgaben wurde zentralisiert und wird in der Klasse «logWindow» verwaltet. Diese Klasse stellt Methoden zur Verfügung um je nach Wichtigkeit Informationen, Warnungen und Fehler darzustellen. Gleichzeitig stellt diese Klasse auch ein Interface zur Verfügung um jegliche Textdateien darzustellen. Als weitere Funktion kann hier falls erwünscht auch noch der Debugoutput angezeigt werden. Dieses zentralisierte Konzept ve reinfacht den Umgang mit verschiedenen Textdaten und ermöglicht es den ganzen Arbeitsprozess in einer Datei zu loggen. Um die Hilfe zu Implementieren wird auf normale HTML-Seiten zurückgegriffen, welche in einem internen HTML-Browser dargestellt werden («HTMLBrowser»). An verschiedensten Stellen im Programm kann somit ein Hilfe-Knopf implementiert werden und es muss dabei nur eine neue Seite aufgerufen werden, die dann sofort dargestellt wird. Da Java alle benötigten Klassen für die schnelle Implementation eines einfachen Webbrowsers mitliefert stellt dies keinen grossen zusätzlichen Aufwand dar. Die Hilfe («helpWindow») und der JavaDoc-Browser («javadocWindow») benutzen beide die Klasse «HTMLBrowser». Autor: Thomas Schädler 34 6 Implementation des Modells Die Klasse «setupWindow» kümmert sich um die Erstellung und anschliessend auch um die Änderung an den grundlegenden Projektdaten. Sie stellt eine Wizard-ähnliche Oberfläche bereit um Datenbankverbindungen einzugeben und zu testen sowie einen Validator für XML Schemas (well-formedness wird überprüft und abhängige Dateien semi-automatisch eingebunden). Hier werden auch die «dtd2xs»-Klassen verwendet um als Inputformat auch Document Type Definitions verwenden zu können (automatische Konvertierung in ein XML Schema). Abbildung 21 : UML Klassen-Diagramm des Konfigurators (Daten) [JVision 02] Eine Datenbankverbindung wird auf zwei Arten getestet. Zuerst wird versucht den angegeben JDBCTreiber zu laden. Ist das erfolgreich wird eine Verbindung hergestellt und der Anwender hat die Möglichkeit mit einem einfachen Datenbankbrowser diese Datenbank zu inspizieren. Die Datenstruktur der Projektdaten spiegelt die vier unterschiedlichen Informationen wieder die darin gespeichert werden. Abbildung 21 zeigt die damit verbundenen Klassen in der Übersicht. Sie bestehen aus einer Liste von «dbItem» (für die Datenbankverbindungen), «xmlItem» für die XML Dateien, «dataItem» für die restlichen Daten und einer optionalen Mappingkomponente welche weiter unten genauer analysiert wird (siehe auch Abbildung 18 und Abbildung 19). Um wenigstens minimale Sicherheit zu gewährleisten wird das Datenbankpasswort sehr einfach verschlüsselt (XOR) in einer Projektdatei gespeichert. Das Passwort ist damit zwar nicht wirklich sicher, verunmöglicht es aber durch einfaches Lesen einer Konfigurationsdatei das Passwort zu erhalten und stellt in diesem Zusammenhang eine ausreichend grosse Sicherheit als Kompromiss zwischen Aufwand und Gefährdung dar, da solche Dateien nur lokal gespeichert werden. Des weiteren enthält die Klasse «projectData» Methoden um die Projektdaten in XML auszugeben oder diese aus einer vorhandenen XML Datei einzulesen. Dieser Vorgang wird auch als Marshalling/Unmarshalling bezeichnet. Beim beenden des Setups wird das ausgewählte Modul gestartet, welches dann die Kontrolle übernimmt. Beide implementierten Module bestehen wiederum aus Klassen, welche «MyInternalFrame» Autor: Thomas Schädler 35 6 Implementation des Modells implementieren und tragen den Namen «SMDBEmain» für das Modul «Simple DB Export», respektive «DB2XMLmain» für das Modul «Database to XML» (siehe Abbildung 20). Damit die ganze Oberfläche während den Berechnungen nicht blockiert, wird ein «ThreadPool» verwendet der sich um die verschiedenen Hintergrundaufgaben kümmert. Alle längeren Berechnungen werden damit in einem eigenen Thread gestartet und der «ThreadPool» kümmert sich um deren Ausführung und Verwaltung. Dieser «Threadpool» wird sowohl für die Benutzeroberfläche als auch für Datenberechnungen verwendet. 6.2.1 Implementation des Moduls «Simple DB Export» Dieses erste Modul ist ein leicht umgebauter Datenbankbrowser und stellt zusätzlich zu dessen Funktion die Möglichkeit bereit einzelne Tabellen auszuwählen (um nicht immer die ganze Datenbank exportieren zu müssen) und stellt dem Anwender zwei verschiedene fixierte Ausgabeformate zur Verfügung. <?xml version="1.0" encoding="UTF-8"?> <database name="Project DB" url="jdbc:mysql://localhost:3306/projekte?useUnicode=true"> <tables> <projekte> <row> <ID>1</ID> <name>orange8</name> <ende>2001-12-31</ende> <status>0</status> <anfang>2001-10-31</anfang> </row> <row> <ID>2</ID> <name>e-freak</name> <ende>2002-06-30</ende> <status>0</status> <anfang>2002-03-01</anfang> </row> </projekte> </tables> </database> Abbildung 22 : Beispielausgabe des Moduls «Simple DB Export» (simple) Das einfachere Format («simple») basiert auf dem von Ronald Bourret vorgeschlagenen Ausgabeformat für Tabellen-basiertes Mapping (siehe Abbildung 13 und ein Beispiel in Abbildung 22) und wurde lediglich um zwei Attribute erweitert welche weitere Informationen zu der ausgewählten Datenbank enthalten (Name und JDBC-URL der Datenbank). Dieses Format basiert auf keiner DTD und kann deshalb nicht validiert werden. Autor: Thomas Schädler 36 6 Implementation des Modells Das erweiterte Format («verbose») ist eine standardisierte Erweiterung des einfachen Formates wobei es so abgeändert wurde, dass es in einer DTD ausgedrückt werden kann (Tabellennamen werden als Attribute und nicht als Elementnamen ausgedrückt). Des weiteren enthält es noch den Typ der Daten. Dies erhöht die Redundanz der Daten, dafür sind alle Informationen enthalten um aus diesen Daten zu einem späteren Zeitpunkt eine Datenbank zu rekonstruieren (siehe Abbildung 23 für die DTD und ein Beispiel der Ausgabe in Abbildung 24). <?xml version="1.0" encoding="UTF-8"?> <!ELEMENT database (tables*)> <!ATTLIST database name CDATA #REQUIRED url CDATA #REQUIRED > <!ELEMENT tables (table*)> <!ELEMENT table (row*)> <!ATTLIST table name CDATA #REQUIRED > <!ELEMENT row (column*)> <!ELEMENT column EMPTY> <!ATTLIST column name CDATA #REQUIRED type CDATA #REQUIRED data CDATA #REQUIRED > Abbildung 23 : xmlizer.smdbe.verbose.dtd Für die Erzeugung des XML Formats, wurde auf die Verwendung von DOM verzichtet, da die Ausgabe von Datenbanktabellen sehr grosse Datenmengen erzeugen kann. DOM kann nur auf kleine XML Dokumente angewendet werden, da der Speicherverbrauch (unabhängig von der verwendeten DOMBibliothek) sehr gross ist. Die Ausgabe von grossen Datenbanken kann daher auch sehr lange dauern. Deshalb ist es möglich die Ausgabe abzubrechen. Dazu wurde die Klasse «activityMeter» bereitgestellt, welche einen Knopf zum abbrechen und eine «JP rogressBar» enthält um den Fortschritt zu beobachten. Diese Progressbar zeigt ausserdem die Anzahl aktuell laufender Hintergrundprozesse an, die aber nicht gestoppt werden können. Durch die ausgiebige Verwendung von Threads ist es auch möglich während eines laufenden Exports weitere Tabellen der Datenbank anzeigen zu lassen. Die grafische Oberfläche diese Moduls («SMDBEmain») ist nichts weiter als ein speziell angepasster Datenbank-Browser («dbBrowser»), da sich die Möglichkeiten dieses Moduls mit der Auswahl von Tabellen und dem Auswählen eines Ausgabenformates erschöpfen. Autor: Thomas Schädler 37 6 Implementation des Modells <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE database SYSTEM "xmlizer.smdbe.verbose.dtd"> <database name="Project DB" url="jdbc:mysql://localhost:3306/projekte?useUnicode=true"> <tables> <table name="projekte"> <row> <column name="ID" type="LONG" data="1"/> <column name="name" type="VARCHAR" data="orange8"/> <column name="ende" type="DATE" data="2001-12-31"/> <column name="status" type="INT" data="0"/> <column name="anfang" type="DATE" data="2001-10-31"/> </row> <row> <column name="ID" type="LONG" data="2"/> <column name="name" type="VARCHAR" data="e-freak"/> <column name="ende" type="DATE" data="2002-06-30"/> <column name="status" type="INT" data="0"/> <column name="anfang" type="DATE" data="2002-03-01"/> </row> </table> </tables> </database> Abbildung 24 : Beispielausgabe des Moduls «Simple DB Export» (verbose) <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE xmlizerprojectconfig SYSTEM "xmlizer.project.config.dtd"> <xmlizerprojectconfig> <initialsetup> ...</initialsetup> <databasesetup> ... </databasesetup> <schemasetup> ... </schemasetup> <mapping> <smdbe> <smdbe_item name="XML-DB" type="simple"> <smdbe_table>activities</smdbe_table> </smdbe_item> <smdbe_item name="Project-DB" type="verbose"> <smdbe_table>dateien</smdbe_table> <smdbe_table>lesezeichen</smdbe_table> <smdbe_table>profile</smdbe_table> <smdbe_table>projekte</smdbe_table> <smdbe_table>termine</smdbe_table> </smdbe_item> </smdbe> </mapping> </xmlizerprojectconfig> Abbildung 25 : Beispiel der Mappingdaten für das Modul «Simple DB Export» (gekürzt) Diese Daten für das Mapping werden in der Konfigurationsdatei nach einem einfachen Schema gespeichert. Abbildung 25 zeigt ein Beispiel für gültige Mappingdaten. Für jede Datenbank wird ein Autor: Thomas Schädler 38 6 Implementation des Modells «smdbe_item» erstellt welches einen Namen und einen Typ haben muss (der Name wird vom Anwender beim Setup selbst zugeteilt und der Typ ist wie schon erwähnt entweder «simple» oder «verbose». Diese Elemente wiederum enthalten beliebig viele Elemente «smdbe_table» welche nur den Namen der zu exportierenden Tabelle enthält. 6.2.2 Implementation des Moduls «Database to XML» Dieses Modul stellt ein Interface zur Verfügung, mit dem beliebige XML Schemas eingelesen, mit Daten aus einer Datenbank gefüllt und als XML Instanz wieder ausgegeben werden können. Das grosse Problem bei diesem Modul ist, dass es momentan noch keinen (freien) XML Schema Parser oder eine XML Schema Bibliothek gibt. Da XML Schema auch in XML spezifiziert ist, kann aber ein normaler XML Parser verwendet werden. Man kommt allerdings nicht darum herum die Logik die hinter den Schemas steht beim Parsvorgang auszulesen und in einer internen Struktur aufzubauen um später daraus eine gültige Instanz abzuleiten. Die Baumstruktur einer XML Instanz ergibt sich aus der Verschachtelung der Elemente in einem XML Schema. Dabei muss allerdings berücksichtigt werden, dass für jedes Element viele Beschränkungen definiert sein können und die Typenbeschreibungen können global oder lokal definiert werden oder aber auch als Referenz auf einen schon definierten Typen angegeben werden. Bei der Implementation wird auf eine Typenüberprüfung verzichtet und alle Typen werden vereinfacht als «Strings» angesehen. Dies vereinfacht den Parsvorgang erheblich, überlässt es aber dem Anwender zu überprüfen, ob die eingegebenen Daten wirklich zu den im XML Schema angegebenen Datentypen passen. Die Typkorrektheit wird jedoch in ihren Grundzügen implementiert und kann (da Open Source) zu einem späteren Zeitpunkt hinzugefügt werden. Als zwischenzeitliche Hilfe wird der zu erwartende Typ immerhin in der Benutzeroberfläche angezeigt und die genaue Typendefinition kann in der Textansicht des XML Schemas (Text- und Baumsansicht werden beide angezeigt) nachgesehen werden. Abbildung 26 : xmlizer.project.config.xsd (Baum, nur Mapping) [XMLSPY 01] Beim Start diese Moduls wird das im Setup schon überprüfte XML Schema von der Klasse «XMLSchemaParser» geparst und als «JTree» (also als Baumansicht) ausgegeben. Die einzelnen Knoten dieses Baums sind von der Klasse «SchemaElement» und beinhalten alle benötigten Informationen über die Eigenschaften dieses Elements. Die Anzahl zulässiger Repetitionen («SchemaOccurAutor: Thomas Schädler 39 6 Implementation des Modells rence»), die Attribute («SchemaAttribute»), ob das Element selbst Text enthalten kann («SchemaContent») und weitere Informationen. Um das ganze grafisch darzustellen wird die Klasse «SchemaElementPanel» verwendet und für das Wurzelelement analog dazu «SchemaRootPanel». Die Unterscheidung von Wurzelelement und «normalen» Elementen wird aus dem Grund gemacht, da das Wurzelelement immer nur einmal vorkommt, also keinen Textinhalt und keine Repetition enthalten kann. Dafür können im Wurzelelement Parameter (mit Standardwerten) definiert werden die global zur Verfügung stehen und bei den anschliessend eingefügten SQL Abfragen Verwendung finden. Dies ermöglicht es die Ausgabe eine XML Instanz von diesen Parametern abhängig zu machen. <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE xmlizerprojectconfig SYSTEM "xmlizer.project.config.dtd"> <xmlizerprojectconfig> <initialsetup> ...</initialsetup> <databasesetup> ... </databasesetup> <schemasetup> ... </schemasetup> <mapping> <db2xml rootelement="activities"> <db2xml_parameter id="1028587364818" name="max" default="12"/> <db2xml_element name="activities" id="/activities"/> <db2xml_element name="activity" id="/activities/activity" repsql="1028581249836"> <db2xml_attribute name="origin"/ mapid="1028581249836" mapinfo="Primarykey"> <db2xml_attribute name="dbKey" mapid="1028581249836" mapinfo="dbKey"/> <db2xml_attribute name="date" mapid="1028581249836" mapinfo="date"/> <db2xml_sql id="1028581249836" db="XML-DB" sql="SELECT * FROM activities where Primarykey< [-1028587364818:max -]"> <db2xml_sql_info name="PrimaryKey" type="LONG"/> <db2xml_sql_info name="ForeignKey" type="LONG"/> <db2xml_sql_info name="date" type="BLOB"/> <db2xml_sql_info name="dbKey" type="BLOB"/> </db2xml_sql> </db2xml_element> <db2xml_element name="ID" id="/activityType/ID" repsql="1028582462540"> <db2xml_attribute name="infoStatus" /> <db2xml_sql id="1028582462540" db="XML-DB" sql="SELECT * FROM id where primarykey= [1028581249836:PrimaryKey]"> <db2xml_sql_info name="PrimaryKey" type="LONG"/> <db2xml_sql_info name="ForeignKey" type="LONG"/> <db2xml_sql_info name="uniqID" type="BLOB"/> </db2xml_sql> </db2xml_element> </db2xml> </mapping> </xmlizerprojectconfig> Abbildung 27 Autor: Thomas Schädler : Beispiel der Mappingdaten für das Modul «Database to XML» 40 6 Implementation des Modells Bei diesem Parsvorgang werden schon vorhandene Informationen aus den geladenen Mappingdaten des verwendeten Projekts (falls vorhanden) in die einzelnen Elemente eingefügt, oder wenn noch keine Mappingdaten verfügbar sind werden diese aufgebaut. Die Struktur der Mappingdaten ist in einer Baumansicht in Abbildung 26 ersichtlich und ein Beispiel eines solchen Mappings ist in Abbildung 27 aufgeführt. Die verschiedenen Elemente und dazugehörigen Daten werden in den Mappingdaten nicht als Baumstruktur gespeichert. Dies ist deshalb nicht nötig, da diese Information im verwendeten XML Schema und in der daraus aufgebauten Baumstruktur vorhanden sind und bei einer Instanzgenerierung einfach dieser Baum durchlaufen wird. Die Mappingstruktur im Detail Als erstes (unterhalb des Elementes «db2xml»), werden die Parameter definiert. Jedes «db2xml_parameter»-Element enthält zwei Attribute. Den Namen des Parameters und sein Standardwert. Der Standardwert wird verwendet, falls bei der anschliessenden Instanzgenerierung beim Server keine Parameter übergeben werden. Andernfalls werden die Werte des übergebenen Parameters verwendet (Genauere Informationen zum Server folgen im nächsten Abschnitt). Bei der Generierung einer Instanz im Konfigurator können keine Parameter angegeben werden, es werden immer die Standardwerte verwendet, was aber für den Zweck einer Testausgabe ausreicht. Alternativ kann man die momentanen Daten speichern und die Ausgabe (mit erweiterten Parametern) mit Hilfe des Servers überprüfen. Als weitere Elemente folgen eine Liste von «db2xml_element»-Elementen. Diese Elemente enthalten als eindeutiges Erkennungsmerkmal eine XPath-ähnliche Pfadangabe, die deshalb benötigt wird, da in einem XML Schema verschiedenen Elementen mit gleichem Namen, aber verschiedenen Typen vorkommen können. Als optionales Attribut kann ein solches Element, falls es mehrfach vorkommen kann, das Attribut «repsql» enthalten welches eine eindeutige ID des zu verwendenden SQL Statements enthält. Des weiteren enthält jedes «db2xml_element»-Element für alle möglichen Attribute ein «db2xml_attribute»-Element welches als Attribut «name» den Namen dieses Attributs enthält und optional dazu noch ein Attribut «mapid» welches wiederum eine eindeutige ID eines SQL Statements enthält und ein Attribut «mapinfo», welches sich auf die zu verwendende Datenbankspalte bezieht. Als letztes kann jedes «db2xml_element»-Element noch ein oder mehrere «db2xml_sql»-Elemente enthalten, welche als Attribut «id» bei der Erzeugung eine eindeutige ID zugewiesen bekommen, welche für die Zuweisung zu den Elementen und Attributen der zu erstellenden Instanz benötigt wird. Das Attribut «db» kennzeichnet die zu verwendende Datenbankverbindung so wie sie im Setup definiert wurde. Dies ermöglicht es eine Instanz zu generieren die aus mehreren Datenbankquellen Informationen enthält und erweitert den Einsatzbereich des Mappingtools erheblich. Des weiteren enthält jedes «db2xml_sql»-Element für jede Datenbankspalte der Abrage ein «db2xml_info»-Element welches den Namen und den Typ dieser Datenbankspalte als Attribut «name» respektive «type» enthält. Autor: Thomas Schädler 41 6 Implementation des Modells Um innerhalb eines SQL Statements auf Parameter oder auf Werte aus übergeordneten (in der Baumstruktur auf einer höheren Ebene vorhandenen) SQL Statements zu verweisen wird eine Substitution angewendet. Die Parameter werden im Format "[-" + <parameterID> + ":" + <parameterName> + "-]" (Beispiel: [-1028587364818:max -]) eingebettet und Referenzen auf andere SQL Statements im Format "[" + <sqlID> + ":" + sqlInfoName + "]" (Beispiel: [1028581249836:PrimaryKey]). Bei der Instanzgenerierung werden nun diese eingebetteten Platzhalter durch die jeweils aktuell aus der Datenbank ausgelesenen Werte ersetzt (Abhängig von der jeweiligen Datenbankreihe). Damit der Anwender sich nicht mit diesen kryptischen Formaten auseinandersetzen muss, wird das Mapping selbst mit Hilfe von Drag and Drop implementiert. In diesem Abschnitt wird jetzt genauer auf die technischen Details der Implementation der Oberfläche und der Instanzgenerierung für dieses Mapping eingegangen. Genauere (weniger technische) Informationen für Anwender finden sich in Abschnitt 7. Die Instanzgenerierung Die am Anfang dieses Abschnitts erläuterte Baumstruktur die sich in der Klasse «DB2XMLmain» befindet ist nach dem Parsvorgang noch leer und enthält keinen Parameter und keine SQL Statements. Eine Instanzgenerierung ist jedoch in diesem Zustand schon zulässig, ergibt aber einfach eine XML Instanz die ein leeres Wurzelelement enthält. Der Vorgang der Instanzgenerierung läuft nach folgendem Schema ab. Der Baum wird von der Wurzel an durchlaufen und bei jedem Element wird zuerst das Repetitionsstatement (SQL) ausgeführt. Die Anzahl Datenbankreihen des Resultates ergibt die Häufigkeit der Wiederholung dieses Elements. Danach werden die einzelnen Daten für den Textinhalt und die Attribute eingesetzt (je nach «mapid» und «mapinfo»). Wenn sich die Daten für den Textinhalt und die Attribute auf das Repetitionsstatement beziehen wird die aktuelle Datenbankreihe verwendet. Es ist aber auch möglich für diesen Inhalt einzelne SQL Statements zu verwenden. Diese SQL Statements sollten immer nur einzelnen Werte (oder nur eine Datenbankreihe) zurückgeben. Als Workaround wird jedoch - sollte das zugeordnete Statement mehrere Resultatreihen liefern - nur immer die erste Datenbankreihe verwendet. Als Einschränkung bei der Verwendung dieser Methode ist es aber nicht Möglich «choices» - die in einem XML Schema verwendet werden - zu generieren, da diese einen Vergleich von zwei Werten benötigen um zu entscheiden wie weiterverfahren wird. Im jetzigen Zustand werden nur echte Schemaelemente implementiert. Die Implementation von «any» (Wildcard-Element) und anderen erweiterten XML Schemakonstrukten wird für eine spätere Erweiterung des Konfigurators aufgespart. Der «XMLSchemaParser» erlaubt es aber auch zu diesem Zeitpunkt XML Schemas die diese Konstrukte verwenden zu parsen, nur können diese Element zum jetzigen Zeitpunkt nicht mit Daten assoziiert werden (sie zeigen bei der Auswahl kein «SchemaElementPanel» an). Autor: Thomas Schädler 42 6 Implementation des Modells Die Benutzeroberfläche mit Drag und Drop Um die Abhängigkeiten für das Mapping grafisch darzustellen und vorzunehmen werden die in Abbildung 20 aufgeführten Klassen «SQLChooser», «dbBrowser» und «DataChooser» benötigt. Die einzelnen Elemente in der Baumansicht enthalten je ein «SchemaElementPanel». Dieses dient dazu die Daten des ausgewählten Elements anzuzeigen und enthält ausserdem noch sog. Droptargets (Ziele für den Datenaustausch). Diese ermöglichen es Daten (in unserem Fall die weiter oben definierten Platzhalter) in das «SchemaElementPanel» einzufügen, wodurch auch gleichzeitig die Mappingdaten angepasst werden. Die Datenquelle für diese Droptargets stellt der «SQLChooser» dar, welcher zu jedem ausgewählten Element in einem eigenen Fenster dargestellt wird. Dieses Fenster enthält alle SQL Statements die für das Mapping benötigt werden. Man kann einfach SQL Statements durch das drücken des «Add»Knopfes hinzufügen. Dies wiederum öffnet zwei neue Fenster: einen «dbBrowser» und den «DataChooser». Diese zwei Fenster funktionieren nach dem gleichen Prinzip. Der «dbBrowser» enthält ein Droptarget (hier das SQL Textfeld) und der «DataChooser» stellt die Datenquelle bereit. Um SQL Statements im Datenbankbrowser von anderen Werten abhängig zu machen, kann im «DataChooser» ein Element ausgewählt werden, welches sich auf einer höheren Ebene in der Baumstruktur befindet. Bei der Selektion eines Elementes wird das mit diesem Element verknüpfte Repetitionsstatement angezeigt und es ist nun möglich die Datenbankspalten dieses Resultates auf das Droptarget zu ziehen. Ausserdem ist es immer möglich die definierten Parameter zu verwenden (global verfügbar). Beim schliessen des Datenbankbrowsers wird das aktuelle SQL Statement zum «SQLChooser» hinzugefügt. Die Daten im «SQLChooser» können nun per Drag und Drop auf die Repetition, die Attribute und den Textinhalt eines Elemente gezogen werden. Hier greifen jedoch einige Einschränkungen die nötig sind um die Ausgabe sinnvoll zu gestalten. Die Droptargets des Textinhalts und der Attribute sind nur aktiv, wenn ein Repetitionsstatement eingefügt wurde, da sonst bei der Instanzgenerierung dieses Element gar nicht erzeugt wird (ausser das Element kommt genau einmal vor). Bei Repetitionen können nur ganze SQL Statements eingefügt werden. Bei Attributen und dem Textinhalt kann entweder ein SQL Statement - jedoch nicht das schon verwendete Repetitionsstatement - oder einzelnen Datenbankspalten des Repetitionsstatements oder eines übergeordneten Repetitionsstatements eingefügt werden. Beim Einfügen eines ganzen SQL Statements ist darauf zu achten, dass das Resultat dieser Abfrage nur einen Einzelwert zurückgibt. Dies wird dadurch erreicht, dass es nicht möglich ist mehrere SQL Statements die mehr als eine Datenbankreihe zurückgeben zum «SQLChooser» hinzuzufügen. Enthält dieses SQL Statement jedoch auch mehrere Spalten ist eine Instanzgenerierung nicht möglich, da nicht entschieden werden kann welcher Wert nun eingefügt werden soll. Els wird dem Anwender überlassen hier eine sinnvolle Zuordnung zu machen. Das «logWindow» gibt entsprechende Hinweise als Warnung aus, die es dem Anwender vereinfachen solche mehrdeutigen Zuordnungen zu erkennen. Autor: Thomas Schädler 43 6 Implementation des Modells 6.3 Implementation des Servers Die Funktion des Servers beschränkt sich auf die Ausgaben der mit dem Konfigurator vorgenommenen Mappingdaten. Die gleiche Funktionalität ist schon im Konfigurator enthalten und wird dort für die Testausgabe verwendet. Das ganze wurde nun automatisiert und Anworten (in XML oder HTML) können auf Abruf generiert werden. Der Server nimmt HTTP Anfragen an, die im «ConnectionHander» analysiert und bei Erkennung einer gültigen Anfrage an den «ProjectManager» weitergegeben werden. Nach erfolgreicher Generierung des Resultats wird dieses an den Webbrowser der die Anfrage geschickt hat zurückgeschickt («Response»). Der «ConnectionHander» ist eine Implementation des Java-Interfaces «HttpRequestListener» und liefert damit die ganze Funktion die für einen einfachen Webserver benötigt wird. Eine Übersicht über die wichtigsten Klassen liefert Abbildung 28. Abbildung 28 : UML Klassen-Diagramm des Servers (Komplett) [JVision 02] Der «ProjectManager» erfüllt dabei die gleiche Funktionalität wie die Hauptklasse des Konfigurators (die Klasse «configurator» in Abbildung 20 und Abbildung 21) und kümmert sich somit um die Erstellung einer XML Instanz aus den gespeicherten Mappingdaten und den optional als sog. «Querystring» übergebenen Parametern. Im folgenden ist nun der Ablauf einer Anfrage im Detail beschrieben. Der «ConnectionHander» nimmt eine Anfrage entgegen und generiert aus dem übergebenen «Querystring» mit Hilfe der Klasse «CgiParser» einen «LookupTable». Dieser enthält nun die aufgerufenen Methode (oder Seite) und eine Liste von Parametern. Wird eine Seite aufgerufen (z.B. index.html) wird diese direkt im «ConnectionHander» behandelt und falls diese im «html»-Verzeichnis vorhanden ist wird die entsprechende HTML-Seite ausgeliefert. Diese Funktionalität kann auch deaktiviert werden (der sog. Steath-Mode, bei dem nur Projektdaten ausgeliefert werden und alle anderen Anfragen stillschweigend unterdrückt werden). Vor der Auslieferung einer HTML-Seite wird diese jedoch noch geparst und eventuell vorkommende Platzhalter werden durch die entsprechende Funktionalität ersetzt (genaueres dazu findet Autor: Thomas Schädler 44 6 Implementation des Modells man im Abschnitt 7.4). Dies ermöglicht es die selbe HTML-Seite mit verschiedenen Inhalten darzustellen und minimiert die Einbettung von HTML-Code im Sourcecode des Servers. Wird als Methode im «LookupTable» jedoch «xmlizer», «htmlizer» oder «customizer» vorgefunden handelt es sich um eine Abfrage von Projektdaten und der «ProjectManager» tritt in Aktion. Die Generierung der Projektdaten verhält sich genau wie in Abschnitt 6.2.1 und 6.2.2 beschrieben mit der Ausnahme, dass für das Module «Database to XML» die übergebenen Parameter deren Namen mit denen in den Projektdaten übereinstimmen ersetzt werden. Die Funktionalität dieser drei Methoden ist fast die gleiche nur wird das Auslieferungsformat der generierten Projektdaten geändert. Bei «xmlizer» wird XML zurückgegeben, bei «htmlizer» werden die gleichen Daten schön in HTML formatiert zurückgegeben und der «customizer» vereint beide Funktionen (mit Hilfe des Parameters «xmlizerformat» mit dem Wert «xmlizer» oder «htmlizer» kann gewählt werden welches Format gewünscht wird). «customizer» ist eigentlich überflüssig und stellt nur eine Hilfsfunktion dar um mit einem Formular beide Formate auswählen zu können ohne zwei Formulare verwenden zu müssen. 6.4 Erfahrungsbericht Wie erwartet war das grösste Problem bei der Implementation die grafische Oberfläche des Konfigurators. Trotz vieler Hilfen durch die verwendete IDE [Forte 02], ist es noch immer nicht trivial eine gut funktionierende Benutzeroberfläche zu erstellen. Die jetzige, brauchbare Version hat noch immer einige Eigenheiten, kann aber produktiv eingesetzt werden. Die Implementation des Servers hingegen stellte sich als einfache Aufgabe heraus und der Zeitaufwand hielt sich sehr in Grenzen. Die XML Unterstützung der benutzen IDE erwies sich aber sehr schnell als unnütz, da sie eher dafür gedacht ist einen grafischen Editor für XML darzustellen als wirkliche (programmiertechnische) Unterstützung für die Einbettung von XML Funktionalität in eine Applikation darzustellen. Als Editor für die verwendeten XML Schemas und DTD's wurde jedoch das viel mächtigere XMLSpy [XMLSpy 01] verwendet, welches sehr gute Hilfe leistete. Für die Implementierung der XML Funktionalität erwies sich jedoch JDOM [JDOM 02 ] als sehr brauchbar und nach einer kurzen Eingewöhnungszeit kann man damit sehr produktiv arbeiten, da JDOM die von Java bekannten Design Patterns unterstützt. Im Gegensatz dazu würde die alleinige Verwendung der W3C XML Bibliothek (die als Grundlage für JDOM dient) einen erheblichen Mehraufwand (an Code und Nerven) bedeuten. Java als Programmiersprache selbst eignet sich für alle benötigten Aufgaben sehr gut (grafische Oberfläche, Serverfunktionalität und sonstige Datenbearbeitung). Als Negativpunkt muss man die ausgeprägte Langatmigkeit dieser Programmiersprache nennen, was sich auch in der Länge des resultierenden Sourcecodes niederschlägt (siehe Anhang A und B). Der Autor ist sich sonst etwas genügsamere Sprachen gewohnt (Perl, PHP). Alles in allem kann aber ein positives Fazit gezogen werden. Autor: Thomas Schädler 45 7 Informationen für Anwender 7 Informationen für Anwender 7.1 Einführung <xmlizer> configurator/server ist ein Werkzeug das aus einem grafischen Mappingtool und dem dazugehörigen Server besteht. Es ist möglich jegliche XML Schemas oder DTD's einzulesen und ein Regelwerk aufzustellen wie die Daten aus verschiedenen Datenbanken in dieses vom XML Schema vorgegebenen Format eingefügt werden kann. Die daraus resultierenden XML Instanzen können mit Hilfe es Servers automatisch auf Abfrage generiert werden. Als Beispiel für eine Anwendung kann das AIDA IDML Format genannt werden. Es ist möglich nach einer einfachen Definition mit Hilfe des Konfigurators diese Daten einem breiten Publikum zugänglich zu machen. Ein weiteres Beispiel wäre das RDF/RSS Format um Nachrichten auszutauchen. Dieses Format wird für die sog. «news syndication» verwendet und stellt heute fast schon einen Standard auf diesem Gebiet dar. Mit Hilfe des Konfigurators kann nun auf einfache Weise dieses Format erzeugt und mit Hilfe des Servers sofort der Öffentlichkeit zugänglich gemacht werden. Eine Fülle ähnlicher Anwendungsmöglichkeiten sind denkbar. 7.2 Systemvoraussetzungen und Installation Die Art des Betriebsystems spielt keine Rolle. Jede Plattform für die eine Java Virtual Machine verfügbar ist kann genutzt werden. Um den Konfigurator oder den Server starten zu können muss jedoch mindestens Java 1.3 oder höher installiert sein. Ausserdem werden einige Bibliotheken benötigt: • jdom.jar è (http://www.jdom.org/ ) • xercesImpl.jar èXerces XML Parser (http://xml.apache.org/xerces-j/) • xmlParserAPIs.jar èXerces W3C XML library(http://xml.apache.org/xerces-j/) • xml.jar èSun's XML Parser API (http://java.sun.com) • xt.jar è a fast XSLT implementation (http://www.blnz.com/xt/) • mm.mysql-2.0.12-bin.jar èmm.mysql database driver (http://mmmysql.sourceforge.net/) • … oder der für Ihre Datenbank benötigte JDBC-Treiber Diese Bibliotheken sowie die neueste Version von <xmlizer> configurator/server sind auf folgender Website verfügbar: http://www.e-freak.ch/xmlizer. Hier finden Sie auch zusätzliche Information, Beispiele und ein Support-Forum. Alternativ kann der Support unter folgender E-Mail angefragt werden: [email protected] Die oben genannten Bibliotheken können Sie einfach in das Verzeichnis «lib/ext» des verwendeten Java Runtime Environments kopieren oder den «classpath» in dem mit der Distribution mitgelieferten Startskript anpassen (siehe weiter unten). Autor: Thomas Schädler 46 7 Informationen für Anwender Die Installation ist sehr einfach. Sie müssen nur den Server und/oder den Konfigurator herunterladen und die gezippten Dateien in ein Verzeichnis entpacken. Achten Sie aber darauf, dass die Verzeichnisstruktur erhalten bleibt. In diesem Verzeichnis befindet sich nun eine readme-Datei und eine Batch-Datei um den Server auf Windows zu starten. Wenn sie ein anderes Betriebssystem verwenden müssen Sie nur die Batch-Datei ausführbar machen und als erste Zeile die Shell angeben, welche dieses Skript starten soll (z.B.#!/bin/bash). Des weiteren müssen Sie - falls Java nicht in Ihrem Pfad ist - den vollständigen Pfad angeben (einfach «java» durch den vollständigen Pfad zu Java ersetzen) und gegebenenfalls den «classpath» anpassen. Wenn Sie die Bibliotheken nicht ins «lib/ext»-Verzeichnis kopiert haben müssen Sie nur alle Bibliotheken in ein Verzeichnis entzippen und diese in den «classpath» hinzufügen (z.B. -classpath %CLASSPATH%;.;xml.jar;jdom.jar etc...). Achten Sie aber darauf auf jeden Fall das aktuelle Verzeichnis (.) nicht zu vergessen. 7.3 Handbuch: <xmlizer> configurator 7.3.1 Startparameter Der Konfigurator unterstützt folgende Startparameter: • -config <name> Mit dieser Option können Sie den Konfigurator mit einer bestimmten Konfigurationsdatei starten. Dies ist nützlich für verschiedene Anwender oder bei der Verwendung unterschiedlicher Projektverzeichnisse. • -open <pfad_zu_einer_xmlizer.xml_datei> Mit dieser Option kann ein bestimmtes Projekt gleich nach dem Start geöffnet werden. • -nosplash Diese Option unterdrückt den Splashscreen welcher beim Start kurz angezeigt wird. • -help Diese Option zeigt die möglichen Startoptionen in einem Fenster. Beim ersten Start des Konfigurator werden Sie nach zwei Verzeichnissen gefragt. Die Angabe ist zwingend notwendig, da der Konfigurator sonst nicht fehlerlos arbeiten kann. Das erste Verzeichnis ist das Basisverzeichnis. Dies ist normalerweise «configurator.xxx» wobei xxx für die Versionsnummer steht. Allgemein gesagt ist es das Verzeichnis in dem sich nach dem entzippen der Dateien das Startskript und die readme-Datei befinden. Das zweite Verzeichnis ist das Verzeichnis in dem die Projektdaten gespeichert werden. Beim ersten Start ist es noch nicht vorhanden und sollte vorher erstellt werden. In diesem Verzeichnis werden die später erstellten Projektdaten gespeichert (es sollte beim ersten Start leer sein). Tauchen beim Benutzen des Konfigurators dauern Fehlermeldungen über nicht gefundenen Dateien oder falsche Pfade auf, überprüfen Sie bitte ob diese Verzeichnisse wirklich richtig gesetzt sind und löschen Sie andernfalls die Konfigurationsdatei oder editieren Sie diese von Hand (einfaches, selbsterklärendes XML). Ist der Start erfolgreich werden die Verzeichnisdaten in einer Datei mit Namen «xmlizer.config» oder bei der Angabe einer Konfigurationsdatei mit dem Namen «xmlizer.config.<name>» in Ihrem Home-Verzeichnis abgelegt. Wenn Sie ihr Home-Verzeichnis nicht Autor: Thomas Schädler 47 7 Informationen für Anwender kennen finden Sie diese und andere Angaben im Konfigurator im Menü Help à System Info unter «USER Home». 7.3.2 Anleitung Diese Anleitung ist nur als Leitfaden zu verstehen. Detaillierte Hilfe zu den einzelnen Fenster und Arbeitsabläufen sind in der integrierten Hilfe der Applikation selbst zu finden. Der Arbeitsablauf ist in zwei Teile gegliedert. Zuerst wird ein neues Projekt angelegt (Menü: Project à New). Im Setupdialog werden die benötigten Datenbankverbindungen und das eventuell verwendete XML Schema (oder eine DTD) hinzugefügt, und als zweiter Schritt werden diese Informationen miteinander assoziiert. Für den zweiten Schritt wird nach beenden des Setupdialogs automatisch das entsprechende Modul gestartet. Abbildung 29 zeigt eine Übersicht des Hauptfensters (mit einem geöffneten Projekt). Abbildung 29 : Der Konfigurator in Aktion Projekt Setup Die Daten für die Erstellung eines neuen Projekts sind in drei Punkte gegliedert. Als erstes wird ein Name festgelegt und das Modul für die Art des zukünftigen Mappings ausgesucht. Der Name kann später nicht mehr geändert werden. Benutzen Sie im Menü Project à Save As um ein Projekt mit einem anderen Namen zu speichern. Im zweiten Schritt werden alle benötigten Datenbankverbindungen erstellt und auf eine erfolgreiche Verbindung getestet. Der dritte Schritt wird nur für das Modul Autor: Thomas Schädler 48 7 Informationen für Anwender «Database to XML» benötigt und legt ein XML Schema oder eine DTD fest, mit welchem gearbeitet werden soll. Eine DTD wird semi-automatisch in ein XML Schema konvertiert. Anleitung für das Modul «Simple DB Export» Diese Modul erlaubt es Ihnen eine Datenbank in zwei festgelegten XML Formaten zu exportieren. Die Einstellungsmöglichkeiten erschöpfen sich in der Auswahl des Formates («simple» oder «verbose») und der Auswahl der Datenbanktabellen die exportiert werden sollen. Dieses Modul besteht nur aus einem Fenster (siehe Abbildung 30). Abbildung 30 : Das Module «Simple DB Export» in Aktion Legen Sie für jede im Setup hinzugefügte Datenbank die Optionen fest und speichern Sie diese Einstellungen. Die Ausgabe können Sie im log-Fenster nach betätigen des «Export»-Knopfes überprüfen. Verwenden Sie anschliessend den Server um diese Ausgaben weiterzuverarbeiten. Anleitung für das Modul «Database to XML» Das im Setup festgelegte XML Schema ist der zentrale Knotenpunkt dieses Moduls. Es wird eingelesen und als Baumansicht dargestellt. Als erstes sollten Sie das Wurzelelement auswählen («schema») und dort die verwendeten Parameter definieren. Diese Parameter können später variiert werden um die Ausgabe von diesen Daten abhängig zu machen (keine statische Ausgabe wie im ersten Modul). Als weiterer Schritt können Sie die einzelnen Elemente mit Daten aus der Datenbank assoziieren. Hier wird vorgeschlagen sich von der Wurzel an aufwärts zu arbeiten. Beim Auswählen eines Elements öffnet sich ein zusätzliches Fenster (der sog. «SQLChooser»). Dieses beinhaltet von Ihnen erstellte SQL Abfragen. Da Sie noch keine SQL Abfragen definiert haben müssen Sie zuerst im «SQLChooser» mit Hilfe des «Add»-Knopfes ein oder mehrere solche Abfragen hinzufügen. Dadurch öffnen sich zwei neue Fenster: ein Datenbankbrowser und der dazugehörige «DataChooser» (siehe Abbildung 31). Wählen Sie im Datenbankbrowser eine Datenbank und selektieAutor: Thomas Schädler 49 7 Informationen für Anwender ren Sie eine Tabelle oder erstellen Sie ihre Abfrage von Hand. Um eine Abfrage von den Parametern oder von übergeordneten SQL Abfragen abhängig zu machen benutzen Sie den «DataChooser». Dort können Sie mit Hilfe von Drag und Drop Datenfelder in das Textfeld des Datenbankbrowsers ziehen, wobei diese (kryptischen) Textausschnitte bei einer ausgeführten Abfrage durch den realen Wert im Hintergrund automatisch substituiert werden. Beachten Sie bitte, dass diese Textauschnitte immer mit einem Leerschlag vom Rest des Textes getrennt sind, das Sie sonst nicht erfolgreich substituiert werden können. Das schliessen des Datenbankbrowsers fügt die erstellte Abfrage zum «SQLChooser» hinzu. Abbildung 31 : Das Modul «Database to XML» in Aktion : Der Datenbankbrowser Diese SQL Abfrage (oder Teile davon) können Sie per Drag und Drop mit einem entsprechenden Feld des ausgewählten Schemaelementes assoziieren. Dabei stehen verschiedene Optionen offen. Sie können und müssen als erstes (falls dieses Schemaelement mehrmals vorkommen kann) zuerst eine Abfrage mit dem (rot markierten) Repetitionsfeld verknüpfen (siehe Abbildung 32). Diese legt fest wie oft dieses Element wiederholt wird (die Anzahl Datenbankzeilen der entsprechenden Abfrage). Des weiteren können Sie SQL Abfragen oder einzelne Tabellenspalten (untere Hälfte des «SQL Choosers») mit den Attributen und dem Textinhalt dieses Elements verknüpfen. Der Textinhalt ist grün und die Attribute sind blau markiert. Dabei sind jedoch folgende Einschränkungen zu beachten. Sie können eine einer Repetition zugeordnete Abfrage nicht mehrfach verwenden und Sie können je Element nur eine Abfrage haben, die mehr als eine Datenbankzeile als Resultat zurückgibt. Es würde auch keinen Sinn machen dem Inhalt Attributs mehr als einen Einzelwert zuzuordnen. Es ist aber durchaus möglich ein Attribut oder den Textinhalt mit Daten aus übergeordneten Abfragen zu assoziieren. Benutzen Sie dazu die Elementauswahl des «SQLChoosers». Autor: Thomas Schädler 50 7 Informationen für Anwender Um die vorgenommenen Zuordnungen zu überprüfen können Sie mit dem «Export»-Knopf eine Instanz generieren. Diese XML Instanz wird im log-Fenter ausgegeben und entspricht der Ausgabe des Servers, der später dazu eingesetzt wird solche Instanzen auf Abfrage zu generieren. Beachten Sie, dass die Parameter im Konfigurator nicht geändert werden können. Es werden immer die definierten Standartwerte verwendet. Beim Server dürfen Sie hingegen diese Parameter nach belieben variieren. Abbildung 32 7.4 : Das Modul «Database to XML» in Aktion: Drag und Drop einer Abfrage Handbuch: <xmlizer> server 7.4.1 Startparameter Der Server unterstützt folgende Startparameter: • -config <name> Mit dieser Option können Sie den Server mit einer bestimmten Konfigurationsdatei starten. Es ist dadurch möglich verschiedenen Server auf unterschiedlichen Ports parallel zu betreiben. • -port <zahl> Diese Option legt den Port fest an dem der Server erreichbar ist (Standartwert = 7777). Es kann immer nur ein Server auf einem Port betrieben werden. • -base <basis_verzeichnis> Diese Option legt das Verzeichnis fest in dem der Server installiert ist. Diese Option ist beim ersten Start zwingend notwendig. • -projects <projekt_verzeichnis> Diese Option legt das Verzeichnis fest in dem sich die Projektdaten befinden. Diese Option ist beim ersten Start zwingend notwendig. Autor: Thomas Schädler 51 7 Informationen für Anwender • -webinterface on|off Diese Option schaltet das Webinterface ein oder aus (Standartwert = on). Wenn das Webinterface ausgeschaltet ist liefert der Server keine Fehlermeldungen an den Browser und es ist zwingend notwendig die genaue URL zu kennen um auf die Daten zuzugreifen. Dafür können neugierige Zeitgenossen den Server nicht so einfach orten (Stealth-mode). Dies ist die sichere Betriebsart für den produktiven Einsatz. • -refresh on|off Diese Option legt fest ob der Server bei jeder Anfrage nach neuen Projekten suchen soll (Standartwert = off). Bei ausgeschaltetem Refresh ist es möglich beim laufenden Betrieb des Server neue Projekte anzulegen ohne Gefahr zu laufen, dass gleichzeitig Abfragen auf ein halbfertiges Projekt zugreifen. Für den produktiven Einsatz wird vorgeschlagen den Refresh aus- und für Testzwecke einzuschalten. • -help Diese Option gibt alle möglichen Startoptionen auf der Kommandozeile aus. Beim ersten Start eines Servers (oder bei der Angabe einer noch nicht vorhandenen Konfigurationsdatei) müssen Sie (analog zum Konfigurator) zwingend die Optionen «-base» und «-projects» angeben. Andernfalls erhalten Sie einen Hinweis, dass Informationen fehlen und der Server so nicht startbar ist. Auch beim Server ist es so, dass das Basisverzeichnis das Installationsverzeichnis bezeichnet (da wo die readme-Datei und das Startskript zu finden sind) und das Projektverzeichnis das Verzeichnis in dem der Server nach Projektdaten suchen soll. Bei erfolgreichem Start werden diese Angaben und alle anderen Startparameter in einer Datei «xmlizer.server.config» oder bei der Angabe einer Konfigurationsdatei mit dem Namen «xmlizer.server.config.<name>» in Ihrem Home-Verzeichnis abgelegt und bei einem erneuten Start genügt es die Konfigurationsdatei anzugeben, oder auch nichts um mit der Standartkonfigurationsdatei zu arbeiten. Alle anderen, optionalen Parameter werden - falls sie spezifiziert sind - in der verwendeten Konfigurationsdatei für weiter Starts des Servers gespeichert. Es ist also zu einem späteren Zeitpunkt möglich einen einzelnen Parameter zu ändern, der dann für alle weiteren Starts nicht mehr angegeben werden muss. 7.4.2 Anleitung Es können mehrere Server auf verschiedenen Ports betrieben werden, wobei jeder Server ein Projektverzeichnis zugeordnet bekommt (über die Kommandozeile oder die angegebenen Konfigurationsdatei). Es ist auch durchaus möglich mehrere Server mit dem gleichen Projektverzeichnis parallel zu betreiben (bessere Entlastung bei Lastbetrieb). In diesem Falle muss aber der Port geändert werden, da jeder Port immer nur einmal belegt sein darf. Um auf die Daten zuzugreifen kann das Webinterface benutzt werden, oder direkt auf die Daten zugegriffen werden. Wenn Sie direkt auf die Daten zugreifen muss Ihnen jedoch die URL bekannt sein. Als Grundsatz gilt, dass eine URL entweder mit «xmlizer» oder «htmlizer» beginnt, je nach gewünschtem Ausgabenformat. Bei allen Modulen wird der Name des Projektes als Parameter «xmlizerproject» übergeben. Alle intern verwendeten Variabeln beginnen mit «xmlizer». Dies wurde so festgelegt, damit Autor: Thomas Schädler 52 7 Informationen für Anwender die projektbezogenen Parameter möglichst nicht mir den internen kollidieren. Beim Modul «Simple DB Export» wird als zweiter Parameter die gewünschte Datenbank angegeben («xmlizerdb», siehe Abbildung 33). Abbildung 33 : Beispiel zweier URL's für das Modul «Simple DB Export» Beim Modul «Database to XML» können zusätzlich zu der Angabe des Projektnamens noch beliebig viele Parameter angegeben werden. Natürlich werden nur solche Parameter verarbeitet, die bei diesem Projekt auch zur Verfügung stehen. Der Rest wird stillschweigend verworfen. Abbildung 34 zeigt ein Beispiel einer solchen URL. Natürlich ist es auch hier möglich «xmlizer» durch «htmlizer» zu ersetzen. Abbildung 34 : Beispiel einer URL für das Modul «Database to XML» Bei der Verwendung des Webinterfaces müssen Sie sich um den Aufbau der URL keine Gedanken machen. Starten Sie einfach ihren Webbrowser mit dem von Ihnen beim Start des Servers angegebenen Hostnamen und der angegebenen Portnummer. Ist der Verbindungsaufbau erfolgreich werden Sie von der in Abbildung 35 abgebildeten Seite begrüsst (je nach vorhandenen Projekten kann die Ausgabe auch abweichen). Abbildung 35 : Auflistung der Projekte des Servers (index.html) Die Projekte sind verlinkt und führen direkt zu der Detailansicht eines Projektes. In der Detailansicht sind je nach Modul verschiedene Informationen aufgelistet. Beim Module «Simple DB Export» werden Autor: Thomas Schädler 53 7 Informationen für Anwender für jede Datenbank zwei Links angezeigt (einer für die XML- und einer für HTML-Ausgabe). Das Modul «Database to XML» hingegen liefert in der Detailansicht zusätzlich ein Formular mit dem sich die Parameter einfach ändern lassen (siehe Abbildung 36). Abbildung 36 Abbildung 37 Autor: Thomas Schädler : Projektdetails für das Modul «Database to XML» : Beispiel einer HTML-formatierten Ausgabe der XML Daten 54 7 Informationen für Anwender Die Ausgabe von XML im Webbrowser kann je nach verwendetem Browser unterschiedlich ausfallen. Es kann auch vorkommen, dass Fehlermeldungen wegen mangelnder Unterstützung von verschiedenen Zeichensätzen oder Sonderzeichen erscheinen. In diesem Fall ist für die Überprüfung der Ausgabe die HTML-Ausgabe vorzuziehen (siehe Abbildung 37). 7.4.3 Anpassung an Ihre Bedürfnisse Um den Server weiter nutzbar zu machen (nicht nur für die Ausgabe von XML Daten) ist es möglich beliebige HTML-Seiten aufzurufen. Diese müssen sich im Verzeichnis «html» des Servers befinden (oder in beliebigen Unterverzeichnissen dieses Verzeichnisses). Die drei vorhandenen Seiten (index.html, project.html und error.html) sollten nicht gelöscht werden. Es ist aber möglich diese Seiten zu verändern und an Ihre Bedürfnisse anzupassen. Dabei wird folgendes Konzept angewandt. In diesen HTML-Seiten können verschiedenen Platzhalter gesetzt werden, die vor der Auslieferung dieser Seite durch die entsprechenden Funktionen ersetzt werden: • %%date%% : bezeichnet das aktuelle Datum • %%version%% : bezeichnet die Versionsnummer des Servers • %%projects%% : listet alle Projekte auf (verlinkt) • %%details%% : listet die Details eines Projektes auf (der Name des Projektes wird als Parameter mit Namen «xmlizerproject» übergeben) • %%debug%% : zeigt alle übergebenen Parameter als Liste an (Name und Wert) Achten Sie jedoch darauf, diese Platzhalter je mit einem Leerschlag oder einem Zeilenvorschub von allem anderen Text zu trennen, da Sie sonst nicht gefunden werden. Autor: Thomas Schädler 55 8 Schlussfolgerungen 8 Schlussfolgerungen Die in Abschnitt 1.2 gesetzten Ziele wurden erfreulicherweise erreicht. Das im Verlaufe dieser Arbeit entwickelte Vermittlungswerkzeug hat noch einige Eigenheiten, kann aber durchaus produktiv eingesetzt werden. Das Werkzeug kann auch - dank einer Open Source Lizenz - beliebige erweitert werden und ist absolut lizenzfrei verwendbar. Eine entsprechende Website ist seit kurzem online und dort ist auch die aktuellste Version und zusätzlich Information verfügbar [XMLIZER 02]. Als grösstes Problem bei der Implementation stellte sich die leider noch immer mangelhafte Verfügbarkeit von Bibliotheken für die Analyse von XML Schemas heraus. Dies ist aber nicht verwunderlich, da XML Schemas eine sehr junge Technologie darstellen. Die Arbeit mit Java konnte hingegen durchaus überzeugen. Genauere Informationen zu den Erfahrungen bei der Implementation findet sich in Abschnitt 6.4. Aus der in Abschnitt 1.1 erläuterten Problemstellung in Bezug auf das AIDA IDML Schema wurde durch eine Verallgemeinerung ein generisches Werkzeug entwickelt, welches nicht auf ein spezifisches XML Schema zugeschnitten ist. Dies erweitert den Einsatzbereich des Vermittlungswerkzeuges enorm, dafür mussten bei der Implementation durch die erhöhte Komplexität des Themas einige Einschränkungen in Kauf genommen werden. Der ausschlaggebende Punkt dieser Diplomarbeit war jedoch die Entwicklung eines Werkzeuges, das es erleichtert Daten im IDML Format auszutauschen. Um den Kreis zu schliessen soll kurz erläutert werden, wie IDML Daten mit Hilfe des Vermittlungswerkzeug ausgetauscht werden können. Die Datenlieferanten können mit dem Konfigurator ein Mapping erzeugen, welches Ihre Daten aus verschiedenen Datenbanken in das IDML Format konvertiert. Dank der relativ einfachen grafischen Oberfläche können diese Mappingregeln ohne grossen Aufwand und ohne Expertenwissen erstellt werden. Um die Daten nun öffentlich zugänglich zu machen genügt es die daraus resultierende Server-URL den Datennachfragern zukommen zu lassen. Diese können dann manuell oder maschinell die immer aktuell erstellten Daten abfragen. Des weiteren kann durch den Einsatz von verschiedenen Servern, Projekten oder auch nur Parametern (je nach Einsatzgebiet) die Erstellung der Daten für verschiedene Datennachfrager individuell angepasst werden. Autor: Thomas Schädler 56 9 Quellenangaben und Literaturverzeichnis 9 Quellenangaben und Literaturverzeichnis [Abiteboul/Buneman/Suciu 00] Abiteboul Serge, Buneman Peter, Suciu Dan: Data on the Web - From Relations to Semistructured Data and XML, Morgan Kaufmann Publishers, San Francisco 2000. [AIDA 01] Accessible Information on Development Activities (AIDA) available: http://developmentgateway.org/idml/ui.tcl Zugriffsdatum: 21.02.2001 [AIDAAuth 02] AIDA Authority Files available: http://server2.minisisinc.com/ciaflog.htm Zugriffsdatum: 22.2.2002 [Bellanet 00] Exploring the Potential Application of IDML for the Aid Effectivenes Exchange Module of the Global Development Gateway. available: http://www.bellanet.org/ [Borland 02] Borland JBuilder Personal Edition available: http://www.borland.com/jbuilder/personal/index.html Zugriffsdatum: 02.04.2002 [Bourret 02] Ronald Bourret: "Mapping DTDs to Databases", "XML and Databases" und "Mapping W3C Schemas to Object Schemas to Relational Schemas" available: http://www.rpbourret.com/xml/index.htm Zugriffsdatum: 12.01.2002 [Castro 00] Castro, Elizabeth: XML for the World Wide Web: Visual QuickStart Guide. Peachpit Press, Berkeley 2000. [DTD2XS 02] Lumrix XML Tools (XSBrowser und DTD2XS) available: http://puvogel.informatik.med.uni-giessen.de/lumrix/ Zugriffsdatum: 15.05.02 [EDI 01] Electronic Data Interchange Organisation available: http:// www.edi.org/ Zugriffsdatum: 06.10.2001 [EDIAT 01] Electronic Business Austria available: http:// www.edi.at/ Zugriffsdatum: 12.10.2001 Autor: Thomas Schädler 57 9 Quellenangaben und Literaturverzeichnis [Forte 02] Forte for Java Community Edition available: http://wwws.sun.com/software/Developer-products/ffj/ Zugriffsdatum: 02.04.2002 [Java 02] Java Technology Products and APIs available: http://java.sun.com/ Zugriffsdatum: 02.04.2002 [JDOM 02] JDOM Project available: http://www.jdom.org Zugriffsdatum: 02.04.2002 [JVision 02] Object-Insight's JVision available: http://www.object-insight.com/ Zugriffsdatum: 04.05.2002 [Laudon/Laudon 00] Laudon, Kenneth. C, Laudon, Jane P.: Management Information Systems, Prentice Hall, New Jersey 2000. [Goldfarb/Prescot 99] Goldfarb, Charles F., Prescod Paul: XML-Handbuch. Prentice Hall, München 1999. [IDML 01] IDML Initiative Website available: http:// www.idmlinitiative.org/ Zugriffsdatum: 05.10.2001 [IDMLDraft 01] Posting Development Information in IDML Format (Draft) available: http://gateway.arsdigita.com/node/100647/post-it.doc Zugriffsdatum: 08.9.2001 [Marchal 00] Marchal, Benôit: XML by Example, Que Publishing, Indianapolis 2000. [McLaughlin 01] McLaughlin, Brett: XML und Java. O'Reilly Verlag, Köln 2001. [Merz 99] Merz, Michael: Electronic Commerce, dpunkt.verlag, Heidelberg 1999. [Morrison 00] Morrison, Michael, et al.: XML Unleashed, Sams Publishing, Indianapolis 2000. [SCLS 01] SQL Call Level Interface Specification, The Open Group, 1995. available: http://www.opengroup.org/products/publications/catalog/c451.htm Zugriffsdatum: 02.12.2001 Autor: Thomas Schädler 58 9 Quellenangaben und Literaturverzeichnis [UNEDI 01] United Nations Directories for EDIFACT available: http://www.unece.org/trade/untdid/ Zugriffsdatum: 10.10.2001 [UUC 01] The XML FAQ ("Recommended Reading" by W3C). available: http://www.ucc.ie/xml/ - FAQ-VALIDWF Zugriffsdatum: 02.04.2001 [XMLS 01] Working with XML (Tutorial, that covers the basics of XML), Sun XML Solutions Spring 2001. CD-Media Sun Part Number WE276-1. [XMLSPY 01] XMLSpy Version 3.5, Altova GmbH & Altova Inc. (30 Tage Testversion erhältlich). available: http://www.xmlspy.com/ Zugriffsdatum: 12.04.2001 [Vanoirbeek/Aboukhaled 00] Vanoirbeek Christine, Aboukhaled Omar, DOM, SAX Gestion de doc uments XML, Vorlesungsunterlagen der Vorlesung Documents Multimedia an der Universität Fribourg, 2000. [W3CS 01] World Wide Web Consortium, XML Schema Recommendation. available: http://www.w3.org/TR/xmlschema-0/ Zugriffsdatum: 04.05.2001 [W3CD 01] World Wide Web Consortium, Document Object Model. avaliable: http://www.w3.org/DOM/ Zugriffsdatum: 03.05.2001 [XERCES 02] Xerces Java Parser available: http://xml.apache.org/xerces-j/ Zugriffsdatum: 02.04.2002 [XMLIZER 02] <xmlizer> configurator/server website available: http://www.e-freak.ch/xmlizer Zugriffsdatum: 12.08.2002 Autor: Thomas Schädler 59 Anhang A: Quelltext <xmlizer> configurator Anhang A: Quelltext <xmlizer> configurator /* * Start.java * * Usage: configurator.Start [options] * * Options: * -config <name> Use or create a custom xmlizer.config.<name> * -open <filename> Loads a project configuration (must conform to DTD) * -nosplash Switch off splash screen * -help Show this help screen. * * Created on 4. April 2002, 18:59 * ---------------------------------------------------------------------------* This file is part of <xmlizer>. * * <xmlizer> is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Foobar is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with <xmlizer>; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * ---------------------------------------------------------------------------*/ package configurator; /** * Main Class, starts the application and handels command line options * @author [email protected] * @version 0.4 */ public class Start { private static configurator conf; /** Main constructor starts the application and processes command line arguments */ public Start() { super(); } /** * Main Method: generates a new configurator object and calls its constructor * if needed, a project file is opened automatically if specified by the command line * @param argv Command line arguments */ public static void main(java.lang.String [] argv) { String remoteOpen = null; String homebase = null; String projectbase = null; String configfileaddition = null; for (int i=0;i<argv.length ;i++) { String arg = argv[i]; // options if (arg.startsWith("-")) { if (arg.equalsIgnoreCase("-open")) //load a projectconfiguration { remoteOpen = argv[i+1]; } else if (arg.equalsIgnoreCase("-nosplash")) //switch off splashscreen { conf.SPLASH = false ; } else if (arg.equalsIgnoreCase("-config")) //set config file name { configfileaddition = argv[i+1]; } else if (arg.equalsIgnoreCase("-help")) //show command line usage { printUsage(true); System.exit(0); } } } conf = new configurator(configfileaddition); conf.showSplashScreen(); if (projectbase != null && homebase != null) { conf.setHomeBase (homebase); conf.setProjectBase(projectbase); } else { //check here for already exitsting xmlizer.config in the home-directory StringBuffer configfilename = new StringBuffer(System.getProperty("user.home" ) + System.getProperty("file.separator") + "xmlizer.config"); if (configfileaddition != null) { configfilename.append("." + configfileaddition); } java.io.File configfile = new java.io.File(configfilename .toString()); if (!configfile.exists ()) { //warn user for 2 directory promts javax.swing.JOptionPane.showMessageDialog( null, "A 'xmlizer.config' file could not be found in\n" +"your home-directory. You will be prompted twice:\n\n" Autor: Thomas Schädler 60 Anhang A: Quelltext <xmlizer> configurator +"1: for the directory where xmlizer is running. \n" +"2: for the directory where xmlizer will store\n" +" the projects. \n\n" +"HINT: These 2 steps are NOT OPTIONAL.\n" +"The paths will be stored in 'xmlizer.config'\n" +"in your home-dir: "+System .getProperty("user.home"), configurator .APPNAME + " First Run Processing", javax.swing.JOptionPane .WARNING_MESSAGE ); boolean homeSet = conf.setHomeBase(homebase); boolean projectSet = conf.setProjectBase(projectbase); if (!homeSet || !projectSet) { printUsage(true); System.exit(0); } else if (homeSet || projectSet) { //write the xmlizer.config pathData pd = new pathData(); if (homeSet) { pd.setHomeDir(conf.getHomeBase()); } if (projectSet ) { pd.setProjectDir (conf.getProjectBase ()); } //System.out.println(pd.getAsXMLText()); pd.save(configfilename.toString(),true); } } else //read existing file { pathData pd = new pathData(); boolean fileread = pd.readFromFile(configfilename.toString ()); if (pd.isValid()) { conf.setHomeBase(pd.getHomeDir()); conf.setProjectBase (pd.getProjectDir()); } else { printUsage(true); System.exit(0); } } } conf.show(); if (remoteOpen != null) { conf.doRemoteOpen(remoteOpen); } } /** * Prints the usage message (on console) */ private static void printUsage (boolean graphic) { if (!graphic) { System .err.println("Usage: configurator.Start [options]"); System .err.println(); System .err.println("Options:"); System .out.println(" -config <name> Use or create a custom xmlizer.config.<name>" ); System .err.println(" -open <filename> Loads a project configuration (must conform to DTD)"); System .err.println(" -nosplash Switch off splash screen"); System .err.println(" -help Show this help screen."); } else { javax.swing .JOptionPane.showMessageDialog( null, "Usage: configurator.Start [options]" +"\n\nOptions:" +"\n -config <name> Use or create a custom xmlizer.config.<name>" +"\n -open <filename> Loads a project configuration (must conform to DTD)" +"\n -nosplash Switch off splash screen" +"\n -help Show this help screen.", configurator.APPNAME + " usage", javax.swing .JOptionPane.ERROR_MESSAGE ); } } } /* * configurator.java * * + resource bundle configurator/configurator.properties * -> java.util.ResourceBundle.getBundle("configurator/configurator").getString("<key>"); * * Created on 4. April 2002, 15:48 * ---------------------------------------------------------------------------* This file is part of <xmlizer>. * * <xmlizer> is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Foobar is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with <xmlizer>; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * ---------------------------------------------------------------------------*/ package configurator; import java.io.*; import java.awt.*; import javax.swing .*; Autor: Thomas Schädler 61 Anhang A: Quelltext <xmlizer> configurator import import import import import import java.lang.*; java.lang.reflect.*; java.util.*; org.jdom.*; org.jdom.output.XMLOutputter; org.jdom.input.SAXBuilder; /** * Class configurator represents the main window * @author [email protected] */ public class configurator extends JFrame { /** The apps name */ public static String APPNAME = "<xmlizer> configurator" ; /** The apps version */ public static String VERSION = "0.9.0"; /** The DTD for the project-files <CODE>xmlizer.project.config.dtd</CODE> */ public static String XMLPROJECTFILEDTD = "xmlizer.project.config.dtd"; /** The name of the root node in the DTD <CODE>xmlizerprojectconfig</CODE> */ public static String XMLPROJECTFILEROOT = "xmlizerprojectconfig"; /** Show the splashscreen or not */ public static boolean SPLASH = true; /** A Helper class <CODE>UniqueID</CODE> generates unique IDs. */ public static UniqueID uniqueID; //The ThreadPool to do the UIThreads and other time consuming methods with //To use the pool just add a Runnable to the pool [pool.execute(someRunnable)] private ThreadPool pool = new ThreadPool (5); private splashWindow sw; private String configname; public boolean mappingState = false ; //CONSTRUCTOR //----------------------------------------------------------------------------------------------/** Creates a new configurator */ public configurator (String configname) { uniqueID = new UniqueID(); this.configname = configname; initComponents(); getMainDesktopPane().setDragMode(JDesktopPane.OUTLINE_DRAG_MODE); Log = new logWindow(this,uniqueID.get()); Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); setWindowTitle(null); //set the name of the app initWindowManager(); //inits the stuff to manage the windows //center the window on the screen on startup Dimension confSize = getSize(); if(confSize.height > screenSize .height) {confSize.height = screenSize.height ;} if(confSize.width > screenSize.width ) {confSize.width = screenSize.width;} setLocation((screenSize.width - confSize.width )/2,(screenSize .height - confSize.height )/2); setLogWindow2StandartLocation(); getMainDesktopPane().add(Log); //show(); //show the whole thing } /** This method is called from within the constructor to * initialize the form. * WARNING: Do NOT modify this code. The content of this method is * always regenerated by the Form Editor. */ private void initComponents()//GEN-BEGIN:initComponents { menuBar = new javax.swing.JMenuBar(); projectMenu = new javax.swing.JMenu(); newMenuItem = new javax.swing.JMenuItem(); jSeparator1 = new javax.swing.JSeparator(); openMenuItem = new javax.swing.JMenuItem(); closeMenuItem = new javax.swing .JMenuItem (); saveMenuItem = new javax.swing.JMenuItem(); saveAsMenuItem = new javax .swing.JMenuItem(); jSeparator4 = new javax.swing.JSeparator(); optionsMenuItem = new javax.swing.JMenuItem(); jSeparator2 = new javax.swing.JSeparator(); exitMenuItem = new javax.swing.JMenuItem(); uiMenu = new javax.swing.JMenu(); UIManager.LookAndFeelInfo[] lf = UIManager.getInstalledLookAndFeels(); for(int i=0;i<lf.length;i++) { String name = lf[i].getName(); String classname = lf[i].getClassName (); JMenuItem mitem = new JMenuItem(name); mitem.addActionListener(new LookAndFeelAction(this,classname)); uiMenu .add(mitem ); } windowMenu = new javax.swing.JMenu(); helpMenu = new javax .swing .JMenu(); contentMenuItem = new javax.swing.JMenuItem(); javadocMenuItem = new javax.swing.JMenuItem(); infoMenuItem = new javax.swing.JMenuItem(); jSeparator3 = new javax.swing.JSeparator(); aboutMenuItem = new javax.swing .JMenuItem (); mainToolBar = new javax.swing.JToolBar(); newButton = new javax.swing.JButton(); openButton = new javax.swing.JButton(); closeButton = new javax.swing.JButton(); saveButton = new javax.swing.JButton(); saveasButton = new javax.swing.JButton(); optionsButton = new javax.swing .JButton(); logButton = new javax.swing.JButton(); Autor: Thomas Schädler 62 Anhang A: Quelltext <xmlizer> configurator infoButton = new javax.swing.JButton(); aboutButton = new javax.swing.JButton(); javadocButton = new javax.swing .JButton(); helpButton = new javax.swing.JButton(); desktopScrollPane = new javax.swing.JScrollPane(); mainDesktopPane = new javax.swing.JDesktopPane (); projectMenu.setText("Project"); newMenuItem.setText(java.util.ResourceBundle.getBundle("configurator/configurator").getString("Menu_Entry_New")); newMenuItem.setIcon(new javax.swing.ImageIcon(getClass().getResource("/configurator/icons/New16.gif"))); newMenuItem.addActio nListener(new java.awt.event.ActionListener() { public void actionPerformed (java.awt.event .ActionEvent evt) { newMenuItemActionPerformed(evt); } }); projectMenu.add(newMenuItem); projectMenu.add(jSeparator1); openMenuItem.setText(java.util.ResourceBundle.getBundle("configurator/configurator").getString("Menu_Entry_Open" )); openMenuItem.setIcon(new javax.swing .ImageIcon (getClass().getResource("/configurator/icons/Open16.gif" ))); openMenuItem.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed (java.awt.event .ActionEvent evt) { openMenuItemActionPerformed(evt); } }); projectMenu.add(openMenuItem); closeMenuItem.setText(java.util.ResourceBundle .getBundle ("configurator/configurator").getString("Menu_Entry_Close")); closeMenuItem.setIcon(new javax .swing.ImageIcon(getClass().getResource("/configurator/icons/Close16.gif"))); closeMenuItem.setEnabled(false); closeMenuItem.addActionListener (new java.awt.event.ActionListener() { public void actionPerformed (java.awt.event .ActionEvent evt) { closeMenuItemActionPerformed (evt); } }); projectMenu.add(closeMenuItem); saveMenuItem.setText(java.util.ResourceBundle.getBundle("configurator/configurator").getString("Menu_Entry_Save")); saveMenuItem.setIcon(new javax.swing .ImageIcon (getClass().getResource("/configurator/icons/Save16.gif" ))); saveMenuItem.setEnabled(false); saveMenuItem.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed (java.awt.event .ActionEvent evt) { saveMenuItemActionPerformed(evt); } }); projectMenu.add(saveMenuItem); saveAsMenuItem .setText(java.util.ResourceBundle.getBundle("configurator/configurator" ).getString("Menu_Entry_SaveAs" )); saveAsMenuItem.setIcon(new javax.swing.ImageIcon(getClass().getResource ("/configurator/icons/SaveAs16.gif"))); saveAsMenuItem.setEnabled(false ); saveAsMenuItem.addActionListener(new java.awt.event .ActionListener () { public void actionPerformed (java.awt.event .ActionEvent evt) { saveAsMenuItemActionPerformed(evt); } }); projectMenu.add(saveAsMenuItem); projectMenu.add(jSeparator4); optionsMenuItem .setToolTipText("Show and Edit the Project Options" ); optionsMenuItem .setText(java.util.ResourceBundle.getBundle("configurator/configurator" ).getString("Menu_Entry_Prefs")); optionsMenuItem .setIcon(new javax.swing.ImageIcon(getClass().getResource("/configurator/icons/Preferences16.gif" ))); optionsMenuItem .setEnabled (false); optionsMenuItem .addActionListener(new java.awt.event.ActionListener() { public void actionPerformed (java.awt.event .ActionEvent evt) { optionsMenuItemActionPerformed(evt); } }); projectMenu.add(optionsMenuItem ); projectMenu.add(jSeparator2); exitMenuItem.setText(java.util.ResourceBundle.getBundle("configurator/configurator").getString("Menu_Entry_Exit" )); exitMenuItem.setIcon(new javax.swing .ImageIcon ("")); exitMenuItem.addActionListener(new java.awt.event.Action Listener() { public void actionPerformed (java.awt.event .ActionEvent evt) { exitMenuItemActionPerformed(evt); } }); projectMenu.add(exitMenuItem); menuBar.add(projectMenu); uiMenu.setText("Look&Feel" ); menuBar.add(uiMenu); windowMenu .setText("View"); menuBar.add(windowMenu); helpMenu.setText("Help"); contentMenuItem .setText(java.util.ResourceBundle.getBundle("configurator/configurator" ).getString("Menu_Entry_Contents")); contentMenuItem .setIcon(new javax.swing.ImageIcon(getClass().getResource("/configurator/icons/Help16.gif"))); contentMenuItem .addActionListener(new java.awt.event.ActionListener() Autor: Thomas Schädler 63 Anhang A: Quelltext <xmlizer> configurator { public void actionPerformed (java.awt.event .ActionEvent evt) { contentMenuItemActionPerformed(evt); } }); helpMenu.add(contentMenuItem); javadocMenuItem.setText(java.util.ResourceBundle .getBundle ("configurator/configurator").getString("Menu_Entry_JavaDoc")); javadocMenuItem .setIcon(new javax.swing.ImageIcon(getClass().getResource("/configurator/icons/WebComponent16.gif"))); javadocMenuItem .addActionListener(new java.awt.event.ActionListener() { public void actionPerformed (java.awt.event .ActionEvent evt) { javadocMenuItemActionPerformed(evt); } }); helpMenu.add(javadocMenuIt em); infoMenuItem .setText(java.util.ResourceBundle.getBundle("configurator/configurator" ).getString("Menu_Entry_SysInfo")); infoMenuItem.setIcon(new javax.swing .ImageIcon (getClass().getResource("/configurator/icons/Information16.gif"))); infoMenuItem.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed (java.awt.event .ActionEvent evt) { infoMenuItemActionPerformed(evt); } }); helpMenu.add(infoMenuItem); helpMenu.add(jSeparator3); aboutMenuItem.setText(java.util.ResourceBundle .getBundle ("configurator/configurator").getString("Menu_Entry_About")); aboutMenuItem.setIcon(new javax .swing.ImageIcon(getClass().getResource("/configurator/icons/About16.gif"))); aboutMenuItem.addActionListener (new java.awt.event.ActionListener() { public void actionPerformed (java.awt.event .ActionEvent evt) { aboutMenuIte mActionPerformed (evt); } }); helpMenu.add(aboutMenuItem ); menuBar.add(helpMenu ); setDefaultCloseOperation(javax.swing .WindowConstants.DO_NOTHING_ON_CLOSE); setName("xmlizer configurator"); addWindowListener(new java.awt.event .WindowAdapter() { public void windowClosing(java.awt.event.WindowEvent evt) { exitForm(evt); } }); mainToolBar.setToolTipText("Project Toolbar"); newButton.setIcon(new javax.swing.ImageIcon(getClass().getResource ("/configurator/icons/New24.gif"))); newButton.setToolTipText("Create a new project..."); newButton.addActionListener(new java.awt.event .ActionListener () { public void actionPerformed (java.awt.event .ActionEvent evt) { newButtonActionPerformed(evt); } }); mainToolBar.add(newButton); mainToolBar.addSeparator(); openButton .setIcon(new javax.swing.ImageIcon(getClass().getResource("/configurator/icons/Open24.gif"))); openButton .setToolTipText("Open an existing project..."); openButton .addActionListener(new java.awt.event.ActionListener() { public void actionPerformed (java.awt.event .ActionEvent evt) { openButtonActionPerformed(evt); } }); mainToolBar.add(openButton ); closeButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/configurator/icons/Close24.gif" ))); closeButton.setToolTipText ("Close this project"); closeButton.setEnabled(false); closeButton.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed (java.awt.event .ActionEvent evt) { closeButtonActionPerformed(evt); } }); mainToolBar.add(closeButton); saveButton .setIcon(new javax.swing.ImageIcon(getClass().getResource("/configurator/icons/Save24.gif"))); saveButton .setToolTipText("Save this project at current state"); saveButton .setEnabled(false); saveButton .addActionListener(new java.awt.event.ActionListener() { public void actionPerformed (java.awt.event .ActionEvent evt) { saveButtonActionPerformed(evt); } }); Autor: Thomas Schädler 64 Anhang A: Quelltext <xmlizer> configurator mainToolBar.add(saveButton ); saveasButton.setIcon(new javax.swing .ImageIcon (getClass().getResource("/configurator/icons/SaveAs24.gif"))); saveasButton.setToolTipText("Save this project with with another name..."); saveasButton.setEnabled(false); saveasButton.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed (java.awt.event .ActionEvent evt) { saveasButtonActionPerformed(evt); } }); mainToolBar.add(saveasButton); mainToolBar.addSeparator(); optionsButton.setIcon(new javax .swing.ImageIcon(getClass ().getResource("/configurator/icons/Preferences24.gif"))); optionsButton.setToolTipText("Opens the Setup Editor"); optionsButton.setEnabled(false); optionsButton.addActionListener (new java.awt.event.ActionListener() { public void actionPerformed (java.awt.event .ActionEvent evt) { optionsButtonActionPerformed (evt); } }); mainToolBar.add(optionsButton); logButton.setIcon(new javax.swing.ImageIcon(getClass().getResource ("/configurator/icons/History24.gif" ))); logButton.setToolTipText("Toggle the log window"); logButton.addActionListener(new java.awt.event .ActionListener () { public void actionPerformed (java.awt.event .ActionEvent evt) { logButtonActionPerformed(evt); } }); mainToolBar.add(logButton); mainToolBar.addSeparator(); infoButton .setIcon(new javax.swing.ImageIcon(getClass().getResource("/configurator/icons/Information24.gif" ))); infoButton .setToolTipText("Show system information..."); infoButton .addActionListener(new java.awt.event.ActionListener() { public void actionPerformed (java.awt.event .ActionEvent evt) { infoButtonActionPerformed(evt); } }); mainToolBar.add(infoButton ); aboutButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/configurator/icons/About24.gif" ))); aboutButton.setToolTipText ("Show application information..."); aboutButton.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed (java.awt.event .ActionEvent evt) { aboutButtonActionPerformed(evt); } }); mainToolBar.add(aboutButton); javadocButton.setIcon(new javax .swing.ImageIcon(getClass ().getResource("/configurator/icons/WebComponent24.gif"))); javadocButton.setToolTipText("Open the JavaDoc Browser"); javadocButton.addActionListener (new java.awt.event.ActionListener() { public void actionPerformed (java.awt.event .ActionEvent evt) { javadocButtonActionPerformed (evt); } }); mainToolBar.add(javadocButton); mainToolBar.addSeparator(); helpButton .setIcon(new javax.swing.ImageIcon(getClass().getResource("/configurator/icons/Help24.gif"))); helpButton .setToolTipText("Open the help browser..."); helpButton .addActionListener(new java.awt.event.ActionListener() { public void actionPerformed (java.awt.event .ActionEvent evt) { helpButtonActionPerformed(evt); } }); mainToolBar.add(helpButton ); getContentPane().add(mainToolBar, java.awt.BorderLayout.NORTH ); getContentPane().add(desktopScrollPane, java.awt.BorderLayout .CENTER); mainDesktopPane .setPreferredSize(new java.awt.Dimension(800, 550)); getContentPane().add(mainDesktopPane , java.awt.BorderLayout.CENTER ); setJMenuBar(menuBar); pack(); }//GEN-END:initComponents private void logButtonActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_logButtonActionPerformed {//GEN-HEADEREND:event_logButtonActionPerformed Autor: Thomas Schädler 65 Anhang A: Quelltext <xmlizer> configurator // Add your handling code here: if (getLog ().isVisible()) { getLog ().setVisible(false); } else { getLog ().show(); } JInternalFrame LogIF = (JInternalFrame)getLog(); try { LogIF.setSelected(true); } catch(Exception e) { System .out.println(e.getLocalizedMessage()); } if (LogIF.isIcon()) { getMainDesktopPane().getDesktopManager().deiconifyFrame(LogIF); } getLog().update (this); }//GEN-LAST:event_logButtonActionPerformed private void optionsMenuItemActionPerformed(java.awt.event.ActionEvent evt)//GEN FIRST:event_optionsMenuItemActionPerformed {//GEN-HEADEREND:event_optionsMenuItemActionPerformed // Add your handling code here: if (data != null) { doOptions(); } }//GEN-LAST:event_optionsMenuItemActionPerformed private void optionsButtonActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_optionsButtonActionPerformed {//GEN-HEADEREND:event_optionsButtonActionPerformed // Add your handling code here: if (data != null) { doOptions(); } }//GEN-LAST:event_optionsButtonActionPerformed private void javadocButtonActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_javadocButtonActionPerformed {//GEN-HEADEREND:event_javadocButtonActionPerformed // Add your handling code here: doJavaDoc(); }//GEN-LAST:event_javadocButtonActionPerformed private void javadocMenuItemActionPerformed(java.awt.event.ActionEvent evt)//GEN FIRST:event_javadocMenuItemActionPerformed {//GEN-HEADEREND:event_javadocMenuItemActionPerformed // Add your handling code here: doJavaDoc(); }//GEN-LAST:event_javadocMenuItemActionPerformed private void closeButtonActionPerformed(java.awt.event.ActionEvent evt )//GEN-FIRST:event_closeButtonActionPerformed {//GEN-HEADEREND:event_closeButtonActionPerformed // Add your handling code here: doClose(); }//GEN-LAST:event_closeButtonActionPerformed private void saveAsMenuItemActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_saveAsMenuItemActionPerformed {//GEN-HEADEREND:event_saveAsMenuItemActionPerformed // Add your handling code here: doSaveAs(); }//GEN-LAST:event_saveAsMenuItemActionPerformed private void openMenuItemActionPerformed (java.awt.event .ActionEvent evt)//GEN-FIRST:event_openMenuItemActionPerformed {//GEN-HEADEREND:event_openMenuItemActionPerformed // Add your handling code here: doOpen(); }//GEN-LAST:event_openMenuItemActionPerformed private void newMenuItemActionPerformed(java.awt.event.ActionEvent evt )//GEN-FIRST:event_newMenuItemActionPerformed {//GEN-HEADEREND:event_newMenuItemActionPerformed // Add your handling code here: doNew(); }//GEN-LAST:event_newMenuItemActionPerformed private void contentMenuItemActionPerformed(java.awt.event.ActionEvent evt)//GEN FIRST:event_contentMenuItemActionPerformed {//GEN-HEADEREND:event_contentMenuItemActionPerformed // Add you r handling code here: doHelp(); }//GEN-LAST:event_contentMenuItemActionPerformed private void helpButtonActionPerformed(java.awt.event.ActionEvent evt)//GEN -FIRST:event_helpButtonActionPerformed {//GEN-HEADEREND:event_helpButtonActionPerformed // Add your handling code here: doHelp(); }//GEN-LAST:event_helpButtonActionPerformed private void infoButtonActionPerformed(java.awt.event.ActionEvent evt)//GEN -FIRST:event_infoButtonActionPerformed {//GEN-HEADEREND:event_infoButtonActionPerformed // Add your handling code here: doInfo(); }//GEN-LAST:event_infoButtonActionPerformed private void aboutButtonActionPerformed(java.awt.event.ActionEvent evt )//GEN-FIRST:event_aboutButtonActionPerformed {//GEN-HEADEREND:event_aboutButtonActionPerformed // Add your handling code here: doAbout(); }//GEN-LAST:event_aboutButtonActionPerformed private void saveasButtonActionPerformed (java.awt.event .ActionEvent evt)//GEN-FIRST:event_saveasButtonActionPerformed {//GEN-HEADEREND:event_saveasButtonActionPerformed // Add your handling code here: doSaveAs(); }//GEN-LAST:event_saveasButtonActionPerformed Autor: Thomas Schädler 66 Anhang A: Quelltext <xmlizer> configurator private void openButtonActionPerfor med(java.awt.event.ActionEvent evt)//GEN -FIRST:event_openButtonActionPerformed {//GEN-HEADEREND:event_openButtonActionPerformed // Add your handling code here: doOpen(); }//GEN-LAST:event_openButtonActionPerformed private void newButtonActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_newButtonActionPerformed {//GEN-HEADEREND:event_newButtonActionPerformed // Add your handling code here: doNew(); }//GEN-LAST:event_newButtonActionPerform ed private void saveButtonActionPerformed(java.awt.event.ActionEvent evt)//GEN -FIRST:event_saveButtonActionPerformed {//GEN-HEADEREND:event_saveButtonActionPerformed // Add your handling code here: doSave(); }//GEN-LAST:event_saveButtonActionPerformed private void infoMenuItemActionPerformed (java.awt.event .ActionEvent evt) {//GEN-FIRST:event_infoMenuItemActionPerformed // Add your handling code here: doInfo(); }//GEN-LAST:event_infoMenuItemActionPerformed private void aboutMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN -FIRST:event_aboutMenuItemActionPerformed // Add your handling code here: doAbout(); }//GEN-LAST:event_aboutMenuItemActionPerformed private void saveMenuItemActionPerformed (java.awt.event .ActionEvent evt) {//GEN-FIRST:event_saveMenuItemActionPerformed // Add your handling code here: doSave(); }//GEN-LAST:event_saveMenuItemActionPerformed private void closeMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN -FIRST:event_closeMenuItemActionPerformed // Add your handling code here: doClose(); }//GEN-LAST:event_closeMenuItemActionPerformed private void exitMenuItemActio nPerformed (java.awt.event .ActionEvent evt) {//GEN-FIRST:event_exitMenuItemActionPerformed // Add your handling code here: doExit(); }//GEN-LAST:event_exitMenuItemActionPerformed /** Exit the Application */ private void exitForm(java.awt.event.WindowEvent evt) {//GEN -FIRST:event_exitForm // Add your handling code here: doExit(); }//GEN-LAST:event_exitForm // Variables declaration - do not modify//GEN -BEGIN:variables private javax.swing .JMenuBar menuBar; private javax.swing .JMenu projectMenu; private javax.swing .JMenuItem newMenuItem; private javax.swing .JSeparator jSeparator1; private javax.swing .JMenuItem openMenuItem; private javax.swing .JMenuItem closeMenuItem; private javax.swing .JMenuItem saveMenuItem; private javax.swing .JMenuItem saveAsMenuItem; private javax.swing .JSeparator jSeparator4; private javax.swing .JMenuItem optionsMenuItem ; private javax.swing .JSeparator jSeparator2; private javax.swing.JMenuItem exitMenuItem; private javax.swing .JMenu uiMenu; private javax.swing .JMenu windowMenu; private javax.swing .JMenu helpMenu; private javax.swing .JMenuItem contentMenuItem ; private javax.swing .JMenuItem javadocMenuItem ; private javax.swing .JMenuItem infoMenuItem; private javax.swing .JSeparator jSeparator3; private javax.swing .JMenuItem aboutMenuItem; private javax.swing .JToolBar mainToolBar ; private javax.swing .JButton newButton; private javax.swing .JButton openButton; private javax.swing .JButton closeButton; private javax.swing .JButton saveButton; private javax.swing .JButton saveasButton ; private javax.swing .JButton optionsButton; private javax.swing .JButton logButton; private javax.swing .JButton infoButton; private javax.swing .JButton aboutButton; private javax.swing .JButton javadocButton; private javax.swing .JButton helpButton; private javax.swing .JScrollPane desktopScrollPane; private javax.swing .JDesktopPane mainDesktopPane; // End of variables declaration//GEN-END:variables //UI RELATED STUFF //----------------------------------------------------------------------------------------------/** * Places the logwindow smart on the screen (half hight and full width) */ public void setLogWindow2StandartLocation() { //set the log initially to a good location and size Dimension paneSize = getMainDesktopPane().getSize(); Log.setSize(paneSize .width ,(paneSize.height/2)); Log.setLocation (0,paneSize .height-Log.getHeight()); } /** * Returns the mainDesktopPane (usefull for adding components etc.) * @return JDesktopPane of the main window to add JInternalFrames (all sub-windows) */ public JDesktopPane getMainDesktopPane() { Autor: Thomas Schädler 67 Anhang A: Quelltext <xmlizer> configurator return mainDesktopPane; } /** * Set the current open project name in the mainwindow-titelbar or only the name if there are no open projects * * @param text The name of the open project */ public void setWindowTitle(String text) { if (text == null || text == new String()) { getLog ().addDebug("SET WindowTITLE: " + APPNAME); if (this.configname != null) { setTitle(APPNAME + " [ configuration: " + this.configname + " ] "); } else { setTitle(APPNAME); } } else { getLog ().addDebug("SET WindowTITLE: " + APPNAME + " -> " + text); if (this.configname != null) { setTitle(APPNAME + " [ configuration: " + this.configname + " ] " + " -> " + text); } else { setTitle(APPNAME + " -> " + text); } } } /** * Returns the windowmenu (of the open windows) to switch em through the menu * @return JMenu containing all open sub -windows (JInternalFrames) */ public JMenu getWindowMenu() { return windowMenu; } //USER RESPOND METHODS [ doXXX() ] //----------------------------------------------------------------------------------------------/** * Starts a new project */ private void doNew() { //start a new project and a setup window Runnable r = new Runnable() { public void run() { makeNewProjectData (); open("setup"); } }; try { pool.execute(r); }catch(InterruptedException ie) { getLog().addError(ie);} } /** * Starts the options-browser (Tree) */ private void doOptions() { Runnable r = new Runnable() { public void run() { //open the setup window //start a new project and a setup window open("setup"); } }; try { pool.execute(r); }catch(InterruptedException ie) { getLog().addError(ie);} } /** * Starts the help -browser (Swing HTML) */ private void doHelp () { Runnable r = new Runnable() { public void run() { //open the help-browser (Swing HTML) //start a new project and a setup window helpWindow help = (helpWindow)open("help"); help.loadPage("/configurator/help/index.html"); } }; try { pool.execute(r); }catch(InterruptedException ie) { getLog().addError(ie);} } /** * Starts the javadoc-browser (Swing HTML) */ private void doJavaDoc() { Runnable r = new Runnable() { public void run() { //open the browser with javadoc javadocWindow javadoc = (javadocWindow )open("javadoc" ); javadoc.loadPage("/configurator/javadoc/index.html"); } }; try { pool.execute(r); }catch(InterruptedException ie) { getLog().addError(ie);} } Autor: Thomas Schädler 68 Anhang A: Quelltext <xmlizer> configurator /** * The path to the homedirectory */ private String projectbase = null; /** * Set the path to the homedirectory */ public boolean setProjectBase(String prodir) { if(prodir == null) //ask for projectbase { projectbase = showDirectoryChooser("<xmlizer>-Project Directory"); if (projectbase != null) { return true; } else { return false ; } } else { projectbase = prodir; return true; } } /** * Get the path to the homedirectory */ public String getProjectBase() { return projectbase; } /** * The path to the homedirectory */ private String homebase = null; /** * Set the path to the homedirectory */ public boolean setHomeBase(String homedir) { if(homedir == null) //ask for homebase { homebase = showDirectoryChooser("<xmlizer> -Home directory"); if (homebase != null) { return true; } else { return false ; } } else { homebase = homedir; return true; } } /** * Get the path to the homedirectory */ public String getHomeBase() { return homebase ; } private String showDirectoryChooser (String Title) { JFileChooser chooser = new JFileChooser(); chooser.setCurrentDirectory(new java.io.File(".")); chooser.setDialogTitle(Title); chooser.setFileSelectionMode(JFileChooser .DIRECTORIES_ONLY); int returnVal = chooser.showOpenDialog(this); if(returnVal == JFileChooser.APPROVE_OPTION) { //System.out.println("getCurrentDirectory(): " + chooser.getCurrentDirectory()); //System.out.println("getSelectedFile() : " + chooser.getSelectedFile()); return chooser.getSelectedFile().toString(); } else return null; } /** * Opens a project - loads a projectdata.xml file and starts with the selected Module * <CODE> * related FILE: some/dir/my.projectdata.file.i.saved.5.minutes.ago.xml * related FILE: some/dir/xmlizer.project.config.dtd * </CODE> * @param filename The filename as String */ public void doRemoteOpen (String filename ) { final String the_filename = filename ; makeNewProjectData(); Runnable r = new Runnable() { public void run() { boolean readSuccessfull = getProjectData().readFromFile(the_filename ,getLog()); if (readSuccessfull)//if all was successful, start the project workspace { boolean startupOK = startupProjectWorkspace(); if(startupOK) { getProjectData().save(); //clean the new data (not dirty, because we just read it) //if that was successful, do the rest setWindowTitle((String)((dataItem)getProjectData().getInitialByKey("name")).getValue()); getLog().addInformation("Open operation successful: loaded project data."); showProjectLoadedMessage( Autor: Thomas Schädler 69 Anhang A: Quelltext <xmlizer> configurator "Project\n\n[" + ((dataItem)getProjectData().getInitialByKey ("name")).getValue() + "]\n\n" + "using Module \n\n[" + ((dataItem)getProjectData().getInitialByKey("module" )).getValue() + "]\n\n" + "loaded successfully." ); } } else { nullifyProjectData(); getLog().addWarning ("Opening Project failed - resetting UI to default."); } } }; try { pool.execute(r); }catch(InterruptedException ie) { getLog().addError(ie);} } /** * Opens a project - jfilechooser to load a projectdata.xml file and starts with the selec ted Module * * FILE: some/dir/my.projectdata.file.i.saved.5.minutes.ago.xml * FILE: some/dir/xmlizer.project.config.dtd * */ private void doOpen () { if (data != null) { getLog ().addWarning("There is already an open project. Save or close the current project first."); return ; } else { //check for already open project and // -> open a new project // -> or close current project and then open an existing project makeNewProjectData(); JFileChooser chooser = new JFileChooser(); String pbase = getProjectBase(); if (pbase != null) { chooser.setCurrentDirectory(new File(getProjectBase())); } chooser.setDialogType(JFileChooser.OPEN_DIALOG); simpleFileFilter filter = new simpleFileFilter(); filter .addExtension("xml"); filter .setDescription("XML Only"); chooser.setFileFilter(filter); final int returnVal = chooser.showOpenDialog(this); if(returnVal == JFileChooser.APPROVE_OPTION) { final String chooserSelectedFilePath = chooser.getSelectedFile().getPath(); Runnable r = new Runnable() { public void run() { boolean readSuccessfull = getProjectData ().readFromFile (chooserSelectedFilePath,getLog ()); if (readSuccessfull)//if all was successful, start the project workspace { getProjectData().save(); //clean the new data (not dirty, because we just read it) //start the project workspace boolean startupOK = startupProjectWorkspace(); if (startupOK) { //if that was successful, do the rest setWindowTit le((String )((dataItem)getProjectData().getInitialByKey("name" )).getValue()); getLog().addInformation("Open operation successful: loaded project data." ); showProjectLoadedMessage( "Project\n\n[" + ((dataItem )getProjectData ().getInitialByKey("name")).getValue () + "]\n\n" + "using Module\n\n[" + ((dataItem)getProjectData().getInitialByKey("module")).getValue() + "]\n\n" + "loaded successfully." ); } } else { nullifyProjectData(); getLog ().addWarning("Opening Project failed - resetting UI to default."); } } }; try { pool.execute(r); }catch(InterruptedException ie) { getLog().addError(ie);} } else { nullifyProjectData (); getLog().addInformation ("Open Project cancelled."); } } } /** * Saves the current project */ private synchronized void doSave() { String location = new String(); //save the data if dirty if (getProjectData().isDirty()) { //save project getProjectData().save(); } location = getProjectBase() + getProjectData().getSaveLocation(); final String thelocation = location; Autor: Thomas Schädler 70 Anhang A: Quelltext <xmlizer> configurator Runnable r = new Runnable() { public void run() { //get the doc, xmlize it and save it under current location if (!thelocation.equals (new String())) { //save the stuff there Document xmldata = getProjectData().getAsXMLDocumentJDOM(); XMLOutputter fmt = new XMLOutputter(" ",true); try { //file stuff getLog().addDebug("Encoding used for save: " + System.getProperty ("file.encoding" )); File outputFile = new File(thelocation+configurator.getFileSeparator()+"xmlizer.xml"); File path = new File(thelocation); if (!path.exists()) { path.mkdirs (); } copyProjectDTD(path.toString()); FileOutputStream outputStream = new FileOutputStream(outputFile); OutputStreamWriter out = new OutputStreamWriter(outputStream ,"UTF8"); fmt.output (xmldata,out); out.close(); } catch (IOException ex) { JOptionPane.showMessageDialog( getContentPane(), "I/O Error, could not save the \ndata correctly!" + "\n ERROR:\n------ \n" + ex.toString(), APPNAME + " save error", JOptionPane.ERROR_MESSAGE ); getProjectData().setDirty (); //not saved, so mark it getLog().addError(ex); return; } } else { //aborted getProjectData ().setDirty(); //not saved, so mark it getLog().addError("Project save error, empty filename provided!" ); return; } getLog().addInformation ("Project successfully saved: " + thelocation + "xmlizer.xml" ); } }; try { pool.execute(r); }catch(InterruptedException ie) { getLog().addError(ie);} } /** * Saves the current project under a new name/file */ private void doSaveAs() { String location = new String(); //show name chooser box String new_name = null; boolean aborted = false; while(new_name == null && !aborted) { String selected = JOptionPane.showInputDialog("Please enter a new directory name:" ); if (selected == null) { aborted = true; } else { if(configurator.isValidPath(selected)) { new_name = selected ; } } } if (!aborted) { //change the initial("name") and save it String old_one = getProjectData().getSaveLocation(); getProjectData().setSaveLocation (new_name); //save the data if dirty if (getProjectData().isDirty()) { //save project getProjectData().save(); } final String old_one_f = old_one; final String new_one_f = new_name; final String thelocation = getProjectBase() + getProjectData().getSaveLocation(); Runnable r = new Runnable() { public void run() { if (!thelocation.equals(new String ())) { //save the stuff there Document xmldata = getProjectData().getAsXMLDocumentJDOM(); XMLOutputter fmt = new XMLOutputter (" ",true); try { //file stuff getLog ().addDebug("Encoding used for save: " + System.getProperty("file.encoding")); File outputFile = new File(thelocation + configurator.getFileSeparator() + "xmlizer.xml"); File path = new File(thelocation); if (!path.exists ()) { path.mkdirs(); } copyProjectDTD(path.toString()); copyXMLFiles(new_one_f,old_one_f); FileOutputStream outputStream = new FileOutputStream(outputFile); OutputStreamWriter out = new OutputStreamWriter(outputStream,"UTF8"); Autor: Thomas Schädler 71 Anhang A: Quelltext <xmlizer> configurator fmt.output(xmldata,out); out.close(); } catch (IOException ex) { JOptionPane .showMessageDialog( getContentPane(), "I/O Error, could not save the\ndata correctly!" + "\n ERROR:\n------\n" + ex.toString(), APPNAME + " save error", JOptionPane .ERROR_MESSAGE ); getProjectData().setDirty(); //not saved, so mark it getLog ().addError(ex); return ; } } else { //aborted getProjectData().setDirty (); //not saved, so mark it getLog().addError("Project save error, empty filename given!"); return; } //getProjectData().setSaveLocation(thelocation); getLog().addInformation("Project successfully saved: " + thelocation + "xmlizer.xml"); } }; try { pool.execute(r); }catch(InterruptedException ie) { getLog().addError(ie);} } } /** * Closes the current project and returns to startup state of the application */ private void doClose() //OK { if (data == null) //no data to save, just reset { //reset to default startup state resetToDefault(); //reset the WindowManager } else if (!getProjectData().isDirty()) //data has not changed { resetToDefault(); } else if (getProjectData().isDirty()) //data has changed { //ask for discard (ok) or cancel (cancel) int result = JOptionPane.showConfirmDialog ( getContentPane(), "Current Project is not saved!\nDiscard this project?", "<xmlizer> project close", JOptionPane .OK_CANCEL_OPTION, JOptionPane .WARNING_MESSAGE ); if (result == JOptionPane.OK_OPT ION) //discard { //reset to default startup state resetToDefault(); //reset the WindowManager setWindowTitle(null); } else //set status and return { getLog().addWarning("Close aborted: Current Project is not saved! (Use Menu: Project ->Save)"); return; } } } /** * Shows the about dialog */ private void doAbout() //OK { JOptionPane.showMessageDialog( getContentPane(), APPNAME + " ver. " + VERSION + "\n\n-----\nThis software is open source (GPL).\nAbsolutely no warranty at all.\nUse at own risk.\n-----\n\nby [email protected]\nfor University of Fribourg\n", "About " + APPNAME, JOptionPane.INFORMATION_MESSAGE , new javax.swing .ImageIcon(getClass().getResource("/configurator/pics/vertical.gif")) ); } /** * Shows the system information dialog */ private void doInfo () //OK { Properties p = new Properties(this); JOptionPane.showMessageDialog( getContentPane(), p.getProps (), "System Information" , JOptionPane.INFORMATION_MESSAGE , new javax.swing .ImageIcon(getClass().getResource("/configurator/pics/vertical.gif")) ); } /** * Exits the application after ensuring that the current project is saved or can be discarted */ private void doExit () //OK Autor: Thomas Schädler 72 Anhang A: Quelltext <xmlizer> configurator { if (data == null || (!getProjectData ().isDirty())) //no unsaved preferences { pool.stopRequestAllWorkers(); dispose(); System .exit(0); } else { //ask for discard (ok) or cancel (cancel) int result = JOptionPane.showConfirmDialog ( getContentPane(), "Current Project is not saved!\nDiscard and exit?", APPNAME + " exit", JOptionPane .OK_CANCEL_OPTION, JOptionPane .WARNING_MESSAGE ); if (result == JOptionPane.OK_OPTION) //discard end exit { pool.stopRequestAllWorkers(); getProjectData().finalize(); dispose(); System.exit(0); } else //set status and return { getLog().addWarning("Exit aborted: Current Project is not saved! (Use Menu: Project->Save)"); } } } //MODULE IMPLEMENTATIONS //----------------------------------------------------------------------------------------------/** * Main Method for the behaviour of the Simple DB Export Module * Note: Runs in a pooled Thread */ private void startModuleSimpleDBExport() { Runnable r = new Runnable() { public void run() { //do stuff here getLog().addDebug("Simple Module DB Export starting..."); open("SMDBEmain"); } }; try { pool.execute(r); }catch(InterruptedException ie) { getLog().addError(ie);} } /** * Main Method for the behaviour of the DB2XML Module * Note: Runs in a pooled Thread */ private void startModuleDB2XML () { Runnable r = new Runnable() { public void run() { //do stuff here getLog().addDebug("Database to XML Module starting..."); open("DB2XMLmain"); } }; try { pool.execute(r); }catch(InterruptedException ie) { getLog().addError(ie);} } //MODULE LOADING METHODS //----------------------------------------------------------------------------------------------/** * Shows a message, indicating a successfull project load operation */ private void showProjectLoadedMessage(String message) { JOptionPane.showMessageDialog( getMainDesktopPane(), message, APPNAME + " project loaded successfully", JOptionPane.INFORMATION_MESSAGE , new javax.swing .ImageIcon(getClass().getResource("/configurator/pics/projectloadok.gif")) ); } /** Updates the currently open project with the new projectData and calls <PRE>update()</PRE> on them. * All internal sub -windows must implement <CODE>MyInternalFrame</CODE> and implment its <PRE>update()</PRE> method. */ synchronized public void updateCurrentProject () { if (currentOpenProject != null) { //System.out.println(currentOpenProject); //if there is already an instance running and only one allowed return that instance for manipulation if (openlist.containsKey(currentOpenProject) && !multiple .contains(currentOpenProject)) { //System.out.println("already running and only one instance allowed"); //gets the unique ID of the given windowtype String theUID = (String )single.get(currentOpenProject ); //return this instance Object target = wmwindows.get(theUID); //get it MyInternalFrame targetCompIF = (MyInternalFrame)target; //System.out.println(this.getProjectData().getDB()); targetCompIF.update(this); } } } private String currentOpenProject = null; Autor: Thomas Schädler 73 Anhang A: Quelltext <xmlizer> configurator /** * Start the selected project module (selected in the current projectData) * @return Returns true if start was OK, otherwise false. */ public boolean startupProjectWorkspace() { //Start the selected project module and init the menus and toolbars //check if the module is in the module-list (modules) as a hashtable per module // with [("name",name),("class",classname),("description",short description)] dataItem mod = getProjectData().getInitialByKey("module" ); String modname = mod.getValue(); //eg: Simple DB Export if (modules.contains (modname)) { if (modname.equalsIgnoreCase("")) { getLog().addError("Modul not defined (key was empty)!"); return false ; } if (modname.equalsIgnoreCase("Simple DB Export" )) { startModuleSimpleDBExport(); currentOpenProject = "SMDBEmain"; doStartProjectState(); return true; } else if (modname.equalsIgnoreCase("Database to XML")) { startModuleDB2XML(); currentOpenProject = "DB2XMLmain" ; doStartProjectState(); return true; } else { return false ; } } else { JOptionPane .showMessageDial og( getContentPane(), niceFormat("Your configuration contains a module currently not loaded. Install this module first: [" + modname + "] and try again later."), APPNAME + " project load error", JOptionPane .ERROR_MESSAGE, new javax.swing.ImageIcon(getClass().getResource("/configurator/pics/projectloaderror.gif")) ); resetToDefault(); return false; } } /** * Shows a splashscreen for 3 secs if <code>SPLASH=true</code> * */ public void showSplashScreen() { if (SPLASH ) { sw = new splashWindow(); sw.start(3000L); } } //XML HELPERS //---------------------------- ------------------------------------------------------------------public Document getFileAsXMLDOM(String filename,boolean validating) { try { SAXBuilder builder = new SAXBuilder(validating); //true -> validating against dtd Document jdoc = builder.build(filename); return jdoc; } catch (JDOMException e) { String the_error_message = new String ( "An ERROR occured while processing a file! \n" + "Make sure your your file is valid\n" + "and has no other errors. If it has a reference\n" + "to a DTD, make sure it is really there! \n\n" + "Original Error Message:\n"); String the_error_string = e.toString(); the_error_string = niceFormat(the_error_string); JOptionPane .showMessageDialog( getContentPane(), the_error_message + the_error_string, APPNAME + " file error", JOptionPane .ERROR_MESSAGE ); } return null; } public org.w3c.dom.Document getFileAsXMLW3C(String filename,boolean validating) { Document jdoc = getFileAsXMLDOM (filename,validating ); if (jdoc != null) { try { org.jdom.output.DOMOutputter outp = new org.jdom.output.DOMOutputter (); return outp.output (jdoc); } catch (JDOMException e ) { String the_error_message = new String( "An ERROR occured while processing a file!\n" + "Make sure your your file is valid\n" + "and has no other errors. If it has a reference\n" Autor: Thomas Schädler 74 Anhang A: Quelltext <xmlizer> configurator + "to a DTD, make sure it is really there!\n\n" + "Original Error Message:\n"); String the_error_string = e.toString(); the_error_string = niceFormat(the_error_string); JOptionPane.showMessageDialog( getContentPane(), the_error_message + the_error_string, APPNAME + " file error" , JOptionPane.ERROR_MESSAGE ); } return null; } else { return null; } } //WINDOW & MODULE MANAGEMENT //----------------------------------------------------------------------------------------------/** Hashtable key="winid", value=Dimension */ private Hashtable winPlace = new Hashtable(); /** * Holds all neccessary data for the modules * system: each Module is a Hashtable with the three items * - "name" simple name * - "class" classname * - "description" description for module */ private Vector modules = new Vector (); /** * Holds a Vector of dbItems to browse with the databaseBrowser */ public Vector nextDBToBrowse = new Vector(0); /** * Holds all menuitems and (toolbar)buttons */ private Hashtable allmenuitems = new Hashtable(); private Hashtable allbuttons = new Hashtable(); //hash of JMenuItems //hash of JButtons /** * Returns the Hashtable allmenuitems * @return Hashtable containing all menuitems which have to be informed for changes in the apps state. */ public Hashtable getAllMenuItems() { return allmenuitems; } /** * Returns the Hashtable allbuttons * @return Hashtable containing all Buttons which have to be informed for changes in the apps state. */ public Hashtable getAllButtons () { return allbuttons; } /** * Returns the module-list as Vector of Strings * @return Vector containing the names of all selectable modules. */ public Vector getAvailableModules() { return modules; } /** * Holds all open windows (=internal frames) * format: id = String : UniqueID of the window after creation * value = Object : the window as object */ public Hashtable wmwindows = new Hashtable(); /** * Holds the windows which depend on a project module (id's only) */ private Vector userwindow_types = new Vector(); private Vector userwindow_ids = new Vector(); /** * Holds all open windows (=internal frames) which allow multiple instances * format: type = String : "typename" */ private Vector multiple = new Vector(); /** * Holds all open * format: key = * value */ private Hashtable windows (=internal frames) which are only once allowed String : the window's typekey = String : UniqueID of the window single = new Hashtable (); /** * Holds all open windowtypes and the number of instances currently open * format: type = String : "typename" * value = Integer : Integer (#) of open instances */ private Hashtable openlist = new Hashtable(); /** Autor: Thomas Schädler 75 Anhang A: Quelltext <xmlizer> configurator * Holds all open windowIDs and a String marking i's type * format: id = String : "uniqueID" * value = String : "typekey" */ private Hashtable id2type = new Hashtable(); /** * Holds all possible wi ndows * format: key = String : * value = String : */ private Hashtable types = new /** * Holds all possible windows * format: key = String : * value = String : */ private Hashtable names = new types (register the here, all you use!) "keyname" "exact name of type" eg: configurator.HTMLFrame Hashtable(); names (register the here, all you use!) "keyname" "name as in window menu" Hashtable(); /** * Holds all possible windows names (register them here, all you use!) * format: key = String : "keyname" * value = JMenuItem : JMenuitem use: setTitle(names.name) or the constructor for the Title */ private Hashtable menu = new Hashtable(); /** * Holds the enable/disable-restrictions for the different windows while opening * (same for closing such a frame, but vice-versa */ private Hashtable openEnable = new Hashtable(); private Hashtable openDisable = new Hashtable(); private Hashtable closeEnable = new Hashtable (); private Hashtable closeDisable = new Hashtable(); private String setupUID = new String(); /** * a logWindow */ private static logWindow Log = null; /** * Return the logWindow object */ public static logWindow getLog () { return Log; } /** * Creates new WindowManager and initiates the types */ private void initWindowManager () { //fill the hashtables to register the windows: // types -> String key, String FQClassname // names -> String key, String Description // openEnable -> String key, String[] keys => Items to enable if opened & disabled if closed // openDisable -> String key, String[] keys => Items to disable if opened & enabled if closed //fix internal windows //helpWindow types.put("help","configurator.helpWindow"); names.put("help","Help Browser" ); //setupWindow types.put("setup","configurator.setupWindow"); names.put("setup","Project Setup"); openEnable .put("setup",new String[] {"options"}); openDisable.put("setup",new String[] {"open","new"}); //closeEnable.put("setup",new String[]{"new"}); //javadocWindow types.put("javadoc","configurator.javadocWindow"); names.put("javadoc","JavaDoc Browser"); //sdbBrowser userwindow_types.add("sdatabaseBrowser"); types.put("sdatabaseBrowser","configurator.sdbBrowser"); names.put("sdatabaseBrowser","Simple Database Browser"); //openEnable.put("projectdata",new String[]{"options"}); //openDisable.put("projectdata",new String[]{"open","new"}); //dbBrowser userwindow_types.add("databaseBrowser"); types.put("databaseBrowser","configurator.dbBrowser"); names.put("databaseBrowser","Database Browser" ); //openEnable.put("projectdata",new String[]{"options"}); //openDisable.put("projectdata",new String[]{"open","new"}); //DataChooser userwindow_types.add("DataChooser"); types.put("DataChooser","configurator.DataChooser"); names.put("DataChooser","Data Chooser"); //SQLChooser userwindow_types.add("SQLChooser"); types.put("SQLChooser","configurator.SQLChooser"); names.put("SQLChooser","SQL Chooser" ); //openEnable.put("projectdata",new String[]{"options"}); //openDisable.put("projectdata",new String[]{"open","new"}); Autor: Thomas Schädler 76 Anhang A: Quelltext <xmlizer> configurator //logWindow userwindow_types.add("log" ); types.put("log" ,"configurator.logWindow"); names.put("log" ,"Log Window"); //Module stuff //moduleSimpleDBExport userwindow_types.add("SMDBEmain"); types.put("SMDBEmain","configurator.SMDBEmain" ); names.put("SMDBEmain","DB Export"); //genericxmlWindow userwindow _types.add("DB2XMLmain"); types.put("DB2XMLmain","configurator.DB2XMLmain"); names.put("DB2XMLmain","XML Window"); //add the modules modules.add("Simple DB Export"); modules.add("Database to XML"); //Button and menu stuff //initiate the list for all menuentries and toolbarbuttons //(only those who will always be enables, can be left aside) allbuttons .put("new" ,newButton); allbuttons .put("open",openButton); allbuttons .put("close",closeButton); allbuttons .put("save",saveButton); allbuttons .put("saveas",saveasButton ); allbuttons .put("options",optionsButton); allmenuitems.put("new",newMenuItem); allmenuitems.put("open",openMenuItem ); allmenuitems.put("close",closeMenuItem); allmenuitems.put("save",saveMenuItem ); allmenuitems.put("saveas",saveAsMenuItem); allmenuitems.put("options" ,optionsMenuItem); } /** * Switch to UI in Project State */ public void doStartProjectState() { //enable stuff doEnable("close"); doEnable("save" ); doEnable("saveas"); doEnable("options"); //disable stuff doDisable("open"); doDisable("new" ); } /** * Switch back to UI in xmlizer state (all projects closed) */ public void doEndProjectState() { //disable stuff doDisable("close"); doDisable("save"); doDisable("saveas"); doDisable("options"); //enable stuff doEnable("open" ); doEnable("new"); } /** * Resets the UI to startup state */ public void resetToDefault() { currentOpenProject = null; //close all open windows (which are depending on workspace) -> userwindow_ids closeUserWindows(); close(setupUID); doEndProjectState(); //update the menu and toolbar String[] enableIT = new String[] {"new","open"}; String[] disableIT = new String [] {"close","options","save","saveas"}; for(int i=0;i<enableIT.length;i++) { JButton button = (JButton)getAllButtons().get(enableIT[i]); if (button != null) { button.setEnabled(true); } JMenuItem mitem = (JMenuItem)getAllMenuItems().get(enableIT[i]); if (mitem != null) { mitem.setEnabled(true); } } for(int i=0;i<disableIT.length;i++) { JButton button = (JButton)getAllButtons().get(disableIT[i]); if (button != null) { button.setEnabled(false ); } JMenuItem m item = (JMenuItem)getAllMenuItems().get(disableIT[i]); if (mitem != null) { Autor: Thomas Schädler 77 Anhang A: Quelltext <xmlizer> configurator mitem.setEnabled(false); } } getMainDesktopPane().updateUI(); nullifyProjectData(); getLog().addInformation("Welcome to " + APPNAME + " ver. " + VERSION); } /** * Enables the toolbar and menuitems of the specified windowtype * @param key The <CODE>key</CODE> of the Menuitem or Button to enable. */ public void doEnable(String key) { JButton button = (JButton)getAllButtons().get(key); if (button != null) { button .setEnabled(true); } JMenuItem mitem = (JMenuItem)getAllMenuItems().get(key); if (mitem != null) { mitem.setEn abled (true); } } /** * Disables the toolbar and menuitems of the specified windowtype * @param key The <CODE>key</CODE> of the Menuitem or Button to enable. */ public void doDisable(String key) { JButton button = (JButton)getAllButtons().get(key); if (button != null) { button .setEnabled(false); } JMenuItem mitem = (JMenuItem)getAllMenuItems().get(key); if (mitem != null) { mitem.setEnabled (false ); } } /** Closes all userwindows (means internal sub-windows) opened by a module. * @return True if OK, false otherwise. */ public void closeUserWindows() { while(userwindow_ids .size()>0) { //getLog().addDebug("LISTSIZE = " + userwindow_ids.size() + " LIST " String current = (String)userwindow_ids.firstElement (); close(current); } } + userwindow_ids.toString()); /** * Returns a specified (look types-list for keys) window, where the key is the type * @return Object which represents a <PRE>JInternalFrame</PRE> or a <PRE>MyInternalFrame</PRE>. Both is castable. * @param key The <CODE>key</CODE> of the Window to enable. */ synchronized public Object open(String key) { //if there is already an instance running and only one allowed return that instance for manipulation if (openlist.containsKey(key) && !multiple.contains (key)) { //gets the unique ID of the given windowtype String theUID = (String)single.get(key); //return this instance Object target = wmwindows.get(theUID); //get it MyInternalFrame targetCompIF = (MyInternalFrame )target; try { targetCompIF .update(this); targetCompIF .setVisible (true); targetCompIF .setSelected(true); if (targetCompIF.isIcon ()) { getMainDesktopPane().getDesktopManager().deiconifyFrame(targetCompIF); } getLog().addDebug("Opening already open Window -> " + theUID + "[" + key + "]"); } catch (Exception ex) { getLog().addDebug(ex); } return target; } else //open a new instance of this window and update all internal lists! { if (types.containsKey(key)) //if the type is known -> get new object of that type { String type = (String)types.get(key); //returns the required type as String String uid = uniqueID.get(); //generates a unique id Object target; //is the newly created target object to be returned Class targetDefinition; //its definition Class[] objectArgsClass = new Class[] {configurator.class,String.class}; //its argument-class Constructor objectConstructor; //and its constructor Object[] objectArgs = new Object[] {this,uid}; //its arguments try { targetDefinition = Class .forName(type); //get a definition for the target type objectConstructor = targetDefinition.getConstructor(objectArgsClass); //get an object constructor target = createObject(objectConstructor , objectArgs); //get an object, finally //put it not with the key, but with it's UniqueNumber and update all lists if (target == null) { getLog().addError("WindowManager failed to create window: " + key + " -> " + type); return null; } wmwindows.put(uid,target ); //System.out.println("WMWINDOWS PUT: " + uid); Autor: Thomas Schädler 78 Anhang A: Quelltext <xmlizer> configurator id2type.put(uid,key); boolean added = add2openlist(key); getLog().addDebug("Opening Window -> " + uid + "[" + key + "]"); if (!multiple.contains(key)) // only once allowed { getLog().addDebug(" --------> is Single: " + uid + "[" + key + "]"); single.put(key,uid); } if (key.equalsIgnoreCase ("setup")) { setupUID = uid; } if (userwindow_types.contains (key)) // add the id to the userwindow_ids table { getLog().addDebug(" --------> is Userwindow: " + uid + "[" + key + "]"); userwindow_ids.add(uid); //getLog().addDebug("USERWINDOW " + uid + " ADDED TO LIST !!! LIST: " + userwindow_ids.toString()); } JDesktopPane pane = getMainDesktopPane(); Component targetComp = (Component)target; MyInternalFrame targetCompIF = (MyInternalFrame)targetComp; targetCompIF.setIdentifier(key); pane.add(targetComp ); if (this.winPl ace.containsKey (key)) { getLog().addDebug("READING BOUNDS FOR " + key); targetCompIF.setBounds((Rectangle)winPlace.get(key)); } else { getLog().addDebug("NO BOUNDS FOR " + key); } targetComp.setVisible(true); String compName = (String)names.get(key); JMenuItem compMenuItem = new JMenuItem(compName,targetCompIF.getFrameIcon()); compMenuItem.addActionListener(new WindowChangeAction(this,uid)); menu.put(uid,compMenuItem); getWindowMenu().add(compMenuItem); try { targetCompIF.setVisible(true); targetCompIF.setSelected(true); } catch (Exception ex ) { getLog().addDebug(ex); } if (added) //if the window is the first instance, then update the toolbar and menuentries { if (openEnable.containsKey(key)) // = enable on open { String [] enables = (String [])openEnable.get(key); for(int i=0;i<enables.length;i++) { JButton button = (JButton)getAllButtons().get(enables[i]); if (button != null) { button.setEnabled(true); } JMenuItem mitem = (JMenuItem)getAllMenuItems().get(enables[i]); if (mitem != null) { mitem.setEnabled(true); } } } if (openDisable .containsKey(key)) // = enable on close { String [] disables = (String[])openDisable .get(key); for(int i=0;i<disables.length;i++) { JButton button = (JButton)getAllButtons().get(disables[i]); if (button != null) { button.setEnabled(false ); } JMenuItem mitem = (JMenuItem)getAllMenuItems().get(disables[i]); if (mitem != null) { mitem.setEnabled(false); } } } getWindowMenu().repaint(); } return target; } catch(ClassNotFoundException e) { System.err.println(e); return null; } catch (NoSuchMethodException e) { System.err.println(e); return null; } } else { getLog().addDebug("Opening w indow failed, unknown key -> " + return null; } key); } } Autor: Thomas Schädler 79 Anhang A: Quelltext <xmlizer> configurator /** * Removes a window from the list where the key is the unique key of the window * note: this must be called in every used type in the exitForm-method * (normally right before a every dispose which is not needed anymore) * @param id The <CODE>ID</CODE> of the Window. The ID is generated on window birth and known by the window itself and it is also contained in a list. */ synchronized public void close (String id ) { if (id != null && !id.equals(new String()) && wmwindows.containsKey(id)) //if the id exists, else do nothing { Object obj = wmwindows .get(id); Component objComp = (Component)obj; MyInternalFrame objCompIF = (MyInternalFrame)obj; Rectangle lastBounds = objCompIF .getBounds (); String lastKey = objCompIF.getIdentifier(); this.winPlace.put(lastKey,lastBounds); getLog ().addDebug("SETTING BOUNDS FOR " + lastKey + " TO " + lastBounds.toString()); getMainDesktopPane().getDesktopManager().closeFrame(objCompIF); wmwindows.remove (id); //System.out.println("WMWINDOWS REMOVED: " + id); String winType = (String)id2type.get(id); id2type.remove(id); if (!multiple.contains (winType)) // only once allowed { single.remove(winType); } if (winType.equalsIgnoreCase("projectdata" )) { setupUID = new String(); } if (userwindow_ids.contains (id)) // delete from the userwindow_ids table { userwindow_ids.remove(id); //getLog().addDebug("USERWINDOW " + id + " REMOVED FROM LIST.!" + userwindow_ids.toString()); } JMenuItem compMenuItem = (JMenuItem)menu.get(id); if (compMenuItem != null) { getWindowMenu().remove(compMenuItem); getWindowMenu().repaint(); } menu.remove (id); boolean removed = remove2openlist(winType); if (removed) //was the last instance { getLog().addDebug("Closing Window -> " + id + "[" + winType + "]"); if (closeDisable.containsKey (winType)) // = disable on close { String[] disables = (String[])closeDisable.get(winType); for(int i=0;i<disables.length ;i++) { JButton button = (JButton)getAllButtons().get(disables[i]); if (button != null) { button .setEnabled(false); } JMenuItem mitem = (JMenuItem)getAllMenuItems().get(disables[i]); if (mitem != null) { mitem.setEnabled (false); } } } if (closeEnable.containsKey(winType)) // = enable on close { String[] enables = (String[])closeEnable.get(winType); for(int i=0;i<enables.length;i++) { JButton button = (JButton)getAllButtons().get(enables[i]); if (button != null) { button .setEnabled(true); } JMenuItem mitem = (JMenuItem)getAllMenuItems().get(enables[i]); if (mitem != null) { mitem.setEnabled (true); } } } } } else { getLog ().addDebug("Closing failed -> no such window: " + id); } } /** * Adds an entry to the openlist or updates the count of open instances of the given windowtype * returns true if added * false if modified */ private boolean add2openlist(String key) { if (openlist.containsKey(key)) //increment the number of open instances { Integer openCountInteger = (Integer)openlist.get(key); int openCount = openCountInteger .intValue(); openCount++; openlist.remove(key); openlist.put(key,new Integer(openCount)); return false; } else //add a new item Autor: Thomas Schädler 80 Anhang A: Quelltext <xmlizer> configurator { openlist.put(key,new Integer(1)); return true; } } /** * Removes an entry from the openlist or updates the count of open instances of the given windowtype * returns true if removed (last instance) * false if modified */ private boolean remove2openlist(String key) { //System.out.println("remove2openlist " + key); if (openlist.containsKey(key)) { Integer openCountInteger = (Integer)openlist.get(key); int openCount = openCountInteger .intValue(); //System.out.println("remove2openlist " + openCount); if (openCount > 1) //there are more of these suckers { openCount--; openlist.remove(key); openlist.put(key,new Integer(openCount )); return false ; } else if (openCount <= 1) //this is the last one { openlist.remove(key); return true; } else { return true; } } else { return true; } } //PROJECTDATA //----------------------------------------------------------------------------------------------/** * Holds all neccessary data for the current project * Note: use getProjectData().isDirty() to determine if it changed since the last save() */ private projectData data = null; /** * Returns the current open <CODE>projectData</CODE> * @return projectData of the current open project. */ public projectData getProjectData() { if (data == null) { getLog ().addDebug("PROJECTDATA == NULL -> automatically made fresh data"); makeNewProjectData(); return data; } else { return data; } } /** * Destroys the old data -set (be carefull) and creates an empty projectdata item */ public void makeNewProjectData () { if (data != null) { data.finalize(); } getLog().addDebug("PROJECTDATA RENEWED!"); data = new projectData(); } /** * Destroys the current project and sets it to null */ public void nullifyProjectData () { if (data != null) { data.finalize(); getLog ().addDebug("PROJECTDATA SET TO NULL!"); data = null; } } /** * Copies the xmlizer.project.config.dtd to the indicated directory * Neccessary to open a project-file (must be in same dir) */ public void copyXMLFiles (String newone, String oldone) { String sep = configurator.getFileSeparator(); String base = getProjectBase() + sep; String oldbase = base + oldone + sep; String newbase = base + newone + sep; Vector xml = getProjectData().getXML (); for (Enumeration e = xml.elements(); e.hasMoreElements();) { xmlItem item = (xmlItem)e.nextElement (); String filename = item.getFile(); File outputFile = new File(newbase + filename); File inputFile = new File(oldbase + filename); try { FileReader in = new FileRead er(inputFile); Autor: Thomas Schädler 81 Anhang A: Quelltext <xmlizer> configurator FileWriter out = new FileWriter(outputFile); int c; while ((c = in.read()) != -1) out.write(c); in.close(); out.close(); } catch (Exception ex) { getLog().addWarning(ex.getLocalizedMessage()); } } } /** * Copies the xmlizer.project.config.dtd to the indicated directory * Neccessary to open a project-file (must be in same dir) */ public void copyProjectDTD(String dir) { String sep = configurator.getFileSeparator(); File outputFile = new File(dir + sep + "xmlizer.project.config.dtd"); if (!outputFile .exists()) { StringBuffer dtdstr = new StringBuffer((getClass().getResource("/configurator/xml/xmlizer.project.config/xmlizer.project.config.dtd" )).toString()); dtdstr .delete(0,5); File inputFile = new File(dtdstr.toString()); try { FileReader in = new FileReader(inputFile); FileWriter out = new FileWriter(outputFile); int c; while ((c = in.read()) != -1) out.write(c); in.close(); out.close(); } catch (Exception ex) { getLog().addWarning(ex.getLocalizedMessage()); } } } //STATIC STUFF //----------------------------------------------------------------------------------------------/** * Return a string containing the systems file separator */ public static String getFileSeparator() { return System.getProperty("file.separator"); } /** Nice-formats a <I>loooooooooong</I> string and breaks it after 30 chars. Not very smart, but it doesn't break between words. * @param s String to break apart. * @return String - newly formated. */ public static String niceFormat(String s ) { String newline = new String("\n"); int makeBreak = 30; boolean setNow = false; StringBuffer b = new StringBuffer(s); for(int i=0;i<b.length();i++) { if(i%makeBreak == 0) { setNow = true; //mark for newline break (but wait till word-end) } if (setNow && (b.charAt(i) == ' ')) { b.insert(i,newline ); setNow = false; } } return b.toString(); } /** * Returns an array of bytes representing the input-string */ public static byte[] String2byteArray(String s,String encoding) { if (encoding == null) { return s.getBytes(); } else { try { return s.getBytes(encoding); } catch(UnsupportedEncodingException ex ) { getLog().addError(ex); return new byte[0]; } } } /** * Converts a File-String to an URL */ public static java.net.URL fileToURL(String sfile) { File file = new File(sfile ); String path = file.getAbsolutePath(); Autor: Thomas Schädler 82 Anhang A: Quelltext <xmlizer> configurator String fSep = configurator .getFileSeparator(); if (fSep != null && fSep.length () == 1) path = path.replace(fSep.charAt(0), '/'); if (path.length () > 0 && path.charAt (0) != '/') path = '/' + path; try { return new java.net.URL("file", null, path); } catch (java.net.MalformedURLException e) { // According to the spec this could only happen if the file // protocol were not recognized. throw new Error("unexpected MalformedURLException"); } } /** * Returns an HTML rendition of the given <code>String</code>. This was * written by <a href=mailto:[email protected]>Kimbo Mundy</a>. * @param text A <code>String</code> to be used in an HTML page. * @return A <code>String</code> that quotes any HTML markup * characters. If no quoting is needed, this will be * the same as <code>text</code>. */ public static String htmlEncode(String text) { if (text == null) { return ""; } StringBuffer results = null; char[] orig = null; int beg = 0, len = text.length(); for (int i = 0; i < len; ++i) { char c = text.charAt(i); switch (c) { case 0: case '&': case '<': case '>': case '"': if (results == null) { orig = text.toCharArray(); results = new StringBuffer(len+10); } if (i > beg) results.append(orig, beg, i-beg); beg = i + 1; switch (c) { default: // case 0: continue; case '&': results.append("&amp;"); break; case '<': results.append("&lt;" ); break; case '>': results.append("&gt;" ); break; case '"': results.append("&quot;"); break; } break; } } if (results == null) return text; results.append(orig, beg, len-beg); return results.toString(); } /** * Debug output for an XML Document (org.w3c.dom.Document) * @param doc org.w3c.dom.Document to output as a string. */ synchronized public static void debugOutput(org.w3c.dom.Document doc) { if (doc != null) { //xml stuff org.apache.xml.serialize.OutputFormat format = new org.apache .xml.serialize.OutputFormat(doc); //Serialize DOM //format it format .setLineWidth(65); format .setIndenting(true); format .setIndent (4); StringWriter stringOut = new StringWriter(); //Writer will be a String org.apache.xml.serialize.XMLSerializer serial = new org.apache .xml.serialize.XMLSerializer(stringOut,format); //serialize it try { serial.asDOMSerializer(); // As a DOM Serializer serial.serialize(doc.getDocumentElement()); System.out.println ("---------------- XML DEBUG START ----------------"); System.out.print(stringOut); System.out.println ("---------------- XML DEBUG END ------------------"); } catch (IOException e) { System.out.println ("DOM Serializer error for debug output!"); } } } /** * Debug output for an XML Document (org.jdom.Document) * @param doc org.jdom.Document to output as a string. */ Autor: Thomas Schädler 83 Anhang A: Quelltext <xmlizer> configurator synchronized public static void debugOutput(Document doc) { //xml stuff XMLOutputter fmt = new XMLOutputter(" ",true); //serialize it try { System .out.println("---------------- XML DEBUG START ----------------"); fmt.output(doc,System.out); System .out.println("---------------- XML DEBUG END ------------------"); } catch (IOException e ) { System .out.println("DOM Serializer error for debug output!"); } } /* * creates a new object */ /** Creates an object from scratch. * @param constructor The Constructor of the class. * @param arguments The arguments of the class. * @return Object just created. */ public static Object createObject(Constructor constructor, Object[] arguments) { Object object = null; try { object = constructor.newInstance (arguments ); return object; } catch (InstantiationException e ) { getLog ().addError(e); } catch (IllegalAccessException e ) { getLog ().addError(e); } catch (IllegalArgumentException e) { getLog ().addError(e); } catch (InvocationTargetException e) { getLog ().addError(e); } return object; } /** * Checks a name if it is a valid path name (no special chars) * -> overall: a-z,A-Z * -> !@ begin: 0-9,-,_ */ public static boolean isValidPath(String path ) { String chars = new String("abcdefhgijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"); String nums = new String("0123456789"); String special = new String("_-"); if (path.length ()>=1) { char first = path.charAt(0); if (!containsChar(chars,first)) { return false ; } } else { return false; } for(int i=0;i<path.length();i++) { char current = path.charAt(i); if (!containsChar(chars,current) && !containsChar(nums,current) && !containsChar(special ,current)) { //System.out.println(" FALSE: " + path + " --> " + current + " [" + i + "]"); return false ; } } return true; } private static boolean containsChar (String stack,char needle ) { for(int i=0;i<stack.length ();i++) { char current = stack.charAt (i); if (current == needle) { return true; } } return false; } //INTERNAL CLASSES //----------------------------------------------------------------------------------------------/** * Window Change Action for choosing the window in the WindowMenu */ class WindowChangeAction extends AbstractAction { String uid ; configurator conf; protected WindowChangeAction(configurator config, String uid) { this.conf = config; this.uid = uid; } public void actionPerformed(java.awt.event.ActionEvent e ) { Runnable r = new Runnable() { public void run() { if (conf.wmwindows.containsKey(uid)) //if there is already an instance Autor: Thomas Schädler 84 Anhang A: Quelltext <xmlizer> configurator { Object target = conf.wmwindows .get(uid); //get it JInternalFrame targetCompIF = (JInternalFrame )target; try { targetCompIF.setVisible(true); targetCompIF.setSelected(true); if (targetCompIF .isIcon()) { conf.getMainDesktopPane().getDesktopManager().deiconifyFrame(targetCompIF ); } conf.getMainDesktopPane().updateUI(); } catch (Exception ex) { // } } } }; SwingUtilities.invokeLater(r); } } /** * Look and Feel Action for choosing in the L&FMenu */ class LookAndFeelAction extends AbstractAction { String laf ; configurator conf; /** This action is attached to Menuentries for the Look&Feel change of the UI. * @param config The <PRE>configurator</PRE> (normally <CODE>this</CODE>). * @param laf String for the Look&Feel (its name) */ protected LookAndFeelAction(configurator config, String laf) { this.conf = config; this.laf = laf; } /** The action */ public void actionPerformed(java.awt.event.ActionEvent e ) { Runnable r = new Runnable() { public void run() { try { UIManager.setLookAndFeel(laf); SwingUtilities.updateComponentTreeUI(conf); } catch(java.lang.Exception ex) { //error handling Vetoable Exception! } } }; SwingUtilities.invokeLater(r); } } } /* * TableMap.java * * ---------------------------------------------------------------------------* This file is part of <xmlizer>. * * <xmlizer> is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Foobar is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with <xmlizer>; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * ---------------------------------------------------------------------------* @(#)TableMap.java 1.7 99/04/23 * * Copyright (c) 1997-1999 by Sun Microsystems, Inc. All Rights Reserved. * * Sun grants you ("Licensee") a non-exclusive, royalty free, license to use, * modify and redistribute this software in source and binary code form, * provided that i) this copyright notice and license appear on all copies of * the software; and ii) Licensee does not utilize the software in a manner * which is disparaging to Sun. * * This software is provided "AS IS," without a warranty of any kind. ALL * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY * IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTI CULAR PURPOSE OR * NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN AND ITS LICENSORS SHALL NOT BE * LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING * OR DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR ITS * LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, * INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER * CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF * OR INABILITY TO USE SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * This software is not designed or intended for use in on-line control of * aircraft, air traffic, aircraft navigation or aircraft communications; or in * the design, construction, operation or maintenance of any nuclear * facility. Licensee represents and warrants that it will not use or * redistribute the Software for such purposes. */ /** Autor: Thomas Schädler 85 Anhang A: Quelltext <xmlizer> configurator * In a chain of data manipulators some behaviour is common. TableMap * provides most of this behavour and can be subclassed by filters * that only need to override a handful of specific methods. TableMap * implements TableModel by routing all requests to its model, and * TableModelListener by routing all events to its listeners. Inserting * a TableMap which has not been subclassed into a chain of table filters * should have no effect. * * @version 1.7 04/23/99 * @author Philip Milne */ package configurator; import javax.swing .table.*; import javax.swing .event.TableModelListener; import javax.swing .event.TableModelEvent; public class TableMap extends AbstractTableModel implements TableModelListener { protected TableModel model; public TableModel return model; } getModel() { public void setModel(TableModel model) { this.model = model; model.addTableModelListener(this); } // By default, Implement TableModel by forwarding all messages // to the model. public Object getValueAt (int aRow, int aColumn) { return model.getValueAt(aRow, aColumn); } public void setValueAt(Object aValue, int aRow, int aColumn) { model.setValueAt(aValue, aRow, aColumn); } public int getRowCount() { return (model == null) ? 0 : model.getRowCount (); } public int getColumnCount() { return (model == null) ? 0 : model.getColumnCount(); } public String getColumnName(int aColumn) { return model.getColumnName (aColumn); } public Class getColumnClass(int aColumn) { return model.getColumnClass(aColumn); } public boolean isCellEditable(int row, int column) { return model.isCellEditable(row, column); } // // Implementation of the TableModelListener interf ace, // // By default forward all events to all the listeners. public void tableChanged (TableModelEvent e) { fireTableChanged(e); } }/* * TableSorter.java * * ---------------------------------------------------------------------------* This file is part of <xmlizer>. * * <xmlizer> is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Foobar is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with <xmlizer>; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * ---------------------------------------------------------------------------* @(#)TableSorter.java 1.8 99/04/23 * * Copyright (c) 1997-1999 by Sun Microsystems, Inc. All Rights Reserved. * * Sun grants you ("Licensee") a non-exclusive, royalty free, license to use, * modify and redistribute this software in source and binary code form, * provided that i) this copyright notice and license appear on all copies of * the software; and ii) Licensee does not utilize the software in a manner * which is disparaging to Sun. * * This software is provided "AS IS," without a warranty of any kind. ALL * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY * IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR * NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN AND ITS LICENSORS SHALL NOT BE * LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING * OR DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR ITS * LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, * INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER Autor: Thomas Schädler 86 Anhang A: Quelltext <xmlizer> configurator * CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF * OR INABILITY TO USE SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * This software is not designed or intended for use in on-line control of * aircraft, air traffic, aircraft navigation or aircraft communications; or in * the design, construction, operation or maintenance of any nuclear * facility. Licensee represents and warrants that it will not use or * redistribute the Software for such purposes. */ /** * A sorter for TableModels. The sorter has a model (conforming to TableModel) * and itself implements TableModel. TableSorter does not store or copy * the data in the TableModel, instead it maintains an array of * integers which it keeps the same size as the number of rows in its * model. When the model changes it notifies the sorter that something * has c hanged eg. "rowsAdded" so that its internal array of integers * can be reallocated. As requests are made of the sorter (like * getValueAt(row, col) it redirects them to its model via the mapping * array. That way the TableSorter appears to hold another copy of the table * with the rows in a different order. The sorting algorthm used is stable * which means that it does not move around rows when its comparison * function returns 0 to denote that they are equivalent. * * @version 1.8 04/23/99 * @auth or Philip Milne */ package configurator; import java.util.*; import javax.swing .table.TableModel; import javax.swing .event.TableModelEvent; // Imports for picking up mouse events from the JTable. import java.awt.event.MouseAdapter ; import java.awt.event.MouseEvent; import java.awt.event.InputEvent; import javax.swing .JTable; import javax.swing .table.JTableHeader; import javax.swing .table.TableColumn; import javax.swing .table.TableColumnModel; public class TableSorter extends TableMap { int indexes[]; Vector sortingColumns = new Vector(); boolean ascending = true; int compares; public TableSorter() { indexes = new int[0]; // For consistency. } public TableSorter(TableModel model ) { setModel(model); } public void setModel(TableModel model) { super.setModel(model ); reallocateIndexes(); } public int compareRowsByColumn (int row1, int row2, int column) { Class type = model.getColumnClass(column); TableModel data = model; // Check for nulls Object o1 = data.getValueAt(row1, column); Object o2 = data.getValueAt(row2, column); // If both values are null return 0 if (o1 == null && o2 == null) { return 0; } else if (o1 == null) { // Define null less than everything. return -1; } else if (o2 == null) { return 1; } /* We copy all ret urned values from the getValue call in case an optimised model is reusing one object to return many values. The Number subclasses in the JDK are immutable and so will not be used in this way but other subclasses of Number might want to do this to save space and avoid unnecessary heap allocation. */ if (type.getSuperclass() == java.lang.Number.class) { Number n1 = (Number)data.getValueAt(row1, column); double d1 = n1.doubleValue(); Number n2 = (Number)data.getValueAt(row2, column); double d2 = n2.doubleValue(); if (d1 < d2) return -1; else if (d1 > d2) return 1; else return 0; } else if (type Date d1 = long n1 = Date d2 = long n2 = == java.util.Date.class) { (Date)data.getValueAt(row1, column); d1.getTime(); (Date)data.getValueAt(row2, column); d2.getTime(); Autor: Thomas Schädler 87 Anhang A: Quelltext <xmlizer> configurator if (n1 < n2) return -1; else if (n1 > n2) return 1; else return 0; } else if (type == String.class) { String s1 = (String)data.getValueAt(row1, column); String s2 = (String)data.getValueAt(row2, column); int result = s1.compareTo(s2); if (result < 0) return -1; else if (result > 0) return 1; else return 0; } else if (type == Boolean.class) { Boolean bool1 = (Boolean)data.getValueAt(row1, column); boolean b1 = bool1.booleanValue(); Boolean bool2 = (Boolean)data.getValueAt(row2, column); boolean b2 = bool2.booleanValue(); if (b1 == b2) return 0; else if (b1) // Define false < true return 1; else return -1; } else { Object v1 = data.getValueAt (row1, column); String s1 = v1.toString(); Object v2 = data.getValueAt (row2, column); String s2 = v2.toString(); int result = s1.compareTo(s2); if (result < 0) return -1; else if (result > 0) return 1; else return 0; } } public int compare(int row1, int row2) { compares++; for(int level = 0; level < sortingColumns .size(); level++) { Integer column = (Integer)sortingColumns.elementAt(level); int result = compareRowsByColumn (row1, row2, column.intValue()); if (result != 0) return ascending ? result : -result; } return 0; } public void reallocateIndexes () { int rowCount = model .getRowCount(); // Set up a new array of indexes with the right number of elements // for the new data model. indexes = new int[rowCount ]; // Initialise with the identity mapping. for(int row = 0; row < rowCount ; row++) indexes[row] = row; } public void tableChanged (TableModelEvent e) { reallocateIndexes(); super.tableChanged(e); } public void checkModel() { if (indexes.length != model.getRowCount()) { System .err.println("Sorter not informed of a change in model." ); } } public void sort(Object sender) { checkModel (); compares = 0; // n2sort(); // qsort(0, indexes.length -1); shuttlesort((int[])indexes .clone(), indexes, 0, indexes.length); } public void n2sort() { for(int i = 0; i < getRowCount(); i++) { for(int j = i+1; j < getRowCount (); j++) { if (compare(indexes[i], indexes[j]) == -1) { swap(i, j); } } } } // // // // // // // This is a home-grown implementation which we have not had time to research - it may perform poorly in some circumstances. It requires twice the space of an in-place algorithm and makes NlogN assigments shuttling the values between the two arrays. The number of compares appears to vary between N-1 and NlogN depending on the initial order but the main reason for using it here is that, unlike qsort, it is stable. Autor: Thomas Schädler 88 Anhang A: Quelltext <xmlizer> configurator public void shuttlesort(int from[], int to[], int low, int high) { if (high - low < 2) { return ; } int middle = (low + high)/2; shuttlesort(to, from, low, middle); shuttlesort(to, from, middle, high); int p = low; int q = middle; /* This is an optional short-cut; at each recursive call, check to see if the elements in this subset are already ordered. If so, no further comparisons are needed; the sub-array can just be copied. The array must be copied rather than assigned otherwise sister calls in the recursion might get out of sinc. When the number of elements is three they are partitioned so that the first set, [low, mid), has one element and and the second, [mid, high), has two. We skip the optimisation when the number of elements is three or less as the first compare in the normal merge will produce the same sequence of steps. This optimisation seems to be worthwhile for partially ordered lists but some analysis is needed to find out how the performan ce drops to Nlog(N) as the initial order diminishes - it may drop very quickly. */ if (high - low >= 4 && compare(from[middle-1], from[middle]) <= 0) { for (int i = low; i < high; i++) { to[i] = from[i]; } return ; } // A normal merge. for(int i = low; i < high; i++) { if (q >= high || (p < middle && compare(from[p], from[q]) <= 0)) { to[i] = from[p++]; } else { to[i] = from[q++]; } } } public void swap(int i, int j) { int tmp = indexes[i]; indexes[i] = indexes[j]; indexes[j] = tmp; } // The mapping only affects the contents of the data rows. // Pass all requests to these rows through the mapping array: "indexes". public Object getValueAt (int aRow, int aColumn) { checkModel (); return model.getValueAt(indexes[aRow], aColumn); } public void setValueAt(Object aValue, int aRow, int aColumn) { checkModel (); model.setValueAt(aValue, indexes[aRow], aColumn); } public void sortByColumn (int column ) { sortByColumn(column, true); } public void sortByColumn (int column , boolean ascending) { this.ascending = ascending ; sortingColumns.removeAllElements(); sortingColumns.addElement(new Integer(column)); sort(this); super.tableChanged(new TableModelEvent(this)); } // There is no -where else to put this. // Add a mouse listener to the Table to trigger a table sort // when a column heading is clicked in the JTable. public void addMouseListenerToHeaderInTable(JTable table) { final TableSorter sorter = this; final JTable tableView = table; tableView.setColumnSelectionAllowed(false ); MouseAdapter listMouseListener = new MouseAdapter() { public void mouseClicked(MouseEvent e ) { TableColumnModel columnModel = tableView.getColumnModel(); int viewColumn = columnModel .getColumnIndexAtX(e.getX()); int column = tableView.convertColumnIndexToModel (viewColumn); if(e.getClickCount () == 1 && column != -1) { int shiftPressed = e.getModifiers()&InputEvent.SHIFT_MASK; boolean ascending = (shiftPressed == 0); sorter.sortByColumn (column, ascending); } } }; JTableHeader th = tableView.getTableHeader(); th.addMouseListener(listMouseListener); } }/* * ThreadPool.java * * Created on 19. Mai 2002, 20:28 * ---------------------------------------------------------------------------* This file is part of <xmlizer>. * Autor: Thomas Schädler 89 Anhang A: Quelltext <xmlizer> configurator * <xmlizer> is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Foobar is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with <xmlizer>; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * ---------------------------------------------------------------------------*/ package configurator; /** * A pool of threads * @author [email protected] */ public class ThreadPool extends Object { private ObjectFIFO idleWorkers ; private ThreadPoolWorker [] workerList; public ThreadPool(int numberOfThreads) { // make sure that it's at least one numberOfThreads = Math.max(1, numberOfThreads); idleWorkers = new ObjectFIFO(numberOfThreads); workerList = new ThreadPoolWorker[numberOfThreads]; for ( int i = 0; i < workerList .length; i++ ) { workerList[i] = new ThreadPoolWorker(idleWorkers); } } public void execute(Runnable target ) throws InterruptedException { // block (forever) until a worker is available ThreadPoolWorker worker = (ThreadPoolWorker) idleWorkers .remove(); worker.process(target); } public void stopRequestIdleWorkers() { try { Object [] idle = idleWorkers .removeAll (); for ( int i = 0; i < idle.length ; i++ ) { ( (ThreadPoolWorker) idle[i] ).stopRequest(); } } catch ( InterruptedException x ) { Thread .currentThread().interrupt(); // re-assert } } public void stopRequestAllWorkers() { // Stop the idle one's first since that won't interfere with anything // productive. stopRequestIdleWorkers(); // give the idle workers a quick chance to die try { Thread.sleep(250); } catch ( InterruptedException x ) { } // Step through the list of ALL workers that are still alive. for ( int i = 0; i < workerList .length; i++ ) { if ( workerList[i].isAlive() ) { workerList[i].stopRequest(); } } } } /* * uniqueID.java * * ---------------------------------------------------------------------------* This file is part of <xmlizer>. * * <xmlizer> is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Foobar is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with <xmlizer>; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * ---------------------------------------------------------------------------*/ package configurator; import java.lang.*; /** * Builds a class returning uniqueID's (based on system time and secured through syncronisiation) * @author [email protected] */ public class UniqueID { static long current = System.currentTimeMillis(); Autor: Thomas Schädler 90 Anhang A: Quelltext <xmlizer> configurator /** * Returns a uniqueID as long */ static public synchronized long getLong() { return current++; } /** * Returns a uniqueID as String */ static public synchronized String get() { String str = new String(); str = str.valueOf(current++); return str; } } /* * HTMLBrowser.java * * ---------------------------------------------------------------------------* This file is part of <xmlizer>. * * <xmlizer> is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Foobar is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with <xmlizer>; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * ---------------------------------------------------------------------------*/ package configurator; import import import import import import import import java.awt.*; java.net.URL; java.net.MalformedURLException; java.io.*; java.util.Vector ; javax.swing .text.*; javax.swing .event.*; javax.swing .*; /** * Is a simple HTML Browser * @author [email protected] */ public class HTMLBrowser extends javax.swing .JScrollPane implements HyperlinkListener { JEditorPane html; class PageLoader implements Runnable { PageLoader (URL u, Cursor c ) { url = u; cursor = c; } public void run() { if(url == null) { // restore the original cursor html.setCursor(cursor); // automatic validation is activated. Container parent = html.getParent (); parent.repaint(); } else { Document doc = html.getDocument(); try { html.setPage(url); } catch(IOException ioe) { html.setDocument(doc); } finally { url = null; SwingUtilities .invokeLater(this); } } } //end run URL url; Cursor cursor; } //end class pageloader public HTMLBrowser() { html = new JEditorPane(); html.setEditable(false); html.addHyperlinkListener(this); JViewport vp = getViewport (); vp.add(html); } //end htmlbrowser public HTMLBrowser(URL url) { try { html = new JEditorPane (url); html.setEditable (false ); html.addHyperlinkListener(this); JViewport vp = getViewport(); vp.add(html); } catch(MalformedURLException e) { System .out.println("Malformed URL: " + e); Autor: Thomas Schädler 91 Anhang A: Quelltext <xmlizer> configurator } catch(IOException e) { System .out.println("IOException: " + e); } } //end htmlbrowser public void hyperlinkUpdate(HyperlinkEvent e) { if(e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) { linkActivated(e.getURL ()); } } //end hyperlinkupdate protected void linkActivated(URL u) { Cursor c = html.getCursor(); Cursor waitCursor = Cursor .getPredefinedCursor (Cursor.WAIT_CURSOR); html.setCursor(waitCursor); SwingUtilities.invokeLater (new PageLoader (u, c)); } //end linkactivated } //end class htmlbroser/* * ThreadPoolWorker.java * * Created on 19. Mai 2002, 20:28 * ---------------------------------------------------------------------------* This file is part of <xmlizer>. * * <xmlizer> is free software; you can redistribute it and /or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Foobar is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY ; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with <xmlizer>; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * ---------------------------------------------------------------------------*/ package configurator; /** * A worker thread which is in the threadpool * @author [email protected] */ public class ThreadPoolWorker extends Object { private static int nextWorkerID = 0; private ObjectFIFO idleWorkers ; private int workerID; private ObjectFIFO handoffBox; private Thread internalThread; private volatile boolean noStopRequested ; public ThreadPoolWorker(ObjectFIFO idleWorkers) { this.idleWorkers = idleWorkers; workerID = getNextWo rkerID (); handoffBox = new ObjectFIFO(1); // only one slot // just before returning, the thread should be created and started. noStopRequested = true; Runnable r = new Runnable() { public void run() { try { runWork(); } catch ( Exception x ) { // in case ANY exception slips through x.printStackTrace(); } } }; internalThread = new Thread(r); internalThread.start (); } public static synchronized int getNextWorkerID() { // notice: synchronized at the class level to ensure uniqueness int id = nextWorkerID; nextWorkerID++; return id; } public void process(Runnable target ) throws InterruptedException { handoffBox .add(target); } private void runWork() { while ( noStopRequested ) { try { //System.out.println("workerID=" + workerID + ", ready for work"); // Worker is ready work. This will never block since the // idleWorker FIFO queue has enough capacity for all of // the workers. idleWorkers.add(this); // wait here until the server puts a request into the box Runnable r = (Runnable) handoffBox.remove(); //System.out.println("workerID=" + workerID + ", starting execution of new Runnable: " + r); runIt(r); // catches all exceptions Autor: Thomas Schädler 92 Anhang A: Quelltext <xmlizer> configurator } catch ( InterruptedException x ) { Thread.currentThread().interrupt(); // re-assert } } } private void runIt(Runnable r) { try { r.run(); } catch ( Exception runex ) { // catch any and all exceptions System .err.println("Uncaught exception fell through from run()"); runex.printStackTrace(); } finally { // Clear the interrupted flag (in case it comes back set) // so that if the loop goes again, the // handoffBox.remove() does not mistakenly throw // an InterruptedException. Thread .interrupted(); } } public void stopRequest() { //System.out.println("workerID=" + workerID + ", stopRequest() received."); noStopRequested = false; internalThread.interrupt(); } public boolean isAlive() { return internalThread.isAlive(); } } /* * Properties.java * * Created on 8. April 2002, 09:58 * ---------------------------------------------------------------------------* This file is part of <xmlizer>. * * <xmlizer> is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Foobar is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with <xmlizer>; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * ----------------------------------------- ----------------------------------*/ package configurator; /** * Just a helper class for compiling all properties in a string * @author [email protected] * @version */ public class Properties { private String s = new String(""); private configurator config; /** * Default constructor */ public Properties(configurator conf ) { config = conf; } /** * Returns a already formated string containing all properties */ public String getProps() { s = s.concat("\n<xmlizer>-Home = "); s = s.concat(config.getHomeBase ()); s = s.concat("\n<xmlizer>-Projects = "); s = s.concat(config.getProjectBase()); s = s.concat("\nOS Name = "); s = s.concat(System.getPro perty ("os.name" )); s = s.concat("\nOS Version = "); s = s.concat(System.getProperty ("os.version")); s = s.concat("\nOS Architecture = "); s = s.concat(System.getProperty ("os.arch" )); s = s.concat("\nJAVA Version = "); s = s.concat(System.getProperty ("java.version" )); s = s.concat("\nJAVA Vendor = " ); s = s.concat(System.getProperty ("java.vendor")); s = s.concat("\nJAVA Vendor URL = "); s = s.concat(System.getProperty ("java.vendor.url")); s = s.concat("\nJAVA Home = "); s = s.concat(System.getProperty ("java.home")); s = s.concat("\nJAVA VM Version = "); s = s.concat(System.getProperty ("java.vm.version")); s = s.concat("\nJAVA VM Vendor = "); s = s.concat(System.getProperty ("java.vm.vendor")); s = s.concat("\nJAVA VM Name = "); s = s.concat(System.getProperty ("java.vm.name" )); s = s.concat("\nUSER Home = "); s = s.concat(System.getProperty ("user.home")); s = s.concat("\nUSER Name = "); s = s.concat(System.getProperty ("user.name")); Autor: Thomas Schädler 93 Anhang A: Quelltext <xmlizer> configurator return s; } } //end class properties /* * ObjectFIFO.java * * Created on 19. Mai 2002, 20:28 * ---------------------------------------------------------------------------* This file is part of <xmlizer>. * * <xmlizer> is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Foobar is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with <xmlizer>; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * ---------------------------------------------------------------------------*/ package configurator; /** * Is a simple FIFO of Objects * @author [email protected] */ public class ObjectFIFO extends Object { private Object [] queue; private int capacity; private int size; private int head; private int tail; public ObjectFIFO(int cap) { capacity = ( cap > 0 ) ? cap : 1; // at least 1 queue = new Object[capacity]; head = 0; tail = 0; size = 0; } public int getCapacity() { return capacity ; } public synchronized int getSize() { return size; } public synchronized boolean isEmpty() { return ( size == 0 ); } public synchronized boolean isFull() { return ( size == capacity ); } public synchronized void add(Object obj) throws InterruptedException { waitWhileFull(); queue[head] = obj; head = ( head + 1 ) % capacity; size++; notifyAll(); // let any waiting threads know about change } public synchronized void addEach(Object[] list) throws InterruptedException { // // You might want to code a more efficient // implementation here ... (see ByteFIFO.java) // for ( int i = 0; i < list.length; i++ ) { add(list[i]); } } public synchronized Object remove() throws InterruptedException { waitWhileEmpty(); Object obj = queue[tail]; // don't block GC by keeping unnecessary reference queue[tail] = null; tail = ( tail + 1 ) % capacity; size--; notifyAll(); // let any waiting threads know about change return obj; } Autor: Thomas Schädler 94 Anhang A: Quelltext <xmlizer> configurator public synchronized Object[] removeAll() throws InterruptedException { // // You might want to code a more efficient // implementation here ... (see ByteFIFO.java) // Object[] list = new Object [size]; // use the current size for ( int i = 0; i < list.length; i++ ) { list[i] = remove (); } // if FIFO was empty, a zero-length array is returned return list; } public synchronized Object[] removeAtLeastOne () throws InterruptedException { waitWhileEmpty(); // wait for a least one to be in FIFO return removeAll(); } public synchronized boolean waitUntilEmpty(long msTimeout) throws InterruptedException { if ( msTimeout == 0L ) { waitUntilEmpty(); // use other method return true; } // wait only for the specified amount of time long endTime = System.currentTimeMillis() + msTimeout; long msRemaining = msTimeout; while ( !isEmpty() && ( msRemaining > 0L ) ) { wait(msRemaining ); msRemaining = endTime - System.currentTimeMillis(); } // May have timed out, or may have met condition, // calc return value. return isEmpty(); } public synchronized void waitUntilEmpty() throws InterruptedException { while ( !isEmpty() ) { wait(); } } public synchronized void waitWhileEmpty() throws InterruptedException { while ( isEmpty() ) { wait(); } } public synchronized void waitUntilFull() throws InterruptedException { while ( !isFull () ) { wait(); } } public synchronized void waitWhileFull() throws InterruptedException { while ( isFull() ) { wait(); } } } /* * dataItem.java * * Created on 18. April 2002, 20:20 * ---------------------------------------------------------------------------* This file is part of <xmlizer>. * * <xmlizer> is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any lat er version. * * Foobar is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with <xmlizer>; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * ---------------------------------------------------------------------------*/ package configurator; import java.lang.*; Autor: Thomas Schädler 95 Anhang A: Quelltext <xmlizer> configurator /* * This class representates a multi-purpose item consiting of the following stuff * * - key (String) * - value (String) * - description (St ring) * * -> ... every variable has its get ans set methods * @author [email protected] */ public class dataItem { private String tkey ; private String tdescription; private String tvalue; /** * Constructors for a new projectdataItem * -> holds: * String key * String value * String description */ public dataItem(String key,String value,String description) { tkey = key; tvalue = value; tdescription = description ; } public dataItem(String key,String value) { tkey = key; tvalue = value; tdescription = new String(); } public dataItem(String key) { tkey = key; tvalue = new String(); tdescription = new String(); } public dataItem() { tkey = new String(); tvalue = new String(); tdescription = new String(); } //STRING REPRESENTATION //----------------------------------------------------------------------------------------------/** * By default show the key as String */ public String toString() { return "\ndataItem : key = " + tkey + "\n" + " : value = " + tvalue + "\n" + " : description = " + tdescription + "\n"; } //GET AND SET METHODS //----------------------------------------------------------------------------------------------/** * Returns the key of the item */ public String getKey() { return tkey; } /** * Get the description of the item */ public String getDescription() { return tdescription; } /** * Get the value of the item */ public String getValue() { return tvalue; } /** * Set a new key */ public void setKey(String s) { tkey = s; } /** * Set a new description */ public void setDescription(String s ) { tdescription = s; } /* * Set a new value */ public void setValue(String s) { tvalue = s; } } /* * * * * * * dataItem.java But more important: This class contains different methods for handling database connections Created on 18. April 2002, 20:20 Autor: Thomas Schädler 96 Anhang A: Quelltext <xmlizer> configurator * ---------------------------------------------------------------------------* This file is part of <xmlizer>. * * <xmlizer> is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Foobar is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with <xmlizer>; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * ---------------------------------------------------------------------------*/ package configurator; import import import import java.sql.*; java.util.*; javax.swing .*; javax.swing .table.*; /** * This class representates a database item consisting of the following stuff * with a get and set method each * * String name * String driver * String url * String timeout * String username * String password * * -> ... every variable has its get an s set methods * @author [email protected] */ public class dbItem { private String tname; private String tdriver; private String turl ; private String ttimeout; private int ttimeoutint; private int tstart = 0; private int chunkSize = 25; private boolean hasLimit = true; private String tusername ; private String tpassword ; private boolean isConnected = false ; private Connection connection = null; private Vector tableList = null; private boolean stopNOW = false; private Hashtable navigator; private String getCountSQL = new String(); private String lastSQL = new String (); private Vector selectedTables = new Vector(); private String outputType = "simple"; //little global helpers private SQLStatement lastStatement = null; //CONSTRUCTORS //----------------------------------------------------------------------------------------------/** * Constructors for a new dbItem * -> holds: * String nam e * String driver * String url * String timeout * int timeoutint * String username * String password */ public dbItem(String name,String driver,String url ,String timeout ,String username,String password) { this.tname = name; this.tdriver = driver; this.turl = url; this.ttimeout = timeout; this.ttimeoutint = ConvertString2int (timeout); this.tusername = username; this.tpassword = password; } public dbItem(String name,String driver,String url ,String timeout ,String username) { this.tname = name; this.tdriver = driver; this.turl = url; this.ttimeout = timeout; this.ttimeoutint = ConvertString2int (timeout); this.tusername = username; this.tpassword = new String(); } public dbItem(String name,String driver,String url ,String timeout ) { this.tname = name; this.tdriver = driver; this.turl = url; this.ttimeout = timeout; this.ttimeoutint = ConvertString2int (timeout); this.tusername = new String(); this.tpassword = new String(); } public dbItem(String name,String driver,String url ) { this.tname = name; Autor: Thomas Schädler 97 Anhang A: Quelltext <xmlizer> configurator this.tdriver = driver; this.turl = url; this.ttimeout = new String (); this.tusername = new String(); this.tpassword = new String(); } public dbItem(String name,String driver) { this.tname = name; this.tdriver = driver; this.turl = new String(); this.ttimeout = new String (); this.tusername = new String(); this.tpassword = new String(); } public dbItem(String name) { this.tname = name; this.tdriver = new String(); this.turl = new String(); this.ttimeout = new String (); this.tusername = new String(); this.tpassword = new String(); } public dbItem() { this.tname = new String(); this.tdriver = new String(); this.turl = new String(); this.ttimeout = new String (); this.tusername = new String(); this.tpassword = new String(); } //STRING REPRESENTATION //------------------------------------------------------------------------- ---------------------/** * By default show the key as String */ public String toString() { return tname; } //HELPER METHODS //----------------------------------------------------------------------------------------------public static int ConvertString2int (String string) { try { Integer to = new Integer(string); return to.intValue(); } catch(NumberFormatException ex) { return 25; //failsafe } } public static String Convertint2String(int integer) { try { Integer to = new Integer(integer); return to.toString(); } catch(NumberFormatException ex) { return "25"; //failsafe } } //THREAD ABORT FLAG MANAGEMENT //----------------------------------------------------------------------------------------------public void halt() { this.stopNOW = true; } private void goon() { this.stopNOW = false ; } //LIMITERS //----------------------------------------------------------------------------------------------public String getLastSQL () { return this.lastSQL; } public void clearLastStatement () { this.lastStatement = null; } public SQLStatement getLastStatement() { return this.lastStatement; } public void updateLastSQLSQL(String s) { if (this.lastStatement != null) { this.lastStatement.setSQL(s); } } public void nextChunk() { setLimitStart(tstart + chunkSize); } public void lastChunk() { setLimitStart(Math.max(tstart - chunkSize ,0)); } private void setLimitStart(int i) { this.tstart = i; Autor: Thomas Schädler 98 Anhang A: Quelltext <xmlizer> configurator } public void resetLimit() { setLimitStart(0); } public void setChunkSize (int i) { this.chunkSize = i; } public int getChunkSize() { return this.chunkSize; } /** * Returns the limit as appendable SQL String * e.g: " LIMIT 0,25", per default if never set */ private String getLimit() { return new String(" LIMIT " + tstart + "," + chunkSize); } /** * Enables/Disables the automatic limit */ public void setLimit(boolean bool) { this.hasLimit = bool; } public boolean hasLimit() { return hasLimit ; } public void setCountSQL(String s) { this.getCountSQL = s; } public String getCountSQL() { return getCountSQL; } //GET AND SET METHODS //----------------------------------------------------------------------------------------------public Hashtable getNavigator() { return navigator; } /** * Get the name of the dbitem */ public String getName() { return this.tname; } /** * Get the driver of the dbitem */ public String getDriver() { return this.tdriver; } /** * Get the url of the dbitem */ public String getUrl() { return this.turl; } /** * Get the timeout of the dbitem */ public String getTimeout () { return this.ttimeout ; } public int getTimeoutAsInt() { return ttimeoutint; } /** * Get the username of the dbitem */ public String getUsername() { return this.tusername; } /** * Get the password of the dbitem */ public String getPassword() { return this.tpassword; } /** * Set the name of the dbitem */ public void setName(String s) { this.tname = s; } /** * Set the driver of the dbitem */ public void setDriver(String s ) { this.tdriver = s; Autor: Thomas Schädler 99 Anhang A: Quelltext <xmlizer> configurator } /** * Set the url of the dbitem */ public void setUrl(String s) { this.turl = s; } /** * Set the timeout of the dbitem */ public void setTimeout(String s) { this.ttimeout = s; this.ttimeoutint = ConvertString2int (s); } /** * Set the username of the dbitem */ public void setUsername(String s) { this.tusername = s; } /** * Set the password of the dbitem */ public void setPassword(String s) { this.tpassword = s; } //SELECTED TABLES FOR SMDBE MAPPING AND EXPORT AND FOR THE OUTPUT TYPE //----------------------------------------------------------------------------------------------public void SMDBEsetSelectedTables(Vector v) { this.selectedTables = v; } public Vector SMDBEgetSelectedTables() { return this.selectedTables ; } public void SMDBEselectTable(String tablename ) { if (!this.selectedTables.contains(tablename)) { this.selectedTables.add(tablename); } } public void SMDBEdeselectTable (String tablename) { if (this.selectedTab les.contains(tablename)) { this.selectedTables.remove(tablename); } } public void SMDBEsetOutputType (String type) { this.outputType = type; } public String SMDBEgetOutputType() { return this.outputType; } //DATABASE CONNECTION METHODS //----------------------------------------------------------------------------------------------public boolean isConnected() { return isConnected; } public void closeConnection() { this.tableList = null; if (isConnected ) { try { isConnected = false; connection.close(); } catch(Exception ex) { //ok } } } synchronized public Connection getConnection() throws Exception { if (!isConnected) { makeConnection(); } while(!isConnected) { if (stopNOW) { throw new Exception("Could not connect to database " + tname + "."); } } return connection; } /** * Tries to create connection * in the thread in order not to "hang" the application */ synchronized private void makeConnection () throws Exception { try { Class.forName(tdriver); DriverManager.setLoginTimeout(ttimeoutint); if(tusername.equalsIgnoreCase(new String())) { connection = DriverManager.getConnection(turl); isConnected = true; Autor: Thomas Schädler 100 Anhang A: Quelltext <xmlizer> configurator //System.out.println("Connection to database " + tname + " successful!"); } else { connection = DriverManager.getConnection(turl,tusername,decryptSecurePassword(tpassword)); isConnected = true; //System.out.println("Connection to database " + tname + " successful!"); } } catch(Exception ex) { //System.out.println("Connection " + tname + " not possible!"); throw new Exception("Could not establish connection " + tname + "."); } } //DATABASE ACCESS METHODS //----------------------------------------------------------------------------------------------/** * Returns a Vectro of all tables in for this DB as listItems where * each listItem has a name, the number or rows and a boolean flag if it should be selected */ public Vector getTableList() throws Exception { if(tableList == null) { Vector result = new Vector(); ResultSet rs = getConnection().getMetaData ().getTables(null, null, null, new String[]{"TABLE"}); Statement stmt = getConnection().createStatement(); while(rs.next()) { //table name String res = rs.getString("TABLE_NAME" ); //rows int rows = 0; ResultSet srs = stmt.executeQuery ("SELECT COUNT(*) FROM " + res); if(srs.next()) { rows = srs.getInt(1); } //mark the listitems as selected or not depending on read in data boolean isThisSelected = false; if (selectedTables != null && selected Tables.size() > 0) { if (selectedTables.contains(res)) { isThisSelected = true; } } listItem item = new listItem (res,rows,isThisSelected); result.add(item); } tableList = result; } return tableList; } /** * Returns a JTable containing the data of the specified SQL statement * The table has a sorter and a clickable header to start the sorting. */ public JTable getQueryAsJTable (String sqlQuery) throws Exception { Hashtable theTable = query (sqlQuery); final String data[][] = (String [][]) theTable.get("table"); final int rows = ((Integer )theTable.get("rows" )).intValue(); final int cols = ((Integer )theTable.get("cols" )).intValue(); final Vector columnnames = (Vector)theTable.get("columnlabels"); final Vector columntypes = (Vector)theTable.get("columntypes" ); //buid the lastStatement Vector lastColumns = new Vector (); for (Enumeration e = columnnames.elements (); e.hasMoreElements();) { String curr = (String)e.nextElement(); lastColumns .add(curr); } //build the lastTypes -> Vector Vector lastTypes = new Vector(); for (Enumeration e = columntypes.elements (); e.hasMoreElements();) { String curr = (String)e.nextElement(); lastTypes.add(curr); } this.lastStatement = new SQLStatement(this.getName(),sqlQuery ,lastColumns,lastTypes,rows); TableModel dataModel = new AbstractTableModel() { public int getColumnCount() { return cols; } public int getRowCount () { return rows; } public Object getValueAt(int row,int col) { return data[col][row]; } public String getColumnName (int col) { String label = (String)columnnames.get(col); return label ; } }; TableSorter sorter = new TableSorter (dataModel ); JTable dbTable = new JTable(sorter); sorter.addMouseListenerToHeaderInTable(dbTable); return dbTable; } private String checkSQL(String sql) { //System.out.println("Checking SQL for limit-tag in: " + sql); StringBuffer countSQL = new StringBuffer("SELECT COUNT(*)"); boolean hadFrom = false; Autor: Thomas Schädler 101 Anhang A: Quelltext <xmlizer> configurator if (this.hasLimit) { boolean theLimit = false; //FIXME limit kann auch ein tablename sein!!! besserer SQL check StringTokenizer tokenizer = new StringTokenizer (sql); while (tokenizer .hasMoreTokens()) { String currentToken = tokenizer.nextToken(); if (hadFrom || currentToken.equalsIgnoreCase(new String("from"))) { hadFrom = true; countSQL .append(" "); countSQL .append(currentToken); } if (currentToken.equalsIgnoreCase (new String("limit"))) { theLimit = true; } } setCountSQL (countSQL.toString()); if (!theLimit) { return sql + getLimit(); } else { setLimit(false); return sql; } } else { return sql; } } /** * Runs a specified SQL Query on the DB connection * and returns a Hashtable containing the different data to preceed * Note: allways use this function to query the DB! */ synchronized public Hashtable query (String sq lQuery) throws Exception { lastSQL = sqlQuery; Statement stmt = getConnection().createStatement(); int MaxRowCount = 0; if (hasLimit) { sqlQuery = checkSQL(sqlQuery); String countSQL = getCountSQL(); ResultSet srs = stmt.executeQuery(countSQL ); if(srs.next()) { MaxRowCount = srs.getInt(1); } } //System.out.println("DB QUERY: " + sqlQuery); ResultSet rs = stmt.executeQuery(sqlQuery ); ResultSetMetaData rsmd = rs.getMetaData(); int cols = rsmd.getColumnCount(); int rowNumber = 0; Vector vector = new Vector (5, 5); Vector collables = new Vector(); //of String Vector colltypes = new Vector(); //of String Vector collsizes = new Vector(); //of Integer Vector collnames = new Vector(); //of String //build collumnvector (with the names of the columns) for(int i=1;i<=cols;i++) { if (stopNOW) { goon(); throw new Exception("Aborted by user."); } collables.add(rsmd.getColumnLabel(i)); colltypes.add(rsmd.getColumnTypeName(i)); collsizes.add(new Integer(rsmd.getColumnDisplay Size(i))); collnames.add(rsmd.getColumnName (i)); } //build rowvector while(rs.next()) { if (stopNOW) { goon(); throw new Exception("Aborted by user."); } rowNumber++; for(int i=1;i<=cols;i++) { if (stopNOW) { goon(); throw new Exception("Aborted by user." ); } vector.add(rs.getString (i)); } } int rows = rowNumber ; if (MaxRowCount == 0) { MaxRowCount = rows; } String info[][] = new String[cols][rows]; vector.trimToSize(); int row = 0; int col = 0; for(int i=0;i<vector .size();i++) { if (stopNOW) { goon(); throw new Exception("Aborted by user."); } try { info[col][row] = vector .get(i).toString(); } catch(NullPointerException ex) { info[col][row] = ""; } if(col+1 == cols) { col = -1; row++; } col++; Autor: Thomas Schädler 102 Anhang A: Quelltext <xmlizer> configurator } Hashtable navData = new Hashtable(); if (hasLimit) { navData.put("first",Convertint2String (this.tstart+1)); if ((this.tstart + chunkSize) > this.tstart + rows) { navData.put("last" ,Convertint2String(this.tstart + rows)); } else { navData.put("last" ,Convertint2String(this.tstart + chunkSize)); } navData.put("max",Convertint2String(MaxRowCount )); if (MaxRowCount > this.tstart + chunkSize) { navData.put("hasNext",new Boolean(true)); } else { navData.put("hasNext",new Boolean (false)); } if (this.tstart != 0) { navData.put("hasLast",new Boolean(true)); } else { navData.put("hasLast",new Boolean(false)); } } else { navData.put("first",Convertint2String (this.tstart+1)); navData.put("last",Convertint2String(rows)); navData.put("max",Convertint2String(rows)); navData.put("hasNext",new Boolean(false)); navData.put("hasLast",new Boolean(false)); } this.navigator = navData; Hashtable result = new Hashtable(); result.put("table",info); result.put("columnname",collnames); result.put("columnsize",collsizes); result.put("columnlabels",collables); result.put("columntypes",colltypes); result.put("rows",new Integer(rows)); result.put("cols",new Integer(cols)); return result; } private Statement getStatement (int limit ) throws Exception { Statement stmt = getConnection().createStatement(); if (limit != 0) { stmt.setFetchSize(limit); } return stmt; } /** * Runs a specified SQL Query on the DB connection but in silent mode * Silent mode: just a clean query, no other data changed (for background and long running threads) * Attention: no metadata and paging available in this mode and it does not care about limit checking etc... * and returns a Hashtable containing the different data to preceed * Note: allways use this function to query the DB in clean mode (without changing something in this class! */ synchronized public Hashtable querySilent(String sqlQuery) throws Exception { return querySilentWithLimit(sqlQuery ,0); } /** * Runs a specified SQL Query on the DB connection but in silent mode with rowlimit * Silent mode: just a clean query, no other data changed (for background and long running threads) * Attention: no metadata and paging available in this mode and it does not care about limit checking etc... * and returns a Hashtable containing the different data to preceed * Note: allways use this function to query the DB in clean mode (without changing something in this class! */ synchronized public Hashtable querySilentWithLimit (String sqlQuery,int limit) throws Exception { Statement stmt = getStatement(limit); //System.out.println("DB QUERY (SILENT): " + sqlQuery); ResultSet rs = stmt.executeQuery(sqlQuery ); ResultSetMetaData rsmd = rs.getMetaData(); int cols = rsmd.getColumnCount(); int rowNumber = 0; Vector vector = new Vector (5, 5); Vector collables = new Vector(); //of String Vector colltypes = new Vector(); //of String Vector collsizes = new Vector(); //of Integer Vector collnames = new Vector(); //of String //build collumnvector (with the names of the columns) for(int i=1;i<=cols;i++) { if (stopNOW) { goon(); throw new Exception("Aborted by user."); } collables.add(rsmd.getColumnLabel(i)); colltypes.add(rsmd.getColumnTypeName(i)); collsizes.add(new Integer(rsmd.getColumnDisplaySize(i))); collnames.add(rsmd.getColumnName (i)); } //build rowvector while(rs.next()) { if (stopNOW) { goon(); throw new Exception("Aborted by user."); } rowNumber++; for(int i=1;i<=cols;i++) { if (stopNOW) { goon(); throw new Exception("Aborted by user." ); } vector.add(rs.getString (i)); Autor: Thomas Schädler 103 Anhang A: Quelltext <xmlizer> configurator } } int rows = rowNumber ; String info[][] = new String[cols][rows]; vector.trimToSize(); int row = 0; int col = 0; for(int i=0;i<vector .size();i++) { if (stopNOW) { goon(); throw new Exception("Aborted by user."); } try { info[col][row] = vector .get(i).toString(); } catch(NullPointerException ex) { info[col][row] = ""; } if(col+1 == cols) { col = -1; row++; } col++; } Hashtable result = new Hashtable(); result.put("table",info); result.put("columnname",collnames); result.put("columnsize",collsizes); result.put("columnlabels",collables); result.put("columntypes",colltypes); result.put("rows",new Integer(rows)); result.put("cols",new Integer(cols)); return result; } //QUASI-SECURE PASSWORD HANDLING //----------------------------------------------------------------------------------------------public static String decryptSecurePassword(String encrypted) { //decrpyt StringBuffer decrypted = new StringBuffer (); char[] sec_char = new char[]{'x','m','l','i','z','e','r'}; int inkr = 0; char aktual; StringBuffer current = new StringBuffer(); for (int j=0;j<encrypted.length ();j++) { aktual = encrypted.charAt(j); if (aktual == ':') { if (inkr<sec_char.length-1){inkr++;}else{inkr=0;} String gotcha = current.toString(); current = new StringBuffer(); // renew buffer Integer goti = new Integer(gotcha ); int gotint = goti.intValue(); int decr = gotint ^ sec_char [inkr]; decrypted.append((char)decr); } else { current.append(aktual); } } return decrypted.toString(); } }/* * xmlItem.java * * Created on 16. May 2002, 20:20 * ---------------------------------------------------------------------------* This file is part of <xmlizer>. * * <xmlizer> is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Foobar is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with <xmlizer>; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * ---------------------------------------------------------------------------*/ package configurator; import java.io.*; import java.util.*; /** * This class representates a xml file item consisting of the following stuff * with a get and set method each * * String name * String file * * -> ... every variable has its get ans set methods * * But more important: This class contains d ifferent methods for handling * xml file access and manipulation * @author [email protected] */ public class xmlItem { private String tname; Autor: Thomas Schädler 104 Anhang A: Quelltext <xmlizer> configurator private String tfile; //CONSTRUCTORS //----------------------------------------------------------------------------------------------/** * Constructors for a new xmlItem * -> holds: * String name * String file */ public xmlItem(String name,String file) { this.tname = name; this.tfile = file; } public xmlItem(String name) { this.tname = name; this.tfile = new String(); } public xmlItem() { this.tname = new String(); this.tname = new String(); } //STRING REPRESENTATION //----------------------------------------------------------------------------------------------/** * By default show the key as String */ public String toString() { return this.tname; } //HELPER METHODS //----------------------------------------------------------------------------------------------//GET AND SET METHODS //----------------------------------------------------------------------------------------------/** * Get the name of the dbitem */ public String getName() { return this.tname; } /** * Get the driver of the dbitem */ public String getFile() { return this.tfile; } /** * Set the name of the dbitem */ public void setName(String s) { this.tname = s; } /** * Set the driver of the dbitem */ public void setFile(String s) { this.tfile = s; } } /* * setupWindow.java * * In your module you can easily add mo re schemas or databases, * only the needed ones are loaded at setup * * Created on 11. April 2002, 00:20 * ---------------------------------------------------------------------------* This file is part of <xmlizer>. * * <xmlizer> is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Foobar is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with <xmlizer>; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * ---------------------------------------------------------------------------*/ package configurator; import import import import import import import import import import import java.sql.*; java.util.*; java.lang.*; javax.swing .*; java.io.*; java.lang.reflect.*; org.jdom.*; org.jdom.input.SAXBuilder; org.jdom.output.XMLOutputter; org.w3c.dom.Document; org.xml.sax.SAXException; Autor: Thomas Schädler 105 Anhang A: Quelltext <xmlizer> configurator import org.xml.sax.SAXParseException; import org.xml.sax.helpers.DefaultHandler; import org.apache.xerces.parsers.DOMParser; /** * The setupwindows loads all neccessary stuff: * * - a database connection * - an xml schema * - a module to load * - a projectname * * and finally starts the module * @author [email protected] */ public class setupWindow extends MyInternalFrame { private configurator mother; private String ID; private Vector moduleList; private Vector databaseList; private Vector xmlList; private boolean isNewSetup = true; private boolean isLoading = true; //backup vectors private Vector oldXML; private Vector oldDB; //threads private Thread connecterThread = null; //colors private final java.awt.Color COLOR_RED = java.awt.Color .red; private java.awt.Color COLOR_DEFAULT = new java.awt.Color(102,102,153); //include resolve stuff private String temporary_name = new String(); private org.jdom.Document temporary = null; private Vector includepaths = new Vector (); /** * Creates new form setupWindow */ public setupWindow(configurator mainProgram,String uid) { this.mother = mainProgram; this.ID = uid; this.moduleList = mother.getAvailableModules(); //init this.databaseList = mother .getProjectData ().getDB(); this.xmlList = mother.getProjectData ().getXML(); //backup try { this.oldXML = (Vector)((Vector)mother .getProjectData ().getXML()).clone(); this.oldDB = (Vector)((Vector)mother.getProjectData().getDB()).clone(); } catch(Exception ex) { this.mother .getLog().addDebug(ex); } initComponents(); //remove the 2 panels databasePanel.remove (dbPanel); //databasePanel.add(dbPanel, java.awt.BorderLayout.CENTER); xmlPanel.remove (xmlsubPanel); //xmlPanel.add(xmlsubPanel, java.awt.BorderLayout.CENTER); loadCurrentProjectData(); doCheck(); this.isLoading = false; convertButton.setVisible(false); } /** This method is called from within the constructor to * initialize the form. * WARNING: Do NOT modify this code. The content of this method is * always regenerated by the Form Editor. */ private void initComponents() {//GEN-BEGIN:initComponents backPanel = new javax.swing.JPanel(); mainTabbedPane = new javax .swing.JTabbedPane(); welcomePanel = new javax.swing.JPanel(); welcomeTextArea = new javax.swing.JTextArea(); buttonPanel = new javax.swing.JPanel (); subPanel = new javax .swing .JPanel(); projectnameLabel = new javax.swing.JLabel (); projectnameTextField = new javax.swing.JTextField(); mappingmoduleLabel = new javax.swing .JLabel(); mappingmoduleComboBox = new javax.swing.JComboBox(moduleList); mappingmoduleComboBox.setSelectedIndex(0); moduleInfoButton = new javax.swing.JButton(); sub2Panel = new javax.swing.JPanel(); dbLabel = new javax.swing.JLabel(); db2Label = new javax .swing .JLabel(); finishButton = new javax.swing.JButton(); welcome2Label = new javax.swing .JLabel(); welcomeLabel = new javax.swing.JLabel(); databasePanel = new javax.swing .JPanel(); dboutputTextArea = new javax.swing.JTextArea(); dbListPanel = new javax.swing.JPanel (); dbListLabel = new javax.swing.JLabel (); dbListComboBox = new javax .swing.JComboBox(databaseList); addDBButton = new javax.swing.JButton(); removeDBButton = new javax .swing.JButton(); dbInfoButton = new javax.swing.JButton(); dbPanel = new javax.swing.JPanel(); dbdriverLabel = new javax.swing .JLabel(); dbdriverTextField = new javax.swing.JTextField (); dburlLabel = new javax.swing.JLabel(); Autor: Thomas Schädler 106 Anhang A: Quelltext <xmlizer> configurator dburlTextField = new javax .swing.JTextFie ld(); drivertestButton = new javax.swing.JButton(); dbtimeoutLabel = new javax .swing.JLabel(); dbusernameLabel = new javax.swing.JLabel(); dbusernameTextField = new javax .swing.JTextField(); dbpasswordLabel = new javax.swing.JLabel(); dbpasswordTextField = new javax .swing.JPasswordField(); connectButton = new javax.swing .JButton(); dbtimeoutTextField = new javax.swing .JTextField(); connameTextField = new javax.swing.JTextField(); connameLabel = new javax.swing.JLabel(); addNewDBButton = new javax .swing.JButton(); jLabel4 = new javax.swing.JLabel(); dbBrowseButton = new javax .swing.JButton(); xmlPanel = new javax .swing .JPanel(); xmlsubPanel = new javax.swing.JPanel (); xmlchooserPanel = new javax.swing.JPanel(); filenameLabel = new javax.swing .JLabel(); filenameTextField = new javax.swing.JTextField (); filechooserButton = new javax.swing.JButton(); fileidentifierTextField = new javax.swing .JTextField(); fileidentifierLabel = new javax .swing.JLabel(); validatePanel = new javax.swing .JPanel(); validateLabel = new javax.swing .JLabel(); validateButton = new javax .swing.JButton(); addNewXMLButton = new javax.swing.JButton(); hintXMLLabel = new javax.swing.JLabel(); convertButton = new javax.swing .JButton(); outputTextArea = new javax .swing.JTextArea(); xmlListPanel = new javax.swing.JPanel(); xmlListLabel = new javax.swing.JLabel(); xmlListComboBox = new javax.swing.JComboBox(xmlList); addXMLButton = new javax.swing.JButton(); removeXMLButton = new javax.swing.JButton(); xmlInfoButton = new javax.swing .JButton(); setTitle("Project Setup"); setIconifiable(true); setClosable(true); setPreferredSize(new java.awt.Dimension(450, 500)); setMinimumSize(new java.awt.Dimension(450, 500)); addInternalFrameListener(new javax.swing.event .InternalFrameListener() { public void internalFrameOpened(javax .swing.event.InternalFrameEvent evt ) { } public void internalFrameClosing (javax.swing.event.InternalFrameEvent evt) { formInternalFrameClosing(evt); } public void internalFrameClosed(javax .swing.event.InternalFrameEvent evt ) { } public void internalFrameIconified(javax.swing.event .InternalFrameEvent evt) { } public void internalFrameDeiconified(javax .swing.event.InternalFrameEvent evt ) { } public void internalFrameActivated(javax.swing.event .InternalFrameEvent evt) { } public void internalFrameDeactivated(javax .swing.event.InternalFrameEvent evt ) { } }); backPanel.setLayout(new java.awt.BorderLayout()); backPanel.setPreferredSize (new java.awt.Dimension(450, 500)); backPanel.setMinimumSize(new java.awt.Dimension(450, 500)); mainTabbedPane.setPreferredSize (new java.awt.Dimension(450, 520)); mainTabbedPane.setMinimumSize(new java.awt.Dimension(450, 520)); welcomePanel.setLayout(new java.awt.BorderLayout(0, 10)); welcomePanel.setPreferredSize(new java.awt.Dimension(431, 387)); welcomePanel.setName("Welcome"); welcomePanel.setMinimumSize(new java.awt.Dimension(431, 387)); welcomeTextArea .setEditable(false); welcomeTextArea .setText("Welcome to <xmlizer> configurator\n\n1. Type in a name for your new project and\nchoose a mapping module from the list.\n\n2. Use the <<Database Setup>> Tab to set up\none or more working database connections.\n\n3. Depending on the module you use, you can\nadd XML schemas or DTDs. DTDs have to be\nconverted to XML schema and a schema has to\nbe well-formed. Use the <<XML Setup>> Tab.\n\n4. Come back to the <<Welcome>> Tab and \n<<Finish Setup>> if everything is set up correctly.\n(all lightbulbs must be ON to finish)"); welcomeTextArea .setBackground(new java.awt.Color(204, 204, 204)); welcomeTextArea .setMargin(new java.awt.Insets(20, 20, 20, 20)); welcomePanel.add(welcomeTextArea, java.awt.BorderLayout.CENTER); buttonPanel.setLayout(new java.awt.BorderLayout(30, 30)); subPanel.setLayout(new java.awt.GridBagLayout()); java.awt.GridBagConstraints gridBagConstraints1; projectnameLabel.setText("Project Name:"); projectnameLabel.setMinimumSize (new java.awt.Dimension(90, 21)); projectnameLabel.setMaximumSize (new java.awt.Dimension(90, 21)); gridBagConstraints1 = new java.awt.GridBagConstraints(); gridBagConstraints1.gridx = 0; gridBagConstraints1.gridy = 0; gridBagConstraints1.ipadx = 17; gridBagConstraints1.anchor = java.awt.GridBagConstraints .WEST; subPanel.add(projectnameLabel, gridBagConstraints1); projectnameTextField .setText("defaultprojectname"); projectnameTextField .setPreferredSize(new java.awt.Dimension(300, 21)); projectnameTextField .setNextFocusableComponent (mappingmoduleComboBox); projectnameTextField .addActionListener(new java.awt.event.ActionListener() { public void actionPerformed (java.awt.event .ActionEvent evt) { projectnameTextFieldActionPerformed(evt); } }); gridBagConstraints1 = new java.awt.GridBagConstraints(); Autor: Thomas Schädler 107 Anhang A: Quelltext <xmlizer> configurator gridBagConstraints1.gridx = 0; gridBagConstraints1.gridy = 1; gridBagConstraints1.gridwidth = 3; gridBagConstraints1.fill = java.awt.GridBagConstraints.HORIZONTAL; gridBagConstraints1.anchor = java.awt.GridBagConstraints .WEST; subPanel.add(projectnameTextField, gridBagConstraints1); mappingmoduleLabel.setText ("Mapping Module:"); mappingmoduleLabel.setMinimumSize(new java.awt.Dimension (90, 21)); mappingmoduleLabel.setMaximumSize(new java.awt.Dimension (90, 21)); gridBagConstraints1 = new java.awt.GridBagConstraints(); gridBagConstraints1.gridx = 0; gridBagConstraints1.gridy = 2; gridBagConstraints1.anchor = java.awt.GridBagConstraints .WEST; subPanel.add(mappingmoduleLabel, gridBagConstraints1); mappingmoduleComboBox.setPreferredSize(new java.awt.Dimension (240, 27)); mappingmoduleComboBox.setMinimumSize (new java.awt.Dimension(126, 27)); mappingmoduleComboBox.setMaximumSize (new java.awt.Dimension(32767, 27)); gridBagConstraints1 = new java.awt.GridBagConstraints(); gridBagConstraints1.gridx = 0; gridBagConstraints1.gridy = 3; gridBagConstraints1.gridwidth = 2; gridBagConstraints1.fill = java.awt.GridBagConstraints.HORIZONTAL; gridBagConstraints1.anchor = java.awt.GridBagConstraints .WEST; subPanel.add(mappingmoduleComboBox, gridBagConstraints1); moduleInfoButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/configurator/icons/Help16.gif"))); moduleInfoButton.setToolTipText ("Open Help"); moduleInfoButton.setFont(new java.awt.Font("Dialog" , 0, 10)); moduleInfoButton.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed (java.awt.event .ActionEvent evt) { moduleInfoButtonActionPerformed(evt); } }); gridBagConstraints1 = new java.awt.GridBagConstraints(); gridBagConstraints1.gridx = 2; gridBagConstraints1.gridy = 3; gridBagConstraints1.anchor = java.awt.GridBagConstraints .EAST; subPanel.add(moduleInfoButton, gridBagConstraints1); buttonPanel.add(subPanel, java.awt.BorderLayout.CENTER); sub2Panel.setLayout(new java.awt.GridBagLayout ()); java.awt.GridBagConstraints gridBagConstraints2; dbLabel.setIcon(new javax.swing .ImageIcon (getClass().getResource("/configurator/icons/TipOfTheDay24.gif"))); dbLabel.setEnabled(false); gridBagConstraints2 = new java.awt.GridBagConstraints(); gridBagConstraints2.gridx = 1; gridBagConstraints2.gridy = 0; sub2Panel.add(dbLabel, gridBagConstraints2); db2Label.setText("Database OK"); gridBagConstraints2 = new java.awt.GridBagConstraints(); gridBagConstraints2.gridx = 1; gridBagConstraints2.gridy = 1; gridBagConstraints2.insets = new java.awt.Insets(0, 5, 0, 5); sub2Panel.add(db2Label, gridBagConstraints2); finishButton.setText("Finish Setup"); finishButton.setEnabled(false); finishButton.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed (java.awt.event .ActionEvent evt) { finishButtonActionPerformed(evt); } }); gridBagConstraints2 = new java.awt.GridBagConstraints(); gridBagConstraints2.gridx = 0; gridBagConstraints2.gridy = 2; gridBagConstraints2.gridwidth = 2; gridBagConstraints2.insets = new java.awt.Insets(10, 0, 10, 0); sub2Panel.add(finishButton , gridBagConstraints2); welcome2Label.setText("Welcome OK"); gridBagConstraints2 = new java.awt.GridBagConstraints(); gridBagConstraints2.gridx = 0; gridBagConstraints2.gridy = 1; gridBagConstraints2.insets = new java.awt.Insets(0, 5, 0, 5); sub2Panel.add(welcome2Label, gridBagConstraints2); welcomeLabel.setIcon(new javax.swing .ImageIcon (getClass().getResource("/configurator/icons/TipOfTheDay24.gif"))); welcomeLabel.setEnabled(false); gridBagConstraints2 = new java.awt.GridBagConstraints(); gridBagConstraints2.gridx = 0; gridBagCon straints2.gridy = 0; sub2Panel.add(welcomeLabel , gridBagConstraints2); buttonPanel.add(sub2Panel, java.awt.BorderLayout.SOUTH); welcomePanel.add(buttonPanel, java.awt.BorderLayout .SOUTH); mainTabbedPane.addTab("Welcome" , welcomePanel); databasePanel.setLayout(new java.awt.BorderLayout()); databasePanel.setPreferredSize(new java.awt.Dimension(431, 387)); dboutputTextArea.setWrapStyleWord(true); dboutputTextArea.setToolTipText ("Shows messages"); dboutputTextArea.setLineWrap(true); dboutputTextArea.setEditable(false); dboutputTextArea.setTabSize(4); dboutputTextArea.setRows(3); Autor: Thomas Schädler 108 Anhang A: Quelltext <xmlizer> configurator dboutputTextArea.setForeground(java.awt.Color.red); dboutputTextArea.setBackground(new java.awt.Color(204, 204, 204)); dboutputTextArea.setPreferredSize(new java.awt.Dimension (10, 51)); dboutputTextArea.setMargin (new java.awt.Insets (10, 5, 5, 10)); dboutputTextArea.setMinimumSize (new java.awt.Dimension(10, 80)); databasePanel.add(dboutputTextArea, java.awt.BorderLayout.SOUTH); dbListPanel.setLayout(new java.awt.GridBagLayout()); java.awt.GridBagConstraints gridBagConstraints3; dbListLabel.setText("Connection List:"); gridBagConstraints3 = new java.awt.GridBagConstraints(); dbListPanel.add(dbListLabel, gridBagConstraints3); dbListComboBox.setPreferredSize (new java.awt.Dimension(240, 27)); dbListComboBox.setMinimumSize(new java.awt.Dimension(126, 27)); dbListComboBox.setMaximumSize(new java.awt.Dimension(32767, 27)); dbListComboBox.addActionListener(new java.awt.event .ActionListener () { public void actionPerformed (java.awt.event .ActionEvent evt) { dbListComboBoxActionPerformed(evt); } }); gridBagConstraints3 = new java.awt.GridBagConstraints(); gridBagConstraints3.gridwidth = 4; gridBagConstraints3.insets = new java.awt.Insets(0, 0, 4, 0); dbListPanel.add(dbListComboBox, gridBagConstraints3 ); addDBButton.setToolTipText ("Add a new connection"); addDBButton.setText("Add"); addDBButton.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed (java.awt.event .ActionEvent evt) { addDBButtonActionPerformed(evt); } }); gridBagConstraints3 = new java.awt.GridBagConstraints(); gridBagConstraints3.gridx = 1; gridBagConstraints3.gridy = 1; gridBagConstraints3.insets = new java.awt.Insets(0, 0, 0, 4); dbListPanel.add(addDBButton, gridBagConstraints3); removeDBButton.setToolTipText("Removes the currently selected connection"); removeDBButton.setText("Remove" ); removeDBButton.setEnabled(false ); removeDBButton.addActionListener(new java.awt.event .ActionListener () { public void actionPerformed(java.awt.event .ActionEvent evt) { removeDBButtonActionPerformed(evt); } }); gridBagConstraints3 = new java.awt.GridBagConstraints(); gridBagConstraints3.gridx = 2; gridBagConstraints3.gridy = 1; gridBagConstraints3.insets = new java.awt.Insets(0, 4, 0, 0); dbListPanel.add(removeDBButton, gridBagConstraints3 ); dbInfoButton.setIcon(new javax.swing .ImageIcon (getClass().getResource("/configurator/icons/Help16.gif"))); dbInfoButton.setToolTipText("Open Help"); dbInfoButton.setFont(new java.awt.Font("Dialog", 0, 10)); dbInfoButton.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed (java.awt.event.ActionEvent evt) { dbInfoButtonActionPerformed(evt); } }); gridBagConstraints3 = new java.awt.GridBagConstraints(); gridBagConstraints3.gridx = 4; gridBagConstraints3.gridy = 1; gridBagConstraints3.anchor = java.awt.GridBagConstraints .EAST; dbListPanel.add(dbInfoButton, gridBagConstraints3); databasePanel.add(dbListPanel, java.awt.BorderLayout.NORTH); dbPanel.setLayout(new java.awt.GridBagLayout()); java.awt.GridBagConstraints gridBagConstraints4; dbdriverLabel.setText("Driver Name:" ); gridBagConstraints4 = new java.awt.GridBagConstraints(); gridBagConstraints4.gridx = 0; gridBagConstraints4.gridy = 2; gridBagConstraints4.anchor = java.awt.GridBagConstraints .WEST; dbPanel.add(dbdriverLabel, gridBagConstraints4 ); dbdriverTextField.setPreferredSize(new java.awt.Dimension(300, 21)); dbdriverTextField.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed (java.awt.event .ActionEvent evt) { dbdriverTextFieldActionPerformed(evt); } }); gridBagConstraints4 = new java.awt.GridBagConstraints(); gridBagConstraints4.gridx = 0; gridBagConstraints4.gridy = 3; gridBagConstraints4.gridwidth = 3; gridBagConstraints4.fill = java.awt.GridBagConstraints.HORIZONTAL; dbPanel.add(dbdriverTextField, gridBagConstraints4); dburlLabel .setText("Database URL:"); gridBagConstraints4 = new java.awt.GridBagConstraints(); gridBagConstraints4.gridx = 0; gridBagConstraints4.gridy = 4; gridBagConstraints4.anchor = java.awt.GridBagConstraints .WEST; dbPanel.add(dburlLabel, gridBagConstraints4); Autor: Thomas Schädler 109 Anhang A: Quelltext <xmlizer> configurator dburlTextField.setPreferredSize (new java.awt.Dimension(300, 21)); dburlTextField.addActionListener(new java.awt.event .ActionListener () { public void actionPerformed (java.awt.event .ActionEvent evt) { dburlTextFieldActionPerformed(evt); } }); gridBagConstraints4 = new java.awt.GridBagConstraints(); gridBagConstraints4.gridx = 0; gridBagConstraints4.gridy = 5; gridBagConstraints4.gridwidth = 3; gridBagConstraints4.fill = java.awt.GridBagConstraints.HORIZONTAL; gridBagConstraints4.anchor = java.awt.GridBagConstraints .WEST; dbPanel.add(dburlTextField , gridBagConstraints4); drivertestButton.setIcon(new javax.swing.ImageIcon("")); drivertestButton.setText("Test" ); drivertestButton.setPreferredSize(new java.awt.Dimension (79, 27)); drivertestButton.setMaximumSize (new java.awt.Dimension(79, 27)); drivertestButton.setMargin (new java.awt.Insets (0, 0, 0, 0)); drivertestButton.setMinimumSize (new java.awt.Dimension(79, 27)); drivertestButton.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed (java.awt.event .ActionEvent evt) { drivertestButtonActionPerformed(evt); } }); gridBagConstraints4 = new java.awt.GridBagConstraints(); gridBagConstraints4.gridx = 2; gridBagConstraints4.gridy = 4; gridBagConstraints4.anchor = java.awt.GridBagConstraints .EAST; dbPanel.add(drivertestButton, gridBagConstraints4); dbtimeoutLabel.setText("Timeout (s):"); gridBagConstraints4 = new java.awt.GridBagConstraints(); gridBagConstraints4.gridx = 0; gridBagConstraints4.gridy = 6; gridBagConstraints4.anchor = java.awt.GridBagConstraints .WEST; dbPanel.add(dbtimeoutLabel , gridBagConstraints4); dbusernameLabel .setText("Username:"); gridBagConstraints4 = new java.awt.GridBagConstraints(); gridBagConstraints4.gridx = 0; gridBagConstraints4.gridy = 8; gridBagConstraints4.anchor = java.awt.GridBagConstraints .WEST; dbPanel.add(dbusernameLabel, gridBagConstraints4); dbusernameTextField.setPreferredSize (new java.awt.Dimension(300, 21)); dbusernameTextField.addActionListener(new java.awt.event .ActionListener () { public void actionPerformed (java.awt.event .ActionEvent evt) { dbusernameTextFieldActionPerformed(evt); } }); gridBagConstraints4 = new java.awt.GridBagConstraints(); gridBagConstraints4.gridx = 0; gridBagConstraints4.gridy = 9; gridBagConstraints4.gridwidth = 3; gridBagConstraints4.fill = java.awt.GridBagConstraints.HORIZONTAL; dbPanel.add(dbusernameTextField , gridBagConstraints4); dbpasswordLabel .setText("Password:"); gridBagConstraints4 = new java.awt.GridBagConstraints(); gridBagConstraints4.gridx = 0; gridBagConstraints4.gridy = 10; gridBagConstraints4.anchor = java.awt.GridBagConstraints .WEST; dbPanel.add(dbpasswordLabel, gridBagConstraints4); dbpasswordTextField.setPreferredSize (new java.awt.Dimension(300, 21)); gridBagConstraints4 = new java.awt.GridBagConstraints(); gridBagConstraints4.gridx = 0; gridBagConstraints4.gridy = 11; gridBagConstraints4.gridwidth = 3; gridBagConstraints4.fill = java.awt.GridBagConstraints.HORIZONTAL; dbPanel.add(dbpasswordTextField , gridBagConstraints4); connectButton.setIcon(new javax .swing.ImageIcon("")); connectButton.setToolTipText("Try to connect to selected Database" ); connectButton.setText("Connect" ); connectButton.setPreferredSize(new java.awt.Dimension(79, 27)); connectButton.setMaximumSize(new java.awt.Dimension (79, 27)); connectButton.setMargin(new java.awt.Insets(0, 0, 0, 0)); connectButton.setMinimumSize(new java.awt.Dimension (79, 27)); connectButton.setEnabled(false); connectButton.addActionListener (new java.awt.event.ActionListener() { public void actionPerformed (java.awt.event .ActionEvent evt) { connectButtonActionPerformed (evt); } }); gridBagConstraints4 = new java.awt.GridBagConstraints(); gridBagConstraints4.gridx = 1; gridBagConstraints4.gridy = 13; gridBagConstraints4.anchor = java.awt.GridBagConstraints .EAST; dbPanel.add(connectButton, gridBagConstraints4 ); dbtimeoutTextField.setPreferredSize(new java.awt.Dimension(300, 21)); dbtimeoutTextField.addActionListener (new java.awt.event.ActionListener() { public void actionPerformed (java.awt.event .ActionEvent evt) { dbtimeoutTextFieldActionPerformed (evt); } }); gridBagConstraints4 = new java.awt.GridBagConstraints(); gridBagConstraints4.gridx = 0; Autor: Thomas Schädler 110 Anhang A: Quelltext <xmlizer> configurator gridBagConstraints4.gridy = 7; gridBagConstraints4.gridwidth = 3; gridBagConstraints4.fill = java.awt.GridBagConstraints.HORIZONTAL; dbPanel.add(dbtimeoutTextField, gridBagConstraints4 ); connameTextField.setPreferredSize(new java.awt.Dimension (300, 21)); connameTextField.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed (java.awt.event .ActionEvent evt) { connameTextFieldActionPerformed(evt); } }); gridBagConstraints4 = new java.awt.GridBagConstraints(); gridBagConstraints4.gridx = 0; gridBagConstraints4.gridy = 1; gridBagConstraints4.gridwidth = 3; gridBagConstraints4.fill = java.awt.GridBagConstraints.HORIZONTAL; dbPanel.add(connameTextField, gridBagConstraints4); connameLabel.setText("Connection Name:"); gridBagConstraints4 = new java.awt.GridBagConstraints(); gridBagConstraints4.gridx = 0; gridBagConstraints4.gridy = 0; gridBagConstraints4.anchor = java.awt.GridBagConstraints .WEST; dbPanel.add(connameLabel, gridBagConstraints4); addNewDBButton.setToolTipText("Adds this connection to the connection list"); addNewDBButton.setText("Save"); addNewDBButton.setPreferredSize (new java.awt.Dimension(79, 27)); addNewDBButton.setMaximumSize(new java.awt.Dimension(79, 27)); addNewDBButton.setMargin(new java.awt.Insets(0, 0, 0, 0)); addNewDBButton.setMinimumSize(new java.awt.Dimension(79, 27)); addNewDBButton.setEnabled(false ); addNewDBButton.addActionListener(new java.awt.event .ActionListener () { public void actionPerformed (java.awt.event .ActionEvent evt) { addNewDBButtonActionPerformed(evt); } }); gridBagConstraints4 = new java.awt.GridBagConstraints(); gridBagConstraints4.gridx = 2; gridBagConstraints4.gridy = 14; gridBagConstraints4.anchor = java.awt.GridBagConstraints .EAST; dbPanel.add(addNewDBButton , gridBagConstraints4); jLabel4.setText("Add the Connection to the List >> "); gridBagConstraints4 = new java.awt.GridBagConstraints(); gridBagConstraints4.gridx = 0; gridBagConstraints4.gridy = 14; gridBagConstraints4.gridwidth = 2; gridBagConstraints4.anchor = java.awt.GridBagConstraints .EAST; dbPanel.add(jLabel4, gridBagConstraints4); dbBrowseButton.setToolTipText("Open a database browser"); dbBrowseButton.setText("Browse" ); dbBrowseBu tton.setPreferredSize (new java.awt.Dimension(79, 27)); dbBrowseButton.setMaximumSize(new java.awt.Dimension(79, 27)); dbBrowseButton.setMargin(new java.awt.Insets(0, 0, 0, 0)); dbBrowseButton.setMinimumSize(new java.awt.Dimension(79, 27)); dbBrowseButton.setEnabled(false ); dbBrowseButton.addActionListener(new java.awt.event .ActionListener () { public void actionPerformed (java.awt.event .ActionEvent evt) { dbBrowseButtonActionPerformed(evt); } }); gridBagConstraints4 = new java.awt.GridBagConstraints(); gridBagConstraints4.gridx = 2; gridBagConstraints4.gridy = 13; gridBagConstraints4.anchor = java.awt.GridBagConstraints .EAST; dbPanel.add(dbBrowseButton , gridBagConstraints4); databasePanel.add(dbPanel, java.awt.BorderLayout.CENTER); mainTabbedPane.addTab("Database Setup", databasePanel); xmlPanel.setLayout(new java.awt.BorderLayout()); xmlsubPanel.setLayout(new java.awt.GridLayout(2, 1)); xmlchooserPanel .setLayout(new java.awt.GridBagLayout()); java.awt.GridBagConstraints gridBagConstraints5; filenameLabel.setText("Load XML Schema or a DTD: " ); gridBagConstraints5 = new java.awt.GridBagConstraints(); gridBagConstraints5.gridx = 0; gridBagConstraints5.gridy = 0; gridBagConstraints5.anchor = java.awt.GridBagConstraints .WEST; xmlchooserPanel.add(filenameLabel, gridBagConstraints5); filenameTextField.setPreferredSize(new java.awt.Dimension(300, 21)); filenameTextField.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed (java.awt.event .ActionEvent evt) { filenameTextFieldActionPerformed(evt); } }); gridBagConstraints5 = new java.awt.GridBagConstraints(); gridBagConstraints5.gridx = 0; gridBagConstraints5.gridy = 1; gridBagConstraints5.gridwidth = 2; gridBagConstraints5.fill = java.awt.GridBagConstraints.HORIZONTAL; xmlchooserPanel .add(filenameTextField, gridBagConstraints5); filechooserButton.setText("Choose..."); Autor: Thomas Schädler 111 Anhang A: Quelltext <xmlizer> configurator filechooserButton.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed (java.awt.event .ActionEvent evt) { filechooserButtonActionPerformed(evt); } }); gridBagConstraints5 = new java.awt.GridBagConstraints(); gridBagConstraints5.gridx = 1; gridBagConstraints5.gridy = 0; gridBagConstraints5.anchor = java.awt.GridBagConstraints .EAST; xmlchooserPanel .add(filechooserButton, gridBagConstraints5); fileidentifierTextField.setPreferredSize(new java.awt.Dimension(300, 21)); fileidentifierTextField.addActionListener (new java.awt.event.ActionListener() { public void actionPerformed (java.awt.event .ActionEvent evt) { fileidentifierTextFieldActionPerformed (evt); } }); gridBagConstraints5 = new java.awt.GridBagConstraints(); gridBagConstraints5.gridx = 0; gridBagConstraints5.gridy = 3; gridBagConstraints5.gridwidth = 2; gridBagConstraints5.fill = java.awt.GridBagConstraints.HORIZONTAL; xmlchooserPanel .add(fileidentifierTextField, gridBagConstraints5); fileidentifierLabel.setText("File Name:"); gridBagConstraints5 = new java.awt.GridBagConstraints(); gridBagConstraints5.gridx = 0; gridBagConstraints5.gridy = 2; gridBagConstraints5.anchor = java.awt.GridBagConstraints .WEST; xmlchooserPanel .add(fileidentifierLabel, gridBagConstraints5); xmlsubPanel.add(xmlchooserPanel ); validatePanel.setLayout(new java.awt.GridBagLayout()); java.awt.GridBagConstraints gridBagConstraints6; validateLabel.setText("Check the XML Schema : "); gridBagConstraints6 = new java.awt.GridBagConstraints(); gridBagConstraints6.gridx = 0; gridBagConstraints6.gridy = 1; validatePanel.add(validateLabel , gridBagConstraints6); validateButton.setText("Check"); validateButton.setEnabled(false ); validateButton.addActionListener(new java.awt.event .ActionListener () { public void actionPerformed (java.awt.event .ActionEvent evt) { validateButtonActionPerformed(evt); } }); gridBagConstraints6 = new java.awt.GridBagConstraints(); gridBagConstraints6.gridx = 1; gridBagConstraints6.gridy = 1; validatePanel.add(validateButton, gridBagConstraints6); addNewXMLButton .setToolTipText("Adds this file to the file list"); addNewXMLButton .setText("Save"); addNewXMLButton .setEnabled (false); addNewXMLButton .addActionListener(new java.awt.event.ActionListener() { public void actionPerformed (java.awt.event .ActionEvent evt) { addNewXMLButtonActionPerformed(evt); } }); gridBagConstraints6 = new java.awt.GridBagConstraints(); gridBagConstraints6.gridx = 1; gridBagConstraints6.gridy = 2; gridBagConstraints6.fill = java.awt.GridBagConstraints.HORIZONTAL; validatePanel.add(addNewXMLButton, gridBagConstraints6); hintXMLLabel.setText("Add the File to the List >> " ); gridBagConstraints6 = new java.awt.GridBagConstraints(); gridBagConstraints6.gridx = 0; gridBagConstraints6.gridy = 2; validatePanel.add(hintXMLLabel, gridBagConstraints6 ); convertButton.setText("Convert DTD to XML Sche ma"); convertButton.addActionListener (new java.awt.event.ActionListener() { public void actionPerformed (java.awt.event .ActionEvent evt) { convertButtonActionPerformed (evt); } }); gridBagConstraints6 = new java.awt.GridBagConstraints(); gridBagConstraints6.gridx = 0; gridBagConstraints6.gridy = 0; gridBagConstraints6.gridwidth = 2; validatePanel.add(convertButton , gridBagConstraints6); xmlsubPanel.add(validatePanel); xmlPanel.add(xmlsubPanel, java.awt.BorderLayout.CENTER); outputTextArea.setWrapStyleWord (true); outputTextArea.setToolTipText("Shows messages" ); outputTextArea.setLineWrap (true); outputTextArea.setEditable (false); outputTextArea.setTabSize(4); outputTextArea.setRows(3); outputTextArea.setForeground(java.awt.Color.red); outputTextArea.setBackground(new java.awt.Color(204, 204, 204)); outputTextArea.setPreferredSize (new java.awt.Dimension(10, 51)); outputTextArea.setMargin(new java.awt.Insets(10, 5, 5, 10)); Autor: Thomas Schädler 112 Anhang A: Quelltext <xmlizer> configurator outputTextArea.setMinimumSize(new java.awt.Dimension(10, 80)); xmlPanel.add(outputTextArea, java.awt.BorderLayout.SOUTH ); xmlListPanel.setLayout(new java.awt.GridBagLayout()); java.awt.GridBagConstraints gridBagConstraints7; xmlListLabel.setText("File List:"); gridBagConstraints7 = new java.awt.GridBagConstraints(); xmlListPanel.add(xmlListLabel, gridBagConstraints7); xmlListComboBox .setPreferredSize(new java.awt.Dimension(240, 27)); xmlListComboBox .setMinimumSize(new java.awt.Dimension(126, 27)); xmlListComboBox .setMaximumSize(new java.awt.Dimension(32767, 27)); xmlListComboBox .addActionListener(new java.awt.event.ActionListener() { public void actionPerformed (java.awt.event .ActionEvent evt) { xmlListComboBoxActionPerformed(evt); } }); gridBagConstraints7 = new java.awt.GridBagConstraints(); gridBagConstraints7.gridwidth = 3; gridBagConstraints7.insets = new java.awt.Insets(0, 0, 4, 0); xmlListPanel.add(xmlListComboBox, gridBagConstraints7); addXMLButton.setToolTipText("Add a new file to the list" ); addXMLButton.setText("Add" ); addXMLButton.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed (java.awt.event .ActionEvent evt) { addXMLButtonActionPerformed(evt); } }); gridBagConstraints7 = new java.awt.GridBagConstraints(); gridBagConstraints7.gridx = 1; gridBagConstraints7.gridy = 1; gridBagConstraints7.insets = new java.awt.Insets(0, 0, 0, 4); xmlListPanel.add(addXMLButton, gridBagConstraints7); removeXMLButton .setToolTipText("Removes the currently selected file"); removeXMLButton .setText("Remove"); removeXMLButton .setEnabled (false); removeXMLButton .addActionListener(new java.awt.event.ActionListener() { public void actionPerformed (java.awt.event .ActionEvent evt) { removeXMLButtonActionPerformed(evt); } }); gridBagConstraints7 = new java.awt.GridBagConstraints(); gridBagConstraints7.gridx = 2; gridBagConstraints7.gridy = 1; gridBagConstraints7.insets = new java.awt.Insets(0, 4, 0, 4); xmlListPanel.add(removeXMLButton, gridBagConstraints7); xmlInfoButton.setIcon(new javax .swing.ImageIcon(getClass ().getResource("/configurator/icons/Help16.gif"))); xmlInfoButton.setToolTipText("Open Help"); xmlInfoButton.setFont(new java.awt.Font("Dialog", 0, 10)); xmlInfoButton.addActionListener (new java.awt.event.ActionListener() { public void actionPerformed (java.awt.event .ActionEvent evt) { xmlInfoButtonActionPerformed (evt); } }); gridBagConstraints7 = new java.awt.GridBagConstraints(); gridBagConstraints7.gridx = 3; gridBagConstraints7.gridy = 1; gridBagConstraints7.anchor = java.awt.GridBagConstraints .EAST; xmlListPanel.add(xmlInfoButton, gridBagConstraints7 ); xmlPanel.add(xmlListPanel, java.awt.BorderLayout.NORTH); mainTabbedPane.addTab("XML Setup", xmlPanel); backPanel.add(mainTabbedPane, java.awt.BorderLayout .CENTER); getContentPane().add(backPanel, java.awt.BorderLayout.CENTER); pack(); }//GEN-END:initComponents private void convertButtonActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_convertButtonActionP erformed {//GEN-HEADEREND:event_convertButtonActionPerformed // Add your handling code here: ConvertDTD2XMLSchema (); }//GEN-LAST:event_convertButtonActionPerformed private void formInternalFrameClosing(javax.swing.event .InternalFrameEvent evt)//GEN-FIRST:event_formInternalFrameClosing {//GEN-HEADEREND:event_formInternalFrameClosing // Add your handling code here: if (isNewSetup) { mother .close(this.ID); mother .resetToDefault(); } else { //redo mother .getProjectData().setDB(oldDB); mother .getProjectData().setXML(oldXML ); mother .getProjectData().save(); //clean the dirty bit //exit doExit (); } }//GEN-LAST:event_formInternalFrameClosing private void dbBrowseButtonActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_dbBrowseButtonActionPerformed Autor: Thomas Schädler 113 Anhang A: Quelltext <xmlizer> configurator {//GEN-HEADEREND:event_dbBrowseButtonActionPerformed // Add your handling code here: dbItem thisDB = new dbItem (); thisDB.setName(connameTextField .getText()); thisDB.setDriver(dbdriverTextField.getText()); thisDB.setUrl(dburlTextField.getText()); thisDB.setTimeout(dbtimeoutTextField .getText()); thisDB.setUsername(dbusernameTextField.getText()); thisDB.setPassword(getSecurePassword ()); //secure pw handling mother.nextDBToBrowse.removeAllElements(); mother.nextDBToBrowse.add(thisDB); mother.open("sdatabaseBrowser"); }//GEN-LAST:event_dbBrowseButtonActionPerformed private void fileidentifierTextFieldActionPerformed(java.awt.event.ActionEvent evt)//GENFIRST:event_fileidentifierTextFieldActionPerformed {//GEN-HEADEREND:event_fileidentifierTextFieldActionPerformed // Add your handling code here: doXMLCheck (); }//GEN-LAST:event_fileidentifierTextFieldActionPerformed private void xmlInfoButtonActionPerformed(java.awt.event.ActionEv ent evt)//GEN-FIRST:event_xmlInfoButtonActionPerformed {//GEN-HEADEREND:event_xmlInfoButtonActionPerformed // Add your handling code here: helpWindow help = (helpWindow)mother .open("help"); help.loadPage("/configurator/help/setup_xml.html"); }//GEN-LAST:event_xmlInfoButtonActionPerformed private void dbInfoButtonActionPerformed (java.awt.event .ActionEvent evt)//GEN-FIRST:event_dbInfoButtonActionPerformed {//GEN-HEADEREND:event_dbInfoButtonActionPerformed // Add your handling code here: helpWindow help = (helpWindow)mother .open("help"); help.loadPage("/configurator/help/setup_database.html"); }//GEN-LAST:event_dbInfoButtonActionPerformed private void moduleInfoButtonActionPerformed(java.awt.event.ActionEvent evt )//GENFIRST:event_moduleInfoButtonActionPerformed {//GEN-HEADEREND:event_moduleInfoButtonActionPerformed // Add your handling code here: String helpinfo = null; String selected = (String)mappingmoduleComboBox.getSelectedItem(); if (selected.equalsIgnoreCase("Simple DB Export")) { helpinfo = "smdbe"; } else if (selected.equalsIgnoreCase("Database to XML")) { helpinfo = "db2xml"; } if (helpinfo != null) { //open the help-browser (Swing HTML) helpWindow help = (helpWindow)mother.open("help"); help.loadPage("/configurator/help/module_" + helpinfo + ".html"); } }//GEN-LAST:event_moduleInfoButtonActionPerformed private void filenameTextFieldActionPerformed (java.awt.event .ActionEvent evt)//GENFIRST:event_filenameTextFieldActionPerformed {//GEN-HEADEREND:event_filenameTextFieldActionPerformed // Add your handling code here: doXMLCheck (); }//GEN-LAST:event_filenameTextFieldActionPerformed private void removeDBButtonActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_removeDBButtonActionPerformed {//GEN-HEADEREND:event_removeDBButtonActionPerformed // Add your handling code here: dbItem toRemove = (dbItem)dbListComboBox.getSelectedItem (); if (toRemove != null) { dbListComboBox.removeItem(toRemove); databasePanel.remove(dbPanel); //databasePanel.add(dbPanel, java.awt.BorderLayout.CENTER); dboutputTextArea .setText(toRemove + " removed!" ); mother .getProjectData().setDirty (); mainTabbedPane.repaint (); doCheck(); } }//GEN-LAST:event_removeDBButtonActionPerformed private void removeXMLButtonActionPerformed(java.awt.event.ActionEvent evt)//GEN FIRST:event_removeXMLButtonActionPerformed {//GEN-HEADEREND:event_removeXMLButtonActionPerformed // Add your handling code here: xmlItem toRemove = (xmlItem)xmlListComboBox.getSelectedItem(); if (toRemove != null) { xmlListComboBox.removeItem(toRemove); xmlPanel.remove(xmlsubPanel ); //xmlPanel.add(xmlsubPanel, java.awt.BorderLayout.CENTER); java.io.File temp = new File(mother.getProjectBase() + mother.getFileSeparator() + projectnameTextField .getText() + mother .getFileSeparator() + toRemove.getFile()); if (temp.exists()) { temp.delete(); } outputTextArea.setText (toRemove + " removed!"); mother .getProjectData().setDirty (); mainTabbedPane.repaint (); doCheck(); } }//GEN-LAST:event_removeXMLButtonActionPerformed private void connameTextFieldActionPerformed(java.awt.event.ActionEvent evt )//GENFIRST:event_connameTextFieldActionPerformed {//GEN-HEADEREND:event_connameTextFieldActionPerformed // Add your handling code here: doDatabaseCheck (); }//GEN-LAST:event_connameTextFieldActionPerformed Autor: Thomas Schädler 114 Anhang A: Quelltext <xmlizer> configurator private void xmlListComboBoxActionPerformed(java.awt.event.ActionEvent evt)//GEN FIRST:event_xmlListComboBoxActionPerformed {//GEN-HEADEREND:event_xmlListComboBoxActionPerformed // Add your handling code here: if (!isLoading) { JComboBox cb = (JComboBox)evt.getSource(); //String selectedXML = (String)cb.getSelectedItem(); xmlItem selectedXML = (xmlItem)cb.getSelectedItem(); if (selectedXML != null) { showXML(selectedXML); removeXMLButton.setEnabled(true); } } }//GEN-LAST:event_xmlListComboBoxActionPerformed private void dbListComboBoxActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_dbListComboBoxActionPerformed {//GEN-HEADEREND:event_dbListComboBoxActionPerformed // Add your handling code here: if (!isLoading) { JComboBox cb = (JComboBox)evt.getSource(); //String selectedDB = (String)cb.getSelectedItem(); dbItem selectedDB = (dbItem )cb.getSelectedItem(); if (selectedDB != null) { showDB(selectedDB); removeDBButton.setEnabled(true); } } }//GEN-LAST:event_dbListComboBoxActionPerformed private void addNewXMLButtonActionPerformed(java.awt.event.ActionEvent evt)//GEN FIRST:event_addNewXMLButtonActionPerformed {//GEN-HEADEREND:event_addNewXMLButtonActionPerformed // Add your handling code here: doXMLSave(); }//GEN-LAST:event_addNewXMLButtonActionPerformed private void addNewDBButtonActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_addNewDBButtonActionPerformed {//GEN-HEADEREND:event_addNewDBButtonActionPerformed // Add your handling code here: doDBSave(); }//GEN-LAST:event_addNewDBButtonActionPerformed private void addXMLButtonActionPerformed (java.awt.event .ActionEvent evt)//GEN-FIRST:event_addXMLButtonActionPerformed {//GEN-HEADEREND:event_addXMLButtonActionPerformed // Add your handling code here: String selected = (String)mappingmoduleComboBox.getSelectedItem(); if (selected.equalsIgnoreCase("Database to XML") && xmlList.size() > 0) { outputTextArea.setText ("In this module (currently) only one file is allowed!" ); } else if (selected.equalsIgnoreCase("Simple DB Export")) { outputTextArea.setText ("In this module no files are needed, only database connections!"); } else { filenameTextField.setText(new String()); fileidentifierTextField.setText(new String ()); doCheck(); xmlPanel.add(xmlsubPanel, java.awt.BorderLayout .CENTER); //addXMLButton.setEnabled(false); removeXMLButton.setEnabled(false ); } mainTabbedPane.repaint(); }//GEN-LAST:event_addXMLButtonActionPerformed private void addDBButtonActionPerformed(java.awt.event.ActionEvent evt )//GEN-FIRST:event_addDBButtonActionPerformed {//GEN-HEADEREND:event_addDBButtonActionPerformed // Add your handling code here: connameTextField.setText(new String()); //dbdriverTextField.setText("org.gjt.mm.mysql.Driver"); //dburlTextField.setText("jdbc:mysql://localhost:3306/xml"); dbdriverTextField.setText("org.gjt.mm.mysql.Driver" ); dburlTextField.setText(new String()); dbtimeoutTextField.setText ("30"); dbpasswordTextField.setText(new String()); doCheck(); databasePanel.add(dbPanel, java.awt.BorderLayout.CENTER); //addDBButton.setEnabled(false); removeDBButton.setEnabled(false ); mainTabbedPane.repaint(); }//GEN-LAST:event_addDBButtonActionPerformed private void dbdriverTextFieldActionPerformed (java.awt.event .ActionEvent evt)//GENFIRST:event_dbdriverTextFieldActionPerformed {//GEN-HEADEREND:event_dbdriverTextFieldActionPerformed // Add your handling code here: doDatabaseCheck (); }//GEN-LAST:event_dbdriverTextFieldActionPerformed private void validateButtonActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_validateButtonActionPerformed {//GEN-HEADEREND:event_validateButtonActionPerformed // Add your handling code here: if(this.selectedFile != null) { try { DOMParser parser = new DOMParser(); parser.setFeature("http://xml.org/sax/features/validation" , false); parser.setProperty ("http://apache.org/xml/properties/schema/external noNamespaceSchemaLocation",filenameTextField .getText()); ErrorChecker errors = new ErrorChecker (); parser.setErrorHandler(errors); parser.parse (filenameTextField.getText()); outputTextArea.setText("The selected file is well-formed!\nResolving includes..."); try { SAXBuilder builder = new SAXBuilder(false); //true -> validating against dtd this.temporary = builder.build(filenameTextField.getText()); Autor: Thomas Schädler 115 Anhang A: Quelltext <xmlizer> configurator File tempfile = new File(filenameTextField.getText()); this.temporary_name = tempfile.getName(); Element loaded_root = this.temporary.getRootElement(); Vector incs2del = new Vector(); //of Elements List elems = loaded_root .getChildren(); //"element",namespace Iterator elems_iter = elems.iterator(); while (elems_iter.hasNext()) { Element xmlelem = (Element)elems_iter.next(); String currName = xmlelem.getName().trim(); //System.out.println("Element name: " + currName); if(currName.equalsIgnoreCase("include")) { String path = JDOMgetIncludePath(xmlelem); //System.out.println("Include path: " + path); String newpath = null; File testinclude = new File(path); if(testinclude.exists ()) //read it automatically, on error go on { newpath = path; } else { newpath = getIncludeFromUser(path); if (newpath == null) { //FIXME aborted include resolver dialog! } } //add the path to the list and delete the include this.includepaths.add(newpath); incs2del.add(xmlelem); } } for (Enumeration e = incs2del .elements(); e.hasMoreElements ();) { Element item = (Element)e.nextElement(); loaded_root.removeContent (item); } } catch (Exception ex) { //show errors of current xml operation mother.getLog().addDebug (ex); } resolveIncludes(); this.XMLvalidated = true; doCheck(); } catch (SAXException e) { outputTextArea.setText("The selected file is NOT well -formed!"); this.XMLvalidated = false; doCheck(); } catch (java.io.IOException ex) { outputTextArea.setText("IO Exception: " + ex.toString()); this.XMLvalidated = false; doCheck(); } } else { outputTextArea.setText ("No XML File selected!"); this.XMLvalidated = false; doCheck(); } }//GEN-LAST:event_validateButtonActionPerformed private void resolveIncludes() { SAXBuilder builder = new SAXBuilder(false ); //true -> validating against dtd for (Enumeration e = this.includepaths.elements(); e.hasMoreElemen ts();) { String currentpath = (String)e.nextElement (); //System.out.println("CURR PATH: " + currentpath); if (currentpath != null) { Element inc_root = this.temporary .getRootElement (); try { org.jdom.Document loaded = builder.build(currentpath); Element loaded_root = loaded.getRootElement(); if (loaded_root != null) { List elems = loaded_root.getChildren(); //"element",namespace Iterator elems_iter = elems.iterator(); while (elems_iter.hasNext()) { Element xmlelem = (Element)elems_iter.next(); try { //System.out.println("INCLUDED ELEMENT ADDED: " + xmlelem.toString()); inc_root.addContent((Element)xmlelem.clone ()); } catch(Exception exc) { mother.getLog().addWarning(exc.getLocalizedMessage()); } } } else { mother.getLog().addWarning("No root element found in include: " + currentpath); } } catch (Exception ex) { mother.getLog().addDebug (ex); } } } outputTextArea.setText("The selected file is well-formed!\nResolving includes...done." ); } private File lastInclude = null; Autor: Thomas Schädler 116 Anhang A: Quelltext <xmlizer> configurator /** * Asks for the include path from the user */ private String getIncludeFromUser(String filepath) { //Show inf o on file to search JOptionPane.showMessageDialog( getContentPane(), "Included file could not be found:\n" + filepath , configurator.APPNAME + " include resolver", JOptionPane.INFORMATION_MESSAGE ); JFileChooser chooser = new JFileChooser(); chooser.setDialogType(JFileChooser.OPEN_DIALOG ); if (lastInclude != null) { chooser.setCurrentDirectory (lastInclude); } int returnVal = chooser.showOpenDialog(this); if(returnVal == JFileChooser.APPROVE_OPTION) { File selectedFile = chooser.getSelectedFile(); this.lastInclude = selectedFile; return selectedFile.toString(); } else { return null; } } private String JDOMgetIncludePath(Element el) { Attribute attr = el.getAttribute("schemaLocation"); if (attr != null) { return attr.getValue().trim(); } else //just to be sure, should not happen though... { return "empty"; } } private void filechooserButtonActionPerformed (java.awt.event .ActionEvent evt)//GENFIRST:event_filechooserButtonActionPerformed {//GEN-HEADEREND:event_filechooserButtonActionPerformed // Add your handling code here: JFileChooser chooser = new JFileChooser(); chooser.setDialogType(JFileChooser.OPEN_DIALOG ); simpleFileFilter filter = new simpleFileFilter (); filter.addExtension("xsd"); filter.addExtension("dtd"); filter.setDescription("XSD & DTD Only"); chooser.setFileFilter(filter); int returnVal = chooser.showOpenDialog(this); if(returnVal == JFileChooser.APPROVE_OPTION) { this.selectedFile = chooser.getSelectedFile(); filenameTextField.setText(chooser.getSelectedFile().getPath()); fileidentifierTextField.setText(chooser.getSelectedFile().getName()); doCheck(); } else { doCheck(); } }//GEN-LAST:event_filechooserButtonActionPerformed private void finishButtonActionPerformed (java.awt.event .ActionEvent evt)//GEN-FIRST:event_finishButtonActionPerformed {//GEN-HEADEREND:event_finishButtonActionPerformed // Add your handling code here: doWelcomeSave(); doExit(); }//GEN-LAST:event_finishButtonActionPerformed private void projectnameTextFieldActionPerformed(java.awt.event.ActionEvent evt)//GEN FIRST:event_projectnameTextFieldActionPerformed {//GEN-HEADEREND:event_projectnameTextFieldActionPerformed // Add your handling code here: doWelcomeCheck(); }//GEN-LAST:event_projectnameTextFieldActionPerformed private void dbusernameTextFieldActionPerformed(java.awt.event.ActionEvent evt)//GENFIRST:event_dbusernameTextFieldActionPerformed {//GEN-HEADEREND:event_dbusernameTextFieldActionPerformed // Add your handling code here: doDatabaseCheck (); }//GEN-LAST:event_dbusernameTextFieldActionPerformed private void dbtimeoutTextFieldActionPerformed(java.awt.event.ActionEvent evt)//GENFIRST:event_dbtimeoutTextFieldActionPerformed {//GEN-HEADEREND:event_dbtimeoutTextFieldActionPerformed // Add your handling code here: doDatabaseCheck (); }//GEN-LAST:event_dbtimeoutTextFieldActionPerformed private void dburlTextFieldActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_dburlTextFieldActionPerformed {//GEN-HEADEREND:event_d burlTextFieldActionPerformed // Add your handling code here: doDatabaseCheck (); }//GEN-LAST:event_dburlTextFieldActionPerformed private void connectButtonActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_connectButtonActionPerformed {//GEN-HEADEREND:event_connectButtonActionPerformed // Add your handling code here: doConnect(); }//GEN-LAST:event_connectButtonActionPerformed private void drivertestButtonActionPerformed(java.awt.event.ActionEvent evt )//GENFIRST:event_drivertestButtonActionPerformed Autor: Thomas Schädler 117 Anhang A: Quelltext <xmlizer> configurator {//GEN-HEADEREND:event_drivertestButtonActionPerformed // Add your handling code here: if (!dbdriverTextField.getText().equals(new String())) { try { Class.forName(dbdriverTextField.getText()); dboutputTextArea.setText("Driver successfully loaded: " + dbdriverTextField.getText()); dbdriverLabel.setForeground(COLOR_DEFAULT); dbdriverTested = true; doDatabaseCheck(); } catch(ClassNotFoundException ee) { dbdriverLabel.setForeground(COLOR_RED); dbdriverTested = false; dboutputTextArea.setText("The selected Driver could not be loaded, make sure it is in the classpath!"); } } else { dbdriverLabel.setForeground (COLOR_RED ); dbdriverTested = false ; dboutputTextArea .setText("Enter a valid driver class. Must be in the classpath!"); } }//GEN-LAST:event_drivertestButtonActionPerformed // Variables declaration - do not modify//GEN -BEGIN:variables private javax.swing .JPanel backPanel; private javax.swing .JTabbedPane mainTabbedPane; private javax.swing .JPanel welcomePanel; private javax.swing .JTextArea welcomeTextArea ; private javax.swing .JPanel buttonPanel; private javax.swing .JPanel subPanel ; private javax.swing .JLabel projectnameLabel; private javax.swing .JTextField projectnameTextField; private javax.swing .JLabel mappingmoduleLabel ; private javax.swing .JComboBox mappingmoduleComboBox; private javax.swing .JButton moduleInfoButton; private javax.swing .JPanel sub2Panel; private javax.swing .JLabel dbLabel; private javax.swing .JLabel db2Label ; private javax.swing .JButton finishButton ; private javax.swing .JLabel welcome2Label ; private javax.swing .JLabel welcomeLabel; private javax.swing .JPanel databasePanel ; private javax.swing .JTextArea dboutputTextArea; private javax.swing .JPanel dbListPanel; private javax.swing .JLabel dbListLabel; private javax.swing .JComboBox dbListComboBox; private javax.swing .JButton addDBButton; private javax.swing .JButton removeDBButton; private javax.swing .JButton dbInfoButton ; private javax.swing .JPanel dbPanel; private javax.swing .JLabel dbdriverLabel ; private javax.swing .JTextField dbdriverTextField; private javax.swing .JLabel dburlLabel; private javax.swing .JTextField dburlTextField ; private javax.swing .JButton drivertestButton; private javax.swing .JLabel dbtimeoutLabel; private javax.swing .JLabel dbusernameLabel; private javax.swing .JTextField dbusernameTextField ; private javax.swing.JLabel dbpasswordLabel; private javax.swing .JPasswordField dbpasswordTextField; private javax.swing .JButton connectButton; private javax.swing .JTextField dbtimeoutTextField; private javax.swing .JTextField connameTextField; private javax.swing .JLabel connameLabel; private javax.swing .JButton addNewDBButton; private javax.swing .JLabel jLabel4; private javax.swing .JButton dbBrowseButton; private javax.swing .JPanel xmlPanel ; private javax.swing .JPanel xmlsubPanel; private javax.swing .JPanel xmlchooserPanel; private javax.swing .JLabel filenameLabel ; private javax.swing .JTextField filenameTextField; private javax.swing .JButton filechooserButton ; private javax.swing .JTextField fileidentifierTextField; private javax.swing .JLabel fileidentifierLabel; private javax.swing .JPanel validatePanel ; private javax.swing .JLabel validateLabel ; private javax.swing .JButton validateButton; private javax.swing .JButton addNewXMLButton; private javax.swing .JLabel hintXMLLabel; private javax.swing .JButton convertButton; private javax.swing .JTextArea outputTextArea; private javax.swing .JPanel xmlListPanel; private javax.swing .JLabel xmlListLabel; private javax.swing .JComboBox xmlLi stComboBox ; private javax.swing .JButton addXMLButton ; private javax.swing .JButton removeXMLButton; private javax.swing .JButton xmlInfoButton; // End of variables declaration//GEN-END:variables private private private private boolean dbdriverTested = false; boolean dbdriverLoaded = false; boolean XMLvalidated = false; java.io.File selectedFile; private void doExit () { mother.close(this.ID); mother.doDisable("new"); mother.doEnable ("close"); mother.doEnable ("save"); mother.doEnable ("saveas"); if (isNewSetup) { mother .startupProjectWorkspace(); Autor: Thomas Schädler 118 Anhang A: Quelltext <xmlizer> configurator mother .getLog().addInformation("Go on with the mapping or save your settings and continue..." ); } else { mother .updateCurrentProject (); } } private void doConnect() { Runnable r = new Runnable() { public void run() { //check the fields (comboboxes) and connect boolean isok = doDatabaseCheck(); if(isok) { //connect to database String theURL = new String(dburlTextField.getText()); dboutputTextArea.setText("Connecting to Database: " + theURL); try { Class.forName(dbdriverTextField.getText()); String to_string = dbtimeoutTextField.getText(); Integer to _integer = new Integer(to_string); int to_int = to_integer.intValue(); DriverManager.setLoginTimeout(to_int); if(dbusernameTextField.getText().equalsIgnoreCase(new String ())) { Connection con = DriverManager.getConnection(theURL ); } else { Connection con = DriverManager.getConnection (theURL,dbusernameTextField.getText(),dbItem.decryptSecurePassword (getSecurePassword())); } dboutputTextArea.setText("DB Connection established!"); dbdriverLoaded = true; doCheck(); } catch (ClassNotFoundException classex) { dbdriverLoaded = false; doCheck(); dboutputTextArea.setText(classex.toString()); } catch (SQLException sqlex) { dbdriverLoaded = false; doCheck(); dboutputTextArea.setText(sqlex .toString()); } } else { doCheck(); dboutputTextArea.setText("Please fill in ALL neccessary fields!" ); } } }; connecterThread = new Thread(r); connecterThread .setDaemon(true); connecterThread .start(); } private void doWelcomeSave() { //initialize projectdata from options for manual edited options projectData data = mother.getProjectData(); if (isNewSetup) { dataItem initial_name = new dataItem(); dataItem initial_module = new dataItem(); if (!projectnameTextField.getText().equals (new String())) { initial_name .setKey("name"); initial_name .setValue(projectnameTextField.getText()); } if (!((String)mappingmoduleComboBox.getSelectedItem()).equals(new String ())) { initial_module.setKey("module"); initial_modu le.setValue ((String)mappingmoduleComboBox .getSelectedItem()); } data.addInitial(initial_name); data.addInitial(initial_module); } else { if (!projectnameTextField.getText().equals (new String())) { dataItem item = data.getInitialByKey("name" ); item.setValue(projectnameTextField.getText()); } } } private void copyFile2ProjectDir() { String sep = configurator.getFileSeparator(); //File inputFile = new File(orig); //String inputFileName = inputFile.getName(); File outputPath = new File(mother.getProjectBase() + sep + projectnameTextField.getText()); outputPath .mkdirs(); File outputFile = new File(outputPath.toString () + sep + this.temporary_name ); try { XMLOutputter fmt = new XMLOutputter(" ",true); FileOutputStream outputStream = new FileOutputStream (outputFile); OutputStreamWriter outsw = new OutputStreamWriter(outputStream ,"UTF8"); fmt.output(this.temporary,outsw); outsw.close (); } catch(Exception exx) { Autor: Thomas Schädler 119 Anhang A: Quelltext <xmlizer> configurator mother .getLog().addError(exx); } } private void doXMLSave() { boolean isUpdated = false; this.projectnameTextField.setEnabled (false); for (Enumeration e = xmlList.elements(); e.hasMoreElements();) { xmlItem iteritem = (xmlItem)e.nextElement(); if (iteritem.getName().equalsIgnoreCase(fileidentifierTextField.getText())) { //update if (!fileidentifierTextField .getText().equalsIgnoreCase(iteritem.getName())) { iteritem .setName(fileidentifierTextField.getText()); } if (!filenameTextField.getText().equalsIgnoreCase(iteritem .getFile())) { //copy the file to the projectdir and save the filename-only! //String original = filenameTextField.getText(); copyFile2ProjectDir (); iteritem .setFile(this.temporary_name); } xmlListComboBox.setSelectedItem(iteritem); outputTextArea.setText("XML file data successfully updated."); mother.getProjectData().setDirty(); isUpdated = true; break; } } if (!isUpdated) { //add new item xmlItem xml = new xmlItem(); if (!fileidentifierTextField.getText().equals(new String())) { xml.setName(fileidentifierTextField.getText()); } if (!filenameTextField .getText().equals(new String())) { //copy the file to the projectdir and save the filename-only! //String original = filenameTextField.getText(); copyFile2ProjectDir(); xml.setFile(this.temporary_name); } //remove the Panel and update the combobox (list) xmlList.add(xml); xmlListComboBox.setSelectedItem(xml); dboutputTextArea .setText("XML File data successfully added."); mother .getProjectData().setDirty (); } xmlPanel.remove (xmlsubPanel); mainTabbedPane.repaint(); doCheck(); addXMLButton.setEnabled(true); validateButton.setEnabled(false ); addNewXMLButton .setEnabled (false); XMLvalidated = false ; } private void showXML(xmlItem item) { filenameTextField.setText(mother.getProjectBase() + mother.getFileSeparator() + projectnameTextField.getText() + mother.getFileSeparator () + item.getFile()); fileidentifierTextField.setText(item.getName()); this.selectedFile = new File(item.getFile()); validateButton.setEnabled(false ); addNewXMLButton .setEnabled (false); xmlPanel.add(xmlsubPanel, java.awt.BorderLayout.CENTER); mainTabbedPane.repaint(); doXMLCheck (); } private void doDBSave() { boolean isUpdated = false; this.projectnameTextField.setEnabled (false); for (Enumeration e = databaseList.elements(); e.hasMoreElements();) { dbItem iteritem = (dbItem)e.nextElement(); if (iteritem.getName().equalsIgnoreCase(connameTextField.getText())) { //update if (!dbdriverTextField.getText().equal sIgnoreCase(iteritem .getDriver ())) { iteritem .setDriver(dbdriverTextField.getText()); } if (!dburlTextField.getText().equalsIgnoreCase(iteritem.getUrl())) { iteritem .setUrl(dburlTextField.getText()); } if (!dbtimeoutTextField .getText().equalsIgnoreCase(iteritem.getTimeout())) { iteritem .setTimeout (dbtimeoutTextField.getText()); } if (!dbusernameTextField.getText().equalsIgnoreCase(iteritem.getUsername())) { iteritem .setUsername(dbusernameTextField.getText()); } if (!getSecurePassword().equalsIgnoreCase(iteritem.getPassword())) { iteritem.setPassword(getSecurePassword()); } dbListComboBox.setSelectedItem(iteritem); dboutputTextArea.setText("Connection successfully updated."); mother.getProjectData().setDirty(); isUpdated = true; break; } Autor: Thomas Schädler 120 Anhang A: Quelltext <xmlizer> configurator } if (!isUpdated) { //add new item dbItem db = new dbItem (); if (!connameTextField.getText().equals(new String())) { db.setName(connameTextField.getText()); } if (!dbdriverTextField .getText().equals(new String())) { db.setDriver (dbdriverTextField.getText()); } if (!dburlTextField.getText ().equals(new String ())) { db.setUrl(dburlTextField.getText()); } if (!dbtimeoutTextField.getText().equals(new String())) { db.setTimeout(dbtimeoutTextField.getText()); } if (!dbusernameTextField.getText().equals(new String ())) { db.setUsername(dbusernameTextField.getText()); } if (!getSecurePassword ().equals(new String ())) { db.setPassword(getSecurePassword()); } databaseList.add(db); dbListComboBox.setSelectedItem(db); dboutputTextArea .setText("Connection successfully added." ); mother .getProjectData().setDirty (); } //remove the Panel and update the combobox (list) databasePanel.remove (dbPanel); mainTabbedPane.repaint(); doCheck(); addDBButton.setEnabled(true); connectButton.setEnabled(false); addNewDBButton.setEnabled(false ); dbdriverTested = false; dbdriverLoaded = false; } private void showDB (dbItem item) { connameTextField.setText(item.getName()); dbdriverTextField.setText(item.getDriver()); dburlTextField.setText(item.getUrl()); dbtimeoutTextField.setText (item.getTimeout()); dbusernameTextField.setText(item.getUsername()); dbpasswordTextField.setText(dbItem.decryptSecurePassword (item.getPassword())); drivertestButton.setEnabled(true); connectButton.setEnabled(false); addNewDBButton.setEnabled(false ); dbBrowseButton.setEnabled(false ); databasePanel.add(dbPanel, java.awt.BorderLayout.CENTER); mainTabbedPane.repaint(); doDatabaseCheck(); } /** * Checks all the neccessary fields on the welcome tab */ private boolean doWelcomeCheck () { boolean result = true; //!projectnameTextField.getText().equals(new String()) if (configurator.isValidPath(projectnameTextField.getText())) { //projectnameCheckBox.setSelected(true); projectnameLabel .setForeground(COLOR_DEFAULT); } else { result = false; //projectnameCheckBox.setSelected(false); projectnameLabel .setForeground(COLOR_RED); } if(result) { welcomeLabel.setEnabled(true); } else { welcomeLabel.setEnabled(false ); } return result; } /** * Checks for all neccessary fields on the database tab */ private boolean doDatabaseCheck() { boolean result = true; if (!connameTextField.getText().equals(new String())) {connameLabel.setForeground(COLOR_DEFAULT );} else {result = false ; connameLabel.setForeground(COLOR_RED);} if (!dbdriverTextField.getText().equals(new String())) {dbdriverLabel.setForeground(COLOR_DEFAULT);} else {result = false ; dbdriverLabel.setForeground(COLOR_RED);} if (!dburlTextField.getText().equals (new String())) {dburlLabel.setForeground(COLOR_DEFAULT);} else {result = false ; dburlLabel.setForeground (COLOR_RED );} if (!dbtimeoutTextField.getText().equals(new String ())) { dbtimeoutLabel.setForeground(COLOR_DEFAULT ); try { Autor: Thomas Schädler 121 Anhang A: Quelltext <xmlizer> configurator Integer intvalue = new Integer(dbtimeoutTextField.getText()); } catch(NumberFormatException nfe) { dbtimeoutLabel.setForeground (COLOR_RED ); dbtimeoutTextField .setText("30"); } } else {result = false ; dbtimeoutLabel .setForeground(COLOR_RED);} if ((connameLabel.getForeground () == COLOR_DEFAULT) && (dbdriverLabel.getForeground() == COLOR_DEFAULT )) { drivertestButton.setEnabled(true); } else { drivertestButton.setEnabled(false); } if (result && dbdriverTested) { connectButton.setEnabled(true); } else { connectButton.setEnabled(false); } return result; } /** * Checks for all the neccessary fields on the xml tab */ private boolean doXMLCheck() { boolean chosen = false; boolean validated = false; boolean result = false; if (!fileidentifierTextField.getText().equals(new String ())) {result = true; fileidentifierLabel.setForeground(COLOR_DEFAULT);} else {result = false ; fileidentifierLabel .setForeground(COLOR_RED);} if (!filenameTextField.getText().equals(new String())) {result = true; filenameLabel.setForeground(COLOR_DEFAULT);} else {result = false ; filenameLabel.setForeground(COLOR_RED);} if (result ) { chosen = true; } if (this.XMLvalidated) { validated = true; } //check here if (chosen ) { if (filenameText Field.getText().endsWith(".dtd" )) { convertButton.setVisible(true); validateButton.setEnabled(false); } else if (filenameTextField.getText().endsWith(".xsd" )) { convertButton.setVisibl e(false); validateButton.setEnabled(true); } } else { convertButton.setVisible(false); validateButton.setEnabled(false); } return (chosen && validated); } /** * Checks all fields on all tabs */ private void doCheck() { boolean wcResult = doWelcomeCheck(); boolean dbResult = doDatabaseCheck(); boolean xmResult = doXMLCheck(); if (wcResult) { welcomeLabel.setEnabled(true); } else { welcomeLabel.setEnabled(false ); } if (dbResult && dbdriverLoaded) { addNewDBButton.setEnabled(true); dbBrowseButton.setEnabled(true); } else { addNewDBButton.setEnabled(false); dbBrowseButton.setEnabled(false); } if (xmResult) { addNewXMLButton.setEnabled(true); } else { addNewXMLButton.setEnabled(false ); } if (databaseList.size() > 0) { dbLabel.setEnabled(true); dbListComboBox.setEnabled(true); removeDBButton.setEnabled(true); } else { dbLabel.setEnabled(false); Autor: Thomas Schädler 122 Anhang A: Quelltext <xmlizer> configurator dbListComboBox.setEnabled(false); removeDBButton.setEnabled(false); addDBButton .setEnabled (true); } if (xmlList.size() > 0) { xmlListComboBox.setEnabled(true); removeXMLButton.setEnabled(true); } else { xmlListComboBox.setEnabled(false ); removeXMLButton.setEnabled(false ); addXMLButton.setEnabled(true); } if (welcomeLabel.isEnabled () && dbLabel.isEnabled()) { finishButton.setEnabled(true); } else { finishButton.setEnabled(false); } } private void ConvertDTD2XMLSchema() { //convert the currently selected DTD String theDTD = filenameTextField.getText().trim(); StringBuffer convLog = new StringBuffer(); dtd2xs translator = new dtd2xs(convLog); dtd2xsdOptions opt = new dtd2xsdOptions(mother ,true); Hashtable options = opt.getOptions(); boolean resolveEntity = ((Boolean)options.get("entities" )).booleanValue (); boolean ignoreComment = ((Boolean)options.get("comments" )).booleanValue ();; int commentLength = dbItem .ConvertString2int((String)options.get("commentLength")); String commentLanguage = (String)options.get("commentLanguage"); String conceptRelation = (String)options.get("conceptRelations"); int conceptHighlight = dbItem.ConvertString2int((String)options.get("conceptHighlight" )); int conceptOccurrence = dbItem.ConvertString2int((String )options.get("minOccur")); //go for it File dtd = new File(theDTD ); //String filename = new String("e:\\forte \\configurator\\xml\\dtd2xsd\\complextype.xsl"); String filename = mother.getHomeBase () + "/xml/dtd2xsd/complextype.xsl" ; File xslt = new File(filename); String xsd = null; xsd = translator.translate ( "file:///" + dtd.getAbsolutePath(), "file:///" + xslt.getAbsolutePath(), resolveEntity, ignoreComment, commentLength, commentLanguage , conceptRelation , conceptHighlight, conceptOccurrence ); //output it in the logWindow if (xsd != null) { dtd2xsdReport rept = new dtd2xsdReport(mother,true,"CONVERSION SUCCESSFULL\n\n"+convLog.toString(),xsd); //show save warning Object [] toptions = {"Yes","No"} ; int warn = JOptionPane .showOptionDialog( getContentPane(), "Do you want to save the newly\ngenerated XML Schema!", mother .APPNAME + " save new XSD" , JOptionPane .YES_NO_OPTION, JOptionPane .QUESTION_MESSAGE, null, toptions, toptions[1] ); if (warn == JOptionPane.YES_OPTION) { //open filechooser File file = null; String location = null; JFileChooser chooser = new JFileChooser(); /* NO GOOD IDEA - FORBIDDEN TO STORE FILES IN THE PROJECT DIRS BY THE USER chooser.setCurrentDirectory( new File( mother.getProjectBase() + mother.getFileSeparator() + ((dataItem)mother.getProjectData().getInitialByKey("name")).getValue() + mother.getFileSeparator() )); **/ chooser.setDialogType(javax.swing .JFileChooser.SAVE_DIALOG ); simpleFileFilter filter = new simpleFileFilter(); filter.addExtension("xsd"); filter.setDescription("XSD Only"); chooser.setFileFilter(filter ); int returnVal = chooser.showSaveDialog (this); if(returnVal == JFileChooser .APPROVE_OPTION ) { file = chooser .getSelectedFile(); location = chooser.getSelectedFile ().getPath(); try { FileWriter writer = new FileWriter(location); writer.write(xsd); Autor: Thomas Schädler 123 Anhang A: Quelltext <xmlizer> configurator writer.close(); fileidentifierTextField.setText(file.getName()); filenameTextField.setText(location); doCheck(); } catch(Exception ex) { mother.getLog().addError(ex); return; } } else { //aborted return; } } //mother.getLog().addNewTab("DTD2XSD",xsd,"DTD2 XSD Conversion"); //mother.getLog().addNewTab("DTD2XSD Report",convLog.toString(),"DTD2XSD Conversion Report"); } else { dtd2xsdReport rept = new dtd2xsdReport(mother,true,"CONVERSION FAILED\n\n"+convLog.toString(),xsd); //mother.getLog().addNewTab("DTD2XSD Error",convLog.toString(),"DTD2XSD Error Report"); } } public synchronized void update(configurator conf) { this.mother = conf; this.databaseList = conf.getProjectData().getDB(); //update the DBList this.xmlList = conf.getProjectData().getXML(); //update the DBList this.repaint(); } /** * Loads the current project data to display */ private void loadCurrentProjec tData () { projectData theData = this.mother.getProjectData(); Vector theInitial = theData.getInitial(); Vector theDB = theData.getDB(); Vector theXML = theData.getXML(); //check for new setup or configuration change -> start the project or not after finishing setup if (theInitial.size() == 0 && theDB.size() == 0 && theXML.size() == 0) { isNewSetup = true; } else { isNewSetup = false; //disable change of module (only for new modules!) mappingmoduleComboBox.setEnabled (false); projectnameTextField.setEnabled(false ); //no new setup, so init the components String projectName = ((dataItem)theData.getInitialByKey("name" )).getValue(); String projectModule = ((dataItem)theData.getInitialByKey ("module")).getValue (); projectnameTextField.setText(projectName); mappingmoduleComboBox.setSelectedItem (projectModule); if (xmlList.size() > 0) { xmlListComboBox.setSelectedIndex(0); } if (databaseList .size() > 0) { dbListComboBox.setSelectedIndex(0); } } } /** * Returns the password from the JPasswordField as lightly encrypted code * (just to minimize time of unecrypted password in memory and to store it in a file) */ private String getSecurePassword() { char[] pw = dbpasswordTextField .getPassword(); StringBuffer result = new StringBuffer(); char[] sec_char = new char[]{'x','m','l','i','z','e','r'}; int incr = 0; char actual; for (int i=0;i<pw.length;i++) { if (incr<sec_char.length-1){incr++;}else{incr=0;} actual = pw[i]; result .append(actual ^ sec_char[incr]); result .append(':'); pw[i] = 0; //for security reasons } return result.toString(); } /** * DOM Parsers ErrorHandler */ public class ErrorChecker extends DefaultHandler { public ErrorChecker() { } public void error(SAXParseException e) { outputTextArea.setText ("Parsing error: "+e.getMessage()); } public void warning(SAXParseException e) { outputTextArea.setText ("Parsing problem: " +e.getMessage()); } public void fatalError(SAXParseException e) { Autor: Thomas Schädler 124 Anhang A: Quelltext <xmlizer> configurator outputTextArea.setText ("Parsing error: "+e.getMessage()); outputTextArea.setText ("Cannot continue."); } } } /* * dbBrowser.java * * Created on 17. Mai 2002, 20:28 * ---------------------------------------------------------------------------* This file is part of <xmlizer>. * * <xmlizer> is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Foobar is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with <xmlizer>; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * ---------------------------------------------------------------------------*/ package configurator; import import import import import import import import import import import import import import import java.io.*; java.sql.*; java.util.*; org.jdom.*; org.jdom.output.XMLOutputter; java.awt.event.*; javax.swing .*; javax.swing .table.*; javax.swing .tree.*; java.util.Vector ; java.util.Enumeration ; java.awt.*; java.awt.dnd.*; java.awt.event.*; java.awt.datatransfer .*; /** * The databrowser (a simple browser for database-connections * with methods for the module DB2XML * @author [email protected] */ public class dbBrowser extends MyInternalFrame { private configurator mother; private String ID; private JPopupMenu popup = new JPopupMenu(); private JMenu mnuAutoresize = new JMenu(); private JMenuItem nextMI ; private JMenuItem lastMI ; private JMenuItem setChunk; private JRadioButtonMenuItem mniOn = new JRadioButtonMenuItem("on"); private JRadioButtonMenuItem mniOff = new JRadioButtonMenuItem("off"); private int autoresize = JTable.AUTO_RESIZE_ALL_COLUMNS ; private projectData theData; private Vector dbList = new Vector(); private Vector tableList = new Vector(); private boolean isLoading = true; private boolean isUpdating = false; private String currentlySelectedTable = new String (); private DataChooser dataChooser = null; //Thread related private activityMeter activity ; private volatile Thread updateThread = null; private volatile Thread workerThread = null; private volatile Thread controllerThread = null; private boolean StopAllThreads = false; //flag used to stop long tasks (but not the controller thread) //TakeoverMode private SchemaElement takeoverelement = null; private boolean takeovermode = false; private String lastSQLStatement = new String(); /** Creates new form dbBrowser */ public dbBrowser(configurator mainProgram,String uid) { this.mother = mainProgram; this.ID = uid; this.theData = mainProgram .getProjectData (); if (mainProgram .nextDBToBrowse.size() > 0) { this.dbList = mainProgram.nextDBToBrowse; } else { this.dbList = mainProgram.getProjectData().getDB(); } initComponents(); activity = new activityMeter(stopButton,theProgressBar); //add the popupmenu //add data browser nextMI = new JMenuItem("Next"); lastMI = new JMenuItem("Last"); nextMI.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed (ActionEvent e) { nextMI_actionPerformed(e); } Autor: Thomas Schädler 125 Anhang A: Quelltext <xmlizer> configurator }); lastMI.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed (ActionEvent e) { lastMI_actionPerformed(e); } }); popup.add(nextMI); popup.add(lastMI); popup.addSeparator(); //add the entry to set the chunksize setChunk = new JMenuItem("Set Rows ("+getActiveDB().getChunkSize()+")"); setChunk.addActionListener (new java.awt.event.ActionListener() { public void actionPerformed (ActionEvent e) { setChunk_actionPerformed(e); } }); popup.add(setChunk); //add autoresize toggle mnuAutoresize.setText("Autoresize"); mnuAutoresize.add(mniOn); mnuAutoresize.add(mniOff); mniOn.setSelected(true); mniOn.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed (ActionEvent e) { mniOn_actionPerformed(e); } }); mniOff.setSelected(false); mniOff.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed (ActionEvent e) { mniOff_actionPerformed(e); } }); popup.add(mnuAutoresize); //init other stuff if (dbList .size() > 0) { dbComboBox.setSelectedIndex (0); } upperPanel .repaint(); isLoading = false; } /** This method is called from within the constructor to * initialize the form. * WARNING: Do NOT modify this code. The content of this method is * always regenerated by the Form Editor. */ private void initComponents()//GEN-BEGIN:initComponents { upperPanel = new javax.swing.JPanel(); dbLabel = new javax.swing.JLabel(); dbComboBox = new javax.swing.JComboBox(dbList); sqlButton = new javax.swing.JButton(); helpButton = new javax.swing.JButton(); sqlLabel = new javax .swing .JLabel(); sqlScrollPane = new javax.swing .JScrollPane(); sqlTextArea = new DNDTextArea(); stopButton = new javax.swing.JButton(); theProgressBar = new javax .swing.JProgressBar(); limitCheckBox = new javax.swing .JCheckBox (); obenPanel = new javax.swing.JPanel(); jSplitPane2 = new javax.swing.JSplitPane(); jPanel4 = new javax.swing.JPanel(); listScrollPane = new javax .swing.JScrollPane(); dbtableList = new javax.swing.JList(tableList); jPanel5 = new javax.swing.JPanel(); jLabel2 = new javax.swing.JLabel(); tableScrollPane = new javax.swing.JScrollPane(); dbTable = new javax.swing.JTable(); setMaximizable(true); setTitle("Database Browser"); setIconifiable(true); setResizable(true); setClosable(true); addInternalFrameListener(new javax.swing.event .InternalFrameListener() { public void internalFrameOpened(javax .swing.event.InternalFrameEvent evt ) { } public void internalFrameClosing (javax.swing.event.InternalFrameEvent evt) { formInternalFrameClosing(evt); } public void internalFrameClosed(javax .swing.event.InternalFrameEvent evt ) { } public void internalFrameIconified(javax.swing.event .InternalFrameEvent evt) { } public void internalFrameDeiconified(javax .swing.event.InternalFrameEvent evt ) { } public void internalFrameActivated(javax.swing.event .InternalFrameEvent evt) { } public void internalFrameDeactivated(javax .swing.event.InternalFrameEvent evt ) { } }); upperPanel .setLayout (new java.awt.GridBagLayout()); Autor: Thomas Schädler 126 Anhang A: Quelltext <xmlizer> configurator java.awt.GridBagConstraints gridBagConstraints1; dbLabel.setText("Database:"); gridBagConstraints1 = new java.awt.GridBagConstraints(); gridBagConstraints1.fill = java.awt.GridBagConstraints.HORIZONTAL; gridBagConstraints1.insets = new java.awt.Insets(0, 2, 0, 0); upperPanel .add(dbLabel, gridBagConstraints1); dbComboBox .setPreferredSize(new java.awt.Dimension(240, 27)); dbComboBox .setMinimumSize(new java.awt.Dimension(126, 27)); dbComboBox .setMaximumSize(new java.awt.Dimension(32767, 27)); dbComboBox .addActionListener(new java.awt.event.ActionListener() { public void actionPerformed (java.awt.event .ActionEvent evt) { dbComboBoxActionPerformed(evt); } }); gridBagConstraints1 = new java.awt.GridBagConstraints(); gridBagConstraints1.insets = new java.awt.Insets(2, 0, 2, 0); gridBagConstraints1.anchor = java.awt.GridBagConstraints .WEST; upperPanel .add(dbComboBox, gridBagConstraints1 ); sqlButton.setIcon(new javax.swing.ImageIcon(getClass().getResource ("/configurator/icons/actions/execute.gif"))); sqlButton.setToolTipText("Query the database with your SQL"); sqlButton.setPreferredSize (new java.awt.Dimension(51, 51)); sqlButton.setMaximumSize(new java.awt.Dimension(51, 51)); sqlButton.setSelected(true); sqlButton.setMinimumSize(new java.awt.Dimension(51, 51)); sqlButton.addActionListener(new java.awt.event .ActionListener () { public void actionPerformed (java.awt.event .ActionEvent evt) { sqlButtonAct ionPerformed(evt); } }); gridBagConstraints1 = new java.awt.GridBagConstraints(); gridBagConstraints1.gridx = 3; gridBagConstraints1.gridy = 1; gridBagConstraints1.insets = new java.awt.Insets(0, 2, 0, 2); gridBagConstraints1.anchor = java.awt.GridBagConstraints .WEST; upperPanel .add(sqlButton, gridBagConstraints1); helpButton .setIcon(new javax.swing.ImageIcon(getClass().getResource("/configurator/icons/Help16.gif"))); helpButton .setToolTipText("Open Help"); helpButton .setFont(new java.awt.Font("Dialog", 0, 10)); helpButton .addActionListener(new java.awt.event.ActionListener() { public void actionPerformed (java.awt.event .ActionEvent evt) { helpButtonActionPerformed(evt); } }); gridBagConstraints1 = new java.awt.GridBagConstraints(); gridBagConstraints1.gridx = 4; gridBagConstraints1.gridy = 0; gridBagConstraints1.insets = new java.awt.Insets(0, 0, 0, 2); gridBagConstraints1.anchor = java.awt.GridBagConstraints .EAST; upperPanel .add(helpButton, gridBagConstraints1 ); sqlLabel.setText("SQL Query:"); gridBagConstraints1 = new java.awt.GridBagConstraints(); gridBagConstraints1.gridx = 0; gridBagConstraints1.gridy = 1; gridBagConstraints1.insets = new java.awt.Insets(0, 2, 0, 0); upperPanel .add(sqlLabel, gridBagConstraints1); sqlTextArea.setLineWrap(true); sqlTextArea.setColumns(45); sqlTextArea.setRows(3); sqlScrollPane.setViewportView(sqlTextArea ); gridBagConstraints1 = new java.awt.GridBagConstraints(); gridBagConstraints1.gridx = 1; gridBagConstraints1.gridy = 1; gridBagConstraints1.gridwidth = 2; gridBagConstraints1.fill = java.awt.GridBagConstraints.HORIZONTAL; upperPanel .add(sqlScrollPane, gridBagConstraints1); stopButton .setIcon(new javax.swing.ImageIcon(getClass().getResource("/configurator/icons/Stop16.gif"))); stopButton .setToolTipText("Stop background activity."); stopButton .setEnabled(false); stopButton .addActionListener(new java.awt.event.ActionListener() { public void actionPerformed (java.awt.event .ActionEvent evt) { stopButtonActionPerformed(evt); } }); gridBagConstraints1 = new java.awt.GridBagConstraints(); gridBagConstraints1.gridx = 3; gridBagConstraints1.gridy = 0; gridBagConstraints1.insets = new java.awt.Insets(0, 2, 0, 2); gridBagConstraints1.anchor = java.awt.GridBagConstraints .WEST; upperPanel .add(stopButton, gridBagConstraints1 ); theProgressBar.setToolTipText("Shows the progress for longer tasks"); theProgressBar.setPreferredSize (new java.awt.Dimension(148, 21)); theProgressBar.setMinimumSize(new java.awt.Dimension(10, 21)); gridBagConstraints1 = new java.awt.GridBagConstraints(); gridBagConstraints1.gridx = 2; Autor: Thomas Schädler 127 Anhang A: Quelltext <xmlizer> configurator gridBagConstraints1.gridy = 0; gridBagConstraints1.insets = new java.awt.Insets(0, 0, 0, 2); gridBagConstraints1.anchor = java.awt.GridBagConstraints .EAST; upperPanel .add(theProgressBar, gridBagConstraints1); limitCheckBox.setToolTipText("If selected, the results are diplayed in browsable chunks, not as one large table."); limitCheckBox.setText("limit"); limitCheckBox.addItemListener(new java.awt.event.ItemListener () { public void itemStateChanged(java.awt.event.ItemEvent evt ) { limitCheckBoxItemStateChanged(evt); } }); gridBagConstraints1 = new java.awt.GridBagConstraints(); gridBagConstraints1.gridx = 4; gridBagConstraints1.gridy = 1; gridBagConstraints1.insets = new java.awt.Insets(0, 0, 0, 2); gridBagConstraints1.anchor = java.awt.GridBagConstraints .EAST; upperPanel .add(limitCheckBox, gridBagConstraints1); getContentPane().add(upperPanel , java.awt.BorderLayout.NORTH); obenPanel.setLayout(new java.awt.BorderLayout()); jSplitPane2.setDividerLocation(120); jSplitPane2.setOneTouchExpandable(true); jPanel4.setLayout(new java.awt.BorderLayout()); listScrollPane.setViewportView(dbtableList); jPanel4.add(listScrollPane, java.awt.BorderLayout.CENTER ); jPanel5.setLayout(new java.awt.GridBagLayout()); java.awt.GridBagConstraints gridBagConstraints2; jLabel2.setText("Tables"); jLabel2.setHorizontalAlignment(javax .swing.SwingConstants.CENTER); gridBagConstraints2 = new java.awt.GridBagConstraints(); gridBagConstraints2.insets = new java.awt.Insets(0, 0, 0, 2); jPanel5.add(jLabel2, gridBagConstraints2); jPanel4.add(jPanel5, java.awt.BorderLayout.NORTH); jSplitPane2.setLeftComponent(jPanel4); tableScrollPane .setPreferredSize(new java.awt.Dimension(400, 320)); dbTable.setPreferredScrollableViewportSize(new java.awt.Dimension(400, 350)); tableScrollPane .setViewportView (dbTable); jSplitPane2.setRightComponent(tableScrollPane); obenPanel.add(jSplitPane2, java.awt.BorderLayout.CENTER); getContentPane().add(obenPanel, java.awt.BorderLayout.CENTER); pack(); }//GEN-END:initComponents private void limitCheckBoxItemStateChanged(java.awt.event.ItemEvent evt)//GEN-FIRST:event_limitCheckBoxItemStateChanged {//GEN-HEADEREND:event_limitCheckBoxItemStateChanged // Add your handling code here: if (!isUpdating ) { getActiveDB ().setLimit (!getActiveDB().hasLimit()); } }//GEN-LAST:event_limitCheckBoxItemStateChanged private void stopButtonActionPerformed(java.awt.event.ActionEvent evt)//GEN -FIRST:event_stopButtonActionPerformed {//GEN-HEADEREND:event_stopButtonActionPerformed // Add your handling code here: Runnable r = new Runnable() { public void run() { stopButton.setEnabled(false); sqlButton.setEnabled(true); activity.init(); StopAllThreads = true; mother.getLog().addInformation("Background activity stopping..."); } }; controllerThread = new Thread(r); controllerThread.start(); }//GEN-LAST:event_stopButtonActionPerformed private void dbComboBoxActionPerformed(java.awt.event.ActionEvent evt)//GEN -FIRST:event_dbComboBoxActionPerformed {//GEN-HEADEREND:event_dbComboBoxActionPerformed // Add your handling code here: if (!isLoading) { updateDB(); //updates the DB Browser } }//GEN-LAST:event_dbComboBoxActionPerformed public void setDataChooser(DataChooser data) { this.dataChooser = data; } private void formInternalFrameClosing(javax.swing.event .InternalFrameEvent evt)//GEN-FIRST:event_formInternalFrameClosing {//GEN-HEADEREND:event_formInternalFrameClosing // Add your handling code here: if (this.takeovermode && this.takeoverelement != null) { dbItem dbitem = this.getActiveDB (); if (dbitem != null) { if (dbitem.getLastStatement() != null) { if (this.takeoverelement .getRepetition() == null) { Autor: Thomas Schädler 128 Anhang A: Quelltext <xmlizer> configurator this.takeoverelement .addSQLStatement(dbitem.getLastStatement ()); } else if (dbitem.getLastStatement().getRowNumber() == 1) { this.takeoverelement.addSQLStatement(dbitem.getLastStatement ()); } else { mother.getLog().addWarning("You can only have one SQL query with more than one result-row (repet ition)!"); } dbitem.clearLastStatement(); //clear the dbitem's sql cache } } mother .getProjectData().setDirty (); if (this.dataChooser != null) { mother.close (this.dataChooser.getWinID ()); mother.mappingState = true; } SQLChooser ch = (SQLChooser )mother.open("SQLChooser" ); ch.updateView(this.takeoverelement); } mother.nextDBToBrowse.removeAllElements(); mother.close(this.ID); }//GEN-LAST:event_formInternalFrameClosing private void helpButtonActionPerformed(java.awt.event.ActionEvent evt)//GEN -FIRST:event_helpButtonActionPerformed {//GEN-HEADEREND:event_helpButtonActionPerformed // Add your handling code here: helpWindow help = (helpWindow)mother .open("help"); help.loadPage("/configurator/help/module_db2xml_databrowser.html"); }//GEN-LAST:event_helpButtonActionPerformed private void sqlButtonActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_sqlButtonActionPerformed {//GEN-HEADEREND:event_sqlButtonActionPerformed // Add your handling code here: if (!(sqlTextArea.getText().trim().equalsIgnoreCase (new String()))) { try { doSQL(sqlTextArea.getText().trim(),true); } catch(Exception sqlex) { mother.getLog().addError(sqlex); } } else { sqlTextArea .setText(this.lastSQLStatement); } }//GEN-LAST:event_sqlButtonActionPerformed // Variables declaration - do not modify//GEN -BEGIN:variables private javax.swing .JPanel upperPanel; private javax.swing .JLabel dbLabel; private javax.swing .JComboBox dbComboBox ; private javax.swing .JButton sqlButton; private javax.swing .JButton helpButton; private javax.swing .JLabel sqlLabel ; private javax.swing .JScrollPane sqlScrollPane ; private javax.swing .JTextArea sqlTextArea; private javax.swing .JButton stopButton; private javax.swing .JProgressBar theProgressBar; private javax.swing .JCheckBox limitCheckBox; private javax.swing .JPanel obenPanel; private javax.swing .JSplitPane jSplitPane2; private javax.swing .JPanel jPanel4; private javax.swing .JScrollPane listScrollPane; private javax.swing .JList dbtableList; private javax.swing .JPanel jPanel5; private javax.swing .JLabel jLabel2; private javax.swing .JScrollPane tableScrollPane; private javax.swing .JTable dbTable; // End of variables declaration//GEN-END:variables /** * Updated the TreeView of the Database */ synchronized private void updateDB() { mother.getLog().addInformation("Retrieving tables from selected database..." ); final dbItem theDB = getActiveDB(); final dbBrowser This = this; if (theDB != null) { Runnable r = new Runnable() { public void run() { activity .start (false); dbtableList.setEnabled(false); isUpdating = true; limitCheckBox.setSelected(theDB.hasLimit()); isUpdating = false; try { tableList = theDB.getTableList (); } catch(Exception e) { activity.stop(false); mother.getLog().addError(e); return; } //make the new list dbtableList = new JList(tableList); //make the list functional dbtableList.getSelectionModel ().setSelectionMode(ListSelectionModel.SINGLE_SELECTION); //add the mouselistener Autor: Thomas Schädler 129 Anhang A: Quelltext <xmlizer> configurator ItemListener ilst = new ItemListener(This); dbtableList.addMouseListener(ilst); //show the new list listScrollPane .getViewport().add(dbtableList ); dbtableList.setEnabled(true); setChunk .setText("Set Rows (" +theDB.getChunkSize()+")"); mother.getLog().addInformation("Tablelist updated."); activity .stop(false ); } }; updateThread = new Thread(r); StopAllThreads = false ; updateThread.start(); } } synchronized public void chooseDB(String dbkey) { int counter = 0; for (Enumeration e = this.dbList.elements (); e.hasMoreElements();) { dbItem item = (dbItem)e.nextElement(); //System.out.println("SEARC HING: " + dbkey + " >> " + item.getName()); if (item.getName().equalsIgnoreCase(dbkey)) { this.dbtableList.setSelectedIndex (counter); this.dbComboBox.setSelectedIndex(counter); //System.out.println(" >> MATCH >> " + counter); } else counter++; } } public synchronized void inspect(SQLStatement stat ) { chooseDB(stat.getDB()); sqlTextArea.setText(stat.getSQL ()); doSQL(stat.getSQL(),true); } /** Returns xxx from xxx:yyy */ private String getFirst(String s,int cutter) { int doublepoint = s.indexOf(":"); if (doublepoint != 0) { return s.substring(cutter,doublepoint ); } else return s; } /** Returns yyy from xxx:yyy */ private String getSecond (String s,int cutter) { int doublepoint = s.indexOf(":"); if (doublepoint != 0) { return s.substring(++doublepoint ,s.length()-cutter); } else return s; } private String getSubstitution (String query) { StringBuffer result = new StringBuffer(); int counter = 0; StringTokenizer st = new StringTokenizer(query ); while (st.hasMoreTokens()) { String token = st.nextToken (); //parameter substitution if (token.startsWith("[-") && token.endsWith("-]")) { StringBuffer newToken = new StringBuffer(); String mapid = getFirst (token,2); String mapinfo = getSecond(token,2); ParameterInfo thisinfo = mother.getProjectData().DB2XMLgetmapping().getParameterByMapID(mapid); newToken.append(thisinfo.getValue ()); result.append(newToken.toString()); } //sql substitution else if (token.startsWith("[") && token.endsWith("]")) { StringBuffer newToken = new StringBuffer(); // [mapid:mapinfo] // evaluierungsschritte: // 1. SQLStatment holen für den angegebenen key String mapid = getFirst (token,1); String mapinfo = getSecond(token,1); //newToken.append("**" + mapid + "=" + mapinfo + "**"); // 2. dbItem holen für das angegebene SQLStatement (siehe XMLSchemaParser) SQLStatement stat = mother.getProjectData().DB2XMLgetmapping().getSQLStatementByMapID(mapid); //newToken.append(stat.toString()); dbItem used_db_item = mother .getProjectData ().getDBByName(stat.getDB ()); Hashtable sql_result; // 3. SQL auf dieser datenbank ausführen: try { String s ub_query = getSubstitution (stat.getSQL()); sql_result = used_db_item.querySilentWithLimit(sub_query,1); // -- bei nur einem resultat -> dieses aus der übereinstimmenden namen (z.B. dbKey) ersetzen // -- bei mehreren resultaten -> einfach das erste nehemn (alternativ oben das limit gleich ändern) // 4. das ganze noch richtig ersetzen (Stringmässig) und dann ab damit zurück nach Hause Vector colnames = (Vector)sql_result.get("columnname"); int col = 0; for (Enumeration en = colnames.elements (); en.hasMoreElements();) { String currname = (String )en.nextElement (); if (currname.equalsIgnoreCase(mapinfo)) { break; } col++; } String info[][] = (String[][])sql_result.get("table"); Autor: Thomas Schädler 130 Anhang A: Quelltext <xmlizer> configurator String resultString = info[col][0]; newToken .append(" "); newToken .append(resultString); result.append(newToken.toString()); counter++; } catch (Exception ex) { mother.getLog().addError (ex); } } else { result.append(" "); result.append(token); } } return result.toString(); } private String resolveQuery(String query ) { //do all data operations on the embedded queries and replace them internally! StringBuffer result = new StringBuffer(); //parse the query and substitute the SQLColumnInfo-Strings //with the real value from the following new statement: (example) result.append(getSubstitution(query)); //achtung! "[..] "könnte probleme machen - format suchen!! return result.toString(); } /** * Shows the specified queries' resultset in a JTable */ synchronized private void doSQL(String sqlQuery,boolean reset) { //finalize for runnable final String ThesqlQuery = sqlQuery; final dbItem theDB = getActiveDB(); if (reset) { theDB.resetLimit(); } this.lastSQLStatement = sqlQuery; Runnable r = new Runnable() { public void run() { String resolvedQuery = resolveQuery(ThesqlQuery); mother.getLog().addInformation("Resolved Query: " + resolvedQuery); Hashtable navData = new Hashtable (); activity.start(false); try { dbTable = theDB.getQueryAsJTable(resolvedQuery); theDB.updateLastSQLSQL(ThesqlQuery ); navData = theDB.getNavigator(); } catch(Exception ex ) { activity .stop(false ); mother.getLog().addError (ex); return; } dbTable.addMouseListener(new java.awt.event .MouseAdapter() { public void mouseClicked (MouseEvent e) { dbTable_mouseClicked (e); } }); dbTable.setAutoResizeMode(autoresize); tableScrollPane.getViewport().add(dbTable); tableScrollPane.setBorder(BorderFactory.createTitledBorder (theDB.getName() + " >> SQL Query Result : Rows " + navData.get("first") + "-" + navData.get("last") + " of " + navData.get("max"))); boolean hasNext = ((Boolean)navData.get("hasNext")).booleanValue(); boolean hasLast = ((Boolean)navData.get("hasLast")).booleanValue(); if (hasNext) { nextMI.setEnabled(true); } else { nextMI.setEnabled(false); } if (hasLast) { lastMI.setEnabled(true); } else { lastMI.setEnabled(false); } mother.getLog().addInformation("SQL Query returned a valid ResultSet."); activity.stop(false); } }; workerThread = new Thread(r); StopAllThreads = false; workerThread.start(); } private void dbTable_mouseClicked(MouseEvent e) { if(SwingUtilities.isRightMouseButton (e)) { popup.show(dbTable,e.getX(),e.getY()); } } private void nextMI_actionPerformed (ActionEvent e) { getActiveDB().nextChunk(); try { doSQL(getActiveDB().getLastSQL(),false); } catch(Exception ex) { mother .getLog().addError(ex); } } Autor: Thomas Schädler 131 Anhang A: Quelltext <xmlizer> configurator private void lastMI_actionPerformed (ActionEvent e) { getActiveDB().lastChunk(); try { doSQL(getActiveDB().getLastSQL(),false); } catch(Exception ex) { mother .getLog().addError(ex); } } private void mniOff_actionPerformed (ActionEvent e) { autoresize = JTable.AUTO_RESIZE_OFF; dbTable.setAutoResizeMode(autoresize ); mniOff.setSelected(true); mniOn.setSelected(false); } private void mniOn_actionPerformed(ActionEvent e) { autoresize = JTable.AUTO_RESIZE_ALL_COLUMNS; dbTable.setAutoResizeMode(autoresize ); mniOff.setSelected(false); mniOn.setSelected(true); } /** * Sets the number of rows to display per DB retrieve */ private void setChunk_actionPerformed(ActionEvent e) { String input = dbItem.Convertint2String(getActiveDB ().getChunkSize ()); String before = new String (input); input = JOptionPane.showInputDialog("Enter the number of rows to show:" ); if ((input != null) && (!input.equalsIgnoreCase(new String())) && (!input.equalsIgnoreCase(before ))) { int newvalue = dbItem.ConvertString2int(input); getActiveDB ().setChunkSize(newvalue); setChunk.setText("Set Rows ("+newvalue+")"); mother .getLog().addInformation("Changed number of rows to display to " + newvalue + "."); } } /** * This method updates the UI if the setupwindow is closed * (and a change in the setup component occured) */ public synchronized void update(configurator conf) { isLoading = true; dbtableList.setEnabled(false); this.mother = conf; this.theData = conf.getProjectData(); if (conf.nextDBToBrowse.size() > 0) { this.dbList = conf.nextDBToBrowse; } else { this.dbList = conf.getProjectData().getDB(); } if (dbList .size() > 0) { dbComboBox.setSelectedIndex (0); } this.repaint(); isLoading = false; } public void enableTakeover(SchemaElement el) { this.takeoverelement = el; this.takeovermode = true; } /** * Returns the currently selected dbItem */ synchronized private dbItem getActiveDB() { return (dbItem)dbComboBox.getSelectedItem (); } /** * Drop-Enabled JTextArea */ class DNDTextArea extends JTextArea implements DropTargetListener { // Constructor public DNDTextArea() { super(); // create a drop target for this component DropTarget dt = new DropTarget(this, this); //this.setForeground(java.awt.Color.red); } /** Returns true if the string contains NO : */ private boolean isValidData(String s ) { int doublepoint = s.indexOf(":"); if (doublepoint < 0) { return true; } else return false; } // DropTargetListener interface implementation public void drop(DropTargetDropEvent event) { /*System.out.println("END > drop");*/ try { Transferable transferable = event .getTransferable(); // we accept only Strings if (transferable.isDataFlavorSupported (DataFlavor.stringFlavor)) { event.acceptDrop(DnDConstants .ACTION_COPY); String s = (String)transferable.getTransferData(DataFlavor.stringFlavor); //System.out.println("DROP >>>>>" + s); Autor: Thomas Schädler 132 Anhang A: Quelltext <xmlizer> configurator if (s != null /*&& isValidData(s)*/) { append(" "); append(s); this.repaint(); } else { mother.getLog().addWarning("You can only drop table results from the Data Chooser!"); } event.getDropTargetContext().dropComplete(true); } else { event.rejectDrop(); } } catch (java.io.IOException exception) { System.err.println ( "Exception" + exception.getMessage()); event.rejectDrop(); } catch (UnsupportedFlavorException ufException ) { System.err.println ( "Exception" + ufException.getMessage()); event.rejectDrop(); } } //REST UNUSED public void dragEnter(DropTargetDragEvent dtde ) { /*System.out.println("END > dragEnter");*/ } public void dragExit (DropTargetEvent dte) { /*System.out.println("END > dragExit");*/ } public void dragOver (DropTargetDragEvent dtde) { /*System.out.println("END > dragOver");*/ } public void dropActionChanged(DropTargetDragEvent dtde) { /*System.out.println("END > dropActionChanged");*/ } } /** * Listens for listItem-(Mouse)-Events on the dbtableList * -> For database queries */ class ItemListener implements MouseListener { protected dbBrowser m_parent; protected JList m_list; public ItemListener(dbBrowser parent ) { m_parent = parent; m_list = parent.dbtableList ; } public void mouseClicked(MouseEvent e) { doAction(); } public {} public {} public {} public {} void mousePressed(MouseEvent e) void mouseReleased(MouseEvent e) void mouseEntered(MouseEvent e) void mouseExited(MouseEvent e ) protected void doAction() { int index = m_list.getSelectedIndex(); if (index < 0) { return; } listItem data = (listItem)m_list .getModel().getElementAt(index ); mother .getLog().addInformation("Retrieving table " + data.getName() + "..."); getActiveDB ().resetLimit(); doSQL("SELECT * FROM " + data.getName(),true); } } }/* * SMDBEmain.java * * Created on 13. Mai 2009, 16:31 * ---------------------------------------------------------------------------* This file is part of <xmlizer>. * * <xmlizer> is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Foobar is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with <xmlizer>; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * ---------------------------------------------------------------------------*/ package configurator; import import import import import import import import import import java.io.*; java.sql.*; java.util.*; org.jdom.*; org.jdom.output.XMLOutputter; java.awt.event.*; javax.swing .event.*; javax.swing .border.*; javax.swing .*; javax.swing .table.*; Autor: Thomas Schädler 133 Anhang A: Quelltext <xmlizer> configurator import import import import import import javax.swing .tree.*; javax.swing .text.*; java.util.Vector ; java.util.Enumeration ; org.xml.sax.*; org.xml.sax.helpers.AttributesImpl; /** * The main class/internalframe of the module SMDBE * @author [email protected] */ public class SMDBEmain extends MyInternalFrame { private configurator mother; private String ID; private JPopupMenu popup = new JPopupMenu(); private JMenu mnuAutoresize = new JMenu(); private JRadioButtonMenuItem mniOn = new JRadioButtonMenuItem("on"); private JRadioButtonMenuItem mniOff = new JRadioButtonMenuItem("off"); private int autoresize = JTable.AUTO_RESIZE_ALL_COLUMNS ; private JMenuItem nextMI ; private JMenuItem lastMI ; private JMenuItem setChunk; private projectData theData; private Vector dbList = new Vector(); private Vector tableList = new Vector(); private Vector levelList = new Vector(); private boolean isLoading = true; private boolean isUpdating = false; private String SPACER = new String(" "); //Thread related private activityMeter activity ; private volatile Thread updateThread = null; private volatile Thread workerThread = null; private volatile Thread controllerThread = null; private boolean StopAllThreads = false; //flag used to stop long tasks (but not the controller thread) public static String XMLSMDBEFILEDTD = "xmlizer.smdbe.verbose.dtd"; public static String XMLSMDBEFILEROOT = "database" ; /** Creates new form SMDBEmain */ public SMDBEmain(configurator mainProgram, String uid) { this.mother = mainProgram; this.ID = uid; this.theData = mainProgram.getProjectData (); this.dbList = this.theData .getDB(); //update the DBList levelList.add("simple"); levelList.add("verbose"); initComponents(); levelComboBox.setSelectedIndex(0); activity = new activityMeter(stopButton,exportProgressBar); //add the popupmenu //add data browser nextMI = new JMenuItem("Next"); lastMI = new JMenuItem("Last"); nextMI.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed (ActionEvent e) { nextMI_actionPerformed(e); } }); lastMI.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed (ActionEve nt e) { lastMI_actionPerformed(e); } }); popup.add(nextMI); popup.add(lastMI); popup.addSeparator(); //add the entry to set the chunksize setChunk = new JMenuItem("Set Rows ("+getActiveDB().getChunkSize()+")"); setChunk.addActionListener (new java.awt.event.ActionListener() { public void actionPerformed (ActionEvent e) { setChunk_actionPerformed(e); } }); popup.add(setChunk); //add autoresize toggle mnuAutoresize.setText("Autoresize"); mnuAutoresize.add(mniOn); mnuAutoresize.add(mniOff); mniOn.setSelected(true); mniOn.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed (ActionEvent e) { mniOn_actionPerformed(e); } }); mniOff.setSelected(false); mniOff.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed (ActionEvent e) { mniOff_actionPerformed(e); } }); popup.add(mnuAutoresize); //init other stuff if (dbList .size() > 0) { dbComboBox.setSelectedIndex(0); } upperPanel .repaint(); Autor: Thomas Schädler 134 Anhang A: Quelltext <xmlizer> configurator isLoading = false; } /** This method is called from within the constructor to * initialize the form. * WARNING: Do NOT modify this code. The content of this method is * always regenerated by the Form Editor. */ private void initComponents() {//GEN-BEGIN:initComponents upperPanel = new javax.swing.JPanel(); dbLabel = new javax.swing.JLabel(); dbComboBox = new javax.swing.JComboBox(dbList); levelComboBox = new javax.swing .JComboBox (levelList ); exportButton = new javax.swing.JButton(); exportProgressBar = new javax.swing.JProgressBar(); stopButton = new javax.swing.JButton(); limitCheckBox = new javax.swing .JCheckBox (); helpButton = new javax.swing.JButton(); obenPanel = new javax.swing.JPanel(); verSplitPane = new javax.swing.JSplitPane (); dbtablePanel = new javax.swing.JPanel(); listScrollPane = new javax .swing.JScrollPane(); dbtableList = new javax.swing.JList(tableList); buttonPanel = new javax.swing.JPanel (); dbTablesLabel = new javax.swing .JLabel(); selectAllButton = new javax.swing.JButton(); tableScrollPane = new javax.swing.JScrollPane(); dbTable = new javax.swing.JTable(); setMaximizable(true); setTitle("Simple Module DB Export"); setIconifiable(true); setResizable(true); dbLabel.setText("Database:"); upperPanel.add(dbLabel); dbComboBox .addActionListener(new java.awt.event.ActionListener() { public void actionPerformed (java.awt.event .ActionEvent evt) { dbComboBoxActionPerformed(evt); } }); upperPanel .add(dbComboBox); levelComboBox.setToolTipText("Output Level"); levelComboBox.addActionListener (new java.awt.event.ActionListener() { public void actionPerformed (java.awt.event .ActionEvent evt) { levelComboBoxActionPerformed (evt); } }); upperPanel .add(levelComboBox); exportButton.setToolTipText("Exports the selected Tables as XML"); exportButton.setText("Export"); exportButton.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed (java.awt.event .ActionEvent evt) { exportButtonActionPerformed(evt); } }); upperPanel .add(expor tButton); exportProgressBar.setToolTipText("Shows the progress for the export thread and DB queries."); exportProgressBar.setPreferredSize(new java.awt.Dimension(148, 21)); exportProgressBar.setMinimumSize(new java.awt.Dimension(10, 21)); upperPanel .add(exportProgressBar); stopButton .setIcon(new javax.swing.ImageIcon(getClass().getResource("/configurator/icons/Stop16.gif"))); stopButton .setToolTipText("Stop background activity..."); stopButton .setEnabled(false); stopButton .addActionListener(new java.awt.event.ActionListener() { public void actionPerformed (java.awt.event .ActionEvent evt) { stopButtonActionPerformed(evt); } }); upperPanel .add(stopButton); limitCheckBox.setToolTipText("If selected, the results are diplayed in browsable chunks, not as one large table."); limitCheckBox.setText("limit"); limitCheckBox.addItemListener(new java.awt.event.ItemListener () { public void itemStateChanged(java.awt.event.ItemEvent evt ) { limitCheckBoxItemStateChanged(evt); } }); upperPanel .add(limitCheckBox); helpButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/configurator/icons/Help16.gif"))); helpButton .setToolTipText("Open Help"); helpButton .setFont(new java.awt.Font("Dialog", 0, 10)); helpButton .addActionListener(new java.awt.event.ActionListener() { public void actionPerformed (java.awt.event .ActionEvent evt) { helpButtonActionPerformed(evt); } }); upperPanel .add(helpButton); getContentPane().add(upperPanel , java.awt.BorderLayout.NORTH); obenPanel.setLayout(new java.awt.BorderLayout()); verSplitPane.setDividerLocation (120); Autor: Thomas Schädler 135 Anhang A: Quelltext <xmlizer> configurator verSplitPane.setOneTouchExpandable(true); dbtablePanel.setLayout(new java.awt.BorderLayout()); listScrollPane.setViewportView(dbtableList); dbtablePanel.add(listScrollPane , java.awt.BorderLayout.CENTER ); buttonPanel.setLayout(new java.awt.GridBagLayout()); java.awt.GridBagConstraints gridBagConstraints1; dbTablesLabel.setText("Tables"); dbTablesLabel.setHorizontalAlignment (javax.swing.SwingConstants.CENTER); gridBagConstraints1 = new java.awt.GridBagConstraints(); gridBagConstraints1.gridx = 0; gridBagConstraints1.gridy = 0; gridBagConstraints1.gridwidth = 2; buttonPanel.add(dbTablesLabel, gridBagConstraints1); selectAllButton .setToolTipText("Select all tables"); selectAllButton .setText("invert selection"); selectAllButton .setMargin(new java.awt.Insets(1, 1, 1, 1)); selectAllButton .addActionListener(new java.awt.event.ActionListener() { public void actionPerformed (java.awt.event .ActionEvent evt) { selectAllButtonActionPerformed(evt); } }); gridBagConstraints1 = new java.awt.GridBagConstraints(); gridBagConstraints1.gridx = 0; gridBagConstraints1.gridy = 1; buttonPanel.add(selectAllB utton , gridBagConstraints1); dbtablePanel.add(buttonPanel, java.awt.BorderLayout .NORTH); verSplitPane.setLeftComponent(dbtablePanel); tableScrollPane .setPreferredSize(new java.awt.Dimension(400, 300)); tableScrollPane .setViewportView (dbTable); verSplitPane.setRightComponent(tableScrollPane ); obenPanel.add(verSplitPane , java.awt.BorderLayout.CENTER ); getContentPane().add(obenPanel, java.awt.BorderLayout.CENTER); pack(); }//GEN-END:initComponents private void levelComboBoxActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_levelComboBoxActionPerformed {//GEN-HEADEREND:event_levelComboBoxActionPerformed // Add your handling code here: if (!isUpdating && !isLoading) { if (levelComboBox.getSelectedItem() != null) { String newLevel = (String)levelComboBox.getSelectedItem(); //System.out.println("SETTIN G LEVEL: "+newLevel); getActiveDB().SMDBEsetOutputType(newLevel); theData.setDirty(); } } }//GEN-LAST:event_levelComboBoxActionPerformed private void limitCheckBoxItemStateChanged(java.awt.event.ItemEvent evt)//GEN-FIRST:event_limitCheckBoxItemStateChanged {//GEN-HEADEREND:event_limitCheckBoxItemStateChanged // Add your handling code here: if (!isUpdating ) { getActiveDB ().setLimit (!getActiveDB().hasLimit()); } }//GEN-LAST:event_limitCheckBoxItemStateChanged private void stopButtonActionPerformed(java.awt.event.ActionEvent evt)//GEN -FIRST:event_stopButtonActionPerformed {//GEN-HEADEREND:event_stopButtonActionPerformed // Add your handling code here: Runnable r = new Runnable() { public void run() { stopButton.setEnabled(false); exportButton .setEnabled (true); activity.init(); StopAllThreads = true; getActiveDB().halt(); mother.getLog().addInformation("Sending stop request..."); } }; controllerThread = new Thread(r); controllerThread.start(); }//GEN-LAST:event_stopButtonActionPerformed private void selectAllButtonActionPerformed(java.awt.event.ActionEvent evt)//GEN FIRST:event_selectAllButtonActionPerformed {//GEN-HEADEREND:event_selectAllButtonActionPerformed // Add your handling code here: for(int i = 0;i<tableList.size();i++) { listItem data = (listItem)dbtableList .getModel(). getElementAt(i); data.toggleSelection(); dbtableList .repaint(); if (data.isSelected()) { getActiveDB().SMDBEselectTable(data.getName()); theData.setDirty(); } else { getActiveDB().SMDBEdeselectTable(data.getName()); theData.setDirty(); Autor: Thomas Schädler 136 Anhang A: Quelltext <xmlizer> configurator } } }//GEN-LAST:event_selectAllButtonActionPerformed private void helpButtonActionPerformed(java.awt.event.ActionEvent evt)//GEN -FIRST:event_helpButtonActionPerformed {//GEN-HEADEREND:event_helpButtonActionPerformed // Add your handling code here: helpWindow help = (helpWindow)mother .open("help"); help.loadPage("/configurator/help/module_smdbe_main.html"); }//GEN-LAST:event_helpButtonActionPerformed private void dbComboBoxActionPerformed(java.awt.event.ActionEvent evt)//GEN -FIRST:event_dbComboBoxActionPerformed {//GEN-HEADEREND:event_dbComboBoxActionPerformed // Add your handling code here: if (!isLoading) { updateDB(); //updates the DB Browser } }//GEN-LAST:event_dbComboBoxActionPerformed private void exportButtonActionPerformed (java.awt.event .ActionEvent evt)//GEN-FIRST:event_exportButtonActionPerformed {//GEN-HEADEREND:event_exportButtonActionPerformed // Add your handling code here: doExport(); }//GEN-LAST:event_exportButtonActionPerformed // Variables declaration - do not modify//GEN -BEGIN:variables private javax.swing .JPanel upperPanel; private javax.swing .JLabel dbLabel; private javax.swing.JComboBox dbComboBox ; private javax.swing .JComboBox levelComboBox; private javax.swing .JButton exportButton ; private javax.swing .JProgressBar exportProgressBar ; private javax.swing .JButton stopButton; private javax.swing .JCheckBox limitCheckBox; private javax.swing .JButton helpButton; private javax.swing .JPanel obenPanel; private javax.swing .JSplitPane verSplitPane; private javax.swing .JPanel dbtablePanel; private javax.swing .JScrollPane listScrollPane; private javax.swing .JList dbtableList; private javax.swing .JPanel buttonPanel; private javax.swing .JLabel dbTablesLabel ; private javax.swing .JButton selectAllButton; private javax.swing .JScrollPane tableScrollPane; private javax.swing .JTable dbTable; // End of variables declaration//GEN-END:variables /** * Updated the List of the Database -Tables */ synchronized private void updateDB() { mother.getLog().addInformation("Retrieving tables from selected database..."); final dbItem theDB = getActiveDB(); final SMDBEmain This = this; if (theDB != null) { Runnable r = new Runnable() { public void run() { activity .start (false); dbtableList.setEnabled(false); //set limit and level isUpdating = true; limitCheckBox.setSelected(theDB.hasLimit()); levelComboBox.setSelectedItem (theDB.SMDBEgetOutputType ()); isUpdating = false; try { tableList = theDB.getTableList (); //vector of listItems } catch(Exception e) { activity.stop(false); mother.getLog().addError(e); return; } //make the new list and set the renderer dbtableList = new JList(tableList); CheckListCellRenderer renderer = new CheckListCellRenderer(); dbtableList.setCellRenderer(renderer); CheckListener lst = new CheckListener(This); dbtableList.addMouseListener(lst); ItemListener ilst = new ItemListener(This); dbtableList.addMouseListener(ilst); //set the selectionModel for the JList dbtableList.getSelectionModel ().setSelectionMode(ListSelectionModel.SINGLE_SELECTION); //show the new list listScrollPane .getViewport().add(dbtableList ); dbtableList.setEnabled(true); setChunk .setText("Set Rows (" +theDB.getChunkSize()+")"); mother.getLog().addInformation("Tablelist updated."); activity .stop(false ); } }; updateThread = new Thread(r); StopAllThreads = false ; updateThread.start(); } } Autor: Thomas Schädler 137 Anhang A: Quelltext <xmlizer> configurator /** * Shows the indicated table of the curr ent database */ private void doSQL(String sqlQuery) { //finalize for runnable final String ThesqlQuery = sqlQuery; final dbItem theDB = getActiveDB(); Runnable r = new Runnable() { public void run() { Hashtable navData = new Hashtable (); activity.start(false); try { dbTable = theDB.getQueryAsJTable(ThesqlQuery ); navData = theDB.getNavigator(); } catch(Exception ex ) { activity .stop(false ); mother.getLog().addError (ex); return; } dbTable.addMouseListener(new java.awt.event .MouseAdapter() { public void mouseClicked (MouseEvent e) { dbTable_mouseClicked (e); } }); dbTable.setAutoResizeMode(autoresize); tableScrollPane.getViewport().add(dbTable); tableScrollPane.setBorder(BorderFactory.createTitledBorder (theDB.getName() + " >> SQL Query Result : Rows " + navData.get("first") + "-" + navData.get("last") + " of " + navData.get("max"))); boolean hasNext = ((Boolean)navData.get("hasNext")).booleanValue(); boolean hasLast = ((Boolean)navData.get("hasLast")).booleanValue(); if (hasNext) { nextMI.setEnabled(true); } else { nextMI.setEnabled(false); } if (hasLast) { lastMI.setEnabled(true); } else { lastMI.setEnabled(false); } mother.getLog().addInformation("SQL Query returned a valid ResultSet."); activity.stop(false); } }; workerThread = new Thread(r); StopAllThreads = false; workerThread.start(); } /** * Exports the selected Tables to the outputwindow (editorpane) * and sets the selected tables in the dbItem (mapping info) */ private void doExport() { //get the selected tables for this DB final dbItem theDB = getActiveDB(); final Vector selectedTables = getSelectedTables(); //do sample/preview export in a new stoppable thread Runnable r = new Runnable() { public void run() { activity.start(true); dbComboBox.setEnabled(false); exportButton .setEnabled (false); levelComboBox.setEnabled(false); mother.getLog().addInformation("Exporting selected tables as XML..." ); //export the data from the selected db and output the xml to the editorpane try { //NEW STYLE outputXMLResult(theDB,selectedTables,out); String level = (String)levelComboBox.getSelectedItem(); File file = null; if (level == null || level.equalsIgnoreCase(new String ())) { level = "simple"; } if (level.equalsIgnoreCase("simple")) { file = outputXMLResultSimple(theDB,selectedTables); } else if (level .equalsIgnoreCase("verbose")) { file = outputXMLResultVerbose(theDB ,selectedTables ); } mother.getLog().addNewTab("DB Export:"+theDB .getName(),file,"DB Export Preview for DB: " + theDB.getName()); } catch (Exception ex) { mother.getLog().addError (ex); } dbComboBox.setEnabled(true); levelComboBox.setEnabled(true); if (StopAllThreads ) { mother.getLog().addWarning("Export aborted by user ... preview output may me incomplete!"); } else { mother.getLog().addInformation("XML Export successful terminated."); } exportButton .setEnabled (true); activity.stop(true); } }; Autor: Thomas Schädler 138 Anhang A: Quelltext <xmlizer> configurator workerThread = new Thread(r); workerThread.setDaemon(true); StopAllThreads = false; workerThread.start(); } /** * Generates Simple DB Export XML from a selected DB and writes it to a temporary file * Therfore it uses no DTD and writes just plain XML without any extra data * @return a temprary file filled with XML */ private File outputXMLResultSimple(dbItem theDB,Vector tables) throws Exception { File temp = File.createTempFile ("xmlizer" ,null); temp.deleteOnExit(); FileOutputStream out = new FileOutputStream(temp); //add the header and doctype out.write(configurator.String2byteArray("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n",null)); //add the <database name="dbname" url="dburl"> tag out.write(configurator.String2byteArray("<database name= \"" +configurator.htmlEncode(theDB.getName()) +"\" url=\"" +configurator.htmlEncode(theDB.getUrl()) +"\">\n",null)); //monitor progress of export per table final int maxi = tables.size(); activity.setMax (maxi); int counter = 0; //tables setup out.write(configurator.String2byteArray(SPACER +"<tables> \n",null)); //for all tables Runnable r ; for (Enumeration e = tables.elements (); e.hasMoreElements();) { if (StopAllThreads) { out.close(); return temp; } counter++; final int rcounter = counter; r = new Runnable () { public void run() { activity .setValue(rcounter); activity .setString(rcounter + " / " + maxi); } }; SwingUtilities.invokeLater(r); //add the <table name="tablename"> tag String this_table = (String )e.nextElement(); out.write(configurator .String2byteArray(SPACER+SPACER+"<"+this_table+">\n",null)); try { Hashtable theTable = theDB.querySilent ("SELECT * FROM " + this_table ); final String data[][] = (String[][])theTable.get("table"); final int rows = ((Integer)theTable.get("rows")).intValue(); final int cols = ((Integer)theTable.get("cols")).intValue(); final Vector columnnames = (Vector)theTable .get("columnlabels"); //for each row of this table for(int i=0;i<rows;i++) { out.write(configurator.String2byteArray (SPACER+SPACER+SPACER+"<row>\n",null)); //for each column of the row String encoded ; String colname ; for(int j=0;j<cols;j++) { colname = configurator.htmlEncode((String)columnnames.get(j)); out.write(configurator.String2byteArray(SPACER+SPACER+SPACER +SPACER+"<"+colname+">",null)); encoded = configurator.htmlEncode((String)data[j][i]); out.write(configurator.String2byteArray(encoded,null)); out.write(configurator.String2byteArray("</"+colname+">\n",null)); } out.write(configurator.String2byteArray (SPACER+SPACER+SPACER+"</row>\n",null)); } out.write(configurator.String2byteArray(SPACER+SPACER +"</"+this_table+">\n",null)); } catch (Exception eq) { mother.getLog().addError(eq); } } out.write(configurator.String2byteArray(SPACER +"</tables>\n",null)); out.write(configurator.String2byteArray("</database>\n",null)); out.close(); return temp; } /** * Generates Simple DB Export XML from a selected DB and writes it to a temporary file * @return a temprary file filled with XML */ private File outputXMLResultVerbose (dbItem theDB,Vector tables) throws Exception { File temp = File.createTempFile ("xmlizer" ,null); temp.deleteOnExit(); FileOutputStream out = new FileOutputStream(temp); //add the header and doctype out.write(configurator.String2byteArray("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n",null)); out.write(configurator.String2byteArray("<!DOCTYPE database SYSTEM \""+XMLSMDBEFILEDTD +"\">\n",null)); //add the <database name="dbname" url="dburl"> tag out.write(configurator.String2byteArray("<database name= \"" +configurator.htmlEncode(theDB.getName()) Autor: Thomas Schädler 139 Anhang A: Quelltext <xmlizer> configurator +"\" url=\"" +configurator.htmlEncode(theDB.getUrl()) +"\">\n",null)); //monitor progress of export per table final int maxi = tables.size(); activity.setMax (maxi); int counter = 0; //tables setup out.write(configurator.String2byteArray(SPACER +"<tables> \n",null)); //for all tables Runnable r ; for (Enumeration e = tables.elements (); e.hasMoreElements();) { if (StopAllThreads) { out.close(); return temp; } counter++; final int rcounter = counter; r = new Runnable () { public void run() { activity .setValue(rcounter); activity .setString(rcounter + " / " + maxi); } }; SwingUtilities.invokeLater(r); //add the <table name="tablename"> tag String this_table = (String )e.nextElement(); out.write(configurator .String2byteArray(SPACER+SPACER+"<table name= \""+this_table+"\">\n",null)); try { Hashtable theTable = theDB.querySilent ("SELECT * FROM " + this_table ); final String data[][] = (String[][])theTable.get("table"); final int rows = ((Integer)theTable.get("rows")).intValue(); final int cols = ((Integer)theTable.get("cols")).intValue(); final Vector columnnames = (Vector)theTable .get("columnlabels"); final Vector columntypes = (Vector)theTable .get("columntypes"); //for each row of this table for(int i=0;i<rows;i++) { out.write(configurator.String2byteArray (SPACER+SPACER+SPACER+"<row>\n",null)); //for each column of the row String encoded ; for(int j=0;j<cols;j++) { out.write(configurator.String2byteArray(SPACER+SPACER+SPACER +SPACER+"<column",null)); encoded = configurator.htmlEncode((String)columnnames.get(j)); out.write(configurator.String2byteArray(" name=\""+encoded+"\"",null)); encoded = configurator.htmlEncode((String)columntypes.get(j)); out.write(configurator.String2byteArray(" type=\""+encoded+"\"",null)); encoded = configurator.htmlEncode((String)data[j][i]); out.write(configurator.String2byteArray(" data=\""+encoded+"\"/>\n",null)); } out.write(configurator.String2byteArray (SPACER+SPACER+SPACER+"</row>\n",null)); } out.write(configurator.String2byteArray(SPACER+SPACER +"</table> \n",null)); } catch (Exception eq) { mother.getLog().addError(eq); } } out.write(configurator.String2byteArray(SPACER +"</tables>\n",null)); out.write(configurator.String2byteArray("</database>\n",null)); out.close(); return temp; } /** * Returns a vector containing all selected tables as string (tablename) */ synchronized public Vector getSelectedTables() { Vector result = new Vector (); for(int i = 0;i<tableList.size();i++) { listItem data = (listItem)dbtableList .getModel(). getElementAt(i); if (data.isSelected()) { result.add(data.getName()); } } return result; } private void dbTable_mouseClicked(MouseEvent e) { if(SwingUtilities.isRightMouseButton (e)) { popup.show(dbTable,e.getX(),e.getY()); } } private void nextMI_actionPerformed (ActionEvent e) { getActiveDB().nextChunk(); try { doSQL(getActiveDB().getLastSQL()); } catch(Exception ex) { mother .getLog().addError(ex); } } private void lastMI_actionPerformed (ActionEvent e) { getActiveDB().lastChunk(); try { doSQL(getActiveDB().getLastSQL()); Autor: Thomas Schädler 140 Anhang A: Quelltext <xmlizer> configurator } catch(Exception ex) { mother .getLog().addError(ex); } } private void mniOff_actionPerformed (ActionEvent e) { autoresize = JTable.AUTO_RESIZE_OFF; dbTable.setAutoResizeMode(autoresize ); mniOff.setSelected(true); mniOn.setSelected(false); } private void mniOn_actionPerformed(ActionEvent e) { autoresize = JTable.AUTO_RESIZE_ALL_COLUMNS; dbTable.setAutoResizeMode(autoresize ); mniOff.setSelected(false); mniOn.setSelected(true); } /** * Sets the number of rows to display per DB retrieve */ private void setChunk_actionPerformed(ActionEvent e) { String input = dbItem.Convertint2String(getActiveDB ().getChunkSize ()); String before = new String (input); input = JOptionPane.showInputDialog("Enter the number of rows to show:" ); if ((input != null) && (!input.equalsIgnoreCase(new String())) && (!input.equalsIgnoreCase(before ))) { int newvalue = dbItem.ConvertString2int(input); getActiveDB ().setChunkSize(newvalue); setChunk.setText("Set Rows ("+newvalue+")"); mother .getLog().addInformation("Changed number of rows to display to " + newvalue + "."); } } /** * This method updates the UI if the setupwindow is closed * (and a change in the setup component occured) */ public synchronized void update(configurator conf) { isLoading = true; dbtableLis t.setEnabled(false); //be sure, perhaps the db got deleted!? who knows! this.mother = conf; this.theData = conf.getProjectData(); this.dbList = conf.getProjectData().getDB (); //update the DBList //System.out.println (dbList.toString()); this.dbComboBox .setModel(new DefaultComboBoxModel(this.dbList )); if (this.dbList .size() > 0) { this.dbComboBox.setSelectedIndex (0); } this.repaint(); isLoading = false; } /** * Returns the currently selected dbItem */ synchronized private dbItem getActiveDB() { return (dbItem)dbComboBox.getSelectedItem (); } /** * Listens for listItem-(Mouse)-Events on the dbtableList * -> For database queries */ class ItemListener implements MouseListener { protected SMDBEmain m_parent; protected JList m_list; public ItemListener(SMDBEmain parent ) { m_parent = parent; m_list = parent.dbtableList ; } public void mouseClicked(MouseEvent e) { if (e.getX() > 20) { doAction(); } } public {} public {} public {} public {} void mousePressed(MouseEvent e) void mouseReleased(MouseEvent e) void mouseEntered(MouseEvent e) void mouseExited(MouseEvent e ) protected void doAction() { int index = m_list.getSelectedIndex(); if (index < 0) { return; } listItem data = (listItem)m_list .getModel().getElementAt(index ); mother .getLog().addInformation("Retrieving table " + data.getName() + "..."); getActiveDB().resetLimit(); doSQL("SELECT * FROM " + data.getName()); } } /** Autor: Thomas Schädler 141 Anhang A: Quelltext <xmlizer> configurator * Listens for CheckBox-(Mouse)-Events on the dbtableList * -> For table-selection */ class CheckListener implements MouseListener { protected SMDBEmain m_parent; protected JList m_list; public CheckListener (SMDBEmain parent) { m_parent = parent; m_list = parent.dbtableList ; } public void mouseClicked(MouseEvent e) { if (e.getX() < 20) { doCheck(); } } public {} public {} public {} public {} void mousePressed(MouseEvent e) void mouseReleased(MouseEvent e) void mouseEntered(MouseEvent e) void mouseExited(MouseEvent e ) protected void doCheck() { int index = m_list.getSelectedIndex(); if (index < 0) { return; } listItem data = (listItem)m_list .getModel().getElementAt(index ); data.toggleSelection(); m_list .repaint(); if (data.isSelected()) { getActiveDB().SMDBEselectTable(data.getName()); m_parent.theData.setDirty(); } else { getActiveDB().SMDBEdeselectTable(data.getName()); m_parent.theData.setDirty(); } } } /** * Renders the cells for the dbtableList (JList) with CheckBoxes etc. */ class CheckListCellRenderer extends JCheckBox implements ListCellRenderer { protected final Border m_noFocusBorder = new EmptyBorder (1, 1, 1, 1); public CheckListCellRenderer() { super(); setOpaque(true); setBorder(m_noFocusBorder); } public java.awt.Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { setText(value.toString ()); setBackground(isSelected ? list.getSelectionBackground() : list.getBackground ()); setForeground(isSelected ? list.getSelectionForeground() : list.getForeground ()); listItem data = (listItem)value; setSelected (data.isSelected ()); setFont(list.getFont()); setBorder((cellHasFocus) ? UIManager.getBorder("List.focusCellHighlightBorder") : m_noFocusBorder); return this; } } } /* * projectData.java * * This projectData container contains all neccessary methods to deal * with the projectData management * * Created on 5. April 2002, 16:30 * ------------------------------------------------------------------ ---------* This file is part of <xmlizer>. * * <xmlizer> is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the Licens e, or * (at your option) any later version. * * Foobar is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with <xmlizer>; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * ---------------------------------------------------------------------------*/ package configurator; import import import import java.io.*; java.util.*; java.lang.*; javax.swing .*; Autor: Thomas Schädler 142 Anhang A: Quelltext <xmlizer> configurator import org.jdom.*; import org.jdom.input.SAXBuilder; import org.jdom.output.XMLOutputter; /** * Represents the data for a project with all methods to change and add * @author [email protected] * @version 0.7 */ public class projectData { public static String XMLPROJECTFILEDTD = "xmlizer.project.config.dtd"; public static String XMLPROJECTFILEROOT = "xmlizerprojectconfig"; private private private private private boolean dirty = true; //set initially on true because never saved Vector initial = new Vector (0); //holds dataItems Vector xml = new Vector(0); //holds xmlItems Vector dbs = new Vector(0); //holds dbItems DB2XMLmapping mapping = new DB2XMLmapping(); //holds the mapping-info for the DB2XML-Module //CONSTRUCTOR //----------------- -----------------------------------------------------------------------------/** * Creates new projectData (Constructor) */ public projectData() { //init here if neccessary } //DIRTY MANAGEMENT //----------------------------------------------------------------------------------------------/** * Shows us if the data has changed scince the last save operation */ public boolean isDirty() { return dirty; } /** * Mark the data as dirty */ public void setDirty() { this.dirty = true; } /** * Reset dirty state */ public void save() { dirty = false; } //SAVE LOCATION == initial_dataitem("name") //----------------------------------------------------------------------------------------------public void setSaveLocation(String loc) { setInitialByKey ("name",loc); } public String getSaveLocation() { dataItem item = getInitialByKey ("name"); String pro_name = item.getValue (); return System.getProperty("file.separator") + pro_name + System.getProperty("file.separator" ); } //INITIAL MANAGEMENT //----------------------------------------------------------------------------------------------/** * Returns a Vector -> project variables as dataItems */ public Vector getInitial () { return initial; } public void addInitial(dataItem dataitem ) { initial.add(dataitem ); dirty = true; } public dataItem getInitialByKey(String key) { for (Enumeration e = this.initial.elements(); e.hasMoreElements();) { dataItem item = (dataItem)e.nextElement(); if (item.getKey().equalsIgnoreCase(key)) { return item; } } return null; } public void setInitialByKey(String key,String new_value ) { for (Enumeration e = this.initial.elements(); e.hasMoreElements();) { dataItem item = (dataI tem)e.nextElement(); if (item.getKey().equalsIgnoreCase(key)) { item.setValue(new_value ); return; } } dataItem newitem = new dataItem (); newitem.setKey(key); newitem.setValue(new_value ); addInitial (newitem); //System.out.println("Added new Item: " + key + " [" + new_value + "]"); } //XML FILES MANAGEMENT //----------------------------------------------------------------------------------- -----------/** * Returns a Vector -> XML-Files as String (whole path or url) */ public Vector getXML() { return xml; Autor: Thomas Schädler 143 Anhang A: Quelltext <xmlizer> configurator } public void addXML(xmlItem xmlitem) { xml.add(xmlitem); dirty = true; } synchronized public void removeXML(String identifier) { for (Enumeration e = xml.elements(); e.hasMoreElements();) { xmlItem xmlitem = (xmlItem)e.nextElement(); if (xmlitem.getName().equalsIgnoreCase(identifier)) { xml.remove(xmlitem ); dirty = true; break; } } } public void setXML(Vector newXML) { xml = newXML; dirty = true; } //DATABASE MANAGEMENT //----------------------------------------------------------------------------------------------/** * Returns a Vector -> databases as dbItem */ public Vector getDB () { return dbs; } public void addDB(dbItem dbitem) { dbs.add(dbitem); dirty = true; } synchronized public void removeDB(String identifier) { for (Enumeration e = dbs.elements(); e.hasMoreElements();) { dbItem dbitem = (dbItem)e.nextElement (); if (dbitem.getName().equalsIgnoreCase (identifier)) { dbitem.closeConnection(); dbs.remove(dbitem); dirty = true; break; } } } synchronized public void setDB (Vector newDB) { dbs = newDB; dirty = true; } public dbItem getDBByName(String name) { for (Enumeration e = this.dbs.elements(); e.hasMoreElements();) { dbItem item = (dbItem)e.nextElement(); if (item.getName().equalsIgnoreCase(name)) { return item; } } return null; } //OBJECT FINALIZATION (CLEANUP) //----------------------------------------------------------------------------------------------/** * Do the cleanup before diposing */ public void finalize() { //close all connections for (Enumeration e = dbs.elements(); e.hasMoreElements();) { dbItem dbitem = (dbItem)e.nextElement (); dbitem .closeConnection (); } } //STRING REPRESENTATION //----------------------------------------------------------------------------------------------public String toString() { StringBuffer result = new StringBuffer("FULL PROJECTDATA >>\n"); for (Enumeration e = this.initial.elements(); e.hasMoreElements();) { dataItem item = (dataItem)e.nextElement(); result .append(item); } for (Enumeration e = this.xml.elements(); e.hasMoreElements();) { result .append("\nXML >> " + e.nextElement()); } for (Enumeration e = this.dbs.elements(); e.hasMoreElements();) { dbItem item = (dbItem)e.nextElement(); result .append(item); } return result.toString(); } //XML REPRESENTATION //----------------------------------------------------------------------------------------------/** * Checks the doctype of the XML-File (just to be sure to read the right information) */ private boolean checkDocType(DocType dt,String rootelement,String systemdtd ,logWindow log) { if (dt.getElementName().equalsIgnoreCase(rootelement) && dt.getSystemID ().equalsIgnoreCase(systemdtd)) { log.addDebug("docType OK: " + dt.getElementName () + " : " + dt.getSystemID()); return true; } else { log.addDebug("docType NOT OK: " + dt.getElementName() + " : " + dt.getSystemID()); JOptionPane .showMessageDialog( null, Autor: Thomas Schädler 144 Anhang A: Quelltext <xmlizer> configurator configurator.niceFormat("The DocumentType of this document does not match the requirements. This file must conform to this DTD [" + systemdtd + "] and start with this RootElement [" + rootelement + "]."), configurator.APPNAME + " project dtd error", JOptionPane .INFORMATION_MESSAGE, new javax.swing.ImageIcon(getClass().getResource("/configurator/pics/projectloaderror.gif")) ); return false; } } /* * Reads an XML file (wh ich must be of type xmlizer.project.config.dtd) and * fills all information in the projectdata * * @param The filename as String * @param The logWindow (to indicate errors etc...) */ synchronized public boolean readFromFile (String filename,logWindow log ) { boolean docOK = false; try { SAXBuilder builder = new SAXBuilder(true); Document jdoc = builder.build(filename); //true -> validating against dtd DocType docType = jdoc.getDocType(); docOK = checkDocType(docType,XMLPROJECTFILEROOT ,XMLPROJECTFILEDTD,log); String mappingModule = null; if (docOK) { //get the root Element root = jdoc.getRootElement(); //get the initialsetup Element initsetup = root.getChild ("initialsetup" ); java.util.List initlist = initsetup.getChildren("inititem" ); Iterator init_iter = initlist.iterator (); while (init_iter.hasNext()) { Element init_item = (Element) init_iter .next(); dataItem initialdataitem = new dataItem (); if (init_item.getAttributeValue("key").equalsIgnoreCase("module" )) { mappingModule = init_item .getTextTrim(); //save the mapping module info } initialdataitem.setKey(init_item.getAttributeValue("key")); initialdataitem.setValue (init_item .getTextTrim()); addInitial(initialdataitem); } //get the databasesetup Element dbsetup = root.getChild("databasesetup"); java.util.List dblist = dbsetup.getChildren ("dbitem"); Iterator db_iter = dblist.iterator(); while (db_iter.hasNext()) { Element db_item = (Element) db_iter.next(); dbItem initialdbitem = new dbItem(); initialdbitem.setName(db_item.getChild("name").getTextTrim()); initialdbitem.setDriver(db_item.getChild("driver" ).getTextTrim()); initialdbitem.setUrl(db_item.getChild("url").getTextTrim()); initialdbitem.setTimeout (db_item.getChild("timeout").getTextTrim ()); initialdbitem.setUsername(db_item.getChild("username").getTextTrim()); initialdbitem.setPassword(db_item.getChild("password").getTextTrim()); addDB(initialdbitem ); } //get the schemasetup Element xmlsetup = root.getChild("schemasetup"); java.util.List xmllist = xmlsetup .getChildren("xmlitem"); Iterator xml_iter = xmllist.iterator(); while (xml_iter.hasNext()) { Element xml_item = (Element) xml_iter.next(); xmlItem xmlitem = new xmlItem(); xmlitem.setName(xml_item .getChild("name").getTextTrim()); xmlitem.setFile(xml_item .getChild("file").getTextTrim()); addXML(xmlitem ); } //get the mapping infor mation depending on mappingModule if(mappingModule != null) { Element maproot = root.getChild("mapping"); if (maproot != null) { if (mappingModule.equalsIgnoreCase("Simple DB Export")) { Element smdberoot = maproot.getChild ("smdbe"); java.util.List smdbeitemlist = smdberoot.getChildren("smdbe_item"); Iterator smdbe_iter = smdbeitemlist.iterator(); String dbName = null; String level = null; while (smdbe_iter.hasNext()) { Element smdbe_item = (Element) smdbe_iter.next(); dbName = smdbe_item.getAttributeValue ("name"); level = smdbe_item.getAttributeValue("type"); Autor: Thomas Schädler //<smdbe_item name="dbname"> 145 Anhang A: Quelltext <xmlizer> configurator java.util.List smdbetablelist = smdbe_item .getChildren("smdbe_table" ); Iterator smdbetable_iter = smdbetablelist.iterator(); Vector selTab = new Vector(); while (smdbetable_iter .hasNext()) { Element smdbe_table_item = (Element) smdbetable_iter.next(); selTab.add(smdbe_table_item.getTextTrim()); } if (selTab.size()>0 && dbName != null && level != null) { dbItem selDB = getDBByName(dbName ); selDB.SMDBEsetSelectedTables (selTab); selDB.SMDBEsetOutputType(level); //System.out.println(dbName + " : " + selTab.toString()); } } } else if (mappingModule.equalsIgnoreCase("Database to XML")) { Element db2xmlroot = maproot.getChild("db2xml" ); String elementRoot = db2xmlroot .getAttributeValue("rootelement"); if (elementRoot != null) { mapping.setRootElement (elementRoot); } //parameter s java.util.List para_list = db2xmlroot.getChildren("db2xml_parameter"); Iterator para_iter = para_list.iterator(); while (para_iter .hasNext()) //for all db2xml_element tag s { Element p_item = (Element) para_iter.next(); String parID = p_item.getAttributeValue("id"); String parName = p_item.getAttributeValue("name"); String parValue = p_item.getAttributeValue ("default" ); //mark this element as loaded -> no dirty check while parsing. mapping.addParameterFromLoa d(parID,parName,parValue); } //elements java.util.List element_list = db2xmlroot.getChildren("db2xml_element"); Iterator element_iter = element_list.iterator(); String el_name = null; String el_rep = null; String el_id = null; while (element_iter.hasNext()) //for all db2xml_element tags { Element el_item = (Element) element_iter.next(); //<db2xml_element id="id" name="el_name"> el_name = el_item.getAttributeValue("name"); el_id = el_item.getAttributeValue("id"); //mark this element as loaded -> no dirty check while parsing. mapping.addElementFromLoad(el_name,el_id); //build repetition el_rep = el_item.getAttributeValue("repsql"); if (el_rep != null) { mapping.addElementRepFromLoad(el_id,el_rep); } //build content Element content_el = el_item.getChild ("db2xml_content"); if (content_el != null) { String temp_mapid = content_el.getAttributeValue ("mapid"); String temp_mapinfo = content_el.getAttributeValue("mapinfo"); SchemaContent temp_cont = new SchemaContent (el_id,temp_mapid,temp_mapinfo); mapping.addContentFromLoad(el_id,temp_cont); //System.out.println("Added content: " + temp_cont.toString()); } //build attributes java.util.List attr_list = el_item.getChildren("db2xml_attribute"); Iterator attr_iter = attr_list.iterator(); while (attr_iter.hasNext()) //for all db2xml_attribute tags { Element attr_item = (Element) attr_iter.next(); String temp_attr_name = attr_item .getAttributeValue("name" ); String temp_mapid = attr_item.getAttributeValue("mapid"); String temp_mapinfo = attr_item.getAttributeValue("mapinfo"); SchemaAttribute temp_attr = new SchemaAttribute(temp_attr_name,temp_mapid,temp_mapinfo); mapping.addAttributeFromLoad (el_id,temp_attr); //System.out.println("Added attr: " + temp_attr.toString()); } //build sql java.util.List sql_list = el_item.getChildren("db2xml_sql"); Iterator sql_iter = sql_list.iterator (); while (sql_iter.hasNext()) //for all db2xml_sql tags { Element sql_item = (Element) sql_iter.next(); String temp_db_name = sql_item.getAttributeValue ("db"); String temp_sql = sql_item.getAttributeValue("sql"); String temp_id = sql_item.getAttributeValue ("id"); SQLStatement temp_stat = new SQLStatement(temp_db_name,temp_sql,temp_id); //System.out.println("Added: " + temp_stat.toString()); java.util.List tsql_list = sql_item.getChildren("db2xml_sql_info"); Iterator tsql_iter = tsql_list.iterator(); while (tsql_iter.hasNext()) //for all db2xml_sql_info tags { Element tsql_item = (Element) tsql_iter .next(); String temp_col_name= tsql_item.getAttributeValue ("name"); String temp_col_type = tsql_item.getAttributeValue("type"); Autor: Thomas Schädler 146 Anhang A: Quelltext <xmlizer> configurator temp_stat .addColName(temp_col_name ); temp_stat .addColType(temp_col_type ); //System.out.println("NAME="+temp_col_name+" >> TYPE="+temp_col_type); } mapping.addSQLFromLoad(el_id ,temp_stat ); //System.out.println("READ FROM FILE: " + el_id + " > " + temp_stat.toString()); } } } } } return true; } else { log.addError ("The docType is not OK, " + XMLPROJECTFILEDTD + " is needed!"); return false ; } } catch (JDOMException e) { String the_error_message = new String ( "An ERROR occured while processing the projectconfig file!\n" + "Make sure your configuration [" + filename + "]\n" + "and the according DTD [" + XMLPROJECTFILEDTD + "]\n" + "is located in THE SAME DIRECTORY.\n\n" + "Original Error Message:\n"); String the_error_string = e.toString(); the_error_string = configurator.niceFormat (the_error_string); JOptionPane .showMessageDialog( null, the_error_message + the_error_string, configurator.APPNAME + " project loader error", JOptionPane .ERROR_MESSAGE, new javax.swing.ImageIcon(getClass().getResource("/configurator/pics/projectloaderror.gif")) ); return false; } } /** * Return the data as String */ public String getAsXMLText() { Document jdoc = this.getAsXMLDocumentJDOM (); org.jdom.output .DOMOutputter outp = new org.jdom.output.DOMOutputter(); XMLOutputter fmt = new XMLOutputter(" return fmt.outputString(jdoc); ",true); } /** * Return the data as XML Document (org.w3c.dom.Document) */ public org.w3c.dom.Document getAsXMLDocumentW3C() { Document jdoc = this.getAsXMLDocumentJDOM (); org.jdom.output .DOMOutputter outp = new org.jdom.output.DOMOutputter(); try { org.w3c.dom.Document result = outp.output(jdoc); return result; //and return the result } catch (JDOMException e) { System .out.println("DOM Serializer error for debug output!"); return null; } } /** * Return the data as XML Document org.jdom.Document */ public synchronized Document getAsXMLDocumentJDOM() { //MAKE DOCTYPE DocType docType = new DocType(XMLPROJECTFILEROOT,XMLPROJECTFILEDTD ); Element root = new Element (XMLPROJECTFILEROOT); //initialsetup Element init = new Element ("initialsetup" ); for (Enumeration e = this.initial.elements(); e.hasMoreElements();) { dataItem ditem = (dataItem)e.nextElement(); Element init_item = new Element("inititem" ).setText(ditem .getValue()); init_item.setAttribute ("key",ditem.getKey()); init.addContent(init_item); } root.addContent (init); //db setup Element dbitems = new Element("databasesetup"); for (Enumeration e = this.dbs.elements(); e.hasMoreElements();) { dbItem dbitem = (dbItem)e.nextElement (); Element db_item = new Element("dbitem"); db_item.addContent(new db_item.addContent(new db_item.addContent(new db_item.addContent(new db_item.addContent(new db_item.addContent(new Element("name" ).setText(dbitem.getName())); Element("driver").setText(dbitem.getDriver())); Element("url").setText(dbitem .getUrl())); Element("timeout").setText(dbitem.getTimeout ())); Element("username").setText(dbitem .getUsername())); Element("password").setText(dbitem .getPassword())); dbitems.addContent(db_item); } Autor: Thomas Schädler 147 Anhang A: Quelltext <xmlizer> configurator root.addContent (dbitems); //schema setup Element schms = new Element("schemasetup" ); for (Enumeration e = this.xml.elements(); e.hasMoreElements();) { xmlItem sitem = (xmlItem)e.nextE lement(); Element schms_item = new Element("xmlitem" ); schms_item.addContent(new Element("name").setText(sitem.getName())); schms_item.addContent(new Element("file").setText(sitem.getFile())); schms.addContent (schms_item ); } root.addContent (schms); //module mapping setup Element mapping = null; try { mapping = getMapping(); } catch(Exception ex) { System .out.println("getMapping() in projectData == NULL, should only happen if there is an error in the DB2XML Mapping."); mapping = null; } if (mapping != null) { root.addContent(mapping); } Document doc = new Document(root,docType); return doc; //and return the doc } /** * Get the DB2XML-Mapping */ public DB2XMLmapping DB2XMLgetmapping() { return this.mapping; } /** Resets the whole mapping info (handle with care) */ synchronized public void DB2XMLclearmapping() { this.mapping = new DB2XMLmapping(); } /** * Returns the mapping element filled with the xml -mapping-data * for the currently selected module */ private Element getMapping() { dataItem datitem = (dataItem)getInitialByKey("module"); String mappingName = datitem.getValue(); if (mappingName .equalsIgnoreCase("Simple DB Export" )) { //Simple DB Export Mapping buildup Element wrapper = new Element("mapping"); Element smdbe_wrapper = new Element("smdbe"); boolean NONempty = false; //set true for not null output for (Enumeration e = this.dbs.elements(); e.hasMoreElements();) { dbItem dbitem = (dbItem )e.nextElement(); Vector selTab = (Vector )dbitem.SMDBEgetSelectedTables (); if (selTab.size()>0) { Element curr_db = new Element("smdbe_item"); curr_db.setAttribute("name",dbitem .getName()); curr_db.setAttribute("type",dbitem .SMDBEgetOutputType()); for (Enumeration enum = selTa b.elements (); enum.hasMoreElements();) { NONempty = true; curr_db.addContent(new Element("smdbe_table").setText((String)enum.nextElement())); } smdbe_wrapper.addContent (curr_db); } } wrapper.addContent(smdbe_wrapper ); if (NONempty) { return wrapper; } else { return null; } } else if (mappingName .equalsIgnoreCase("Database to XML")) { //Database to XML buildup return this.mapping.getMapping(); } else { //failsafe only, should NEVER happen, though return null; } } /** * Cleans all SchemaElements which are associated to the specified SQLStatement * but cleans only the content and attribute-mapping (not repet.) = new repet. set */ synchronized public void cleanSchemaElementDataDependencies(SQLStatement toclean ) { if (toclean != null) { //System.out.println("Statement ====> " + toclean); Vector elms = this.DB2XMLgetmapping().getElements(); if(elms != null) { Autor: Thomas Schädler 148 Anhang A: Quelltext <xmlizer> configurator for(Enumeration e = elms.elements ();e.hasMoreElements ();) { SchemaElement el = (SchemaElement)e.nextElement(); el.cleanMapData(toclean); //System.out.println("Cleaning: " + el); } } } } /** * Cleans all SchemaElements which are associated to the specified SQLStatement * cleans the content,the attributes and the repetition mapping = total-remove */ synchronized public void cleanSchemaElementFullDependencies(SQLStatement toclean ) { if (toclean != null) { //System.out.println("Statement ====> " + toclean); Vector elms = this.DB2XMLgetmapping().getElements(); if(elms != null) { for(Enumerat ion e = elms.elements ();e.hasMoreElements ();) { SchemaElement el = (SchemaElement)e.nextElement(); el.removeSQLStatement(toclean); setDirty (); //System.out.println("Cleaning: " + el); } } } } } /* * helpWindow.java * * ---------------------------------------------------------------------------* This file is part of <xmlizer>. * * <xmlizer> is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Foobar is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public Li cense * along with <xmlizer>; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * ---------------------------------------------------------------------------*/ package configurator; import import import import import import import java.awt.*; java.net.*; java.lang.*; java.io.*; javax.swing .*; javax.swing .event.*; java.util.*; /** * Represents a helpwindow (just another browser) * @author [email protected] */ public class helpW indow extends MyInternalFrame { String initialPage = new String("/configurator/help/index.html"); HTMLBrowser html = new HTMLBrowser(getClass().getResource(initialPage)); JPanel p = new JPanel(); private configurator mother; private String ID; //constructor public helpWindow(configurator mainProgram,String uid) { this.mother = mainProgram; this.ID = uid; setIconifiable(true); setClosable(true); setResizable(true); setMaximizable(true); setTitle("Help Browser"); setSize(580,450); setFrameIcon(new ImageIcon (getClass().getResource("/configurator/icons/Help16.gif"))); p.setLayout(new BorderLayout()); p.add("Center", html); getContentPane().add(p); this.addInternalFrameListener(new InternalFrameAdapter() { public void internalFrameClosing (InternalFrameEvent evt) { exitForm(evt); } }); } /** * Exit the Help Browser */ private void exitForm(InternalFrameEvent evt) { mother.close(this.ID); } /** * Loads a new html page (give full path) */ public void loadPage(String url) { URL theURL = getClass().getResource(url); Autor: Thomas Schädler 149 Anhang A: Quelltext <xmlizer> configurator html.linkActivated(theURL); } } /* * simpleFileFilter.java * * ---------------------------------------------------------------------------* This file is part of <xmlizer>. * * <xmlizer> is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Foobar is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with <xmlizer>; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * ---------------------------------------------------------------------------* @(#)ExampleFileFilter.java 1.9 99/04/23 * * Copyright (c) 1998, 1999 by Sun Microsystems, Inc. All Rights Reserved. * * Sun grants you ("Licensee") a non-exclusive, royalty free, license to use, * modify and redistribute this software in source and binary code form, * provided that i) this copyright notice and license appear on all copies of * the software; and ii) Licensee does not utilize the software in a manner * which is disparaging to Sun. * * This software is provided "AS IS," without a warranty of any kind. ALL * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY * IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR * NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN AND ITS LICENSORS SHALL NOT BE * LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING * OR DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR ITS * LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, * INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER * CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF * OR INABILITY TO USE SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * This software is not designed or intended for use in on-line control of * aircraft, air traffic, aircraft navigation or aircraft communications; or in * the design, construction, operation or maintenance of any nuclear * facility. Licensee represents and warrants that it will not use or * redistribute the Software for such purposes. */ package configurator; import import import import import java.io.File; java.util.Hashtable; java.util.Enumeration ; javax.swing .*; javax.swing .filechooser.*; /** * A convenience implementation of FileFilter that filters out * all files except for those type extensions that it knows about. * * Extensions are of the type ".foo", which is typically found on * Windows and Unix boxes, but not on Macinthosh. Case is ignored. * * Example - create a new fi lter that filerts out all files * but gif and jpg image files: * * JFileChooser chooser = new JFileChooser(); * ExampleFileFilter filter = new ExampleFileFilter( * new String{"gif", "jpg"}, "JPEG & GIF Images") * chooser.addChoosableFileFilter(filter); * chooser.showOpenDialog(this); * * @version 1.9 04/23/99 * @author Jeff Dinkins */ public class simpleFileFilter extends FileFilter { private static String TYPE_UNKNOWN = "Type Unknown"; private static String HIDDEN_FILE = "Hidden File"; private private private private Hashtable filters = null; String description = null; String fullDescription = null; boolean useExtensionsInDescription = true; /** * Creates a file filter. If no filters are added, then all * files are accepted. * * @see #addExtension */ public simpleFileFilter() { this.filters = new Hashtable(); } /** * Creates a file filter that accepts files with the given extension. * Example: new ExampleFileFilter("jpg"); * * @see #addExtension */ public simpleFileFilter(String extension ) { Autor: Thomas Schädler 150 Anhang A: Quelltext <xmlizer> configurator this(extension,null); } /** * Creates a file filter that accepts the given file type. * Example: new ExampleFileFilter("jpg", "JPEG Image Images"); * * Note that the "." before the extension is not needed. If * provided, it will be ignored. * * @see #addExtension */ public simpleFileFilter(String extension , String description ) { this(); if(extension!=null) addExtension(extension); if(description!=null) setDescription (description); } /** * Creates a file filter from the given string array. * Example: new ExampleFileFilter(String {"gif", "jpg"}); * * Note that the "." before the extension is not needed adn * will be ignored. * * @see #addExtension */ public simpleFileFilter(String [] filters) { this(filters, null); } /** * Creates a file filter from the given string array and description. * Example: new ExampleFileFilter(String {"gif", "jpg"}, "Gif and JPG Images"); * * Note that the "." before the extension is not needed and will be ignored. * * @see #addExtension */ public simpleFileFilter(String [] filters, String description ) { this(); for (int i = 0; i < filters.length; i++) { // add filters one by one addExtension(filters[i]); } if(description!=null) setDescription (description); } /** * Return true if this file should be shown in the directory pane, * false if it shouldn't. * * Files that begin with "." are ignored. * * @see #getExtension * @see FileFilter#accepts */ public boolean accept(File f) { if(f != null) { if(f.isDirectory ()) { return true; } String extension = getExtension(f); if(extension != null && filters.get(getExtension(f)) != null) { return true; }; } return false; } /** * Return the extension portion of the file's name . * * @see #getExtension * @see FileFilter#accept */ public String getExtension(File f) { if(f != null) { String filename = f.getName(); int i = filename .lastIndexOf('.'); if(i>0 && i<filename.length ()-1) { return filename.substring(i+1).toLowerCase(); }; } return null; } /** * Adds a filetype "dot" extension to filter against. * * For example: the following code will create a filter that filters * out all files except those that end in ".jpg" and ".tif": * * ExampleFileFilter filter = new ExampleFileFilter(); * filter.addExtension("jpg"); * filter.addExtension("tif"); * * Note that the "." before the extension is not needed and will be ignored. */ public void addExtension (String extension) { if(filters == null) { filters = new Hashtable(5); } filters.put(extension.toLowerCase(), this); fullDescription = null; Autor: Thomas Schädler 151 Anhang A: Quelltext <xmlizer> configurator } /** * Returns the human readable description of this filter. For * example: "JPEG and GIF Image Files (*.jpg, *.gif)" * * @see setDescription * @see setExtensionListInDescription * @see isExtensionListInDescription * @see FileFilter#getDescription */ public String getDescription() { if(fullDescription == null) { if(description == null || isExtensionListInDescription()) { fullDescription = description==null ? "(" : description + " ("; // build the description from the extension list Enumeration extensions = filters.keys(); if(extensions != null) { fullDescription += "." + (String) extensions .nextElement(); while (extensions.hasMoreElements()) { fullDescription += ", " + (String) extensions .nextElement(); } } fullDescription += ")"; } else { fullDescription = description; } } return fullDescription; } /** * Sets the human readable description of this filter. For * example: filter.setDescription("Gif and JPG Images"); * * @see setDescription * @see setExtensionListInDescription * @see isExtensionListInDescription */ public void setDescription(String description ) { this.description = description; fullDescription = null; } /** * Determines whether the extension list (.jpg, .gif, etc) should * show up in the human readable description. * * Only relevent if a description was provided in the constructor * or using setDescription(); * * @see getDescription * @see setDescription * @see isExtensionListInDescription */ public void setExtensionListInDescription(boolean b) { useExtensionsInDescription = b; fullDescription = null; } /** * Returns whether the extension list (.jpg, .gif, etc) should * show up in the human readable description. * * Only relevent if a description was provided in the constructor * or using setDescription(); * * @see getDescription * @see s etDescription * @see setExtensionListInDescription */ public boolean isExtensionListInDescription() { return useExtensionsInDescription; } } /* * splashWindow.java * * ---------------------------------------------------------------------------* This file is part of <xmlizer>. * * <xmlizer> is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Foobar is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with <xmlizer>; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * ---------------------------------------------------------------------------*/ package configurator; import java.awt.*; import javax.swing .*; /** * Shows a simple Splashwindow before starting the configurator * @author [email protected] Autor: Thomas Schädler 152 Anhang A: Quelltext <xmlizer> configurator */ public class splashWindow extends JWindow { ImageIcon splash = new ImageIcon(getClass().getResource ("/configurator/pics/splash.jpg")); JLabel pic = new JLabel(splash ); JLabel txt = new JLabel(); splashWindow s ; /** * Builds the splash screen */ public splashWindow () { txt.setText(configurator.APPNAME + " ver. " + configurator.VERSION); txt.setForeground(new Color(255,255,255)); txt.setHorizontalAlignment (JLabel.CENTER); this.getContentPane().setBackground(new Color(0,54,100)); this.getContentPane().add(pic, BorderLayout.NORTH); this.getContentPane().add(txt, BorderLayout.CENTER); s = this; } /** * Shows the splash screen for a specified time in ms */ public void start(long time) { //get the screen size Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); //place in center of screen s.pack(); Dimension splashScreenSize = s.getSize(); if(splashScreenSize.height > screenSize.height ) { splashScreenSize .height = screenSize.height; } if(splashScreenSize.width > screenSize.width) { splashScreenSize .width = screenSize.width; } s.setLocation((screenSize.width - splashScreenSize.width ) / 2, (screenSize.height - splashScreenSize.height ) / 2); s.setVisible(true); try { Thread .sleep(time); } catch(InterruptedException ie) { System .err.print ("Thread.sleep: " + ie); } s.dispose(); } }/* * MyInternalFrame.java * * Created on 15. Mai 2002, 16:08 * ---------------------------------------------------------------------------* This file is part of <xmlizer>. * * <xmlizer> is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later ver sion. * * Foobar is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with <xmlizer>; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * ---------------------------------------------------------------------------*/ package configurator; /** * The superclass of all internalframes (update()) * @author [email protected] * @version 1.0 */ public class MyInternalFrame extends javax.swing.JInternalFrame { private configurator mother; private projectData theData; private String identifier; public void setIdentifier(String id ) { this.identifier = id; } public String getIdentifier() { return this.identifier; } /** * Must be overwritten to update the component if the setup changes * and the component relies on that kind of information (setup info) */ public synchronized void update(configurator conf) { this.mother = conf; this.theData = conf.getProjectData(); } }/* * SQLColumnInfo.java * * Created on 25. Juli 2002, 02:47 * ---------------------------------------------------------------------------* This file is part of <xmlizer>. * * <xmlizer> is free software; you can redistribute it and/or modify Autor: Thomas Schädler 153 Anhang A: Quelltext <xmlizer> configurator * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Foobar is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with <xmlizer>; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * ---------------------------------------------------------------------------*/ package configurator; /** * Represents the ColumnInfo of a SQLStatement * @author [email protected] */ class SQLColumnInfo { protected String id ; protected String name; protected String type; public SQLColumnInfo(String id ,String name,String type) { this.id = id; this.name = name; this.type = type; } public String getID () { return this.id; } public String getName() { return this.name; } public String getType() { return this.type; } public String toString() { return this.name + " [" + this.type + "]"; } } /* * javadocWindow.java * * ---------------------------------------------------------------------------* This file is part of <xmlizer>. * * <xmlizer> is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your optio n) any later version. * * Foobar is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with <xmlizer>; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * ---------------------------------------------------------------------------*/ package configurator; import import import import import import import java.awt.*; java.net.*; java.lang.*; java.io.*; javax.swing .*; javax.swing .event.*; java.util.*; /** * Is a browser (containing the javadoc) * @author [email protected] */ public class javadocWindow extends MyInternalFrame { String initialPage = new String("/configurator/javadoc/index.html"); HTMLBrowser html = new HTMLBrowser(getClass().getResource(initialPage)); JPanel p = new JPanel(); private static configurator mother; private String ID; //constructor public javadocWindow(configurator mainProgram ,String uid) { this.mother = mainProgram; this.ID = uid; setIconifiable(true); setClosable(true); setResizable(true); setMaximizable(true); setTitle("JavaDoc Browser" ); setSize(580,450); setFrameIcon(new ImageIcon (getClass().getResource("/configurator/icons/WebComponent16.gif"))); p.setLayout(new BorderLayout()); p.add("Center", html); getContentPane().add(p); Autor: Thomas Schädler 154 Anhang A: Quelltext <xmlizer> configurator this.addInternalFrameListener(new InternalFrameAdapter() { public void internalFrameClosing (InternalFrameEvent evt) { exitForm(evt); } }); } /** * Exit the Help Browser */ private void exitForm(InternalFrameEvent evt) { mother.close(this.ID); } /** * Loads a new html page (give full path) */ public void loadPage(String url) { URL theURL = getClass().getResource(url); html.linkActivated(theURL); } }/* * SchemaElementPanel.java * * This class representates a Schema Element Panel for showing its content * * Created on 2. August 2002, 19:02 * ---------------------------------------------------------------------------* This file is part of <xmlizer>. * * <xmlizer> is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Foobar is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with <xmlizer>; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * ---------------------------------------------------------------------------*/ package configurator; import org.jdom.*; import java.util.*; import javax.swing .*; /** * A special panel for the root-element holding methods to set the parameters * @author [email protected] */ public class SchemaRootPanel extends javax.swing.JPanel { private configurator mother; private SchemaElement element; private Vector params = new Vector(); private boolean isEmpty = true; /** Creates new form SchemaRootPanel */ public SchemaRootPanel(configurator config,SchemaElement element) { this.mother = config ; this.element = element; initComponents(); fillLabels (); fillData(); } /** This method is called from within the constructor to * initialize the form. * WARNING: Do NOT modify this code. The content of this method is * always regenerated by the Form Editor. */ private void initComponents()//GEN-BEGIN:initComponents { mainPanel = new javax.swing.JPanel(); infoPanel = new javax.swing.JPanel(); jLabel1 = new javax.swing.JLabel(); afdLabel = new javax .swing .JLabel(); jLabel3 = new javax.swing.JLabel(); efdLabel = new javax .swing .JLabel(); jLabel4 = new javax.swing.JLabel(); tnsLabel = new javax .swing .JLabel(); jLabel5 = new javax.swing.JLabel(); verLabel = new javax .swing .JLabel(); jLabel6 = new javax.swing.JLabel(); langLabel = new javax.swing.JLabel(); parameterPanel = new javax .swing.JPanel(); workPanel = new javax.swing.JPanel(); jPanel7 = new javax.swing.JPanel(); jPanel9 = new javax.swing.JPanel(); jLabel14 = new javax .swing .JLabel(); nameTextField = new javax.swing .JTextField(); jPanel10 = new javax .swing .JPanel(); jLabel15 = new javax .swing .JLabel(); valueTextField = new javax .swing.JTextField(); jPanel8 = new javax.swing.JPanel(); addButton = new javax.swing.JButton(); removeButton = new javax.swing.JButton(); jScrollPane1 = new javax.swing.JScrollPan e(); paramList = new JList(params); setLayout(new java.awt.BorderLayout()); Autor: Thomas Schädler 155 Anhang A: Quelltext <xmlizer> configurator mainPanel.setLayout(new java.awt.BorderLayout()); infoPanel.setLayout(new java.awt.GridLayout(5, 2, 10, 10)); infoPanel.setBorder(new javax.swing.border.TitledBorder("Schema Root Information:")); infoPanel.setMinimumSize(new java.awt.Dimension(0, 0)); jLabel1.setText("Attribute Form Default:" ); jLabel1.setForeground(java.awt.Color .darkGray); infoPanel.add(jLabel1); infoPanel.add(afdLabel); jLabel3.setText("Element From Default:"); jLabel3.setForeground(java.awt.Color .darkGray); infoPanel.add(jLabel3); infoPanel.add(efdLabel); jLabel4.setText("Target Namespace:"); jLabel4.setForeground(java.awt.Color .darkGray); infoPanel.add(jLabel4); infoPanel.add(tnsLabel); jLabel5.setText("Version:" ); jLabel5.setForeground(java.awt.Color .darkGray); infoPanel.add(jLabel5); infoPanel.add(verLabel); jLabel6.setText("Language:"); jLabel6.setForeground(java.awt.Color .darkGray); infoPanel.add(jLabel6); infoPanel.add(langLabel); mainPanel.add(infoPanel, java.awt.BorderLayout .NORTH); parameterPanel.setLayout(new java.awt.BorderLayout()); parameterPanel.setBorder(new javax.swing.border.TitledBorder("Query parameters:")); workPanel.setLayout(new java.awt.BorderLayout()); jPanel7.setLayout(new javax.swing.BoxLayout(jPanel7, javax.swing.BoxLayout.Y_AXIS )); jPanel9.setLayout(new javax.swing.BoxLayout(jPanel9, javax.swing.BoxLayout.X_AXIS )); jLabel14.setText("Name: jPanel9.add(jLabel14 ); " ); nameTextField.setPreferredSize(new java.awt.Dimension(100, 27)); nameTextField.setMinimumSize(new java.awt.Dimension (60, 27)); jPanel9.add(nameTextField); jPanel7.add(jPanel9); jPanel10.setLayout(new javax.swing.BoxLayout(jPanel10, javax.swing .BoxLayout .X_AXIS)); jLabel15.setText("Default Value: jPanel10.add(jLabel15); "); valueTextField.setPreferredSize (new java.awt.Dimension(100, 27)); valueTextField.setMinimumSize(new java.awt.Dimension(60, 27)); jPanel10.add(valueTextField); jPanel7.add(jPanel10 ); workPanel.add(jPanel7, java.awt.BorderLayout.CENTER ); jPanel8.setLayout(new javax.swing.BoxLayout(jPanel8, javax.swing.BoxLayout.Y_AXIS )); addButton.setIcon(new javax.swing.ImageIcon(getClass().getResource ("/configurator/icons/Plus16.gif"))); addButton.addActionListener(new java.awt.event .ActionListener () { public void actionPerformed (java.awt.event .ActionEvent evt) { addButtonActionPerformed(evt); } }); jPanel8.add(addButton); removeButton.setIcon(new javax.swing .ImageIcon (getClass().getResource("/configurator/icons/Minus16.gif"))); removeButton.setEnabled(false); removeButton.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed (java.awt.event .ActionEvent evt) { removeButtonActionPerformed(evt); } }); jPanel8.add(removeButton); workPanel.add(jPanel8, java.awt.BorderLayout.EAST); parameterPanel.add(workPanel, java.awt.BorderLayout .NORTH); paramList.addMouseListener (new java.awt.event.MouseAdapter() { public void mouseClicked(java.awt.event.MouseEvent evt) { paramListMouseClicked(evt); } Autor: Thomas Schädler 156 Anhang A: Quelltext <xmlizer> configurator }); jScrollPane1.setViewportView(paramList); parameterPanel.add(jScrollPane1 , java.awt.BorderLayout.CENTER ); mainPanel.add(parameterPanel, java.awt.BorderLayout .CENTER); add(mainPanel, java.awt.BorderLayout .CENTER); }//GEN-END:initComponents private void paramListMouseClicked(java.awt.event.MouseEvent evt)//GEN -FIRST:event_paramListMouseClicked {//GEN-HEADEREND:event_paramListMouseClicked // Add your handling code here: int index = paramList.getSelectedIndex(); if (index < 0) { removeButton.setEnabled(false); return ; } if (paramList.getModel().getSize() > index) { ParameterInfo data = (ParameterInfo)paramList.getModel().getElementAt(index); setDisplay(data); removeButton.setEnabled(true); } }//GEN-LAST:event_paramListMouseClicked private void removeButtonActionPerformed (java.awt.event .ActionEvent evt)//GEN-FIRST:event_removeButtonActionPerformed {//GEN-HEADEREND:event_removeButtonActionPerformed // Add your handling code here: int index = paramList.getSelectedIndex(); if (index < 0) { removeButton.setEnabled(false); return ; } if (paramList.getModel().getSize() > index) { ParameterInfo data = (ParameterInfo)paramList.getModel().getElementAt(index); boolean success = mother.getProjectData().DB2XMLgetmapping().removeParameter(data.getName()); if (success) { mother.getProjectData().setDirty(); removeButton .setEnabled (false); if (this.params.size() < 1) { this.isEmpty = true; } this.params.remove (data); this.paramList.repaint(); } } }//GEN-LAST:event_removeButtonActionPerformed private void addButtonActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_addButtonActionPerformed {//GEN-HEADEREND:event_addButtonActionPerformed // Add your handling code here: String name = nameTextField.getText(); String value = valueTextField.getText(); if (!name.equalsIgnoreCase (new String()) && !value.equalsIgnoreCase(new String())) { String id = mother.uniqueID .get(); boolean success = mother.getProjectData().DB2XMLgetmapping().addParameterFromLoad(id,name,value); if (success) { mother.getProjectData().setDirty(); if (this.isEmpty) { this.isEmpty = false; } this.params.add(new ParameterInfo (id,name,value)); this.paramList.setListData(this.params ); this.paramList.repaint(); } } }//GEN-LAST:event_addButtonActionPerformed //Initialization of the data //----------------------------------------------------------------------------------------------private void fillLabels() { afdLabel.setText(this.element.SCHEMAattributeFormDefault ); afdLabel.setToolTipText(this.element.SCHEMAattributeFormDefault); efdLabel.setText(this.element.SCHEMAelementFormDefault); efdLabel.setToolTipText(this.element.SCHEMAelementFormDefault ); tnsLabel.setText(this.element.SCHEMAtargetNameSpace ); tnsLabel.setToolTipText(this.element.SCHEMAtargetNameSpace); verLabel.setText(this.element.SCHEMAversion); verLabel.setToolTipText(this.element.SCHEMAversion); langLabel.setText(this.element.SCHEMAlanguage); langLabel.setToolTipText(this.element.SCHEMAlanguage); } private void fillData() { //add the ParameterInfos to the params-vector Hashtable paraHash = mother.getProjectData().DB2XMLgetmapping ().getParameters(); for (Enumeration e = paraHash.elements(); e.hasMoreElements();) { ParameterInfo item = (ParameterInfo)e.nextElement(); this.params .add(item); this.isEmpty = false; } } private void setDisplay(ParameterInfo current ) { nameTextField.setText(current.getName()); valueTextField.setText(current.getValue()); } // Variables declaration private javax.swing .JPanel private javax.swing .JPanel private javax.swing .JLabel private javax.swing .JLabel private javax.swing .JLabel private javax.swing .JLabel private javax.swing .JLabel private javax.swing .JLabel Autor: Thomas Schädler do not modify//GEN -BEGIN:variables mainPanel; infoPanel; jLabel1; afdLabel; jLabel3; efdLabel ; jLabel4; tnsLabel ; 157 Anhang A: Quelltext <xmlizer> configurator private javax.swing .JLabel jLabel5; private javax.swing .JLabel verLabel ; private javax.swing .JLabel jLabel6; private javax.swing .JLabel langLabel; private javax.swing .JPanel parameterPanel; private javax.swing .JPanel workPanel; private javax.swing .JPanel jPanel7; private javax.swing .JPanel jPanel9; private javax.swing .JLabel jLabel14 ; private javax.swing .JTextField nameTextField; private javax.swing .JPanel jPanel10 ; private javax.swing .JLabel jLabel15 ; private javax.swing .JTextField valueTextField ; private javax.swing .JPanel jPanel8; private javax.swing .JButton addButton; private javax.swing .JButton removeButton ; private javax.swing .JScrollPane jScrollPane1; private javax.swing .JList paramList ; // End of variables declaration//GEN-END:variables } /* * SchemaType.java * * Created on 24. Juli 2002, 11:59 * * This represents the neccessary info for a type of a SchemaElement * ---------------------------------------------------------------------------* This file is part of <xmlizer>. * * <xmlizer> is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Foobar is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with <xmlizer>; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * ---------------------------------------------------------------------------*/ package configurator; import org.jdom.*; import java.util.*; import javax.swing .*; /** * Hold the information for the type of the SchemaElement * (currently unused) * @author [email protected] */ public class SchemaType { private String tname = null; //name= //CONSTRUCTORS public SchemaType() { //none for now } public void setName(String name) { this.tname = name; } public String getName() { return this.tname; } //TYPE PROCESSING public void processType(Element typeElement) { //name Attribute attr = null; attr = typeElement.getAttribute ("name"); if (attr != null) { this.tname = attr.getValue().trim(); } //System.out.println("TYPE: " + typeElement.getName()); List kids = typeElement.getChildren(); //"element",namespace Iterator kids_iter = kids.iterator(); while (kids_iter.hasNext()) { Element xmlelem = (Element) kids_iter .next(); if (xmlelem.getName().equalsIgnoreCase("complexType" )) //can conatain new elements { List subkids = xmlelem.getChildren(); //"element",namespace Iterator subkids_iter = subkids.iterator(); while (subkids_iter.hasNext()) { Element dxmlelem = (Element) subkids_iter.next(); if (dxmlelem.getName().equalsIgnoreCase ("simpleContent")) { List dsubkids = dxmlelem.getChildren(); //"element",namespace Iterator dsubkids_iter = dsubkids.iterator(); while (dsubkids_iter .hasNext()) { } } else if else if else if else if else if (dxmlelem.getName().equalsIgnoreCase ("complexContent")) { } (dxmlelem.getName().equalsIgnoreCase ("group")) { } (dxmlelem.getName().equalsIgnoreCase ("all")) { } (dxmlelem.getName().equalsIgnoreCase ("choice")) { } (dxmlelem.getName().equalsIgnoreCase ("sequence")) { } Autor: Thomas Schädler 158 Anhang A: Quelltext <xmlizer> configurator else if (dxmlelem.getName().equalsIgnoreCase ("attribute")) { } } } else if (xmlelem.getName().equalsIgnoreCase("simpleType")) //no more deeper elements { List subkids = xmlelem.getChildren(); //"element",namespace Iterator subkids_iter = subkids.iterator(); while (subkids_iter.hasNext()) { Element dxmlelem = (Element) subkids_iter.next(); if (dxmlelem.getName().equalsIgnoreCase ("restriction")) { } else if (dxmlelem.getName().equalsIgnoreCase ("list")) { } else if (dxmlelem.getName().equalsIgnoreCase ("union")) { } } } } } public void processTypeRef(Element typeElement) { //System.out.println("TREF:" + typeElement.getName()); } public void processInternalType(Element typeElement) { //System.out.println("ITYP: " + typeElement.getName()); } //STRING REPRESENTATION /** * By default show the key as String */ public String toString() { return this.tname; /* if (this.ttype == null && this.ttyperef != null) //has a typeref { return this.tname + " - " + this.ttyperef + " [" + this.tuse + "]"; } else if (this.ttype != null && this.ttyperef == null) //has a type { return this.tname + " - " + this.ttype + " [" + this.tuse + "]"; } else //has nothing of both (should not happen -> invalid) { return this.tname + " - !noType! [" + this.tuse + "]"; }*/ } }/* * ---------------------------------------------------------------------------* This file is part of <xmlizer>. * * <xmlizer> is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Foobar is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR P URPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with <xmlizer>; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * ---------------------------------------------------------------------------**************************************************************************** * xuri **************************************************************************** * Copyright (C) 05/2001 Ralf Schweiger * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * Contact the Author: * * University of Giessen * c/o Ralf Schweiger * Heinrich-Buff-Ring 44 * 35392 Giessen * Germany * * tel.: +49-641-9941370 * fax.: +49-641-9941359 * mailto: [email protected] -giessen.de * ***************************************************************************/ package configurator; import java.net.*; import java.io.*; Autor: Thomas Schädler 159 Anhang A: Quelltext <xmlizer> configurator import java.util.Date; // import javax.servlet.*; class xurl { private final String defaultEncoding = "ISO-8859-1"; private String charset; private StringBuffer toSend; private PrintStream psLog; // application private StringBuffer sbLog; // applet private void log(Object item) { if (psLog != null) psLog.print(item); if (sbLog != null) sbLog.append (item); } public xurl() { charset = defaultEncoding; psLog = null; sbLog = null; toSend = new StringBuffer(""); } public xurl(String charset) { this.charset = charset; psLog = null; sbLog = null; toSend = new StringBuffer(""); } public xurl(StringBuffer sbLog ) { charset = defaultEncoding; psLog = null; this.sbLog = sbLog; toSend = new StringBuffer(""); } public xurl(String charset, StringBuffer sbLog) { this.charset = charset; psLog = null; this.sbLog = sbLog; toSend = new StringBuffer (""); } public void setCharset(String charset) { this.charset = charset; } public void send(String name, Object value) { if (toSend .length() > 0) toSend .append("&"); toSend.append(name).append ("=").append(URLEncoder.encode (value.toString ())); } public String communicate(String url) { // send & receive Date date0 = new Date(); log("<xurl:communicate>" + url + "\n<xurl:send charset=" + charset + ">" + toSend ); try { URL u = new URL(url); URLConnection uc = u.openConnection(); uc.setDoInput(true); uc.setUseCaches(false); uc.setRequestProperty("content-type", "application/x -www-form-urlencoded"); uc.setRequestProperty("charset", charset); if (toSend.toString().length() > 0) { uc.setDoOutput(true); PrintWriter pw = new PrintWriter(uc.getOutputStream()); pw.print(toSend); toSend = new StringBuffer(""); pw.close(); } StringBuffer receive = new StringBuffer(""); String enc = uc.getContentEncoding(); // equals to charset if xurl is used for communication InputStreamReader isr = new InputStreamReader(uc.getInputStream(), enc != null ? enc : charset); int c; while ((c = isr.read()) != -1) receive.append((char) c); isr.close(); log("</xurl:send>\n<xurl:receive charset=" + enc + ">" + receive + "</xurl:receive>\n" + ((new Date()).getTime() - date0.getTime()) + " ms</xurl:communicate>"); return receive.toString(); } catch (Exception x) { log(x); return null; } } /******************************************* * * public String receive(ServletRequest req) { * Date date0 = new Date(); * if (log != null) log.put("<xurl:receive charset=" + req.getCharacterEncoding() + ">"); * try { * StringBuffer content = new StringBuffer(""); * BufferedReader br = req.getReader(); * int c; * while ((c = br.read()) != -1) content.append((char) c); * br.close(); * if (log != null) log.put(((new Date()).getTime() - date0.getTime()) + " ms</xurl:receive>"); * return content.toString(); * } * catch (Exception x) { if (log != null) log.put(x); return null; } * } * * public void send(ServletResponse res, Object content) { * Date date0 = new Date(); * if (log != null) log.put("<xurl:send charset=" + charset + ">" + content); * try { * res.setContentType("text/plain; charset=" + charset); * PrintWriter pw = res.getWriter(); * pw.print(content); * pw.close(); * if (log != null) log.put(((new Date()).getTime() - date0.getTime()) + " ms</xurl:send>"); * } * catch (Exception x) { if (log != null) log.put(x); } * } * ************************************************/ } /* * sdbBrowser.java * * Created on 17. Mai 2002, 20:28 * ---------------------------------------------------------------------------- Autor: Thomas Schädler 160 Anhang A: Quelltext <xmlizer> configurator * This file is part of <xmlizer>. * * <xmlizer> is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Foobar is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with <xmlizer>; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * ---------------------------------------------------------------------------*/ package configurator; import import import import import import import import import import import java.io.*; java.sql.*; java.util.*; org.jdom.*; org.jdom.output.XMLOutputter; java.awt.event.*; javax.swing .*; javax.swing .table.*; javax.swing .tree.*; java.util.Vector ; java.util.Enumeration ; /** * A simple database browser without any specail stuff used for testing db's in the setup * @author [email protected] */ public class sdbBrowser extends MyInternalFrame { private private private private private private private private private private private private private private private private private configurator mother; String ID; JPopupMenu popup = new JPopupMenu(); JMenu mnuAutoresize = new JMenu(); JMenuItem nextMI ; JMenuItem lastMI ; JMenuItem setChunk; JRadioButtonMenuItem mniOn = new JRadioButtonMenuItem("on"); JRadioButtonMenuItem mniOff = new JRadioButtonMenuItem("off"); int autoresize = JTable.AUTO_RESIZE_ALL_COLUMNS ; projectData theData; Vector dbList = new Vector(); Vector tableList = new Vector(); boolean isLoading = true; boolean isUpdating = false; String currentlySelectedTable = new String (); DataChooser dataChooser = null; //Thread related private activityMeter activity ; private volatile Thread updateThread = null; private volatile Thread workerThread = null; private volatile Thread controllerThread = null; private boolean StopAllThreads = false; //flag used to stop long tasks (but not the controller thread) private String lastSQLStatement = new String(); /** Creates new form dbBrowser */ public sdbBrowser(configurator mainProgram,String uid) { this.mother = mainProgram; this.ID = uid; this.theData = mainProgram .getProjectData (); if (mainPr ogram .nextDBToBrowse.size() > 0) { this.dbList = mainProgram.nextDBToBrowse; } else { this.dbList = mainProgram.getProjectData().getDB(); } initComponents(); activity = new activityMeter(stopButton,theProgressBar); //add the popupmenu //add data browser nextMI = new JMenuItem("Next"); lastMI = new JMenuItem("Last"); nextMI.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed (ActionEvent e) { nextMI_actionPerformed(e); } }); lastMI.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed (ActionEvent e) { lastMI_actionPerformed(e); } }); popup.add(nextMI); popup.add(lastMI); popup.addSeparator(); //add the entry to set the chunksize setChunk = new JMenuItem("Set Rows ("+getActiveDB().getChunkSize()+")"); setChunk.addActionListener (new java.awt.event.ActionListener() { public void actionPerformed (ActionEvent e) { setChunk_actionPerformed(e); } }); Autor: Thomas Schädler 161 Anhang A: Quelltext <xmlizer> configurator popup.add(setChunk); //add autoresize toggle mnuAutoresize.setText("Autoresize"); mnuAutoresize.add(mniOn); mnuAutoresize.add(mniOff); mniOn.setSelected(true); mniOn.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed (ActionEvent e) { mniOn_actionPerformed(e); } }); mniOff.setSelected(false); mniOff.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed (ActionEvent e) { mniOff_actionPerformed(e); } }); popup.add(mnuAutoresize); //init other stuff if (dbList .size() > 0) { dbComboBox.setSelectedIndex (0); } upperPanel .repaint(); isLoading = false; } /** This method is called from within the constructor to * initialize the form. * WARNING: Do NOT modify this code. The content of this method is * always regenerated by the Form Editor. */ private void initComponents() { upperPanel = new javax.swing.JPanel(); dbLabel = new javax.swing.JLabel(); dbComboBox = new javax.swing.JComboBox(dbList); sqlButton = new javax.swing.JButton(); helpButton = new javax.swing.JButton(); sqlLabel = new javax .swing .JLabel(); sqlScrollPane = new javax.swing .JScrollPane(); sqlTextArea = new javax.swing.JTextArea(); stopButton = new javax.swing.JButton(); theProgressBar = new javax .swing.JProgressBar(); limitCheckBox = new javax.swing .JCheckBox (); obenPanel = new javax.swing.JPanel(); jSplitPane2 = new javax.swing.JSplitPane(); jPanel4 = new javax.swing.JPanel(); listScrollPane = new javax .swing.JScrollPane(); dbtableList = new javax.swing.JList(tableList); jPanel5 = new javax.swing.JPanel(); jLabel2 = new javax.swing.JLabel(); tableScrollPane = new javax.swing.JScrollPane(); dbTable = new javax.swing.JTable(); setMaximizable(true); setTitle("Database Browser"); setIconifiable(true); setResizable(true); setClosable(true); addInternalFrameListener(new javax.swing.event .InternalFrameListener() { public void internalFrameOpened(javax .swing.event.InternalFrameEvent evt ) { } public void internalFrameClosing (javax.swing.event.InternalFrameEvent evt) { formInternalFrameClosing(evt); } public void internalFrameClosed(javax .swing.event.InternalFrameEvent evt ) { } public void internalFrameIconified(javax.swing.event .InternalFrameEvent evt) { } public void internalFrameDeiconified(javax .swing.event.InternalFrameEvent evt ) { } public void internalFrameActivated(javax.swing.event .InternalFrameEvent evt) { } public void internalFrameDeactivated(javax .swing.event.InternalFram eEvent evt ) { } }); upperPanel .setLayout (new java.awt.GridBagLayout()); java.awt.GridBagConstraints gridBagConstraints1; dbLabel.setText("Database:"); gridBagConstraints1 = new java.awt.GridBagConstraints(); gridBagConstraints1.fill = java.awt.GridBagConstraints.HORIZONTAL; gridBagConstraints1.insets = new java.awt.Insets(0, 2, 0, 0); upperPanel .add(dbLabel, gridBagConstraints1); dbComboBox .setPreferredSize(new java.awt.Dimension(240, 27)); dbComboBox .setMinimumSize(new java.awt.Dimension(126, 27)); dbComboBox .setMaximumSize(new java.awt.Dimension(32767, 27)); dbComboBox .addActionListener(new java.awt.event.ActionListener() { public void actionPerformed (java.awt.event .ActionEvent evt) { dbComboBoxActionPerformed(evt); } }); gridBagConstraints1 = new java.awt.GridBagConstraints(); gridBagConstraints1.insets = new java.awt.Insets(2, 0, 2, 0); gridBagConstraints1.anchor = java.awt.GridBagConstraints .WEST; upperPanel .add(dbComboBox, gridBagConstraints1 ); sqlButton.setIcon(new javax.swing.ImageIcon(getClass().getResource ("/configurator/icons/actions/execute.gif"))); sqlButton.setToolTipText("Query the database with your SQL"); sqlButton.setPreferredSize (new java.awt.Dimension(51, 51)); sqlButton.setMaximumSize(new java.awt.Dimension(51, 51)); Autor: Thomas Schädler 162 Anhang A: Quelltext <xmlizer> configurator sqlButton.setSelected(true); sqlButton.setMinimumSize(new java.awt.Dimension(51, 51)); sqlButton.addActionListener(new java.awt.event .ActionListener () { public void actionPerformed (java.awt.event .ActionEvent evt) { sqlButtonActionPerformed(evt); } }); gridBagConstraints1 = new java.awt.GridBagConstraints(); gridBagConstraints1.gridx = 3; gridBagConstraints1.gridy = 1; gridBagConstraints1.insets = new java.awt.Insets(0, 2, 0, 2); gridBagConstraints1.anchor = java.awt.GridBagConstraints .WEST; upperPanel .add(sqlButton, gridBagConstraints1); helpButton .setIcon(new javax.swing.ImageIcon(getClass().getResource("/configurator/icons/Help16.gif"))); helpButton .setToolTipText("Open Help"); helpButton .setFont(new java.awt.Font("Dialog", 0, 10)); helpButton .addActionListener(new java.awt.event.ActionListener() { public void actionPerformed (java.awt.event .ActionEvent evt) { helpButtonActionPerformed(evt); } }); gridBagConstraints1 = new java.awt.GridBagConstraints(); gridBagConstraints1.gridx = 4; gridBagConstraints1.gridy = 0; gridBagConstraints1.insets = new java.awt.Insets(0, 0, 0, 2); gridBagConstraints1.anchor = java.awt.GridBagConstraints .EAST; upperPanel .add(helpButton, gridBagConstraints1 ); sqlLabel.setText("SQL Query:"); gridBagConstraints1 = new java.awt.GridBagConstraints(); gridBagConstraints1.gridx = 0; gridBagConstraints1.gridy = 1; gridBagConstraints1.insets = new java.awt.Insets(0, 2, 0, 0); upperPanel .add(sqlLabel, gridBagConstraints1); sqlTextArea.setLineWrap(true); sqlTextArea.setColumns(45); sqlTextArea.setRows(3); sqlScrollPane.setViewportView(sqlTextArea ); gridBagConstraints1 = new java.awt.GridBagConstraints(); gridBagConstraints1.gridx = 1; gridBagConstraints1.gridy = 1; gridBagConstraints1.gridwidth = 2; gridBagConstraints1.fill = java.awt.GridBagConstraints.HORIZONTAL; upperPanel .add(sqlScrollPane, gridBagConstraints1); stopButton .setIcon(new javax.swing.ImageIcon(getClass().getResource("/configurator/icons/Stop16.gif"))); stopButton .setToolTipText("Stop background activity."); stopButton .setEnabled(false); stopButton .addActionListener(new java.awt.event.ActionListener() { public void actionPerformed (java.awt.event .ActionEvent evt) { stopButtonActionPerformed(evt); } }); gridBagConstraints1 = new java.awt.GridBagConstraints(); gridBagConstraints1.gridx = 3; gridBagConstraints1.gridy = 0; gridBagConstraints1.insets = new java.awt.Insets(0, 2, 0, 2); gridBagConstraints1.anchor = java.awt.GridBagConstraints .WEST; upperPanel .add(stopButton, gridBagConstraints1); theProgressBar.setToolTipText("Shows the progress for longer tasks"); theProgressBar.setPreferredSize (new java.awt.Dimension(148, 21)); theProgressBar.setMinimumSize(new java.awt.Dimension(10, 21)); gridBagConstraints1 = new java.awt.GridBagConstraints(); gridBagConstraints1.gridx = 2; gridBagConstraints1.gridy = 0; gridBagConstraints1.insets = new java.awt.Insets(0, 0, 0, 2); gridBagConstraints1.anchor = java.awt.GridBagConstraints.EAST; upperPanel .add(theProgressBar, gridBagConstraints1); limitCheckBox.setToolTipText("If selected, the results are diplayed in browsable chunks, not as one large table."); limitCheckBox.setText("limit"); limitCheckBox.addItemListener(new java.awt.event.ItemListener () { public void itemStateChanged(java.awt.event.ItemEvent evt ) { limitCheckBoxItemStateChanged(evt); } }); gridBagConstraints1 = new java.awt.GridBagConstraints(); gridBagConstraints1.gridx = 4; gridBagConstraints1.gridy = 1; gridBagConstraints1.insets = new java.awt.Insets(0, 0, 0, 2); gridBagConstraints1.anchor = java.awt.GridBagConstraints .EAST; upperPanel .add(limitCheckBox, gridBagConstraints1); getContentPane().add(upperPanel , java.awt.BorderLayout.NORTH); obenPanel.setLayout(new java.awt.BorderLayout()); jSplitPane2.setDividerLocation(120); jSplitPane2.setOneTouchExpandable(true); jPanel4.setLayout(new java.awt.BorderLayout()); listScrollPane.setViewportView(dbtableList); jPanel4.add(listScrollPane , java.awt.BorderLayout.CENTER ); jPanel5.setLayout(new java.awt.GridBagLayout()); java.awt.GridBagConstraints gridBagConstraints2; Autor: Thomas Schädler 163 Anhang A: Quelltext <xmlizer> configurator jLabel2.setText("Tables"); jLabel2.setHorizontalAlignment(javax .swing.SwingConstants.CENTER); gridBagConstraints2 = new java.awt.GridBagConstraints(); gridBagConstraints2.insets = new java.awt.Insets(0, 0, 0, 2); jPanel5.add(jLabel2, gridBagConstraints2); jPanel4.add(jPanel5, java.awt.BorderLayout.NORTH); jSplitPane2.setLeftComponent(jPanel4); tableScrollPane .setPreferredSize(new java.awt.Dimension(400, 320)); dbTable.setPreferredScrollableViewportSize(new java.awt.Dimension(400, 350)); tableScrollPane .setViewportView (dbTable); jSplitPane2.setRightComponent(tableScrollPane); obenPanel.add(jSplitPane2, java.awt.BorderLayout.CENTER); getContentPane().add(obenPanel, java.awt.BorderLayout.CENTER); pack(); } private void limitCheckBoxItemStateChanged(java.awt.event.ItemEvent evt) { // Add your handling code here: if (!isUpdating ) { getActiveDB ().setLimit (!getActiveDB().hasLimit()); } } private void stopButtonActionP erformed(java.awt.event.ActionEvent evt) { // Add your handling code here: Runnable r = new Runnable() { public void run() { stopButton.setEnabled(false); sqlButton.setEnabled(true); activity.init(); StopAllThreads = true; mother.getLog().addInformation("Background activity stopping..."); } }; controllerThread = new Thread(r); controllerThread.start(); } private void dbComboBoxActionPerformed(java.awt.event.ActionEvent evt) { // Add your handling code here: if (!isLoading) { updateDB(); //updates the DB Browser } } public void setDataChooser(DataChooser data) { this.dataChooser = data; } private void formInternalFrameClosing(javax.swing.event .InternalFrameEvent evt) { // Add your handling code here: boolean update = false; mother.nextDBToBrowse.removeAllElements(); mother.close(this.ID); } private void helpButtonActionPerformed(java.awt.event.ActionEvent evt) { // Add your handling code here: helpWindow help = (helpWindow)mother .open("help"); help.loadPage("/configurator/help/tools_dbbrowser.html"); } private void sqlButtonActionPerformed(java.awt.event.ActionEvent evt) { // Add your handling code here: if (!(sqlTextArea.getText().trim().equalsIgnoreCase (new String()))) { try { doSQL(sqlTextArea.getText().trim(),true); } catch(Exception sqlex) { mother.getLog().addError(sqlex); } } else { sqlTextArea .setText(this.lastSQLStatement); } } // Variables declaration - do not modify private javax.swing .JPanel upperPanel; private javax.swing .JLabel dbLabel; private javax.swing .JComboBox dbComboBox ; private javax.swing .JButton sqlButton; private javax.swing .JButton helpButton; private javax.swing .JLabel sqlLabel ; private javax.swing .JScrollPane sqlScrollPane ; private javax.swing .JTextArea sqlTextArea; private javax.swing .JButton stopButton; private javax.swing .JProgressBar theProgressBar; private javax.swing .JCheckBox limitCheckBox; private javax.swing .JPanel obenPanel; private javax.swing .JSplitPane jSplitPane2; private javax.swing .JPanel jPanel4; private javax.swing .JScrollPane listScrollPane; private javax.swing.JList dbtableList; private javax.swing .JPanel jPanel5; private javax.swing .JLabel jLabel2; Autor: Thomas Schädler 164 Anhang A: Quelltext <xmlizer> configurator private javax.swing .JScrollPane tableScrollPane; private javax.swing .JTable dbTable; // End of variables declaration /** * Updated the TreeView of the Database */ synchronized private void updateDB() { mother.getLog().addInformation("Retrieving tables from selected database..." ); final dbItem theDB = getActiveDB(); final sdbBrowser This = this; if (theDB != null) { Runnable r = new Runnable() { public void run() { activity .start (false); dbtableList.setEnabled(false); isUpdating = true; limitCheckBox.setSelected(theDB.hasLimit()); isUpdating = false; try { tableList = theDB.getTableList (); } catch(Exception e) { activity.stop(false); mother.getLog().addError(e); return; } //make the new list dbtableList = new JList(tableList); //make the list functional dbtableList.getSelectionModel ().setSelectionMode(ListSelectionModel.SINGLE_SELECTION); //add the mouselistener ItemListener ilst = new ItemListener(This); dbtableList.addMouseListener(ilst); //show the new list listScrollPane .getViewport().add(dbtableList ); dbtableList.setEnabled(true); setChunk .setText("Set Rows (" +theDB.getChunkSize()+")"); mother.getLog().addInformation("Tablelist updated."); activity .stop(false); } }; updateThread = new Thread(r); StopAllThreads = false ; updateThread.start(); } } public void chooseDB(String dbkey) { int counter = 0; for (Enume ration e = this.dbList.elements (); e.hasMoreElements();) { dbItem item = (dbItem)e.nextElement(); //System.out.println("SEARCHING: " + dbkey + " >> " + item.getName()); if (item.getName().equalsIgnoreCase(dbkey)) { this.dbtableList.setSelectedIndex (counter); this.dbComboBox.setSelectedIndex(counter); //System.out.println(" >> MATCH >> " + counter); } else counter++; } } public synchronized void inspect(SQLStatement stat ) { chooseDB(stat.getDB()); sqlTextArea.setText(stat.getSQL ()); doSQL(stat.getSQL(),true); } /** * Shows the specified queries' resultset in a JTable */ private void doSQL(String sqlQuery,boolean reset) { //finalize for runnable final String ThesqlQuery = sqlQuery; final dbItem theDB = getActiveDB(); if (reset) { theDB.resetLimit(); } this.lastSQLStatement = sqlQuery; Runnable r = new Runnable() { public void run() { Hashtable navData = new Hashtable (); activity.start(false); try { dbTable = theDB.getQueryAsJTable(ThesqlQuery ); navData = theDB.getNavigator(); } catch(Exception ex ) { activity .stop(false ); mother.getLog().addError (ex); return; } dbTable.addMouseListener(new java.awt.event .MouseAdapter() { public void mouseClicked (MouseEvent e) { dbTable_mouseClicked (e); } }); dbTable.setAutoResizeMode(autoresize); tableScrollPane.getViewport().add(dbTable); Autor: Thomas Schädler 165 Anhang A: Quelltext <xmlizer> configurator tableScrollPane.setBorder(BorderFactory.createTitledBorder (theDB.getName() + " >> SQL Query Result : Rows " + navData.get("first") + "-" + navData.get("last") + " of " + navData.get("max"))); boolean hasNext = ((Boolean)navData.get("hasNext")).booleanValue(); boolean hasLast = ((Boolean)navData.get("hasLast")).booleanValue(); if (hasNext) { nextMI.setEnabled(true); } else { nextMI.setEnabled(false); } if (hasLast) { lastMI.setEnabled(true); } else { lastMI.setEnabled(false); } mother.getLog().addInformation("SQL Query returned a valid ResultSet."); activity.stop(false); } }; workerThread = new Thread(r); StopAllThreads = false; workerThread.start(); } private void dbTable_mouseClicked(MouseEvent e) { if(SwingUtilities.isRightMouseButton (e)) { popup.show(dbTable,e.getX(),e.getY()); } } private void nextMI_actionPerformed (ActionEvent e) { getActiveDB().nextChunk(); try { doSQL(getActiveDB().getLastSQL(),false); } catch(Exception ex) { mother .getLog().addError(ex); } } private void lastMI_actionPerformed (ActionEvent e) { getActiveDB().lastChunk(); try { doSQL(getActiveDB().getLastSQL(),false); } catch(Exception ex) { mother .getLog().addError(ex); } } private void mniOff_actionPerformed (ActionEvent e) { autoresize = JTable.AUTO_RESIZE_OFF; dbTable.setAutoResizeMode(autoresize ); mniOff.setSelected(true); mniOn.setSelected(false); } private void mniOn_actionPerformed(ActionEvent e) { autoresize = JTable.AUTO_RESIZE_ALL_COLUMNS; dbTable.setAutoResizeMode(autoresize ); mniOff.setSelected(false); mniOn.setSelected(true); } /** * Sets the number of rows to display per DB retrieve */ private void setChunk_actionPerformed(ActionEvent e) { String input = dbItem.Convertint2String(getActiveDB ().getChunkSize ()); String before = new String (input); input = JOptionPane.showInputDialog("Enter the number of rows to show:" ); if ((input != null) && (!input.equalsIgnoreCase(new String())) && (!input.equalsIgnoreCase(before ))) { int newvalue = dbItem.ConvertString2int(input); getActiveDB ().setChunkSize(newvalue); setChunk.setText("Set Rows ("+newvalue+")"); mother .getLog().addInformation("Changed number of ro ws to display to " + newvalue + "."); } } /** * This method updates the UI if the setupwindow is closed * (and a change in the setup component occured) */ public synchronized void update(configurator conf) { isLoading = true; dbtableList.setEnabled(false); this.mother = conf; this.theData = conf.getProjectData(); if (conf.nextDBToBrowse.size() > 0) { this.dbList = conf.nextDBToBrowse; } else { this.dbList = conf.getProjectData().getDB(); } if (dbList .size() > 0) { dbComboBox.setSelectedIndex (0); } this.repaint(); isLoading = false; } /** * Returns the currently selected d bItem */ synchronized private dbItem getActiveDB() { return (dbItem)dbComboBox.getSelectedItem (); } /** Autor: Thomas Schädler 166 Anhang A: Quelltext <xmlizer> configurator * Listens for listItem-(Mouse)-Events on the dbtableList * -> For database queries */ class ItemListener implements MouseListener { protected sdbBrowser m_parent; protected JList m_list; public ItemListener(sdbBrowser parent) { m_parent = parent; m_list = parent.dbtableList ; } public void mouseClicked(MouseEvent e) { doAction(); } public {} public {} public {} public {} void mousePressed(MouseEvent e) void mouseReleased(MouseEvent e) void mouseEntered(MouseEvent e) void mouseExited(MouseEvent e ) protected void doAction() { int index = m_list.getSelectedIndex(); if (index < 0) { return; } listItem data = (listItem)m_list .getModel().getElementAt(index ); mother .getLog().addInformation("Retrieving table " + data.getName() + "..."); getActiveDB ().resetLimit(); doSQL("SELECT * FROM " + data.getName(),true); } } }/* * dtd2xs.java * * ---------------------------------------------------------------------------* This file is part of <xmlizer>. * * <xmlizer> is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Foobar is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with <xmlizer>; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * ---------------------------------------------------------------------------**************************************************************************** * dtd2xs: Translates XML 1.0 DTD to REC-xmlschema-1-20010502 **************************************************************************** * Copyright (C) 07/2001 Ralf Schweiger * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * Contact the Author: * * University of Giessen * c/o Ralf Schweiger * Heinrich-Buff-Ring 44 * 35392 Giessen * Germany * * tel.: +49-641-9941370 * fax.: +49-641-9941359 * mailto: [email protected] -giessen.de * ***************************************************************************/ package configurator; import import import import import import java.io.*; java.util.*; com.sun.xml.tree.XmlDocument; org.w3c.dom.*; org.xml.sax.InputSource; com.jclark.xsl.dom.*; /** * DTD => REC -xmlschema -1-20010502 * @author Ralf Schweiger * @version 1.00, 06/12/01 */ public class dtd2xs { Autor: Thomas Schädler 167 Anhang A: Quelltext <xmlizer> configurator private String [] delimiter = { ",|", ";/" }; private private private private private final final final final final int int int int int meaninglessEntity = -1; // no meaningful entity enumerationEntity = 0; contentModelEntity = 1; attributeListEntity = 2; unusedEntity = 3; private final String schemaPrefix = "xs"; private final String [] builtInSimpleType = { "string", "normalizedString" , "token", "byte", "unsignedByte", "base64Binary", "hexBinary", "integer", "positiveInteger", "negativeInteger" , "nonNegativeInteger", "nonPositiveInteger", "int" , "unsignedInt" , "long", "unsignedLong", "short", "unsignedShort", "decimal", "float", "double", "boolean", "time" , "dateTime", "duration", "date", "gMonth", "gYear", "gYearMonth", "gDay", "gMonthDay", "Name", "QName", "NCName" , "anyURI" , "language", "ID", "IDREF", "IDREFS", "ENTITY", "ENTITIES", "NOTATION", "NMTOKEN", "NMTOKENS" }; private private private private private private private private private final int maxNumComments = 1000; int numComments; String [] comment; boolean ignoreComments ; String commentLanguage ; int conceptHighlight; int conceptOccurrence; int commentLength; String conceptRelation ; /** * Logging information. */ private PrintStream psLog; // application private StringBuffer sbLog; // applet private void log(Object item) { if (psLog != null) psLog.print(item); else if (sbLog != null) sbLog.append (item); } /** * Create a DTD to REC-xmlschema-1-20010502 translator. * @param log Where to put logging information. */ public dtd2xs(Object log ) { comment = new String [maxNumComments ]; psLog = null; sbLog = null; if (log instanceof PrintStream) psLog = (PrintStream) log; else if (log instanceof StringBuffer ) sbLog = (StringBuffer) log; } private Element simpleType(Document schema, String name , String content) { Element simpleType = schema.createElement ("simpleType"); if (name != null) { schema .getDocumentElement().appendChild(simpleType); simpleType.setAttribute("name", name); annotate(schema, simpleType ); } Element restriction = schema.createElement("restriction" ); simpleType .appendChild(restriction); if (content.startsWith("(")) { restriction .setAttribute("base", "string"); StringTokenizer contentTokenizer = new StringTokenizer(content, "(|)"); while (contentTokenizer.hasMoreTokens ()) { Element enumeration = schema .createElement("enumeration"); restriction.appendChild (enumeration); enumeration.setAttribute("value", contentTokenizer.nextToken().trim()); annotate(schema, enumeration ); } } else restriction.setAttribute("base" , content); return simpleType; // enumeration } private void attributeGroup(Document schema, Element group, String content) { StringTokenizer contentTokenizer = new StringTokenizer(content); String lookahead, name = null; while (contentTokenizer.hasMoreTokens()) { if (name == null) name = contentTokenizer.nextToken(" \t\n\r\f"); if (name.startsWith("%") && name.endsWith(";")) { Element attributeGroupRef = schema.createElement ("attributeGroup"); group.appendChild(attributeGroupRef); attributeGroupRef.setAttribute("ref", name.substring(1, name.length() - 1)); name = null; continue; } Element attribute = schema.createElement("attribute" ); group.appendChild(attribute ); String type = contentTokenizer.nextToken(" \t\n\r\f"); if (type.startsWith("(") && ! type.endsWith(")")) type += contentTokenizer.nextToken(")"); String use = contentTokenizer.nextToken(") \t\n\r\f"); String value = null; if ("#IMPLIED #REQUIRED #FIXED".indexOf(use.toUpperCase()) < 0) { value = use; use = "#IMPLIED"; } else if (contentTokenizer.hasMoreTokens()) value = contentTokenizer.nextToken(" \t\n\r\f"); String quote = null; if (value != null && -1 < "\"'".indexOf(value.charAt (0))) quote = String.valueOf(value .charAt(0)); if (quote != null) { if (! value.endsWith(quote) || value.equals (quote)) value = value.substring(1, value.length ()) + contentTokenizer.nextToken(quote); else value = value.substring(1, value.length () - 1); Autor: Thomas Schädler 168 Anhang A: Quelltext <xmlizer> configurator lookahead = null; } else { lookahead = value; value = null; } // log("\ndtd2xs: attribute[" + name + "][" + type + "][" + use + "][" + value + "]"); if (name.indexOf(':') < 0) { // non-colonized name (NCName) attribute.setAttribute("name", name); if (type.startsWith("%")) attribute.setAttribute("type" , type.substring(1, type.length() - 1)); else if (type.startsWith("(")) attribute.appendChild(simpleType(schema , null, type)); else if (type.toUpperCase().equals("CDATA")) // no valid simpleType attribute.setAttribute("type" , "string" ); else attribute.setAttribute("type" , type); } else attribute.setAttribute ("ref", name); // colonized name (QName) annotate(schema, attribute); use = use.toUpperCase(); if (use.equals("#REQUIRED")) attribute.setAttribute("use" , "required"); if (use.equals("#FIXED")) attribute.setAttribute("fixed", value); else if (value != null) attribute.setAttribute("default", value); name = lookahead ; } } private int occurs(Element el, String content ) { int length = content.length(); if (content.endsWith ("?")) { el.setAttribute("minOccurs", "0"); -- length ; } else if (content.endsWith("+")) { el.setAttribute("maxOccurs", "unbounded"); -- length; } else if (content.endsWith("*")) { el.setAttribute("minOccurs", "0"); el.setAttribute("maxOccurs", "unbounded"); -- length; } return length; } private Element createGroup(Document schema, String type, StringTokenizer content, int delimiterIndex ) { Element groupType = schema .createElement(type); while (content.hasMoreTokens()) { String item = content.nextToken().trim(); if (item.startsWith("(")) groupType.appendChild(anonymousGroup(schema , item, delimiterIndex)); else if (item.startsWith("%")) { // reference to dtd entity respectively xs group Element groupRef = schema.createElement("group"); groupType.appendChild(groupRef); groupRef.setAttribute("ref", item.substring (1, occurs (groupRef, item) - 1)); // remove semicolon } else if (item.startsWith("#")) groupType.setAttribute("_dtd2xs_mixed_", "true"); // later moved to complexType!!! else { Element elRef = schema.createElement("element"); groupType.appendChild(elRef); elRef.setAttribute ("ref", item.substring(0, occurs(elRef, item))); } } return groupType; } private String hideDepth (String content, int delimiterIndex) { // ((a, b), (x, y)) => ((a; b), (x; y)) for correct parsing StringBuffer newContent = new StringBuffer(""); int depth = 0; for (int i = 0; i < content.length(); ++ i) { char c = content.charAt(i); if (c == '(') { newContent.append(c); ++ depth ; } else if (c == ')') { newContent.append(c); -- depth ; } else if (depth > 0 && c == delimiter[delimiterIndex].charAt(0)) // comma newContent.append(delimiter[1 - delimiterIndex].charAt(0)); else if (depth > 0 && c == delimiter[delimiterIndex].charAt(1)) // bar newContent.append(delimiter[1 - delimiterIndex].charAt(1)); else newContent.append(c); } return newContent.toString (); } private void element(Document schema, String name, String content, int delimiterIndex ) { Element el = schema.createElement("element"); schema.getDocumentElement().appendChild(el); el.setAttribute ("name", name); annotate(schema , el); StringTokenizer contentTokenizer = new StringTokenizer(content, "(,;|/?+* \t\n\r\f)"); if (contentTokenizer .countTokens() == 1 && contentTokenizer.nextToken().toUpperCase().equals ("#PCDATA" )) // simpleType el.setAttribute("type" , "string" ); else { Element complexType = schema.createElement ("complexType"); el.appendChild(complexType); Element group = anonymousGroup(schema , content, delimiterIndex ); complexType .appendChild(group); /* done by xslt if (group.getAttribute("_dtd2xs_mixed_").equals("true")) { group.removeAttribute("_dtd2xs_mixed_"); complexType.setAttribute("mixed", "true"); } */ } Autor: Thomas Schädler 169 Anhang A: Quelltext <xmlizer> configurator } private void group(Document schema, String name, String content, int delimiterIndex) { Element namedGroup = schema.createElement ("group"); schema.getDocumentElement().appendChild(namedGroup); namedGroup .setAttribute("name", name); annotate(schema , namedGroup); namedGroup.appendChild(anonymousGroup(schema, content, delimiterIndex)); } private Element anonymousGroup (Document schema, String content, int delimiterIndex) { Element group, atHolder = schema.createElement ("atHolder"); if (content.startsWith("(")) content = content.substring (1, occurs (atHolder, content) - 1); // remove parentheses else content = content.substring (0, occurs (atHolder, content)); content = hideDepth(content, delimiterIndex); StringTokenizer contentTokenizer = new StringTokenizer(content, delimiter[delimiterIndex].substring(1, 2)); // BAR if (contentTokenizer .countTokens() > 1) group = createGroup(schema, "choice", contentTokenizer, 1 - delimiterIndex); else if (content.trim().toUpperCase().equals("EMPTY")) group = schema.createElement("_dtd2xs_empty_"); else if (content.trim().toUpperCase().equals("ANY")) group = schema.createElement("_dtd2xs_any_"); else // default group = createGroup(schema, "sequence", new StringTokenizer(content, delimiter[delimiterIndex ]), 1 - delimiterIndex); // COMMA SEPARATION // optimize if (atHolder.getAttribute("minOccurs").length() > 0) group.setAttribute("minOccurs", atHolder.getAttribute("minOccurs" )); if (atHolder.getAttribute("maxOccurs").length() > 0) group.setAttribute ("maxOccurs", atHolder.getAttribute("maxOccurs" )); return group; } private Document transform(Document xml, String xsltURI ) { try { Document xslt = XmlDocument .createXmlDocument(xsltURI); Document result = new XmlDocument(); (new XSLTransformEngine()).createTransform (xslt).transform(xml, result); result .getDocumentElement().removeAttribute("xmlns"); // added by xt return result; } catch (Exception x) { log("\ndtd2xs: " + x); return null; } } private void minusAtplusNs(Document schema) { schema.replaceChild(minusAtplusNs(schema, schema.getDocumentElement()), schema.getDocumentElement ()); schema.getDocumentElement().setAttribute("xmlns:" + schemaPrefix, "http://www.w3.org/2001/XMLSchema"); } private boolean isBuiltInSimpleType (String type) { for (int i = 0; i < builtInSimpleType.length; ++ i) if (type.equals(builtInSimpleType[i])) return true; return false; } private Node minusAtplusNs(Document schema, Element e) { Element ee = schema.createElement(schemaPrefix + ':' + e.getTagName()); // attributes NamedNodeMap ats = e.getAttributes(); for (int i = 0; i < ats.getLength(); ++ i) { String name = ats.item(i).getNodeName (); String value = ats.item(i).getNodeValue(); if (! name.equals("xmlns") && ! name.equals("_dtd2xs_mixed_")) // remove these attributes if ((name.equals("type" ) || name.equals("base")) && isBuiltInSimpleType(value)) ee.setAttribute(name, schemaPrefix + ':' + value); else ee.setAttribute(name, value); } // elements for (Node x = e.getFirstChild(); x != null; x = x.getNextSibling()) if (x.getNo deType() == Node.ELEMENT_NODE) ee.appendChild(minusAtplusNs (schema, (Element) x)); else ee.appendChild(x.cloneNode(true)); return ee; } /* private String replace(String source, String from, String to) { StringBuffer goal = new StringBuffer(""); int i = 0, j = source.indexOf(from); while (j >= 0) { goal.append(source.substring(i, j)); goal.append(to); i = j + from.length(); j = source.indexOf(from, i); } goal.append(source.substring(i)); return goal.toString(); } */ private String removeComments(String dtd ) { StringBuffer dtdWithoutComments = new StringBuffer(""); int commentStart, commentEnd = 0, from = 0; while ((commentStart = dtd.indexOf("<!--", commentEnd)) >= 0) { commentEnd = dtd.indexOf("-->", commentStart) + 3; dtdWithoutComments.append(dtd.substring(from, commentStart)); if (! ignoreComments) { comment[numComments] = dtd.substring(commentStart + "<!--".length(), commentEnd - "-->".length ()); if (comment[numComments ].length() <= commentLength) ++ numComments; Autor: Thomas Schädler 170 Anhang A: Quelltext <xmlizer> configurator } from = commentEnd; } return dtdWithoutComments + dtd.substring (from, dtd.length()); } private int weightOf(char c, boolean prefix) { if ("\n\t:".indexOf(c) >= 0) return 10; else if (prefix && "<[{(\"'".indexOf(c) >=0 || ! prefix && ">]})\"'".indexOf(c) >= 0) return 100; else return 1; } private boolean related(String comment, String concept) { int occurrence = 0; boolean highlighted = false; int conceptStart, conceptEnd = 0; while ((conceptStart = comment.indexOf(concept, conceptEnd)) >= 0) { conceptEnd = conceptStart + concept.length (); ++ occurrence; int highlightPrefix = 0; for (int i = conceptStart; i > 0 && ! Character .isLetterOrDigit(comment.charAt(i - 1)); -- i) { highlightPrefix += weightOf(comment.charAt(i - 1), true); if (comment.charAt (i - 1) == '\n') break; } int highlightPostfix = 0; for (int i = conceptEnd; i < comment.length() && ! Character.isLetterOrDigit(comment.charAt(i)); ++ i) { highlightPostfix += weightOf (comment.charAt (i), false ); if (comment.charAt (i) == '\n') break; } if (highlightPrefix > 0 && highlightPostfix > 0) highlighted |= (highlightPrefix + highlightPostfix >= conceptHighlight); } return (highlighted && occurrence >= conceptOccurrence); } private void annotate(Document schema, Element construct) { if (ignoreComments || conceptRelation.indexOf(construct.getTagName ()) < 0) return ; Element annotation = schema.createElement ("annotation"); String concept; if (! construct .getAttribute("name").equals("")) concept = construct.getAttribute ("name"); else if (! construct .getAttribute("ref").equals("")) concept = construct.getAttribute ("ref"); else if (! construct .getAttribute("value").equals("")) concept = construct.getAttribute ("value"); else return ; int numDocumentation = 0; for (int i = 0; i < numComments ; ++ i) if (related(comment[i], concept)) { log("\ndtd2xs: relate(" + concept + ", \"" + comment[i] + "\")"); Element documentation = schema.createElement("documentation"); annotation.appendChild(documentation); if (commentLanguage != null && ! commentLanguage .equals("")) documentation.setAttribute("xml:lang", commentLanguage ); documentation.appendChild(schema.createTextNode(comment[i])); ++ numDocumentation; } if (numDocumentation > 0) construct.appendChild(annotation); } private boolean isLexicalUnit(char first , char last) { if (Character.isWhitespace (first) && ! Character.isWhitespace (last)) return false ; if (! Character .isWhitespace(first) && Character.isWhitespace (last)) return false ; if (first == '(' && last != ')') return false; if (first != '(' && last == ')') return false; return true; } private int useOf(String entityName , String entityContent, String dtd, boolean resolveEntity) { // log("\ndtd2xs: <useOf entityName= \"" + entityName + " \" entityContent=\"" + entityContent + "\">\n"); if (resolveEntity || entityContent.length () < 2 || ! isLexicalUnit (entityContent.charAt(0), entit yContent.charAt(entityContent .lengt h() - 1))) return meaninglessEntity; /* does the entity represent a meaningful unit? */ String entityUse = "%" + entityName + ";"; int entityUseStart, entityUseEnd = 0, entityIndex = -1, elementIndex = -1, attlistIndex = -1; boolean entityUsed = false ; while ((entityUseStart = dtd.indexOf(entityUse , entityUseEnd)) >= 0) { entityUsed = true; entityUseEnd = entityUseStart + entityUse.length(); if (entityIndex < 0) { entityIndex = dtd.lastIndexOf("<!ENTITY", entityUseStart); if (-1 < entityIndex && dtd.indexOf(">", entityIndex) < entityUseStart) entityIndex = -1; } if (elementIndex < 0) { elementIndex = dtd.lastIndexOf("<!ELEMENT", entityUseStart ); if (-1 < elementIndex && dtd.indexOf(">", elementIndex) < entityUseStart) elementIndex = -1; } if (attlistIndex < 0) { attlistIndex = dtd.lastIndexOf("<!ATTLIST", entityUseStart ); if (-1 < attlistIndex && dtd.indexOf(">", attlistIndex) < entityUseStart) attlistIndex = -1; } } if (! entityUsed) return unused Entity; // if (entityIndex >= 0) return meaninglessEntity; // comment out for CDA because of null.code.set // -1 < elementIndex means that entity is used in element declaration ... int entityMeaning = meaninglessEntity; Autor: Thomas Schädler 171 Anhang A: Quelltext <xmlizer> configurator if (elementIndex >= 0 && attlistIndex < 0 || -1 < entityContent.indexOf("#PCDATA" ) || -1 < entityContent.indexOf('*') || -1 < entityContent.indexOf('?') || -1 < entityContent.indexOf(',') || -1 < entityContent.indexOf('+')) entityMeaning = contentModelEntity; else if (-1 < "CDATA".indexOf(entityContent) || entityContent .startsWith("(") && entityContent.endsWith(")")) entityMeaning = enumerationEntity; else if (attlistIndex >= 0 && elementIndex < 0 && (new StringTokenizer(entityContent)).countTokens() >= 2) entityMeaning = attributeListEntity; return entityMeaning ; } private String resolveEntity(String name , String content, String dtd) { StringBuffer resolved = new StringBuffer(""); int endUse = 0, startUse; while (-1 < (startUse = dtd.indexOf("%" + name + ";", endUse))) { resolved.append(dtd.substring(endUse, startUse)); resolved.append(content); endUse = startUse + name.length() + 2; } resolved.append (dtd.substring(endUse , dtd.length())); return resolved .toString(); } /** * Translate DTD to REC-xmlschema-1-20010502.<P> * @param dtdURL Location of the DTD resource.<P> * @param resolveEntities Resolve DTD entities. Unused DTD entities are ignored. Map meaningful DTD entities onto named, i.e. reusable XML Schema concepts such as group, attributeGroup and simpleType.<P> * @param preserveComments Preserve DTD comments. Map DTD comments onto XML Schema documentation. Locates DTD comments at /schema/annotation[1]/documentation[<I>i</I>] referred to by <BR>&lt;documentation source="#xpointer(/schema/annotation[1]/documentation[<I>i</I>]/text())"/&gt;.<P> * @param commentLanguage Examples: "en", "de" ... Result: &lt;documentation xml:lang="en"/&gt;.<P> * @param commentLength Ignore DTD comments with length greater than <code>commentLength</code>.<P> * @param conceptRelation Relate DTD comments to model concepts. Ignore comments without concept relation.<P> * @param schemaConcepts Example: "element enumeration" relates DTD comments to the model concepts valueof(element/@name), value-of(enumeration/@value).<P> * @param minRelation Minimum relation between DTD comment and model concept. Heuristics <BR>{ relation = 0; for (concept occurs in comment) relation += highlight(concept); return relation >= minRelation; }<P> * @return XML Schema<P> */ public String translate( String dtdURI, String xsltURI , boolean resolveEntities, boolean ignoreComments, int commentLength, String commentLanguage, String conceptRelation, int conceptHighlight, int conceptOccurrence) { try { log("\ndtd2xs: dtdURI " + dtdURI ); log("\ndtd2xs: resolveEntities " + resolveEntities); log("\ndtd2xs: ignoreComments " + ignoreComments); log("\ndtd2xs: commentLength " + commentLength); log("\ndtd2xs: commentLanguage " + commentLanguage); log("\ndtd2xs: conceptHighlight " + conceptHighlight ); log("\ndtd2xs: conceptOccurrence " + conceptOccurrence); log("\ndtd2xs: conceptRelation " + conceptRelation); Document schema = new XmlDocument(); schema .appendChild(schema.createElement("schema")); log("\ndtd2xs: load DTD ... "); String dtd = (new xurl()).communicate (dtdURI); log("done"); log("\ndtd2xs: remove comments from DTD ... "); this.ignoreComments = ignoreComments; this.commentLength = commentLength; this.commentLanguage = commentLanguage; this.conceptRelation = conceptRelation; this.conceptHighlight = conceptHighlight; this.conceptOccurrence = conceptOccurrence ; numComments = 0; dtd = removeComments(dtd); log("done"); log("\ndtd2xs: DOM translation ..."); StringTokenizer dtdTokenizer = new StringTokenizer(dtd, "<>"); while (dtdTokenizer.hasMoreTokens()) { String decl = dtdTokenizer.nextToken(); if (decl.startsWith("!ENTITY")) { StringTokenizer entTokenizer = new StringTokenizer(decl, " \t\n\r\f%"); entTokenizer.nextToken(); String name = entTokenizer.nextToken(); String content = entTokenizer .nextToken ("").trim(); content = content.substring(1, content.length() - 1); // remove quotes switch (useOf(name, content, dtd, resolveEntities )) { case enumerationEntity: log("\ndtd2xs: simpleType[" + name + "][" + content + "]"); simpleType(schema, name, content); break; case contentModelEntity: log("\ndtd2xs: group[" + name + "][" + content + "]"); group(schema, name, content, 0); break; case attributeListEntity: log("\ndtd2xs: attributeGroup[" + name + "]"); Element atGroup = schema.createElement("attributeGroup"); schema .getDocumentElement().appendChild(atGroup); atGroup.setAttribute("name", name); annotate(schema, atGroup); attributeGroup(schema , atGroup, content); break; case meaninglessEntity: // resolve entity that must be declared before used !!! log("\ndtd2xs: resolve[" + name + "][" + content + "]"); dtd = resolveEntity(name, content, dtd); dtd = dtd.substring(dtd.indexOf(decl) + decl.length (), dtd.length()); // entity is processed and can be redefined! Autor: Thomas Schädler 172 Anhang A: Quelltext <xmlizer> configurator dtdTokenizer = new StringTokenizer(dtd, "<>"); // ignore unusedEntity } } else if (decl.startsWith("!ELEMENT")) { StringTokenizer elTokenizer = new StringTokenizer (decl); elTokenizer.nextToken(); String name = elTokenizer.nextToken(); String content = elTokenizer.nextToken("").trim(); // log("\ndtd2xs: element[" + name + "][" + content + "]"); element(schema , name, content, 0); } else if (decl.startsWith("!ATTLIST")) { StringTokenizer atTokenizer = new StringTokenizer (decl); atTokenizer.nextToken(); String complexTypeRef = atTokenizer.nextToken(); String content = atTokenizer.nextToken("").trim(); // attached to element by xsl Element attributes = schema.createElement("_dtd2xs_attributes_"); schema.getDocumentElement().appendChild (attributes); attributes.setAttribute("of", complexTypeRef ); // log("\ndtd2xs: attributeGroup[" + content + "]"); attributeGroup(schema, attributes, content); } } log("\n... done" ); log("\ndtd2xs: complextype.xsl ... "); schema = transform(schema, xsltURI); // move mixed attribute, attach attributes to element, remove redundant groups log("done"); log("\ndtd2xs: add namespace ... "); minusAtplusNs(schema); // remove crap attributes, add xml schema namespace log("done"); // further optimization possible StringWriter sw = new StringWriter(); ((XmlDocument) schema).write(sw); return sw.toString(); } catch (Exception x) { log("\ndtd2xs: " + x); return null; } } } /* * SchemaElement.java * * This class representates a Schema Element * * Created on 18. April 2002, 20:20 * ---------------------------------------------------------------------------* This file is part of <xmlizer>. * * <xmlizer> is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Foobar is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with <xmlizer>; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * ---------------------------------------------------------------------------*/ package configurator; import import import import org.jdom.*; java.util.*; javax.swing .*; javax.swing .tree.*; /** * Represents a SchemaElement <element name="..." ...> * @author [email protected] */ public class SchemaElement { private String tname; private String id; private String trealname ; private Element telement ; private Vector attributes = new Vector(); //of SchemaAttributes private SchemaContent content; private Vector children = new Vector(); private JPanel tpanel = null; private String type = null; private String typeRef = null; private boolean hasInternalType = false; private SchemaSimpleConstraint simpleConstraint = null; private SchemaOccurrence occurrence = null; private String documentation = null; private Vector parents = new Vector (); //of SchemaElements private DefaultMutableTreeNode node = null; private configurator mother = null; //schemaElement-Data public String SCHEMAattributeFormDefault = new String("unqualified"); public String SCHEMAelementFormDefault = new String("unqualified" ); public String SCHEMAtargetNameSpace = new String(""); public String SCHEMAversion = new String (""); public String SCHEMAlanguage = new String(""); Autor: Thomas Schädler 173 Anhang A: Quelltext <xmlizer> configurator //type handling private SchemaType theType = null; //SQL private Vector SQLStatements = new Vector(); //of SQLStatement private String repetitionStatement = null; //CONSTRUCTORS //----------------------------------------------------------------------------------------------/** * Document node-like constructor **/ public SchemaElement(configurator conf,DefaultMutableTreeNode node,String name,Element element) { this.mother = conf; this.tname = name; this.node = node; this.telement = element; if (name.equalsIgnoreCase("<schema>" )) //special treatment { this.tpanel = new JPanel(new java.awt.GridLayout(7,1)); this.tpanel .add(new JLabel("XML Schema root element")); this.tpanel .add(new JLabel("-----------------------")); this.trealname = "schema root"; //disableRefresh(); } else if (name.equalsIgnoreCase("-=sequence=-")) { this.tpanel = new JPanel(); this.tpanel .add(new JLabel("Sequence of elements:")); this.trealname = "sequence" ; disableRefresh(); } else if (name.equalsIgnoreCase("-=choice= -")) { this.tpanel = new JPanel(); this.tpanel .add(new JLabel("Choice of elements:")); this.trealname = "choice"; disableRefresh(); } else if (name.equalsIgnoreCase("-=all=-")) { this.tpanel = new JPanel(); this.tpanel .add(new JLabel("All elements:" )); this.trealname = "all" ; disableRefresh(); } else if (name.equalsIgnoreCase("-=group=-")) { this.tpanel = new JPanel(); this.tpanel .add(new JLabel("Group of elements:")); this.trealname = "group"; disableRefresh(); } else if (name.equalsIgnoreCase("<any>")) { this.tpanel = new JPanel(); this.tpanel .add(new JLabel("Any elements):")); this.trealname = "any" ; disableRefresh(); } process(); } /** * XMLSchemaParser-like constructor */ public SchemaElement(configurator conf,DefaultMutableTreeNode node,Element element,String idpath ) { this.mother = conf; this.id = idpath; this.tname = null; this.node = node; this.telement = element; } /** * Constructor for special elements (no precessing, just showing the right name) */ public SchemaElement(configurator conf,DefaultMutableTreeNode node,String name) { this.mother = conf; this.tname = name; this.node = node; this.telement = null; if (name.equalsIgnoreCase("<schema>" )) //special treatment { this.tpanel = new JPanel(new java.awt.GridLayout(7,1)); this.tpanel .add(new JLabel("XML Schema root element" )); this.tpanel .add(new JLabel("-----------------------")); this.trealname = "schema root"; //disableRefresh(); } else if (name.equalsIgnoreCase("-=sequence=-")) { this.tpanel = new JPanel(); this.tpanel .add(new JLabel("Sequence of elements..." )); this.trealname = "sequence" ; disableRefresh(); } else if (name.equalsIgnoreCase("-=choice= -")) { this.tpanel = new JPanel(); this.tpanel .add(new JLabel("Choice of elements...")); this.trealname = "choice"; disableRefresh(); } else if (name.equalsIgnoreCase("-=all=-")) { this.tpanel = new JPanel(); this.tpanel .add(new JLabel("All elements...")); this.trealname = "all" ; disableRefresh(); } Autor: Thomas Schädler 174 Anhang A: Quelltext <xmlizer> configurator else if (name.equalsIgnoreCase("-=group=-")) { this.tpanel = new JPanel(); this.tpanel .add(new JLabel("Group of elements...")); this.trealname = "group"; disableRefresh(); } else if (name.equalsIgnoreCase("<any>")) { this.tpanel = new JPanel(); this.tpanel .add(new JLabel("Wildcard Component (any)")); this.trealname = "any" ; disableRefresh(); } } //Initialization of the data //----------------------------------------------------------------------------------------------private void process() { if (this.tname != null && this.tname .equalsIgnoreCase("<schema>")) { Attribute attr = null; attr = this.telement.getAttribute("attributeFormDefault"); if (attr != null) { SCHEMAattributeFormDefault = attr.getValue().trim(); } this.tpanel .add(new JLabel("attributeFormDefault : " + SCHEMAattributeFormDefault)); attr = this.telement.getAttribute("elementFormDefault"); if (attr != null) { SCHEMAelementFormDefault = attr.getValue().trim(); } this.tpanel .add(new JLabel("elementFormDefault : " + SCHEMAelementFormDefault )); attr = this.telement.getAttribute("targetNamespace"); if (attr != null) { SCHEMAtargetNameSpace = attr.getValue().trim(); } this.tpanel .add(new JLabel("targetNamespace : " + SCHEMAtargetNameSpace)); attr = this.telement.getAttribute("version"); if (attr != null) { SCHEMAversion = attr.getValue().trim(); } this.tpanel.add(new JLabel("version : " + SCHEMAversion)); attr = this.telement.getAttribute("xml:lang"); if (attr != null) { SCHEMAlanguage = attr.getValue().trim(); } this.tpanel .add(new JLabel("xml:lang : " + SCHEMAlanguage )); } } //FIXME - Process the types correctly or delete it //or leave it here for next (type aware) version public void processType(Element typeElement) { this.theType = new SchemaType(); //theType.processType(typeElement); } public void processTypeRef(Element typeElement) { this.theType = new SchemaType(); //theType.processTypeRef(typeElement); } public void processInternalType() { this.theType = new SchemaType(); //theType.processInternalType(this.telement); } private StringBuffer addOccurrenceString (StringBuffer name) { if (getOccurrence() == null) { return name; } else { name.append (this.occurrence .getShortOcc()); return name; } } public void addDocumentation(String doc) { if(!doc.equalsIgnoreCase("")) { this.documentation = doc; } } public String getDocumentation () { return this.documentation; } public void addAttribute (Element attr,Hashtable loadedAttribs) { SchemaAttribute newattr = new SchemaAttribute(attr); //System.out.print("IN ELEMENT " + this.trealname); if (loadedAttribs.containsKey(this.id + newattr.getName())) //an element of this name loaded { //add a new attribute, but fill it with the loaded info SchemaAttribute loaded = (SchemaAttribute)loadedAttribs.get(this.id + newattr.getName()); newattr.setMapID (loaded.getMapID ()); newattr.setMapInfo(loaded.getMapInfo()); this.attributes.add(newattr); //System.out.println("ADDED ATTR: " + newattr.getName() + " >> " + newattr.getMapID() + " >> " + n ewattr.getMapInfo()); //System.out.print(" ADDED WITH LOAD:" + newattr.getName() + " \n"); } else //add a new (clean) attribute Autor: Thomas Schädler 175 Anhang A: Quelltext <xmlizer> configurator { this.attributes.add(newattr); //System.out.print(" ADDED CLEAR: " + newattr.getName() + "\n"); } } public boolean hasContent() { if (this.content != null) { return true; } else return false; } public SchemaContent getContent() { return this.content; } public void setContent(SchemaContent cont) { if (cont != null) { this.content = cont; //System.out.println(cont); } } public Vector getAttributes() { return this.attributes; } public boolean hasType() { if (this.type != null) { return true; } else { return false; } } public boolean hasTypeRef() { if (this.typeRef != null) { return true; } else { return false; } } public void setInternalType() { this.hasInternalType = true; } public boolean hasInternalType () { return this.hasInternalType; } /** * Add a name to the parent-vector: holds names of parent SchemaElements */ public void addParent(SchemaElement parent) { this.parents.add(parent); } public Vector getParents() { return this.parents; } //SQL STATEMENTS //----------------------------------------------------------------------------------------------//for the (linked) repetition public void setRepetition(String sqlid) { this.repetitionStatement = sqlid; } public String getRepetition() { return this.repetitionStatement ; } public SQLStatement getRepetitionStatement() { if (this.repetitionStatement != null) { return mother.getProjectData().DB2XMLgetmapping ().getSQLStatementByMapID (this.repetitionStatement); } else return null; } //for the statments of the element public void addSQLStatement(SQLStatement stat ) { if (stat != null) { this.SQLStatements.add(stat); this.updateList(); } } public Vector getSQLStatements () { return this.SQLStatements; } public void removeSQLStatement (SQLStatement st) { if (st != null) { for (Enumeration e = this.SQLStatements.elements(); e.hasMoreElements();) { SQLStatement temp = (SQLStatement )e.nextElement(); if (temp.equals(st)) { //remove the statement String id = st.getID(); this.SQLStatements.remove(temp); //clean the repetitions for this id if (this.getRepetitionStatement() != null) { Autor: Thomas Schädler 176 Anhang A: Quelltext <xmlizer> configurator if (this.getRepetitionStatement().equals (st)) { this.repetitionStatement = null; } } //clean the content for this id if (this.hasContent ()) { this.getContent ().cleanMapping (); } //clean the attributes for this id cleanAttributeByID(id); mother.getLog().addDebug ("Removed SQL Statement: " + temp.toString()); break; } } } } /** * Clears all mappings of all attributes, but only the data, not the rep. * which are dependent on the specified SQLStatement */ public void cleanMapData(SQLStatement stat) { String id = stat.getID(); //clean the content if (this.hasContent()) { this.getContent().cleanMapping(); } //clean the attributes for (Enumeration ee = this.attributes.elements (); ee.hasMoreElements();) { SchemaAttribute attr = (SchemaAttribute)ee.nextElement(); if (attr.getMapID() != null) { if (attr.getMapID().equalsIgnoreCase(id)) { attr.cleanMapping(); } } } } /** * Clears the mapping of the specified attribute (via ID) of this element */ public void cleanAttributeByID (String id ) { for (Enumeration ee = this.attributes.elements(); ee.hasMoreElements();) { SchemaAttribute attr = (SchemaAttribute)ee.nextElement(); if (attr.getMapID() != null) { if (attr.getMapID().equalsIgnoreCase(id)) { attr.cleanMapping(); } } } } //STRING REPRESENTATION //----------------------------------------------------------------------------------------------/** * By default show the key as String */ public String toString() { return this.tname; } //GET AND SET METHODS //----------------------------------------------------------------------------------------------public void setElement(Element element) { this.telement = element; process(); } public Element getElement() { return this.telement ; } public void setRealName(String n) { this.trealname = n; } public String getRealName() { return this.trealname; } public void setID(String n) { this.id = n; } public String getID () { return this.id; } public void setName(String name) { StringBuffer buff = new StringBuffer (name); buff = addOccurrenceString (buff); this.tname = buff.toString (); } public String getName() { return this.tname; } public void setType(String type) { if (!type.equalsIgnoreCase ("")); { this.type = type; } Autor: Thomas Schädler 177 Anhang A: Quelltext <xmlizer> configurator } public void setTypeRef(String typeref) { if (!typeref.equalsIgnoreCase("")) { this.typeRef = typeref ; } } public String getType() { return this.type; } public String getTypeRef () { return this.typeRef; } public SchemaOccurrence getOccurrence() { return this.occurrence; } public void setOccurrence(SchemaOccurrence occ) { this.occurrence = occ; } //GRAPHIC REPRESENTATION //----------------------------------------------------------------------------------------------private boolean refresh = true; private void enableRefresh() { this.refresh = true; } private void disableRefresh() { this.refresh = false ; } public boolean isRefresh () { return this.refresh; } private void updateList() { //the database-lister window updater SQLChooser sqlch = (SQLChooser)mother.open("SQLChooser"); //make it's combobox not enabled->only the current element is shown sqlch.updateView(this); } private JLabel getDragTargetForRepetition(String rep_short_name) { return new JLabel("Repetition: " + rep_short_name); } /** * Returns the Element Info Panel * Can also be called Refresh or something because it does exactly that, not only creating the panel */ public JPanel getElementPanel() { //the database-lister window updater if(this.refresh && this.trealname.equalsIgnoreCase("schema root")) { this.tpanel = new SchemaRootPanel(this.mother,this); } else if (this.refresh) { this.tpanel = new SchemaElementPanel(this.mother,this); } SQLChooser sqlch = (SQLChooser)mother.open("SQLChooser"); sqlch.updateView(this); return this.tpanel; } private void dataButtonActionPerformed(java.awt.event.ActionEvent evt) { dbBrowser browser = (dbBrowser)this.mothe r.open("databaseBrowser"); browser.enableTakeover(this); } }/* * listItem.java * * Created on 22. Mai 2002, 12:44 * ---------------------------------------------------------------------------* This file is part of <xmlizer>. * * <xmlizer> is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Foobar is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should hav e received a copy of the GNU General Public License * along with <xmlizer>; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * ---------------------------------------------------------------------------*/ package configurator; /** * Represents the metadata of a table * * @author [email protected] * @version 0.3 */ class listItem { private String name ; Autor: Thomas Schädler 178 Anhang A: Quelltext <xmlizer> configurator private int rowcount; private boolean selected = false; public listItem(String name,int rowcount ) { this.name = name; this.rowcount = rowcount; } public listItem(String name,int rowcount ,boolean marked ) { this.name = name; this.rowcount = rowcount; this.selected = marked; } public String toString() { return this.name + " (" + this.rowcount + ")"; } public String getName() { return this.name; } public int getRowCount() { return this.rowcount ; } public boolean isSelected() { return this.selected ; } public void toggleSelection() { if (this.selected) { this.selected = false; } else { this.selected = true; } //System.out.println("ListItem " + name + " is now " + selected); } }/* * activityMeter.java * * Created on 21. Mai 2002, 21:54 * ---------------------------------------------------------------------------* This file is part of <xmlizer>. * * <xmlizer> is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Foobar is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with <xmlizer>; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * ---------------------------------------------------------------------------*/ package configurator; import javax.swing .JButton; import javax.swing .JProgressBar; /** * All neccessary information for showing the current background activity * as well as STOP -Button * @author [email protected] * @version 0.3 */ public class activityMeter { private int running = 0; private String meter = new String(); private JButton thebutton; private JProgressBar theprogressbar ; /** * Constructor: * @param JButton * @param JProgressBar */ public activityMeter(JButton b , JProgressBar p) { this.thebutton = b; this.theprogressbar = p; } synchronized public void start (boolean stoppable) { running++; if (stoppable) { thebutton.setEnabled(true); theprogressbar.setValue(0); } ensure(); } synchronized public void stop(boolean stoppable) { if (running >= 1) //no negative numbers at all { if (stoppable) { thebutton.setEnabled(false); meter = new String (); theprogressbar.setValue (0); } Autor: Thomas Schädler 179 Anhang A: Quelltext <xmlizer> configurator running--; } ensure(); } synchronized public void setMax(int max) { theprogressbar.setMaximum(max); } synchronized public void setValue(int value) { theprogressbar.setValue(value); } synchronized public void setString(String string) { meter = string; ensure(); } synchronized public void init() { running = 0; meter = new String(); theprogressbar.setValue(0); ensure(); } private void ensure () { if (running > 0) { theprogressbar.setStringPai nted(true); if (meter.equalsIgnoreCase(new String ())) { theprogressbar.setString("[" + new Integer(running).toString() + "]"); } else { theprogressbar.setString(meter + " : [" + new Integer(running).toString() + "] "); } } else if (running <= 0) { theprogressbar.setStringPainted(false ); } } } /* * logWindow.java * * Created on 24. Mai 2002, 16:19 * ---------------------------------------------------------------------------* This file is part of <xmlizer>. * * <xmlizer> is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Foobar is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with <xmlizer>; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * ---------------------------------------------------------------------------*/ package configurator; import java.io.*; import java.awt.*; import java.lang.*; import java.util.*; import javax.swing .*; import java.awt.event.*; import javax.swing .text.*; /** * The logwindow is the interface to output files, information and debug-info * in one centralized window * @author [email protected] * @version 0.3 */ public class logWindow extends MyInternalFrame { private configurator mother; private String ID; private boolean isDebugEnabled = false; private java.awt.Component selectedTab = null; private StyleContext styles; private Style errorStyle ; private Style warnStyle; private Style infoStyle; private Style debugStyle ; private Style defaultStyle; private Style errorStyleIcon; private Style warnStyleIcon; private Style infoStyleIcon; private Style debugStyleIcon; private DefaultStyledDocument logDoc; private DefaultStyledDocument debugDoc; private JPopupMenu popup = new JPopupMenu(); private JMenuItem saveThis; private JMenuItem placeWindow; private JMenuItem clearThis; private JMenuItem clearAll; private JMenuItem removeThis; private JMenuItem removeAll; private JCheckBoxMenuItem debug; private boolean isUpdating = false; Autor: Thomas Schädler 180 Anhang A: Quelltext <xmlizer> configurator /** Creates new form logWindow * @param mainProgram The configurator * @param uid The unique ID for this window */ public logWindow(configurator mainProgram,String uid) { this.mother = mainProgram; this.ID = uid; initStyles (); initLog(); initDebug(); initComponents(); initLogComp(); initPopupMenu(); show(); } /** This method is called from within the constructor to * initialize the form. * WARNING: Do NOT modify this code. The content of this method is * always regenerated by the Form Editor. */ private void initComponents()//GEN-BEGIN:initComponents { backPanel = new javax.swing.JPanel(); theTabbedPane = new javax.swing .JTabbedPane(); setMaximizable(true); setTitle("Log Window"); setIconifiable(true); setResizable(true); setClosable(true); try { setIcon(true); } catch (java.beans.PropertyVetoException e) { e.printStackTrace(); } setFrameIcon(new javax.swing.ImageIcon(getClass().getResource ("/configurator/icons/History16.gif" ))); setDefaultCloseOperation(javax.swing .WindowConstants.HIDE_ON_CLOSE ); backPanel.setLayout(new java.awt.BorderLayout()); theTabbedPane.setTabPlacement(javax.swing .JTabbedPane.BOTTOM); theTabbedPane.setPreferredSize(new java.awt.Dimension(600, 200)); theTabbedPane.addKeyListener(new java.awt.event.KeyAdapter() { public void keyReleased(java.awt.event.KeyEvent evt) { theTabbedPaneKeyReleased(evt); } }); theTabbedPane.addMouseListener(new java.awt.event.MouseAdapter() { public void mouseClicked(java.awt.event.MouseEvent evt) { theTabbedPaneMouseClicked(evt); } }); backPanel.add(theTabbedPane, java.awt.BorderLayout.CENTER); getContentPane().add(backPanel, java.awt.BorderLayout.CENTER); pack(); }//GEN-END:initComponents private void theTabbedPaneKeyReleased(java.awt.event.KeyEvent evt )//GEN-FIRST:event_theTabbedPaneKeyReleased {//GEN-HEADEREND:event_theTabbedPaneKeyReleased // Add your handling code here: logWindow log = (logWindow)mother.open("log"); log.setVisible(true); }//GEN-LAST:event_theTabbedPaneKeyReleased private void theTabbedPaneMouseClicked(java.awt.event.MouseEvent evt)//GEN-FIRST:event_theTabbedPaneMouseClicked {//GEN-HEADEREND:event_theTabbedPaneMouseClicked // Add your handling code here: if(SwingUtilities.isRightMouseButton (evt)) { checkPopup(); popup.show(evt.getComponent (),evt.getX(),evt.getY()); } }//GEN-LAST:event_theTabbedPaneMouseClicked private JTextPane getSelectedTextPane() { JScrollPane selected = (JScrollPane)theTabbedPane.getSelectedComponent(); if (selected == debugScrollPane ) { return debugTextPane; } else if (selected == logScrollPane) { return logTextPane; } else { JTextPane custom = null; int position = 0; for (Enumeration e = filetabs.elements(); e.hasMoreElements();) { JScrollPane item = (JScrollPane)e.nextElement(); if (item == selected) { position = filetabs .lastIndexOf(item); break; } } return (JTextPane)tabtexts.get(position); } Autor: Thomas Schädler 181 Anhang A: Quelltext <xmlizer> configurator } // Variables declaration - do not modify//GEN -BEGIN:variables private javax.swing .JPanel backPanel; private javax.swing .JTabbedPane theTabbedPane ; // End of variables declaration//GEN-END:variables private private private private private private Vector filetabs = new Vector(); //holds all file tabs (JScrollPanes) Vector tabtexts = new Vector(); //holds all text components in the JScrollPanes JScrollPane debugScrollPane = null; JTextPane debugTextPane = null; JScrollPane logScrollPane = null; JTextPane logTextPane = null; private void clearLog() { if (logTextPane != null) { try { logDoc.remove(0,logDoc.getLength()); } catch(Exception ex) { addDebug(ex); } } } private void clearDebug() { if (debugTextPane != null) { try { debugDoc.remove(0,debugDoc.getLength()); } catch(Exception ex) { addDebug(ex); } } } private void saveThis_actionPerformed(java.awt.event.ActionEvent evt) { // Add your handling code here: JTextPane selected = getSelectedTextPane(); Document doc = selected.getDocument(); try { final String message = doc.getText(0,doc.getLength()); if (!message.equals(new String())) { String location = new String (); //open filechooser JFileChooser chooser = new JFileChooser(); chooser.setDialogType(javax.swing .JFileChooser.SAVE_DIALOG ); simpleFileFilter filter = new simpleFileFilter(); filter.addExtension("xml"); filter.addExtension("txt"); filter.addExtension("log"); filter.setDescription("xml;txt;log"); chooser.setFileFilter(filter ); int returnVal = chooser.showSaveDialog (this); if(returnVal == JFileChooser .APPROVE_OPTION ) { location = chooser.getSelectedFile ().getPath(); } else { //aborted mother.getLog().addInformation("Custom Output save aborted!"); return; } final String thelocation = location; if (!thelocation.equals (new String())) { Runnable r = new Runnable() { public void run() { //save the stuff there try { //file stuff File outputFile = new File(thelocation); FileOutputStream outputStream = new FileOutputStream (outputFile); OutputStreamWriter out = new OutputStreamWriter (outputStream,"UTF8"); out.write(message); out.close(); } catch (IOException ex ) { mother.getLog().addError(ex); return; } } }; Thread saver = new Thread(r); saver.start(); } } else { mother.getLog().addInformation("Nothing to save. Preview XML Output is empty!" ); } } catch(Exception ex) { mother .getLog().addError(ex); } } private void clearAll_actionPerformed(java.awt.event.ActionEvent evt) { clearLog(); clearDebug (); for (Enumeration e = tabtexts.elements(); e.hasMoreElements();) { Document doc = ((JTextPane)e.nextElement()).getDocument(); Autor: Thomas Schädler 182 Anhang A: Quelltext <xmlizer> configurator try { doc.remove(0,doc.getLength()); } catch(Exception ex) { mother.getLog().addError(ex); } } } private void clearThis_actionPerformed(java.awt.event.ActionEvent evt) { JTextPane selected = getSelectedTextPane(); if (selected == debugTextPane) { clearDebug(); } else if (selected == logTextPane) { clearLog(); } else { Document doc = selected.getDocument(); try { doc.remove(0,doc.getLength()); } catch(Exception ex) { mother.getLog().addError(ex); } } //saveButton.setEnabled(false); mother.getLog().addInformation("Output cleared ."); } private void removeThis_actionPerformed(java.awt.event.ActionEvent evt ) { JScrollPane selected = (JScrollPane)theTabbedPane.getSelectedComponent(); if ((selected != debugScrollPane) && (selected != logScrollPane)) { int sel = filetabs.indexOf(selected); filetabs.remove(sel); tabtexts.remove(sel); theTabbedPane.remove(selected); } } private void removeAll_actionPerformed(java.awt.event.ActionEvent evt) { for (Enumeration e = filetabs.elements(); e.hasMoreElements();) { theTabbedPane.remove((JScrollPane)e.nextElement ()); } filetabs.removeAllElements (); tabtexts.removeAllElements (); } private void placeWindow_actionPerformed (java.awt.event .ActionEvent evt) { mother.setLogWindow2StandartLocation (); } private void debug_actionPerformed(java.awt.event.ActionEvent evt ) { if(!isDebugEnabled) //create new tab and enable { //create new components debugScrollPane = new JScrollPane(); debugTextPane = new JTextPane(debugDoc); debugTextPane.setEditable(false); //add the textpane to the scrollpane --> scroll debugScrollPane.setViewportView(debugTextPane); //add the new tab to theTabbedPane theTabbedPane.addTab("Debug", new javax.swing.ImageIcon(getClass ().getResource("/configurator/icons/actions/startDebugger.gif")),debugScrollPane,"Debug log" ); theTabbedPane.setSelectedComponent(debugScrollPane); debugTextPane.addMouseListener(new java.awt.event.MouseAdapter () { public void mouseClicked(java.awt.event.MouseEvent evt) { theTabbedPaneMouseClicked(evt); } }); ensureIsOnTop(debugScrollPane); //toggle isDebugEnabled = true; } else { //toggle isDebugEnabled = false ; //remove the tab theTabbedPane.remove(debugScrollPane); //to be sure debugScrollPane = null; debugTextPane = null; } } private void initPopupMenu() { saveThis = new JMenuItem("Save" ); placeWindow = new JMenuItem("Smart Layout"); clearThis = new JMenuItem("Clear"); clearAll = new JMenuItem("Clear all" ); removeThis = new JMenuItem ("Close"); removeAll = new JMenuItem("Close all"); debug = new JCheckBoxMenuItem("Debug"); debug.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed (ActionEvent e) { debug_actionPerformed(e); Autor: Thomas Schädler 183 Anhang A: Quelltext <xmlizer> configurator } }); saveThis.addActionListener (new java.awt.event.ActionListener() { public void actionPerformed (ActionEvent e) { saveThis_actionPerformed(e); } }); placeWindow.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed (ActionEvent e) { placeWindow_actionPerformed(e); } }); clearThis.addActionListener(new java.awt.event.ActionListener () { public void actionPerformed (ActionEvent e) { clearThis_actionPerformed(e); } }); clearAll.addActionListener (new java.awt.event.ActionListener() { public void actionPerformed(ActionEvent e) { clearAll_actionPerformed(e); } }); removeThis .addActionListener(new java.awt.event.ActionListener() { public void actionPerformed (ActionEvent e) { removeThis_a ctionPerformed(e); } }); removeAll.addActionListener(new java.awt.event .ActionListener () { public void actionPerformed (ActionEvent e) { removeAll_actionPerformed(e); } }); popup.add(saveThis); popup.addSeparator(); popup.add(clearThis); popup.add(clearAll); popup.addSeparator(); popup.add(removeThis ); popup.add(removeAll); popup.addSeparator(); popup.add(debug ); popup.addSeparator(); popup.add(placeWindow); } /** * Checks the popupmenu for enabled/disabled items before popping up */ private void checkPopup() { if (isUpdating) { removeAll.setEnabled(false); removeThis.setEnabled(false ); clearThis.setEnabled(false); clearAll.setEnabled(false); } else { //saveThis & clearThis if (getSelectedTextPane().getDocument ().getLength() > 0) { clearThis.setEnabled(true); saveThis.setEnabled(true); } else { clearThis.setEnabled(false); saveThis.setEnabled(false); } //removeThis & removeAll if(tabtexts .size() > 0) { removeThis.setEnabled(true); removeAll.setEnabled(true); } else { removeThis.setEnabled(false); removeAll.setEnabled(false); } //clearAll and debug is always on } } private void initLogComp () { //create new components logScrollPane = new JScrollPane (); logTextPane = new JTextPane(logDoc); logTextPane.setEditable(false); //add the textpane to the scrollpane --> scroll logScrollPane.setViewportView(logTextPane ); //add the new tab to theTabbedPane theTabbedPane.addTab ("Log" , new javax.swing.ImageIcon(getClass ().getResource("/configurator/icons/History16.gif")),logScrollPane ,"Event log"); theTabbedPane.setSelectedComponent(logScrollPane); logTextPane.addMouseListener(new java.awt.event.MouseAdapter() { public void mouseClicked(java.awt.event.MouseEvent evt) { theTabbedPaneMouseClicked(evt); } }); } private void initDebug() { debugDoc = new DefaultStyledDocument (styles); debugDoc.setLogicalStyle(0,debugStyle); } Autor: Thomas Schädler 184 Anhang A: Quelltext <xmlizer> configurator private void initLog() { logDoc = new DefaultStyledDocument(styles ); logDoc.setLogicalStyle(0,errorStyle); } private void initStyles() { styles = new StyleContext(); defaultStyle = styles.addStyle("defaultStyle", null); StyleConstants.setForeground(defaultStyle , Color.black); StyleConstants.setFontFamily(defaultStyle , "Dialog" ); errorStyle = styles.addStyle("errorStyle" , null); StyleConstants.setForeground(errorStyle, Color .red); StyleConstants.setFontFamily(errorStyle, "Dialog"); errorStyleIcon = styles.addStyle("errorStyleIcon", null); StyleConstants.setIcon(errorStyleIcon,new javax.swing.ImageIcon(getClass ().getResource("/configurator/icons/list/red.gif"))); warnStyle = styles.addStyle("warnStyle", null); StyleConstants.setForeground(warnStyle, Color.blue); StyleConstants.setFontFamily(warnStyle, "Dialog"); warnStyleIcon = styles.addStyle ("warnStyleIcon", null); StyleConstants.setIcon(warnStyleIcon ,new javax.swing.ImageIcon(getClass ().getResource("/configurator/icons/list/blue.gif"))); infoStyle = styles.addStyle("infoStyle", null); StyleConstants.setForeground(infoStyle, Color.black ); StyleConstants.setFontFamily(infoStyle, "Dialog"); infoStyleIcon = styles.addStyle ("infoStyleIcon", null); StyleConstants.setIcon(infoStyleIcon ,new javax.swing.ImageIcon(getClass ().getResource("/configurator/icons/list/green.gif" ))); debugStyle = styles.addStyle("debugStyle" , null); StyleConstants.setForeground(debugStyle, Color .black); StyleConstants.setFontFamily(debugStyle, "Dialog"); debugStyleIcon = styles.addStyle("debugStyleIcon", null); StyleConstants.setIcon(debugStyleIcon,new javax.swing.ImageIcon(getClass ().getResource("/configurator/icons/list/gray.gif"))); } /** * Adds an error message to the log (log tab) * @param text The error message to display */ public void addError(String text) { if (!(text == null) || !text.equals(new String ())) { this.addMessage(logDoc ,errorStyle,errorStyleIcon,"[E] ",text); } ensureIsOnTop(logScrollPane); } /** * Adds an exception as error message to the log (log tab) * @param ex The Exception */ public void addError(Exception ex) { this.addMessage (logDoc,errorStyle,errorStyleIcon,"[E] ",ex.getLocalizedMessage()); ensureIsOnTop(logScrollPane); } /** * Adds a warning message to the log (log tab) * @param text The warning message to display */ public void addWarning(String text) { if (!(text == null) || !text.equals(new String ())) { this.addMessage(logDoc ,warnStyle ,warnStyleIcon,"[W] ",text); } } /** * Adds an information message to the log (log tab) * @param text The information message to display */ public void addInformation(String text) { if (!(text == null) || !text.equals(new String ())) { this.addMessage(logDoc ,infoStyle ,infoStyleIcon,"[I] ",text); } } /** * Adds a debug message to the debuglog (debug tab) * @param text The debug message to display */ public void addDebug(String text) { if (!(text == null) || !text.equals(new String ())) { if (isDebugEnabled) { this.addMessage(debugDoc,debugStyle,debugStyleIcon,"[D] ",text); } } } /** * Adds an exception as debug message to the debuglog (debug tab) * @param extends Exception to show */ public void addDebug(Exception ex) { if (isDebugEnabled) { this.addMessage(debugDoc,debugStyle,debugStyleIcon,"[D] " ,ex.getLocalizedMessage()); } } Autor: Thomas Schädler 185 Anhang A: Quelltext <xmlizer> configurator /** * Adds a debug message to the debuglog (debug tab) and includes the caller -method * @param caller The debug messages caller method * @param text The debug message to display */ public void addDebug(String caller,String text) { if (!(text == null) || !text.equals(new String ())) { if (isDebugEnabled) { this.addMessage(debugDoc,debugStyle,debugStyleIcon,"[D] ",text+"\n -------> From: "+caller); } } } /** * Adds a file to a newly created Tab (always a seperate tab) * @param tabname The name of the new Tab * @param file The file to read in * @param tooltip The tooltip to display while hovering over this tab */ public void addNewTab(String thetabname,File file,String thetooltip) { if (file != null) { //make new Components final JScrollPane newScrollPane = new JScrollPane(); final JTextPane newTextPane = new JTextPane(); final Document doc = new DefaultStyledDocument(); FileInputStream instr = null; try { instr = new FileInputStream(file); } catch(FileNotFoundException ex) { mother.getLog().addError(ex); } BufferedReader reader = new BufferedReader (new InputStreamReader(instr)); StringWriter writer = new StringWriter(); PrintWriter out = new PrintWriter(writer); String line ; try { while ((line = reader.readLine()) != null) { out.println(line); } } catch(IOException ioe) { mother.getLog().addError(ioe); } out.flush(); newTextPane .setDocument(doc); newTextPane .setEditable(false); if (thetabname == null || thetabname.equals(new String())) { thetabname = "output"; } if (thetooltip == null) { thetooltip = ""; } final String tabname = thetabname; final String text = writer.toString(); final String tooltip = thetooltip; Runnable r = new Runnable() { public void run() { //set text if (text != null && (!text.equals(new String ()))) { try { doc.insertString (0,text,defaultStyle ); } catch(BadLocationException ble ) { mother .getLog().addError(ble); } } newTextPane.addMouseListener(new java.awt.event.MouseAdapter() { public void mouseClicked(java.awt.event.MouseEvent evt) { theTabbedPaneMouseClicked(evt); } }); //add the textpane to the scrollpane --> scroll newScrollPane.setViewportView (newTextPane); //add the new tab to theTabbedPane theTabbedPane.addTab(tabname,new javax.swing.ImageIcon(getClass ().getResource("/configurator/icons/openide/xmlObject.gif")),newScrollPane,tooltip); ensureIsOnTop(newScrollPane); //add the to the list and synch their positions filetabs .add(newScrollPane); int position = filetabs.lastIndexOf(newScrollPane ); tabtexts .add(position,newTextPane); } }; Thread runner = new Thread(r); runner .start(); } } /** * Adds a custom string (message) to a newly created Tab (always a seperate tab) * @param tabname The name of the new Tab * @param text The text to display in new tab * @param tooltip The tooltip to display while hovering over this tab */ public void addNewTab(String thetabname,String thetext,String thetooltip) { //make new Components final JScrollPane newScrollPane = new JScrollPane(); Autor: Thomas Schädler 186 Anhang A: Quelltext <xmlizer> configurator final JTextPane newTextPane = new JTextPane(); final Document doc = new DefaultStyledDocument (); newTextPane.setDocument(doc); newTextPane.setEditable(false); if (thetabname == null || thetabname .equals(new String())) { thetabname = "output"; } if (thetooltip == null) { thetooltip = ""; } final String tabname = thetabname; final String text = thetext; final String tooltip = thetooltip; Runnable r = new Runnable() { public void run() { //set text if (text != null && (!text.equals (new String()))) { try { doc.insertString(0,text,defaultStyle); } catch(BadLocationException ble) { mother.getLog().addError(ble); } } newTextPane.addMouseListener (new java.awt.event.MouseAdapter() { public void mouseClicked (java.awt.event .MouseEvent evt ) { theTabbedPaneMouseClicked (evt); } }); //add the textpane to the scrollpane --> scroll newScrollPane.setViewportView(newTextPane); //add the new tab to theTabbedPane theTabbedPane.addTab(tabname,new javax.swing.ImageIcon(getClass ().getResource("/configurator/icons/openide/xmlObject.gif")),newScrollPane,tooltip); ensureIsOnTop(newScrollPane); //add the to the list and synch their positions filetabs.add(newScrollPane); int position = filetabs .lastIndexOf(newScrollPane); tabtexts.add(position,newTextPane ); } }; Thread runner = new Thread (r); runner.start(); } public void isUpdating(boolean bool) { //System.out.println(bool); this.isUpdating = bool; } /** * Creates a new Tab (always a seperate tab) and returns a PipedOutputStream to fill it * @return PipedOutputStream * @param tabname The name of the new Tab * @param tooltip The tooltip to display while hovering over this tab */ public PipedOutputStream addNewTab(String tabname,String tooltip) { //make new Components JScrollPane newScrollPane = new JScrollPane(); JTextPane newTextPane = new JTextPane(); final EditorKit editor = new StyledEditorKit(); final Document doc = editor.createDefaultDocument(); final PipedInputStream in = new PipedInputStream(); PipedOutputStream out = new PipedOutputStream(); newTextPane.setEditorKit(editor ); newTextPane.setDocument(doc); newTextPane.setEditable(false); try { out.connect(in); Runnable reader = new Runnable() { public void run() { mother.getLog().isUpdating(true); try { editor.read(in,doc,0); in.close(); //mother.getLog().isUpdating(false); } catch(Exception ex) { mother.getLog().addError(ex); //mother.getLog().isUpdating(false); return; } } }; Thread readerthread = new Thread (reader); readerthread.setDaemon (true); readerthread.start(); } catch (IOException e ) { mother .getLog().addError(e); } //set tabname if (tabname == null || tabname.equals(new String())) { tabname = new String("output"); } //set tooltip Autor: Thomas Schädler 187 Anhang A: Quelltext <xmlizer> configurator if (tooltip == null) { tooltip = new String(); } newTextPane.addMouseListener(new java.awt.event.MouseAdapter() { public void mouseClicked(java.awt.event.MouseEvent evt) { theTabbedPaneMouseClicked(evt); } }); //add the textpane to the scrollpane --> scroll newScrollPane.setViewportView(newTextPane ); //add the new tab to theTabbedPane theTabbedPane.addTab (tabname,new javax.swing.ImageIcon(getClass ().getResource("/configurator/icons/openide/xm lObject.gif")),newScrollPane,tooltip); ensureIsOnTop(newScrollPane); //add the to the list and synch their positions filetabs.add(newScrollPane ); int position = filetabs.lastIndexOf(newScrollPane); tabtexts.add(position,newTextPane); return out; } private String getDate() { return java.text.DateFormat.getDateInstance().format(new java.util.Date()); } private String getTime() { return java.text.DateFormat.getTimeInstance().format(new java.util.Date()); } private synchronized void addMessage(DefaultStyledDocument doc,Style style,Style iconStyle ,String iconreplacer,String message) { String datetime = getDate() + " : " + getTime() + " >> " ; try { doc.insertString (doc.getLength(),iconreplacer,iconStyle); doc.insertString (doc.getLength(),datetime,style ); doc.insertString (doc.getLength(),message,style); doc.insertString (doc.getLength(),"\n",style); theTabbedPane.repaint(); } catch(BadLocationException ex) { mother .getLog().addError(ex); } if (doc == logDoc) { logTextPane .setCaretPosition(logDoc.getLength()); } if (doc == debugDoc) { debugTextPane.setCaretPosition(debugDoc.getLength()); } } synchronized private void ensureIsOnTop(JScrollPane pane) { if(!this.isVisible()) { this.setVisible(true); } if (this.isIcon ()) { mother .getMainDesktopPane().getDesktopManager().deiconifyFrame (this); } //mother.getMainDesktopPane().getDesktopManager().activateFrame(this); theTabbedPane.repaint(); } /** * This m ethod updates the UI if the setupwindow is closed * (and a change in the setup component occured) * Not used in this context! * @param conf The configurator */ public void update(configurator conf) { this.mother = conf; } } /* * DB2XMLmain.java * * Created on 9. April 2002, 20:43 * ---------------------------------------------------------------------------* This file is part of <xmlizer>. * * <xmlizer> is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Foobar is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along wit h <xmlizer>; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * ---------------------------------------------------------------------------*/ package configurator; import import import import import import import java.io.*; java.awt.*; java.util.*; java.lang.*; javax.swing .*; javax.swing .tree.*; org.jdom.*; Autor: Thomas Schädler 188 Anhang A: Quelltext <xmlizer> configurator import org.jdom.output.XMLOutputter; /** * The main class/internalframe of the module DB2XML * @author [email protected] */ public class DB2XMLmain extends MyInternalFrame { private static configurator mother; private String ID; private projectData theData; private Vector fileList = new Vector(); private Vector dbList = new Vector(); static int WARNING = 0; static int ERROR=1; static int FATAL_ERROR=2; private boolean isLoading = true; private static JTree theTree = null; private String xmlFile = new String (); private XMLSchemaParser schemaparser = null; //To use the pool just add a Runnable to the pool [pool.execute(someRunnable)] private ThreadPool pool = new ThreadPool (3); /** Creates new form projectdataWindow */ public DB2XMLmain(configurator mainProgram, String uid) { this.mother = mainProgram; this.ID = uid; this.theData = mainProgram .getProjectData (); this.fileList = this.theData.getXML(); //update the DBList initComponents(); if (fileList.size()>0) { //setFile(((xmlItem)((Vector)this.theData.getXML()).get(0)).getFile()); fileComboBox.setSelectedItem(fileList .get(0)); } isLoading = false; doFileSelect(); } /** This method is called from within the constructor to * initialize the form. * WARNING: Do NOT modify this code. The content of this method is * always regenerated by the Form Editor. */ private void initComponents() {//GEN-BEGIN:initComponents toolPanel = new javax.swing.JPanel(); fileLabel = new javax.swing.JLabel(); fileComboBox = new javax.swing.JComboBox(fileList); buildButton = new javax.swing.JButton(); clearButton = new javax.swing.JButton(); jButton1 = new javax .swing .JButton(); theSplitPane = new javax.swing.JSplitPane (); rightPanel = new javax.swing.JPanel(); leftPanel = new javax.swing.JPanel(); mainPanel = new javax.swing.JPanel(); theTabbedPane = new javax.swing .JTabbedPane(); treePanel = new javax.swing.JPanel(); treeScrollPane = new javax .swing.JScrollPane(); textPanel = new javax.swing.JPanel(); sourceScrollPane = new javax.swing.JScrollPane (); sourceTextArea = new javax .swing.JTextArea(); setMaximizable(true); setTitle("Database to XML Module"); setIconifiable(true); setResizable(true); toolPanel.setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.LEFT)); toolPanel.setPreferredSize (new java.awt.Dimension(300, 37)); fileLabel.setText("File:"); toolPanel.add(fileLabel); fileComboBox.setPreferredSize(new java.awt.Dimension(240, 27)); fileComboBox.setMinimumSize(new java.awt.Dimension(126, 27)); fileComboBox.setMaximumSize(new java.awt.Dimension(32767 , 27)); fileComboBox.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed (java.awt.event .ActionEvent evt) { fileComboBoxActionPerformed(evt); } }); toolPanel.add(fileComboBox ); buildButton.setText("Build"); buildButton.setEnabled(false); buildButton.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event .ActionEvent evt) { buildButtonActionPerformed(evt); } }); toolPanel.add(buildButton); clearButton.setToolTipText ("Clears the whole mapping-information"); clearButton.setText("Clear"); clearButton.setEnabled(false); clearButton.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed (java.awt.event .ActionEvent evt) { clearButtonActionPerformed(evt); } }); toolPanel.add(clearButton); jButton1.setIcon(new javax .swing.ImageIcon(getClass ().getResource("/configurator/icons/Help16.gif"))); jButton1.setToolTipText("Open Help"); jButton1.setFont(new java.awt.Font("Dialog", 0, 10)); Autor: Thomas Schädler 189 Anhang A: Quelltext <xmlizer> configurator jButton1.addActionListener (new java.awt.event.ActionListener() { public void actionPerformed (java.awt.event .ActionEvent evt) { jButton1ActionPerformed (evt); } }); toolPanel.add(jButton1); getContentPane().add(toolPanel, java.awt.BorderLayout.NORTH); theSplitPane.setDividerLocation (300); theSplitPane.setPreferredSize(new java.awt.Dimension(500, 302)); theSplitPane.setOneTouchExpandable(true); rightPanel .setLayout (new java.awt.BorderLayout ()); theSplitPane.setRightComponent(rightPanel ); leftPanel.setLayout(new java.awt.BorderLayout()); mainPanel.setLayout(new java.awt.BorderLayout()); theTabbedPane.setPreferredSize(new java.awt.Dimension(200, 300)); treePanel.setLayout(new java.awt.BorderLayout()); treeScrollPane.setPreferredSize (new java.awt.Dimension(400, 250)); treePanel.add(treeScrollPane, java.awt.BorderLayout .CENTER); theTabbedPane.addTab ("DOM Tree" , treePanel); textPanel.setLayout(new java.awt.BorderLayout()); sourceTextArea.setTa bSize(4); sourceScrollPane.setViewportView(sourceTextArea); textPanel.add(sourceScrollPane, java.awt.BorderLayout.CENTER); theTabbedPane.addTab ("Text View", textPanel); mainPanel.add(theTabbedPane, java.awt.BorderLayout.CENTER); leftPanel.add(mainPanel, java.awt.BorderLayout .CENTER); theSplitPane.setLeftComponent(leftPanel); getContentPane().add(theSplitPane, java.awt.BorderLayout .CENTER); pack(); }//GEN-END:initComponents private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN -FIRST:event_jButton1ActionPerformed // Add your handling code here: helpWindow help = (helpWindow)mother .open("help"); help.loadPage("/configurator/help/module_db2xml_main.html"); }//GEN-LAST:event_jButton1ActionPerformed private void clearButtonActionPerformed(java.awt.event.ActionEvent evt )//GEN-FIRST:event_clearButtonActionPerformed {//GEN-HEADEREND:event_clearButtonActionPerformed // Add your handling code here: //ask for discard (ok) or cancel (cancel) int result = JOptionPane.showConfirmDialog( mother.getContentPane(), "This operation removes ALL mapping\ninformation and SQL queries. Are you sure?", "<xmlizer> clear mapping", JOptionPane.OK_CANCEL_OPTION, JOptionPane.WARNING_MESSAGE ); if (result == JOptionPane.OK_OPTION) //discard { mother .getProjectData().DB2XMLclearmapping (); doFileSelect(); mother .getLog().addInformation("All mapping information and SQL queries removed."); } else //set status and return { mother .getLog().addWarning("Clear aborted: Current mapping is is not altered."); return ; } }//GEN-LAST:event_clearButtonActionPerformed private void buildButtonActionPerformed(java.awt.event.ActionEvent evt )//GEN-FIRST:event_buildButtonActionPerformed {//GEN-HEADEREND:event_buildButtonActionPerformed // Add your handling code here: if (this.schemaparser != null) { //start a new project and a setup window Runnable r = new Runnable() { public void run() { schemaparser.buildInstance(); Document doc = schemaparser.getInstance (); if (doc != null) { //mother.debugOutput(doc); PipedOutputStream outstr = mother.getLog ().addNewTab("DB2XML Output","Preview output for current DB2XML Mapping"); XMLOutputter fmt = new XMLOutputter (" ",true); try { fmt.output(doc,outstr ); mother .getLog().isUpdating (false); } catch(IOException ioex) { mother .getLog().isUpdating (false); mother .getLog().addError(ioex); } } else { mother.getLog().addWarning("Instance Generation failed."); Autor: Thomas Schädler 190 Anhang A: Quelltext <xmlizer> configurator } } }; try { pool.execute(r); }catch(InterruptedException ie) { mother.getLog().addError(ie);} } }//GEN-LAST:event_buildButtonActionPerformed private void fileComboBoxActionPerformed (java.awt.event .ActionEvent evt)//GEN-FIRST:event_fileComboBoxActionPerformed {//GEN-HEADEREND:event_fileComboBoxActionPerformed // Add your handling code here: doFileSelect(); }//GEN-LAST:event_fileComboBoxActionPerformed private void selectedTextFieldKeyReleased(java.awt.event.KeyEvent evt)//GEN -FIRST:event_selectedTextFieldKeyReleased {//GEN-HEADEREND:event_selectedTextFieldKeyReleased // Add your handling code here: if(evt.getKeyCode() == 10) //press enter { doItemUpdate(); } }//GEN-LAST:event_selectedTextFieldKeyReleased /** * Is called if a new file is selected */ private void doFileSelect() { if (!isLoading) { final xmlItem item = (xmlItem)fileComboBox .getSelectedItem(); if (item != null) { //start a new project and a setup window Runnable r = new Runnable() { public void run() { dataItem it = mother .getProjectData ().getInitialByKey("name" ); String pro_name = it.getValue(); setFile(mother.getProjectBase() + mother .getFileSeparator() + pro_name + mother.getFileSeparator () + item.getFile()); //updates the selected file } }; try { pool.execute(r); }catch(InterruptedException ie) { mother.getLog().addError(ie);} } } } /** * Do an Item-change Update */ public void doItemUpdate () { MutableTreeNode node = (MutableTreeNode)theTree.getLastSelectedPathComponent (); if (node == null) return; } /** * Set a file and diplay (call update automatically) * @param String indicat ing the full path to the file */ private void setFile(String fullfilenameandpath) { this.xmlFile = fullfilenameandpath; Runnable r = new Runnable() { public void run() { updateCurrentSelection(); } }; try { pool.execute(r); }catch(InterruptedException ie) { mother.getLog ().addError (ie);} } /** * Do the update on the tree */ private void updateCurrentSelection () { //update the tree if (theTree != null) { treeScrollPane.remove(theTree); theTree = null; } boolean wasSuccessfull = initTree(); if (wasSuccessfull) { treeScrollPane.setViewportView(theTree); toolPanel.repaint(); treeScrollPane.repaint (); fileComboBox.repaint(); //update the text initText(); } } public synchronized void update(configurator conf) { isLoading = true; this.mother = conf; this.theData = conf.getProjectData(); this.fileList = conf.getProjectData().getXML(); //update the dbList this.dbList = conf.getProjectData().getDB (); //update the fileList this.fileComboBox.setModel (new DefaultComboBoxModel (this.fileList)); if (this.fileList.size()>0) { this.fileComboBox.setSelectedIndex(0); } this.repaint(); isLoading = false; Autor: Thomas Schädler 191 Anhang A: Quelltext <xmlizer> configurator } private void expandTree() { int rows = 0; for (int levels =0; levels <= 4; levels++) { rows=theTree.getRowCount(); for (int i = 0; i < rows; i++) { theTree.expandRow(i); } } } private void initText() { //file stuff StringBuffer the_source = new StringBuffer(); File inputFile = new File(xmlFile); FileInputStream inputStream = null; InputStreamReader in = null; try { inputStream = new FileInputStream(xmlFile); in = new InputStreamReader(inputStream,"UTF8"); if (in != null) { int c; while ((c = in.read()) != -1) { the_source.append((char)c); } in.close(); sourceTextArea.setText(the_source .toString()); } } catch(Exception ex) { mother .getLog().addError(ex.getMessage()); } } private boolean initTree () { Document thedoc = mother.getFileAsXMLDOM(xmlFile,false); if (thedoc != null) { this.schemaparser = new XMLSchemaParser(mother); boolean parsing_is_ok = schemaparser.parse (thedoc); if (parsing_is_ok) { //get the tree (visual) theTree = schemaparser.getTree(); theTree.addTreeSelectionListener(new javax.swing .event.TreeSelectionListener() { public void valueChanged (javax.swing.event.TreeSelectionEvent evt) { //respond to tree-node selection and show the according interface (for db-entries) optionsTreeValueChanged(evt); } }); theTree.putClientProperty("JTree.lineStyle" , "Angled" ); expandTree(); buildButton.setEnabled(true); clearButton.setEnabled(true); return true; } else { clearButton.setEnabled(true); buildButton.setEnabled(false); return false; } } else { clearButton.setEnabled(true); buildButton.setEnabled(false); return false; } } // Variables declaration - do not modify//GEN -BEGIN:variables private javax.swing .JPanel toolPanel; private javax.swing .JLabel fileLabel; private javax.swing .JComboBox fileComboBox; private javax.swing .JButton buildButton; private javax.swing .JButton clearButton; private javax.swing .JButton jButton1; private javax.swing .JSplitPane theSplitPane; private javax.swing .JPanel rightPanel; private javax.swing .JPanel leftPanel; private javax.swing .JPanel mainPanel; private javax.swing .JTabbedPane theTabbedPane ; private javax.swing .JPanel treePanel; private javax.swing .JScrollPane treeScrollPane; private javax.swing .JPanel textPanel; private javax.swing .JScrollPane sourceScrollPane; private javax.swing .JTextArea sourceTextArea; // End of variables declaration//GEN-END:variables /** * Customizes a selection of a tree node */ private void optionsTreeValueChanged(javax.swing.event.TreeSelectionEvent evt) { DefaultMutableTreeNode node = (DefaultMutableTreeNode)theTree.getLastSelectedPathComponent(); if (node == null) return; //GET THE SchemaElement SchemaElement schemel = (SchemaElement)node.getUserObject(); if (schemel != null) { JPanel thisPanel = schemel.getElementPanel (); if (thisPanel != null) { rightPanel.removeAll(); this.repaint(); rightPanel.add(thisPanel,java.awt.BorderLayout.CENTER ); this.validate(); } } } }/* * pathData.java * * This projectData contain er contains all neccessary methods to deal * with the projectData management Autor: Thomas Schädler 192 Anhang A: Quelltext <xmlizer> configurator * * Created on 5. April 2002, 16:30 * ---------------------------------------------------------------------------* This file is part of <xmlizer>. * * <xmlizer> is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Foobar is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with <xmlizer>; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * ---------------------------------------------------------------------------*/ package configurator; import import import import import import import java.io.*; java.util.*; java.lang.*; javax.swing .*; org.jdom.*; org.jdom.input.SAXBuilder; org.jdom.output.XMLOutputter; /** * Represents the pathdata (absolutley neccessary for running xmlizer) * [email protected] * @version 0.5 */ public class pathData { public static String XMLFILEROOT = "xmlizerconfig" ; private String homedir = null; private String projectdir = null; //CONSTRUCTOR //----------------------------------------------------------------------------------------------/** * Creates new projectData (Constructor) */ public pathData() { //init here if neccessary } //GET AND SET //----------------------------------------------------------------------------------------------public String getHomeDir () { return homedir; } public void setHomeDir(String dir) { this.homedir = dir; } public String getPr ojectDir() { return projectdir; } public void setProjectDir(String dir) { this.projectdir = dir; } //STRING REPRESENTATION //----------------------------------------------------------------------------------------------public String toString() { StringBuffer result = new StringBuffer("FULL PATHDATA >>"); result.append("\nHOME-DIR >> " + this.homedir); result.append("\nPROJECT-DIR >> " + this.projectdir ); return result.toString(); } //XML REPRESENTATION //----------------------------------------------------------------------------------------------public boolean isValid() { if ((this.homedir != null) && (this.projectdir != null)) { return true; } else return false; } /** * Checks the doctype of the XML-File (just to be sure to read the right information) */ private boolean checkDocType(DocType dt,String rootelement) { if (dt.getElementName().equalsIgnoreCase(rootelement)) { return true; } else { return false; } } /* * Reads an XML file (which must be of type xmlizer.project.config.dtd) and * fills all information in the projectdata * * @param The filename as String * @param The logWindow (to indicate errors etc...) */ synchronized public boolean readFromFile (String filename) { Autor: Thomas Schädler 193 Anhang A: Quelltext <xmlizer> configurator boolean docOK = false; try { SAXBuilder builder = new SAXBuilder(false); Document jdoc = builder.build(filename); //true -> validating against dtd DocType docType = jdoc.getDocType(); docOK = checkDocType(docType,XMLFILEROOT); if (docOK) { //get the root Element root = jdoc.getRootElement(); java.util.List itemlist = root.getChildren("path"); Iterator item_iter = itemlist.iterator (); while (item_iter.hasNext()) { Element path_item = (Element) item_iter .next(); if (path_item.getAttributeValue("description").equalsIgnoreCase("home")) { this.homedir = path_item.getTextTrim(); //System.out.println("HOME: " + path_item.getTextTrim()); } else if (path_item.getAttributeValue("description").equalsIgnoreCase("project")) { this.projectdir = path_item.getTextTrim(); //System.out.println("PROJECT: " + path_item.getTextTrim()); } } return true; } else { //System.out.println("DOC NOT OK"); return false ; } } catch (JDOMException e) { //System.out.println("JDOM Exception: " + e.getMessage()); return false; } } /** * Return the data as String */ public String getAsXMLText() { Document jdoc = this.getAsXMLDocumentJDOM (); org.jdom.output .DOMOutputter outp = new org.jdom.output.DOMOutputter(); XMLOutputter fmt = new XMLOutputter(" return fmt.outputString(jdoc); ",true); } /** * Return the data as XML Document (org.w3c.dom.Document) */ public org.w3c.dom.Document getAsXMLDocumentW3C() { Document jdoc = this.getAsXMLDocumentJDOM (); org.jdom.output .DOMOutputter outp = new org.jdom.output.DOMOutputter(); try { org.w3c.dom.Document result = outp.output(jdoc); return result; //and return the result } catch (JDOMException e) { System .out.println("DOM Serializer error for debug output!"); return null; } } /** * Return the data as XML Document org.jdom.Document */ public Document getAsXMLDocumentJDOM() { //MAKE DOCTYPE DocType docType = new DocType(XMLFILEROOT ,null); Element root = new Element (XMLFILEROOT); Element init_item1 = new Element("path").setText(this.homedir); init_item1 .setAttribute("description","home"); root.addContent (init_item1 ); Element init_item2 = new Element("path").setText(this.projectdir); init_item2 .setAttribute("description","project"); root.addContent (init_item2 ); Document doc = new Document(root,docType); return doc; //and return the doc } /** * save the config in the user home directory as xmlizer.config */ public void save(String path,boolean ui) { org.jdom.Document xmldata = getAsXMLDocumentJDOM(); org.jdom.output.XMLOutputter fmt = new org.jdom.output.XMLOutputter(" ",true); try { //file stuff java.io.File outputFile = new java.io.File(path); java.io.FileOutputStream outputStream = new java.io.FileOutputStream(outputFile); java.io.OutputStreamWriter out = new java.io.OutputStreamWriter(outputStream,"UTF8"); fmt.output(xmldata,out); out.close(); } catch (java.io.IOException ex) { if (ui) { javax.swing.JOptionPane .showMessageDialog( null, Autor: Thomas Schädler 194 Anhang A: Quelltext <xmlizer> configurator "I/O Error, could not save the\ndata correctly!" + "\n ERROR: \n------\n" + ex.toString(), configurator .APPNAME + " save error", javax.swing.JOptionPane .ERROR_MESSAGE ); } else { System.out.println ("SAVE ERROR: " + ex.toString()); } } } } /* * dtd2xsdOptions.java * * Created on 7. Juni 2002, 01:31 * ---------------------------------------------------------------------------* This file is part of <xmlizer>. * * <xmlizer> is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Foobar is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with <xmlizer>; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * ---------------------------------------------------------------------------*/ package configurator; import java.awt.*; import java.util.*; import javax.swing .*; /** * An options dialog for the dtd2xs - package * @author [email protected] */ public class dtd2xsdOptions extends javax.swing.JDialog { private Hashtable options = new Hashtable(); /** Creates new form dtd2xsdOptions */ public dtd2xsdOptions(java.awt.Frame parent, boolean modal) { super(parent, modal); initComponents(); Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); Dimension mySize = getSize (); if(mySize.height > screenSize.height ) { mySize .height = screenSize.height; } if(mySize.width > screenSize.width) { mySize .width = screenSize.width; } setLocation((screenSize.width - mySize.width) / 2, (screenSize.height - mySize.height) / 2); show(); } /** This method is called from within the constructor to * initialize the form. * WARNING: Do NOT modify this code. The content of this method is * always regenerated by the Form Editor. */ private void initComponents()//GEN-BEGIN:initComponents { thePanel = new javax .swing .JPanel(); mapDTDentitiesLabel = new javax .swing.JLabel(); mapDTDentitiesCheckBox = new javax.swing.JCheckBox(); mapDTDcommentsLabel = new javax .swing.JLabel(); mapDTDcommentsCheckBox = new javax.swing.JCheckBox(); maxCommLenghtLabel = new javax.swing .JLabel(); commLangLabel = new javax.swing .JLabel(); commLangComboBox = new javax.swing.JComboBox(); annotationLabel = new javax.swing.JLabel(); annotationList = new javax .swing.JList(); conceptHighllightLabel = new javax.swing.JLabel(); conceptHighlightComboBox = new javax .swing.JComboBox(); minOccLabel = new javax.swing.JLabel (); minOccComboBox = new javax .swing.JComboBox(); maxCommLengthComboBox = new javax.swing.JComboBox(); buttonPanel = new javax.swing.JPanel (); okButton = new javax .swing .JButton(); cancelButton = new javax.swing.JButton(); setTitle("DTD 2 XSD Options"); setDefaultCloseOperation(javax.swing .WindowConstants.DISPOSE_ON_CLOSE); setModal(true); addWindowListener(new java.awt.event .WindowAdapter() { public void windowClosing(java.awt.event.WindowEvent evt) { closeDialog(evt); } }); thePanel.setLayout(new java.awt.GridBagLayout()); java.awt.GridBagConstraints gridBagConstraints 1; Autor: Thomas Schädler 195 Anhang A: Quelltext <xmlizer> configurator thePanel.setBorder(new javax.swing.border .TitledBorder("DTD to XML Schema Transform options:")); mapDTDentitiesLabel.setText("Map DTD entities" ); gridBagConstraints1 = new java.awt.GridBagConstraints(); gridBagConstraints1.gridx = 0; gridBagConstraints1.gridy = 0; gridBagConstraints1.fill = java.awt.GridBagConstraints.HORIZONTAL; gridBagConstraints1.insets = new java.awt.Insets(0, 5, 0, 2); thePanel.add(mapDTDentitiesLabel, gridBagConstraints1); gridBagConstraints1 = new java.awt.GridBagConstraints(); gridBagConstraints1.gridx = 1; gridBagConstraints1.gridy = 0; gridBagConstraints1.fill = java.awt.GridBagConstraints.HORIZONTAL; gridBagConstraints1.insets = new java.awt.Insets(0, 2, 0, 5); gridBagConstraints1.anchor = java.awt.GridBagConstraints .WEST; thePanel.add(mapDTDentitiesCheckBox, gridBagConstraints1 ); mapDTDcommentsLabel.setText("Map DTD comments" ); gridBagConstraints1 = new java.awt.GridBagConstraints(); gridBagConstraints1.gridx = 0; gridBagConstraints1.gridy = 1; gridBagConstraints1.fill = java.awt.GridBagConstraints.HORIZONTAL; gridBagConstraints1.insets = new java.awt.Insets(0, 5, 0, 2); thePanel.add(mapDTDcommentsLabel, gridBagConstraints1); gridBagConstraints1 = new java.awt.GridBagConstraints(); gridBagConstraints1.gridx = 1; gridBagConstraints1.gridy = 1; gridBagConstraints1.fill = java.awt.GridBagConstraints.HORIZONTAL; gridBagConstraints1.insets = new java.awt.Insets(0, 2, 0, 5); gridBagConstraints1.anchor = java.awt.GridBagConstraints .WEST; thePanel.add(mapDTDcommentsCheckBox, gridBagConstraints1 ); maxCommLenghtLabel.setText ("Max. length comment"); gridBagConstraints1 = new java.awt.GridBagConstraints(); gridBagConstraints1.gridx = 0; gridBagConstraints1.gridy = 2; gridBagConstrai nts1.fill = java.awt.GridBagConstraints.HORIZONTAL; gridBagConstraints1.insets = new java.awt.Insets(0, 5, 0, 2); thePanel.add(maxCommLenghtLabel , gridBagConstraints1); commLangLabel.setText("Comment language"); gridBagConstraints1 = new java.awt.GridBagConstraints(); gridBagConstraints1.gridx = 0; gridBagConstraints1.gridy = 3; gridBagConstraints1.fill = java.awt.GridBagConstraints.HORIZONTAL; gridBagConstraints1.insets = new java.awt.Insets(0, 5, 0, 2); thePanel.add(commLangLabel , gridBagConstraints1); commLangComboBox.setModel(new javax.swing .DefaultComboBoxModel(new String[] { "undefined", "English", "German", "French" })); gridBagConstraints1 = new java.awt.GridBagConstraints(); gridBagConstraints1.gridx = 1; gridBagConstraints1.gridy = 3; gridBagConstraints1.fill = java.awt.GridBagConstraints.HORIZONTAL; gridBagConstraints1.insets = new java.awt.Insets(0, 2, 0, 5); gridBagConstraints1.anchor = java.awt.GridBagConstraints .WEST; thePanel.add(commLangComboBox, gridBagConstraints1); annotationLabel .setText("Annotation of"); gridBagConstraints1 = new java.awt.GridBagConstrain ts(); gridBagConstraints1.gridx = 0; gridBagConstraints1.gridy = 6; gridBagConstraints1.fill = java.awt.GridBagConstraints.HORIZONTAL; gridBagConstraints1.insets = new java.awt.Insets(0, 5, 0, 2); thePanel.add(annotationLabel, gridBagConstraints1); annotationList.setToolTipText("Select all that apply"); annotationList.setModel(new javax.swing.AbstractListModel() { String [] strings = { "element" , "attribute", "group", "attributeGroup", "simpleType", "enumeration" }; public int getSize() { return strings.length; } public Object getElementAt(int i) { return strings[i]; } }); annotationList.setVisibleRowCount(3); gridBagConstraints1 = new java.awt.GridBagConstraints(); gridBagConstraints1.gridx = 1; gridBagConstraints1.gridy = 6; gridBagConstraints1.fill = java.awt.GridBagConstraints.HORIZONTAL; gridBagConstraints1.insets = new java.awt.Insets(0, 2, 0, 5); gridBagConstraints1.anchor = java.awt.GridBagConstraints .WEST; thePanel.add(annotationList, gridBagConstraints1); conceptHighllightLabel.setText("Concept highlight"); gridBagConstraints1 = new java.awt.GridBagConstraints(); gridBagConstraints1.gridx = 0; gridBagConstraints1.gridy = 7; gridBagConstraints1.fill = java.awt.GridBagConstraints.HORIZONTAL; gridBagConstraints1.insets = new java.awt.Insets(0, 5, 0, 2); thePanel.add(conceptHighllightLabel, gridBagConstraints1 ); conceptHighlightComboBox.setModel(new javax.swing.DefaultComboBoxModel(new String [] { "no", "by space", "embraced" })); gridBagConstraints1 = new java.awt.GridBagConstraints(); gridBagConstraints1.gridx = 1; gridBagConstraints1.gridy = 7; gridBagConstraints1.fill = java.awt.GridBagConstraints.HORIZONTAL; gridBagConstraints1.insets = new java.awt.Insets(0, 2, 0, 5); gridBagConstraints1.anchor = java.awt.GridBagConstraints .WEST; thePanel.add(conceptHighlightComboBox, gridBagConstraints1); minOccLabel.setText("Min. concept occurence"); Autor: Thomas Schädler 196 Anhang A: Quelltext <xmlizer> configurator gridBagConstraints1 = new java.awt.GridBagConstraints(); gridBagConstraints1.gridx = 0; gridBagConstraints1.gridy = 8; gridBagConstraints1.insets = new java.awt.Insets(0, 5, 0, 2); thePanel.add(minOccLabel, gridBagConstraints1); minOccComboBox.setModel(new javax.swing.DefaultComboBoxModel(new String [] { "1", "2", "3", "4", "5" })); gridBagConstraints1 = new java.awt.GridBagConstraints(); gridBagConstraints1.gridx = 1; gridBagConstraints1.gridy = 8; gridBagConstraints1.fill = java.awt.GridBagConstraints.HORIZONTAL; gridBagConstraints1.insets = new java.awt.Insets(0, 2, 0, 5); gridBagConstraints1.anchor = java.awt.GridBagConstraints .WEST; thePanel.add(minOccComboBox, gridBagConstraints1); maxCommLengthComboBox.setModel(new javax.swing .DefaultComboBoxModel(new String[] { "1", "10", "25", "50", "100", "500", "1000", "10000", "50000" })); maxCommLengthComboBox.setSelectedItem("1000"); gridBagConstrai nts1 = new java.awt.GridBagConstraints(); gridBagConstraints1.gridx = 1; gridBagConstraints1.gridy = 2; gridBagConstraints1.fill = java.awt.GridBagConstraints.HORIZONTAL; gridBagConstraints1.insets = new java.awt.Insets(0, 2, 0, 5); gridBagConstraints1.anchor = java.awt.GridBagConstraints .WEST; thePanel.add(maxCommLengthComboBox, gridBagConstraints1); getContentPane().add(thePanel, java.awt.BorderLayout.CENTER); okButton.setText("OK"); okButton.setPreferredSize(new java.awt.Dimension(73, 27)); okButton.setMaximumSize(new java.awt.Dimension (73, 27)); okButton.setMinimumSize(new java.awt.Dimension (73, 27)); okButton.addActionListener (new java.awt.event.ActionListener() { public void actionPerformed (java.awt.event .ActionEvent evt) { okButtonActionPerformed (evt); } }); buttonPanel.add(okButton); cancelButton.setText("Cancel"); cancelButton.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed (java.awt.event .ActionEvent evt) { cancelButtonActionPerformed(evt); } }); buttonPanel.add(cancelButton); getContentPane().add(buttonPanel, java.awt.BorderLayout.SOUTH ); pack(); }//GEN-END:initComponents private void cancelButtonActionPerformed (java.awt.event .ActionEvent evt)//GEN-FIRST:event_cancelButtonActionPerformed {//GEN-HEADEREND:event_cancelButtonActionPerformed // Add your handling code here: doExit(); }//GEN-LAST:event_cancelButtonActionPerformed private void okButtonActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_okButtonActionPerformed {//GEN-HEADEREND:event_okButtonActionPerformed // Add your handling code here: doExit(); }//GEN-LAST:event_okButtonActionPerformed /** Closes the dialog */ private void closeDialog (java.awt.event.WindowEvent evt ) {//GEN-FIRST:event_closeDialog doExit(); }//GEN-LAST:event_closeDialog // Variables declaration - do not modify//GEN -BEGIN:variables private javax.swing .JPanel thePanel ; private javax.swing .JLabel mapDTDentitiesLabel; private javax.swing .JCheckBox mapDTDentitiesCheckBox; private javax.swing .JLabel mapDTDcommentsLabel; private javax.swing .JCheckBox mapDTDcommentsCheckBox; private javax.swing .JLabel maxCommLenghtLabel ; private javax.swing .JLabel commLangLabel ; private javax.swing .JComboBox commLangComboBox; private javax.swing .JLabel annotationLabel; private javax.swing .JList annotationList ; private javax.swing .JLabel conceptHighllightLabel; private javax.swing .JComboBox conceptHighlightComboBox; private javax.swing .JLabel minOccLabel; private javax.swing .JComboBox minOccComboBox; private javax.swing .JComboBox maxCommLengthComboBox; private javax.swing .JPanel buttonPanel; private javax.swing .JButton okButton; private javax.swing .JButton cancelButton ; // End of variables declaration//GEN-END:variables public void doExit() { options = new Hashtable(); //mapDTDentitiesCheckBox if (mapDTDentitiesCheckBox .isSelected()) { options.put("entities" ,new Boolean(true)); } Autor: Thomas Schädler 197 Anhang A: Quelltext <xmlizer> configurator else { options.put("entities" ,new Boolean(false)); } //mapDTDcommentsCheckBox if (mapDTDcommentsCheckBox .isSelected()) { options.put("comments" ,new Boolean(true)); } else { options.put("comments" ,new Boolean(false)); } //maxCommLengthComboBox options.put("commentLength",(String)maxCommLengthComboBox.getSelectedItem()); //commLangComboBox options.put("commentLanguage",(String)commLangComboBox.getSelectedItem()); StringBuffer allRelations = new StringBuffer(); Object sel [] = annotationList.getSelectedValues(); if (sel.length > 0) { boolean first = true; for(int i=0;i<sel.length;i++) { if (!first) { allRelations.append (" "); } allRelations .append(sel[i]); first = false; } } options.put("conceptRelations",allRelations.toString()); //conceptHighlightComboBox String this_val_str = new String("2"); String this_val = (String)conceptHighlightComboBox.getSelectedItem (); if (this_val.equalsIgnoreCase("no")) { this_val_str = "2"; } else if (this_val.equalsIgnoreCase("by space")) { this_val_str = "12"; } else if (this_val.equalsIgnoreCase("embraced")) { this_val_str = "200"; } options.put("conceptHighlight",this_val_str); //minOccComboBox options.put("minOccur",(String)minOccComboBox.getSelectedItem ()); setVisible (false); dispose(); } public Hashtable getOptions() { return this.options; } } /* * dtd2xsdReport.java * * Created on 7. Juni 2002, 11:19 * ---------- -----------------------------------------------------------------* This file is part of <xmlizer>. * * <xmlizer> is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Foobar is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with <xmlizer>; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * ---------------------------------------------------------------------------*/ package configurator; import java.awt.*; import java.util.*; import javax.swing .*; /** * Shows the output of a conversion dtd2xs * @author [email protected] */ public class dtd2xsdReport extends javax.swing.JDialog { /** Creates new form dtd2xsdReport */ public dtd2xsdReport(java.awt.Frame parent, boolean modal, String report, String schema) { super(parent, modal); initComponents(); Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); Dimension mySize = getSize (); if(mySize.height > screenSize.height ) { mySize .height = screenSize.height; } if(mySize.width > screenSize.width) { mySize .width = screenSize.width; } setLocation((screenSize.width - mySize.width) / 2, (screenSize.height - mySize.height) / 2); Autor: Thomas Schädler 198 Anhang A: Quelltext <xmlizer> configurator reportTextField.setText(report); if (schema == null) { theTabbedPane.remove(outputPanel ); this.repaint(); } else { outputTextField.setText(schema); this.repaint(); } pack(); show(); } /** This method is called from within the constructor to * initialize the form. * WARNING: Do NOT modify this code. The content of this method is * always regenerated by the Form Editor. */ private void initComponents()//GEN-BEGIN:initComponents { buttonPanel = new javax.swing.JPanel (); okButton = new javax .swing .JButton(); cancelButton = new javax.swing.JButton(); mainPanel = new javax.swing.JPanel(); theTabbedPane = new javax.swing .JTabbedPane(); reportPanel = new javax.swing.JPanel (); reportScrollPane = new javax.swing.JScrollPane (); reportTextField = new javax.swing.JTextField(); outputPanel = new javax.swing.JPanel (); outputScrollPane = new javax.swing.JScrollPane (); outputTextField = new javax.swing.JTextField(); addWindowListener(new java.awt.event .WindowAdapter() { public void windowClosing(java.awt.event.WindowEvent evt) { closeDialog(evt); } }); okButton.setText("OK"); okButton.setPreferredSize(new java.awt.Dimension(73, 27)); okButton.setMaximumSize(new java.awt.Dimension (73, 27)); okButton.setMinimumSize(new java.awt.Dimension (73, 27)); okButton.addActionListener (new java.awt.event.ActionListener() { public void actionPerformed (java.awt.event .ActionEvent evt) { okButtonActionPerformed (evt); } }); buttonPanel.add(okButton); cancelButton.setText("Cancel"); cancelButton.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event .ActionEvent evt) { cancelButtonActionPerformed(evt); } }); buttonPanel.add(cancelButton); getContentPane().add(buttonPanel, java.awt.BorderLayout.SOUTH ); mainPanel.setLayout(new java.awt.BorderLayout()); theTabbedPane.setTabPlacement(javax.swing .JTabbedPane.BOTTOM); theTabbedPane.setPreferredSize(new java.awt.Dimension(300, 350)); reportPanel.setLayout(new java.awt.BorderLayout()); reportScrollPane.setAutoscrolls (true); reportTextField .setToolTipText("Conversion Report"); reportScrollPane.setViewportView(reportTextField); reportPanel.add(reportScrollPane, java.awt.BorderLayout.CENTER); theTabbedPane.addTab ("Report", reportPanel); outputPanel.setLayout(new java.awt.BorderLayout()); outputScrollPane.setAutoscrolls (true); outputTextField .setToolTipText("Conversion Report"); outputScrollPane.setViewportView(outputTextField); outputPanel.add(outputScrollPane, java.awt.BorderLayout.CENTER); theTabbedPane.addTab ("Generated XML Schema", outputPanel ); mainPanel.add(theTabbedPane, java.awt.BorderLayout.CENTER); getContentPane().add(mainPanel, java.awt.BorderLayout.CENTER); pack(); }//GEN-END:initComponents private void cancelButtonActionPerformed (java.awt.event .ActionEvent evt)//GEN-FIRST:event_cancelButtonActionPerformed {//GEN-HEADEREND:event_cancelButtonActionPerformed // Add your handling code here: doExit(); }//GEN-LAST:event_cancelButtonActionPerformed Autor: Thomas Schädler 199 Anhang A: Quelltext <xmlizer> configurator private void okButtonActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_okButtonActionPerformed {//GEN-HEADEREND:event_okButtonActionPerformed // Add your handling code here: doExit(); }//GEN-LAST:event_okButtonActionPerformed /** Closes the dialog */ private void closeDialog (java.awt.event.WindowEvent evt ) {//GEN-FIRST:event_closeDialog doExit(); }//GEN-LAST:event_closeDialog // Variables declaration - do not modify//GEN -BEGIN:variables private javax.swing.JPanel buttonPanel; private javax.swing .JButton okButton; private javax.swing .JButton cancelButton ; private javax.swing .JPanel mainPanel; private javax.swing .JTabbedPane theTabbedPane ; private javax.swing .JPanel reportPanel; private javax.swing .JScrollPane reportScrollPane; private javax.swing .JTextField reportTextField; private javax.swing .JPanel outputPanel; private javax.swing .JScrollPane outputScrollPane; private javax.swing .JTextField outputTextField; // End of variables declaration//GEN-END:variables private void doExit () { setVisible (false); dispose(); } } /* * SchemaAttribute.java * * This class representates a Schema Attribute * * Created on 18. Mai 2002, 20:52 * ---------------------------------------------------------------------------* This file is part of <xmlizer>. * * <xmlizer> is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Foobar is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with <xmlizer>; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * ---------------------------------------------------------------------------*/ package configurator; import org.jdom.*; import java.util.*; import javax.swing .*; /** * Represents a SchemaAttribute and all related info * @author [email protected] */ public class SchemaAttribute { private String tname = null; //name= private String ttype = null; //type= private String ttyperef = null; //ref= private String tuse = new String("optional"); //use= private String mapid = null; private String mapinfo = null; private Element tattribute; private String tannotation = null; //CONSTRUCTORS //--------------------------------------------------------------- -------------------------------public SchemaAttribute(Element attribute ) { this.tattribute = attribute; process(); } public if if if } SchemaAttribute(String name,String mapid,String mapinfo) { (name != null) { this.tname = name; } (mapid != null) { this.mapid = mapid; } (mapinfo != null) { this.mapinfo = mapinfo; } //Initialization of the data //----------------------------------------------------------------------------------------------private void process() { if (this.tattribute != null) { Attribute attr = null; //name attr = this.tattribute .getAttribute("name" ); if (attr != null) { this.tname = attr.getValue().trim(); } //type attr = this.tattribute .getAttribute("type" ); if (attr != null) { this.ttype = attr.getValue().trim(); } //ref Autor: Thomas Schädler 200 Anhang A: Quelltext <xmlizer> configurator attr = this.tattribute .getAttribute("ref"); if (attr != null) { this.ttyperef = attr.getValue().trim(); } //use attr = this.tattribute .getAttribute("use"); if (attr != null) { this.tuse = attr.getValue().trim(); } } } /** Cleans the mapinfo of this attribute */ public void cleanMapping () { this.mapid = null; this.mapinfo = null; //System.out.println(this.tname); } //SETTERS public void setMapID(String id ) { if (id != null) { this.mapid = id; } } public void setMapInfo(String info) { if (info != null) { this.mapinfo = info; } } //GETTERS public String getMapID() { return this.mapid; } public String getMapInfo () { return this.mapinfo; } public Element getAttribute() { return this.tattribute; } public String getType() { return this.ttype; } public String getTypeTef () { return this.ttyperef ; } public String getUse() { return this.tuse; } public String getName() { return this.tname; } //STRING REPRESENTATION //----------------------------------------------------------------------------------------------/** * By default show the key as String */ public String toString() { StringBuffer result = new StringBuffer(); //display the name if (this.ttype == null && this.ttyperef != null) //has a typeref { result .append(this.tname + " - " + this.ttyperef + " [" + this.tuse + "]"); } else if (this.ttype != null && this.ttyperef == null) //has a type { result .append(this.tname + " - " + this.ttype + " [" + this.tuse + "]"); } else //has nothing of both (should not happen -> invalid) { result .append(this.tname + " - !noType! [" + this.tuse + "]"); } //display the mapid if there is one if (this.mapid != null) { result .append(" > " + this.mapid); } if (this.mapinfo != null) { result .append(" : " + this.mapinfo); } return result.toString(); } public Element getAsJDOMElement() { if (this.tname == null) //check for validity { return null; } else { Element curr = new Element("db2xml_attribute"); curr.setAttribute("name",this.tname); if (this.mapid != null) { curr.setAttribute("mapid",this.mapid); Autor: Thomas Schädler 201 Anhang A: Quelltext <xmlizer> configurator } if (this.mapinfo != null) { curr.setAttribute("mapinfo",this.mapinfo); } return curr; } } }/* * SchemaSimpleConstraint.java * * Created on 4. April 2002, 15:48 * ---------------------------------------------------------------------------* This file is part of <xmlizer>. * * <xmlizer> is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Founda tion; either version 2 of the License, or * (at your option) any later version. * * Foobar is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with <xmlizer>; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * ---------------------------------------------------------------------------*/ package configurator; import java.util.List; import java.util.LinkedList; /** * <p> * The <code>SchemaSimpleConstraint</code> class represents a single data constraint, * including the data type, allowed values, and required ranges. * </p> * @author [email protected] */ public class SchemaSimpleConstraint { /** The identifier for this constraint */ private String identifier; /** The Java data type for this constraint */ private String dataType; /** Minimum inclusive value allowed */ private double minInclusive; /** Minimum exclusive value allowed */ private double minExclusive; /** Maximum inclusive value allowed */ private double maxInclusive; /** Maximum exclusive value allowed */ private double maxExclusive; /** Allowed values */ private List allowedValues; /** * <p> * This will create a new <code>SPConstraint</code> with the specified * identifier as the "name". * </p> * * @param identifier <code>String</code> identifier for <code>SPConstraint</code>. */ public SchemaSimpleConstraint(String identifier) { this.identifier = identifier; // Null out values minInclusive = Double.NaN; minExclusive = Double.NaN; maxInclusive = Double.NaN; maxExclusive = Double.NaN; // Allocate storage for allowed values allowedValues = new LinkedList(); } /** * <p> * This will return the identifier for this <code>SPConstraint</code>. * </p> * * @return <code>String</code> - identifier for this constraint. */ public String getIdentifier() { return identifier; } /** * <p> * This will allow the data type for the constraint to be set. The type is specified * as a Java <code>String</code>. * </p> * * @param dataType <code>String</code> that is the Java data type for this constraint. */ public void setDataType(String dataType) { Autor: Thomas Schädler 202 Anhang A: Quelltext <xmlizer> configurator this.dataType = dataType; } /** * <p> * This will return the <code>String</code> version of the Java data type for this * constraint. * </p> * * @return <code>String</code> - the data type for this constraint. */ public String getDataType() { return dataType ; } /** * <p> * This will set the minimum allowed value for this data type (inclusive). * </p> * * @param minInclusive minimum allowed value (inclusive) */ public void setMinInclusive(double minInclusive) { this.minInclusive = minInclusive; } /** * <p> * This will return the minimum allowed value for this data type (inclusive). * </p> * * @return <code>double</code> - minimum value allowed (inclusive) */ public double getMinInclusive() { return minInclusive; } /** * <p> * This will return <code>true</code> if a minimum value (inclusive) constraint * exists. * </p> * * @return <code>boolean</code> - whether there is a constraint for the * minimum value (inclusive) */ public boolean hasMinInclusive () { return (!(new Double (minInclusive)).isNaN ()); } /** * <p> * This will set the minimum allowed value for this data type (exclusive). * </p> * * @param minInclusive minimum allowed value (exclusive) */ public void setMinExclusive(double minExclusive) { this.minExclusive = minExclusive; } /** * <p> * This will return the minimum allowed value for this data type (exclusive). * </p> * * @return <code>double</code> - minimum value allowed (exclusive) */ public double getMinExclusive() { return minExclusive; } /** * <p> * This will return <code>true</code> if a minimum value (exclusive) constraint * exists. * </p> * * @return <code>boolean</code> - whether there is a constraint for the * minimum value (exclusive) */ public boolean hasMinExclusive () { return (!(new Double (minExclusive)).isNaN ()); } /** * <p> * This will set the maximum allowed value for this data type (inclusive). * </p> * * @param maxInclusive maximum allowed value (inclusive) */ public void setMaxInclusive(double maxInclusive) { this.maxInclusive = maxInclusive; } /** * <p> * This will return the maximum allowed value for this data type (inclusive). * </p> * * @return <code>double</code> - maximum value allowed (inclusive) */ public double getMaxInclusive() { return maxInclusive; Autor: Thomas Schädler 203 Anhang A: Quelltext <xmlizer> configurator } /** * <p> * This will return <code>true</code> if a maximum value (inclusive) constraint * exists. * </p> * * @return <code>boolean</code> - whether there is a constraint for the * maximum value (inclusive) */ public boolean hasMaxInclusive () { return (!(new Double (maxInclusive)).isNaN ()); } /** * <p> * This will set the maximum allowed value for this data type (exclusive). * </p> * * @param maxInclusive maximum allowed value (exclusive) */ public void setMaxExclusive(double maxExclusive) { this.maxExclusive = maxExclusive; } /** * <p> * This will return the maximum allowed value for this data type (exclusive). * </p> * * @return <code>double</code> - maximum value allowed (exclusive) */ public double getMaxExclusive() { return maxExclusive; } /** * <p> * This will return <code>true</code> if a maximum value (exclusive) constraint * exists. * </p> * * @return <code>boolean</code> - whether there is a constraint for the * maximum value (exclusive) */ public boolean hasMaxExclusive () { return (!(new Double (maxExclusive)).isNaN ()); } /** * <p> * This will add another value to the list of allowed values for this data type. * </p> * * @param value <code>String</code> value to add. */ public void addAllowedValue(String value ) { allowedValues.add(value); } /** * <p> * This will return the list of allowed values for this data type. * </p> * * @return <code>List</code> - allowed values for this <code>SPConstraint</code>. */ public List getAllowedValues() { return allowedValues ; } /** * <p> * This will indicate if there are a set of allowed values for this data type. * </p> * * @return <code>boolean</code> - whether there are allowed values for this type. */ public boolean hasAllowedValues() { return (allowedValues.size() > 0); } }/* * SchemaOccurrence.java * * Created on 4. April 2002, 15:48 * ---------------------------------------------------------------------------* This file is part of <xmlizer>. * * <xmlizer> is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Foobar is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Publ ic License * along with <xmlizer>; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * ---------------------------------------------------------------------------*/ Autor: Thomas Schädler 204 Anhang A: Quelltext <xmlizer> configurator package configurator; import java.lang.Integer; /** * Holds all neccessary info for XML Schema occurrences (repetition) * @author [email protected] */ public class SchemaOccurrence { /** The identifier for this constraint */ private String identifier; /** Minimum inclusive value allowed */ private Integer minOccurs; /** Maximum exclusive value allowed */ private Integer maxOccurs; private boolean maxUnbounded = false; /** * <p> * This will create a new <code>SPConstraint</code> with the specified * identifier as the "name". * </p> * * @param identifier <code>String</code> identifier for <code>SPConstraint</code>. */ public SchemaOccurrence(String identifier) { this.identifier = identifier; //init values to default this.minOccurs = new Integer(1); this.maxOccurs = new Integer(1); } /** * <p> * This will return the identifier for this <code>SPConstraint</code>. * </p> * * @return <code>String</code> - identifier for this constraint. */ public String getIdentifier() { return identifier; } /** * <p> * This will set the minimum allowed value for this data type (inclusive). * </p> * * @param minInclusive minimum allowed value (inclusive) */ public void setMinOccurs (String min ) { if (min != null) { Integer min_int = Integer.valueOf(min); this.minOccurs = min_i nt; } } /** * <p> * This will return the minimum allowed value for this data type (inclusive). * </p> * * @return <code>double</code> - minimum value allowed (inclusive) */ public Integer getMinOccurs() { return this.minOccurs; } /** * <p> * This will set the maximum allowed value for this data type (inclusive). * In case of unbounded the value shall be Integer.MAX_VALUE * </p> * * @param minInclusive minimum allowed value (inclusive) */ public void setMaxOccurs (String max ) { if (max != null) { if (max.equalsIgnoreCase("unbounded")) { this.maxUnbounded = true; this.maxOccurs = new Integer(Integer.MAX_VALUE); } else { Integer max_int = Integer.getInteger(max); this.maxOccurs = max_int; } } } /** * Return true if this element can be repeated more than once */ public boolean hasRepeat () { if ((getMinOccurs().intValue() == 1) && (getMaxOccurs().intValue() == 1)) { return false; } else if (getMaxOccurs().intValue() > 1) { return true; } else { return false; } Autor: Thomas Schädler 205 Anhang A: Quelltext <xmlizer> configurator } /** * <p> * This will return the minimum allowed value for this data type (inclusive). * </p> * * @return <code>double</code> - minimum value allowed (inclusive) */ public Integer getMaxOccurs() { return maxOccurs; } /** * Returns a short occurrence description as String */ public String getShortOcc() { if ((getMinOccurs().intValue() == 1) && (getMaxOccurs().intValue() == 1)) { return " [1]"; } else { StringBuffer buff = new StringBuffer(" ["); buff.append (getMinOccurs()); buff.append (".."); if (this.maxUnbounded == true) { //buff.append("\u221E"); //means "infinite symbol" in unicode buff.append("max"); //unicode is font dependant! no good idea } else { buff.append(getMaxOccurs()); } buff.append ("]"); return buff.toString(); } } }/* * DB2XMLmapping.java * * This class contains all neccessary information on the mapping of the module * DB2XML (for building it and getting it for save) * * Created on 15. Juni 2002, 13:38 * ---------------------------------------------------------------------------* This file is part of <xmlizer>. * * <xmlizer> is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public Licen se as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Foobar is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with <xmlizer>; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * ---------------------------------------------------------------------------*/ package configurator; import java.util.*; import org.jdom.*; /** * * @author [email protected] */ public class DB2XMLmapping { private String rootElement = null; private Vector otherElements = new Vector(); //of SchemaElements private Hashtable loadedElementNames = new Hashtable(); //of key=id,value=name(ambigous) private Hashtable loadedAttributes = new Hashtable (); //of SchemaAttributes private Hashtable loadedSQL = new Hashtable(); //of SQLStatements private Hashtable loadedReps = new Hashtable(); //of Strings key=elementid,value=sqlid private Hashtable loadedContent = new Hashtable(); //of SchemaContent private Hashtable loadedParameters = new Hashtable (); //of ParameterInfo /** Creates new DB2XMLmapping */ public DB2XMLmapping(){} public DB2XMLmapping(String rootElementName) { this.rootElement = rootElementName; } /* * Set the root element */ public void setRootElement(String rootElementName) { this.rootElement = rootElementName; } /** * Adds a repetition info for the specified element to the list * a Hashtable with key=elementname,value=sqlid/mapid */ public void addElementRepFromLoad(String elementid ,String sqlid) { this.loadedReps .put(elementid,sqlid); } public Hashtable getLoadedReps () { return this.loadedReps; Autor: Thomas Schädler 206 Anhang A: Quelltext <xmlizer> configurator } /** * Adds an element name to the list of known elements */ public void addElementFromLoad (String name,String id) { if (id!= null && name != null) { this.loadedElementNames.put(id,name); } } /** * Adds an Element to the list and returns true if new (not loaded from xmlizer.xml) else false */ public boolean addElement(SchemaElement el) { if (el != null) { if (this.loadedElementNames .containsKey(el.getID())) { this.otherElements .add(el); return false ; } else { this.otherElements .add(el); return true; } } else return false; } public Vector getElements() { return this.otherElements; } /* * Set the root element */ public String getRootElement() { return rootElement; } /** * adds a SQLStatement to the list */ public void addSQLFromLoad(String id, SQLStatement statement ) { if (this.loadedSQL.containsKey(id)) //add to Vector { Vector temp_vec = (Vector)this.loadedSQL.get(id); temp_vec.add(statement ); //System.out.println("addSQLFromLoad NEW: " + statement.toString()); } else //add new Vector with current SQLStatement as first one { Vector temp_vec = new Vector(); temp_vec.add(statement ); this.loadedSQL.put(id,temp_vec); //System.out.println("addSQLFromLoad ADD: " + statement.toString()); } } /** * Return a Hashtable full of happy SQLStatements * key: elementname (to attach to) + attributename (combined key) * value: SQLStatement */ public Hashtable getLoadedSQL() { return this.loadedSQL; } /** * Returns the appropriate SQLStatement for a mapid */ public SQLStatement getSQLStat ementByMapID(String mapid ) { for (Enumeration e = this.loadedSQL.elements(); e.hasMoreElements();) { Vector element = (Vector)e.nextElement(); for (Enumeration ee = element.elements(); ee.hasMoreElements();) { SQLStatement item = (SQLStatement )ee.nextElement (); if (item.getID().equalsIgnoreCase (mapid)) { return item; } } } return null; } /** * adds a SchemaAttribute to the list */ public void addAttributeFromLoad(String id, SchemaAttribute attr) { this.loadedAttributes.put(id + attr.getName(),attr); } /** * returns the parameters (hashtabel key=id,value=ParameterInfo */ public Hashtable getParameters () { return this.loadedParameters; } /** * Returns the appropriate SQLStatement for a mapid */ public ParameterInfo getParameterByMapID (String mapid) { for (Enumeration e = this.loadedParameters.elements (); e.hasMoreElements();) { Autor: Thomas Schädler 207 Anhang A: Quelltext <xmlizer> configurator ParameterInfo item = (ParameterInfo)e.nextElement(); if (item.getID().equalsIgnoreCase(mapid)) { return item; } } return null; } /** * adds a ParameterInfo to the list * returns true if add was successfull * else false (= no insert) */ public boolean addParameterFromLoad (String id , String name, String value) { if (!this.loadedParameters .containsKey(name)) { //System.out.println("NOT FOUND - ADDING"); this.loadedParameters.put(name,new ParameterInfo(id,name,value )); return true; } else { /*System.out.println("FOUND - DO NOTHING");*/ return false; } } /** * Removes the specified (name) parameter */ public boolean removeParameter (String name_to_remove) { if (this.loadedParameters.containsKey(name_to_remove)) { this.loadedParameters.remove(name_to_remove); return true; } else return false; } /** * adds a SchemaContent to the list */ public void addContentFromLoad (String id , SchemaContent cont ) { this.loade dContent.put(id,cont); } /** * Return a Hashtable full of happy SchemaAttributes * key: elementname (which it belongs to) + attributename * value: SchemaAttribute */ public Hashtable getLoadedAttributes() { return this.loadedAttributes; } /** * Return a Hashtable full of happy SchemaContent * key: elementname (which it belongs to) * value: SchemaContent */ public Hashtable getLoadedContent() { return this.loadedContent; } public Element getMapping() { if (this.rootElement == null) //check for validity { return null; } else { //DB2XML Mapping buildup Element wrapper = new Element("mapping"); Element db2xml_wrapper = new Element("db2xml"); //root element db2xml_wrapper.setAttribute ("rootelement",this.rootElement); wrapper.addContent(db2xml_wrapper); //add the parameters for (Enumeration e = this.loadedParameters .elements(); e.hasMoreElements ();) { ParameterInfo item = (ParameterInfo)e.nextElement(); Element curr = new Element("db2xml_parameter"); curr.setAttribute("id",item.getID ()); curr.setAttribute("name",item.getName()); curr.setAttribute("default",item.getValue()); db2xml_wrapper.addContent(curr); } //add the elements for (Enumeration e = this.otherElements.elements(); e.hasMoreElements();) { SchemaElement item = (SchemaElement)e.nextElement(); Element curr = new Element("db2xml_element" ); curr.setAttribute("name",item.getRealName()); curr.setAttribute("id",item.getID ()); //build content if (item.hasContent()) { SchemaContent cont = item.getContent(); curr.addContent(cont.getAsJDOMElement()); } //build repetition info (attribute repsql) if (item.getRepetition() != null) { curr.setAttribute("repsql",item.getRepetition()); } //build attributes for (Enumeration enum = item.getAttributes().elements (); enum.hasMoreElements();) { SchemaAttribute attr = (SchemaAttribute )enum.nextElement(); curr.addContent(attr.getAsJDOMElement()); Autor: Thomas Schädler 208 Anhang A: Quelltext <xmlizer> configurator } //build sql for (Enumeration enum = item.getSQLStatements().elements(); enum.hasMoreElements();) { SQLStatement stat = (SQLStatement)enum.nextElement(); curr.addContent(stat.getAsJDOMElement()); } //add the element db2xml_wrapper.addContent(curr); } return wrapper; } } }/* * XMLSchemaParser.java * * This class parsers a XML Schema and generates all neccessary info for * using this XML Schema (instance generator, tree-view and element info) * * Created on 17. Juni 2002, 09:02 * ---------------------------------------------------------------------------* This file is part of <xmlizer>. * * <xmlizer> is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Foobar is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOS E. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with <xmlizer>; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * ---------------------------------------------------------------------------*/ package configurator; import import import import java.util.*; javax.swing .*; javax.swing .tree.*; org.jdom.*; /** * Parses a XML Schema and builds an in ternal representation (tree) and * can generate instances * @author [email protected] */ public class XMLSchemaParser { private configurator mother; private Document doc; private JTree tree = null; //Hashtable for saving info-lists private Hashtable xml_elements = new Hashtable(); private Hashtable xml_types = new Hashtable(); //little global helpers private String rootelement = null; private DefaultMutableTreeNode topNode = null; private Hashtable loadedSQL = null; private Hashtable loadedReps = null; private Hashtable loadedContent = null; /** Creates new XMLSchemaParser */ public XMLSchemaParser(configurator conf ) { this.mother = conf; } /** * Returns a JTree representing this XML Schema as browsable tree */ public JTree getTree() { return tree; } /** * Returns an instance document (test-output) */ public Document getInstance() { return this.instance ; //and return the doc } //INSTANCE GENERATION //----------------------------------------------------------------------------------------------private Document instance; private Element DocumentRoot; private boolean rootSet; private Hashtable madeSQLs; //key = sqlid, value = SQLStatement private Hashtable madeSQLsCurrentRow; //key = sqlid, value = currentRow //private Vector all_current_ids; //holds all currently known ids public void buildInstance() { instance = null; DocumentRoot = null; rootSet = false ; madeSQLs = new Hashtable(); //key = sqlid, value = SQLStatement //all_current_ids = new Vector(); madeSQLsCurrentRow = new Hashtable(); //key = sqlid, value = currentRow for (Enumeration e = this.topNode.children(); e.hasMoreElements();) { DefaultMutableTreeNode dmtr = (DefaultMutableTreeNode)e.nextElement (); try { makeInstance (DocumentRoot,null,dmtr); } catch(Exception ex) { Autor: Thomas Schädler 209 Anhang A: Quelltext <xmlizer> configurator //mother.getLog().addError(ex); return; } } if (DocumentRoot != null) { instance = new Document(DocumentRoot); } } // parent=JDOM Element, lastParentElement=parental_SchemaElement, current=current_DefaultMutableTreeNode private void makeInstance(Element parent ,SchemaElement lastParentElement,DefaultMutableTreeNode current) throws Exception { if (current == null) { return; } //failsafe //get the schemaelement of the current node -> curse SchemaElement curse = (SchemaElement )current.getUserObject(); //check for the root -element (as defined in the mapping - do something only if found) if (!rootSet && curse.getRealName().equalsIgnoreCase(mother.getProjectData().DB2XMLgetmapping().getRootElement())) { //insert the document root as indicated, can have no repetition (root!) DocumentRoot = new Element(curse .getRealName()); prepareSQLStatements(curse.getSQLStatements()); processCurrentElement(DocumentRoot,null,curse); rootSet = true; } //if the current schemaelement is valid and the root -> start buil ding if (curse.isRefresh() && rootSet && curse .getID() != null) { prepareSQLStatements(curse.getSQLStatements()); //process this element (builds it) if (curse.getRepetition() != null) //if this element has a repetition sql statement { //get the maximum allowed repetition value (maxOccurs for this Element) int max = ((Integer)curse.getOccurrence().getMaxOccurs()).intValue(); //get the data assocciated with the element's repetition String mapid_for_rep = curse .getRepetition(); mother.getLog().addDebug("MAPID: " + mapid_for_rep); Hashtable sql_result = (Hashtable )madeSQLs.get(mapid_for_rep); //mother.getLog().addDebug("SQLRESULT: " + sql_result + " ROWS = " + ((Integer)sql_result.get("rows")).intValue()); //check for the maximum, if more then just cut it there so it will be valid int sqlmax = ((Integer)sql_result .get("rows")).intValue(); if (sqlmax < max) { max = sqlmax; } //adjust the max for maxOccurs //finally do it for each DB-row for (int i=0;i<max;i++) { Element this_element = new Element(curse.getRealName()); processCurrentElement(this_element ,parent,curse); if (parent == null) //root set, but no parent -> this is the root element! { parent = DocumentRoot; //do the same for all children for (Enumeration e = current.children(); e.hasMoreElements();) { makeInstance(parent,curse,(DefaultMutableTreeNode)e.nextElement()); } } else // this is a normal element (sub-node (or more sub-sub-...) of the rootelement) { parent.addContent(this_element ); //do the same for all children for (Enumeration e = current.children(); e.hasMoreElements();) { makeInstance(this_element,curse ,(DefaultMutableTreeNode)e.nextElement()); } } //update the row_counter for other statements of this element int row_counter = ((Integer)madeSQLsCurrentRow.get(mapid_for_rep )).intValue() + 1; //System.out.println(curse.getRealName() + " >>" + row_counter); madeSQLsCurrentRow.put(mapid_for_rep,new Integer(row_counter)); } } else //no repetition statement a nd no minimum, so skip it (if it is not the root) { /* special treatment for the root node! */ if (curse.getRealName().equalsIgnoreCase(mother.getProjectData().DB2XMLgetmapping().getRootElement())) { Element this_element = new Element(curse.getRealName()); processCurrentElement(this_element ,parent,curse); if (parent == null) //root set, but no parent -> this ist the root element! { parent = DocumentRoot; //do the same for all children for (Enumeration e = current.children(); e.hasMoreElements();) { makeInstance(parent,curse,(DefaultMutableTreeNode)e.nextElement()); } } else // this is a normal element (sub-node (or more sub-sub-...) of the rootelement) { parent.addContent(this_element ); //do the same for all children for (Enumeration e = current.children(); e.hasMoreElements();) { makeInstance(this_element,curse ,(DefaultMutableTreeNode)e.nextElement()); } } } // has a minOccurence of more than 0 but no repetition -> make it at least an empty element else if (curse.getOccurrence ().getMinOccurs ().intValue() > 0) { Element this_element = new Element(curse.getRealName()); processCurrentElement(this_element ,parent,curse); parent.addContent(this_element); //do the same for all children for (Enumeration e = current.children(); e.hasMoreElements();) { makeInstance(this_element ,curse,(DefaultMutableTreeNode )e.nextElement()); Autor: Thomas Schädler 210 Anhang A: Quelltext <xmlizer> configurator } } } } else //just go on without doing something (no buildup for those elements) { //do the same for all children for (Enumeration e = current.children (); e.hasMoreElements();) { makeInstance (parent,curse,(DefaultMutableTreeNode)e.nextElement ()); } } } private void processCurrentElement(Element el ,Element parent ,SchemaElement sch) { //fill in the content if (sch.getContent() != null && sch.getContent ().getMapID() != null) //has content { SchemaContent cont = sch.getContent(); if (cont.getMapID() != null && cont.getMapInfo() != null) { //get the data and fill the attribute String mapid = cont.getMapID (); //the ID String mapinfo = cont.getMapInfo(); //the tableName int currentRow = ((Integer)madeSQLsCurrentRow.get(mapid)).intValue(); Hashtable data = (Hashtable)madeSQLs.get(mapid); //get the hash-data from the list if (data == null) { mother.getLog ().addError("No data for referenced sql with id="+mapid+" found!"); } Vector colnames = (Vector)data.get("columnname"); int col = 0; for (Enumeration en = colnames.elements(); en.hasMoreElements();) { String currname = (String)en.nextElement(); if (currname.equalsIgnoreCase (mapinfo)) { break; } col++; } String info[][] = (String[][])data.get("table"); String result = info[col][currentRow]; //mother.getLog().addDebug("GOT Content: " + result + " [" +col+"]["+currentRow+"]"); //System.out.println("COL: " + col + " <> " + "ROW:" + row); //System.out.println(madeSQLsCurrentRow.toString()); el.setText(result); } else if (cont.getMapID() != null && cont.getMapInfo() == null) { //here comes the result of a simple statement //which has only a mapid //get the data and fill the attribute String mapid = cont.getMapID (); //the ID int currentRow = ((Integer)madeSQLsCurrentRow.get(mapid)).intValue(); Hashtable data = (Hashtable)madeSQLs.get(mapid); //get the hash-data from the list if (data == null) { mother.getLog().addError("No data for referenced sql with id="+mapid+" found!"); } String info[][] = (String[][])data.get("table"); String result = info[0][0]; //mother.getLog().addDebug("GOT Content: " + result + " ["+0+"]["+0+"]"); //System.out.println("COL: " + col + " <> " + "ROW:" + row); //System.out.println(madeSQLsCurrentRow.toString()); el.setText(result); } else { /*/dev/null*/} } //fill the attributes with the apropriate values for (Enumeration e = sch.getAttributes().elements(); e.hasMoreElements();) { SchemaAttribute att = (SchemaAttribute)e.nextElement (); //System.out.println(att.getName() + " >>> " + att.getUse() + " >>>" + att.getMapID()); if (att.getUse().equalsIgnoreCase("prohibited")) { mother.getLog().addWarning("In element <" + sch.getRealName() + "> an attribute " + att.getName() + " is PROHIBITED but has a value! Skipping..."); } else if (att.getMapID() == null && att.getUse().equalsIgnoreCase("required")) //req. but not there -> tell the user { mother.getLog().addWarning("In element <" + sch.getRealName() + "> an attribute " + att.getName() + " is REQUIRED but has no value."); } else if (att.getMapID() != null && att.getMapInfo() != null) { //get the data and fill the attribute String mapid = att.getMapID(); //the ID String mapinfo = att.getMapInfo(); //the tableName mother.getLog().addDebug("Query: "+ mapid+":"+mapinfo); int currentRow = ((Integer)madeSQLsCurrentRow.get(mapid)).intValue(); Hashtable data = (Hashtable)madeSQLs.get(mapid); //get the hash-data from the list if (data == null) { mother.getLog ().addError("No data for id="+mapid +" found!" ); } Vector colnames = (Vector)data.get("columnname"); int col = 0; for (Enumeration en = colnames.elements(); en.hasMoreElements();) { String currname = (String)en.nextElement(); if (currname.equalsIgnoreCase (mapinfo)) { break; } col++; } String info[][] = (String[][])data.get("table"); String result = info[col][currentRow]; //mother.getLog().addDebug("GOT Attribute Value: " + result + " ["+col+"]["+currentRow+"]"); //System.out.println("COL: " + col + " <> " + "ROW:" + row); //System.out.println(madeSQLsCurrentRow.toString()); el.setAttribute(att.getName(),result); } else if (att.getMapID() != null && att.getMapInfo() == null) { //here comes the result of a simple statement Autor: Thomas Schädler 211 Anhang A: Quelltext <xmlizer> configurator //which has only a mapid //get the data and fill the attribute String mapid = att.getMapID(); //the ID mother.getLog().addDebug("Query: "+ mapid); int currentRow = ((Integer)madeSQLsCurrentRow.get(mapid)).intValue(); Hashtable data = (Hashtable)madeSQLs.get(mapid); //get the hash-data from the list if (data == null) { mother.getLog ().addError("No data for id="+mapid +" found!" ); } String info[][] = (String[][])data.get("table"); String result = info[0][0]; //mother.getLog().addDebug("GOT Attribute Value: " + result + " ["+0+"]["+0+"]"); //System.out.println("COL: " + col + " <> " + "ROW:" + row); //System.out.println(madeSQLsCurrentRow.toString()); el.setAttribute(att.getName(),result); } else { /*/dev/null*/} } } private Vector prepareSQLStatements (Vector vec) throws Exception { if (vec == null) { return new Vector (0); } //check for fail Vector res = new Vector(); for (Enumeration e = vec.elements(); e.hasMoreElements();) { SQLStatement current = (SQLStatement)e.nextElement(); String current_id = current.getID(); //System.out.println("MAKING : " + current_id); dbItem used_db_item = mother.getProjectData().getDBByName (current.getDB()); //System.out.println(" dbItem -> " + used_db_item); Hashtable sql_result = null; try { //System.out.println(" Query -> " + current.getSQL()); String resolvedQuery = resolveQuery(current.getSQL()); //System.out.println(" Resol -> " + resolvedQuery); sql_result = used_db_item.querySilent(resolvedQuery); this.madeSQLs.put(current_id ,sql_result); //add them to the list this.madeSQLsCurrentRow .put(current_id ,new Integer(0)); res.add(current_id ); //System.out.println(" SUCCESS !!"); } catch (Exception ex) { mother.getLog().addError(ex); } } //System.out.println(res.toString()); //System.out.println(madeSQLsCurrentRow.toString()); return res; } /** Returns xxx from xxx:yyy */ private String getFirst(String s,int cutter) { int doublepoint = s.indexOf(":"); if (double point != 0) { return s.substring(cutter,doublepoint ); } else return s; } /** Returns yyy from xxx:yyy */ private String getSecond (String s,int cutter) { int doublepoint = s.indexOf(":"); if (doublepoint != 0) { return s.substring(++doublepoint ,s.length()-cutter); } else return s; } private String getSubstitution (String query) { StringBuffer result = new StringBuffer(); int counter = 0; StringTokenizer st = new StringTokenizer(query ); while (st.hasMoreTokens()) { String token = st.nextToken (); //parameter substitution if (token.startsWith("[-") && token.endsWith("-]")) //parameter substitution { StringBuffer newToken = new StringBuffer(); String mapid = getFirst (token,2); String mapinfo = getSecond(token,2); ParameterInfo thisinfo = mother.getProjectData().DB2XMLgetmapping().getParameterByMapID(mapid); newToken.append(thisinfo.getValue ()); result.append(newToken.toString()); } //sql substitution else if (token.startsWith("[") && token.endsWith("]")) //sql substitution { StringBuffer newToken = new StringBuffer(); // [mapid:mapinfo] // evaluierungsschritte: // 1. SQLStatment holen für den angegebenen key String mapid = getFirst (token,1); String mapinfo = getSecond(token,1); //newToken.append("**" + mapid + "=" + mapinfo + "**"); // 2. dbItem holen für das angegebene SQLStatement (siehe XMLSchemaParser) SQLStatement stat = mother.getProjectData().DB2XMLgetmapping().getSQLStatementByMapID(mapid); //newToken.append(stat.toString()); dbItem used_db_item = mother .getProjectData ().getDBByName(stat.getDB ()); Hashtable sql_result; // 3. SQL auf dieser datenbank ausführen: try { String sub_query = getSubstitution (stat.getSQL()); sql_result = used_db_item.querySil ent(sub_query); Autor: Thomas Schädler 212 Anhang A: Quelltext <xmlizer> configurator // -- bei nur einem resultat -> dieses aus der übereinstimmenden namen (z.B. dbKey) ersetzen // -- bei mehreren resultaten -> einfach das erste nehemn (alternativ oben das limit gleich ändern) // 4. das ganze noch richtig ersetzen (Stringmässig) und dann ab damit zurück nach Hause Vector colnames = (Vector)sql_result.get("columnname"); int col = 0; for (Enumeration en = colnames.elements (); en.hasMoreElements();) { String currname = (String )en.nextElement (); if (currname.equalsIgnoreCase(mapinfo)) { break; } col++; } String info[][] = (String[][])sql_result.get("table"); int row = ((Integer)madeSQLsCurrentRow.get(mapid)).intValue (); //get the current row String resultString = info[col][row]; newToken .append(" "); newToken .append(resultString); result.append(newToken.toString()); counter++; } catch (Exception ex) { mother.getLog().addError (ex); } } else { result.append(" "); result.append(token); } } return result.toString(); } private String resolveQuery(String query ) { //do all data operations on the embedded queries and replace them internally! StringBuffer result = new StringBuffer(); //parse the query and substitute the SQLColumnInfo-Strings //with the real value from the following new statement: (example) result.append(getSubstitution(query)); //achtung! "[..] "könnte probleme machen - format suchen!! return result.toString(); } //PARSING //----------------------------------------------------------------------------------------------/** * Parse an XML Schema */ public boolean parse(Document doc) { this.doc = doc; //parse it and make everything ok, then try { doParse(); return true; } catch (Exception ex) { //mother.getLog().addError(ex); //System.out.println(ex.toString()); return false; } } private void doParse() throws Exception { //parse the xml schema Element xmlroot = doc.getRootElement (); //get the xml root Namespace namespace = xmlroot.getNamespace(); //get the namespac e topNode = insertDocumentNode(xmlroot); //insert the doc root in the tree // iterate over children of the root node List elems = xmlroot.getChildren(); //"element",namespace Iterator elems_iter = elems.iterator (); int item_count = elems.size(); Object[] rootElems = new Object [item_count]; int counter = 0; while (elems_iter.hasNext()) { Element xmlelem = (Element) elems_iter.next(); if (this.JDOMisElement (xmlelem)) { rootElems[counter] = this.JDOMgetElementName(xmlelem); this.xml_elements.put(this.JDOMgetElementName(xmlelem),xmlelem); counter++; } else if (this.JDOMisType(xmlelem)) //build type-lib for simpleTypes { this.xml_types.put(this.JDOMgetElementName(xmlelem),xmlelem); } } //load the Content to add them to the elements this.loadedContent = mother.getProjectData().DB2XMLgetmapping ().getLoadedContent(); //load the Repetitions to add them to the elements this.loadedReps = mother.getProjectData().DB2XMLgetmapping().getLoadedReps(); //load the SQLStatements from xmlizer.xml this.loadedSQL = mother.getProjectData().DB2XMLgetmapping().getLoadedSQL(); //check for saved root-element, else choose one rootelement = mother .getProjectData().DB2XMLgetmapping().getRootElement (); //check if the saved root element is available, else choose new if (rootelement != null) { if (!this.xml_elements .containsKey(rootelement)) { rootelement = null; } } Autor: Thomas Schädler 213 Anhang A: Quelltext <xmlizer> configurator //else choose a new root (auto or manual) if (rootelement == null) { if (counter > 1) //has at least two or more elements { //Ask for the root element to start with and build up the logical semi-resolved tree rootelement = (String)JOptionPane .showInputDialog ( null, "Ambigous root elements detected. \nSelect one of the following as your root element" , "Root selection", JOptionPane.INFORMATION_MESSAGE, null, rootElems, rootElems[0] ); } else if (counter == 1) { rootelement = (String)rootElems[0]; } else { JOptionPane.showMessageDialog( null, "The selected XML Schema has no root\n element(s) and is therfore not usable.\nCheck the schema and try again.", configurator .APPNAME + " schema error" , JOptionPane.ERROR_MESSAGE ); } //save it in config mother .getProjectData().DB2XMLgetmapping().setRootElement (rootelement); mother .getProjectData().setDirty (); //mark dirty } Element current = (Element )this.xml_elements.get(rootelement); recursiveTreeBuilder (topNode,current); //make the tree tree = new JTree(topNode); tree.setRootVisible(true); tree.getSelectionModel().setSelectionMode (TreeSelectionModel.SINGLE_TREE_SELECTION); tree.setShowsRootHandles(true); tree.setCellRenderer (new XMLTreeCellRenderer()); } //------------------------------------------------------ PARSE HELPERS /** * Walks the JDOM Path to the root and build a xpath-like (unique string) * which identifies a element for sure */ private String walkJDOMPath(Element element) { StringBuffer buff = new StringBuffer (); Element current = element; do { if (current.getAttribute("name") != null) { buff.insert(0,"/" + current.getAttribute("name").getValue()); } current = current.getParent (); } while (!current.isRootElement ()); return buff.toString(); } /** * Walks the tree-path of the jtree and adds all parent -nodes(=elements) * to the list of the element's parents */ private SchemaElement walkTreePath(Object[] path,SchemaElement elem) { //add all parent ele ments to this element and return it //System.out.println(elem.getName() + " --> " + path.length); for(int i=0;i<path.length;i++) { DefaultMutableTreeNode curr = (DefaultMutableTreeNode)path[i]; SchemaElement currse = (SchemaElement )curr.getUserObject(); if (currse.isRefresh() && currse .getID() != null) //is a real element (xml) { //System.out.println(currse.getID()); elem.addParent(currse); } } return elem; } private DefaultMutableTreeNode lastParent = null; private SchemaElement lastSchemaElement = null; private void recursiveTreeBuilder(DefaultMutableTreeNode parentNode,Element current) { //inspect this element and recurse for child-elements with current as new parentNode if (current == null) { return; } //failsafe DefaultMutableTreeNode treeNode = null; SchemaElement schemel = null; if (current.getName().equalsIgnoreCase("element")) { treeNode = new DefaultMutableTreeNode (current); String uniquePath = walkJDOMPath (current); schemel = new SchemaElement (this.mother,treeNode,current,uniquePath ); StringBuffer name = new StringBuffer(); Attribute attr = null; SchemaOccurrence occurrence = new SchemaOccurrence(current.getName().trim()); //name attr = current.getAttribute ("name"); if (attr != null) { Autor: Thomas Schädler 214 Anhang A: Quelltext <xmlizer> configurator //System.out.println(attr.getValue()); schemel.setRealName(attr.getValue ().trim()); name.append("<" + attr.getValue().trim() + ">"); //get the current elementname //add the Repetition if available if (this.loadedReps.containsKey(uniquePath)) { schemel.setRepetition((String )this.loadedReps.get(uniquePath)); } //add the SQLStatements according to the elementName in loadedSQL if (this.loadedSQL .containsKey(uniquePath)) { //System.out.println(uniquePath + " has a SQLStatement attached"); Vector this_sqls = (Vector)this.loadedSQL.get(uniquePath); for (Enumeration e = this_sqls.elements (); e.hasMoreElements();) { SQLStatement this_stat = (SQLStatement)e.nextElement(); //System.out.println("ADDING SQL WHILE PARSING: " + this_stat); schemel.addSQLStatement(this_stat); } } } //type attr = current.getAttribute ("type"); if (attr != null) { schemel.setType(attr.getValue().trim()); name.append(" - " + attr.getValue ().trim()); } //ref attr = current.getAttribute ("ref"); if (attr != null) { schemel.setTypeRef (attr.getValue().trim()); name.append(" => " +attr.getValue ().trim()); } //minOccurs attr = current.getAttribute ("minOccurs"); if (attr != null) { String min = attr.getValue().trim(); if (min != null) { occurrence.setMinOccurs(min); } //System.out.println("MIN: " + min); } //maxOccurs attr = current.getAttribute ("maxOccurs"); if (attr != null) { String max = attr.getValue().trim(); if (max != null) { occurrence.setMaxOccurs(max); } //System.out.println("MAX: " + max); } schemel.setOccurrence(occurrence ); schemel.setName(name.toString()); if (schemel.hasTypeRef ()) //typ dereferencing { String typeRef = schemel.getTypeRef(); //System.out.println("TypeRef: " + typeRef); typeRef = removeNamespacePrefix(typeRef); Element newcurrent = (Element)this.xml_elements.get(typeRef); if (newcurrent != null) { recursiveTreeBuilder(parentNode,newcurrent); } } else if (schemel.hasType()) //type buildup { //add the stuff treeNode.setUserObject(schemel); parentNode.add(treeNode ); lastParent = treeNode; //set last to current //System.out.println(schemel.getID() + " >> " + schemel.getName()); boolean isnew = mother.getProjectData().DB2XMLgetmapping().addElement(schemel); if (isnew) { mother.getProjectData().setDirty(); }//mark dirty //add the stuff //end should be reached because of having a simple type String typeR = schemel.getType(); //System.out.println("Type: " + typeR); typeR = removeNamespacePrefix(typeR); Element newcurrent = (Element)this.xml_types.get(typeR); if (newcurrent != null) { //System.out.println(schemel); schemel.processType (newcurrent); lookForAttributes(schemel,newcurrent); lookForContent (schemel,newcurrent); recursiveTreeBuilder(treeNode ,newcurrent); } else //must be an internal type (per default just take it for now) { //could also be an invalid type! if (this.loadedContent.containsKey (schemel.getID())) { schemel.setContent((SchemaContent)this.loadedContent.get(schemel.getID ())); } else { schemel.setContent(new SchemaContent(schemel.getID ())); } } //fill in parents schemel = walkTreePath(treeNode.getPath(),schemel); //make age change here lastSchemaElement = schemel; Autor: Thomas Schädler 215 Anhang A: Quelltext <xmlizer> configurator } else { //must have an internal type -> buildup //add the stuff treeNode.setUserObject(schemel); parentNode.add(treeNode ); lastParent = treeNode; //set last to current boolean isnew = mother.getProjectData().DB2XMLgetmapping().addElement(schemel); if (isnew) { mother.getProjectData().setDirty(); }//mark dirty //add the stuff schemel.setInternalType (); //mark that it has an internal type def. schemel.processInternalType(); //fill in parents schemel = walkTreePath(treeNode.getPath(),schemel); //make age change here lastSchemaElement = schemel; } } else if (current.getName().equalsIgnoreCase("any")) { treeNode = new DefaultMutableTreeNode (); schemel = new SchemaElement (this.mother,treeNode,"<any>"); treeNode.setUserObject (schemel); parentNode.add(treeNode); lastParent = treeNode; } else if (current.getName().equalsIgnoreCase("all")) { treeNode = new DefaultMutableTreeNode (); schemel = new SchemaElement (this.mother,treeNode,"-=all=-"); treeNode.setUserObject (schemel); parentNode.add(treeNode); lastParent = treeNode; } else if (current.getName().equalsIgnoreCase("group")) { treeNode = new DefaultMutableTreeNode (); schemel = new SchemaElement (this.mother,treeNode,"-=group=-"); treeNode.setUserObject (schemel); parentNode.add(treeNode); lastParent = treeNode; } else if (current.getName().equalsIgnoreCase("sequence")) { treeNode = new DefaultMutableTreeNode (); schemel = new SchemaElement (this.mother,treeNode,"-=sequence=-"); treeNode.setUserObject (schemel); parentNode.add(treeNode); lastParent = treeNode; } else if (current.getName().equalsIgnoreCase("choice")) { treeNode = new DefaultMutableTreeNode (); schemel = new SchemaElement (this.mother,treeNode,"-=choice=-"); treeNode.setUserObject (schemel); parentNode.add(treeNode); lastParent = treeNode; } else if (current.getName().equalsIgnoreCase("documentation")) { lastSchemaElement.addDocumentation(current.getText()); } else { treeNode = lastParent; } //look for complexType // iterate over children of the this element node List elems = current.getChildren(); //"elements",namespace Iterator elems_iter = elems.iterator (); while (elems_iter.hasNext()) { Element xmlelem = (Element) elems_iter.next(); recursiveTreeBuilder(treeNode,xmlelem); } } /** * Recursive search for simpleContent in type -Elements (simple and complex) */ private void lookForContent(SchemaElement attachHere,Element typeElement) { if (typeElement == null) { return; } //failsafe if (typeElement .getName().equalsIgnoreCase("simpleContent")) { if (this.loadedContent .containsKey(attachHere.getID())) { attachHere.setContent((SchemaContent)this.loadedContent.get(attachHere.getID())); return; } else { attachHere.setContent(new SchemaContent(attachHere.getID())); return; } } // iterate over children of the this element node List elems = typeElement.getChildren (); //"elements",namespace Iterator elems_iter = elems.iterator (); while (elems_iter.hasNext()) { Element xmlelem = (Element) elems_iter.next(); lookForContent(attachHere,xmlelem); } } /** * Recursive search for attributes in type-Elements (si mple and complex) */ private void lookForAttributes (SchemaElement attachHere ,Element typeElement ) { if (typeElement == null) { return; } //failsafe if (typeElement .getName().equalsIgnoreCase("attribute")) { attachHere.addAttribute(typeElement,mother .getProjectData ().DB2XMLgetmapping().getLoadedAttributes ()); Autor: Thomas Schädler 216 Anhang A: Quelltext <xmlizer> configurator } // iterate over children of the this element node List elems = typeElement.getChildren (); //"elements",namespace Iterator elems_iter = elems.iterator (); while (elems_iter.hasNext()) { Element xmlelem = (Element) elems_iter.next(); lookForAttributes(attachHere,xmlelem); } } /** * Returns the name of this JDOMElement (attribute name of <element name="asdf"...> * else returns "anonymous" */ private String JDOMgetElementName(Element el) { Attribute attr = el.getAttribute("name"); if (attr != null) { return attr.getValue().trim(); } else //just to be sure, should not happen though... { return "anonymous"; } } /** * Returns true if this JDOMElement is an <element ...> -tag */ private boolean JDOMisType(Element el) { if (el.getName().equalsIgnoreCase("simpleType" ) || el.getName().equalsIgnoreCase("complexType")) return true; return false; } /** * Tests if the JDOMElement is of indicated type or not */ private boolean JDOMisOfType(String type ,Element el) { if (el.getName().equalsIgnoreCase(type)) return true; else return false; } /** * Returns true if this JDOMElement is an <element ...> -tag */ private boolean JDOMisElement(Element el ) { if (el.getName().equalsIgnoreCase("element")) return true; return false; } private DefaultMutableTreeNode insertDocumentNode(Element what) { DefaultMutableTreeNode treeNode = new DefaultMutableTreeNode(); SchemaElement schemel = new SchemaElement (this.mother,treeNode,"<schema>",what); treeNode.setUserObject(schemel); return treeNode ; } //------------------------------------------------------ TREE HELPERS private class XMLTreeCellRenderer extends DefaultTreeCellRenderer { ImageIcon mainImg; ImageIcon leafImg; ImageIcon openImg; ImageIcon closeImg; public XMLTreeCellRenderer (){} public java.awt.Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) { mainImg = new javax.swing.ImageIcon(getClass().getResource("/configurator/icons/openide/xmlObject.gif")); leafImg = new javax.swing.ImageIcon(getClass().getResource("/configurator/icons/list/blue.gif")); closeImg = new javax.swing.ImageIcon(getClass().getResource("/configurator/icons/openide/defaultFolder.gif")); openImg = new javax.swing.ImageIcon(getClass().getResource("/configurator/icons/openide/defaultFolderOpen.gif")); java.awt.Component comp = super.getTreeCellRendererComponent(tree,value,selected,expanded,leaf,row,hasFocus); if(row==0) { setIcon(mainImg); } else if (leaf) { setIcon(leafImg); } else if (expanded) { setIcon(openImg); } else { setIcon(closeImg); } return comp; } } private static String removeNamespacePrefix(String s) { int doublepoint = s.indexOf(":"); if (doublepoint != 0) { return s.substring(++doublepoint ); } else return s; } } /* Autor: Thomas Schädler 217 Anhang A: Quelltext <xmlizer> configurator * SQLStatement.java * * This class contains all neccessary info for SQL Statements * * Created on 24. Juli 2002, 14:35 * ---------------------------------------------------------------------------* This file is part of <xmlizer>. * * <xmlizer> is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Foobar is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with <xmlizer>; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * ---------------------------------------------------------------------------*/ package configurator; import java.util.*; import org.jdom.*; /** * A SQL Statement with all related methods * @author thomas.schae [email protected] * @version 0.3 */ public class SQLStatement { private private private private private private String db = null; String sql = null; String id = null; int rowNumber = 0; Vector colnames = new Vector(); Vector colt ypes = new Vector(); /** Creates new SQLStatement */ /** * Creats a new Statement with the given id */ public SQLStatement (String db,String sql ,String id ) { this.db = db; this.sql = sql; this.id = id; } /** * Creates a new Statement with a generated (unique) id */ public SQLStatement (String db,String sql ,Vector cols,Vector types ,int rows) { UniqueID ID = new UniqueID (); this.id = ID.get(); this.db = db; this.sql = sql; this.colnames = cols; this.coltypes = types; this.rowNumber = rows; //System.out.println("ROWNUMBER: " + rows); } /** * Creates a new Statement with the given id and given vectors */ public SQLStatement (String db,String sql ,String id ,Vector cols,Vector types ) { this.id = id; this.db = db; this.sql = sql; this.colnames = cols; this.coltypes = types; } /* * Set the db */ public void setDB(String name) { this.db = name; } /* * Set the sql statement */ public void setSQL(String sql) { this.sql = sql; } /* * Set the sql statement */ public void setCols(Vector hash) { this.colnames = hash; } /* * Set the sql statement */ public void setColTypes(Vector hash ) { this.coltypes = hash; } Autor: Thomas Schädler 218 Anhang A: Quelltext <xmlizer> configurator /* * Get the db */ public String getDB () { return this.db; } /* * Get the sql statement */ public String getSQL() { return this.sql; } public void setRowNumber (int r) { //System.out.println("SETROWNUMBER: " + this.rowNumber); this.rowNumber = r; } public int getRowNumber() { //System.out.println("GETROWNUMBER: " + this.rowNumber); return this.rowNumber; } public Vector getCols() { return this.colnames ; } /** * Returns the columns as Vector of SQLColumnInfo (ad hoc type) */ public Vector getColsAsSQLColumnInfo() { Vector itemcols = new Vector(); int counter = 0; for (Enumeration e = this.colnames.elements(); e.hasMoreElements();) { String this_col_name = (String)e.nextElement(); String this_col_type = (String)this.coltypes.get(counter); itemcols.add(new SQLColumnInfo(this.id,this_col_name ,this_col_type)); counter++; } return itemcols ; } /** * Returns the columns as Vector of ColumnItems (ad hoc type) */ public Vector getColsAsColumnInfo() { Vector itemcols = new Vector(); int counter = 0; for (Enumeration e = this.colnames.elements(); e.hasMoreElements();) { String this_col_name = (String)e.nextElement(); String this_col_type = (String)this.coltypes.get(counter); itemcols.add(new ColumnInfo (this.id,this_col_name,this_col_type)); counter++; } return itemcols ; } public Vector getColTypes() { return this.coltypes ; } /** * Add a name to the colname-vector */ public void addColName(String name) { if (name != null) { this.colnames.add(name); } } /** * Add a name to the coltype-vector */ public void addColType(String type) { if (type != null) { this.coltypes.add(type); } } /** * Returns the mapid */ public String getID () { return this.id; } public String toString() { return this.db + " -> " + this.sql + " [" + this.colnames.size() + "]"; } public Element getAsJDOMElement() { if (this.db == null || this.id == null || this.sql == null || this.colnames == null || this.coltypes == null) //check for validity { return null; } else { Element curr = new Element("db2xml_sql"); curr.setAttribute("id",this.id); curr.setAttribute("db",this.db); curr.setAttribute("sql",this.sql); if (this.colnames.size() > 0 && this.colnames.size() == this.coltypes.size()) { Autor: Thomas Schädler 219 Anhang A: Quelltext <xmlizer> configurator int counter = 0; for (Enumeration e = this.colnames.elements (); e.hasMoreElements();) { Element sub = new Element("db2xml_sql_info"); String item = (String)e.nextElement(); sub.setAttribute("name",item); sub.setAttribute("type",(String)this.coltypes.get(counter)); counter++; curr.addContent(sub); } } return curr; } } }/* * SQLChooser.java * * Created on 24. Juli 2002, 18:53 * ---------------------------------------------------------------------------* This file is part of <xmlizer>. * * <xmlizer> is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Foobar is distributed in the hope that it will be useful, * but WITHOUT AN Y WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with <xmlizer>; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * ---------------------------------------------------------------------------*/ package configurator; import import import import import import java.awt.*; java.util.*; javax.swing .*; java.awt.dnd.*; java.awt.event.*; java.awt.datatransfer .*; /** * Is the SQLChooser, used to drop queries and columninfos to the module DB2XML * @author [email protected] */ public class SQLCh ooser extends MyInternalFrame { private configurator mother; private String ID; private boolean isLoading = true; private String title = new String(); private SQLStatement lastSQL = null; private SchemaElement currentElement = null; private Vector allSchemaElements = new Vector (); //To use the pool just add a Runnable to the pool [pool.execute(someRunnable)] private ThreadPool pool = new ThreadPool (2); /** Creates new form SQLChooser */ public SQLChooser(configurator mainProgram,String uid) { this.mother = mainProgram; this.ID = uid; initComponents(); theSplitPane.setDividerLocation (180); //make the list functional sqlList.getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION); tableList.getSelectionModel().setSelectionMode (ListSelectionModel.SINGLE_SELECTION); //add the mouselistener ItemListener ilst = new ItemListener (this); sqlList.addMouseListener(ilst); this.setTitleElementName(""); } public void setLastSQL(SQLStatement stat ) { this.lastSQL = stat; } /** * Listens for listItem-(Mouse)-Events on the dbtableList * -> For database queries */ class ItemListener implements java.awt.event.MouseListener { protected SQLChooser m_parent; protected JList m_list; public ItemListener(SQLChooser parent) { m_parent = parent; m_list = parent.sqlList; } public void mouseClicked(java.awt.event.MouseEvent e) { if(SwingUtilities.isRightMouseButton(e)) { m_parent.getPopup().show(m_list,e.getX(),e.getY()); } else { doAction(); } } Autor: Thomas Schädler 220 Anhang A: Quelltext <xmlizer> configurator public public public public void void void void mousePressed(java.awt.event.MouseEvent e){} mouseReleased(java.awt.event.MouseEvent e){} mouseEntered(java.awt.event.MouseE vent e){} mouseExited(java.awt.event.MouseEvent e ){} protected void doAction() { int index = m_list.getSelectedIndex(); if (index < 0) { return; } if (m_list.getModel().getSize() > index) { SQLStatement data = (SQLStatement )m_list.getModel().getElementAt(index); if (data != null) { m_parent .setLastSQL (data); m_parent .updateTables(data.getColsAsColumnInfo()); } } } } private void setTitleElementName(String name) { StringBuffer buff = new StringBuffer ("SQL Chooser"); if (name != null) { buff.append (" @ " + name); this.setTitle(buff.toString ()); } this.repaint(); } public JPopupMenu getPopup() { return this.sqlPopupMenu; } /** This method is called from within the constructor to * initialize the form. * WARNING: Do NOT modify this code. The content of this method is * always regenerated by the Form Editor. */ private void initComponents() {//GEN-BEGIN:initComponents sqlPopupMenu = new javax.swing.JPopupMenu (); testMenuItem = new javax.swing.JMenuItem(); jSeparator1 = new javax.swing.JSeparator(); deleteMenuItem = new javax .swing.JMenuItem(); theSplitPane = new javax.swing.JSplitPane (); upperPanel = new javax.swing.JPanel(); jScrollPane1 = new javax.swing.JScrollPane(); sqlList = new DNDListSQL(); lowerPanel = new javax.swing.JPanel(); jScrollPane2 = new javax.swing.JScrollPane(); tableList = new DNDListInfo(); jPanel1 = new javax.swing.JPane l(); elementComboBox = new javax.swing.JComboBox(); jPanel2 = new javax.swing.JPanel(); addButton = new javax.swing.JButton(); jButton1 = new javax .swing .JButton(); testMenuItem.setToolTipText("Test this SQL Query"); testMenuItem.setText("Inspect Query" ); testMenuItem.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed (java.awt.event .ActionEvent evt) { testMenuItemActionPerformed(evt); } }); sqlPopupMenu.add(testMenuItem); sqlPopupMenu.add(jSeparator1); deleteMenuItem.setToolTipText("Remove/Delete this SQL Query"); deleteMenuItem.setText("Remove Query"); deleteMenuItem.addActionListener(new java.awt.event .ActionListener () { public void actionPerformed (java.awt.event .ActionEvent evt) { deleteMenuItemActionPerformed(evt); } }); sqlPopupMenu.add(deleteMenuItem); setMaximizable(true); setTitle("SQL Chooser"); setIconifiable(true); setResizable(true); setClosable(true); setPreferredSize(new java.awt.Dimension(300, 400)); addInternalFrameListener(new javax.swing.event .InternalFrameListener() { public void internalFrameOpened(javax .swing.event.InternalFrameEvent evt ) { } public void internalFrameClosing (javax.swing.event.InternalFrameEvent evt) { formInternalFrameClosing(evt); } public void internalFrameClosed(javax .swing.event.InternalFrameEvent evt ) { } public void internalFrameIconified(javax.swing.event .InternalFrameEvent evt) { } public void internalFrameDeiconified(javax .swing.event.InternalFrameEvent evt ) { } public void internalFrameActivated(javax.swing.event .InternalFrameEvent evt) { } public void internalFrameDeactivated(javax.swing.event.InternalFrameEvent evt ) { } }); theSplitPane.setOrientation(javax.swing.JSplitPane.VERTICAL_SPLIT); theSplitPane.setOneTouchExpandable(true); upperPanel .setLayout (new java.awt.BorderLayout()); Autor: Thomas Schädler 221 Anhang A: Quelltext <xmlizer> configurator sqlList.setBorder(new javax.swing.border.TitledBorder(null, "SQL Queries:", javax .swing.border.TitledBorder .LEFT, javax.swing.border .TitledBorder.DEFAULT_POSITION)); jScrollPane1.setViewportView(sqlList); upperPanel .add(jScrollPane1, java.awt.BorderLayout.CENTER); theSplitPane.setLeftComponent(upperPanel); lowerPanel .setLayout (new java.awt.BorderLayout ()); tableList.setBorder(new javax.swing.border.TitledBorder(null, "Result Table Columns of selected Query:", javax.swing.border.TitledBorder.LEFT, javax.swing.border .TitledBorder.DEFAULT_POSITION )); jScrollPane2.setViewportView(tableList); lowerPanel .add(jScrollPane2, java.awt.BorderLayout.CENTER); theSplitPane.setRightComponent(lowerPanel ); getContentPane().add(theSplitPane, java.awt.BorderLayout .CENTER); jPanel1.setLayout(new java.awt.BorderLayout()); elementComboBox .addActionListener(new java.awt.event.ActionListener() { public void actionPerformed (java.awt.event .ActionEvent evt) { elementComboBoxActionPerformed(evt); } }); jPanel1.add(elementComboBox, java.awt.BorderLayout.CENTER); jPanel2.setLayout(new java.awt.FlowLayout (java.awt.FlowLayout .CENTER, 0, 0)); addButton.setIcon(new javax.swing.ImageIcon(getClass().getResource ("/configurator/icons/html/refresh.gif"))); addButton.setText("Add"); addButton.addActionListener(new java.awt.event .ActionListener () { public void actionPerformed (java.awt.event .ActionEvent evt) { addButtonActionPerformed(evt); } }); jPanel2.add(addButton); jButton1.setIcon(new javax .swing.ImageIcon(getClass ().getResource("/configurator/icons/Help16.gif"))); jButton1.setToolTipText("Open Help"); jButton1.setFont(new java.awt.Font("Dialog", 0, 10)); jButton1.addActionListener (new java.awt.event.ActionListener() { public void actionPerformed (java.awt.event .ActionEvent evt) { jButton1ActionPerformed (evt); } }); jPanel2.add(jButton1 ); jPanel1.add(jPanel2, java.awt.BorderLayout.EAST); getContentPane().add(jPanel1, java.awt.BorderLayout .NORTH); pack(); }//GEN-END:initComponents private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN -FIRST:event_jButton1ActionPerformed // Add your handling code here: helpWindow help = (helpWindow)mother .open("help"); help.loadPage("/configurator/help/module_db2xml_sqlchooser.html"); }//GEN-LAST:event_jButton1ActionPerformed private void addButtonActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_addButtonActionPerformed {//GEN-HEADEREND:event_addButtonActionPerformed // Add your handling code here: final SchemaElement currsel = getActiveElement (); final configurator tmother = this.mother; final String tid = this.ID; if (currsel != null) { this.addButton.setEnabled(false); Runnable r = new Runnable() { public void run() { tmother.mappingState = false; //opening the DataChooser DataChooser dch = (DataChooser)tmother.open("DataChooser"); dch.setSchemaElement(currsel); //opening the dbBrowser dbBrowser browser = (dbBrowser)tmother.open("databaseBrowser"); browser.setDataChooser(dch); browser.enableTakeover(currsel); tmother.close(tid); } }; try { pool.execute(r); }catch(InterruptedException ie) { tmother.getLog ().addError (ie);} } /* SchemaElement currsel = getActiveElement(); mother.mappingState = false; dbBrowser browser = (dbBrowser)mother.open("databaseBrowser"); DataChooser dch = (DataChooser)mother.open("DataChooser"); dch.setSchemaElement(currsel); browser.setDataChooser(dch); mother.close(this.ID); browser.enableTakeover(currsel); **/ Autor: Thomas Schädler 222 Anhang A: Quelltext <xmlizer> configurator }//GEN-LAST:event_addButtonActionPerformed private void deleteMenuItemActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_deleteMenuItemActionPerformed {//GEN-HEADEREND:event_deleteMenuItemActionPerformed // Add your handling code here: SchemaElement currsel = getActiveElement(); if (currsel != null) { //currsel.removeSQLStatement(this.lastSQL); //mother.getProjectData().DB2XMLgetmapping().cleanElements(this.lastSQL); mother .getProjectData().cleanSchemaElementFullDependencies(this.lastSQL); sqlList.repaint(); } }//GEN-LAST:event_deleteMenuItemActionPerformed private void testMenuItemActionPerformed (java.awt.event .ActionEvent evt)//GEN-FIRST:event_testMenuItemActionPerformed {//GEN-HEADEREND:event_testMenuItemActionPerformed // Add your handling code here: if (this.lastSQL != null) { dbBrowser browser = (dbBrowser)this.mother .open("databaseBrowser"); browser.inspect(this.lastSQL); } }//GEN-LAST:event_testMenuItemActionPerformed private void elementComboBoxActionPerformed(java.awt.event.ActionEvent evt)//GEN FIRST:event_elementComboBoxActionPerformed {//GEN-HEADEREND:event_elementComboBoxActionPerformed // Add your handling code here: showActiveElement(); }//GEN-LAST:event_elementComboBoxActionPerformed private void formInternalFrameClosing(javax.swing.event .InternalFrameEvent evt)//GEN-FIRST:event_formInternalFrameClosing {//GEN-HEADEREND:event_formInternalFrameClosing // Add your handling code here: mother.close(this.ID); }//GEN-LAST:event_formInternalFrameClosing // Variables declaration - do not modify//GEN -BEGIN:variables private javax.swing .JPopupMenu sqlPopupMenu; private javax.swing .JMenuItem testMenuItem; private javax.swing .JSeparator jSeparator1; private javax.swing .JMenuItem deleteMenuItem; private javax.swing .JSplitPane theSplitPane; private javax.swing .JPanel upperPanel; private javax.swing .JScrollPane jScrollPane1; private javax.swing .JList sqlList; private javax.swing .JPanel lowerPanel; private javax.swing .JScrollPane jScrollPane2; private javax.swing .JList tableList ; private javax.swing .JPanel jPanel1; private javax.swing .JComboBox elementComboBox ; private javax.swing .JPanel jPanel2; private javax.swing .JButton addButton; private javax.swing .JButton jButton1; // End of variables declaration//GEN-END:variables /** * Shows the db-entries for the active Element */ private void showActiveE lement () { if (this.getActiveElement() != null) { sqlList.setEnabled(false); this.updateTables(new Vector()); sqlList.setListData(this.getActiveElement().getSQLStatements()); sqlList.setEnabled(true); sqlList.repaint(); } } /** * Returns the currently selected dbItem */ synchronized private SchemaElement getActiveElement() { return (SchemaElement)elementComboBox.getSelectedItem(); } /** * Gets the new data and fills the lists */ synchronized public void updateView (SchemaElement el) { mother.mappingState = true; this.currentElement = el; //build element comboBox elementComboBox .setVisible (false); elementComboBox .removeAllItems(); int counter = 0; int selected = -1; for (Enumeration e = el.getParents().elements(); e.hasMoreElements ();) { SchemaElement curr_el = (SchemaElement)e.nextElement (); //determine the selected element by comparing the ids if (curr_el.getID().equalsIgnoreCase(el.getID())) { selected = counter ; } elementComboBox.addItem(curr_el); counter++; } if (selected > 0) { elementComboBox.setSelectedIndex (selected); } if (counter <= 0) { //elementComboBox.setEnabled(false); sqlList.setEnabled(false); tableList.setEnabled(false); Autor: Thomas Schädler 223 Anhang A: Quelltext <xmlizer> configurator } else { //elementComboBox.setEnabled(true); sqlList.setEnabled(true); tableList.setEnabled(true); } elementComboBox .setVisible (true); setTitleElementName(el.getRealName()); elementComboBox .repaint(); } /** * Gets the new data and fills the lists */ synchronized private void updateTables(Vector tab) { tableList.setEnabled (false ); tableList.setListData(tab); tableList.setEnabled (true); tableList.repaint(); } /** * This method updates the UI if the setupwindow is closed * (and a change in the setup component occured) */ public synchronized void update(configurator conf) { isLoading = true; this.mother = conf; isLoading = false; } /** * A draggabel List of SQLStatements * -> sends a SQLStatment.id (as String) */ class DNDListSQL extends JList implements DragSourceListener, DragGestureListener { DragSource dragSource = null; /**constructor - initializes the DragSource */ public DNDListSQL() { dragSource = new DragSource (); dragSource.createDefaultDragGestureRecogni zer(this,DnDConstants.ACTION_COPY,this); } /** a drag gesture has been initiated */ public void dragGestureRecognized(DragGestureEvent event ) { //System.out.println("START > dragGestureRecognized"); SQLStatement selected = (SQLStatement )getSelectedValue(); if (selected != null) { StringSelection text = new StringSelection(selected.getID()); // as the name suggests, starts the dragging dragSource.startDrag(event,DragSource.DefaultMoveDrop ,text,this); } } //REST UNUSED /**this message goes to DragSourceListener, informing it that the dragging has ended */ public void dragDropEnd(DragSourceDropEvent event) { /*System.out.println("START > dragDropEnd");*/ } /** this message goes to DragSourceListener, informing it that the dragging has entered the DropSite */ public void dragEnter(DragSourceDragEvent event) { /*System.out.println("START > dragEnter");*/ } /** this message goes to DragSourceListener, informing it that the dragging has exited the DropSite */ public void dragExit (DragSourceEvent event) { /*System.out.println("START > dragExit");*/ } /**this message goes to DragSourceListener, informing it that the dragging is currently ocurring over the DropSite */ public void dragOver (DragSourceDragEvent event ) { /*System.out.println("START > dragOver");*/ } /** is invoked when the user changes the dropAction */ public void dropActionChanged(DragSourceDragEvent event) { /*System.out.println("START > dragActionChanged");*/ } } /** * A draggable list of Columninfos * -> Sends a String-Combination of ColumnInfo.getID:ColumnInfo.getName (as String) */ class DNDListInfo extends JList implements DragSourceListener, DragGestureListener { DragSource dragSource = null; /**constructor - initializes the DragSource */ public DNDListInfo() { dragSource = new DragSource (); dragSource.createDefaultDragGestureRecognizer(this,DnDConstants.ACTION_COPY,this); } /** a drag gesture has been initiated */ public void dragGestureRecognized(DragGestureEvent event ) { //System.out.println("START > dragGestureRecognized"); ColumnInfo selected = (ColumnInfo)getSelectedValue(); if (selected != null) { StringSelection text = new StringSelection(selected.getID() + ":" + selected.getName ()); // as the name suggests, starts the dragging dragSource.startDrag(event,DragSource.DefaultMoveDrop ,text,this); } } //REST UNUSED /**this message goes to DragSourceListener, informing it that the dragging has ended */ public void dragDropEnd(DragSourceDropEvent event) { /*System.out.println("START > dragDropEnd");*/ } /** this message goes to DragSourceListener, informing it that the dragging has entered the DropSite */ public void dragEnter(DragSourceDragEvent event) { /*System.out.println("START > dragEnter");*/ } /** this message goes to DragSourceListener, informing it that the dragging has exited the DropSite */ public void dragExit (DragSourceEvent event) Autor: Thomas Schädler 224 Anhang A: Quelltext <xmlizer> configurator { /*System.out.println("START > dragExit");*/ } /**this message goes to DragSourceListener, informing it that the dragging is currently ocurring over the DropSite */ public void dragOver (DragSourceDragEvent event ) { /*System.out.println("START > dragOver");*/ } /** is invoked when the user changes the dropAction */ public void dropActionChanged(DragSourceDragEvent event) { /*System.out.println("START > dragActionChanged");*/ } } }/* * SchemaElementPanel.java * * This class representates a Schema Element Panel for showing its content * * Created on 20. Juli 2002, 10:22 * ---------------------------------------------------------------------------* This file is part of <xmlizer>. * * <xmlizer> is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Foobar is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with <xmlizer>; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * ---------------------------------------------------------------------------*/ package configurator; import import import import import import java.awt.*; java.util.*; javax.swing .*; java.awt.dnd.*; java.awt.event.*; java.awt.datatransfer .*; /** * The panel for the SchemaElement (used to drop queries here from the SQLChooser) * @author [email protected] */ public class SchemaElementPanel extends javax.swing.JPanel { private configurator mother; private SchemaElement element; private Vector attLabels = new Vector(); private DNDLabelRep dndl ; private DNDLabelCont clab; /** Creates new form SchemaElementPanel */ public SchemaElementPanel(configurator config ,SchemaElement element) { this.mother = config ; this.element = element; initComponents(); fillPanel(); checkDropEnables(); } private void fillPanel() { //set the elements name elementLabel.setText(this.element.getRealName()); String temp_srr = this.element.getType(); if (temp_srr == null || temp_srr.equalsIgnoreCase("")) { typeLabel.setText("anonymous"); } else typeLabel.setText(temp_srr ); //set the repetition //add a droptarget for controlling how many (SQL to iterate over) //only if occurrence is good for that (more than one element allowed! repPanel.setLayout(new java.awt.GridLayout(1,3)); String temp_str = this.element.getOccurrence().getShortOcc(); repPanel.add(new JLabel(temp_str)); StringBuffer temp_rep = new StringBuffer(); if (this.element.getRepetition() != null) { temp_rep.append(this.element.getRepetition ()); } dndl = new DNDLabelRep(this,temp_rep .toString(),this.element,mother); repPanel.add(dndl); JButton tempbutt1 = new RepButton(this.element,dndl); tempbutt1.setIcon(new javax.swing.ImageIcon(getClass().getResource ("/configurator/icons/Delete16.gif"))); tempbutt1.addActionListener(new java.awt.event .ActionListener () { public void actionPerformed (java.awt.event .ActionEvent evt) { repdelButtonActionPerformed(evt); } }); repPanel.add(tempbutt1); //set the content contentPanel.setLayout(new java.awt.GridLayout (1,3)); if (this.element.hasContent()) { SchemaContent cont = this.element.getContent(); String temp_str1 = this.element.getType(); contentPanel.add(new JLabel (temp_str1 )); StringBuffer cbuff = new StringBuffer (); if (cont.getMapID() != null) { cbuff.append (cont.getMapID()); if (cont.getMapInfo() != null) { Autor: Thomas Schädler 225 Anhang A: Quelltext <xmlizer> configurator cbuff.append(":" + cont.getMapInfo ()); } } clab = new DNDLabelCont(cbuff.toString(),cont,mother ,this.element); //System.out.println("ADDED cont: " + cont.toString()); contentPanel.add(clab); JButton ctempbutt = new ContButton(cont,clab); ctempbutt.setIcon(new javax .swing.ImageIcon(getClass ().getResource("/configurator/icons/Delete16.gif"))); ctempbutt.addActionListener (new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt ) { contdelButtonActionPerformed(evt); } }); contentPanel.add(ctempbutt); } else { contentPanel.add(new JLabel ("Has no text." )); } //set the attributes int numrows = //calculate the number of used rows to display all data + this.element.getAttributes().size() + 0 //additional output ; attributePanel.setLayout(new java.awt.GridLayout(numrows,4)); for (Enumeration e = this.element.getAttributes().elements(); e.hasMoreElements();) { SchemaAttribute att = (SchemaAttribute)e.nextElement (); //JLabel temp_lab = new JLabel("Attribute:"); //temp_lab.setForeground(java.awt.Color.darkGray); //attributePanel.add(temp_lab); attrib utePanel.add(new JLabel(att.getName())); attributePanel.add(new JLabel(att.getUse())); StringBuffer dndtext = new StringBuffer(); SQLStatement usedsql = mother.getProjectData().DB2XMLgetmapping().getSQLState mentByMapID (att.getMapID()); if (usedsql != null) { //FIXME //usedsql.getDB() //usedsql.getSQL() StringBuffer buff = new StringBuffer(att.getMapID()); if (att.getMapInfo () != null) { buff.append(":" + att.getMapInfo()); } dndtext.append(buff.toString ()); } DNDLabelAtt lab = new DNDLabelAtt(dndtext.toString(),att,mother,this.element); this.attLabels.add(lab); //System.out.println("ADDED attr: " + lab.toString()); attributePanel.add(lab); JButton tempbutt = new AttButton (att,lab); tempbutt.setIcon(new javax.swing .ImageIcon (getClass().getResource("/configurator/icons/Delete16.gif"))); tempbutt.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt ) { deleteButtonActionP erformed(evt); } }); attributePanel.add(tempbutt ); } } /** * enable the drop for the content and attributes * only if the repetition-label is set! */ public void checkDropEnables() { if (this.dndl != null) { String id = this.dndl.getID (); if (id != null && !id.equalsIgnoreCase(new String())) { if (clab != null) { clab.setEnabled(true); } setAttributesDroppable(true); } else if (this.element.getOccurrence().getMinOccurs().intValue() > 0) { if (clab != null) { clab.setEnabled(true); } setAttributesDroppable(true); } else { if (clab != null) { clab.setEnabled(false); } setAttributesDroppable(false ); } } } public void setAttributesDroppable(boolean bool) { for (Enumeration e = this.getAttLabels().elements(); e.hasMoreElements();) { DNDLabelAtt curat = (DNDLabelAtt )e.nextElement(); curat.setEnabled (bool); } } class ContButton extends JButton { private SchemaContent cont ; private DNDLabelCont lab; public ContButton(SchemaContent cont ,DNDLabelCont lab) { this.cont = cont; this.lab = lab; //setSize(31,31); } public DNDLabelCont getDNDLabel () { Autor: Thomas Schädler 226 Anhang A: Quelltext <xmlizer> configurator return this.lab; } public SchemaContent getContent () { return this.cont; } } class RepButton extends JButton { private SchemaElement elm; private DNDLabelRep lab; public RepButton(SchemaElement elm,DNDLabelRep lab) { this.elm = elm; this.lab = lab; //setSize(31,31); } public DNDLabelRep getDNDLabel() { return this.lab; } public SchemaElement getElement () { return this.elm; } } class AttButton extends JButton { private SchemaAttribute att; private DNDLabelAtt lab; public AttButton(SchemaAttribute att ,DNDLabelAtt lab) { this.att = att; this.lab = lab; //setSize(31,31); } public DNDLabelAtt getDNDLabel() { return this.lab; } public SchemaAttribute getAttribute() { return this.att; } } /** handels the delete action for the attlabels */ private void deleteButtonActionPerformed (java.awt.event .ActionEvent evt) { AttButton but = (AttButton )evt.getSource(); SchemaAttribute att = but.getAttribu te(); DNDLabelAtt lab = but.getDNDLabel(); att.cleanMapping(); lab.setText(""); lab.setToolTipText(""); checkDropEnables(); mother.getProjectData().setDirty(); } /** handels the delete action for the content*/ private void contdelButtonActionPerformed(java.awt.event.ActionEvent evt) { ContButton but = (ContButton)evt.getSource(); SchemaContent cont = but.getContent(); DNDLabelCont lab = but.getDNDLabel(); cont.cleanMapping(); lab.setText(""); lab.setToolTipText(""); checkDropEnables(); this.repaint(); mother.getProjectData().setDirty(); } /** handels the delete action for the repetition -> sideeffect-clearing of dependencies */ private void repdelButtonActionPerformed (java.awt.event .ActionEvent evt) { RepButton but = (RepButton )evt.getSource(); SchemaElement elm = but.getElement(); DNDLabelRep lab = but.getDNDLabel(); SQLStatement oldStat = elm.getRepetitionStatement(); if (oldStat != null) { mother .getProjectData().cleanSchemaElementDataDependencies(oldStat); updateAttributeLabels(); } elm.setRepetition(null); lab.setText(""); lab.setToolTipText(""); checkDropEnables(); this.repaint(); mother.getProjectData().setDirty(); } public void updateAttributeLabels() { if (clab != null) { clab.setToolTipText(""); clab.setText(""); } for (Enumeration e = this.getAttLabels().elements(); e.hasMoreElements();) { DNDLabelAtt curat = (DNDLabelAtt )e.nextElement(); curat.setText(""); curat.setToolTipText(""); curat.repaint(); } } public void updateAttributeLabels(String id) { //System.out.println("LABELS: " + this.getAttLabels()); for (Enumeration e = this.getAttLabels().elements(); e.hasMoreElements();) { DNDLabelAtt curat = (DNDLabelAtt )e.nextElement(); //System.out.print(">>> " + curat.getText()); Autor: Thomas Schädler 227 Anhang A: Quelltext <xmlizer> configurator if (curat.getID().equalsIgnoreCase(id)) { curat.setText(""); curat.setToolTipText(""); curat.repaint(); //System.out.print(" deleted!"); } //System.out.print(curat.getID() + "\n"); } } public void updateAttributeLabels(SQLStatement st) { updateAttributeLabels(st.getID()); } /** This method is called from within the constructor to * initialize the form. * WARNING: Do NOT modify this code. The content of this method is * always regenerated by the Form Editor. */ private void initComponents()//GEN-BEGIN:initCompo nents { mainPanel = new javax.swing.JPanel(); infoPanel = new javax.swing.JPanel(); fixedLabel1 = new javax.swing.JLabel (); elementLabel = new javax.swing.JLabel(); fixedLabel2 = new javax.swing.JLabel (); typeLabel = new javax.swing.JLabel(); repPanel = new javax .swing .JPanel(); contentPanel = new javax.swing.JPanel(); attributePanel = new javax .swing.JPanel(); setLayout(new java.awt.BorderLayout()); setBorder(new javax.swing.border.TitledBorder("Element information:")); mainPanel.setLayout(new javax.swing.BoxLayout(mainPanel, javax.swing.BoxLayout.Y_AXIS)); mainPanel.setMinimumSize(new java.awt.Dimension(0, 0)); infoPanel.setLayout(new java.awt.GridLayout(2, 2, 1, 1)); infoPanel.setMinimumSize(new java.awt.Dimension(0, 0)); fixedLabel1.setText("Element name:"); fixedLabel1.setForeground(java.awt.Color.darkGray); infoPanel.add(fixedLabel1); elementLabel.setText("<element>"); infoPanel.add(elementLabel ); fixedLabel2.setText("Element type:"); fixedLabel2.setForeground(java.awt.Color.darkGray); infoPanel.add(fixedLabel2); typeLabel.setText("<type>" ); infoPanel.add(typeLabel); mainPanel.add(infoPanel); repPanel.setLayout(null); repPanel.setBorder(new javax.swing.border .TitledBorder("Repetition:")); mainPanel.add(repPanel); contentPanel.setLayout(null); contentPanel.setBorder(new javax.swing.border.TitledBorder("Content:")); mainPanel.add(contentPanel ); attributePanel.setLayout(null); attributePanel.setBorder(new javax.swing.border.TitledBorder("Attributes:")); mainPanel.add(attributePanel); add(mainPanel, java.awt.BorderLayout .CENTER); }//GEN-END:initComponents // Variables declaration - do not modify//GEN -BEGIN:variables private javax.swing .JPanel mainPanel; private javax.swing .JPanel infoPanel; private javax.swing .JLabel fixedLabel1; private javax.swing .JLabel elementLabel; private javax.swing .JLabel fixedLabel2; private javax.swing .JLabel typeLabel; private javax.swing .JPanel repPanel ; private javax.swing .JPanel contentPanel; private javax.swing .JPanel attributePanel; // End of variables declaration//GEN-END:variables public Vector getAttLabels() { return this.attLabels; } /** * Drop-Enabled Label for the Repetition (Occurrence) */ class DNDLabelRep extends JLabel implements DropTargetListener { private SchemaElement element; private configurator mother; private SchemaElementPanel panel; // Constructor public DNDLabelRep() { super(); // create a drop target for this component DropTarget dt = new DropTarget(this, this); Autor: Thomas Schädler 228 Anhang A: Quelltext <xmlizer> configurator this.setForeground(java.awt.Color.red); this.setBorder(new javax.swing.border .LineBorder(java.awt.Color.red)); } public DNDLabelRep(SchemaElementPanel parent,String text ,SchemaElement elem,confi gurator conf) { super(text); this.setToolTipText(text); this.mother = conf; this.element = elem; this.panel = parent; // create a drop target for this component DropTarget dt = new DropTarget(this, this); this.setForeground(java.awt.Color.red); //System.out.println(attLabels); this.setBorder(new javax.swing.border .LineBorder(java.awt.Color.red)); } public String getID() { return this.getText(); } /** Returns true if the string contains NO : */ private boolean isValidData(String s ) { int doublepoint = s.indexOf(":"); if (doublepoint < 0) { return true; } else return false; } // DropTargetListener interface implementation public void drop(DropTargetDropEvent event) { /*System.out.println("END > drop");*/ try { Transferable transferable = event .getTransferable(); // we accept only Strings if (transferable.isDataFlavorSupported (DataFlavor.stringFlavor)) { event.acceptDrop(DnDConstants .ACTION_COPY); String s = (String)transferable.getTransferData(DataFlavor.stringFlavor); //do the thing with the key: mapid:mapinfo //System.out.println("DROP >>>>>" + s); if (s != null && mother.mappingState && isValidData(s)) { setText(s); setToolTipText(s); SQLStatement oldStat = this.element.getRepetitionStatement(); if (oldStat != null) { mother .getProjectData ().cleanSchemaElementDataDependencies(oldStat); } this.element.setRepetition(s); mother.getProjectData().setDirty(); this.panel .updateAttributeLabels(); this.panel .checkDropEnables(); this.repaint(); } else if(!mother.mappingState) { mother.getLog().addWarning("You cannot drop queries to the Mapping in Database-Mode!"); } event.getDropTargetContext().dropComplete(true); } else { event.rejectDrop(); } } catch (java.io.IOException exception) { System.err.println ( "Exception" + exception .getMessage()); event.rejectDrop(); } catch (UnsupportedFlavorException ufException ) { System.err.println ( "Exception" + ufException.getMessage()); event.rejectDrop(); } } //REST UNUSED public void dragEnter(DropTargetDragEvent dtde ) { /*System.out.println("END > dragEnter");*/ } public void dragExit (DropTargetEvent dte) { /*System.out.println("END > dragExit");*/ } public void dragOver (DropTargetDragEvent dtde) { /*System.out.println("END > dragOver");*/ } public void dropActionChanged(DropTargetDragEvent dtde) { /*System.out.println("END > dropActionChanged");*/ } } /** * Drop-Enabled Label for the Content */ class DNDLabelCont extends JLabel implements DropTargetListener { private SchemaContent content; private configurator mother; private SchemaElement element; // Constructor public DNDLabelCont() { super(); // create a drop target for this component DropTarget dt = new DropTarget(this, this); this.setForeground(new java.awt.Color (33,86,130)); this.setBorder(new javax.swing.border .LineBorder(new java.awt.Color (33,86,130))); } public DNDLabelCont(String text ,SchemaContent cont,configurator conf,SchemaElement el) { super(text); this.setToolTipText(text); this.mother = conf; this.content = cont; Autor: Thomas Schädler 229 Anhang A: Quelltext <xmlizer> configurator this.element = el; // create a drop target for this component DropTarget dt = new DropTarget(this, this); this.setForeground(new java.awt.Color (33,86,130)); this.setBorder(new javax.swing.border .LineBorder(new java.awt.Color (33,86,130))); } public String getID() { if (!this.getText().equalsIgnoreCase(new String ())) { return getFirst(this.getText()); } else return ""; } /** Returns xxx from xxx:yyy */ private String getFirst(String s) { int doublepoint = s.indexOf(":"); if (doublepoint != 0) { return s.substring (0,doublepoint); } else return s; } /** Returns yyy from xxx:yyy */ private String getSecond(String s) { int doublepoint = s.indexOf(":"); if (doublepoint != 0) { return s.substring (++doublepoint); } else return s; } /** Returns true if the string contains a : */ private boolean isValidData(String s ) { int doublepoint = s.indexOf(":"); if (doublepoint < 0) { return false ; } else return true; } /** * Returns true if this statement is not the repetition statement **/ private boolean isNotRepStat(String s) { if (this.element.getRepetition() != null) { if (this.element.getRepetition().equalsIgnoreCase(s)) { return false; } } return true; } // DropTargetListener interface implementation public void drop(DropTargetDropEvent event) { /*System.out.println("END > drop");*/ try { Transferable transferable = event .getTransferable(); // we accept only Strings if (transferable.isDataFlavorSupported (DataFlavor.stringFlavor)) { event.acceptDrop(DnDConstants .ACTION_COPY); String s = (String)transferable.getTransferData(DataFlavor.stringFlavor); //do the thing with the key: mapid:mapinfo //System.out.println("DROP >>>>>" + s); if (s != null && mother.mappingState && isValidData(s) && isNotRepStat(s)) { String mapid = getFirst(s); String mapinfo = getSecond(s); if (mapid != null && mapinfo != null && isEnabled()) { content.setMapID (mapid); content.setMapInfo(mapinfo); setText(mapid + ":" + mapinfo); setToolTipText(mapid + ":" + mapinfo); mother .getProjectData ().setDirty(); } } else if (s != null && mother.mappingState && !isValidData(s) && isNotRepStat(s) && isEnabled()) // { //System.out.print(">>>" + s); //dropped a SQLStatement with only one possible result content.setMapID(s); setText(s); setToolTipText(s); mother.getProjectData().setDirty(); } else { if(!mother .mappingState) { mother .getLog().addWarning ("You cannot drop queries to the Mapping in Database-Mode!"); } else if(!isNotRepStat(s)) { mother .getLog().addWarning ("This SQL Query is already assigned to the repetition!" ); } else { mother .getLog().addWarning ("Assign a repetition SQL query before filling the content."); } } event.getDropTargetContext().dropComplete(true); } else { event.rejectDrop(); } } catch (java.io.IOException exception) { System.err.println ( "Exception" + exception .getMessage()); event.rejectDrop(); } catch (UnsupportedFlavorException ufException ) { Autor: Thomas Schädler 230 Anhang A: Quelltext <xmlizer> configurator System.err.println ( "Exception" + ufException.getMessage()); event.rejectDrop(); } } //REST UNUSED public void dragEnter(DropTargetDragEvent dtde ) { /*System.out.println("END > dragEnter");*/ } public void dragExit (DropTargetEvent dte) { /*System.out.println("END > dragExit");*/ } public void dragOver (DropTarget DragEvent dtde) { /*System.out.println("END > dragOver");*/ } public void dropActionChanged(DropTargetDragEvent dtde) { /*System.out.println("END > dropActionChanged");*/ } } /** * Drop-Enabled Label for Attributes */ class DNDLabelAtt extends JLabel implements DropTargetListener { private SchemaAttribute attribute; private configurator mother; private SchemaElement element; // Constructor public DNDLabelAtt() { super(); // create a drop target for this component DropTarget dt = new DropTarget(this, this); this.setForeground(java.awt.Color.blue); this.setBorder(new javax.swing.border .LineBorder(java.awt.Color.blue)); } public DNDLabelAtt(String text,SchemaAttribute attr ,configurator conf,SchemaElement el ) { super(text); this.setToolTipText(text); this.mother = conf; this.attribute = attr; this.element = el; // create a drop target for this component DropTarget dt = new DropTarget(this, this); this.setForeground(java.awt.Color.blue); this.setBorder(new javax.swing.border .LineBorder(java.awt.Color.blue)); } public String getID() { if (!this.getText().equalsIgnoreCase(new String ())) { return getFirst(this.getText()); } else return ""; } /** Returns xxx from xxx:yyy */ private String getFirst(String s) { int doublepoint = s.indexOf(":"); if (doublepoint != 0) { return s.substring (0,doublepoint); } else return s; } /** Returns yyy from xxx:yyy */ private String getSecond(String s) { int doublepoint = s.indexOf(":"); if (doublepoint != 0) { return s.substring (++doublepoint); } else return s; } /** Returns true if the string contains a : */ private boolean isValidData(String s ) { int doublepoint = s.indexOf(":"); if (doublepoint < 0) { return false ; } else return true; } /** * Returns true if this statement is not the repetition statement **/ private boolean isNotRepStat(String s) { if (this.element.getRepetition() != null) { if (this.element.getRepetition().equalsIgnoreCase(s)) { return false; } } return true; } // DropTargetListener interface implementation public void drop(DropTargetDropEvent event) { /*System.out.println("END > drop");*/ try { Transferable transferable = event .getTransferable(); // we accept only Strings if (transferable.isData FlavorSupported (DataFlavor.stringFlavor)) { event.acceptDrop(DnDConstants .ACTION_COPY); String s = (String)transferable.getTransferData(DataFlavor.stringFlavor); //do the thing with the key: mapid :mapinfo //System.out.println("DROP >>>>>" + s); if (s != null && mother.mappingState && isValidData(s) && isNotRepStat(s)) { String mapid = getFirst(s); String mapinfo = getSecond(s); if (mapid != null && mapinfo != null && isEnabled()) { attribute.setMapID(mapid); Autor: Thomas Schädler 231 Anhang A: Quelltext <xmlizer> configurator attribute.setMapInfo(mapinfo); setText(mapid + ":" + mapinfo); setToolTipText(mapid + ":" + mapinfo); mother .getProjectData ().setDirty(); } } else if (s != null && mother.mappingState && !isValidData(s) && isNotRepStat(s) && isEnabled()) // { //System.out.print(">>>" + s); //dropped a SQLStatement with only one possible result attribute.setMapID(s); setText(s); setToolTipText(s); mother.getProjectData().setDirty(); } else { if(!mother .mappingState) { mother .getLog().addWarning ("You cannot drop queries to the Mapping in Database-Mode!"); } else if(!isNotRepStat(s)) { mother .getLog().addWarning ("This SQL Query is already assigned to the repetition!" ); } else { mother .getLog().addWarning ("Assign a repetition SQL query before filling the attributes."); } } event.getDropTargetContext().dropComplete(true); } else { event.rejectDrop(); } } catch (java.io.IOException exception) { System.err.println ( "Exception" + exception .getMessage()); event.rejectDrop(); } catch (UnsupportedFlavorException ufException ) { System.err.println ( "Exception" + ufException.getMessage()); event.rejectDrop(); } } //REST UNUSED public void dragEnter(DropTargetDragEvent dtde ) { /*System.out.println("END > dragEnter");*/ } public void dragExit (DropTargetEvent dte) { /*System.out.println("END > dragExit");*/ } public void dragOver (DropTargetDragEvent dtde) { /*System.out.println("END > dragOver");*/ } public void dropActionChanged(DropTargetDragEvent dtde) { /*System.out.println("END > dropActionChanged");*/ } } }/* * ColumnInfo.java * * Created on 25. Juli 2002, 02:47 * ---------------------------------------------------------------------------* This file is part of <xmlizer>. * * <xmlizer> is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Foobar is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with <xmlizer>; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * ---------------------------------------------------------------------------*/ package configurator; /** * Represents the information neccessary to show a columninfo (from the db) * @author [email protected] */ class ColumnInfo { protected String id ; protected String name; protected String type; public ColumnInfo(String id,String name,String type) { this.id = id; this.name = name; this.type = type; } public String getID () { return this.id; } public String getName() { return this.name; } public String getType() { return this.type; } public String toString() { return this.name + " [" + this.type + "]"; } Autor: Thomas Schädler 232 Anhang A: Quelltext <xmlizer> configurator }/* * DataChooser.java * * Created on 30. Juli 2002, 11:03 * ---------------------------------------------------------------------------* This file is part of <xmlizer>. * * <xmlizer> is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Foobar is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with <xmlizer>; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * ---------------------------------------------------------------------------*/ package configurator; import import import import import import java.awt.*; java.util.*; javax.swing .*; java.awt.dnd.*; java.awt.event.*; java.awt.datatransfer .*; /** * Represents the DataChooser (used to drop dependencies to the databaseBrowser * @author [email protected] */ public class DataChooser extends MyInternalFrame { private configurator mother; private String ID; private private private private boolean isLoading = true; String title = new String(); SchemaElement currentElement = null; Vector params = new Vector(); /** Creates new form SQLChooser */ public DataChooser(configurator mainProgram,String uid) { this.mother = mainProgram; this.ID = uid; initComponents(); setClosable(false); theSplitPane.setDividerLocation (150); theSecondSplitPane.setDividerLocation(250); //make the list functional sqlList.getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION); tableList.getSelectionModel().setSelectionMode (ListSelectionModel.SINGLE_SELECTION); paramList.getSelectionModel().setSelectionMode (ListSelectionM odel.SINGLE_SELECTION); //add the ParameterInfos to the params-vector Hashtable paraHash = mother.getProjectData().DB2XMLgetmapping ().getParameters(); for (Enumeration e = paraHash.elements(); e.hasMoreElements();) { ParameterInfo item = (ParameterInfo)e.nextElement(); this.params .add(item); } paramList.setListData(this.params); //add the mouselistener ItemListener ilst = new ItemListener (this); sqlList.addMouseListener(ilst); this.setTitleElementName(""); } /** Returns this windows uniqueID */ public String getWinID() { return this.ID; } /** * Listens for listItem-(Mouse)-Events on the dbtableList * -> For database queries */ class ItemListener implements java.awt.event.MouseListener { protected DataChooser m_parent; protected JList m_list; public ItemListener(DataChooser parent) { m_parent = parent; m_list = parent.sqlList; } public void mouseClicked(java.awt.event.MouseEvent e) { doAction(); } public public public public void void void void mousePressed(java.awt.event.MouseEvent e){} mouseReleased(java.awt.event.MouseEvent e){} mouseEntered(java.awt.event.MouseEvent e){} mouseExited(java.awt.event.MouseEvent e ){} protected void doAction() { int index = m_list.getSelectedIndex(); if (index < 0) { return; } Autor: Thomas Schädler 233 Anhang A: Quelltext <xmlizer> configurator if (m_list.getModel().getSize() > index) { SQLStatement data = (SQLStatement )m_list.getModel().getElementAt(index); if (data != null) { m_parent .updateTables(data.getColsAsSQLColumnInfo ()); } } } } private void setTitleElementName(String name) { StringBuffer buff = new StringBuffer ("Data Chooser" ); if (name != null) { buff.append (" @ " + name); this.setTitle(buff.toString ()); } this.repaint(); } /** This method is called from within the constructor to * initialize the form. * WARNING: Do NOT modify this code. The content of this method is * always regenerated by the Form Editor. */ private void initComponents() { theSplitPane = new javax.swing.JSplitPane (); upperPanel = new javax.swing.JPanel(); jScrollPane1 = new javax.swing.JScrollPane(); sqlList = new JList(); lowerPanel = new javax.swing.JPanel(); jScrollPane2 = new javax.swing.JScrollPane(); tableList = new DNDListInfo(); jPanel1 = new javax.swing.JPanel(); elementComboBox = new javax.swing.JComboBox(); jButton1 = new javax .swing .JButton(); paramList = new DNDListParam(); theSecondSplitPane = new JSplitPane(); paramPanel = new JPanel(); paramScrollPane = new javax.swing.JScrollPane(); setMaximizable(true); setTitle("Data Chooser"); setIconifiable(true); setResizable(true); setClosable(true); setPreferredSize(new java.awt.Dimension(300, 400)); addInternalFrameListener(new javax.swing.event .InternalFrameListener() { public void internalFrameOpened(javax .swing.event.InternalFrameEvent evt ) { } public void internalFrameClosing (javax.swing.event.InternalFrameEvent evt) { formInternalFrameClosing(evt); } public void internalFrameClosed(javax .swing.event.InternalFrameEvent evt ) { } public void internalFrameIconified(javax.swing.event .InternalFrameEvent evt) { } public void internalFrameDeiconified(javax .swing.event.InternalFrameEvent evt ) { } public void internalFrameActivated(javax.swing.event .InternalFrameEvent evt) { } public void internalFrameDeactivated(javax .swing.event.InternalFrameEvent evt ) { } }); theSecondSplitPane.setOrientation(javax.swing.JSplitPane .VERTICAL_SPLIT ); theSecondSplitPane.setOneTouchExpandable(true); paramPanel .setLayout (new java.awt.BorderLayout ()); paramList.setBorder(new javax.swing.border.TitledBorder(null, "Global Parameters:", javax.swing.border.TitledBorder.LEFT, javax.swing.border .TitledBorder.DEFAULT_POSITION )); paramScrollPane .setViewportView(paramList ); paramPanel .add(paramScrollPane, java.awt.BorderLayout.CENTER); theSecondSplitPane.setLeftComponent(theSplitPane); theSecondSplitPane.setRightComponent (paramPanel); theSplitPane.setOrientation(javax.swing.JSplitPane.VERTICAL_SPLIT); theSplitPane.setOneTouchExpandable(true); upperPanel .setLayout (new java.awt.BorderLayout ()); sqlList.setBorder(new javax.swing.border.TitledBorder(null, "SQL Repetition Queries:", javax.swing.border.TitledBorder.LEFT, javax.swing.border .TitledBorder.DEFAULT_POSITION )); jScrollPane1.setViewportView(sqlList); upperPanel .add(jScrollPane1, java.awt.BorderLayout.CENTER); theSplitPane.setLeftComponent(upperPanel); lowerPanel .setLayout (new java.awt.BorderLayout ()); tableList.setBorder(new javax.swing.border.TitledBorder(null, "Result Table Columns of selected Query:", javax.swing.border.TitledBorder.LEFT, javax.swing.border .TitledBorder.DEFAULT_POSITION )); jScrollPane2.setViewportView(tableList); lowerPanel .add(jScrollPane2, java.awt.BorderLayout.CENTER); theSplitPane.setRightComponent(lowerPanel ); getContentPane().add(theSecondSplitPane, java.awt.BorderLayout.CENTER); jPanel1.setLayout(new java.awt.BorderLayout()); elementComboBox .addActionListener(new java.awt.event.ActionListener() { public void actionPerformed (java.awt.event .ActionEvent evt) { elementComboBoxActionPerformed(evt); } }); Autor: Thomas Schädler 234 Anhang A: Quelltext <xmlizer> configurator jPanel1.add(elementComboBox, java.awt.BorderLayout.CENTER); jButton1.setIcon(new javax .swing.ImageIcon(getClass ().getResource("/configurator/icons/Help16.gif"))); jButton1.setToolTipText("Open Help"); jButton1.setFont(new java.awt.Font("Dialog", 0, 10)); jButton1.addActionListener (new java.awt.event.ActionListener() { public void actionPerformed (java.awt.event .ActionEvent evt) { jButton1ActionPerformed (evt); } }); jPanel1.add(jButton1 , java.awt.BorderLayout.EAST); getContentPane().add(jPanel1, java.awt.BorderLayout .NORTH); pack(); } private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) { // Add your handling code here: helpWindow help = (helpWindow)mother .open("help"); help.loadPage("/configurator/help/module_db2xml_datachooser.html"); } private void elementComboBoxActionPerformed(java.awt.event.ActionEvent evt) { // Add your handling code here: showActiveElement(); } synchronized private void formInternalFrameClosing (javax.swing.event.InternalFrameEvent evt) { // Add your handling code here: mother.close(this.ID); } // Variables declaration - do not modify private javax.swing .JSplitPane theSplitPane; private javax.swing .JPanel upperPanel; private javax.swing .JScrollPane jScrollPane1; private javax.swing .JList sqlList; private javax.swing .JPanel lowerPanel; private javax.swing .JScrollPane jScrollPane2; private javax.swing .JList tableList ; private javax.swing.JPanel jPanel1; private javax.swing .JComboBox elementComboBox ; private javax.swing .JButton jButton1; private JList paramList; private JSplitPane theSecondSplitPane; private JPanel paramPanel; private JScrollPane paramScrollPane ; // End of variables declaration /** * Shows the db-entries for the active Element */ private void showActiveElement () { if (this.getActiveElement() != null) { sqlList.setEnabled(false); this.updateTables(new Vector()); Vector temp_vec = new Vector(); temp_vec.add(this.getActiveElement().getRepetitionStatement()); sqlList.setListData(temp_vec); sqlList.setEnabled(true); sqlList.repaint(); } } /** * Returns the currently selected dbItem */ private SchemaElement getActiveElement() { return (SchemaElement)elementComboBox.getSelectedItem(); } /** * Gets the new data and fills the lists */ synchronized public void setSchemaElement(SchemaElement el) { this.currentElement = el; //build element comboBox elementComboBox .setVisible (false); elementComboBox .removeAllItems(); int counter = 0; int selected = -1; for (Enumeration e = el.getParents().elements(); e.hasMoreElements ();) { SchemaElement curr_el = (SchemaElement)e.nextElement (); if (curr_el.getID().equalsIgnoreCase(el.getID())) { selected = counter ; } elementComboBox.addItem(curr_el); counter++; } if (selected > 0) { elementComboBox.setSelectedIndex (selected); } if (counter <= 0) { //elementComboBox.setEnabled(false); sqlList.setEnabled(false); tableList.setEnabled(false); } else { //elementComboBox.setEnabled(true); Autor: Thomas Schädler 235 Anhang A: Quelltext <xmlizer> configurator sqlList.setEnabled(true); tableList.setEnabled(true); } elementComboBox .setVisible (true); setTitleElementName(el.getRealName()); elementComboBox .repaint(); } /** * Gets the new data and fills the lists */ private void updateTables(Vector tab) { tableList.setEnabled (false ); tableList.setListData(tab); tableList.setEnabled (true); tableList.repaint(); } /** * This method updates the UI if the setupwindow is closed * (and a change in the setup component occured) */ public synchronized void update(configurator conf) { isLoading = true; this.mother = conf; isLoading = false; } /** * A draggable list of ParameterInfos * -> Sends a String-Combination of ParameterInfo.getID:ParameterInfo.getName (as String) */ class DNDListParam extends JList implements DragSourceListener, DragGestureListener { DragSource dragSource = null; /**constructor - initializes the DragSource */ public DNDListParam() { dragSource = new DragSource (); dragSource.createDefaultDragGestureRecognizer(this,DnDConstants.ACTION_COPY,this); } /** a drag gesture has been initiated */ public void dragGestureRecognized(DragGestureEvent event ) { //System.out.println("START > dragGestureRecognized"); ParameterInfo selected = (ParameterInfo)getSelectedValue(); if (selected != null) { StringSelection text = new StringSelection("[-" + selected .getID() + ":" + selected.getName() + "-]"); // as the name suggests, starts the dragging dragSource.startDrag(event,DragSource.DefaultMoveDrop ,text,this); } } //REST UNUSED /**this message goes to DragSourceListener, informing it that the dragging has ended */ public void dragDropEnd(DragSourceDropEvent event) { /*System.out.println("START > dragDropEnd");*/ } /** this message goes to DragSourceListener, informing it that the dragging has entered the DropSite */ public void dragEnter(DragSourceDragEvent event) { /*System.out.println("START > dragEnter");*/ } /** this message goes to DragSourceListener, informing it that the dragging has exited the DropSite */ public void dragExit (DragSourceEvent event) { /*System.out.println("START > dragExit");*/ } /**this message goes to DragSourceListener, informing it that the dragging is currently ocurring over the DropSite */ public void dragOver (DragSourceDragEvent event ) { /*System.out.println("START > dragOver");*/ } /** is invoked when the user changes the dropAction */ public void dropActionChanged(DragSourceDragEvent event) { /*System.out.println("START > dragActionChanged");*/ } } /** * A draggable list of SQLColumninfos * -> Sends a String-Combination of SQLColumnInfo.getID:SQLColumnInfo.getName (as String) */ class DNDListInfo extends JList implements DragSourceListener, DragGestureListener { DragSource dragSource = null; /**constructor - initializes the DragSource */ public DNDListInfo() { dragSource = new DragSource (); dragSource.createDefaultDragGestureRecognizer(this,DnDConstants.ACTION_COPY,this); } /** a drag gesture has been initiated */ public void dragGestureRecognized(DragGestureEvent event) { //System.out.println("START > dragGestureRecognized"); SQLColumnInfo selected = (SQLColumnInfo)getSelectedValue(); if (selected != null) { StringSelection text = new StringSelection("[" + selected.getID () + ":" + selected.getName() + "]"); // as the name suggests, starts the dragging dragSource.startDrag(event,DragSource.DefaultMoveDrop ,text,this); } } //REST UNUSED /**this message goes to DragSourceListener, informing it that the dragging has ended */ public void dragDropEnd(DragSourceDropEvent event) { /*System.out.println("START > dragDropEnd");*/ } /** this message goes to DragSourceListener, informing it that the dragging has entered the DropSite */ public void dragEnter(DragSourceDragEvent event) { /*System.out.println("START > dragEnter");*/ } /** this message goes to DragSourceListener, informing it that the dragging has exited the DropSite */ public void dragExit (DragSourceEvent event) { /*System.out.println("START > dragExit");*/ } /**this message goes to DragSourceListener, informing it that the dragging is currently ocurring over the DropSite */ public void dragOver (DragSourceDragEvent event ) Autor: Thomas Schädler 236 Anhang A: Quelltext <xmlizer> configurator { /*System.out.println("START > dragOver");*/ } /** is invoked when the user changes the dropAction */ public void dropActionChanged(DragSourceDragEvent event) { /*System .out.println("START > dragActionChanged");*/ } } }/* * SchemaContent.java * * Created on 25. Juli 2002, 02:47 * ---------------------------------------------------------------------------* This file is part of <xmlizer>. * * <xmlizer> is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Foobar is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with <xmlizer>; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * ---------------------------------------------------------------------------*/ package configurator; import org.jdom.*; import java.util.*; import javax.swing .*; /** * Represents the content of a SchemaElement * @author [email protected] */ class SchemaContent { protected String id ; //element id protected String mapid; protected String mapinfo ; public SchemaContent(){} public SchemaContent(String id ) { this.id = id; } public SchemaContent(String id ,String mapid,String mapinfo) { this.id = id; this.mapid = mapid; this.mapinfo = mapinfo; } public String getElementID() { return this.id; } public String getMapID() { return this.mapid; } public String getMapInfo () { return this.mapinfo; } /** Cleans the mapinfo of this content */ public void cleanMapping () { this.mapid = null; this.mapinfo = null; //System.out.println(this.tname); } //SETTERS public void setMapID(String id ) { if (id != null) { this.mapid = id; } } public void setMapInfo(String info) { if (info != null) { this.mapinfo = info; } } public String toString() { return "<" + this.id + ">" + this.mapid + ":" + this.mapinfo + "</" + this.id + ">"; } public Element getAsJDOMElement() { Element curr = new Element ("db2xml_content"); if (this.mapid != null) { curr.setAttribute("mapid",this.mapid); } if (this.mapinfo != null) { curr.setAttribute("mapinfo" ,this.mapinfo); } //System.out.println("<" + this.id + ">" + this.mapid + ":" + this.mapinfo + "</" + this.id + ">"); return curr; } } /* * ParameterInfo.java * Autor: Thomas Schädler 237 Anhang A: Quelltext <xmlizer> configurator * Created on 25. Juli 2002, 02:47 * ---------------------------------------------------------------------------* This file is part of <xmlizer>. * * <xmlizer> is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Foobar is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with <xmlizer >; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * ---------------------------------------------------------------------------*/ package configurator; import java.util.*; import org.jdom.*; /** * Represents a ParameterInfo * @author [email protected] */ class ParameterInfo { protected String id ; protected String name; protected String value; public ParameterInfo(String id ,String name,String value ) { this.id = id; this.name = name; this.value = value; } public String getID () { return this.id; } public String getName() { return this.name; } public String getValue() { return this.value; } public String toString() { return this.name + " (" + this.value + ")"; } public Element getAsJDOMElement() { if (this.name == null || this.value == null) //check for validity { return null; } else { Element curr = new Element("db2xml_parameter"); curr.setAttribute("name",this.name); curr.setAttribute("default" ,this.value); return curr; } } } Autor: Thomas Schädler 238 Anhang B: Quelltext <xmlizer> server Anhang B: Quelltext <xmlizer> server /* * Start.java * * Usage: server.start [options] * * Hints: * - if there is no config file, it will be generated * - if port,base or projects are specifed, the config file will be updated * - to use a custom config file (multiple server), specify its name * - command line arguments update the indicated configfile * * Options: * -config <name> Use custom xmlizer.server.config.<name> * -port <portnumber> Start the server on that port (default = 7777) * -base <dir> Directory where the server is running * -projects <dir> Directory where the projects are saved * -webinterface on|off Switch on/off webinterface (default=on) * -refresh on|off Switch on/off continous directory scan (default=off) * -help Show this help screen * * Created on 1. August 2002, 18:59 * ---------------------------------------------------------------------------* This file is part of <xmlizer>. * * <xmlizer> is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Foobar is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the G NU General Public License * along with <xmlizer>; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * ---------------------------------------------------------------------------* http://localhost:7777/htmlizer?project=Simple_Module_DB_Export&db=XML-DB */ package server; import java.util.*; import java.net.*; import java.io.*; /** * Starts the server * @author [email protected] * @version 0.2 */ public class Start extends Thread { private static Vector requests ; private ServerSocket serverSocket; private boolean stop; private int port = 7777; public static final String VERSION = "0.7.1"; public StringBuffer configfilename = new StringBuffer(System .getProperty("user.home") + System.getProperty("file.separator") + "xmlizer.server.config" ); public String homebase = null; public String projectbase = null; private String web = "on"; private String refresh = "off" ; private boolean saveConfig = false; private boolean portSet = false; private boolean baseSet = false; private boolean webSet = false ; private boolean projectSet = false; private boolean nameSet = false; private boolean refreshSet = false; private String customname = null; private Hashtable data = new Hashtable(); public static void main(String [] argv) { new Start(argv); } public Start(String [] argv) { System.out.println("<xmlizer> server " + VERSION); readCommandLine(argv); buildConfigFileName(); if (this.projectSet || this.baseSet || this.portSet || this.webSet || this.refreshSet) //if something is set by command line { System .out.println(" - saving/updating command line data to configuration file"); updatePathData(); } if (this.homebase == null || this.projectbase == null) //not all data available { if (hasPathData()) //read existing file { pathData pd = new pathData(); boolean fileread = pd.readFromFile(configfilename.toString ()); if (pd.isValid()) { System.out.println(" - reading configuration from user home directory"); this.homebase = pd.getHomeDir (); this.projectbase = pd.getProjectDir(); this.web = pd.getWeb(); this.refresh = pd.getRefresh(); Autor: Thomas Schädler 239 Anhang B: Quelltext <xmlizer> server this.port = Integer.parseInt(pd.getPort()); } else { this.homebase = pd.getHomeDir (); this.projectbase = pd.getProjectDir(); this.web = pd.getWeb(); this.refresh = pd.getRefresh(); this.port = Integer.parseInt(pd.getPort()); printUsage(); } } else //ask @ commandline + test + save OR exit { printUsage(); } } //else just start the sever startServer(); } private void buildConfigFileName() { if (this.nameSet) { this.configfilename.append("." + this.customname); } } private void readCommandLine(String [] argv) { for (int i=0;i<argv.length ;i++) { String arg = argv[i]; //System.out.println(i + " ==> " + arg); // options if (arg.startsWith("-")) { if (arg.equalsIgnoreCase("-port")) //load a projectconfiguration { String currarg = argv[i+1]; try { int currport = Integer.parseInt(currarg); this.port = currport ; System.out.println(" - setting port by command line"); this.portSet = true; } catch (NumberFormatException ex) { printUsage (); } } else if (arg.equalsIgnoreCase("-base")) //set the homebase (dir where the server is running) { String currarg = argv[i+1]; if(testPath(currarg)) { this.homebase = currarg; System.out.println(" - setting base directory by command line"); this.baseSet = true; } } else if (arg.equalsIgnoreCase("-projects")) //set the projectbase (dir where the projects are saved) { String currarg = argv[i+1]; if(testPath(currarg)) { this.projectbase = currarg; System.out.println(" - setting project directory by command line" ); this.projectSet = true; } } else if (arg.equalsIgnoreCase("-config")) //set the configname to load { String currarg = argv[i+1]; this.customname = currarg; System.out.println(" - using custom configuration: xmlizer.server.config." + currarg); this.nameSet = true; } else if (arg.equalsIgnoreCase("-webinterface")) //switch webinterface off { String currarg = argv[i+1]; if(currarg.equalsIgnoreCase("on") || currarg.equalsIgnoreCase("off")) { this.web = currarg; System.out.println(" - switching webinterface " + currarg); this.webSet = true; } } else if (arg.equalsIgnoreCase("-refresh")) //switch refresh off { String currarg = argv[i+1]; if(currarg.equalsIgnoreCase("on") || currarg.equalsIgnoreCase("off")) { this.refresh = currarg; System.out.println(" - switching refresh " + currarg); this.refreshSet = true; } } else if (arg.equalsIgnoreCase("-help")) //show command line usage { printUsage(); } } } } private void startServer () { //be sure everything is avaliable what is needed. if (this.homebase != null && !this.homebase.equalsIgnoreCase("") && this.projectbase != null && !this.projectbase .equalsIgnoreCase("")) { requests=new Vector(); try { Autor: Thomas Schädler 240 Anhang B: Quelltext <xmlizer> server serverSocket =new ServerSocket(this.port); this.data.put("homebase",this.homebase ); this.data.put("projectbase",this.projectbase); this.data.put("port",Integer.toString(this.port)); this.data.put("webinterface" ,this.web); this.data.put("refresh" ,this.refresh); System.out.println (" ... starting server"); if (this.port == 7777) { System.out.println(" -> listening on default port " + serverSocket.getLocalPort() + "."); } else { System.out.println(" -> listening on custom port " + serverSocket.getLocalPort() + "."); } System.out.println (" System.out.println (" System.out.println (" System.out.println (" -> -> -> -> webinterface switched proj. dir refresh switched using home directory: using project directory: " " " " + + + + this.web); this.refresh); this.homebase ); this.projectbase); //do it at least once! if (this.refresh.equalsIgnoreCase ("off")) { scanProjectFiles(); } start(); System.out.println ("ready"); } catch(Exception e) { System.out.println ("[E] Error creating ServerSocket: " + e.getLocalizedMessage ()); } } else { printUsage(); } } /** * Checks for existence of pathdata (file) */ private boolean hasPathData() { java.io.File configfile = new java.io.File(configfilename.toString ()); if (configfile.exists()) { return true; } else return false; } /** * Updates the pathdata (or creates them if neccessary) */ private void updatePathData() { if(hasPathData()) //update { //update the xmlizer.server.config pathData pd = new pathData(); pd.readFromFile(configfilename.toString()); if (this.baseSet) { pd.setHomeDir(this.homebase); } else this.homebase = pd.getHomeDir(); if (this.projectSet) { pd.setProjectDir(this.projectbase ); } else this.projectbase = pd.getProjectDir (); if (this.portSet) { String portstr = Integer.toString (this.port); pd.setPort(portstr ); } else this.port = Integer.parseInt(pd.getPort()); if (this.webSet) { pd.setWeb(this.web); } else this.web = pd.getWeb (); if (this.refreshSet) { pd.setRefresh(this.refresh); } else this.refresh = pd.getRefresh(); pd.save(configfilename .toString()); } else { //write the xmlizer.server.config[.<name>] pathData pd = new pathData(); pd.setHomeDir(this.homebase ); pd.setProjectDir (this.projectbase); String portstr = Integer.toString(this.port); pd.setPort(portstr); pd.setWeb(this.web); pd.setRefresh(this.refresh); pd.save(configfilename .toString()); } } /** * Test if the indicated directory a valid directory */ private boolean testPath (String path) { java.io.File isdir = new java.io.File(path); if (isdir.exists()) { return isdir.isDirectory (); } else return false; } /** * Prints the usage message (on console) */ private void printUsage() { System.out.println("\nUsage: server.start [options]"); System.out.println(); System.out.println("Hints:"); System.out.println(" - if there is no config file, it will be generated"); System.out.println(" - if port,base or projects are specifed, the config file will be updated"); System.out.println(" - to use a custom config file (multiple server), specify its name"); Autor: Thomas Schädler 241 Anhang B: Quelltext <xmlizer> server System.out.println(" - command line arguments update the indicated configfile"); System.out.println(); System.out.println("Options:"); System.out.println(" -config <name> Use custom xmlizer.server.config.<name>"); System.out.println(" -port <portnumber> Start the server on that port (default = 7777)"); System.out.println(" -base <dir> Directory where the server is running"); System.out.println(" -projects <dir> Directory where the projects are saved"); System.out.println(" -webinterface on|off Switch on/off webinterface (default=on)"); System.out.println(" -refresh on|off Switch on/off continous directory scan (default=off)" ); System.out.println(" -help Show this help screen."); System.out.println(); System.out.println("Warnings from this start attempt:"); if (this.homebase == null || this.homebase.equalsIgnoreCase("")) { System .out.println(" -> base directory was not set" ); } if (this.projectbase == null || this.projectbase.equalsIgnoreCase("")) { System .out.println(" -> project directory was not set"); } System.exit(0); } public void run() { while(!stop) { try { //optional projectfilesscan for permanent updates (costs much time though) if (this.refresh.equalsIgnoreCase ("on")) { scanProjectFiles(); } ConnectionHandler temp = new ConnectionHandler(this.data); temp.connectionRequest(serverSocket.accept()); requests.add(temp); } catch(Exception e) { System.out.println ("[E] Error accepting request: " + e.getLocalizedMessage()); } } } public void stopListening() { stop = true; } public Vector getRequests() { return requests ; } public static void removeFromUserList(ConnectionHandler ch) { requests.remove (ch); } /** * Scans the project files directory and fill a list with valid dirs */ private void scanProjectFiles() { Hashtable fileHash = new Hashtable(); File prodir = new File((String)this.data.get("projectbase")); if (prodir .exists() && prodir.isDirectory ()) { File[] prodirs = prodir.listFiles(); for(int i = 0;i<prodirs.length;i++) { File temp = prodirs[i]; //must be a valid directory and not start with underscore if (temp.isDirectory() && !temp.getName().startsWith("_")) { fileData fd = new fileData(); fd.setName(temp.getName()); File[] profiles = temp.listFiles(); for(int k=0;k<profiles.length ;k++) { File temp5 = profiles[k]; //must be a valid file if (temp5.isFile()) { fd.addFile(temp5 .getName(),temp5); } } if (fd.hasConfig()) //is a valid project dir { fileHash.put(temp.getName(),fd); } } } } this.data.put("files",fileHash); } /** * Returns an HTML rendition of the given <code>String</code>. This was * written by <a href=mailto:[email protected]>Kimbo Mundy</a>. * @param text A <code>String</code> to be used in an HTML page. * @return A <code>String</code> that quotes any HTML markup * characters. If no quoting is needed, this will be * the same as <code>text</code>. */ public static String htmlEncode(String text) { if (text == null) { return ""; } StringBuffer results = null; char[] orig = null; int beg = 0, len = text.length(); for (int i = 0; i < len; ++i) { char c = text.charAt(i); switch (c) { case 0: case '&': Autor: Thomas Schädler 242 Anhang B: Quelltext <xmlizer> server case '<': case '>': case '"': if (results == null) { orig = text.toCharArray(); results = new StringBuffer(len+10); } if (i > beg) results.append(orig, beg, i-beg); beg = i + 1; switch (c) { default: // case 0: continue; case '&': results.append("&amp;"); break; case '<': results.append("&lt;" ); break; case '>': results.append("&gt;" ); break; case '"': results.append("&quot;"); break; } break; } } if (results == null) return text; results.append(orig, beg, len-beg); return results.toString(); } }/* * ConnectionHandler.java * * Created on 1. August 2002, 18:59 * ---------------------------------------------------------------------------* This file is part of <xmlizer>. * * <xmlizer> is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Foobar is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with <xmlizer>; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * ---------------------------------------------------------------------------*/ package server; import java.net.*; import java.io.*; import java.util.*; /** * Handles the Connection * @author [email protected] * @version 0.2 */ public class ConnectionHandler extends Thread implements HttpRequestListener { private Socket socket; private Request request; private Response response; private boolean ready; private boolean isDataRequest = false; private Hashtable data; private LookupTable queryString; private ProjectManager manager ; private boolean isXMLOutput = false ; private boolean isDataOutput = false; private String errorMessage = "unspecified error"; public ConnectionHandler (Hashtable data) { this.data = data; } public void connectionRequest(Socket socket) { //System.out.println("[I] New request."); this.socket=socket; try { response = new Response(socket); } catch(Exception e) { System .out.println("[E] Error creating Response."); } //System.out.println("[I] Response object created."); request=initRequest(); System.out.println("[I] Request(" + request.getId() + ", " + request.getResource() + ") object created."); ready=true; start(); } private Request initRequest() { try { BufferedReader in=new BufferedReader(new InputStreamReader(socket.getInputStream())); String line ; while((line=in.readLine())!="") { Autor: Thomas Schädler 243 Anhang B: Quelltext <xmlizer> server StringTokenizer token=new StringTokenizer(line); token.nextToken(); return new Request (token.nextToken().substring(1)); } } catch(Exception e) { System .out.println("[E] Error creating Request."); } return null; } public void run() { while(ready) { StringBuffer buffer = new StringBuffer(); try { buffer = dispatchRequest(request.getResource()); } catch(Exception e) { this.errorMessage = e.getMessage(); if (request != null) { if (!this.errorMessage.equalsIgnoreCase ("stealth" )) { System.out.println("[E] Error loading requested resource(" + request.getResource()); } } if (request != null && ((String)this.data.get("webinterface")).equalsIgnoreCase("on")) { System.out.println("[I] Sending error response."); try { buffer = processFileRequest("error.html" ); } catch (Exception ex ) { System.out.println("[E] Error sending error request, PLEASE CHECK THE PATHs!"); } } ready=false; Start.removeFromUserList(this); } finally { if (((String )this.data.get("webinterface")).equalsIgnoreCase("on") || this.isDataRequest) { if(response != null && !this.errorMessage.equalsIgnoreCase("stealth") && ((String)this.data.get("webinterface")).equalsIgnoreCase ("on") || (this.isDataOutput && request != null) ) { if (this.isDataOutput) { System .out.println("[I] Sending data output."); } if (this.isXMLOutput ) { response.formatResponseXML (buffer); } else { response.formatResponseHTML(buffer); } } } Start.removeFromUserList(this); try { socket.close(); } catch(Exception e) { System.out.println("[E] Error closing socket: " + e.getLocalizedMessage()); } request=null; response=null; } } } /** * Returns the project details (HTML formated) */ private String getProjectDetails() { String sel_pro = this.queryString.getValue("xmlizerproject"); Hashtable pro_data = (Hashtable )this.data.get("files"); fileData temp = (fileData)pro_data.get(sel_pro); StringBuffer buff = new StringBuffer (); // show the projct name buff.append("<h3><font color=\"white \">project details: "); buff.append(temp.getName()); buff.append("</font></h3><br><ul>"); if (this.manager != null) { //checkUsedDatabases dataItem module = this.manager.getProjectData().getInitialByKey("module" ); if (module.getValue().equalsIgnoreCase("Simple DB Export" )) { //smdbe_items for smdbe module buff.append("<li><font color=\"white\">"); buff.append("Mapping module: " + module.getValue ()); buff.append("</font></li>"); Vector dbs = this.manager.getProjectData().getSimpleItems(); for (Enumeration e = dbs.elements (); e.hasMoreElements();) { dbItem currentdb = (dbItem)e.nextElement(); //link params String params = "?xmlizerproject=" + temp.getName() + "&xmlizerdb=" + currentdb.getName() + "\">"; //output links buff.append("<li><font color= \"white\">"); buff.append(temp.getName() + " :: " + currentdb .getName()); Autor: Thomas Schädler 244 Anhang B: Quelltext <xmlizer> server buff.append(" [ <a href=\"xmlizer" + params + "XML</a> ] "); buff.append(" [ <a href=\"htmlizer" + params + "HTML</a> ] "); buff.append("</font></li>"); } buff.append("</ul>"); } else if (module.getValue().equalsIgnoreCase("Database to XML")) { //project detail data (module and xsd filename buff.append("<li><font color=\"white\">"); buff.append("Mapping module: " + module.getValue ()); buff.append("</font></li>"); //link params String params = "?xmlizerproject=" + temp.getName() + "\">"; //output links buff.append("<li><font color=\"white\">"); buff.append(temp.getName()); buff.append(" [ <a href=\"xmlizer" + params + "XML</a> ] " ); buff.append(" [ <a href=\"htmlizer" + params + "HTML</a> ] "); buff.append("</font></li>"); buff.append("</ul>"); //add the parameters and stuff Hashtable paraHash = this.manager.getProjectData ().DB2XMLgetmapping().getParameters(); //print form header if neccessary if (paraHash .size() > 0) { buff.append("<br><font color= \"white\">"); buff.append("<b>Custom query parameters:</b><br>" ); buff.append("</font><br>"); buff.append("<form action='customizer' method='GET'>"); buff.append("<input type='hidden' type='text' name='xm lizerproject' value='"+ temp.getName() +"'>"); buff.append("<table>"); buff.append("<tr><th>Name</th><th>Default value</th></tr>"); } else { buff.append("<br><font color= \"white\">"); buff.append("This project does not provide parameters.<br>No custom queries possible."); buff.append("</font>"); } for (Enumeration e = paraHash.elements ();e.hasMo reElements ();) { ParameterInfo currentInfo = (ParameterInfo)e.nextElement(); buff.append("<tr><td><font color=\"white\"><b>"+ currentInfo.getName() +":</b></font></td><td><input type='text' name='"+ currentInfo.getName() +"' size='25' maxlength='256' value='"+ currentInfo .getValue() +"'></td></tr>"); } //print form footer & buttons if neccessary if (paraHash .size() > 0) { buff.append("<tr><td><b>Outpu t format:</b></td>"); buff.append("<td><input type='radio' name='xmlizerformat' checked value='xmlizer'>[ XML ]</td></tr>" ); buff.append("<tr><td>&nbsp;</td><td><input type='radio' name='xmlizerformat' value='htmlizer'>[ HTML ]</td></tr>"); buff.append("<tr><td>&nbsp;</td><td><input type='submit' value='Query'>&nbsp;<input type='reset' value='Reset'></td></tr>"); buff.append("<table></form>"); } } } else { buff.append ("<li><font color=\"white\">Due to configuration problems, this project is currently unavailable.</a></font></li>"); } return buff.toString (); } /** * Returns a HTML formated lis t of all available projects */ private String getProjectsAsHTML() { StringBuffer buff = new StringBuffer (); buff.append("<h3><font color=\"white \">available projects:</font></h3><br><ul>"); Hashtable projectFiles = (Hashtable)this.data.get("files"); for(Enumeration en = projectFiles.elements();en.hasMoreElements();) { fileData temp = (fileData)en.nextElement(); buff.append ("<li><font color=\"white\"><a href= \"index.html?xmlizerproject="); buff.append (temp.getName()); buff.append ("\">"); buff.append (temp.getName()); buff.append ("</a></font></li>"); } buff.append("</ul>"); return buff.toString (); } /** * Parses a line and replaces the tokens (patterns) as specified in the html-files * tokens: %%tokenname%% -> will be substituted with the output of the given method * adding more tokens and editing (customizing) of the html output is absolutly recommended * but always include the credits on each pages footer, thanx a lot */ private String parseLine (String line) { StringBuffer result = new StringBuffer(); java.util.StringTokenizer tokenizer = new java.util.StringTokenizer(line); while (tokenizer.hasMoreTokens()) { String token = tokenizer.nextToken(); if (token.equalsIgnoreCase("%%date%%" )) { token = new java.util.Date().toString(); //show the actual date and time } if (token.equalsIgnoreCase("%%version%%")) { token = Start.VERSION; //show the servers version } if (token.equalsIgnoreCase("%%projects%%")) { Autor: Thomas Schädler 245 Anhang B: Quelltext <xmlizer> server token = getProjectsAsHTML(); //show a list of li nked projects ( -> detail link) } if (token.equalsIgnoreCase("%%details%%")) { token = getProjectDetails(); //show the selected projects details (-> query mask) } if (token.equalsIgnoreCase("%%debug%%")) { token = this.queryString.toHTML(); //add debug information (GET data) } if (token.equalsIgnoreCase("%%error%%")) { token = this.errorMessage; //set the error message } result .append(token + " "); } return result.toString() + "\n"; } /** * Dispatches a request */ private StringBuffer dispatchRequest(String request) throws Exception { //returns the method to check //and saves the variables in global queryString (LookupTable) String method = parseQueryString(request); if (method .equalsIgnoreCase("xmlizer")) //return xml { this.isDataRequest = true; return processXMLRequest(true); } else if (method .equalsIgnoreCase("htmlizer")) //return html { this.isDataRequest = true; return processHTMLRequest(); } else if (method .equalsIgnoreCase("customizer")) //return either xml or html! { String sel_format = this.queryString.getValue("xmlizerformat"); if (sel_format != null && sel_format.equalsIgnoreCase("xmlizer")) { this.isDataRequest = true; return processXMLRequest(true); } else if (sel_format != null && sel_format.equalsIgnoreCase("htmlizer")) { this.isDataRequest = true; return processHTMLRequest(); } else { throw new Exception("The requested format " + sel_format + "is not valid."); } } else { if (((String)this.data.get("webinterface")).equalsIgnoreCase("on")) { //processInterfaceRequest this.isDataRequest = false; return processFileRequest(method); } else { this.isDataRequest = true; throw new Exception("stealth"); } } } /** * Reads the queryString and extracts all parameters not starting with xmizer */ private Hashtable getMappingParameters() { Hashtable xmlParams = new Hashtable(); //key=name, value=value String[] allNames = this.queryString .getNames(); String[] allValues = this.queryString.getValues(); for (int i=0;i<allNames.length;i++) { String curr_name = allNames [i]; if (!curr_name.startsWith("xmlizer")) { String curr_value = allValues[i]; xmlParams.put(curr_name ,curr_value); } } return xmlParams; } /** * Processes a XML Request: xmlizer... * Sends back XML-data */ public StringBuffer processXMLRequest(boolean isXML) throws Exception { //as error message, make a readFile("error.html"); StringBuffer xmloutput = null; String sel_pro = this.queryString.getValue("xmlizerproject"); String db_pro = this.queryString.getValue ("xmlizerdb"); Hashtable pro_data = (Hashtable )this.data.get("files"); if (sel_pro != null && pro_data .containsKey(sel_pro)) { // a project request must be called fileData f_data = (fileData )pro_data.get(sel_pro); boolean ok = prepareProject (f_data); //prepare the data for this project -> manager if (ok) { dataItem module = this.manager.getProjectData().getInitialByKey ("module"); if (module.getValue().equalsIgnoreCase ("Simple DB Export") && db_pro != null) { xmloutput = this.manager.getXML_SMDBE(db_pro ); this.isDataOutput = true; } else if (module.getValue().equalsIgnoreCase ("Database to XML")) { String base = (String)this.data.get("projectbase" ) + System .getProperty("file.separator") + sel_pro + System.getProperty ("file.separator"); Autor: Thomas Schädler 246 Anhang B: Quelltext <xmlizer> server Hashtable mappingParameters = getMappingParameters(); //key=name,value=value of user params (no xmlizer...) //System.out.println(mappingParameters.size()); xmloutput = this.manager.getXML_DB2XML(base,mappingParameters); this.isDataOutput = true; } } } //debug info only if (xmloutput == null) { throw new Exception("unspecified xml processing error"); } this.isXMLOutput = true; return xmloutput; } /** * Processes a HTML Request: htmlizer... * (is a wrapper for XML only to output the data HTML-formated to the browser */ public StringBuffer processHTMLRequest() throws Exception { StringBuffer xmloutput = processXMLRequest(false); StringBuffer htmloutput = new StringBuffer("<html>\n<head><title>xmlizer server html output</title></head>\n\n<body bgcolor= \"#215682\" text=\"white\" link=\"white\" vlink=\"white\" alink=\"white \"><h3>&lt;xmlizer&gt; server html output</h3><br><pre>\n"); String htmloutputstr = Start.htmlEncode(xmloutput.toString()); htmloutput .append(htmloutputstr ); htmloutput .append("</pre><hr color=\"white\"><br><div align=\"left \"><font color= \"white\"><a href=\"index.html\">back to the index</a></font></div><div align=\"right\"><font color=\"white \">(c) 2002 &lt;xmlizer&gt; server/configurator freely available @ <a href=\"http://www.e-freak.ch/xmlizer/ \">e-freak</a> Spread the data!</font></div></body></html>"); this.isXMLOutput = false; //set the right content-type for the output return htmloutput; } /** * prepare the data for a project */ private boolean prepareProject (fileData fdata ) throws Exception { String projectpath = fdata .getConfigFile().toString (); //cannont be empty or null! //System.out.println("PATH: " + projectpath); this.manager = new ProjectManager(projectpath); //System.out.println("DATA:\n" + this.manager.getProjectData().getAsXMLText()); if (this.manager != null) { return true; } else throw new Exception ("projectdata invalid"); } /** * Processes a file request: index.html?bla=bla&bla=bla **/ public synchronized StringBuffer processFileRequest(String method ) throws Exception { //decode the resouce string and do the right thing //url decoding? class? //if (method.equalsIgnoreCase("index.html") || method.equalsIgnoreCase("error.html")) { if (method.equalsIgnoreCase ("index.html")) //check for parameters on the index { String sel_pro = this.queryString .getValue("xmlizerproject"); Hashtable pro_data = (Hashtable)this.data.get("files"); if (sel_pro != null && pro_data.containsKey (sel_pro)) { // a project request must be called fileData f_data = (fileData)pro_data.get(sel_pro); boolean ok = prepareProject(f_data ); //prepare the data for this project if (ok) { method = "project.html"; } } }//else try to reach the called file (for custom files added by users try { FileReader fReader = new FileReader( (String )this.data.get("homebase") + System.getProperty("file.separator") + "html" + System.getProperty("file.separator") + method //her comes the resolved ressource, only the filename tos substitute ); BufferedReader reader = new BufferedReader(fReader); StringBuffer buffer = new StringBuffer (); String line; while((line = reader.readLine())!=null) { line = parseLine(line); buffer.append(line); } fReader.close(); return buffer; } catch(Exception e) { throw new Exception(e.getLocalizedMessage()); } //} //else throw new Exception("unknown command"); } /** * Parses the incoming querystring and extracts the parameters to the global * queryString (LookupTable) and return the method -string (eg: xmlizer?...)=> xmlizer */ private String parseQueryString(String query) { //remove the stuff before the (optional) ? String method; String resolvedQuery ; int questionMark = query.indexOf("?"); { if (questionMark < 0) //no parameters { Autor: Thomas Schädler 247 Anhang B: Quelltext <xmlizer> server resolvedQuery = new String(); method = query; } else { resolvedQuery = query.substring(questionMark+1,query.length()); method = query.substring(0,questionMark); } } //parse the parameters and fill the queryString CgiParser parser = new CgiParser(resolvedQuery ,"&","="); this.queryString = parser.parse (); return method; } }/* * Response.java * * Created on 1. August 2002, 18:59 * ---------------------------------------------------------------------------* This file is part of <xmlizer>. * * <xmlizer> is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Foobar is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with <xmlizer>; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * ---------------------------------------------------------------------------*/ package server; import java.io.PrintWriter; import java.net.Socket; /** * Represents a Response (and the methods to print the result) * @author [email protected] * @version 0.2 */ public class Response { private PrintWriter out; public Response(Socket socket) throws Exception { try { out=new PrintWriter(socket.getOutputStream ()); } catch(Exception e) { throw new Exception(); } } public void formatResponseHTML (StringBuffer data) { String header="HTTP/1.1 200 OK\nContent-Type: text/html\n\n"; StringBuffer newResponse=new StringBuffer (); try { newResponse .append(header); newResponse .append(data.toString ()); write(newResponse); } catch(Exception e) { System .out.println("[E] Error sending Response: " + e.getLocalizedMessage()); } } public void formatResponseXML(StringBuffer data) { String header="HTTP/1.1 200 OK\nContent-Type: text/xml\n\n"; StringBuffer newResponse=new StringBuffer (); try { newResponse .append(header); newResponse .append(data.toString ()); write(newResponse); } catch(Exception e) { System .out.println("[E] Error sending Response: " + e.getLocalizedMessage()); } } public void write(StringBuffer data ) throws Exception { try { out.print(data.toString()); out.flush(); } catch(Exception e) { throw new Exception(); } } }/* * HttpRequestListener.java * * Created on 1. August 2002, 18:59 * ---------------------------------------------------------------------------* This file is part of <xmlizer>. * * <xmlizer> is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * Autor: Thomas Schädler 248 Anhang B: Quelltext <xmlizer> server * Foobar is distributed in the hope that it will be useful, * but WITHO UT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with <xmlizer>; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * ---------------------------------------------------------------------------*/ package server; import java.net.Socket; /** * Listents for HTTP Requests * @author [email protected] * @version 0.2 */ public interface HttpRequestListener { public void connectionRequest(Socket socket); }/* * Request.java * * Created on 1. August 2002, 18:59 * ---------------------------------------------------------------------------* This file is part of <xmlizer>. * * <xmlizer> is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Foobar is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with <xmlizer>; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * ---------------------------------------------------------------------------*/ package server; /** * Represents a Request (id and querystring) * @author [email protected] * @version 0.2 */ public class Request { private String id; private String resource; public Request(String resource ) { id=generateId(); if (resource.equalsIgnoreCase(new String())) { this.resource = "index.html"; } else this.resource = resource; } public String generateId () { Double id=new Double (Math.random()); return String.valueOf(id); } public String getId () { return id; } public String getResource() { return resource; } }/* * pathData.java * * This projectData container contains all neccessary methods to deal * with the projectData management * * Created on 5. April 2002, 16:30 * ---------------------------------------------------------------------------* This file is part of <xmlizer>. * * <xmlizer> is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Foobar is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with <xmlizer>; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * ---------------------------------------------------------------------------*/ package server; import import import import java.io.*; java.util.*; java.lang.*; org.jdom.*; Autor: Thomas Schädler 249 Anhang B: Quelltext <xmlizer> server import org.jdom.input.SAXBuilder; import org.jdom.output.XMLOutputter; /** * Represents the pathData for the server and all other config-infos * [email protected] * @version */ public class pathData { public static String XMLFILEROOT = "xmlizerconfig" ; private private private private private String String String String String homedir = null; projectdir = null; port = new String("7777"); web = "on"; refresh = "off" ; //CONSTRUCTOR //----------------------------------------------------------------------------------------------/** * Creates new pathData (Constructor) */ public pathData() { //init here if neccessary } //GET AND SET //----------------------------------------------------------------------------------------------//homedir public String getHomeDir() { return homedir; } public void setHomeDir(String dir) { this.homedir = dir; } //port public String getPort() { return this.port; } public void setPort(String port) { this.port = port; } //projectdir public String getProjectDir() { return this.projectdir; } public void setProjectDir(String dir) { this.projectdir = dir; } public String getWeb() { return this.web; } public void setWeb(String web) { this.web = web; } public String getRefresh () { return this.refresh; } public void setRefresh(String refresh) { this.refresh = refresh; } //STRING REPRESENTATION //----------------------------------------------------------------------------------------------public String toString() { StringBuffer result = new StringBuffer("FULL PATHDATA >>"); result.append("\nWEB >> " + this.web); result.append("\nREFRESH >> " + this.refresh); result.append("\nPORT >> " + this.port); result.append("\nHOME-DIR >> " + this.homedir); result.append("\nPROJECT-DIR >> " + this.projectdir ); return result.toString(); } //XML REPRESENTATION //----------------------------------------------------------------------------------------------public boolean isValid() { if ( this.homedir != null && !this.homedir.equalsIgnoreCase("") && this.projectdir != null && !this.projectdir.equalsIgnoreCase ("") && this.port != null && this.web != null && !this.web.equalsIgnoreCase("") && this.refresh != null && !this.refresh.equalsIgnoreCase("") ) { return true; } else return false; } /** * Checks the doctype of the XML-File (just to be sure to read the right information) */ private boolean checkDocType(DocType dt,String rootelement) { if (dt.getElementName().equalsIgnoreCase(rootelement)) { return true; } else { return false; Autor: Thomas Schädler 250 Anhang B: Quelltext <xmlizer> server } } /* * Reads an XML file (which must be of type xmlizer.project.config.dtd) and * fills all information in the projectdata * * @param The filename as String * @param The logWindow (to indicate errors etc...) */ synchronized public boolean readFromFile (String filename) { boolean docOK = false; try { SAXBuilder builder = new SAXBuilder(false); //true -> validating against dtd Document jdoc = builder.build(filename); DocType docType = jdoc.getDocType(); docOK = checkDocType(docType,XMLFILEROOT); if (docOK) { //get the root Element root = jdoc.getRootElement(); java.util.List itemlist = root.getChildren("path"); Iterator item_iter = itemlist.iterator (); while (item_iter.hasNext()) { Element path_item = (Element) item_iter .next(); if (path_item.getAttributeValue("description").equalsIgnoreCase("home")) { this.homedir = path_item.getTextTrim(); //System.out.println("HOME: " + path_item.getTextTrim()); } else if (path_item.getAttributeValue("description").equalsIgnoreCase("project")) { this.projectdir = path_item.getTextTrim(); //System.out.println("PROJECT: " + path_item.getTextTrim()); } else if (path_item.getAttributeValue("description").equalsIgnoreCase("port")) { this.port = path_item.getTextTrim(); //System.out.println("PORT: " + path_item.getTextTrim()); } else if (path_item.getAttributeValue("description").equalsIgnoreCase("web" )) { this.web = path_item .getTextTrim(); //System.out.println("WEBINTERFACE: " + path_item.getTextTrim()); } else if (path_item.getAttributeValue("description").equalsIgnoreCase("refresh")) { this.refresh = path_item.getTextTrim(); //System.out.println("REFRESH: " + path_item.getTextTrim()); } } return true; } else { //System.out.println("DOC NOT OK"); return false ; } } catch (JDOMException e) { //System.out.println("JDOM Exception: " + e.getMessage()); return false; } } /** * Return the data as String */ public String getAsXMLText() { Document jdoc = this.getAsXMLDocumentJDOM (); org.jdom.output .DOMOutputter outp = new org.jdom.output.DOMOutputter(); XMLOutputter fmt = new XMLOutputter(" return fmt.outputString(jdoc); ",true); } /** * Return the data as XML Document (org.w3c.dom.Document) */ public org.w3c.dom.Document getAsXMLDocumentW3C() { Document jdoc = this.getAsXMLDocumentJDOM (); org.jdom.output .DOMOutputter outp = new org.jdom.output.DOMOutputter(); try { org.w3c.dom.Document result = outp.output(jdoc); return result; //and return the result } catch (JDOMException e) { System .out.println("DOM Serializer error for debug output!"); return null; } } /** * Return the data as XML Document org.jdom.Document */ public Document getAsXMLDocumentJDOM() { //MAKE DOCTYPE DocType docType = new DocType(XMLFILEROOT,null); Element root = new Element (XMLFILEROOT); Element init_item1 = new Element("path").setText(this.homedir); init_item1 .setAttribute("description","home"); root.addContent (init_item1 ); Element init_item2 = new Element("path").setText(this.projectdir); init_item2 .setAttribute("description","project"); root.addContent (init_item2 ); Element init_item3 = new Element("path").setText(this.port); Autor: Thomas Schädler 251 Anhang B: Quelltext <xmlizer> server init_item3 .setAttribute("description","port"); root.addContent (init_item3 ); Element init_item4 = new Element("path").setText(this.web); init_item4 .setAttribute("description","web"); root.addContent (init_item4 ); Element init_item5 = new Element("path").setText(this.refresh); init_item5 .setAttribute("description","refresh"); root.addContent (init_item5 ); Document doc = new Document(root,docType); return doc; //and return the doc } /** * save the config */ public void save(String path) { org.jdom.Document xmldata = getAsXMLDocumentJDOM(); org.jdom.output .XMLOutputter fmt = new org.jdom.output.XMLOutputter(" ",true); try { //file stuff java.io.File outputFile = new java.io.File(path); java.io.FileOutputStream outputStream = new java.io.FileOutputStream(outputFile); java.io.OutputStreamWriter out = new java.io.OutputStreamWriter(outputStream,"UTF8"); fmt.output(xmldata,out); out.close(); } catch (java.io.IOException ex) { System .out.println("SAVE ERROR: " + ex.toString ()); } } }/* * XMLSchemaParser.java * * This class parsers a XML Schema and generates all neccessary info for * using this XML Schema (instance generator, tree-view and element info) * * Created on 17. Juni 2002, 09:02 * ---------------------------------------------------------------------------* This file is part of <xmlizer>. * * <xmlizer> is f ree software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Foobar is dist ributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with <xmlizer>; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * ----------------------------------------------------------------------- ----*/ package server; import import import import java.util.*; javax.swing .*; javax.swing .tree.*; org.jdom.*; /** * Parses an XML Schema * @author [email protected] * @version 0.2 */ public class XMLSchemaParser { private ProjectManager mother; private Document doc; private JTree tree = null; //Hashtable for saving info-lists private Hashtable xml_elements = new Hashtable(); private Hashtable xml_types = new Hashtable(); //little global helpers private String rootelement = null; private DefaultMutableTreeNode topNode = null; private Hashtable loadedSQL = null; private Hashtable loadedReps = null; private Hashtable loadedContent = null; /** Creates new XMLSchemaParser */ public XMLSchemaParser(ProjectManager conf) { this.mother = conf; } /** * Returns a JTree representing this XML Schema as browsable tree */ public JTree getTree() { return tree; } /** * Returns an instance document (test-output) */ public Document getInstance() { return this.instance ; //and return the doc } //INSTANCE GENERATION //----------------------------------------------------------------------------------------------- Autor: Thomas Schädler 252 Anhang B: Quelltext <xmlizer> server private private private private private private Document instance; Element DocumentRoot; boolean rootSet; Hashtable madeSQLs; //key = sqlid, value = SQLStatement Hashtable madeSQLsCurrentRow; //key = sqlid, value = currentRow Hashtable userParams; public void buildInstance(Hashtable userParams) { instance = null; DocumentRoot = null; rootSet = false ; this.userParams = userParams; madeSQLs = new Hashtable(); //key = sqlid, value = SQLStatement //all_current_ids = new Vector(); madeSQLsCurrentRow = new Hashtable(); //key = sqlid, value = currentRow for (Enumeration e = this.topNode.children(); e.hasMoreElements();) { DefaultMutableTreeNode dmtr = (DefaultMutableTreeNode)e.nextElement (); try { makeInstance (DocumentRoot,null,dmtr); } catch(Exception ex) { return; } } if (DocumentRoot != null) { instance = new Documen t(DocumentRoot); } } // parent=JDOMElement, lastParentElement=parental_SchemaElement, current=current_DefaultMutableTreeNode private void makeInstance(Element parent ,SchemaElement lastParentElement,DefaultMutableTreeNode current) throws Exception { if (current == null) { return; } //failsafe //get the schemaelement of the current node -> curse SchemaElement curse = (SchemaElement )current.getUserObject(); //check for the root -element (as defined in the mapping - do something only if found) if (!rootSet && curse.getRealName().equalsIgnoreCase(mother.getProjectData().DB2XMLgetmapping().getRootElement())) { //insert the document root as indicated, can have no repetition (root!) DocumentRoot = new Element(curse .getRealName()); prepareSQLStatements(curse.getSQLStatements()); processCurrentElement(DocumentRoot,null,curse); rootSet = true; } //if the current schemaelement is valid and the root -> start building if (curse.isRefresh() && rootSet) { prepareSQLStatements(curse.getSQLStatements()); //process this element (builds it) if (curse.getRepetition() != null) //if this element has a repetition sql statement { //get the maximum allowed repetition value (maxOccurs for this Element) int max = ((Integer)curse.getOccurrence().getMaxOccurs()).intValue(); //get the data assocciated w ith the element's repetition String mapid_for_rep = curse .getRepetition(); Hashtable sql_result = (Hashtable )madeSQLs.get(mapid_for_rep); //check for the maximum, if more then just cut it there so it will b e valid int sqlmax = ((Integer)sql_result .get("rows")).intValue(); if (sqlmax < max) { max = sqlmax; } //adjust the max for maxOccurs //finally do it for each DB-row for (int i=0;i<max;i++) { Element this_element = new Element(curse.getRealName()); processCurrentElement(this_element ,parent,curse); if (parent == null) //root set, but no parent -> this is the root element! { parent = DocumentRoot; //do the same for all children for (Enumeration e = current.children(); e.hasMoreElements();) { makeInstance(parent,curse,(DefaultMutableTreeNode)e.nextElement()); } } else // this is a normal element (sub-node (or more sub-sub-...) of the rootelement) { parent.addContent(this_element ); //do the same for all children for (Enumeration e = current.children(); e.hasMoreElements();) { makeInstance(this_element,curse ,(DefaultMutableTreeNode)e.nextElement()); } } //update the row_counter for other statements of this element int row_counter = ((Integer)madeSQLsCurrentRow.get(mapid_for_rep )).intValue() + 1; //System.out.println(curse.getRealName() + " >>" + row_counter); madeSQLsCurrentRow.put(mapid_for_rep,new Integer(row_counter)); } } else //no repetition statement and no minimum, so skip it (if it is not the root) { /* special treatment for the root node! */ if (curse.getRealName().equalsIgnoreCase(mother.getProjectData().DB2XMLgetmapping().getRootElement())) { Element this_elemen t = new Element(curse.getRealName()); processCurrentElement(this_element ,parent,curse); if (parent == null) //root set, but no parent -> this ist the root element! { parent = DocumentRoot; //do the same for all children for (Enumeration e = current.children(); e.hasMoreElements();) { makeInstance(parent,curse,(DefaultMutableTreeNode)e.nextElement()); } Autor: Thomas Schädler 253 Anhang B: Quelltext <xmlizer> server } else // this is a normal element (sub-node (or more sub-sub-...) of the rootelement) { parent.addContent(this_element ); //do the same for all children for (Enumeration e = current.children(); e.hasMoreElements();) { makeInstance(this_element,curse ,(DefaultMutableTreeNode)e.nextElement()); } } } // has a minOccurence of more than 0 but no repetition -> make it at least an empty element else if (curse.getOccurrence ().getMinOccurs ().intValue() > 0) { Element this_e lement = new Element(curse.getRealName()); processCurrentElement(this_element ,parent,curse); parent.addContent(this_element); //do the same for all children for (Enumeration e = current.children(); e.hasMoreElements();) { makeInstance(this_element ,curse,(DefaultMutableTreeNode )e.nextElement()); } } } } else //just go on without doing something (no buildup for those elements) { //do the same for all children for (Enumeration e = current.children (); e.hasMoreElements();) { makeInstance (parent,curse,(DefaultMutableTreeNode)e.nextElement ()); } } } private void processCurrentElement(Element el ,Element parent ,SchemaElement sch) throws Exception { //fill in the content if (sch.getContent() != null && sch.getContent ().getMapID() != null) //has content { SchemaContent cont = sch.getContent(); if (cont.getMapID() != null && cont.getMapInfo() != null) { //get the data and fill the attribute String mapid = cont.getMapID (); //the ID String mapinfo = cont.getMapInfo(); //the tableName int currentRow = ((Integer)madeSQLsCurrentRow.get(mapid)).intValue(); Hashtable data = (Hashtable)madeSQLs.get(mapid); //get the hash-data from the list if (data == null) { throw new Exception("No data for referenced sql with id="+mapid+" found!"); } Vector colnames = (Vector)data.get("columnname"); int col = 0; for (Enumeration en = colnames.elements(); en.hasMoreElements();) { String currname = (String)en.nextElement(); if (currname.equalsIgnoreCase (mapinfo)) { break; } col++; } String info[][] = (String[][])data.get("table"); String result = info[col][currentRow]; el.setText(result); } else if (cont.getMapID () != null && cont.getMapInfo() == null) { //FIXME //here comes the result of a simple statement //which has only a mapid //get the data and fill the attribute String mapid = cont.getMapID (); //the ID int currentRow = ((Integer)madeSQLsCurrentRow.get(mapid)).intValue(); Hashtable data = (Hashtable)madeSQLs.get(mapid); //get the hash-data from the list if (data == null) { throw new Exception("No data for referenced sql with id="+mapid+" found!"); } String info[][] = (String[][])data.get("table"); String result = info[0][0]; el.setText(result); } else { /*/dev/null*/} } //fill the attributes with the apropriate values for (Enumeration e = sch.getAttributes().elements(); e.hasMoreElements();) { SchemaAttribute att = (SchemaAttribute)e.nextElement (); //System.out.println(att.getName() + " >>> " + att.getUse() + " >>>" + att.getMapID()); if (att.getUse().equalsIgnoreCase("prohibited")) { //mother.getLog().addWarning("In element <" + sch.getRealName() + "> an attribute " + att.getName() + " is PROHIBITED but has a value! Skipping..."); } else if (att.getMapID() == null && att.getUse().equalsIgnoreCase("required")) //req. but not there -> tell the user { //mother.getLog().addWarning("In element <" + sch.getRealName() + "> an attribute " + att.getName() + " is REQUIRED but has no value."); } else if (att.getMapID() != null && att.getMapInfo() != null) { //get the data and fill the attribute String mapid = att.getMapID(); //the ID String mapinfo = att.getMapInfo(); //the tableName //mother.getLog().addDebug("Query: "+ mapid+":"+mapinfo); int currentRow = ((Integer)madeSQLsCurrentRow.get(mapid)).intValue(); Hashtable data = (Hashtable)madeSQLs.get(mapid); //get the hash-data from the list if (data == null) { throw new Exception("No data for id="+mapid +" found!" ); } Vector colnames = (Vector)data.get("columnname"); int col = 0; for (Enumeration en = colnames.elements(); en.hasMoreElements();) { String currname = (String)en.nextElement(); if (currname.equalsIgnoreCase (mapinfo)) { Autor: Thomas Schädler 254 Anhang B: Quelltext <xmlizer> server break; } col++; } String info[][] = (String[][])data.get("table"); String result = info[col][currentRow]; el.setAttribute(att.getName(),result); } else if (att.getMapID() != null && att.getMapInfo() == null) { //here comes the result of a simple statement //which has only a mapid //get the data and fill the attribute String mapid = att.getMapID(); //the ID //mother.getLog().addDebug("Query: "+ mapid); int currentRow = ((Integer)madeSQLsCurrentRow.get(mapid)).intValue(); Hashtable data = (Hashtable)madeSQLs.get(mapid); //get the hash-data from the list if (data == null) { throw new Exception("No data for id="+mapid +" found!" ); } String info[][] = (String[][])data.get("table"); String result = info[0][0]; el.setAttribute(att.getName(),result); } else { /*/dev/null*/} } } private Vector prepareSQLStatements (Vector vec) throws Exception { if (vec == null) { return new Vector (0); } //check for fail Vector res = new Vector(); for (Enumeration e = vec.elements(); e.hasMoreElements();) { SQLStatement current = (SQLStatement)e.nextElement(); String current_id = current.getID(); //System.out.println("MAKING : " + current_id); dbItem used_db_item = mother.getProjectData().getDBByName (current.getDB()); //System.out.println(" dbItem -> " + used_db_item); Hashtable sql_result = null; try { //System.out.println(" Query -> " + current.getSQL()); String resolvedQuery = resolveQuery(current.getSQL()); //System.out.println(" Resol -> " + resolvedQuery); sql_result = used_db_item.querySilent(resolvedQuery); this.madeSQLs.put(current_id ,sql_result); //add them to the list this.madeSQLsCurrentRow .put(current_id ,new Integer(0)); res.add(current_id ); //System.out.println(" SUCCESS !!"); } catch (Exception ex) { throw new Exception(ex.getLocalizedMessage()); } } //System.out.println(res.toString()); //System.out.println(madeSQLsCurrentRow.toString()); return res; } /** Returns xxx from xxx:yyy */ private String getFirst(String s,int cutter) { int doublepoint = s.indexOf(":"); if (doublepoint != 0) { return s.substring(cutter,doublepoint ); } else return s; } /** Retur ns yyy from xxx:yyy */ private String getSecond (String s,int cutter) { int doublepoint = s.indexOf(":"); if (doublepoint != 0) { return s.substring(++doublepoint ,s.length()-cutter); } else return s; } private String getSubstitution (String query) throws Exception { StringBuffer result = new StringBuffer(); int counter = 0; StringTokenizer st = new StringTokenizer(query ); while (st.hasMoreTokens()) { String token = st.nextToken (); //parameter substitution if (token.startsWith("[-") && token.endsWith("-]")) //parameter substitution { StringBuffer newToken = new StringBuffer(); String mapid = getFirst (token,2); String mapinfo = getSecond(token,2); ParameterInfo thisinfo = mother.getProjectData().DB2XMLgetmapping().getParameterByMapID(mapid); if (this.userParams.containsKey(thisinfo.getName())) { newToken .append(this.userParams.get(thisinfo .getName())); } else //take the default value { newToken .append(thisinfo .getValue()); } result.append(newToken.toString()); } //sql substitution else if (token.startsWith("[") && token.endsWith("]")) //sql substitution { StringBuffer newToken = new StringBuffer(); // [mapid:mapinfo] Autor: Thomas Schädler 255 Anhang B: Quelltext <xmlizer> server // evaluierungsschritte: // 1. SQLStatment holen für den angegebenen key String mapid = getFirst (token,1); String mapinfo = getSecond(token,1); //newToken.append("**" + mapid + "=" + mapinfo + "**"); // 2. dbItem holen für das angegebene SQLStatement (siehe XMLSchemaParser) SQLStatement stat = mother.getProjectData().DB2XMLgetmapping().getSQLStatementByMapID(mapid); //newToken.append(stat.toString()); dbItem used_db_item = mother .getProjectData ().getDBByName(stat.getDB ()); Hashtable sql_result; // 3. SQL auf dieser datenbank ausführen: try { String sub_query = getSubstitution (stat.getSQL()); sql_result = used_db_item.querySilent(sub_query); // -- bei nur einem resultat -> dieses aus der übereinstimmenden namen (z.B. dbKey) ersetzen // -- bei mehreren resultaten -> einfach das erste nehemn (alternativ oben das limit gleich ändern) // 4. das ganze noch richtig ersetzen (Stringmässig) und dann ab damit zurück nach Hause Vector colnames = (Vector)sql_result.get("columnname"); int col = 0; for (Enumeration en = colnames.elements (); en.hasMoreElements();) { String currname = (String )en.nextElement (); if (currname.equalsIgnoreCase(mapinfo)) { break; } col++; } String info[][] = (String[][])sql_result.get("table"); //FIXME fix the row here until it works int row = ((Integer)madeSQLsCurrentRow.get(mapid)).intValue (); //get the current row String resultString = info[col][row]; newToken .append(" "); newToken .append(resultString); result.append(newToken.toString()); counter++; } catch (Exception ex) { throw new Exception (ex.getLocalizedMessage()); } } else { result.append(" "); result.append(token); } } return result.toString(); } private String resolveQuery(String query ) throws Exception { //do all data operations on the embedded queries and replace them internally! StringBuffer result = new StringBuffer(); //parse the query and substitute the SQLColumnInfo-Strings //with the real value from the following new statement: (exam ple) result.append(getSubstitution(query)); //achtung! "[..] "könnte probleme machen - format suchen!! return result.toString(); } //PARSING //----------------------------------------------------------------------------------------------/** * Parse an XML Schema */ public void parse(Document doc ) throws Exception { this.doc = doc; //parse it and make everything ok, then doParse(); } private void doParse() throws Excep tion { //parse the xml schema Element xmlroot = doc.getRootElement (); //get the xml root Namespace namespace = xmlroot.getNamespace(); //get the namespace topNode = insertDocumentNode(xmlroot); //insert the doc root in the tree // iterate over children of the root node List elems = xmlroot.getChildren(); //"element",namespace Iterator elems_iter = elems.iterator (); int item_count = elems.size(); Object[] rootElems = new Object[item_count]; int counter = 0; while (elems_iter.hasNext()) { Element xmlelem = (Element) elems_iter.next(); if (this.JDOMisElement (xmlelem)) { rootElems[counter] = this.JDOMgetElementName(xmlelem); this.xml_elements.put(this.JDOMgetElementName(xmlelem),xmlelem); counter++; } else if (this.JDOMisType(xmlelem)) //build type-lib for simpleTypes { this.xml_types.put(this.JDOMgetElementName(xmlelem),xmlelem); } } //load the Content to add them to the elements this.loadedContent = mother.getProjectData().DB2XMLgetmapping ().getLoadedContent(); //load the Repetitions to add them to the elements this.loadedReps = mother.getProjectData().DB2XMLgetmapping().getLoadedReps(); //load the SQLStatements from xmlizer.xml this.loadedSQL = mother.getProjectData().DB2XMLgetmapping().getLoadedSQL(); //check for saved root-element, else choose one Autor: Thomas Schädler 256 Anhang B: Quelltext <xmlizer> server rootelement = mother .getProjectData().DB2XMLgetmapping().getRootElement (); //check if the saved root element is available, else choose new if (rootelement != null) { if (!this.xml_elements.containsKey(rootelement)) { rootelement = null; } } if (rootelement == null) { throw new Exception("No root element specified in mapping, aborting."); } Element current = (Element)this.xml_elements.get(rootelement); recursiveTreeBuilder (topNode,current); //make the tree tree = new JTree(topNode); } //------------------------------------------------------ PARSE HELPERS /** * Walks the JDOM Path to the root and build a xpath-like (unique string) * which identifies a element for sure */ private String walkJDOMPath(Element element) { StringBuffer buff = new StringBuffer (); Element current = element; do { if (current.getAttribute("name") != null) { buff.insert(0,"/" + current.getAttribute("name").getValue()); } current = current.getParent (); } while (!current.isRootElement ()); return buff.toString (); } /** * Walks the tree-path of the jtree and adds all parent -nodes(=elements) * to the list of the element's parents */ private SchemaElement walkTreePath(Object[] path,SchemaElement elem) { //add all parent elements to this element and return it //System.out.println(elem.getName() + " --> " + path.length); for(int i=0;i<path.length;i++) { DefaultMutableTreeNode curr = (DefaultMutableTreeNode)path[i]; SchemaElement currse = (SchemaElement )curr.getUserObject(); //System.out.println(currse.toString()); if (currse.isRefresh()) //is a real element (xml) { elem.addParent(currse); } } return elem; } private DefaultMutableTreeNode lastParent = null; private SchemaElement lastSchemaElement = null; private void recursiveTreeBuilder(DefaultMutableTreeNode parentNode,Element current) { //inspect this element and recurse for child-elements with current as new parentNode if (current == null) { return; } //failsafe DefaultMutableTreeNode treeNode = null; SchemaElement schemel = null; if (current.getName().equalsIgnoreCase("element")) { treeNode = new DefaultMutableTreeNode (current); String uniquePath = walkJDOMPath (current); schemel = new SchemaElement (this.mother,treeNode,current,uniquePath ); StringBuffer name = new StringBuffer(); Attribute attr = null; SchemaOccurrence occurrence = new SchemaOccurrence(current.getName().trim()); //name attr = current.getAttribute ("name"); if (attr != null) { //System.out.println(attr.getValue()); schemel.setRealName(attr.getValue ().trim()); name.append("<" + attr.getValue().trim() + ">"); //add the Repetition if available if (this.loadedReps.containsKey(uniquePath)) { schemel.setRepetition((String )this.loadedReps.get(uniquePath)); } //add the SQLStatements according to the elementName in loadedSQL if (this.loadedSQL .containsKey(uniquePath)) { //System.out.println(currentElementName + " has a SQLStatement attached"); Vector this_sqls = (Vector)this.loadedSQL.get(uniquePath); for (Enumeration e = this_sqls.elements (); e.hasMoreElements();) { SQLStatement this_stat = (SQLStatement)e.nextElement(); //System.out.println("ADDING SQL WHILE PARSING: " + this_stat); schemel.addSQLStatement(this_stat); } } } //type attr = current.getAttribute ("type"); if (attr != null) { schemel.setType(attr.getValue().trim()); name.append(" - " + attr.getValue ().trim()); } Autor: Thomas Schädler 257 Anhang B: Quelltext <xmlizer> server //ref attr = current.getAttribute ("ref"); if (attr != null) { schemel.setTypeRef (attr.getValue().trim()); name.append(" => " +attr.getValue ().trim()); } //minOccurs attr = current.getAttribute ("minOccurs"); if (attr != null) { String min = attr.getValue().trim(); if (min != null) { occurrence.setMinOccurs(min); } //System.out.println("MIN: " + min); } //maxOccurs attr = current.getAttribute ("maxOccurs"); if (attr != null) { String max = attr.getValue().trim(); if (max != null) { occurrence.setMaxOccurs(max); } //System.out.println("MAX: " + max); } schemel.setOccurrence(occurrence ); schemel.setName(name.toString()); /* if (schemel.getRealName().equalsIgnoreCase("uniqID")) { System.out.println(schemel); } */ if (schemel.hasTypeRef ()) //typ dereferencing { //FIXME String typeRef = schemel.getTypeRef(); //System.out.println("TypeRef: " + typeRef); typeRef = removeNamespacePrefix(typeRef); Element newcurrent = (Element)this.xml_elements.get(typeRef); if (newcurrent != null) { recursiveTreeBuilder(parentNode,newcurrent); } } else if (schemel.hasType()) //type buildup { //add the stuff treeNode.setUserObject(schemel); parentNode.add(treeNode ); lastParent = treeNode; //set last to current mother.getProjectData().DB2XMLgetmapping().addElement (schemel); //add the stuff //end should be reached because of having a simple type String typeR = schemel.getType(); //System.out.println("Type: " + typeR); typeR = removeNamespacePrefix(typeR); Element newcurrent = (Element)this.xml_types.get(typeR); if (newcurrent != null) { //System.out.println(schemel); schemel.processType (newcurrent); lookForAttributes(schemel,newcurrent); lookForContent (schemel,newcurrent); recursiveTreeBuilder(treeNode ,newcurrent); } else //must be an internal type (per default just take it for now) { //could also be an invalid type! if (this.loadedContent.containsKey (schemel.getRealName ())) { schemel.setContent((SchemaContent)this.loadedContent.get(schemel.getID ())); } else { schemel.setContent(new SchemaContent(schemel.getID ())); } } //fill in parents schemel = walkTreePath(treeNode.getPath(),schemel); //make age change here lastSchemaElement = schemel; } else { //must have an internal type -> buildup //add the stuff treeNode.setUserObject(schemel); parentNode.add(treeNode ); lastParent = treeNode; //set last to current mother.getProjectData().DB2XMLgetmapping().addElement (schemel); //add the stuff schemel.setInternalType (); //mark that it has an internal type def. schemel.processInternalType(); //fill in parents schemel = walkTreePath(treeNode.getPath(),schemel); //make age change here lastSchemaElement = schemel; } } else if (current.getName().equalsIgnoreCase("any")) { treeNode = new DefaultMutableTreeNode (); schemel = new SchemaElement (this.mother,treeNode,"<any>"); treeNode.setUserObject (schemel); Autor: Thomas Schädler 258 Anhang B: Quelltext <xmlizer> server parentNode.add(treeNode); lastParent = treeNode; } else if (current.getName().equalsIgnoreCase("all")) { treeNode = new DefaultMutableTreeNode (); schemel = new SchemaElement (this.mother,treeNode,"-=all=-"); treeNode.setUserObject (schemel); parentNode.add(treeNode); lastParent = treeNode; } else if (current.getName().equalsIgnoreCase("group")) { treeNode = new DefaultMutableTreeNode (); schemel = new SchemaElement (this.mother,treeNode,"-=group=-"); treeNode.setUserObject (schemel); parentNode.add(treeNode); lastParent = treeNode; } else if (current.getName().equalsIgnoreCase("sequence")) { treeNode = new DefaultMutableTreeNode(); schemel = new SchemaElement (this.mother,treeNode,"-=sequence=-"); treeNode.setUserObject (schemel); parentNode.add(treeNode); lastParent = treeNode; } else if (current.getName().equalsIgnoreCase("choice")) { treeNode = new DefaultMutableTreeNode (); schemel = new SchemaElement (this.mother,treeNode,"-=choice=-"); treeNode.setUserObject (schemel); parentNode.add(treeNode); lastParent = treeNode; } else if (current.getName().equalsIgnoreCase("documentation")) { lastSchemaElement.addDocumentation(current.getText()); } else { treeNode = lastParent; } //look for complexType // iterate over children of the this element node List elems = current.getChildren(); //"elements",namespace Iterator elems_iter = elems.iterator (); while (elems_iter.hasNext()) { Element xmlelem = (Element) elems_iter.next(); recursiveTreeBuilder(treeNode,xmlelem); } } /** * Recursive search for simpleContent in type -Elements (simple and complex) */ private void lookForContent(SchemaElement attachHere,Element typeElement) { if (typeElement == null) { return; } //failsafe if (typeElement .getName().equalsIgnoreCase("simpleContent")) { if (this.loadedContent .containsKey(attachHere.getID())) { attachHere.setContent((Schem aContent)this.loadedContent.get(attachHere.getID())); return; } else { attachHere.setContent(new SchemaContent(attachHere.getID())); return; } } // iterate over children of the this element node List elems = typeElement.getChildren (); //"elements",namespace Iterator elems_iter = elems.iterator (); while (elems_iter.hasNext()) { Element xmlelem = (Element) elems_iter.next(); lookForContent(attachHere,xmlelem); } } /** * Recursive search for attributes in type-Elements (simple and complex) */ private void lookForAttributes (SchemaElement attachHere ,Element typeElement ) { if (typeElement == null) { return; } //failsafe if (typeElement .getName().equalsIgnoreCase("attribute")) { attachHere.addAttribute(typeElement,mother .getProjectData ().DB2XMLgetmapping().getLoadedAttributes ()); } // iterate over children of the this element node List elems = typeElement.getChildren (); //"elements",namespace Iterator elems_iter = elems.iterator (); while (elems_iter.hasNext()) { Element xmlelem = (Element) elems_iter.next(); lookForAttributes(attachHere,xmlelem); } } /** * Returns the name of this JDOMElement (attribute name of <element name="asdf"...> * else returns "anonymous" */ private String JDOMgetElementName(Element el) { Attribute attr = el.getAttribute("name"); if (attr != null) { return attr.getValue().trim(); } else //just to be sure, should not happen though... { return "anonymous"; } Autor: Thomas Schädler 259 Anhang B: Quelltext <xmlizer> server } /** * Returns true if this JDOMElement is an <element ...> -tag */ private boolean JDOMisType(Element el) { if (el.getName().equalsIgnoreCase("simpleType" ) || el.getName().equalsIgnoreCase("complexType")) return true; return false; } /** * Tests if the JDOMElement is of indicated type or not */ private boolean JDOMisOfType(String type ,Element el) { if (el.getName().equalsIgnoreCase(type)) return true; else return false; } /** * Returns true if this JDOMElement is an <element ...> -tag */ private boolean JDOMisElement(Element el ) { if (el.getName().equalsIgnoreCase("element")) return true; return false; } private DefaultMutableTreeNode insertDocumentNode(Element what) { DefaultMutableTreeNode treeNode = new DefaultMutableTreeNode(); SchemaElement schemel = new SchemaElement (this.mother,treeNode,"<schema>",what); treeNode.setUserObject(schemel); return treeNode ; } private static String removeNamespacePrefix(String s) { int doublepoint = s.indexOf(":"); if (doublepoint != 0) { return s.substring(++doublepoint ); } else return s; } } /* * fileData.java * * Created on 4. August 2002, 00:40 * * ---------------------------------------------------------------------------* This file is part of <xmlizer>. * * <xmlizer> is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Foobar is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along wit h <xmlizer>; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * ---------------------------------------------------------------------------*/ package server; import java.io.*; import java.util.*; import java.lang.*; /** * Represents the fileData (all files belonging to a project) * @author [email protected] * @version 0.2 */ public class fileData { public static String XMLFILEROOT = "xmlizerconfig" ; private String name; private Hashtable files = new Hashtable(); //key = name, value = file //CONSTRUCTOR //----------------------------------------------------------------------------------------------/** * Creates new fileData (Constructor) */ public fileData() { //init here if neccessary } //GET AND SET //----------------------------------------------------------------------------------------------//name public String getName() { return name; } public void setName(String name) { this.name = name; } //files public Enumeration getFileEnumeration() { Autor: Thomas Schädler 260 Anhang B: Quelltext <xmlizer> server return this.files.elements (); } //REST //----------------------------------------------------------------------------------------------/** * adds a new filedata element to the list */ public void addFile(String name,File file) { if (name != null && file != null) { //System.out.println(name + " >> " + file.toString()); this.files.put(name,file); } } /** * returns the specified file as file */ public File getFile(String name) { if (this.files.containsKey (name)) { return (File)this.files.get(name); } else return null; } /** * returns the main config file (xmlizer.xml) as file */ public File getConfigFile() { if (this.files.containsKey ("xmlizer.xml")) { return (File)this.files.get("xmlizer.xml"); } else return null; } /** * returns true if this filedata contains a file called xmlizer.xml */ public boolean hasConfig () { return this.files.containsKey("xmlizer.xml"); } //STRING REPRESENTATION //----------------------------------------------------------------------------------------------public String toString() { StringBuffer result = new StringBuffer("FILEDATA = >>"); result.append("\nNAME >> " + this.name); result.append("\nFILES >> " + this.files .toString()); return result.toString(); } } /* * dataItem.java * * This class representates a multi-purpose item consiting of the following stuff * * - key (String) * - value (String) * - description (String) * * -> ... every variable has its get ans set methods * * Created on 18. April 2002, 20:20 * ---------------------------------------------------------------------------* This file is part of <xmlizer>. * * <xmlizer> is f ree software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Foobar is dist ributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with <xmlizer>; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * ----------------------------------------------------------------------- ----*/ package server; import java.lang.*; /** * Represents a dataItem * @author [email protected] * @version 0.2 */ public class dataItem { private String tkey ; private String tdescription; private String tvalue; /** * Constructors for a new projectdataItem * -> holds: * String key * String value * String description */ public dataItem(String key,String value,String description) { Autor: Thomas Schädler 261 Anhang B: Quelltext <xmlizer> server tkey = key; tvalue = value; tdescription = description ; } public dataItem(String key,String value) { tkey = key; tvalue = value; tdescription = new String(); } public dataItem(String key) { tkey = key; tvalue = new String(); tdescription = new String(); } public dataItem() { tkey = new String(); tvalue = new String(); tdescription = new String(); } //STRING REPRESENTATION //---------------------------------------------------------- ------------------------------------/** * By default show the key as String */ public String toString() { return "\ndataItem : key = " + tkey + "\n" + " : value = " + tvalue + "\n" + " : description = " + tdescription + "\n"; } //GET AND SET METHODS //----------------------------------------------------------------------------------------------/** * Returns the key of the item */ public String getKey() { return tkey; } /** * Get the description of the item */ public String getDescription() { return tdescription; } /** * Get the value of the item */ public String getValue() { return tvalue; } /** * Set a new key */ public void setKey(String s) { tkey = s; } /** * Set a new description */ public void setDescription(String s ) { tdescription = s; } /* * Set a new v alue */ public void setValue(String s) { tvalue = s; } } /* * CgiParser.java * * Created on 4. August 2002, 00:40 * * ---------------------------------------------------------------------------* This file is part of <xmlizer>. * * <xmlizer> is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Foobar is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with <xmlizer>; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * ---------------------------------------------------------------------------* This appears in Core Web Programming from * Prentice Hall Publishers, and may be freely used * or adapted. 1997 Marty Hall, [email protected]. */ package server; import java.net.*; import java.util.*; Autor: Thomas Schädler 262 Anhang B: Quelltext <xmlizer> server /** * Parses the CGI QueryString * @author [email protected] * @version 0.2 */ public class CgiParser { private String data , delims1, delims2; private String [] nameArray, valueArray; private String [][] fullValueArray; public CgiParser(String data,String delims1,String delims2) { this.data = data; this.delims1 = delims1; this.delims2 = delims2; } public LookupTable parse () { Vector nameVector = new Vector(); Vector valueVector = new Vector (); if (data == null) { return (buildTable(nameVector,valueVector,0)); } StringTokenizer tok = new StringTokenizer (data, delims1); String nameValuePair , name, value; StringTokenizer tempTok; int index, numNames=0; Vector values; while(tok.hasMoreTokens()) { nameValuePair = tok.nextToken(); tempTok = new StringTokenizer(nameValuePair,delims2); name = URLDecoder.decode(tempTok.nextToken ()); if (tempTok.hasMoreTokens()) { value = URLDecoder .decode(tempTok.nextToken ()); } else { value = ""; } index = nameVector.indexOf(name); if (index == -1) { nameVector.addElement(name); values = new Vector(); values.addElement(value ); valueVector.addElement(values); numNames++; } else { values = (Vector)valueVector.elementAt (index); values.addElement(value ); } } return(buildTable(nameVector, valueVector, numNames)); } private LookupTable buildTable (Vector nameVector,Vector valueVector,int numNames ) { nameArray = new String[numNames ]; valueArray = new String[numNames]; fullValueArray = new String[numNames ][]; LookupTable table = new LookupTable(nameArray,valueArray ,fullValueArray ); String[] fullValues; Vector values; for(int i=0; i<nameVector.size(); i++) { nameArray[i] = (String )nameVector.elementAt(i); values = (Vector )valueVector.elementAt(i); valueArray[i] = (String)values.firstElement(); fullValues = new String[values.size()]; values .copyInto(fullValues); fullValueArray[i] = fullValues; } return(table); } } /* * LookupTable.java * * Created on 4. August 2002, 00:40 * * -------------------- -------------------------------------------------------* This file is part of <xmlizer>. * * <xmlizer> is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Softw are Foundation; either version 2 of the License, or * (at your option) any later version. * * Foobar is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with <xmlizer>; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * ---------------------------------------------------------------------------* This appears in Core Web Programming from * Prentice Hall Publishers, and may be freely used * or adapted. 1997 Marty Hall, [email protected]. */ package server; /** * Holds the parsed Querystring Autor: Thomas Schädler 263 Anhang B: Quelltext <xmlizer> server * @author [email protected] * @version 0.2 */ public class LookupTable { private String [] nameArray, valueArray; private String [][] fullValueArray; public LookupTable(String[] nameArray, String[] valueArray , String[][] fullValueArray) { this.nameArray = nameArray ; this.valueArray = valueArray; this.fullValueArray = fullValueArray ; } public String[] getNames () { return(nameArray); } public String[] getValues() { return(valueArray); } public String[][] getFullValues() { return(fullValueArray); } // Although this is O(N) and HashTable would // be O(1), N is typically so small that a HashTable // is the same or slower. // null -- no such name. Empty string -- name // supplied with empty value. public String getValue(String name) { for(int i=0; i<nameArray.length ; i++) if (nameArray[i].equals(name)) return(valueArray[i]); return(null); } public String[] getFullValue(String name ) { for(int i=0; i<nameArray.length ; i++) if (nameArray[i].equals(name)) return(fullValueArray[i]); return(null); } public int numValues(String name) { String[] values = getFullValue(name); if (values == null) return (0); else return (values.length); } public String toHTML() { StringBuffer buff = new StringBuffer (); if (nameArray.length > 0) { buff.append ("<H4>DEBUG: Parameter data supplied:</h4>\n" + "<CENTER>\n" + "<TABLE BORDER=1>\n" + " <TR><TH>Name<TH>Value(s)"); } else { buff.append ("<H4>DEBUG: No Parameter data supplied.</H4>" ); } String name, value; for(int i=0; i<nameArray.length ; i++) { name = nameArray [i]; buff.append (" <TR><TD>" + name); if (numValues(name) > 1) { String[] fullValue = getFullValue (name); buff.append(" <TD>Multiple values supplied: \n for(int j=0; j<fullValue.length; j++) { buff.append(" <LI>" + fullValue[j]); } buff.append(" </UL>"); } else { value = valueArray [i]; if (value.equals("")) { buff.append(" <TD><I>No Value Supplied</I>"); } else { buff.append(" <TD>" + value); } } } buff.append("</TABLE>\n</CENTER>"); return buff.toString (); } <UL>"); }/* * ProjectManager.java * * Created on 4. August 2002, 17:41 * * ---------------------------------------------------------------------------* This file is part of <xmlizer>. * * <xmlizer> is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Foobar is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of Autor: Thomas Schädler 264 Anhang B: Quelltext <xmlizer> server * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with <xmlizer>; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * ---------------------------------------------------------------------------*/ package server; import import import import import java.io.*; org.jdom.*; org.jdom.input.SAXBuilder; org.jdom.output.XMLOutputter; java.util.*; /** * Manages the projectData * @author [email protected] * @version 0.2 */ public class ProjectManager { private String path ; private projectData data ; private String db2xmlMapping; private boolean hasMappingDB2XML = false ; private boolean hasMappingSMDBE = false; private static String SPACER = new String(" "); public static String XMLSMDBEFILEDTD = "xmlizer.smdbe.verbose.dtd"; public static String XMLSMDBEFILEROOT = "database" ; /** Creates new ProjectManager */ public ProjectManager(String projectfilepath) throws Exception { this.path = projectfilepath; this.data = new projectData(); init(); } /** * init the data from the file xmlizer.xml **/ private boolean init() throws Exception { //set the data with the given path return getProjectData().readFromFile (path); } public projectData getProjectData() { return this.data; } //DB2XML //---------------------------/** * Returns the output as XML for the module DB2XML */ public StringBuffer getXML_DB2XML(String basedirectory,Hashtable userParams ) throws Exception { getMappingDB2XML(basedirectory,userParams ); return new StringBuffer(db2xmlMapping); } private void getMappingDB2XML(String basedirectory ,Hashtable userParams) throws Exception { if (!hasMappingDB2XML) { Vector onexml = (Vector)this.data.getXML(); xmlItem xmlitem = (xmlItem)onexml.get(0); String thefilename = basedirectory + xmlitem.getFile(); //System.out.println(thefilename); Document thedoc = getFileAsXMLDOM(thefilename,false); //make the mapping XMLSchemaParser schemaparser = new XMLSchemaParser(this); schemaparser.parse(thedoc); schemaparser.buildInstance(userParams ); Document doc = schemaparser .getInstance(); if (doc != null) { XMLOutputter fmt = new XMLOutputter(" ",true); this.db2xmlMapping = fmt.outputString(doc); //set and return hasMappingDB2XML = true; } else { throw new Exception("unspecified xml document parsing error"); } } } public Document getFileAsXMLDOM(String filename,boolean validating) throws Exception { try { SAXBuilder builder = new SAXBuilder(validating); //true -> validating against dtd Document jdoc = builder.build(filename); return jdoc; } catch (JDOMException e) { throw new Exception(e.getLocalizedMessage()); } } //SMDBE //---------------------------/** * Returns the output as XML for the module SMDBE */ public StringBuffer getXML_SMDBE(String dbname) throws Exception { dbItem item = this.data.getDBByName(dbname); Autor: Thomas Schädler 265 Anhang B: Quelltext <xmlizer> server String otype = item.SMDBEgetOutputType(); if (otype.equalsIgnoreCase ("simple")) { return outputXMLResultSimple(item,item.SMDBEgetSelectedTables()); } else if (otype.equalsIgnoreCase ("verbose" )) { return outputXMLResultVerbose(item,item.SMDBEgetSelectedTables ()); } else throw new Exception("unsupported output type in configuration: " + otype); } /** * Generates Simple DB Export XML from a selected DB and writes it to a temporary file * Therfore it uses no DTD and writes just plain XML without any extra data * @return a stringbuffer filled with the xml output */ private StringBuffer outputXMLResultSimple(dbItem theDB ,Vector tables) throws Exception { StringBuffer out = new StringBuffer(); //add the header and doctype out.append ("<?xml version= \"1.0\" encoding=\"UTF-8\"?>\n"); //add the <database name="dbname" url="dburl"> tag out.append ( "<database name=\"" +Start.htmlEncode(theDB.getName()) //+"\" url=\"" //+Start.htmlEncode(theDB.getUrl()) +"\">\n" ); //tables setup out.append (SPACER+"<tables>\n"); //for all tables for (Enumeration e = tables.elements (); e.hasMoreElements();) { //add the <table name="tablename"> tag String this_table = (String )e.nextElement(); out.append(SPACER+SPACER+"<"+this_table+">\n"); try { Hashtable theTable = theDB.querySilent ("SELECT * FROM " + this_table ); final String data[][] = (String[][])theTable.get("table"); final int rows = ((Integer)theTable.get("rows")).intValue(); final int cols = ((Integer)theTable.get("cols")).intValue(); final Vector columnnames = (Vector)theTable .get("columnlabels"); //for each row of this table for(int i=0;i<rows;i++) { out.append(SPACER+SPACER +SPACER+"<row>\n"); //for each column of the row String encoded ; String colname ; for(int j=0;j<cols;j++) { colname = Start .htmlEncode((String)columnnames.get(j)); out.append (SPACER+SPACER+SPACER+SPACER+"<"+colname+">"); encoded = Start .htmlEncode((String)data[j][i]); out.append (encoded); out.append ("</"+colname+">\n"); } out.append(SPACER+SPACER +SPACER+"</row>\n"); } out.append(SPACER+SPACER+"</"+this_table+">\n"); } catch (Exception eq) { throw new Exception(eq.getLocalizedMessage()); } } out.append (SPACER+"</tables>\n"); out.append ("</database>\n"); return out; } /** * Generates Simple DB Export XML from a selected DB and writes it to a temporary file * @return a temprary file filled with XML */ private StringBuffer outputXMLResultVerbose(dbItem theDB,Vector tables ) throws Exception { StringBuffer out = new StringBuffer(); //add the header and doctype out.append ("<?xml version= \"1.0\" encoding=\"UTF-8\"?>\n"); //out.append("<!DOCTYPE database SYSTEM \""+XMLSMDBEFILEDTD+" \">\n"); //add the <database name="dbname" url="dburl"> tag out.append ( "<database name=\"" +Start.htmlEncode(theDB.getName()) //+"\" url=\"" //+Start.htmlEncode(theDB.getUrl()) +"\">\n" ); //tables setup out.append (SPACER+"<tables>\n"); //for all tables for (Enumeration e = tables.elements (); e.hasMoreElements();) { //add the <table name="tablename"> tag String this_table = (String )e.nextElement(); out.append(SPACER+SPACER+"<table name=\""+this_table +"\">\n"); try { Hashtable theTable = theDB.querySilent ("SELECT * FROM " + this_table ); final String data[][] = (String[][])theTable.get("table"); final int rows = ((Integer)theTable.get("rows")).intValue(); final int cols = ((Integer)theTable.get("cols")).intValue(); final Vector columnnames = (Vector)theTable .get("columnlabels"); Autor: Thomas Schädler 266 Anhang B: Quelltext <xmlizer> server final Vector columntypes = (Vector)theTable .get("columntypes"); //for each row of this table for(int i=0;i<rows;i++) { out.append(SPACER+SPACER +SPACER+"<row>\n"); //for each column of the row String encoded ; for(int j=0;j<cols;j++) { out.append (SPACER+SPACER+SPACER+SPACER+"<column"); encoded = Start .htmlEncode((String)columnnames.get(j)); out.append (" name=\""+encoded+"\""); encoded = Start .htmlEncode((String)columntypes.get(j)); out.append (" type=\""+encoded+"\""); encoded = Start .htmlEncode((String)data[j][i]); out.append (" data=\""+encoded+"\"/>\n"); } out.append(SPACER+SPACER +SPACER+"</row>\n"); } out.append(SPACER+SPACER+"</table>\n"); } catch (Exception eq) { throw new Exception(eq.getLocalizedMessage()); } } out.append (SPACER+"</tables>\n"); out.append ("</database>\n"); return out; } } /* * projectData.java * * This projectData container contains all neccessary methods to deal * with the projectData management * * Created on 5. April 2002, 16:30 * ---------------------------------------------------------------------------* This file is part of <xmlizer>. * * <xmlizer> is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Foobar is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with <xmlizer>; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * ---------------------------------------------------------------------------*/ package server; import import import import import import import java.io.*; java.util.*; java.lang.*; javax.swing .*; org.jdom.*; org.jdom.input.SAXBuilder; org.jdom.output.XMLOutputter; /** * Represents the projectData * @author [email protected] * @version 0.2 */ public class projectData { public static String XMLPROJECTFILEDTD = "xmlizer.project.config.dtd"; public static String XMLPROJECTFILEROOT = "xmlizerprojectconfig"; private private private private private Vector initial = new Vector (0); //holds dataItems Vector xml = new Vector(0); //holds xmlItems Vector dbs = new Vector(0); //holds dbItems DB2XMLmapping mapping = new DB2XMLmapping(); //holds the mapping-info for the DB2XML-Module Vector simpleItems = new Vector(); //of dbItems //CONSTRUCTOR //----------------------------------------------------------------------------------------------/** * Creates new projectData (Constructor) */ public projectData() { //init here if neccessary } //INITIAL MANAGEMENT //----------------------------------------------------------------------------------------------/** * Returns a Vector -> project variables as dataItems */ public Vector getInitial () { return initial; } public void addInitial(dataItem dataitem ) { initial.add(dataitem ); } public dataItem getInitialByKey(String key) { for (Enumeration e = this.initial.elements(); e.hasMoreElements();) { dataItem item = (dataItem)e.nextElement(); if (item.getKey().equalsIgnoreCase(key)) { return item; Autor: Thomas Schädler 267 Anhang B: Quelltext <xmlizer> server } } return null; } public void setInitialByKey(String key,String new_value ) { for (Enumeration e = this.initial.elements(); e.hasMoreElements();) { dataItem item = (dataItem)e.nextElement(); if (item.getKey().equalsIgnoreCase(key)) { item.setValue(new_value ); return; } } dataItem newitem = new dataItem (); newitem.setKey(key); newitem.setValue(new_value ); addInitial (newitem); System.out.println("Added new Item: " + key + " [" + new_value + "]"); } //XML FILES MANAGEMENT //----------------------------------------------------------------------------------------------/** * Returns a Vector -> XML-Files as String (whole path or url) */ public Vector getXML() { return xml; } public void addXML(xmlItem xmlitem) { xml.add(xmlitem); } public void removeXML(String identifier) { for (Enumeration e = xml.elements(); e.hasMoreElements();) { xmlItem xmlitem = (xmlItem)e.nextElement(); if (xmlitem.getName().equalsIgnoreCase(identifier)) { xml.remove(xmlitem ); break; } } } public void setXML(Vector newXML) { xml = newXML; } //DATABASE MANAGEMENT //----------------------------------------------------------------------------------- -----------/** * Returns a Vector -> databases as dbItem */ public Vector getDB () { return dbs; } public void addDB(dbItem dbitem) { dbs.add(dbitem); } public void removeDB(String identifier) { for (Enumeration e = dbs.elements(); e.hasMoreElements();) { dbItem dbitem = (dbItem)e.nextElement (); if (dbitem.getName().equalsIgnoreCase (identifier)) { dbitem.closeConnection(); dbs.remove(dbitem); break; } } } public void setDB(Vector newDB ) { dbs = newDB; } public dbItem getDBByName(String name) { for (Enumeration e = this.dbs.elements(); e.hasMoreElements();) { dbItem item = (dbItem)e.nextElement(); if (item.getName().equalsIgnoreCase(name)) { return item; } } return null; } //OBJECT FINALIZATION (CLEANUP) //----------------------------------------------------------------------------------------------/** * Do the cleanup before diposing */ public void finalize() { //close all connections for (Enumeration e = dbs.elements(); e.hasMoreElements();) { dbItem dbitem = (dbItem)e.nextElement (); dbitem .closeConnection (); } } //STRING REPRESENTATION //----------------------------------------------------------------------------------------------public String toString() { StringBuffer result = new StringBuffer("FULL PROJECTDATA >>\n"); for (Enumeration e = this.initial.elements(); e.hasMoreElements();) { dataItem item = (dataItem)e.nextElement(); result .append(item); } for (Enumeration e = this.xml.elements(); e.hasMoreElements();) { result .append("\nXML >> " + e.nextElement()); } for (Enumeration e = this.dbs.elements(); e.hasMoreElements();) { dbItem item = (dbItem)e.nextElement(); result .append(item); Autor: Thomas Schädler 268 Anhang B: Quelltext <xmlizer> server } return result.toString(); } //XML REPRESENTATION //----------------------------------------------------------------------------------------------/** * Checks the doctype of the XML-File (just to be sure to read the right information) */ private boolean checkDocType(DocType dt,String rootelement,String systemdtd ) { if (dt.getElementName().equalsIgnoreCase(rootelement) && dt.getSystemID ().equalsIgnoreCase(systemdtd)) { return true; } else { return false; } } public Vector getSimpleItems() { return this.simpleItems; } /* * Reads an XML file (which must be of type xmlizer.project.config.dtd) and * fills all information in the projectdata * * @param The filename as String */ synchronized public boolean readFromFile (String filename) throws Exception { boolean docOK = false; try { SAXBuilder build er = new SAXBuilder(true); Document jdoc = builder.build(filename); //true -> validating against dtd DocType docType = jdoc.getDocType(); docOK = checkDocType(docType,XMLPROJECTFILEROOT ,XMLPROJECTFILEDTD); String mappingModule = null; if (docOK) { //get the root Element root = jdoc.getRootElement(); //get the initialsetup Element initsetup = root.getChild ("initialsetup" ); java.util.List initlist = initsetup.getChildren("inititem" ); Iterator init_iter = initlist.iterator (); while (init_iter.hasNext()) { Element init_item = (Element) init_iter .next(); dataItem initialdataitem = new dataItem (); if (init_item.getAttributeValue("key").equalsIgnoreCase("module" )) { mappingModule = init_item .getTextTrim(); //save the mapping module info } initialdataitem.setKey(init_item.getAttributeValue("key")); initialdataitem.setValue (init_item .getTextTrim()); addInitial(initialdataitem); } //get the databasesetup Element dbsetup = root.getChild("databasesetup"); java.util.List dblist = dbsetup.getChildren ("dbitem"); Iterator db_iter = dblist.iterator(); while (db_iter.hasNext()) { Element db_item = (Element) db_iter.next(); dbItem initialdbitem = new dbItem(); initialdbitem.setName(db_item.getChild("name").getTextTrim()); initialdbitem.setDriver(db_item.getChild("driver" ).getTextTrim()); initialdbitem.setUrl(db_item.getChild("url").getTextTrim()); initialdbitem.setTimeout (db_item.getChild("timeout").getTextTrim ()); initialdbitem.setUsername(db_item.getChild("username").getTextTrim()); initialdbitem.setPassword(db_item.getChild("password").getTextTrim()); addDB(initialdbitem ); } //get the schemasetup Element xmlsetup = root.getChild("schemasetup"); java.util.List xmllist = xmlsetup .getChildren("xmlitem"); Iterator xml_iter = xmllist.iterator(); while (xml_iter.hasNext()) { Element xml_item = (Element) xml_iter.next(); xmlItem xmlitem = new xmlItem(); xmlitem.setName(xml_item .getChild("name").getTextTrim()); xmlitem.setFile(xml_item .getChild("file").getTextTrim()); addXML(xmlitem ); } //get the mapping information depending on mappingModule if(mappingModule != null) { Element maproot = root.getChild("mapping"); if (maproot != null) { Autor: Thomas Schädler 269 Anhang B: Quelltext <xmlizer> server if (mappingModule.equalsIgnoreCase("Simple DB Export")) { Element smdberoot = maproot.getChild ("smdbe"); java.util.List smdbeitemlist = smdberoot.getChildren("smdbe_item"); Iterator smdbe_iter = smdbeitemlist.iterator(); String dbName = null; String level = null; while (smdbe_iter.hasNext()) { Element smdbe_item = (Element) smdbe_iter.next(); dbName = smdbe_item.getAttributeValue ("name"); level = smdbe_item.getAttributeValue("type"); //<smdbe_item name="dbname"> java.util.List smdbetablelist = smdbe_item .getChildren("smdbe_table" ); Iterator smdbetable_iter = smdbetablelist.iterator(); Vector selTab = new Vector(); while (smdbetable_iter .hasNext()) { Element smdbe_table_item = (Element) smdbetable_iter.next(); selTab.add(smdbe_table_item.getTextTrim()); } if (selTab.size()>0 && dbName != null && level != null) { dbItem selDB = getDBByName(dbName ); selDB.SMDBEsetSelectedTables (selTab); selDB.SMDBEsetOutputType(level); this.simpleItems.add(selDB); //System.out.println(dbName + " : " + selTab.toString()); } } } else if (mappingModule.equalsIgnoreCase("Database to XML")) { Element db2xmlroot = maproot.getChild("db2xml" ); String elementRoot = db2xmlroot .getAttributeValue("rootelement"); if (elementRoot != null) { mapping.setRootElement (elementRoot); } //parameters java.util.List para_list = db2xmlroot.getChildren("db2xml_parameter"); Iterator para_iter = para_list.iterator(); while (para_iter .hasNext()) //for all db2xml_element tags { Element p_item = (Element) para_iter.next(); String parID = p_item.getAttributeValue("id"); String parName = p_item.getAttributeValue("name "); String parValue = p_item.getAttributeValue ("default" ); //mark this element as loaded -> no dirty check while parsing. mapping.addParameterFromLoad(parID,parName,parValue); } //elements java.util.List element_list = db2xmlroot.getChildren("db2xml_element"); Iterator element_iter = element_list .iterator(); String el_name = null; String el_rep = null; String el_id = null; while (element_iter.hasNext()) //for all db2xml_element tags { Element el_item = (Element) element_iter.next(); //<db2xml_element id="id" name="el_name"> el_name = el_item.getAttributeValue("name" ); el_id = el_item.getAttributeValue("id"); //mark this element as loaded -> no dirty check while parsing. mapping.addElementFromLoad(el_name,el_id); //build repetition el_rep = el_item.getAttributeValue("repsql"); if (el_rep != null) { mapping.addElementRepFromLoad(el_id,el_rep); } //build content Element content_el = el_item.getChild ("db2xml_content"); if (content_el != null) { String temp_mapid = content_ el.getAttributeValue ("mapid"); String temp_mapinfo = content_el.getAttributeValue("mapinfo"); SchemaContent temp_cont = new SchemaContent (el_id,temp_mapid,temp_mapinfo); mapping.addContentFromLoad(el_id,temp_cont); //System.out.println("Added content: " + temp_cont.toString()); } //build attributes java.util.List attr_list = el_item.getChildren("db2xml_attribute"); Iterator attr_iter = attr_list.iterator(); while (attr_iter.hasNext()) //for all db2xml_attribute tags { Element attr_item = (Element) attr_iter.next(); String temp_attr_name = attr_item .getAttributeValue("name" ); String temp_mapid = attr_item.getAttributeValue("mapid"); String temp_mapinfo = attr_item.getAttributeValue("mapinfo"); SchemaAttribute temp_attr = new SchemaAttribute(temp_attr_name,temp_mapid,temp_mapinfo); mapping.addAttributeFromLoad (el_id,temp_attr); //System.out.println("Added attr: " + temp_attr.toString()); } //build sql java.util.List sql_list = el_item.getChildren("db2xml_sql"); Iterator sql_iter = sql_list.iterator (); while (sql_iter.hasNext()) //for all db2xml_sql tags { Element sql_item = (Element) sql_iter.next(); String temp_db_name = sql_item.getAttributeValue ("db"); Autor: Thomas Schädler 270 Anhang B: Quelltext <xmlizer> server String temp_sql = sql_item.getAttributeValue("sql"); String temp_id = sql_item.getAttributeValue ("id"); SQLStatement temp_stat = new SQLStatement(temp_db_name,temp_sql,temp_id); //System.out.println("Added: " + temp_stat.toString()); java.util.List tsql_list = sql_item.getChildren("db2xml_sql_info"); Iterator tsql_iter = tsql_list.iterator(); while (tsql_iter.hasNext()) //for all db2xml_sql_info tags { Element tsql_item = (Element) tsql_iter .next(); String temp_col_name= tsql_item.getAttributeValue ("name"); String temp_col_type = tsql_item.getAttributeValue("type"); temp_stat .addColName(temp_col_name ); temp_stat .addColType(temp_col_type ); //System.out.println("NAME="+temp_col_name+" >> TYPE="+temp_col_type); } mapping.addSQLFromLoad(el_id ,temp_stat ); //System.out.println("READ FROM FILE: " + el_id + " > " + temp_stat.toString()); } } } } } return true; } else { return false ; } } catch (JDOMException e) { throw new Exception(e.getLocalizedMes sage()); } } /** * Return the data as String */ public String getAsXMLText() { Document jdoc = this.getAsXMLDocumentJDOM (); org.jdom.output .DOMOutputter outp = new org.jdom.output.DOMOutputter(); XMLOutputter fmt = new XMLOutputter(" return fmt.outputString(jdoc); ",true); } /** * Return the data as XML Document (org.w3c.dom.Document) */ public org.w3c.dom.Document getAsXMLDocumentW3C() { Document jdoc = this.getAsXMLDocumentJDOM (); org.jdom.output .DOMOutputter outp = new org.jdom.output.DOMOutputter(); try { org.w3c.dom.Document result = outp.output(jdoc); return result; //and return the result } catch (JDOMException e) { System .out.println("DOM Serializer error for debug output!"); return null; } } /** * Return the data as XML Document org.jdom.Document */ public Document getAsXMLDocumentJDOM() { //MAKE DOCTYPE DocType docType = new DocType(XMLPROJECTFILEROOT,XMLPROJECTFILEDTD ); Element root = new Element (XMLPROJECTFILEROOT); //initialsetup Element init = new Element ("initialsetup" ); for (Enumeration e = this.initial.elements(); e.hasMoreElements();) { dataItem ditem = (dataItem)e.nextElement(); Element init_item = new Element("inititem" ).setText(ditem .getValue()); init_item.setAttribute ("key",ditem.getKey()); init.addContent(init_item); } root.addContent (init); //db setup Element dbitems = new Element("databasesetup"); for (Enumeration e = this.dbs.elements(); e.hasMoreElements();) { dbItem dbitem = (dbItem)e.nextElement (); Element db_item = new Element("dbitem"); db_item.addContent(new db_item.addContent(new db_item.addContent(new db_item.addContent(new db_item.addContent(new db_item.addContent(new Element("name" ).setText(dbitem.getName())); Element("driver").setText(dbitem.getDriver())); Element("url").setText(dbitem .getUrl())); Element("timeout").setText(dbitem.getTimeout ())); Element("username").setText(dbitem .getUsername())); Element("password").setText(dbitem .getPassword())); dbitems.addContent(db_item); } root.addContent (dbitems); //schema setup Element schms = new Element("schemasetup" ); Autor: Thomas Schädler 271 Anhang B: Quelltext <xmlizer> server for (Enumeration e = this.xml.elements(); e.hasMoreElements();) { xmlItem sitem = (xmlItem)e.nextElement(); Element schms_item = new Element("xmlitem" ); schms_item.addContent(new Element("name").setText(sitem.getName())); schms_item.addContent(new Element("file").setText(sitem.getFile())); schms.addContent (schms_item ); } root.addContent (schms); //module mapping setup Element mapping = null; try { mapping = getMapping(); } catch(Exception ex) { System .out.println("getMapping() in projectData == NULL, should only happen if there is an error in the DB2XML Mapping."); mapping = null; } if (mapping != null) { root.addContent(mapping); } Document doc = new Document(root,docType); return doc; //and return the doc } /** * Get the DB2XML-Mapping */ public DB2XMLmapping DB2XMLgetmapping() { return this.mapping; } /** Resets the whole mapping info (handle with care) */ public void DB2XMLclearmapping () { this.mapping = new DB2XMLmapping(); } /** * Returns the mapping element filled with the xml -mapping-data * for the currently selected module */ private Element getMapping() { dataItem datitem = (dataItem)getInitialByKey("module"); String mappingName = datitem.getValue(); if (mappingName .equalsIgnoreCase("Simple DB Export" )) { //Simple DB Export Mapping buildup Element wrapper = new Element("mapping"); Element smdbe_wrapper = new Element("smdbe"); boolean NONempty = false; //set true for not null output for (Enumeration e = this.dbs.elements(); e.hasMoreElements();) { dbItem dbitem = (dbItem )e.nextElement(); Vector selTab = (Vector )dbitem.SMDBEgetSelectedTables (); if (selTab.size()>0) { Element curr_db = new Element("smdbe_item"); curr_db.setAttribute("name",dbitem .getName()); curr_db.setAttribute("type",dbitem .SMDBEgetOutputType()); for (Enumeration enum = selTab.elements (); enum.hasMoreElements();) { NONempty = true; curr_db.addContent(new Element("smdbe_table").setText((String)enum.nextElement())); } smdbe_wrapper.addContent (curr_db); } } wrapper.addContent(smdbe_wrapper ); if (NONempty) { return wrapper; } else { return null; } } else if (mappingName .equalsIgnoreCase("Database to XML")) { //Database to XML buildup return this.mapping.getMapping(); } else { //failsafe only, should NEVER happen, though return null; } } }/* * DB2XMLmapping.java - UNTOUCHED * * This class contains all neccessary information on the mapping of the module * DB2XML (for building it and getting it for save) * * Created on 15. Juni 2002, 13:38 * ---------------------------------------------------------------------------* This file is part of <xmlizer>. * * <xmlizer> is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. Autor: Thomas Schädler 272 Anhang B: Quelltext <xmlizer> server * * Foobar is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with <xmlizer>; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * ---------------------------------------------------------------------------*/ package server; import java.util.*; import org.jdom.*; /** * Represents the projectData * @author [email protected] * @version 0.2 */ public class DB2XMLmapping { private String rootElement = null; private Vector otherElements = new Vector(); //of SchemaElements private Hashtable loadedElementNames = new Hashtable(); //of key=id,value=name(ambigous) private Hashtable loadedAttributes = new Hashtable (); //of SchemaAttri butes private Hashtable loadedSQL = new Hashtable(); //of SQLStatements private Hashtable loadedReps = new Hashtable(); //of Strings key=elementid,value=sqlid private Hashtable loadedContent = new Hashtable(); //of SchemaContent private Hashtable loadedParameters = new Hashtable (); //of ParameterInfo /** Creates new DB2XMLmapping */ public DB2XMLmapping(){} public DB2XMLmapping(String rootElementName) { this.rootElement = rootElementName; } /* * Set the root element */ public void setRootElement(String rootElementName) { this.rootElement = rootElementName; } /** * Adds a repetition info for the specified element to the list * a Hashtable with key=elementname,value=sqlid/mapid */ public void addElementRepFromLoad(String elementid ,String sqlid) { this.loadedReps .put(elementid,sqlid); } public Hashtable getLoadedReps () { return this.loadedReps; } /** * Adds an element name to the list of known elements */ public void addElementFromLoad (String name,String id) { if (id!= null && name != null) { this.loadedElementNames.put(id,name); } } /** * Adds an Element to the list and returns true if new (not loaded from xmlizer.xml) else false */ public boolean addElement(SchemaElement el) { if (el != null) { if (this.loadedElementNames .containsKey(el.getID())) { this.otherElements .add(el); //System.out.println(el.getID() + " -> " + el.getRealName() + " known & added"); return false ; } else { this.otherElements .add(el); //System.out.println(el.getID() + " -> " + el.getRealName() + " added"); return true; } } else return false; } public Vector getElements() { return this.otherElements; } /* * Set the root element */ public String getRootElement() { return rootElement; } /** * adds a SQLStatement to the list */ public void addSQLFromLoad(String id, SQLStatement statement ) { if (this.loadedSQL.containsKey(id)) //add to Vector { Vector temp_vec = (Vector)this.loadedSQL.get(id); Autor: Thomas Schädler 273 Anhang B: Quelltext <xmlizer> server temp_vec.add(statement ); //System.out.println("addSQLFromLoad NEW: " + statement.toString()); } else //add new Vector with current SQLStatement as first one { Vector temp_vec = new Vector(); temp_vec.add(statement ); this.loadedSQL.put(id,temp_vec); //System.out.println("addSQLFromLoad ADD: " + statement.toString()); } } /** * Return a Hashtable full of happy SQLStatements * key: elementname (to attach to) + attributename (combined key) * value: SQLStatement */ public Hashtable getLoadedSQL() { return this.loadedSQL; } /** * Returns the appropriate SQLStatement for a mapid */ public SQLStatement getSQLStatementByMapID(String mapid ) { for (Enumeration e = this.loadedSQL.elements(); e.hasMoreElements();) { Vector element = (Vector)e.nextElement(); for (Enumeration ee = element.elements(); ee.hasMoreElements();) { SQLStatement item = (SQLStatement )ee.nextElement (); if (item.getID().equalsIgnoreCase (mapid)) { return item; } } } return null; } /** * adds a SchemaAttribute to the list */ public void addAttributeFromLoad(String id, SchemaAttribute attr) { this.loadedAttributes.put(id + attr.getName(),attr); } /** * returns the parameters (hashtabel key=id,value=ParameterInfo */ public Hashtable getParameters () { return this.loadedParameters; } /** * Returns the appropriate SQLStatement for a mapid */ public ParameterInfo getParameterByMapID (String mapid) { for (Enumeration e = this.loadedParameters.elements (); e.hasMoreElements();) { ParameterInfo item = (ParameterInfo)e.nextElement(); if (item.getID().equalsIgnoreCase(mapid)) { return item; } } return null; } /** * adds a ParameterInfo to the list * returns true if add was successfull * else false (= no insert) */ public boolean addParameterFromLoad (String id , String name, String value) { if (!this.loadedParameters .containsKey(name)) { //System.out.println("NOT FOUND - ADDING"); this.loadedParameters.put(name,new ParameterInfo(id,name,value )); return true; } else { /*System.out.println("FOUND - DO NOTHING");*/ return false; } } /** * Removes the specified (name) parameter */ public boolean removeParameter (String name_to_remove) { if (this.loadedParameters.containsKey(name_to_remove)) { this.loadedParameters.remove(name_to_remove); return true; } else return false; } /** * adds a SchemaContent to the list */ public void addContentFromLoad (String id , SchemaContent cont ) { this.loadedContent.put(id,cont); } /** * Return a Hashtable full of happy SchemaAttributes * key: elementname (which it belongs to) + attributename * value: SchemaAttribute */ public Hashtable getLoadedAttributes() { Autor: Thomas Schädler 274 Anhang B: Quelltext <xmlizer> server return this.loadedAttributes; } /** * Return a Hashtable full of happy SchemaContent * key: elementname (which it belongs to) * value: SchemaContent */ public Hashtable getLoadedContent() { return this.loadedContent; } public Element getMapping() { if (this.rootElement == null) //check for validity { return null; } else { //DB2XML Mapping buildup Element wrapper = new Element("mapping"); Element db2xml_wrapper = new Element("db2xml"); //root element db2xml_wrapper.setAttribute ("rootelement",this.rootElement); wrapper.addContent(db2xml_wrapper); //add the parameters for (Enumeration e = this.loadedParameters .elements(); e.hasMoreElements ();) { ParameterInfo item = (ParameterInfo)e.nextElement(); Element curr = new Element("db2xml_parameter"); curr.setAttribute("id",item.getID ()); curr.setAttribute("name",item.getName()); curr.setAttribute("default",item.getValue()); db2xml_wrapper.addContent(curr); } //add the elements for (Enumeration e = this.otherElements.elements(); e.hasMoreElements();) { SchemaElement item = (SchemaElement)e.nextElement(); Element curr = new Element("db2xml_element" ); curr.setAttribute("name",item.getRealName()); curr.setAttribute("id",item.getID ()); //build content if (item.hasContent()) { SchemaContent cont = item.getContent(); curr.addContent(cont.getAsJDOMElement()); } //build repetition info (attribute repsql) if (item.getRepetition() != null) { curr.setAttribute("repsql",item.getRepetition()); } //build attributes for (Enumeration enum = item.getAttributes().elements (); enum.hasMoreElements();) { SchemaAttribute attr = (SchemaAttribute )enum.nextElement(); curr.addContent(attr.getAsJDOMElement()); } //build sql for (Enumeration enum = item.getSQLStatements().elements(); enum.hasMoreElements();) { SQLStatement stat = (SQLStatement)enum.nextElement(); curr.addContent(stat.getAsJDOMElement()); } //add the element db2xml_wrapper.addContent(curr); } return wrapper; } } } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * dataItem.java This class representates a database item consisting of the following stuff with a get and set method each String String String String String String name driver url timeout username password -> ... every variable has its get ans set methods But more important: This class contains different methods for handling database connections Created on 18. April 2002, 20:20 ---------------------------------------------------------------------------This file is part of <xmlizer>. <xmlizer> is free software; you can redistribute i t and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Foobar is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with <xmlizer>; if not, write to the Free Software Autor: Thomas Schädler 275 Anhang B: Quelltext <xmlizer> server * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * ---------------------------------------------------------------------------*/ package server; import import import import java.sql.*; java.util.*; javax.swing .*; javax.swing .table.*; /** * Represents a dbItem * @author [email protected] * @version 0.2 */ public class dbItem { private String tname; private String tdriver; private String turl; private String ttimeout; private int ttimeoutint; private int tstart = 0; private int chunkSize = 25; private boolean hasLimit = true; private String tusername ; private String tpassword ; private boolean isConnected = false ; private Connection connection = null; private Vector tableList = null; private boolean stopNOW = false; private Hashtable navigator; private String getCountSQL = new String(); private String lastSQL = new String (); private Vector selectedTables = new Vector(); private String outputType = "simple"; //little global helpers private SQLStatement lastStatement = null; //CONSTRUCTORS //----------------------------------------------------------------------------------------------/** * Constructors for a new dbItem * -> holds: * String name * String driver * String url * String timeout * int timeoutint * String username * String password */ public dbItem(String name,String driver,String url ,String timeout ,String username,String password) { this.tname = name; this.tdriver = driver; this.turl = url; this.ttimeout = timeout; this.ttimeoutint = ConvertString2int(timeout); this.tusername = username; this.tpassword = password; } public dbItem(String name,String driver,String url ,String timeout ,String username) { this.tname = name; this.tdriver = driver; this.turl = url; this.ttimeout = timeout; this.ttimeoutint = ConvertString2int (timeout); this.tusername = username; this.tpassword = new String(); } public dbItem(String name,String driver,String url ,String timeout ) { this.tname = name; this.tdriver = driver; this.turl = url; this.ttimeout = timeout; this.ttimeoutint = ConvertString2int (timeout); this.tusername = new String(); this.tpassword = new String(); } public dbItem(String name,String driver,String url ) { this.tname = name; this.tdriver = driver; this.turl = url; this.ttimeout = new String (); this.tusername = new String(); this.tpassword = new String(); } public dbItem(String name,String driver) { this.tname = name; this.tdriver = driver; this.turl = new String(); this.ttimeout = new String (); this.tusername = new String(); this.tpassword = new String(); } public dbItem(String name) { this.tname = name; this.tdriver = new String(); this.turl = new String(); this.ttimeout = new String (); this.tusername = new String(); this.tpassword = new String(); } public dbItem() { this.tname = new String(); this.tdriver = new String(); Autor: Thomas Schädler 276 Anhang B: Quelltext <xmlizer> server this.turl = new String(); this.ttimeout = new String (); this.tusername = new String(); this.tpassword = new String(); } //STRING REPRESENTATION //----------------------------------------------------------------------------------------------/** * By default show the key as String */ public String toString() { return tname; } //HELPER METHODS //----------------------------------------------------------------------------------------------public static int ConvertString2int (String string) { try { Integer to = new Integer(string); return to.intValue(); } catch(NumberFormatException ex) { return 25; //failsafe } } public static String Convertint2String(int integer) { try { Integer to = new Integer(integer); return to.toString(); } catch(NumberFormatException ex) { return "25"; //failsafe } } //THREAD ABORT FLAG MANAGEMENT //----------------------------------------------------------------------------------------------public void halt() { this.stopNOW = true; } private void goon() { this.stopNOW = false ; } //LIMITERS //----------------------------------------------------------------------------------------------public String getLastSQL () { return this.lastSQL; } public void clearLastStatement () { this.lastStatement = null; } public SQLStatement getLastStatement() { return this.lastStatement; } public void updateLastSQLSQL(String s) { if (this.lastStatement != null) { this.lastStatement.setSQL(s); } } public void nextChunk() { setLimitStart(tstart + chunkSize); } public void lastChunk() { setLimitStart(Math.max(tstart - chunkSize ,0)); } private void setLimitStart(int i) { this.tstart = i; } public void resetLimit() { setLimitStart(0); } public void setChunkSize (int i) { this.chunkSize = i; } public int getChunkSize() { return this.chunkSize; } /** * Returns the limit as appendable SQL String * e.g: " LIMIT 0,25", per default if never set */ private String getLimit() { return new String(" LIMIT " + tstart + "," + chunkSize); } /** * Enables/Disables the automatic limit */ Autor: Thomas Schädler 277 Anhang B: Quelltext <xmlizer> server public void setLimit(boolean bool) { this.hasLimit = bool; } public boolean hasLimit() { return hasLimit ; } public void setCountSQL(String s) { this.getCountSQL = s; } public String getCountSQL() { return getCountSQL; } //GET AND SET METHODS //----------------------------------------------------------------------------------------------public Hashtable getNavigator() { return navigator; } /** * Get the name of the dbitem */ public String getName() { return this.tname; } /** * Get the driver of the dbitem */ public String getDriver() { return this.tdriver; } /** * Get the url of the dbitem */ public String getUrl() { return this.turl; } /** * Get the timeout of the dbitem */ public String getTimeout () { return this.ttimeout ; } public int getTimeoutAsInt() { return ttimeoutint; } /** * Get the username of the dbitem */ public String getUsername() { return this.tusername; } /** * Get the password of the dbitem */ public String getPassword() { return this.tpassword; } /** * Set the name of the dbitem */ public void setName(String s) { this.tname = s; } /** * Set the driver of the dbitem */ public void setDriver(String s ) { this.tdriver = s; } /** * Set the url of the dbitem */ public void setUrl(String s) { this.turl = s; } /** * Set the timeout of the dbitem */ public void setTimeout(String s) { this.ttimeout = s; this.ttimeoutint = ConvertString2int (s); } /** * Set the username of the dbitem */ public void setUsername(String s) { this.tusername = s; } /** Autor: Thomas Schädler 278 Anhang B: Quelltext <xmlizer> server * Set the password of the dbitem */ public void setPassword(String s) { this.tpassword = s; } //SELECTED TABLES FOR SMDBE MAPPING AND EXPORT AND FOR THE OUTPUT TYPE //----------------------------------------------------------------------------------- -----------public void SMDBEsetSelectedTables(Vector v) { this.selectedTables = v; } public Vector SMDBEgetSelectedTables() { return this.selectedTables ; } public void SMDBEselectTable(String tablename ) { if (!this.selectedTables.contains(tablename)) { this.selectedTables.add(tablename); } } public void SMDBEdeselectTable (String tablename) { if (this.selectedTables.contains(tablename)) { this.selectedTables.remove(tablename); } } public void SMDBEsetOutputType (String type) { this.outputType = type; } public String SMDBEgetOutputType() { return this.outputType; } //DATABASE CONNECTION METHODS //----------------------------------------------------------------------------------------------public boolean isConnected() { return isConnected; } public void closeConnection() { this.tableList = null; if (isConnected ) { try { isConnected = false; connection.close(); } catch(Exception ex) { //ok } } } synchronized public Connection getConnection() throws Exception { if (!isConnected) { makeConnection(); } while(!isConnected) { if (stopNOW) { throw new Exception("Could not connect to database " + tname + "."); } } return connection; } /** * Tries to create connection * in the thread in order not to "hang" the application */ synchronized private void makeConnection () throws Exception { try { Class.forName(tdriver); DriverManager.setLoginTimeout(ttimeoutint); if(tusername.equalsIgnoreCase(new String())) { connection = DriverManager.getConnection(turl); isConnected = true; //System.out.println("Connection to database " + tname + " successful!"); } else { connection = DriverManager.getConnection(turl,tusername,decryptSecurePassword(tpassword)); isConnected = true; //System.out.println("Connection to database " + tname + " successful!"); } } catch(Exception ex) { //System.out.println("Connection " + tname + " not possible!"); throw new Exception("Could not establish connection " + tname + "."); } } //DATABASE ACCESS METHODS //----------------------------------------------------------------------------------------------/** * Returns a Vector of all tables for this DB as listItems where * each listItem has a name, the number or rows and a boolean flag if it should be selected */ public Vector getTableList() throws Exception { if(tableList == null) { Vector result = new Vector(); ResultSet rs = getConnection().getMetaData ().getTables(null, null, null, new String[]{"TABLE"}); Autor: Thomas Schädler 279 Anhang B: Quelltext <xmlizer> server Statement stmt = getConnection().createStatement(); while(rs.next()) { //table name String res = rs.getString("TABLE_NAME" ); //rows int rows = 0; ResultSet srs = stmt.executeQuery ("SELECT COUNT(*) FROM " + res); if(srs.next()) { rows = srs.getInt(1); } //mark the listitems as selected or not depending on read in data boolean isThisSelected = false; if (selectedTables != null && selectedTables.size() > 0) { if (selectedTables.contains(res)) { isThisSelected = true; } } listItem item = new listItem (res,rows,isThisSelected); result.add(item); } tableList = result; } return tableList; } private String checkSQL(String sql) { //System.out.println("Checking SQL for limit-tag in: " + sql); StringBuffer countSQL = new StringBuffer("SELECT COUNT(*)"); boolean hadFrom = false; if (this.hasLimit) { boolean theLimit = false; //FIXME limit kann auch ein tablename sein!!! besserer SQL check StringTokenizer tokenizer = new StringTokenizer (sql); while (tokenizer .hasMoreTokens()) { String currentToken = tokenizer.nextToken(); if (hadFrom || currentToken.equalsIgnoreCase(new String("from"))) { hadFrom = true; countSQL .append(" "); countSQL .append(currentToken); } if (currentToken.equalsIgnoreCase (new String("limit"))) { theLimit = true; } } setCountSQL (countSQL.toString()); if (!theLimit) { return sql + getLimit(); } else { setLimit(false); return sql; } } else { return sql; } } /** * Runs a specified SQL Query on the DB connection * and returns a Hashtable containing the different data to preceed * Note: allways use this function to query the DB! */ synchronized public Hashtable query (String sqlQuery) throws Exception { lastSQL = sqlQuery; Statement stmt = getConnection().createStatement(); int MaxRowCount = 0; if (hasLimit) { sqlQuery = checkSQL(sqlQuery); String countSQL = getCountSQL(); ResultSet srs = stmt.executeQuery(countSQL ); if(srs.next()) { MaxRowCount = srs.getInt(1); } } //System.out.println("DB QUERY: " + sqlQuery); ResultSet rs = stmt.executeQuery(sqlQuery ); ResultSetMetaData rsmd = rs.getMetaData(); int cols = rsmd.getColumnCount(); int rowNumber = 0; Vector vector = new Vector (5, 5); Vector collables = new Vector(); //of String Vector colltypes = new Vector(); //of String Vector collsizes = new Vector(); //of Integer Vector collnames = new Vector(); //of String //build collumnvector (with the names of the columns) for(int i=1;i<=cols;i++) { if (stopNOW) { goon(); throw new Exception("Aborted by user."); } collables.add(rsmd.getColumnLabel(i)); colltypes.add(rsmd.getColumnTypeName(i)); collsizes.add(new Integer(rsmd.getColumnDisplaySize(i))); Autor: Thomas Schädler 280 Anhang B: Quelltext <xmlizer> server collnames.add(rsmd.getColumnName (i)); } //build rowvector while(rs.next()) { if (stopNOW) { goon(); throw new Exception("Aborted by user."); } rowNumber++; for(int i=1;i<=cols;i++) { if (stopNOW) { goon(); throw new Exception("Aborted by user." ); } //use the types here to get it right FIXME vector.add(rs.getString (i)); } } int rows = rowNumber ; if (MaxRowCount == 0) { MaxRowCount = rows; } String info[][] = new String[cols][rows]; vector.trimToSize(); int row = 0; int col = 0; for(int i=0;i<vector .size();i++) { if (stopNOW) { goon(); throw new Exception("Aborted by user."); } try { info[col][row] = vector .get(i).toString(); } catch(NullPointerException ex) { info[col][row] = ""; } if(col+1 == cols) { col = -1; row++; } col++; } Hashtable navData = new Hashtable(); if (hasLimit) { navData.put("first",Convertint2String (this.tstart+1)); if ((this.tstart + chunkSize) > this.tstart + rows) { navData.put("last" ,Convertint2String(this.tstart + rows)); } else { navData.put("last" ,Convertint2String(this.tstart + chunkSize)); } navData.put("max",Convertint2String(MaxRowCount )); if (MaxRowCount > this.tstart + chunkSize) { navData.put("hasNext",new Boolean(true)); } else { navData.put("hasNext",new Boolean(false)); } if (this.tstart != 0) { navData.put("hasLast",new Boolean(true)); } else { navData.put("hasLast",new Boolean(false)); } } else { navData.put("first",Convertint2String (this.tstart+1)); navData.put("last",Convertint2String(rows)); navData.put("max",Convertint2String(rows)); navData.put("hasNext",new Boolean(false)); navData.put("hasLast",new Boolean(false)); } this.navigator = navData; Hashtable result = new Hashtable(); result.put("table",info); result.put("columnname",collnames); result.put("columnsize",collsizes); result.put("columnlabels",collables); result.put("columntypes",colltypes); result.put("rows",new Integer(rows)); result.put("cols",new Integer(cols)); return result; } private Statement getStatement (int limit ) throws Exception { Statement stmt = getConnection().createStatement(); if (limit != 0) { stmt.setFetchSize(limit); } return stmt; } /** * Runs a specified SQL Query on the DB connection but in silent mode * Silent mode: just a clean query, no other data changed (for background and long running threads) * Attention: no metadata and paging available in this mode and it does not care about limit checking etc... * and returns a Hashtable containing the different data to preceed * Note: allways use this function to query the DB in clean mode (without changing something in this class! */ synchronized public Hashtable querySilent(String sqlQuery) throws Exception { return querySilentWithLimit(sqlQuery ,0); } /** * Runs a specified SQL Query on the DB connection but in silent mode with rowlimit Autor: Thomas Schädler 281 Anhang B: Quelltext <xmlizer> server * Silent mode: just a clean query, no other data changed (for background and long running threads) * Attention: no metadata and paging available in this mode and it does not care about limit checking etc... * and returns a Hashtable containing the different data to preceed * Note: allways use this function to query the DB in clean mode (without changing something in this class! */ synchronized public Hashtable querySilentWithLimit (String sqlQuery,int limit) throws Exception { Statement stmt = getStatement(limit); //System.out.println("DB QUERY (SILENT): " + sqlQuery); ResultSet rs = stmt.executeQuery(sqlQuery ); ResultSetMetaData rsmd = rs.getMetaData(); int cols = rsmd.getColumnCount(); int rowNumber = 0; Vector vector = new Vector (5, 5); Vector collables = new Vector(); //of String Vector colltypes = new Vector(); //of String Vector collsizes = new Vector(); //of Integer Vector collnames = new Vector(); //of String //build collumnvector (with the names of the columns) for(int i=1;i<=cols;i++) { if (stopNOW) { goon(); throw new Exception("Aborted by user."); } collables.add(rsmd.getColumnLabel(i)); colltypes.add(rsmd.getColumnTypeName(i)); collsizes.add(new Integer(rsmd.getColumnDisplaySize(i))); collnames.add(rsmd.getColumnName (i)); } //build rowvector while(rs.next()) { if (stopNOW) { goon(); throw new Exception("Aborted by user."); } rowNumber++; for(int i=1;i<=cols;i++) { if (stopNOW) { goon(); throw new Exception("Aborted by user." ); } //use the types here to get it right FIXME vector.add(rs.getString (i)); } } int rows = rowNumber ; String info[][] = new String[cols][rows]; vector.trimToSize(); int row = 0; int col = 0; for(int i=0;i<vector .size();i++) { if (stopNOW) { goon(); throw new Exception("Aborted by user."); } try { info[col][row] = vector .get(i).toString(); } catch(NullPointerException ex) { info[col][row] = ""; } if(col+1 == cols) { col = -1; row++; } col++; } Hashtable result = new Hashtable(); result.put("table",info); result.put("columnname",collnames); result.put("columnsize",collsizes); result.put("columnlabels",collables); result.put("columntypes",colltypes); result.put("rows",new Integer(rows)); result.put("cols",new Integer(cols)); return result; } //QUASI-SECURE PASSWORD HANDLING //----------------------------------------------------------------------------------------------public static String decryptSecurePassword(String encrypted) { //decrpyt StringBuffer decrypted = new StringBuffer (); char[] sec_char = new char[]{'x','m','l','i','z','e','r'}; int inkr = 0; char aktual; StringBuffer current = new StringBuffer(); for (int j=0;j<encrypted.length ();j++) { aktual = encrypted.charAt(j); if (aktual == ':') { if (inkr<sec_char.length-1){inkr++;}else{inkr=0;} String gotcha = current.toString(); current = new StringBuffer(); // renew buffer Integer goti = new Integer(gotcha ); int gotint = goti.intValue(); int decr = gotint ^ sec_char [inkr]; decrypted.append((char)decr); } else { current.append(aktual); } } return decrypted.toString(); } }/* * xmlItem.java * * This class representates a xml file item consisting of the following stuff * with a get and set method each Autor: Thomas Schädler 282 Anhang B: Quelltext <xmlizer> server * * String name * String file * * -> ... every variable has its get ans set methods * * But more important: This class contains different methods for handling * xml file access and manipulation * * Created on 16. May 2002, 20:20 * ---------------------------------------------------------------------------* This file is part of <xmlizer>. * * <xmlizer> is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Foobar is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with <xmlizer>; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * ---------------------------------------------------------------------------*/ package server; import java.io.*; import java.util.*; /** * Represents a xmlItem * @author [email protected] * @version 0.2 */ public class xmlItem { private String tname; private String tfile; //CONSTRUCTORS //----------------------------------------------------------------------------------------------/** * Constructors for a new xmlItem * -> holds: * String name * String file */ public xmlItem(String name,String file) { this.tname = name; this.tfile = file; } public xmlItem(String name) { this.tname = name; this.tfile = new String(); } public xmlItem() { this.tname = new String(); this.tname = new String(); } //STRING REPRESENTATION //----------------------------------------------------------------------------------------------/** * By default show the key as String */ public String toString() { return this.tname; } //HELPER METHODS //----------------------------------------------------------------------------------------------//GET AND SET METHODS //----------------------------------------------------------------------------------------------/** * Get the name of the dbitem */ public String getName() { return this.tname; } /** * Get the driver of the dbitem */ public String getFile() { return this.tfile; } /** * Set the name of the dbitem */ public void setName(String s) { this.tname = s; } /** * Set the driver of the dbitem */ public void setFile(String s) { this.tfile = s; } Autor: Thomas Schädler 283 Anhang B: Quelltext <xmlizer> server } /* * SQLStatement.java * * This class contains all neccessary info for SQL Statements * * Created on 24. Juli 2002, 14:35 * ---------------------------------------------------------------------------* This file is part of <xmlizer>. * * <xmlizer> is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Foobar is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with <xmlizer>; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * ---------------------------------------------------------------------------*/ package server; import java.util.*; import org.jdom.*; /** * Represents a SQL Statement * @author [email protected] * @version 0.2 */ public class SQLSt atement { private private private private private private String db = null; String sql = null; String id = null; int rowNumber = 0; Vector colnames = new Vector(); Vector coltypes = new Vector(); /** Creates new SQLStatement * / /** * Creats a new Statement with the given id */ public SQLStatement (String db,String sql ,String id ) { this.db = db; this.sql = sql; this.id = id; } /** * Creates a new Statement with a generated (unique) id */ public SQLStatement (String db,String sql ,Vector cols,Vector types ,int rows) { UniqueID ID = new UniqueID (); this.id = ID.get(); this.db = db; this.sql = sql; this.colnames = cols; this.coltypes = types; this.rowNumber = rows; //System.out.println("ROWNUMBER: " + rows); } /** * Creates a new Statement with the given id and given vectors */ public SQLStatement (String db,String sql ,String id ,Vector co ls,Vector types ) { this.id = id; this.db = db; this.sql = sql; this.colnames = cols; this.coltypes = types; } /* * Set the db */ public void setDB(String name) { this.db = name; } /* * Set the sql statement */ public void setSQL(String sql) { this.sql = sql; } /* * Set the sql statement */ public void setCols(Vector hash) { this.colnames = hash; } /* * Set the sql statement */ public void setColTypes(Vector hash ) { Autor: Thomas Schädler 284 Anhang B: Quelltext <xmlizer> server this.coltypes = hash; } /* * Get the db */ public String getDB () { return this.db; } /* * Get the sql statement */ public String getSQL() { return this.sql; } public void setRowNumber (int r) { //System.out.println("SETROWNUMBER: " + this.rowNumber); this.rowNumber = r; } public int getRowNumber() { //System.out.println("GETROWNUMBER: " + this.rowNumber); return this.rowNumber; } public Vector getCols() { return this.colnames ; } /** * Returns the columns as Vector of SQLColumnInfo (ad hoc type) */ public Vector getColsAsSQLColumnInfo() { Vector itemcols = new Vector(); int counter = 0; for (Enumeration e = this.colnames.elements(); e.hasMoreElements();) { String this_col_name = (String)e.nextElement(); String this_col_type = (String)this.coltyp es.get(counter); itemcols.add(new SQLColumnInfo(this.id,this_col_name ,this_col_type)); counter++; } return itemcols ; } /** * Returns the columns as Vector of ColumnItems (ad hoc type) */ public Vector getColsAsColumnInfo() { Vector itemcols = new Vector(); int counter = 0; for (Enumeration e = this.colnames.elements(); e.hasMoreElements();) { String this_col_name = (String)e.nextElement(); String this_col_type = (String)this.coltypes.get(counter); itemcols.add(new ColumnInfo (this.id,this_col_name,this_col_type)); counter++; } return itemcols ; } public Vector getColTypes() { return this.coltypes; } /** * Add a name to the colname-vector */ public void addColName(String name) { if (name != null) { this.colnames.add(name); } } /** * Add a name to the coltype-vector */ public void addColType(String type) { if (type != null) { this.coltypes.add(type); } } /** * Returns the mapid */ public String getID () { return this.id; } public String toString() { return this.db + " -> " + this.sql + " [" + this.colnames.size() + "]"; } public Element getAsJDOMElement() { if (this.db == null || this.id == null || this.sql == null || this.colnames == null || this.coltypes == null) //check for validity { return null; } else { Element curr = new Element("db2xml_sql"); curr.setAttribute("id",this.id); curr.setAttribute("db",this.db); curr.setAttribute("sql",this.sql); Autor: Thomas Schädler 285 Anhang B: Quelltext <xmlizer> server if (this.colnames.size() > 0 && this.colnames.size() == this.coltypes.size()) { int counter = 0; for (Enumeration e = this.colnames.elements (); e.hasMoreElements();) { Element sub = new Element("db2xml_sql_info"); String item = (String)e.nextElement(); sub.setAttribute("name",item); sub.setAttribute("type",(String)this.coltypes.get(counter)); counter++; curr.addContent(sub); } } return curr; } } }/* * uniqueID.java * * ---------------------------------------------------------------------------* This file is part of <xmlizer>. * * <xmlizer> is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Foobar is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with <xmlizer>; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * ------------------------------------------------------------------ ---------*/ package server; import java.lang.*; /** * Builds a class returning uniqueID's (based on system time and secured through syncronisiation) * @author [email protected] */ public class UniqueID { static long current = System.currentTimeMillis(); /** * Returns a uniqueID as long */ static public synchronized long getLong() { return current++; } /** * Returns a uniqueID as String */ static public synchronized String get() { String str = new String(); str = str.valueOf(current++); return str; } }/* * SQLColumnInfo.java * * Created on 25. Juli 2002, 02:47 * ---------------------------------------------------------------------------* This file is part of <xmlizer>. * * <xmlizer> is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Foobar is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with <xmlizer>; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * ---------------------------------------------------------------------------*/ package server; /** * Represents info for a column of a SQL table * @author [email protected] * @version 0.2 */ class SQLColumnInfo { protected String id ; protected String name; protected String type; public SQLColumnInfo(String id ,String name,String type) { this.id = id; this.name = name; this.type = type; } public String getID () { return this.id; } Autor: Thomas Schädler 286 Anhang B: Quelltext <xmlizer> server public String getName() { return this.name; } public String getType() { return this.type; } public String toString() { return this.name + " [" + this.type + "]"; } } /* * ColumnInfo.java * * Created on 25. Juli 2002, 02:47 * ---------------------------------------------------------------------------* This file is part of <xmlizer>. * * <xmlizer> is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Foobar is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNE SS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with <xmlizer>; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * ---------------------------------------------------------------------------*/ package server; /** * Represents the columnInfo of a db table * @author [email protected] * @version 0.2 */ class ColumnInfo { protected String id ; protected String name; protected String type; public ColumnInfo(String id,String name,String type) { this.id = id; this.name = name; this.type = type; } public String getID () { return this.id; } public String getName() { return this.name; } public String getType() { return this.type; } public String toString() { return this.name + " [" + this.type + "]"; } }/* * listItem.java * * Created on 22. Mai 2002, 12:44 * ---------------------------------------------------------------------------* This file is part of <xmlizer>. * * <xmlizer> is free software; you can redistribute it and/or modify * it under the t erms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Foobar is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with <xmlizer>; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * ---------------------------------------------------------------------------*/ package server; /** * Represents the metadata of a table * @author [email protected] * @version 0.2 */ class listItem { private String name ; private int rowcount; private boolean selected = false; public listItem(String name,int rowcount ) { this.name = name; this.rowcount = rowcount; Autor: Thomas Schädler 287 Anhang B: Quelltext <xmlizer> server } public listItem(String name,int rowcount ,boolean marked ) { this.name = name; this.rowcount = rowcount; this.selected = marked; } public String toString() { return this.name + " (" + this.rowcount + ")"; } public String getName() { return this.name; } public int getRowCount() { return this.rowcount ; } public boolean isSelected() { return this.selected ; } public void toggleSelection() { if (this.selected) { this.selected = false; } else { this.selected = true; } //System.out.println("ListItem " + name + " is now " + selected); } }/* * ParameterInfo.java * * Created on 25. Juli 2002, 02:47 * ---------------------------------------------------------------------------* This file is part of <xmlizer>. * * <xmlizer> is free software; you can redistribute it and/or modify * it under the terms of the GNU General Pu blic License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Foobar is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with <xmlizer>; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * ---------------------------------------------------------------------------*/ package server; import java.util.*; import org.jdom.*; /** * Represents the parameterinfo (name and value) * @author [email protected] * @version 0.2 */ class ParameterInfo { protected String id ; protected String name; protected String value; public ParameterInfo(String id ,String name,String value ) { this.id = id; this.name = name; this.value = value; } public String getID () { return this.id; } public String getName() { return this.name; } public String getValue() { return this.value; } public String toString() { return this.name + " (" + this.value + ")"; } public Element getAsJDOMElement() { if (this.name == null || this.value == null) //check for validity { return null; } else { Element curr = new Element("db2xml_parameter"); curr.setAttribute("name",this.name); curr.setAttribute("default" ,this.value); return curr; } } } Autor: Thomas Schädler 288 Anhang B: Quelltext <xmlizer> server /* * SchemaElement.java * * This class representates a Schema Element * * Created on 18. April 2002, 20:20 * ---------------------------------------------------------------------------* This file is part of <xmlizer>. * * <xmlizer> is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Foobar is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with <xmlizer>; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * ---------------------------------------------------------------------------*/ package server; import import import import org.jdom.*; java.util.*; javax.swing .*; javax.swing .tree.*; /** * Represents a SchemaElement - slightly adjusted from the configurator * @author [email protected] * @version 0.2 */ public class SchemaElement { private String id; private String tname; private String trealname ; private Element telement ; private Vector attributes = new Vector(); //of SchemaAttributes private SchemaContent content; private Vector children = new Vector(); private JPanel tpanel = null; private String type = null; private String typeRef = null; private boolean hasInternalType = false; private SchemaOccurrence occurrence = null; private String documentation = null; private Vector parents = new Vector (); //of SchemaElements private DefaultMutableTreeNode node = null; private ProjectManager mother = null; //schemaElement-Data public String SCHEMAattributeFormDefault = new String("unqualified"); public String SCHEMAelementFormDefault = new String("unqualified" ); public String SCHEMAtargetNameSpace = new String(""); public String SCHEMAversion = new String (""); public String SCHEMAlanguage = new String(""); //type handling private SchemaType theType = null; //SQL private Vector SQLStatements = new Vector(); //of SQLStatement private String repetitionStatement = null; //CONSTRUCTORS //----------------------------------------------------------------------------------------------public SchemaElement(ProjectManager conf ,DefaultMutableTreeNode node,String name ,Element element ) { this.mother = conf; this.tname = name; this.node = node; this.telement = element; if (name.equalsIgnoreCase("<schema>" )) //special treatment { this.tpanel = new JPanel(new java.awt.GridLayout(7,1)); this.tpanel .add(new JLabel("XML Schema root element" )); this.tpanel .add(new JLabel("-----------------------")); this.trealname = "schema root"; //disableRefresh(); } else if (name.equalsIgnoreCase("-=sequence=-")) { this.tpanel = new JPanel(); this.tpanel .add(new JLabel("Sequence of elements:")); this.trealname = "sequence"; disableRefresh(); } else if (name.equalsIgnoreCase("-=choice= -")) { this.tpanel = new JPanel(); this.tpanel .add(new JLabel("Choice of elements:")); this.trealname = "choice"; disableRefresh(); } else if (name.equalsIgnoreCase("-=all=-")) { this.tpanel = new JPanel(); this.tpanel .add(new JLabel("All elements:" )); this.trealname = "all" ; disableRefresh(); } else if (name.equalsIgnoreCase("-=group=-")) { this.tpanel = new JPanel(); this.tpanel .add(new JLabel("Group of elements:" )); this.trealname = "group"; Autor: Thomas Schädler 289 Anhang B: Quelltext <xmlizer> server disableRefresh(); } else if (name.equalsIgnoreCase("<any>")) { this.tpanel = new JPanel(); this.tpanel .add(new JLabel("Any elements):")); this.trealname = "any" ; disableRefresh(); } process(); } public SchemaElement(ProjectManager conf ,DefaultMutableTreeNode node,Element element,String idpath) { this.id = idpath; this.mother = conf; this.tname = null; this.node = node; this.telement = element; } /** * Constructor for special elements (no precessing, just showing the right name */ public SchemaElement(ProjectManager conf ,DefaultMutableTreeNode node,String name ) { this.mother = conf; this.tname = name; this.node = node; this.telement = null; if (name.equalsIgnoreCase("<schema>" )) //special treatment { this.tpanel = new JPanel(new java.awt.GridLayout(7,1)); this.tpanel .add(new JLabel("XML Schema root element" )); this.tpanel .add(new JLabel("-----------------------")); this.trealname = "schema root"; //disableRefresh(); } else if (name.equalsIgnoreCase("-=sequence=-")) { this.tpanel = new JPanel(); this.tpanel .add(new JLabel("Sequence of elements..." )); this.trealname = "sequence" ; disableRefresh(); } else if (name.equalsIgnoreCase("-=choice= -")) { this.tpanel = new JPanel(); this.tpanel .add(new JLabel("Choice of elements...")); this.trealname = "choice"; disableRefresh(); } else if (name.equalsIgnoreCase("-=all=-")) { this.tpanel = new JPanel(); this.tpanel .add(new JLabel("All elements...")); this.trealname = "all" ; disableRefresh(); } else if (name.equalsIgnoreCase("-=group=-")) { this.tpanel = new JPanel(); this.tpanel .add(new JLabel("Group of elements...")); this.trealn ame = "group"; disableRefresh(); } else if (name.equalsIgnoreCase("<any>")) { this.tpanel = new JPanel(); this.tpanel .add(new JLabel("Wildcard Component (any)")); this.trealname = "any" ; disableRefresh(); } } //Initialization of the data //----------------------------------------------------------------------------------------------private void process() { if (this.tname != null && this.tname .equalsIgnoreCase("<schema>")) { Attribute attr = null; attr = this.telement.getAttribute("attributeFormDefault"); if (attr != null) { SCHEMAattributeFormDefault = attr.getValue().trim(); } this.tpanel .add(new JLabel("attributeFormDefault : " + SCHEMAattributeFormDefault)); attr = this.telement.getAttribute("elementFormDefault"); if (attr != null) { SCHEMAelementFormDefault = attr.getValue().trim(); } this.tpanel .add(new JLabel("elementFormDefault : " + SCHEMAelementFormDefault )); attr = this.telement.getAttribute("targetNamespace"); if (attr != null) { SCHEMAtargetNameSpace = attr.getValue().trim(); } this.tpanel .add(new JLabel("targetNamespace : " + SCHEMAtargetNameSpace)); attr = this.telement.getAttribute("version"); if (attr != null) { SCHEMAversion = attr.getValue().trim(); } this.tpanel .add(new JLabel("version : " + SCHEMAversion)); attr = this.telement.getAttribute("xml:lang"); if (attr != null) { SCHEMAlanguage = attr.getValue().trim(); } this.tpanel .add(new JLabel("xml:lang : " + SCHEMAlanguage )); } } Autor: Thomas Schädler 290 Anhang B: Quelltext <xmlizer> server //FIXME - Process the types correctly or delete it for the fucks sacke public void processType(Element typeElement) { this.theType = new SchemaType(); //theType.processType(typeElement); } public void processTypeRef(Element typeElement) { this.theType = new SchemaType(); //theType.processTypeRef(typeElement); } public void processInternalType() { this.theType = new SchemaType(); //theType.processInternalType(this.telement); } private StringBuffer addOccurrenceString (StringBuffer name) { if (getOccurrence() == null) { return name; } else { name.append (this.occurrence .getShortOcc()); return name; } } public void addDocumentation(String doc) { if(!doc.equalsIgnoreCase("")) { this.documentation = doc; } } public String getDocumen tation () { return this.documentation; } public void addAttribute (Element attr,Hashtable loadedAttribs) { SchemaAttribute newattr = new SchemaAttribute(attr); //System.out.print("IN ELEMENT " + this.trealname); if (loadedAttribs.containsKey(this.id + newattr.getName())) //an element of this name loaded { //add a new attribute, but fill it with the loaded info SchemaAttribute loaded = (SchemaAttribute)loadedAttribs.get(this.id + newattr.getName()); newattr.setMapID (loaded.getMapID ()); newattr.setMapInfo(loaded.getMapInfo()); this.attributes.add(newattr); //System.out.println("ADDED ATTR: " + newattr.getName() + " >> " + newattr.getMapID() + " >> " + n ewattr.getMapInfo()); //System.out.print(" ADDED WITH LOAD:" + newattr.getName() + " \n"); } else //add a new (clean) attribute { this.attributes.add(newattr); //System.out.print(" ADDED CLEAR: " + newattr.getName() + "\n"); } } public void setID(String n) { this.id = n; } public String getID () { return this.id; } public boolean hasContent() { if (this.content != null) { return true; } else return false; } public SchemaContent getContent() { return this.content; } public void setContent(SchemaContent cont) { if (cont != null) { this.content = cont; //System.out.println(cont); } } public Vector getAttributes() { return this.attributes; } public boolean hasType() { if (this.type != null) { return true; } else { return false; } } public boolean hasTypeRef() { if (this.typeRef != null) { return true; } else { return false; } } Autor: Thomas Schädler 291 Anhang B: Quelltext <xmlizer> server public void setInternalType() { this.hasInternalType = true; } public boolean hasInternalType () { return this.hasInternalType; } public void setRealName(String n) { this.trealname = n; } public String getRealName() { return this.trealname; } /** * Add a name to the parent-vector: holds names of parent SchemaElements */ public void addParent(SchemaElement parent) { this.parents.add(parent); } public Vector getParents () { return this.parents; } //SQL STATEMENTS //----------------------------------------------------------------------------------------------//for the (linked) repetition public void setRepetition(String sqlid) { this.repetitionStatement = sqlid; } public String getRe petition() { return this.repetitionStatement ; } public SQLStatement getRepetitionStatement() { if (this.repetitionStatement != null) { return mother.getProjectData().DB2XMLgetmapping ().getSQLStatementByMapID (this.repetitionStatement); } else return null; } //for the statments of the element public void addSQLStatement(SQLStatement stat ) { if (stat != null) { this.SQLStatements.add(stat); } } public Vector getSQLStatements () { return this.SQLStatements; } //STRING REPRESENTATION //----------------------------------------------------------------------------------------------/** * By default show the key as String */ public String toString() { return this.tname; } //GET AND SET METHODS //----------------------------------------------------------------------------------------------public void setElement(Element element) { this.telement = element; process(); } public Element getElement() { return this.telement ; } public void setName(String name) { StringBuffer buff = new StringBuffer (name); buff = addOccurrenceString (buff); this.tname = buff.toString (); } public String getName() { return this.tname; } public void setType(String type) { if (!type.equalsIgnoreCase ("")); { this.type = type; } } public void setTypeRef(String typeref) { if (!typeref.equalsIgnoreCase("")) { this.typeRef = typeref ; } } public String getType() { return this.type; } public String getTypeRef () { return this.typeRef; Autor: Thomas Schädler 292 Anhang B: Quelltext <xmlizer> server } public SchemaOccurrence getOccurrence() { return this.occurrence; } public void setOccurrence(SchemaOccurrence occ) { this.occurrence = occ; } //GRAPHIC REPRESENTATION //----------------------------------------------------------------------------------------------private boolean refresh = true; private void enableRefresh() { this.refresh = true; } private void disableRefresh() { this.refresh = false ; } public boolean isRefresh () { return this.refresh; } private JLabel getDragTargetForRepetition(String rep_short_name) { return new JLabel("Repetition: " + rep_short_name); } }/* * SchemaType.java * * Created on 24. Juli 2002, 11:59 * * This represents the neccessary info for a type of a SchemaElement * ---------------------------------------------------------------------------* This file is part of <xmlizer>. * * <xmlizer> is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Foobar is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with <xmlizer>; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * ---------------------------------------------------------------------------*/ package server; import org.jdom.*; import java.util.*; import javax.swing .*; /** * Represents the type of a SchemaElement (currently unused) * @author [email protected] * @version 0.2 */ public class SchemaType { private String tname = null; //name= //CONSTRUCTORS //----------------------------------------------------------------------------------------------public SchemaType() { //none for now } public void setName(String name) { this.tname = name; } public String getName() { return this.tname; } //TYPE PROCESSING //----------------------------------------------------------------------------------------------public void processType(Element typeElement) { //name Attribute attr = null; attr = typeElement.getAttribute ("name"); if (attr != null) { this.tname = attr.getValue().trim(); } //System.out.println("TYPE: " + typeElement.getName()); List kids = typeElement.getChildren(); //"element",namespace Iterator kids_iter = kids.iterator(); while (kids_iter.hasNext()) { Element xmlelem = (Element) kids_iter .next(); if (xmlelem.getName().equalsIgnoreCase("complexType" )) //can conatain new elements { List subkids = xmlelem.getChildren(); //"element",namespace Iterator subkids_iter = subkids.iterator(); while (subkids_iter.hasNext()) { Element dxmlelem = (Element) subkids_iter.next(); if (dxmlelem.getName().equalsIgnoreCase ("simpleContent")) { List dsubkids = dxmlelem.getChildren(); //"element",namespace Autor: Thomas Schädler 293 Anhang B: Quelltext <xmlizer> server Iterator dsubkids_iter = dsubkids.iterator(); while (dsubkids_iter.hasNext()) { } } else if (dxmlelem.getName().equalsIgnoreCase ("complexContent")) { } else if (dxmlelem.getName().equalsIgnoreCase ("group")) { } else if (dxmlelem.getName().equalsIgnoreCase ("all")) { } else if (dxmlelem.getName().equalsIgnoreCase ("choice")) { } else if (dxmlelem.getName().equalsIgnoreCase ("sequence")) { } else if (dxmlelem.getName().equalsIgnoreCase ("attribute")) { } } } else if (xmlelem.getName().equalsIgnoreCase("simpleType")) //no more deeper elements { List subkids = xmlelem.getChildren(); //"element",namespace Iterator subkids_iter = subkids.iterator(); while (subkids_iter.hasNext()) { Element dxmlelem = (Element) subkids_iter.next(); if (dxmlelem.getName().equalsIgnoreCase ("restriction")) { } else if (dxmlelem.getName().equalsIgnoreCase ("list")) { } else if (dxmlelem.getName().equalsIgnoreCase ("union")) { } } } } } public void processTypeRef(Element typeElement) { //System.out.println("TREF:" + typeElement.getName()); } public void processInternalType(Element typeElement) { //System.out.println("ITYP: " + typeElement.getName()); } //STRING REPRESENTATION //----------------------------------------------------------------------------------------------/** * By default show the key as String */ public String toString() { return this.tname; /* if (this.ttype == null && this.ttyperef != null) //has a typeref { return this.tname + " - " + this.ttyperef + " [" + this.tuse + "]"; } else if (this.ttype != null && this.ttyperef == null) //has a type { return this.tname + " - " + this.ttype + " [" + this.tuse + "]"; } else //has nothing of both (should not happen -> invalid) { return this.tname + " - !noType! [" + this.tuse + "]"; }*/ } }/* * SchemaContent.java * * Created on 25. Juli 2002, 02:47 * ---------------------------------------------------------------------------* This file is part of <xmlizer>. * * <xmlizer> is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Foobar is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with <xmlizer>; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * ---------------------------------------------------------------------------*/ package server; import org.jdom.*; import java.util.*; import javax.swing .*; /** * Represents the content of a SchemaElement Autor: Thomas Schädler 294 Anhang B: Quelltext <xmlizer> server * @author [email protected] * @version 0.2 */ class SchemaContent { protected String elementname; protected String mapid; protected String mapinfo ; public SchemaContent(){} public SchemaContent(String elementname) { this.elementname = elementname; } public SchemaContent(String elementname,String mapid,String mapinfo) { this.elementname = elementname; this.mapid = mapid; this.mapinfo = mapinfo; } public String getElementName() { return this.elementname; } public String getMapID() { return this.mapid; } public String getMapInfo () { return this.mapinfo; } /** Cleans the mapinfo of this content */ public void cleanMapping () { this.mapid = null; this.mapinfo = null; //System.out.println(this.tname); } //SETTERS public void setMapID(String id ) { if (id != null) { this.mapid = id; } } public void setMapInfo(String info) { if (info != null) { this.mapinfo = info; } } public String toString() { return "<" + this.elementname + ">" + this.mapid + ":" + this.mapinfo + "</" + this.elementname + ">"; } public Element getAsJDOMElement() { Element curr = new Element ("db2xml_content"); if (this.mapid != null) { curr.setAttribute("mapid",this.mapid); } if (this.mapinfo != null) { curr.setAttribute("mapinfo" ,this.mapinfo); } //System.out.println("<" + this.elementname + ">" + this.mapid + ":" + this.mapinfo + "</" + this.elementname + ">"); return curr; } } /* * SchemaOccurrence.java * * Created on 4. April 2002, 15:48 * ------------------------------------ ---------------------------------------* This file is part of <xmlizer>. * * <xmlizer> is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Foobar is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with <xmlizer>; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * ---------------------------------------------------------------------------*/ package server; import java.lang.Integer; /** * Represents the occurrence of a SchemaElement (repetition) * @author [email protected] * @version 0.2 */ public class SchemaOccurrence { /** The identifier for this constraint */ private String identifier; /** Minimum inclusive value allowed */ private Integer minOccurs; Autor: Thomas Schädler 295 Anhang B: Quelltext <xmlizer> server /** Maximum exclusive value allowed */ private Integer maxOccurs; private boolean maxUnbounded = false; /** * <p> * This will create a new <code>SPConstraint</code> with the specified * identifier as the "name". * </p> * * @param identifier <code>String</code> identifier for <code>SPConstraint</code>. */ public SchemaOccurrence(String identifier) { this.identifier = identifier; //init values to default this.minOccurs = new Integer(1); this.maxOccurs = new Integer(1); } /** * <p> * This will return the identifier for this <code>SPConstraint</code>. * </p> * * @return <code>String</code> - identifier for this constraint. */ public String getIdentifier() { return identifi er; } /** * <p> * This will set the minimum allowed value for this data type (inclusive). * </p> * * @param minInclusive minimum allowed value (inclusive) */ public void setMinOccurs (String min ) { if (min != null) { Integer min_int = Integer.valueOf(min); this.minOccurs = min_int; } } /** * <p> * This will return the minimum allowed value for this data type (inclusive). * </p> * * @return <code>double</code> - minimum value allowed (inclusive) */ public Integer getMinOccurs() { return this.minOccurs; } /** * <p> * This will set the maximum allowed value for this data type (inclusive). * In case of unbounded the value shall be Integer.MAX_VALUE * </p> * * @param minInclusive minimum allowed value (inclusive) */ public void setMaxOccurs (String max ) { if (max != null) { if (max.equalsIgnoreCase("unbounded")) { this.maxUnbounded = true; this.maxOccurs = new Integer(Integer.MAX_VALUE); } else { Integer max_int = Integer.getInteger(max); this.maxOccurs = max_int; } } } /** * Return true if this element can be repeated more than once */ public boolean hasRepeat () { if ((getMinOccurs().intValue() == 1) && (getMaxOccurs().intValue() == 1)) { return false; } else if (getMaxOccurs().intValue() > 1) { return true; } else { return false; } } /** * <p> * This will return the minimum allowed value for this data type (inclusive). * </p> * * @return <code>double</code> - minimum value allowed (inclusive) */ public Integer getMaxOccurs() { return maxOccurs; } /** * Returns a short occurrence description as String Autor: Thomas Schädler 296 Anhang B: Quelltext <xmlizer> server */ public String getShortOcc() { if ((getMinOccurs().intValue() == 1) && (getMaxOccurs().intValue() == 1)) { return " [1]"; } else { StringBuffer buff = new StringBuffer(" ["); buff.append (getMinOccurs()); buff.append(".."); if (this.maxUnbounded == true) { //buff.append("\u221E"); //means "infinite symbol" in unicode buff.append("max"); //unicode is font dependant! no good idea } else { buff.append(getMaxOccurs()); } buff.append ("]"); return buff.toString(); } } }/* * SchemaAttribute.java * * This class representates a Schema Attribute * * Created on 18. Mai 2002, 20:52 * ---------------------------------------------------------------------------* This file is part of <xmlizer>. * * <xmlizer> is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Foobar is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with <xmlizer>; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * ---------------------------------------------------------------------------*/ package server; import org.jdom.*; import java.util.*; import javax.swing .*; /** * Represents a SchemaAttribute * @author [email protected] * @version 0.2 */ public class SchemaAttribute { private String tname = null; //name= private String ttype = null; //type= private String ttyperef = null; //ref= private String tuse = new String("optional"); //use= private String mapid = null; private String mapinfo = null; private Element tattribute; private String tannotation = null; //CONSTRUCTORS //----------------------------------------------------------------------------------- -----------public SchemaAttribute(Element attribute ) { this.tattribute = attribute; process(); } public if if if } SchemaAttribute(String name,String mapid,String mapinfo) { (name != null) { this.tname = name; } (mapid != null) { this.mapid = mapid; } (mapinfo != null) { this.mapinfo = mapinfo; } //Initialization of the data //----------------------------------------------------------------------------------------------private void process() { if (this.tattribute != null) { Attribute attr = null; //name attr = this.tattribute .getAttribute("name" ); if (attr != null) { this.tname = attr.getValue().trim(); } //type attr = this.tattribute .getAttribute("type" ); if (attr != null) { this.ttype = attr.getValue().trim(); } //ref attr = this.tattribute .getAttribute("ref"); if (attr != null) { this.ttyperef = attr.getValue().trim(); } //use attr = this.tattribute .getAttribute("use"); Autor: Thomas Schädler 297 Anhang B: Quelltext <xmlizer> server if (attr != null) { this.tuse = attr.getValue().trim(); } } } /** Cleans the mapinfo of this attribute */ public void cleanMapping () { this.mapid = null; this.mapinfo = null; //System.out.println(this.tname); } //SETTERS public void setMapID(String id ) { if (id != null) { this.mapid = id; } } public void setMapInfo(String info) { if (info != null) { this.mapinfo = info; } } //GETTERS public String getMapID() { return this.mapid; } public String getMapInfo () { return this.mapinfo; } public Element getAttribute() { return this.tattribute; } public String getType() { return this.ttype; } public String getTypeTef () { return this.ttyperef ; } public String getUse() { return this.tuse; } public String getName() { return this.tname; } //STRING REPRESENTATION //----------------------------------------------------------------------------------------------/** * By default show the key as String */ public String toString() { StringBuffer result = new StringBuffer(); //display the name if (this.ttype == null && this.ttyperef != null) //has a typeref { result .append(this.tname + " - " + this.ttyperef + " [" + this.tuse + "]"); } else if (this.ttype != null && this.ttyperef == null) //has a type { result .append(this.tname + " - " + this.ttype + " [" + this.tuse + "]"); } else //has nothing of both (should not happen -> invalid) { result .append(this.tname + " - !noType! [" + this.tuse + "]"); } //display the mapid if there is one if (this.mapid != null) { result .append(" > " + this.mapid); } if (this.mapinfo != null) { result .append(" : " + this.mapinfo); } return result.toString(); } public Element getAsJDOMElement() { if (this.tname == null) //check for validity { return null; } else { Element curr = new Element("db2xml_attribute"); curr.setAttribute("name",this.tname); if (this.mapid != null) { curr.setAttribute("mapid",this.mapid); } if (this.mapinfo != null) { curr.setAttribute("mapinfo",this.mapinfo); } return curr; } } } Autor: Thomas Schädler 298 Ehrenwörtliche Erklärung Autor: Thomas Schädler 299