Swarovski Shop Administration Program

Transcription

Swarovski Shop Administration Program
HTBLuVA Innsbruck
Höhere Lehranstalt für Elektronik
Ausbildungsschwerpunkt: Technische Informatik
DIPLOMARBEIT
SSAP
Swarovski Shop Administration Program
Ausgeführt im Schuljahr 2012/13 von:
Betreuer:
Tobias Lanzanasto
Gregor Neumann
Michael Plattner
Dipl.- lng. Mag(FH) Felix Klingler
Innsbruck, am 22.05.2013
Diplomarbeit
Lanzanasto, Neumann, Plattner
Eidesstattliche Erklärung
Wir erklären an Eides statt, dass wir die vorliegende
Diplomarbeit selbstständig und ohne fremde Hilfe
verfasst, andere als die angegebenen Quellen und
Hilfsmittel nicht benutzt und die den benutzten
Quellen wörtlich und inhaltlich entnommen Stellen als
solche erkenntlich gemacht haben.
Verfasser:
Lanzanasto Tobias
Innsbruck, am 22.05.2013
Neumann Gregor
Plattner Michael
Seite 1
Diplomarbeit
Lanzanasto, Neumann, Plattner
Kurzbeschreibung
Die Diplomarbeit befasst sich mit dem Shop Administration Program für das
Unternehmen Swarovski. Unser Projekt soll das jahrelang verwendete Excel File,
welches zur Shop Administration verwendet wird, ablösen.
Die Grundidee zur Verbesserung der Administration besteht darin, die Shops in eine
Datenbank zu importieren und diese mittels eines User Interfaces zu verwalten.
Das Projekt kann in folgende Teile unterteil werden:
1. Daten Import in die Datenbank
Mithilfe eines Visual Basic Programmes sollen die Daten des Excel Files in die
Datenbank importiert werden. Dies geschieht einmalig zur Einführung dieses
Projektes.
2. Datenbank
Die MySQL Datenbank dient zur Speicherung aller Daten. Sie ermöglicht das
schnelle Suchen und Editieren der Datensätze.
3. Benutzeroberfläche
Um die Datenbank einfach zu verwalten wird mit Java-RCP eine
Benutzeroberfläche programmiert. Über diese kann man Datensätze in der
MySQL Datenbank suchen, editieren, hinzufügen und löschen.
Seite 2
Diplomarbeit
Lanzanasto, Neumann, Plattner
Summary
This work covers the Swarovski Shop Administration Program for the company
Swarovski. It should replace the current Excel-File to administrate Swarovski
shops used for years.
The main theory to improve the administration is to fill a database with all
information about the shops and manage this database with a specific user
interface.
This project can be divided into following parts:
1. Import data into the database (Visual Basic)
Import the data from the Excel file into the database by using a Visual Basic
Program. This is done only once for the implementation of this project.
2. Database (MySQL)
The MySQL database is used to store all data. The database allows quick
searching and editing of the records.
3. User Interface
The User Interface is programmed with Java-RCP-technology, to enable
simple managing of the database. With the UI is it possible to search, edit,
add and remove data from the database.
Seite 3
Diplomarbeit
Lanzanasto, Neumann, Plattner
Inhaltsverzeichnis
1.
Einleitung............................................................................................................. 6
1.1. Verlauf Diplomarbeit ...................................................................................... 6
1.2. Zielsetzung und Aufgabenstellung................................................................. 7
1.3. Aufbau der Diplomarbeit ................................................................................ 8
1.4. Partnerfirma ................................................................................................... 9
2.
Visual Basic Import ............................................................................................ 10
2.1. Allgemein ..................................................................................................... 10
2.2. Excel File ..................................................................................................... 11
2.3. Microsoft Visual Basic 2010 ........................................................................ 12
2.4. Programmübersicht ..................................................................................... 13
2.4.1. Connection Excel .................................................................................. 13
2.4.2. Connection DB ...................................................................................... 14
2.4.3. Import Country ...................................................................................... 14
2.4.4. Import Shops......................................................................................... 15
2.4.5. Import Hardware ................................................................................... 17
3.
MySQL Database .............................................................................................. 19
3.1. Allgemein ..................................................................................................... 19
3.2. MySQL Workbench ..................................................................................... 20
3.3. Datenbankübersicht..................................................................................... 21
4.
Java RCP Userinterface .................................................................................... 24
4.1. Allgemein ..................................................................................................... 24
4.2. Programmierumgebung ............................................................................... 24
4.2.1. Eclipse .................................................................................................. 24
4.2.2. Eclipse 4 – Eclipse Juno ....................................................................... 25
4.2.3. Subversion Client .................................................................................. 25
4.3. Java-RCP .................................................................................................... 25
4.4. JDBC ........................................................................................................... 26
4.5. Programmübersicht ..................................................................................... 27
4.5.1. Basis-Projekt ......................................................................................... 27
4.5.2. RCP-Struktur......................................................................................... 28
4.5.3. Oberfläche und Application Model ........................................................ 30
4.5.4. Verbindung zur DB................................................................................ 37
Seite 4
Diplomarbeit
Lanzanasto, Neumann, Plattner
4.5.5. Handler ................................................................................................. 43
4.5.6. Gesamttabellen ..................................................................................... 45
4.5.7. TreePart ................................................................................................ 46
4.5.8. TreeListener .......................................................................................... 50
4.5.9. Search .................................................................................................. 53
5.
4.5.10.
Statistics ............................................................................................ 57
4.5.11.
Details................................................................................................ 59
4.5.12.
Add .................................................................................................... 69
Manual/Bedienungsanleitung ............................................................................ 70
5.1. Oberfläche ................................................................................................... 70
5.2. Menü ........................................................................................................... 71
5.3. Tree ............................................................................................................. 72
5.4. Arbeitsfläche ................................................................................................ 72
5.5. Suche .......................................................................................................... 73
5.6. Neues Element hinzufügen ......................................................................... 74
5.7. Statistiken .................................................................................................... 75
5.8. Details ......................................................................................................... 75
Bilder-Verzeichnis ..................................................................................................... 78
Seite 5
Diplomarbeit
Lanzanasto, Neumann, Plattner
1. Einleitung
Diese Diplomarbeit beschreibt die Entwicklung eines neuen Shop Administrations
Programmes, das das bisherige Excel Shopfile ablösen wird. Dieses wird im
Auftrag von Swarovski im Rahmen einer Diplomarbeit verwirklicht.
1.1.
Verlauf Diplomarbeit
Dank Herrn Prof. Schwarz, Professor an unserer Schule sowie Dienstnehmer bei
Swarovski, erfuhren wir über die Möglichkeit bei Swarovski unsere Diplomarbeit
zu verfassen. Von Swarovski wurden uns grundlegende Informationen über die
Administration deren Shops gegeben, sowie der Aufbau der Excel Tabelle erklärt.
Ebenfalls wurden die zu verwendende Datenbank und die Programmiersprachen
festgelegt. Die Entwicklung, angefangen von Informationssammlungen über die
Realisierbarkeit bis hin zum funktionsfähigen Programm, war selbstständig
durchzuführen. Natürlich standen die Firma Swarovski, unser Betreuer Herrn
Prof. Klingler sowie mehrere andere Personen bei auftretenden Fragen immer
gerne zur Verfügung. Während des Sommers konnten wir ein vierwöchiges
Ferialpraktikum bei Swarovski (Außenstelle Hall) absolvieren, in welchem wir
ausschließlich an unserer Diplomarbeit arbeiteten konnten. Dies hatte für uns den
großen Vorteil, dass wir bei auftretenden Problemen und Fragen immer sofort
eine Ansprechperson hatten.
Nach dem Vertrautmachen mit der Excel Tabelle wurde der Grundstein mit der
Erstellung eines Datenbank-Strukturplanes gelegt. Alle Daten aus der Excel
Tabelle, die nicht berechnet werden können, müssen in die Datenbank
übernommen werden. Jene Informationen, die sich aus anderen Einträgen
ergeben, werden nicht in der Datenbank gespeichert, sondern direkt vom
Benutzeroberflächen-Programm aus den Datenbankeinträgen ermittelt.
Anschließend schrieben wir ein Programm zur Übertragung der Daten aus der
Excel Tabelle in die Datenbank.
Seite 6
Diplomarbeit
Lanzanasto, Neumann, Plattner
Zum Verwalten der Datenbank für den Endnutzer implementierten wir eine
Benutzeroberfläche, mit welcher Datensätze in der Datenbank erstellt, gelöscht,
editiert und gesucht werden können.
Nach Fertigstellung des Programmes wurde es Swarovski gegeben, wo es in der
Abteilung RETAIL zum Testen verwendet wird.
1.2.
Zielsetzung und Aufgabenstellung
Die Motivation der Diplomarbeit liegt darin, etwas im Fachbereich technische
Informatik zu entwickeln, sowie mit einer namhaften Firma zusammenzuarbeiten
und deren Arbeitsumfeld kennenzulernen.
Die generelle Aufgabenstellung wurde von der Firma Swarovski gestellt, jedoch
wurde uns in der Ausführung viel Spielraum gelassen. Laut Aufgabenstellung der
Firma, soll eine Lösung gefunden werden Datensätze aus einer bestehenden
Excel-Tabelle in eine MySQL-Datenbank zu übertragen. Zur Verwaltung der
Datenbank soll eine in Java Rich Client Platform (RCP) geschriebene
Benutzeroberfläche implementiert werden.
Von Seiten der Firma wurde uns nahegelegt, das Import-Programm von der Excel
Tabelle in die Datenbank mittels eines Visual Basic Programmes
zu
verwirklichen. Die Abteilung RETAIL arbeitet mit Microsoft-SQL-Datenbanken, da
diese jedoch Closed Source sind, wurde vereinbart, dass wir eine MySQLDatenbank mit einer General Public License lokal auf unseren eigenen Rechnern
für die Entwicklung des Programmes verwenden. Für die spätere Einbindung des
Programmes in die MS-SQL-Datenbank muss lediglich der Verbindungsaufbau
zur Datenbank angepasst werden, die restlichen SQL-Befele sind in ANSI-SQL
geschrieben, wodurch es zu keinen weiteren Problemen kommen sollte. Ebenso
wurde vereinbart, dass die Benutzeroberfläche mittels Java Rich Client Platform
(RCP) implementiert wird.
Zeitliche Begrenzungen gibt es seitens der Firma keine. Der Zeitplan ist uns
überlassen worden.
Seite 7
Diplomarbeit
1.3.
Lanzanasto, Neumann, Plattner
Aufbau der Diplomarbeit
Die Arbeit kann prinzipiell in drei Teilgebiete gegliedert werden:
 Visual Basic
Das Visual Basic Programm dient zur Übertragung der Datensätze
aus der Excel Tabelle in die Datenbank.
 MySQL-Datenbank
Die Aufgabe der MySQL Datenbank ist es, die Datensätze effizient,
widerspruchsfrei
und
dauerhaft
zu
speichern
und
benötigte
Datensätze in unterschiedlichen bedarfsgerechten Darstellungsformen bereitzustellen.
 Java Rich Client Platform
Das Java Rich Client Platform (RCP) Program ermöglicht die
Verwaltung der Datenbank mittels eines User-Interfaces.
Abb. 1: Grundaufbau
Diese drei Teilgebiete werden in den folgenden Seiten, in entsprechender
Reihenfolge, möglichst genau beschrieben und die Funktionen erklärt. Es wurde
darauf Wert gelegt, dass jeder Funktionsblock zuerst allgemein beschrieben wird
und erst im weiteren Verlauf auf die Details eingegangen wird.
Seite 8
Diplomarbeit
1.4.
Lanzanasto, Neumann, Plattner
Partnerfirma
Abb. 2: Firmenlogo Swarovski
Die Firma Swarovski ist ein österreichisches Familienunternehmen, welches 1895
in Wattens gegründet wurde. Zum einen produziert Swarovski Kristall diverse
Schmuckstücke aus Kristallglas, zum anderen gehören der Swarovski Gruppe
ebenfalls die Tyrolit Schleifmittel in Schwaz und die Swarovski Optik in Absam an.
Swarovski und seine Tochterunternehmen beschäftigen knapp 30.000 Mitarbeiter
in 40 Länder.
Die Standpunkte in Wattens und Hall sind durch ihre Nähe zu Innsbruck ideal für
unsere Partnerschaft.
Seite 9
Diplomarbeit
Lanzanasto, Neumann, Plattner
2. Visual Basic Import
2.1.
Allgemein
Die erste Aufgabe unserer Arbeit war es, die vorhandenen Daten der ExcelTabelle in die Datenbank zu importieren. Dies soll mit einem Programm
geschehen, das in Visual Basic geschrieben ist. Was sich zu Beginn recht einfach
anhörte, führte jedoch gleich zu einigen Schwierigkeiten. Was die Arbeit an
diesem Import-Programm erschwerte, war, dass die Struktur der Daten, die im
Excel-File verwendet wurde, nicht unbedingt geeignet für eine Datenbank war.
Somit konnten wir die einzelnen Tabellen nicht einfach in der Datenbank
übernehmen, sondern mussten zuerst eine geeignete Datenbankstruktur
zusammenstellen. Durch die neue Struktur wurde das Import-Programm jedoch
um einiges komplizierter, da nun teilweise Daten aus mehreren verschiedenen
Sheets der Excel Tabellen zusammengefasst werden mussten. Durch dieses
Zusammenfassen der Daten dauert die Ausführung des Programms auch recht
lange. Bei einem kompletten Durchlauf des Programms kommt es zu einer Dauer
von ca. 30 Minuten. Das Programm muss jedoch nur einmal ausgeführt werden,
weshalb nicht zusätzlicher Aufwand in Zeitoptimierung des Programms gesteckt
wurde.
Da dieses Programm nur zum einmaligen Importieren der Daten verwendet wird,
wäre eine aufwändige Oberfläche nicht notwendig. Daher öffnet sich beim Start
der Übertragung nur ein Konsolenfenster, das den Fortschritt des Programms
grob darstellt. Es wird angezeigt, aus welcher Excel-Tabelle gerade Daten
importiert werden und für jede erfolgreiche Übertragung wird ein Punkt auf dem
Fenster angezeigt.
Seite 10
Diplomarbeit
2.2.
Lanzanasto, Neumann, Plattner
Excel File
Bisher wurden die Shops der Firma Swarovski mit Hilfe einer Excel-Tabelle
verwaltet. Angefangen hat das vor ca. 10 Jahren mit noch einigen wenigen
Shops. Da die Firma mittlerweile stark expandiert, gibt es 1000 Shops, die auf der
ganzen Welt verteilt sind. Dadurch wurde die anfangs noch recht übersichtliche
Excel-Tabelle immer größer und mit der Zeit, durch zum Teil auch fehlerhafte
Einträge, komplizierter und unübersichtlicher.
Dieses Excel-File ist in mehrere Sheets aufgeteilt. Im ersten Sheet, dem „ROC
Info“-Sheet, sind Informationen über die einzelnen Länder gespeichert, in denen
Shops der Firma Swarovski ihren Standpunkt haben. Man kann diesem Sheet
beispielsweise entnehmen, auf welchem Kontinent das Land liegt, wie viel
Steuern zu zahlen sind oder in welcher Zeitzone es liegt. Außerdem sind
Kennungsnummern wie VG-Nummer oder Country-Code ersichtlich.
In den Sheets „EUROPE“, „AMERICAS” und „ASIA PACIFIC” sind Details zu den
einzelnen Shops gespeichert. Dabei werden im Sheet „EUROPE“ alle
europäischen Shops, im Sheet „AMERICAS“ alle Nord-, Mittel- und Südamerikanischen Shops und im Sheet „ASIA PACIFIC“ alle Shops im Raum Asien,
Ozeanien und Australien zusammengefasst. In diesen Sheets sind Informationen
wie Shop-Nummer, Shop-Name, Stadt, Land, Adresse, Telefonnummer, Verkaufsfläche und noch einiges mehr gespeichert. Zusätzlich wird die im Shop
vorhandene Hardware inklusive einiger Details angezeigt. Eine Ausnahme sind
dabei die europäischen Shops, da hier noch ein weiterer Sheet existiert, in dem
nur Informationen über die einzelnen Hardwarekomponenten zu sehen sind.
Details für Hardware sind zum Beispiel Seriennummer, Installationsdatum, Alter,
Modellbezeichnung und MAC-Adresse.
Seite 11
Diplomarbeit
Lanzanasto, Neumann, Plattner
Ein weiterer Sheet ist der „TOTALS & Licenses“-Sheet. Hier werden die Inhalte
aller anderen Sheets zu einer Statistik zusammengefasst. Es wird beispielsweise
angezeigt, wie viele Shops eines bestimmten Typs in einem Land vorhanden
sind. Außerdem sind dort Informationen zum jeweiligen Kassensystem in den
jeweiligen Ländern gespeichert.
2.3.
Microsoft Visual Basic 2010
Das Visual Basic Programm wird mit mit Hilfe der von Microsoft angebotenen
Programmierumgebung Microsoft Visual Basic 2010 Express implementiert. Für
die Verwirklichung des Import-Programms mittels Microsoft Visual Basic spricht,
dass schlussendlich sowohl eine Microsoft Datenbank also auch eine Microsoft
Excel Tabelle verwendet wird und durch die ausschließliche Verwendung von
Microsoft Produkten die hundertprozentige Kompatibilität gegeben ist.
Die Programmiersprache Visual Basic ist zwar sehr simpel und kann mit
Vorkenntnissen von C oder anderen Sprachen sehr schnell erlernt werden,
jedoch kann ein komplexes Programm sehr unübersichtlich werden. Es werden
Variablen zum Beispiel nicht als INT, VCHAR, etc. deklariert sondern alle als Dim
und das Programm erkennt den Typen automatisch, jedoch kann dadurch der
Überblick über die verschiedenen Variablen schneller verloren gehen.
Seite 12
Diplomarbeit
2.4.
Lanzanasto, Neumann, Plattner
Programmübersicht
2.4.1. Connection Excel
Um mit dem Transfer der Daten in die Datenbank beginnen zu können, muss
zuerst eine Verbindung mit dem Excel-File aufgebaut werden. Dazu wird als
erstes mit der Funktion CreateObject(„Excel-Application“) ein neues
Objekt generiert. Mit der Funktion Workbooks.Open(FileName, ,true) wird nun
eine Verbindung zum gewünschten Excel-File aufgebaut. Dabei wird das File
schreibgeschützt im Hintergrund geöffnet. Bei einem unerwarteten Programmabsturz würde das File geöffnet bleiben, daher wird es zur Vorsicht sichtbar
gemacht, um zu sehen, dass es geöffnet wurde,und man es dann zu schließen
hat.
Dim objExcel, FileName, objWorkbook
objExcel = CreateObject("Excel.Application")
FileName = "...\SR Shops - IT Info.xlsm"
objWorkbook = objExcel.Workbooks.Open(FileName, , True) ' Open Read Only
objExcel.Visible = True
Anschließend werden einzelne Unterprogramme zum Import nacheinander
gestartet. Zuerst werden die Länder übertragen, danach die Shops und zuletzt die
Hardware. Die Unterprogramme für Shops und Hardware werden immer für jeden
Kontinent einzeln gestartet, da so für eine Übertragung weniger Worksheets aus
dem Excelfile verwendet werden müssen.
Seite 13
Diplomarbeit
Lanzanasto, Neumann, Plattner
2.4.2. Connection DB
Am Beginn jedes Unterprogramms wird immer eine Verbindung zur Datenbank
aufgebaut. Für die Verbindung wird ein Connection-String benötigt, der sämtliche
Informationen zur Anmeldung enthält. Dieser besteht aus Serveradresse,
Username, Passwort und Datenbank. Mit der Funktion conn.Open() wird nun die
Verbindung eröffnet. Jetzt können MySqlCommands mit einer Abfrage in Form
eines Strings und der passenden Datenbankverbindung generiert werden, welche
anschließend mit Hilfe eines MySqlDataReaders ausgeführt werden können.
2.4.3. Import Country
Zu Beginn des Imports der Länder werden alle Einträge der „Country“-Tabelle
gelöscht. Dadurch wird das Programm stark vereinfacht, da nicht darauf geachtet
werden muss, ob ein Eintrag bereits in der Datenbank vorhanden ist und somit
keine Fehler durch Duplikate entstehen können.
Anschließend werden für jede Spalte des Datensatzes zwei Variablen erstellt. In
einer werden später die Einträge des Excel-Files zwischengespeichert, in der
anderen wird „hard coded“ angegeben, in welcher Spalte des Excel-Files der
passende Eintrag zu finden ist.
Nun wird in einer „Do Until“-Schleife für jede Zeile im Excel-File, in diesem Fall
beginnend mit Zeile 5, ein Datensatz in der Datenbank erstellt. Zum Auslesen der
Excel-Einträge können zwei Funktionen verwendet werden. Die Funktion
objWorkSheet.Cells(row, column).Text gibt einfach den Text zurück den
man beim Betrachten der Tabelle in den Zellen lesen kann. Das ist bei fast allen
Einträgen die richtige Lösung, außer bei den meisten Datumswerten. Die
Tabellen sind nämlich so formatiert, dass beispielsweise
beim Datum
„01.10.2011“ in der Zelle nur der Text „10.11“ zu sehen ist. Erst wenn man auf die
Zelle klickt, erscheint oben in der Eingabeleiste das richtige Datum. In solchen
Fällen wird die Funktion objWorkSheet.Cells(row, column).Value benötigt,
um den kompletten Wert der Zelle zu entnehmen. Außerdem ist bei
Datumswerten darauf zu achten, dass wirklich ein gültiges Datum verwendet wird,
Seite 14
Diplomarbeit
Lanzanasto, Neumann, Plattner
da es ansonsten beim Eintrag in die Datenbank zu Fehlern kommt. Daher wird
überprüft, ob der erhaltene Eintrag aus dem Excel-File stimmen kann, falls nicht,
wird er wenn möglich in ein einheitliches Datumformat umgewandelt oder durch
einen Default-Wert ersetzt.
Wenn alle Werte des Datensatzes aus dem Excel-File übernommen wurden, wird
daraus eine „INSERT INTO“-Abfrage erstellt, welche anschließend in einem
MySqlCommand verpackt und mit dem MySqlDataReader an der Datenbank ausgeführt wird. Nach einem solchen Durchlauf wird ein Punkt im Konsolenfenster
geschrieben, um den erfolgreichen Eintrag eines Datensatzes in die Datenbank
zu signalisieren.
Dieser Vorgang wird für jede ausgefüllte Zeile der Excel-Tabelle wiederholt.
2.4.4. Import Shops
Dieses Unterprogramm ist im Prinzip ähnlich gegliedert wie das zum Importieren
der Länder. Auch hier werden zu Beginn vorhandene Einträge in den Tabellen
„shopinfo.shops“ und „shopinfo.closed_shops“ der Datenbank gelöscht. Das darf
aber nur dann geschehen, wenn Daten aus dem EUROPE-Sheet (dem ersten
Sheet) des Excel-Files übertragen werden, da dieses Unterprogramm für jeden
Kontinent neue ausgeführt wird und sonst schon regulär importierte Shops wieder
gelöscht werden würden.
Anschließend werden wieder Variablen zur Zwischenspeicherung angelegt und
die passenden Spaltennummern eingetragen. Dabei muss jedoch darauf geachtet
werden, dass die drei Excel-Sheets „EUROPE“, „AMERICAS“ und „ASIA
PACIFIC“ nicht genau gleich formatiert sind, daher variieren die Spaltennummern
für bestimmte Einträge zwischen den verschiedenen Sheets.
Nun beginnt wieder die eigentliche Übertragung der Daten aus dem Excel-File in
das VB-Programm. Dieser Vorgang ist bei den Shops jedoch um einiges
komplizierter als bei den Ländern, da im Excel-File manchmal Shops ohne SAPNummer auftreten, die die einzelnen Shops identifizieren. In der neuen
Datenbank wird diese Nummer als „Primary Key“ gehandhabt und muss daher für
alle Shops eindeutig sein. Shops ohne eine solche SAP-Nummer werden als
Seite 15
Diplomarbeit
Lanzanasto, Neumann, Plattner
„Dummy-Shops“ behandelt, das heißt, sie bekommen vorübergehend die SAPNummer „999999999“, somit werden sie vom Programm als gültiger Shop
erkannt und sind gleichzeitig als Dummy-Shop gekennzeichnet. Nachdem nun
alle Daten aus dem Excel-File ausgelesen wurden, wird überprüft, ob es sich
beim vorhandenen Shop um einen Dummy-Shop handelt. Falls das der Fall ist,
wird nun eine einzigartige SAP-Nummer generiert. Diese setzt sich aus drei
Teilen zusammen. Die ersten drei Ziffern sind immer „999“. Darauf folgt die
vierstellige VG-Nummer des Landes, in dem der Shop seinen Standpunkt hat.
Diese Nummer wird dem „ROC Info“-Sheet des Excel-Files entnommen.
Abschließend wird noch die Shop-Nummer, die innerhalb eines Landes eindeutig
ist, angehängt.
Ähnlich wie Dummy-Shops werden auch VG-Shops behandelt. Sie besitzen im
Excel-File ebenfalls keine SAP-Nummer, daher muss auch hier eine Nummer
generiert werden. Auch sie setzt sich aus drei Teilen zusammen. Die ersten drei
Ziffern sind dieses Mal „802“. Darauf folgt wieder die VG-Nummer des jeweiligen
Landes. Um den VG-Shop innerhalb eines Landes zu identifizieren, wird nun die
Workstation-Nummer als zweistellige Zahl verwendet.
Danach müssen wieder Einträge überprüft und verändert werden, die für einen
Eintrag in die Datenbank nicht geeignet sind. Wie schon bei den Ländern werden
Datumswerte umformatiert bzw. durch Default-Werte ersetzt. Bei diesen Daten
kann es aber zusätzlich vorkommen, dass Namen von Shops, Shop-Managern,
Straßen oder Ähnlichem ein einfaches Hochkomma enthalten. Das führt beim
Ausführen der SQL-Abfrage zu Fehlern. Daher müssen alle einfachen
Hochkommas durch zwei einfache Hochkommas für das Einfügen in die
Datenbank ersetzt werden, sodass die Daten ohne Fehler korrekt in der
Datenbank stehen.
Beim Erstellen der SQL-Abfrage muss nun noch entschieden werden, ob der
Shop in die shopinfo.shops-Tabelle oder in die shopinfo.closed_shops-Tabelle
geschrieben werden muss. Geschlossene Shops werden dadurch gekennzeichnet, dass sich ein „X“ im Shop-Typ befindet.
Seite 16
Diplomarbeit
Lanzanasto, Neumann, Plattner
Nachdem eine passende „INSERT INTO“-Abfrage erstellt wurde, wird diese an
der Datenbank ausgeführt und dieser Vorgang für alle anderen Shops wiederholt.
2.4.5. Import Hardware
Zum Importieren der Hardware werden zwei Unterfunktionen benötigt. Die
Unterfunktion Import_hardware stellt die Hauptkomponente der Übertragung dar.
Gleich wie bei der Shop-Importierung werden auch hier zu Beginn bei der
Übertragung aus dem EUROPE-Sheet alle vorhandenen Datensätze aus der
shopinfo.hardware-Tabelle der Datenbank gelöscht. Anschließend werden auch
hier die Spaltennummern je nach Sheet gespeichert, da diese nicht bei allen
Kontinenten übereinstimmen. Eine weitere Besonderheit dabei ist, dass für
Europa ein weiterer Sheet im Excel-File existiert, der detaillierte Informationen
über die Hardware in europäischen Shops enthält, wie zum Beispiel bisherige
Standorte. Daher wird in der „DO UNTIL“-Schleife immer unterschieden, ob die
folgenden Informationen eine europäische Hardware betreffen oder eine andere.
Die allgemeinen Details werden bei beiden Möglichkeiten gleich ausgelesen.
Da es in einem Shop mehrere Hardwarekomponenten geben kann, muss die
richtige SAP-Nummer des Shops gefunden werden. Dabei wird darauf geachtet,
ob sich die Shop-Nummer ändert. Immer wenn das der Fall ist, handelt es sich
um einen neuen Shop und die Reihe in der die richtige SAP-Nummer zu finden
ist, wird aktualisiert. Anschließend werden alle notwendigen Informationen aus
dem jeweiligen Sheet des Kontinents ausgelesen. Mit Hilfe des Country-Codes
werden nun noch zusätzliche Informationen aus dem „ROC Info“-Sheet
gewonnen.
Handelt es sich um einen europäischen Shop, muss nun mit Hilfe der
Seriennummer die passende Zeile im „EUR HW Details“-Sheet herausgesucht
werden. Hier werden nun spezielle Informationen für die europäischen Shops
übertragen. Bei anderen Shops werden diese Spalten in der Datenbank mit
einem Leerstring bzw. einem Default-Wert gefüllt.
Anschließend werden die Einträge wieder überprüft und wenn notwendig
verändert. Vor allem beim „ASIA PACIFIC“-Sheet kommt es vor, dass
Seite 17
Diplomarbeit
Lanzanasto, Neumann, Plattner
Seriennummern identisch sind und sie werden daher erweitert, um sie eindeutig
identifizieren zu können. Es kommt auch vor, dass keine Seriennummer im ExcelFile eingetragen ist. Wenn dabei jedoch ein gültiger Hostname vorhanden ist, wird
eine Seriennummer als Platzhalter generiert. Diese Nummer beginnt immer mit
„unknown“. Danach kommen der Country-Code und die Nummer der Zeile, aus
der die Information stammt.
Damit auch Hardware aus einem VG-Shop richtig verknüpft werden kann, muss
wieder die SAP-Nummer generiert werden. Sie muss gleich wie beim Shop selbst
generiert werden, damit auch das gleiche Ergebnis geliefert wird und somit auch
die Verknüpfung möglich ist.
Anschließend wird wieder eine „INSERT INTO“-Abfrage erstellt und der Vorgang
für alle weiteren Hardwarekomponenten wiederholt.
Sogenannte „Retired Hardware“, also Hardware, die nicht mehr in Shops
verwendet wird, wird mit dieser Funktion nicht importiert. Für diese Einträge wird
die zweite Unterfunktion Import_retired_hardware verwendet.
Einziger Unterschied zur ersten Funktion ist, dass hier alle Informationen nur aus
dem Sheet „EUR HW Details“ kommen. Es werden jedoch nur Hardwarekomponenten importiert, die in der Spalte „active/retired“ als retired markiert sind.
Seite 18
Diplomarbeit
Lanzanasto, Neumann, Plattner
3. MySQL Database
3.1.
Allgemein
Wir verwenden zum Testen unseres Projekts eine auf unseren Rechnern lokal
installierte MySQL-Datenbank, da diese in der Basisversion eine sehr anerkannte
Freeware Lösung für eine Datenbank ist. Zum Bearbeiten der Datenbank wird
von uns die MySQL Workbench verwendet, welche wie die MySQL Datenbank
frei zur Verfügung steht. Der Entwickler der MySQL Datenbank sowie der MySQL
Workbench ist Oracle Corporation.
Die von uns eingerichtete MySQL Datenbank wird später in eine bestehende
Microsoft Datenbank von Swarovski implementiert. Da die SQL-Befehle in ANSISQL geschrieben sind, ist es unerheblich, ob eine Microsoft-SQL- oder eine
MySQL-Datenbank verwendet wird. Lediglich der Datenbankzugriff von dem
Visual Basic Programm, beziehungsweise des Java Programms muss angepasst
werden.
Um die Datenbank an sich zu übertragen, werden einfach die Create-Statements
kopiert und beim Erstellen einer weiteren Datenbank direkt ausgeführt. Es wird
dabei nur die Datenbankstruktur erstellt.
Seite 19
Diplomarbeit
3.2.
Lanzanasto, Neumann, Plattner
MySQL Workbench
Die MySQL-Workbench ist ein Modellierungswerkzeug zur Planung und Wartung
von Datenbanken. Der Entwickler dieses Modellierungstools ist Oracle Corporation
und steht es für alle gängigen Betriebssysteme zur Verfügung. Die
MySQL Workbench wird sowohl als „Community Edition“ unter der General Public
License (GPL) als auch mit zusätzlichen Funktionalitäten als „Standard Edition“
kommerziell in Form eines Jahresabos angeboten. Es wurde bei diesem Projekt
die Version 5.2.40 verwendet. Trotz umfangreichen Funktionen liegt der HauptEinsatzbereich der Workbench bei der Modellierung der Daten.
Mittels der MySQL-Workbench können Entity-Relationship-Diagramme (ERDiagramme) erstellt werden. Diese sind oft der erste Schritt bei einer Datenbank
Modellierung. Das ER-Diagramm stellt die Zusammenhänge zwischen einzelnen
Tabellen graphisch dar, wodurch ein Verlust der Übersicht über eine komplexe
Datenbankstruktur
verhindert
werden
soll.
Zusätzlich
können
Relationen
zwischen den einzelnen Tabellen definiert werden, welche die Übersicht der
Tabellenverknüpfungen verbessern sollen.
Die Verbindung zur Datenbank wurde mittels einer TCP/IP-Verbindung
ermöglicht.
Seite 20
Diplomarbeit
Lanzanasto, Neumann, Plattner
3.3.
Datenbankübersicht
Seite 21
Diplomarbeit
Lanzanasto, Neumann, Plattner
Die gesamte Datenbank besteht aus 4 miteinander verknüpften Tabellen, in der
ersten Tabelle werden die verschiedenen Länder gespeichert.
Für die einzelnen Shops gibt es zwei verschiedene Tabellen, eine für die
geöffneten Shops und eine für die geschlossenen Shops. Diese beiden Tabellen
sind im Prinzip genau gleich, sie haben nur einen einzigen Unterschied: In der
„shops“-Tabelle wird die SAP-Nummer als Primary Key verwendet, in der
„closed_shops“-Tabelle übernimmt diese Aufgabe ein automatischer Index. Das
kommt daher, dass die SAP-Nummern geschlossener Shops wieder freigegeben
sind und somit neu vergeben werden dürfen. Würde man dann einen Shop
schließen,
dessen
SAP-Nummer
mit
der
eines
geschlossenen
Shops
übereinstimmt, würde ein Fehler in der Datenbank auftreten, da der Primary Key
einzigartig sein muss. Um solchen Problemen vorzubeugen, wird hier ein
automatischer Index von der Datenbank generiert.
In der vierten und letzten Tabelle sind Informationen über die Hardware
gespeichert, die in den einzelnen Shops eingesetzt wird.
Die Pfeile im Datenbankstrukturplan stellen die einzelnen Verknüpfungen
zwischen den Tabellen dar. Diese Verknüpfungen sind in der Datenbank nicht
fest vorgegeben, sondern werden bei jeder Abfrage, bei der sie benötigt werden,
angegeben.
Die Verknüpfungen zwischen „shops“-Tabelle bzw. „closed_shops“-Tabelle und
„country“-Tabelle müssen immer korrekt sein. Sollte ein User versuchen, einen
Shop-Datensatz so zu verändern, dass die Spalte mit dem Country-Code mit
keinem Land übereinstimmt, wird eine Fehlermeldung ausgegeben.
Bei der Verknüpfung der Spalte „ship_to“ der „hardware“-Tabelle mit dem Primary
Key eines Shop-Datensatzes muss nicht unbedingt eine passende Nummer
angegeben werden. Wenn die Nummer existiert, besteht eine Verknüpfung, wenn
nicht, wird dem Programm signalisiert, dass die ausgewählte Hardware in keinem
Shop verwendet wird und somit entweder an einen neuen Shop vergeben werden
kann oder bereits ausrangiert wurde. Außerdem kann keine Hardware mit einem
geschlossenen Shop verknüpft werden, auch wenn die SAP-Nummer zufällig
zusammenstimmen würde, wären die beiden Datensätze trotzdem nicht
miteinander verknüpft.
Seite 22
Diplomarbeit
Lanzanasto, Neumann, Plattner
Die Verknüpfungen, welche strichliert zwischen Hardware und Shop eingezeichnet sind, werden vom Programm eigentlich nicht benötigt. Hierbei handelt es
sich um die Nummern der Shops, in denen die Hardware früher verwendet wurde.
Da jedoch früher andere Nummern zur Identifizierung eines Shops verwendet
wurden, stehen hier meist noch Nummern des alten Systems. Normalerweise
sollte jedoch auch hier eine gültige SAP-Nummer aufscheinen, welche auf den
vorherigen Shop hinweist.
Seite 23
Diplomarbeit
Lanzanasto, Neumann, Plattner
4. Java RCP Userinterface
Das Nachfolgende Kapitel (inkl. Bilder) wurde bis auf weiteres mit Hilfe des Buches “Eclipse 4
Application Development“ von Lars Vogel verfasst. (ISBN: 3943747034)
4.1.
Allgemein
Für das User-Interface wurde die Java-RCP (Rich Client Project) Technologie
empfohlen, weil diese plattformunabhängig ausführbar ist und leicht in RAP (Rich
Ajax Platform) für Online-Verfügbarkeit umgeschrieben werden kann.
Eine generelle Web-Application ist aus rechtlichen Gründen nicht realisierbar
gewesen.
4.2.
Programmierumgebung
Zum Programmieren der GUI verwenden wir speziell Eclipse for RCP and RAP
Developers (Juno Release) mit folgenden Add-Ons: E4 CSS Spy (incubation) und
Eclipse e4 Tools (incubation). Der Hauptdownload bietet die Möglichkeit JavaRCP zu programmieren, die Add-Ons bieten diverse Hilfen.
Zur einfacheren Abgleichung unter den Mitarbeitern wurde uns ein Subversion
Client (siehe 4.2.3. Subversion Client) von Swarovski zur Verfügung gestellt.
4.2.1. Eclipse
Eclipse ist eine Entwicklungsumgebung, welche ursprünglich zum Programmieren
von Java gedacht war. Heute kann man mit passenden Plug-Ins auch andere
Sprachen mit Eclipse programmieren. Der modulare Aufbau von Eclipse hilft beim
genauen Anpassen der Programmieroberfläche an die eigenen Bedürfnisse. Die
Formatierungstools und Autokomplettierung sind äußerst hilfreich für ein flüssiges
Programmieren.
Seite 24
Diplomarbeit
Lanzanasto, Neumann, Plattner
4.2.2. Eclipse 4 – Eclipse Juno
Eclipse 4 bietet neue Sets an Technologie, welche die Flexibilität der Eclipse
Plug-In Entwicklung erhöhen. Die letzte veröffentlichte Version von Eclipse ist
Juno, und basiert auf Eclipse 4.2. Dieses beinhaltet alle Vorteile von der Eclipse
3.x Serie, lässt aber die wunden Punkte der Version aus. Grundsätzlich sind aber
viele Konzepte von Eclipse 3 in der neuen Version vorhanden.
Es können auch weiterhin Eclipse 3.x Plug-Ins mit Eclipse 4 ohne Änderungen
ausgeführt werden.
4.2.3. Subversion Client
Mit dem entsprechenden Add-On kann von Eclipse direkt auf einen Subversion
Client
zugegriffen werden. So liegt das Projekt nicht mehr lokal auf einem
Rechner, sondern wird auf einen angegebenen Server ausgelagert. Mit einem
Update des Projektes wird die neueste Version heruntergeladen und lokal am
Rechner in einer Workspace gespeichert. Nach Änderungen im Projekt wird
dieses Commited, um diese Version wieder auf den Server zu laden. Neben der
einfachen Abgleichung mit den Mitarbeitern ist ein weiterer großer Vorteil, dass in
einer History ebenfalls Zugriff auf ältere Versionen des Projektes besteht.
4.3.
Java-RCP
Java-RCP (Rich Client Platform) ist eine bestimmte Art, wie man mit Java
programmiert. Dabei ist die Grundstruktur der große Unterschied zu „normalem“
Java. Die Sprache ist weiterhin dieselbe. Die Vorteile der Rich Client Struktur
liegen in der Anpassungsfähigkeit des Programms an das Problem und die
leichte Umsetzung in ein webbasierendes Programm.
Seite 25
Diplomarbeit
4.4.
Lanzanasto, Neumann, Plattner
JDBC
Dieses Unterkapitel (inkl. Bilder) wurde mit Hilfe der Oracle-Homepage erstellt.
http://www.oracle.com/technetwork/java/javase/jdbc/index.html (30.04.2013 17:00)
JDBC (Java Data Base Connectivity) ist eine Datenbankschnittstelle, die eine
Kommunikation
zwischen
einem
Java-Programm
und
einer
Datenbank
ermöglicht. Die JDBC API ist Bestandteil der Java-Plattform und ist somit bereits
überall vorhanden.
Im Prinzip übersetzt diese Java-Statements in für die Datenbank leserliche
Stücke und umgekehrt. Es gibt dabei vier verschiedene Typen:
Links: Typ 4
Links: Typ 1
Mit dem Pure Java JDBC Driver wird Die Java Anfrage wird zuerst in einen
ein Java Befehl direkt in einen DBMS ODBC (Open Data Base Connectivity)
Befehl übersetzt.
Code umgewandelt und muss dann auch
von
der
Datenbank
umgewandelt werden.
Seite 26
wieder
eigens
Diplomarbeit
Lanzanasto, Neumann, Plattner
Rechts: Typ 3
Rechts: Typ 2
Über eine DB Middleware wird mit der Die Java Anfrage wird in Anfragen der
Datenbank kommuniziert. Der Java eigenen
Client-API
übersetzt.
Dabei
Befehl wird dann speziell für die muss auf beiden Seiten ein zusätzlicher
vorliegende
Datenbank
übersetzt. Code hinzugefügt werden.
Java muss sich somit keine Gedanken
über die Datenbank oder sonstige
Sonderheiten machen.
Diese sind die gängigsten Methoden.
Diese beiden werden nur bei keiner
anderen Möglichkeit verwendet.
In diesem Projekt wird der Treiber-Typ 4 verwendet, weil dieser klein und
ausreichend für die Anforderungen ist.
Um diesen JDBC-Treiber verwenden zu können, muss neben der bereits
vorhandenen JDBC API noch ein Jar-File eingebunden werden. Dieses muss im
Manifest-File in den Classpath eingefügt werden.
4.5.
Programmübersicht
4.5.1. Basis-Projekt
Um das Basis-Projekt zu erstellen, verwendet man am besten den vorhandenen
Wizard, damit alle benötigten Files und Strukturen automatisch erstellt werden.
Dazu wählt man File → New → Others → Eclipse 4 → Eclipse 4 Application
Project aus und gibt einen Projektnamen an und wählt entsprechende weitere
Optionen aus.
Nachdem das Projekt erstellt wurde, kann man das .product-File auswählen, und
im Übersicht-Tab auf den Launch an Eclipse Apllication Button klicken. Das RCPProjekt startet.
Seite 27
Diplomarbeit
Lanzanasto, Neumann, Plattner
Dies kann je nach Optionenwahl schon mit Beispiel-Komponenten gefüllt sein,
wie zum Beispiel einer Menü-Leiste.
Um Fehler beim Start zu vermeiden, müssen die Plug-Ins geprüft werden und bei
Bedarf die fehlenden hinzugefügt werden. Dies geschieht im Plug-In-Tab des
Product-Files. Dort können mit dem Klick auf Add Required Plug-Ins automatisch
die fehlenden Plug-Ins hinzugefügt werden. Mit dem Aktivieren der Checkbox
Validate plug-ins prior to launching werden dann vor jedem Start des Programms
automatisch die Plug-Ins überprüft.
4.5.2. RCP-Struktur
Ein fertiges Projekt besteht aus
diversen Files und Ordnern. Wie
in der Abb. 3: Ordnerstruktur zu
erkennen ist, sind grundsätzlich
einmal die JRE (Java Runtime
Environment) System Library und
die Plug-in Dependencies vorhanden. Diese stellen die Grundfunktion von Java dar.
Im Application.e4xmi File ist die
Oberfläche des Programms definiert. Beim Öffnen dieser Datei
öffnet sich ein Tool, mit dem die
Oberfläche
verändert
kann.
Die
Oberflächenbearbei-
tung
ist
im
Kapitel
werden
Abb. 3: Ordnerstruktur
4.5.3
Oberfläche genauer beschrieben.
Das
wichtigste
File
des
Projekts
ist
das
*.product
File
(hier:
at.swarovski.rcp.shopinfo.product). Dabei handelt es sich nicht um ein Textfile,
sondern um eine graphische Oberfläche, die formularartig Parameter für das
Projekt umsetzt. In diesem File kann das Programm unter anderem auch
Seite 28
Diplomarbeit
Lanzanasto, Neumann, Plattner
gestartet werden. Dort befindet sich auch ein Export-Wizard, mit dem das Projekt
exportiert werden kann. In weiteren Reitern lassen sich z. B. die Dependencies
eintragen oder ein Branding (Icons) hinzufügen.
Im File build.properties können weitere Einstellungen zum Generieren des
Programms vorgenommen werden.
Das plugin.xml File öffnet wieder ein Optionen-Feld mit mehreren Reitern. Das
plugin.xml File ist dabei so ein Reiter. Dieses File wird automatisch erstellt und
kann nicht „per Hand“ abgeändert werden.
Mit diesem Optionen-Feld lassen sich fast alle Einstellungen für das Projekt
vornehmen. Es beinhaltet auch manche Reiter des *.product Files.
Zu diesen vorgenerierten Dateien kommen noch einige vorgenerierte Ordner und
selbsterstellte Ordner.
Im Ordner src befinden sich alle Source-Files, der Quelltext sozusagen. Diese
Files nennt man Klassen und sie sind in Packages aufgeteilt. Diese Packages
haben aber keine große Rolle, sie agieren wie Ordner.
Im ersten Package at.swarovski.rcp.shopinfo befindet sich Activator.java. Dies ist
ein automatisch generiertes File, welches für unser Projekt nicht abgeändert
werden muss.
Im Package at.swarovski.rcp.shopinfo.database sind alle notwendigen Klassen
vorhanden, um mit einer Datenbank Verbindung aufzunehmen und auch Daten
auszutauschen. Die Verbindung zur Datenbank wird im Kapitel 4.5.4 Verbindung
zur DB genauer beschrieben.
Das Package at.swarovski.rcp.shopinfo.handlers beinhaltet alle Funktionen des
Programms. Im Kapitel 4.5.5 Handler werden diese genauer beschrieben.
Im Package at.swarovski.rcp.shopinfo.listener befindet sich der Treelistener, eine
Klasse, welche das ausgewählte Item im Tree feststellen kann.
Im Package at.swarovski.rcp.shopinfo.view werden die Oberflächen der einzelnen
Parts
definiert. Im Kapitel 4.5.3 Oberfläche und Application Model wird dies
genauer beschrieben.
Seite 29
Diplomarbeit
Lanzanasto, Neumann, Plattner
Im Ordner css befindet sich das Style-Sheet File, welches für dieses Projekt nicht
verändert wird.
Im Ordner icons sind alle Icons vorhanden, die für das Projekt benötigt werden.
Sie werden z. B. in der Menüleiste verwendet.
Im Ordner lib befindet sich der Treiber für die Verbindung zur Datenbank.
Und schlussendlich befindet sich im Ordner META-INF das MANIFEST.MF.
Dieses öffnet auch das Optionen-Feld, welches weiter oben in diesem Kapitel
schon beschrieben wurde.
4.5.3. Oberfläche und Application Model
Um das Basis-Projekt an die jeweiligen Bedürfnisse des Kunden anzupassen,
muss zuerst einmal die Oberfläche verändert werden, bevor die Intelligenz
hineinprogrammiert werden kann.
Mit den zusätzlichen Tools, die nachträglich zu Eclipse hinzugefügt wurden, kann
relativ einfach die Oberfläche des Programms verändert werden. Dazu muss das
Application-File geöffnet werden. Es erscheint ein Menü, mit dem man die
benötigten Komponenten hinzufügen kann.
Die wichtigsten User Interface Komponenten einer Eclipse 4 Applikation sind
Windows, Parts, Perspectives, PartStacks und PartSashContainers.
Typischerweise besteht eine Applikation, ein Programm, aus einem Window
(Fenster). Man ist aber nicht darauf beschränkt, es ist möglich, weitere Fenster
hinzuzufügen.
Parts sind User Interface Komponenten, die einem ermöglichen, Daten zu
navigieren und zu modifizieren. Diese Parts sind meistens eingeteilt in Views und
Editors.
Diese
Unterteilung
basiert
primär
aber
nicht
auf
technischen
Unterschieden, sondern auf der Art der Verwendung dieser Parts.
Ein View wird verwendet, um ein Daten-Set, welches möglicherweise hierarchisch
aufgebaut ist, direkt zu verändern. Wird in einer View eine Änderung
vorgenommen, so geschieht diese auch direkt in der darunterliegenden DatenStruktur.
Seite 30
Diplomarbeit
Lanzanasto, Neumann, Plattner
Mit einem Editor werden einzelne Daten-Elemente verändert, zum Beispiel eine
Datei. Vorgenommene Änderungen treten aber erst in Kraft, wenn diese explizit
gespeichert werden.
Perspectives sind visuelle Container, welche Parts beinhalten. Sie werden
verwendet, um Parts für verschiedene Anwendungen zu positionieren. Parts
können in den Perspectives geöffnet, geschlossen und neu arrangiert werden.
Parts können direkt im Window oder in einer Perspective platziert werden. Um
solche Parts zu arrangieren, können PartStacks und PartSashContainer
verwendet werden. PartStacks beinhalten Parts, welche immer nur zur gleichen
Zeit dargestellt werden können. Solche PartStacks können über Tabs ausgewählt
werden.
PartSashContainer stellen den Inhalt entweder horizontal oder vertikal zur
gleichen Zeit dar.
Zu den visuellen Teilen in Eclipse (Perspectives, Parts, etc.) gibt es noch
verschiedene nicht-visuelle Komponenten wie zum Beispiel Handlers, Commands
und Key Bindings.
Bei Eclipse 4 wird das sogenannte Application Model verwendet, um die Struktur
einer Applikation zu beschreiben. In diesem Modell sind sowohl die sichtbaren als
auch die nicht sichtbaren Elemente der Oberfläche enthalten.
Jedes Element hat bestimmte Eigenschaften, welche den derzeitigen Zustand
beschreiben. Manche Elemente müssen in einer hierarchischen Struktur
angeordnet werden (Parts in Perspectives).
Dieses Application Model definiert jedoch nur die Struktur der Oberfläche und
nicht den Inhalt des User Interfaces. Es stellt die Parts zur Verfügung, wo dann
später zum Beispiel SWT-Widgets integriert werden können. Diese müssen nach
wie vor im Source-Code eingebettet werden. Das Application model entspricht
sozusagen nur einem Haus mit Räumen, der Inhalt muss extra programmiert
werden.
Seite 31
Diplomarbeit
Lanzanasto, Neumann, Plattner
Abb. 4 Application Model
Dieses
Application
Model
ist
ein
einziges
File
mit
dem
Namen
Application.e4xmi und befindet sich im Hauptverzeichnis des Projekts.
Die Verbindung der einzelnen Elemente zu den Java Klassen geschieht über
Uniform Resource Identifier (URI). Diese beschreibt den Ort, wo sich die Klasse
befindet. Die Klasse beschreibt nun den Inhalt und das Verhalten dieses Inhalts.
Wird nun ein Element aus dem Application Model aktiviert, so wird gleichzeitig die
Klasse instanziert.
4.5.3.1.
Commands, Handlers
Das Application Model kann auch Commands und Handlers beinhalten. Ein
Command ist in diesem Fall eine Beschreibung einer Aktion, wie zum Beispiel
„speichern“ oder „kopieren“.
Das Verhalten eines Commands wird bestimmt von Handler. Ein Handler definiert
eine Klasse über den contributionURI. Dieses Attribut wird als Class URI im
Model Editor dargestellt.
Solche Handler können global für die gesamte Applikation fungieren oder nur für
einzelne Parts. So kann es zum Beispiel eine Save-Aktion für die gesamte
Applikation geben, und eine eigene Save-Aktion für einen speziellen Part.
Seite 32
Diplomarbeit
4.5.3.2.
Lanzanasto, Neumann, Plattner
Menus, Toolbars
Für Windows und Parts können Menus und Toolbars erstellt werden. Menu und
Toolbar Items enthalten Referenzen zu Commands. Ist dann so ein Command
ausgewählt, wird von der Runtime der dazugehörende Handler ausgewählt.
Toolbars sind im Application Model als Trimbar eingebunden. Eine Trimbar kann
für Windows definiert werden. Es können hier zur Übersicht auch Separatoren
und Untermenüs erstellt werden.
Um eine Toolbar/Menüleiste im Fenster zu implementieren, so benötigt man
dreierlei Dinge: ein Handled Tool Item, einen Command und einen Handler.
Das Handled Tool Item beschreibt dabei die optischen Eigenschaften des
Menüeintrags. Dabei kann unter anderem der angezeigte Text, die Art des
Eintrags (Push, Radial, Check) oder ein Icon verändert werden. Diesem Item
muss noch der vorher erwähnte Command eingetragen werden.
Dem Handler müssen der Command und eine URI zugewiesen werden, denn
diese weist auf die dazugehörende Klasse in Java hin.
Schlussendlich wird bei einer Aktion mit dem Menüeintrag diese Klasse
ausgeführt.
Damit alle Änderungen im Application Model auch gleich übernommen werden,
muss im Product-Configuration-File bei im Reiter Launching beim Unterpunkt
Programm Arguments folgender Eintrag hinzugefügt werden:
-clearPersistedState
Seite 33
Diplomarbeit
4.5.3.3.
Lanzanasto, Neumann, Plattner
Inhalt des Application Model
Das Application Model beschreibt nur die Struktur des UI. Alles, was in diese
Struktur hinein kommt, Labels, Textfelder, Buttons usw., kann mit SWT-Widgets
in den Parts integriert werden. SWT bedeutet Standard Widget Toolkit und
umfasst eine große Bibliothek an diversen graphischen Ein- und AusgabeKomponenten.
Um
diese
org.eclipse.swt.widgets
zu
verwenden,
muss
und org.eclipse.swt.custom
die
Bibliothek
zuerst einge-
bunden werden.
Die Widgets werden per Snippet (Code-Besipiel) im Internet angeboten. Der
Code kann einfach in den Quellcode hineinkopiert werden.
Um diese Widgets optisch ansprechend zu positionieren, muss zuerst ein Layout
mit SWT erstellt werden. Dann kann das Widget genau positioniert werden.
SWT beitet eine Reihe von Layout-Managern. Dabei gibt es AbsoluteLayout,
FillLayout, RowLayout, GridLayout und FormLayout. Jedes Layout verfügt über
andere Eigenschaften und ist somit nicht für jeden Fall geeignet.
In diesem Projekt werden hauptsächlich GridLayouts verwendet, da diese den
Anforderungen am ehesten entsprechen. Grundsätzlich ordnet dieses die
Widgets in einer Gitterform an. Es können dabei die Anzahl der Spalten und die
Spalten- und Abstand-Größe angegeben werden.
Zu jedem Layout Manager gibt es auch noch eine Layout Data, in dem
widgetspezifische Eigenschaften eingetragen werden können. Dabei muss die
Data dem Manager entsprechen, ansonsten kommt es zu einem Fehler bei der
Ausführung des Programms.
Durch die Benützung eines GridLayouts wird das GridData Objekt verwendet.
Seite 34
Diplomarbeit
4.5.3.4.
Lanzanasto, Neumann, Plattner
Fenster-Struktur
Dieses Programm besteht aus nur einem
Window (Trimmed Window). In diesem
Window wird ein PerspectiveStack und
darin eine Perspective erstellt, um Parts
zu beherbergen. Um immer zwei Parts
gleichzeitig darstellen zu lassen benötigt
es
einen
PartSashContainer.
Dieser
trennt das Fenster vertikal in zwei Hälften,
dass die Parts nebeneinander angezeigt
werden. In diesem PartSashContainer
befinden sich zwei PartStacks.
Abb. 5: Fenster-Struktur
Einer besteht aus zwei, der andere aus drei Parts. Diese können per Tabs
durchgeschalten werden.
Am oberen Fensterrand befindet sich eine
Toolbar. Dazu muss ein Window Trim
erstellt werden, und darin eine Toolbar.
Diese wird dann mit Handled Tool Items
und Separatoren befüllt.
Abb. 6: Toolbar
Zusätzlich zu den visuellen Komponenten kommen noch acht Handlers und acht
Commands. Diese beziehen sich hauptsächlich auf die Funktionen der Toolbar.
Seite 35
Diplomarbeit
Lanzanasto, Neumann, Plattner
Abb. 7: Handlers
Abb. 8: Commands
Schlussendlich sieht die Grundstruktur des Programms, gestaltet im Application
Model wie folgt aus:
Toolbar
PartStack 1
PartStack 2
Abb. 9: Grundstruktur
Seite 36
Diplomarbeit
Lanzanasto, Neumann, Plattner
4.5.4. Verbindung zur DB
Die Verbindung zur Datenbank wird mit Hilfe der „DatabaseConnection“-Klasse
verwirklicht. Wichtig ist, dass von dieser Klasse immer nur eine Instanz existiert,
da ansonsten Fehler auftreten können, wenn gleichzeitig mehrere Verbindungen
zur Datenbank aufgebaut werden. Daher verwendet man einen sogenannten
Singleton. Somit wird beim Generieren einer solchen Instanz immer zuerst
abgefragt, ob diese schon existiert und anschließend der weitere Vorgang
entschieden.
public static DatabaseConnection getInstance() {
if (instance == null) {
instance = new DatabaseConnection();
}
return instance;
}
Innerhalb der Klasse existieren zwei verschiedene Variablen, die möglicherweise
verwechselt werden könnten.
DatabaseConnection:
Hier spricht man von der Instanz dieser Klasse, die sämtliche Informationen nach
außen hin bereithält.
Connection:
So wird die eigentliche Verbindung zur Datenbank bezeichnet.
Seite 37
Diplomarbeit
4.5.4.1.
Lanzanasto, Neumann, Plattner
Verbindungsaufbau
In der Methode „DatabaseConnection()“ wird die Verbindung zur Datenbank
mittels JDBC -Treiber (siehe 4.4 JDBC) aufgebaut.
private DatabaseConnection() {
try {
Class.forName("com.mysql.jdbc.Driver").newInstance();
connection = DriverManager.getConnection(
"jdbc:mysql://localhost/shopinfo?zeroDateTimeBehavior=convertToNull",
"root", "gipfelkreuz");
connection.setReadOnly(false);
} catch (InstantiationException e) {
System.out.println("InstantiationException: " + e);
} catch (IllegalAccessException e) {
System.out.println("IllegalAccessException: " + e);
} catch (ClassNotFoundException e) {
System.out.println("ClassNotFoundException: " + e);
} catch (SQLException e) {
System.out.println("SQLException: " + e);
}
}
Wie man sieht, handelt es sich hier um die Verbindung zu einer lokalen MySQL
Datenbank, die während der Entwicklung verwendet wird. Die Argumente
beziehen sich dabei erstens auf die Adresse der Datenbank, zweitens auf den
Benutzer und drittens auf das Passwort der Datenbank.
Die Adresse der Datenbank ergibt sich aus dem Treiber, dann die Art der
Datenbank und schlussendlich der wirklichen Adresse der Datenbank. In diesem
Fall muss zusätzlich noch ein zeroDateTimeBehavior=convertToNull Statement
hinzugefügt werden, um Fehler mit Datumswerten in der Datenbank zu
vermeiden.
Da beim Verbindungsaufbau Fehler auftreten können, wenn beispielsweise die
Datenbank nicht erreicht werden kann oder Benutzer und Passwort nicht
stimmen, muss dieser Code in einer Try-Catch-Anweisung ausgeführt werden,
um diverse Exceptions abzufangen.
Seite 38
Diplomarbeit
4.5.4.2.
Lanzanasto, Neumann, Plattner
Auslesen der Daten
Zum Auslesen der Daten aus der Datenbank gibt es für jede Tabelle der
Datenbank drei verschiedene Methoden.
public List<Shop> getShops() {
.
.
.
}
public List<Shop> getShops(String sSQLStatement) {
.
.
.
}
public List<Shop> getShops(TreeListener treeListener) {
.
.
.
}
Bei der ersten Methode werden keine Parameter übergeben, da immer die
gesamte Tabelle als Liste von Datensätzen zurückgegeben wird. Diese Methode
wird hauptsächlich für die Gesamttabellen und für die Erstellung der Baumstruktur
verwendet.
Die beiden weiteren Methoden sind für die speziellere Rückgabe von
Datensätzen konzipiert. Dabei kann entweder eine fertige SQL-Abfrage als String
übergeben werden, wie es zum Beispiel bei der erweiterten Suche der Fall ist,
oder es wird die im TreeListener gespeicherte Information übergeben, um daraus
eine SQL-Abfrage zu formen und einzelne Datensätze, unter anderem für die
Details-Anzeige, zu erhalten.
Seite 39
Diplomarbeit
Lanzanasto, Neumann, Plattner
sSQLStatement = "SELECT Shops.sap_ship_to, Shops.country_code, Shops.type,..."
sSQLStatement = sSQLStatement + "FROM shopinfo.country Country, shopinfo.shops Shops";
sSQLStatement = sSQLStatement + " WHERE Country.country_code = Shops.country_code ";
if (treeListener.getSelectedRegion() != "") {
sSQLStatement = sSQLStatement + "AND Country.region = '"
+ treeListener.getSelectedRegion() + "'";
}
if (treeListener.getSelectedCountry() != "") {
sSQLStatement = sSQLStatement + "AND Shops.country_code = '"
+ treeListener.getSelectedCountry() + "'";
}
if (treeListener.getSelectedShop() != "") {
sSQLStatement = sSQLStatement + "AND Shops.sap_ship_to = '"
+ treeListener.getSelectedShop() + "'";
}
ResultSet rs = stmt.executeQuery(sSQLStatement + " LIMIT 10000");
Obwohl
nur
ein
Datensatz
zurückgegeben
werden
muss,
wird
aus
Einfachheitsgründen eine Liste zurückgegeben, die jedoch nur einen Eintrag
besitzt, dieser eine Eintrag wird im Anschluss über die „get(0)“-Funktion
herausgeholt.
Die vorhin angesprochenen Listen bestehen aus mehreren Objekten, bei denen
die Inhalte eines Datensatzes mittels „set“-Funktion in privaten Variablen
eingetragen werden. Es gibt hierbei vier verschiedene Klassen für die
verschiedenen Tabellen der Datenbank. Darin befinden sich nur private Variablen
entsprechend der Spalten einer Tabelle, welche mittels „set“- und „get“Funktionen verarbeitet werden.
public class Shop {
private String sapShipTo;
.
.
.
public String getSapShipTo() {
return sapShipTo;
}
public void setSapShipTo(String sapShipTo) {
this.sapShipTo = sapShipTo;
}
.
.
.
}
Seite 40
Diplomarbeit
Lanzanasto, Neumann, Plattner
Zum Verändern von Datensätzen der Datenbank werden in der Klasse zwei
weitere Methoden verwendet. Beide haben prinzipiell die gleiche Funktion, sie
führen die als String übergebene SQL-Schreib-Abfrage auf der Datenbank durch.
Einziger Unterschied ist, dass eine Funktion mögliche Exceptions selbst abfängt,
die andere Funktion gibt solche nur an die ausführende Instanz zurück, wo diese
dann weiter verarbeitet werden, zum Beispiel wird diese Vorgangsweise bei der
Ausgabe von Pop-Up-Fehlermeldungen benötigt.
public void editDatabase(String sSQLStatement) {
try {
Statement stmt = connection.createStatement();
stmt.execute(sSQLStatement);
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
public void editDatabaseWithException(String sSQLStatement) throws SQLException {
Statement stmt = connection.createStatement();
stmt.execute(sSQLStatement);
stmt.close();
}
Weitere Funktionen sind die „getSingleCount()“- und die „getHwAge()“-Methoden.
Die „getSingleCount()“-Methode wird vor allem zum Erstellen von Statistiken
verwendet,
findet
Überprüfungsvorgängen.
aber
Hier
auch
wird
Anwendung
wieder
als
in
String
eine
verschiedenen
SQL-Abfrage
übergeben, welche jedoch nur einen „Count“-Befehl enthält und somit lediglich
eine Zahl wieder zurückgibt, diese Zahl wird anschließend als String
weitergegeben und muss dann verarbeitet werden.
public String getSingleCount(String sSQLStatement) {
try {
Statement stmt = connection.createStatement();
ResultSet rs = stmt.executeQuery(sSQLStatement);
String sCount = "Error";
if (rs.next())
sCount = rs.getString(1);
rs.close();
stmt.close();
return sCount;
} catch (SQLException e) {
e.printStackTrace();
Seite 41
Diplomarbeit
Lanzanasto, Neumann, Plattner
return null;
}
}
Die „getHwAge()“-Methode wird eigentlich nur bei der Anzeige der HardwareDetails benötigt, um das Alter der Hardware zu ermitteln. Hier wird das Datum der
Erstinstallation als String übergeben und anschließend mittels SQL-DATEDIFFAbfrage die Differenz zum aktuellen Datum in Jahren über die Datenbank
ermittelt.
public String getHwAge(String sDate) {
String sSQLStatement;
String sAge = "-";
int iAge = 0;
float fAge = 0;
try {
Statement stmt = connection.createStatement();
sSQLStatement = "SELECT DATEDIFF ( NOW(), \"";
sSQLStatement = sSQLStatement + sDate;
sSQLStatement = sSQLStatement + "\")";
ResultSet rs = stmt.executeQuery(sSQLStatement);
if (rs.next())
iAge = rs.getInt(1);
rs.close();
stmt.close();
fAge = iAge;
fAge = fAge / 365;
sAge = Float.toString(fAge);
try {
sAge = sAge.substring(0, sAge.indexOf(".") + 3);
} catch (StringIndexOutOfBoundsException e1) {
}
if (fAge > 1000)
sAge = "-";
return sAge;
} catch (SQLException e) {
e.printStackTrace();
return "-";
}
}
Seite 42
Diplomarbeit
Lanzanasto, Neumann, Plattner
4.5.5. Handler
Alle Klassen im Package „at.swarovski.rcp.shopinfo.handlers“ werden für die
Schaltflächen in der Menüleiste benötigt. Dabei existiert für jeden Button ein
Handler. Die meisten dieser Handler öffnen beim Auslösen einen neuen Part, um
beispielsweise das Suchfenster oder Statistiken anzuzeigen. Dabei wird der neue
Part im Prinzip immer gleich generiert.
Nachdem der Part erschaffen wurde, werden Eigenschaften wie Label und
„Closeable“-Status eingestellt. Anschließend wird definiert, mit der Instanz
welcher View-Klasse der Part gefüllt werden soll. Danach wird der passende
PartStack gesucht, um dann den neuen Part zu diesem Stack hinzuzufügen.
public class NewShopHandler {
@Execute
public void execute(EPartService partService, MApplication application,
EModelService modelService) {
MPart part = MBasicFactory.INSTANCE.createPart();
part.setLabel("New");
part.setCloseable(true);
part.setContributionURI("bundleclass://at.swarovski.rcp.shopinfo/
at.swarovski.rcp.shopinfo.view.NewShop");
List<MPartStack> stacks = modelService.findElements(application, null,
MPartStack.class, null);
stacks.get(1).getChildren().add(part);
partService.showPart(part, PartState.ACTIVATE);
}
}
Der Handler des „showDetails“-Buttons in der Menüleiste generiert die Parts auch
nach genau diesem Verfahren, jedoch wird dabei vorher mittels TreeListener
entschieden, welche Art von Details angezeigt werden soll, damit schlussendlich
auch die richtige Label-Beschriftung ausgewählt wird.
Seite 43
Diplomarbeit
Lanzanasto, Neumann, Plattner
public class DetailsHandler {
@Execute
public void execute(EPartService partService, MApplication application,
EModelService modelService) {
TreeListener treeListener = TreeListener.getInstance();
if (treeListener.getSelectedShop() != "") {
MPart part = MBasicFactory.INSTANCE.createPart();
part.setLabel("Shop-Details: " + treeListener.getSelectedShop());
part.setCloseable(true);
.
.
.
}
else if (treeListener.getSelectedClosedShop() != "") {
MPart part = MBasicFactory.INSTANCE.createPart();
part.setLabel("Closed Shop-Details: " +
treeListener.getSelectedClosedShop());
part.setCloseable(true);
.
.
.
}
else if (treeListener.getSelectedHardware() != "") {
MPart part = MBasicFactory.INSTANCE.createPart();
part.setLabel("HW-Details: " + treeListener.getSelectedHardware());
.
.
.
}
else if (treeListener.getSelectedCountry() != "") {
MPart part = MBasicFactory.INSTANCE.createPart();
part.setLabel("Country-Details: " +
treeListener.getSelectedCountry());
.
.
.
}
}
}
Andere Handler wie der „About“-Handler oder der „Quit“-Handler werden
automatisch bereitgestellt und müssen bei Bedarf nur abgeändert werden, um
zum Beispiel die „About“-Information anzupassen.
Seite 44
Diplomarbeit
Lanzanasto, Neumann, Plattner
4.5.6. Gesamttabellen
Die Gesamttabellen werden sofort nach Start des Programms angezeigt. Sie
stellen den kompletten Inhalt der Datenbank-Tabellen „country“, „shops“ und
„closed_shops“ dar. Dabei wird für jede Tabelle ein eigener Part erstellt.
Zuerst wird dabei eine Tabelle mit sämtlichen Spalten für die Datensätze erstellt.
final Table tableShop = new Table(parentShop, SWT.MULTI | SWT.BORDER |
SWT.FULL_SELECTION);
tableShop.setLinesVisible(true);
tableShop.setHeaderVisible(true);
GridData dataShop = new GridData(SWT.FILL, SWT.FILL, true, true);
dataShop.heightHint = 200;
tableShop.setLayoutData(dataShop);
final String[] titlesShop = { "SAP ship-to", "country code", "Type", "Pilote",...
for (int i = 0; i < titlesShop.length; i++) {
TableColumn column = new TableColumn(tableShop, SWT.NONE);
column.setText(titlesShop[i]);
}
Anschließend
werden
zwischengespeichert.
die
Diese
Datensätze
eingelesen
Liste
dann
wird
in
und
einer
in
einer
Liste
for-each-Schleife
durchlaufen und dabei jeder Eintrag in die Tabelle geschrieben.
shops = db_conShop.getShops();
if (shops != null) {
for (Shop entry : shops) {
TableItem item = new TableItem(tableShop, SWT.NONE);
item.setText(0, entry.getSapShipTo());
item.setText(1, entry.getCountryCode());
item.setText(2, entry.getType());
item.setText(3, entry.getPilote());
.
.
.
Abschließend wird noch ein Listener generiert. So kann ein Datensatz in der
Tabelle durch Klicken ausgewählt werden, um später in der Detailansicht Einträge
zu verändern.
Seite 45
Diplomarbeit
Lanzanasto, Neumann, Plattner
Rectangle clientArea = parentShop.getClientArea();
tableShop.setLocation(clientArea.x, clientArea.y);
Point size = tableShop.computeSize(SWT.DEFAULT, 200);
tableShop.setSize(size);
tableShop.addListener(SWT.MouseDown, new Listener() {
public void handleEvent(Event event) {
Rectangle clientArea = tableShop.getClientArea();
Point pt = new Point(event.x, event.y);
int index = tableShop.getTopIndex();
while (index < tableShop.getItemCount()) {
boolean visible = false;
TableItem item = tableShop.getItem(index);
for (int i = 0; i < titlesShop.length; i++) {
Rectangle rect = item.getBounds(i);
if (rect.contains(pt)) {
final TreeListener searchListener = TreeListener.getInstance();
searchListener.setSelectedShop(tableShop.getItem(index).getText(0));
System.out.println(tableShop.getItem(index).getText(0));
}
if (!visible && rect.intersects(clientArea)) {
visible = true;
}
}
if (!visible)
return;
index++;
}
}
});
4.5.7. TreePart
Der TreePart stellt im Programm das Kernelement zur schnellen, strukturierten
Suche von Datensätzen dar. Einerseits besteht die Möglichkeit über ein Textfeld
direkt einen Shop auszuwählen, indem man die zu ihm gehörige SAP-Nummer
eintippt, andererseits wird die eigentliche Baumstruktur zur Auswahl der
Datensätze angezeigt.
Seite 46
Diplomarbeit
4.5.7.1.
Lanzanasto, Neumann, Plattner
Quick search
Zur schnellen Suche wird im Prinzip nur ein Textfeld verwendet, das mit einem
Listener ausgerüstet wird, sodass die Eingabe mittels Entertaste bestätigt werden
kann. Dabei wird die eingegebene Nummer versucht im TreeListener zu speichern, um so den gewünschten Shop auszuwählen (siehe 4.5.8 TreeListener).
textstyle;
parent.setLayout(new GridLayout(1, false));
final TreeListener searchListener = TreeListener.getInstance();
Listener listener = new Listener() {
public void handleEvent(Event event) {
Text t = (Text) event.widget;
String msg = t.getMessage();
if (event.detail == SWT.ICON_CANCEL) {
System.out.println("Cancel on " + msg);
} else if (event.detail == SWT.ICON_SEARCH) {
System.out.println("ICON on " + msg);
} else {
System.out.println("Default selection on " + msg + ": "
+ t.getText());
searchListener.setSelectedShop(t.getText());
}
}
};
textstyle = new Text(parent, SWT.SEARCH);
textstyle.setMessage("Quick search");
textstyle.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
textstyle.addListener(SWT.DefaultSelection, listener);
4.5.7.2.
Baumstruktur
Um die Baumstruktur aufbauen zu können, müssen zuerst alle Datensätze aus
der Datenbank eingelesen und zwischengespeichert werden. Dazu wird jeweils
eine Liste für Shops, Länder und Hardware generiert. Zusätzlich werden noch
Listen für Regionen und Shoptypen benötigt, in denen die bereits generierten
Items gespeichert werden. Außerdem wird eine bool‘sche Variable verwendet, um
anzugeben, ob der aktuelle Datensatz als neues Item erstellt werden muss oder
nicht.
Zuerst werden beim dynamischen Aufbau der Baumstruktur alle Datensätze der
„country“-Tabelle durchlaufen. Dabei wird überprüft, ob der Region-Eintrag des
Landes mit einem Punkt des Trees übereinstimmt, genauer gesagt wird der
Seite 47
Diplomarbeit
Lanzanasto, Neumann, Plattner
Eintrag mit der Liste der Items verglichen, denn hier werden diese immer
eingetragen, wenn ein solches erstellt wird.
if (countries != null) {
for (Country entryRegion : countries) {
bNewItem = true;
for (String sUniqueRegion : ItemsRegion) {
if (entryRegion.getRegion().equals(sUniqueRegion)) {
bNewItem = false;
}
}
if (bNewItem == true) {
// Region-----------------------------------------------------TreeItem treeItemRegion = new TreeItem(tree, 0);
treeItemRegion.setText(entryRegion.getRegion());
ItemsRegion.add(entryRegion.getRegion());
.
.
.
}
}
}
Wenn also der Region-Eintrag des Landes noch nicht verwendet wurde, wird für
diese Region ein Punkt erstellt und in der Item-Liste eingetragen. Anschließend
werden in einer for-each-Schleife alle Country-Datensätze durchlaufen und immer
dann wird ein neuer Unterpunkt erstellt, wenn die Region des Landes mit der
ausgewählten Region übereinstimmt. Außerdem wird hier die Item-Liste, in der
die Shoptypen zwischengespeichert sind, geleert, da natürlich in jedem Land
immer wieder die gleichen Shoptypen vorkommen können.
.
.
.
// Country-----------------------------------------------------for (Country entryCountry : countries) {
if (entryCountry.getRegion().equals(entryRegion.getRegion())) {
ItemsType.clear();
TreeItem treeItemCountry = new TreeItem(treeItemRegion, 0);
treeItemCountry.setText(entryCountry.getCountryCode() +
" (" + entryCountry.getVgNr() + ")");
ItemsCountry.add(entryCountry.getCountryCode());
.
.
.
}
}
.
.
.
Seite 48
Diplomarbeit
Lanzanasto, Neumann, Plattner
Nun werden die Shops in einer for-each-Schleife durchlaufen, um für jeden neu
gefunden Shoptypen einen neuen Unterpunkt zu erstellen. Dabei muss aber
zusätzlich noch überprüft werden, ob der gefundene Eintrag auch wirklich einen
Shop dieses Landes beinhaltet. Wenn dies der Fall ist, wird wieder ein neues
Item erstellt und in der Item-Liste für Shoptypen eingetragen.
.
.
.
// Shop-Type-----------------------------------------------------for (Shop entryType : shops) {
bNewItem = true;
for (String sUniqueType : ItemsType) {
if (entryType.getType().equals(sUniqueType)) {
bNewItem = false;
}
}
if (bNewItem == true) {
if (entryCountry.getCountryCode().equals(entryType.getCountryCode())) {
TreeItem treeItemType = new TreeItem(treeItemCountry, 0);
treeItemType.setText(entryType.getType());
ItemsType.add(entryType.getType());
.
.
.
}
}
}
.
.
.
Als Nächstes werden die Datensätze der „shops“-Tabelle ein weiteres Mal in
einer for-each-Schleife durchlaufen, um hier für jeden Shop, der sich im richtigen
Land befindet und den passenden Shoptypen besitzt, einen neuen Unterpunkt zu
erstellen.
Zum Abschluss werden noch die Hardware-Einträge mit einer for-each-Schleife
durchsucht, um auch für die zum Shop gehörige Hardware noch weitere
Unterpunkte zu erstellen.
Seite 49
Diplomarbeit
Lanzanasto, Neumann, Plattner
.
.
.
// SAP_Ship-to-----------------------------------------------------for (Shop entrySap : shops) {
if (entrySap.getCountryCode().equals(entryCountry.getCountryCode()) &&
entrySap.getType().equals(entryType.getType())) {
TreeItem treeItemSap = new TreeItem(treeItemType, 0);
treeItemSap.setText(entrySap.getSapShipTo() + " ("
+ entrySap.getLocation() + " - "
+ entrySap.getStoreName() + ")");
// Hardware-----------------------------------------------------for (Hardware entryHardware : hardware) {
if (entryHardware.getShipTo().equals(entrySap.getSapShipTo())) {
TreeItem treeItemHardware = new TreeItem(treeItemSap, 0);
treeItemHardware.setText(entryHardware.getHostname()
+ " - (" + entryHardware.getSn() + ")");
ItemsHw.add(entryHardware.getHw());
}
}
ItemsSap.add(entrySap.getCountryCode());
}
}
.
.
.
Nachdem die Baumstruktur nun dynamisch erstellt wurde, wird diese noch mit
dem TreeListener verknüpft, um durch Klicken eines Unterpunktes auch wirklich
einen Eintrag auswählen zu können.
TreeListener treeListener = TreeListener.getInstance();
treeListener.SelectionListener(tree);
4.5.8. TreeListener
Die TreeListener-Klasse hatte in den ersten Versionen des Programms eigentlich
nur die Aufgabe, herauszufinden, welcher Eintrag der Baumstruktur geklickt
wurde, und diese Information für die weitere Verarbeitung zu speichern.
Mit
Voranschreiten der Programmierung gewann diese Klasse aber immer mehr an
Bedeutung und stellt schlussendlich einen zentralen Punkt des Programms dar.
Seite 50
Diplomarbeit
Lanzanasto, Neumann, Plattner
Während des Programmablaufs existiert immer nur eine Instanz dieser Klasse,
ein sogenannter Singleton. Das bedeutet, wenn diese Instanz benötigt wird, wird
nicht in einer anderen Klasse eine Instanz generiert, sondern immer die Anfrage
„TreeListener.getInstance();“ an diese Klasse gesendet. Hier wird
überprüft, ob die Instanz bereits existiert, wenn nötig generiert und anschließend
zurückgegeben. Das gleiche Prinzip wird bei der Datenbankverbindung
verwendet, da auch hier natürlich immer nur einmal eine Verbindung aufgebaut
werden darf.
Würde man beim TreeListener eine Instanz erstellen, einen ausgewählten Eintrag
zwischenspeichern und anschließend in einem anderen Teil des Programms
wieder eine andere TreeListener-Instanz erstellen, könnte man nicht auf den
gespeicherten Eintrag zugreifen und der Zweck dieser Klasse wäre nicht erfüllt.
Der TreeListener arbeitet also sozusagen als globale Variable, auf die beinahe
alle Instanzen anderer Klassen zugreifen.
public static TreeListener getInstance() {
if (instance == null) {
instance = new TreeListener();
}
return instance;
}
Der TreeListener beinhaltet im Prinzip nur sechs String-Variablen, in denen die
jeweilige Auswahl gespeichert ist. Diese Variablen sind jedoch „private“, können
also von außen nicht beeinflusst werden. Daher gibt es für jede Variable eine
„set“- und eine „get“-Methode. Bei jeder „set“-Methode wird überprüft, ob die
gewünschte Änderung Sinn macht und man schützt somit die zugehörige
Variable vor fehlerhaften Einträgen. Die „get“-Methoden liefern nur die
gewünschte Variable, haben aber sonst keine weitere Funktion. Hier die „set“und „get“-Methode für die Shop-Variable:
Seite 51
Diplomarbeit
Lanzanasto, Neumann, Plattner
public String getSelectedShop() {
return sSelectedShop;
}
public void setSelectedShop(TreeItem selectedShop) {
String sNewSelectedShop = selectedShop.getText();
int iSAP;
if ((sNewSelectedShop.indexOf('(')) > 0) {
sNewSelectedShop = sNewSelectedShop.substring(0,
sNewSelectedShop.indexOf('(')).trim();
if (sNewSelectedShop.length() >= 4 && sNewSelectedShop.length() <= 9) {
try {
iSAP = Integer.parseInt(sNewSelectedShop);
resetSelection();
this.sSelectedShop = sNewSelectedShop;
System.out.println("Shop: " + getSelectedShop());
} catch (NumberFormatException e) {
this.sSelectedShop = "";
}
} else if (sNewSelectedShop.substring(0, 3).equals("999")) {
resetSelection();
this.sSelectedShop = sNewSelectedShop;
System.out.println("Dummy-Shop: " + getSelectedShop());
} else
this.sSelectedShop = "";
} else
this.sSelectedShop = "";
}
Eine weitere Funktion ist die „resetSelection()“-Methode. Sie schreibt in alle
sechs Variablen einen Leerstring und löscht somit die gespeicherte Auswahl. Es
sollte nämlich immer nur eine der Variablen einen Eintrag enthalten, da
beispielsweise nicht gleichzeitig ein Shop und ein Land ausgewählt sein können.
Daher wird bei jeder „set“-Methode vor Erneuerung des Variableneintrags diese
Funktion aufgerufen. Es gibt jedoch Ausnahmen wie bei der Suche nach
Hardware, die mit einem Shop verlinkt ist. Hier werden nämlich bei der Auswahl
die SAP-Nummer des Shops und zusätzlich der Hostname der Hardware für die
weiter Verarbeitung gespeichert (siehe 4.5.9 Search).
Zusätzlich gibt es noch die ursprüngliche „SelectionListener()“-Funktion.
Sie erkennt welcher Eintrag in der Baumstruktur angeklickt wurde und leitet diese
Information anschließend an die „set“-Methoden weiter, die dann überprüfen zu
welcher Art von Eintrag die übertragene Information passt.
Seite 52
Diplomarbeit
Lanzanasto, Neumann, Plattner
public void SelectionListener(final Tree tree) {
tree.addListener(SWT.MouseDown, new Listener() {
public void handleEvent(Event event) {
Point point = new Point(event.x, event.y);
if (tree.getItem(point) != null) {
setSelectedRegion(tree.getItem(point));
setSelectedCountry(tree.getItem(point));
setSelectedShop(tree.getItem(point));
}
}
});
}
4.5.9. Search
Bei der Suche wird der Part in einen TabFolder mit zwei Elementen unterteilt. Je
nachdem, welches der beiden Elemente ausgewählt wurde, wird entweder nach
einem Shop oder nach einer Hardware gesucht. Die beiden Elemente des
TabFolders sind im Prinzip genau gleich aufgebaut, es befinden sich jeweils zwei
ContentGroups darin, eine für die Eingabe der Suchkriterien, die andere
beinhaltet eine Tabelle, in der die Suchergebnisse dargestellt werden. Diese
Tabelle ist so programmiert, dass beim Klick auf eine der Zeilen die SAP-Nummer
des Shops bzw. die Seriennummer der Hardware zwischengespeichert wird und
somit genauere Informationen durch einen Klick auf „Details“-Button angezeigt
werden (siehe 4.5.11 Details).
Wichtigster Bestandteil der Programmierung des Suchfensters ist natürlich der
„Search“-Button beziehungsweise die Funktion, die beim Klick dieses Buttons
aufgerufen wird. Hier wird eine SQL-Abfrage mit mehreren WHERE-Bedingungen
erstellt, die alle Suchkriterien beinhalten.
Bei der Suche nach einem Shop besteht außerdem noch die Möglichkeit nach
geschlossenen Shops zu suchen, indem in der CheckBox „Closed Shop“ ein
Haken gesetzt wird. Im Prinzip wählt man mit dieser Suchoption lediglich aus, in
welcher Tabelle der Datenbank nach Datensätzen gesucht werden soll, da mit
der Datenbankstruktur getrennte Tabellen für geöffnete und geschlossene Shops
verwendet werden.
Im Anschluss wird das Suchergebnis entweder in einer Objektliste der Klasse
„Shop“ oder der Klasse „ClosedShops“ gespeichert, je nachdem, welche Art der
Seite 53
Diplomarbeit
Lanzanasto, Neumann, Plattner
Suche ausgewählt wurde. Diese Unterteilung zieht sich die weiteren Schritte
immer weiter hindurch, da die beiden Tabellen der Datenbank nicht genau gleich
sind (siehe 3.3 Datenbankübersicht).
if (btnCheckClosedShop.getSelection() == false) {
sSQLStatement = "SELECT Shops.sap_ship_to, Shops.country_code, Shops.type, ...
sSQLStatement = sSQLStatement + "FROM shopinfo.country Country, shopinfo.shops Shops ";
} else if (btnCheckClosedShop.getSelection() == true) {
sSQLStatement = "SELECT Shops.auto_id, Shops.sap_ship_to, Shops.country_code, ...
sSQLStatement = sSQLStatement + "FROM shopinfo.country Country, shopinfo.closed_shops Shops
";
}
sSQLStatement
sSQLStatement
";
sSQLStatement
sSQLStatement
"%' ";
sSQLStatement
= sSQLStatement + "WHERE Country.country_code = Shops.country_code ";
= sSQLStatement + "AND Shops.sap_ship_to LIKE '%" + textShopShipTo.getText() + "%'
= sSQLStatement + "AND Shops.type LIKE '%" + textShopType.getText() + "%' ";
= sSQLStatement + "AND Shops.store_name LIKE '%" + textShopShopname.getText() +
= sSQLStatement + "AND (Shops.country_code LIKE '%" + textShopCountry.getText() +
"%' OR Country.country LIKE '%" + textShopCountry.getText() + "%') ";
sSQLStatement = sSQLStatement + "AND (Shops.location LIKE '%" + textShopLocation.getText() +
"%' OR Shops.city LIKE '%" + textShopLocation.getText() + "%') ";
sSQLStatement = sSQLStatement + "AND Shops.zip_code LIKE '%" + textShopZIP.getText() + "%' ";
sSQLStatement = sSQLStatement + "AND Shops.phone LIKE '%" + textShopPhone.getText() + "%' ";
sSQLStatement = sSQLStatement + "LIMIT 10000";
if (btnCheckClosedShop.getSelection() == false)
searchResult = db_con.getShops(sSQLStatement);
else if (btnCheckClosedShop.getSelection() == true)
searchResultClosed = db_con.getClosedShops(sSQLStatement);
Danach werden sämtliche bereits vorhandenen Einträge, die nach der
vorhergehenden Suche in der Ergebnistabelle angezeigt werden, entfernt. Sollte
die Suche mit den eingegebenen Kriterien keine Ergebnisse liefern, wird ein
Popup-Fenster am Bildschirm angezeigt, welches den Benutzer auf dieses
Problem hinweist.
if (searchResult != null) {
if (searchResult.size() == 0) {
System.out.println("No shop was found!");
MessageBox dialogSQLError = new MessageBox(shell,
SWT.ICON_WARNING | SWT.OK);
dialogSQLError.setText("No result!");
dialogSQLError.setMessage("No shop was found with this parameters!");
returnCode = dialogSQLError.open();
} else {
System.out.println(searchResult.get(0).getSapShipTo());
}
}
Seite 54
Diplomarbeit
Lanzanasto, Neumann, Plattner
Bei der Suche nach Hardware sieht die prinzipielle Suchfunktion ähnlich aus, wie
die der Shop-Suche. Es werden auch hier alle Bedingungen in ein SQL-Abfrage
verpackt. Aus Sicht des Benutzers fungiert auch die CheckBox zur Suche nach
entfernter Hardware nach dem gleichen Prinzip wie bei der Suche nach
geschlossenen Shops. Programmintern wird diese Suchbedingung aber etwas
anders abgehandelt, da bei der Hardware nur eine Tabelle in der Datenbank
vorhanden ist, in der alle Hardware-Datensätze gespeichert sind.
Hier wird diese Auswahloption zur eigentlichen Suche in der Datenbank ignoriert,
es werden also alle Hardware-Datensätze, egal ob entfernt oder nicht, in einer
Objektliste der Klasse „Hardware“ gespeichert. Anschließend werden alle
Datensätze in einer for-each-Schleife in die Tabelle eingetragen, dabei wird
jedoch bei jedem Datensatz vorher mit einer SQL-Abfrage (COUNT-Funktion),
wie sie auch beim Erstellen der Statistiken verwendet wird (siehe 4.5.10 Statistic),
überprüft, wie oft die jeweilige Hardware mit einem Shop verlinkt ist. Diese
Abfrage gibt entweder den Wert 1, die Hardware wird in einem Shop verwendet,
oder den Wert 0, die Hardware ist in keinem Shop vorhanden (also entfernt),
zurück.
Anschließend wird mit einer IF-Abfrage entschieden, ob der Datensatz in der
Ergebnistabelle angezeigt wird, indem überprüft wird, ob die Hardware der
gewünschten Suchbedingung entspricht.
Diese kleine Abfrage muss für jeden Datensatz, der bei der ursprünglichen SQLAbfrage zurückgegeben wurde, wiederholt werden. Dadurch dauert die Suche bei
ungenauen Angaben der Kriterien etwas länger, was dem Benutzer jedoch nicht
zu sehr auffallen wird.
Seite 55
Diplomarbeit
Lanzanasto, Neumann, Plattner
if (searchHWResult != null) {
for (Hardware entry : searchHWResult) {
sSQLHWStatement
sSQLHWStatement
sSQLHWStatement
sSQLHWStatement
=
=
=
=
"SELECT COUNT(sap_ship_to) FROM shopinfo.shops ";
sSQLHWStatement + "WHERE sap_ship_to='";
sSQLHWStatement + entry.getShipTo();
sSQLHWStatement + "'";
if (((btnCheckRemoved.getSelection() == false) &&
(Integer.parseInt(db_con.getSingleCount(sSQLHWStatement)) == 1)) ||
((btnCheckRemoved.getSelection() == true) &&
(Integer.parseInt(db_con.getSingleCount(sSQLHWStatement)) == 0))) {
bNoResult = false;
TableItem item = new TableItem(tableHWResult, SWT.NONE);
item.setText(0, entry.getSn());
item.setText(1, entry.getShipTo());
item.setText(2, entry.getHostname());
item.setText(3, entry.getHw());
item.setText(4, entry.getStoreType());
item.setText(5, entry.getOsVersion());
}
}
}
Auch bei dieser Suche wird wieder ein Popup-Fenster angezeigt, falls keine
Suchergebnisse vorliegen. Da jedoch nicht alle Ergebnisse der eigentlichen SQLAbfrage angezeigt werden, kann hier nicht die Objektliste zur Speicherung auf
„null“ abgefragt werden, sondern es muss eine eigene bool’sche Variable
„bNoResult“ generiert werden, die kennzeichnet, ob die Suche erfolgreich war.
Diese Variable ist standardmäßig auf „true“, also kein Ergebnis, und wird, sobald
der erste Datensatz in die Ergebnistabelle eingetragen wird, auf „false“ gesetzt.
Eine Besonderheit bei der Suche von Hardware ist die Auswahl des gewünschten
Datensatzes zur Anzeige der Details. Beim Klick auf eine Zeile der
Ergebnistabelle wird überprüft, ob die ausgewählte Hardware mit einem Shop
verlinkt ist. Wenn dies der Fall ist, wird nicht die Seriennummer der Hardware,
sondern die SAP-Nummer des Shops in Verbindung mit dem Hostnamen der
Hardware im TreeListener gespeichert. So kann später bei der Anzeige der
Details der Shop dargestellt werden und zugleich die gesuchte Hardware im
TabFolder ausgewählt werden (siehe 4.5.11 Details).
Am Ende der „Search“-Klasse wird noch die Selection des TabFolders auf „0“
gesetzt, damit schon beim Öffnen des Parts die Shop-Suche angezeigt wird und
nicht nur ein leerer Bildschirm.
Seite 56
Diplomarbeit
4.5.10.
Lanzanasto, Neumann, Plattner
Statistics
Zuerst wird im Stastistics-Part ein „TabFolder“ für die einzelnen Regionen erstellt.
Darin werden anschließend Tabellen eingefügt. Hier werden bereits alle Spalten
fertig beschriftet und angepasst.
Nun startet die eigentliche Auswertung der Daten. Zur Zwischenspeicherung wird
für jede Spalte eine Variable erstellt, zusätzlich werden Felder definiert, in denen
die zusammengehörigen Daten der einzelnen Länder immer zusammengezählt
werden, um am Ende die Gesamtwerte für die Regionen ausgeben zu können.
Anschließend werden in einer Schleife die drei Kontinente abgearbeitet. Dabei
werden zu Beginn die Daten aller Länder eines Kontinents eingelesen. Wichtig
sind hier im Prinzip nur die Country-Codes, da mit Hilfe dieser die richtigen Shops
aus der „shops“-Tabelle herausgeholt werden. Mit diesem Ergebnis wird nun eine
„for-each“-Schleife für alle Länder des Kontinents durchgeführt.
sSQLStatement = "SELECT * FROM shopinfo.country WHERE region='";
sSQLStatement = sSQLStatement + sRegion;
sSQLStatement = sSQLStatement + "'";
searchResultCountries = db_con.getCountries(sSQLStatement);
Wichtigster Bestandteil des Programms ist für die Erstellung der Statistiken die
Funktion „getSingleCount()“. Dieser Funktion wird immer eine SQL-Query
übergeben, die eine einzige „Count“-Abfrage enthält. In diesem Fall enthält die
Antwort der Datenbank nur einen Wert, welcher von der Funktion als String
zurückgegeben wird, anschließend wird dieser String jedoch immer in einen
Integer-Wert umgewandelt. Genaueres über diese Funktion ist bei der
Datenbankverbindung zu finden. (siehe 4.5.4 Verbindung zur DB)
Diese Funktion wird immer wieder ausgeführt. Das Einzige, das sich ändert, ist
bei der Abarbeitung eines Landes der Typ der Shops, die gezählt werden sollen.
Hier sieht man die Code-Zeilen zum Zählen der AW-Shops:
Seite 57
Diplomarbeit
Lanzanasto, Neumann, Plattner
sSQLStatement = "SELECT COUNT(country_code) FROM shopinfo.shops WHERE country_code='";
sSQLStatement = sSQLStatement + entry.getCountryCode();
sSQLStatement = sSQLStatement + "' AND type='AW'";
iCountAW = Integer.parseInt(db_con.getSingleCount(sSQLStatement));
if (sRegion.equals("EUROPE"))
iCountEurope[0] += iCountAW;
if (sRegion.equals("AMERICAS"))
iCountAmericas[0] += iCountAW;
if (sRegion.equals("ASIA PACIFIC"))
iCountAsia[0] += iCountAW;
Sobald alle Shops des Landes durchgezählt wurden, wird eine Tabellenzeile in
der passenden Tabelle angelegt und mit den in den Variablen zwischengespeicherten Werten gefüllt.
Wurde der Vorgang für alle Länder und auch alle Kontinente beendet, müssen
nun noch die Statistiken für die Regionen in die Tabelle eingetragen werden. Die
Werte wurden für die Kontinente bei jedem Land aufsummiert und sind in den
Variablen-Feldern gespeichert. Diese müssen nur noch addiert werden, um auch
die Gesamtwerte der ganzen Welt anzeigen zu können.
for (iLoop = 0; iLoop < 13; iLoop++) {
iCountWorld[iLoop] = iCountEurope[iLoop] + iCountAmericas[iLoop]
+ iCountAsia[iLoop];
}
Um diese Statistik nach dieser Methode zu erstellen, wird ca. eine Sekunde
benötigt. Bei einem ersten Versuch ließen wir alle Daten der Shops einlesen und
wollten die Shops eines Typs innerhalb des Java-Programms zählen lassen.
Diese Methode funktionierte zwar auch, es brauchte aber um ein Vielfaches mehr
Zeit, die beim normalen Gebrauch des Programms nicht zumutbar gewesen
wäre, deshalb entschieden wir uns die Shops direkt von der Datenbank zählen zu
lassen.
Seite 58
Diplomarbeit
4.5.11.
Lanzanasto, Neumann, Plattner
Details
Bei einem Klick auf den „Details“-Button im Menü wird ein Part der Klasse
„ShopDetails“ geöffnet. Dabei wird als erster Schritt die Funktion „showDetails“
ausgeführt. Im Prinzip wird mit dieser Funktion lediglich herausgesucht, welche
Details welchen Country’s, welchen Shops bzw. welcher Hardware angezeigt
werden sollen. Dazu wird das TreeListener-Objekt importiert, in der die Auswahl
immer zwischengespeichert wird (siehe 4.5.8 TreeListener).
Je nachdem, welcher Eintrag des TreeListeners ein Ergebnis liefert, wird die
passende Funktion zur Anzeige aufgerufen und dabei unter anderem auch der
TreeListener übergeben, um in der Funktion den passenden Datensatz aus der
Datenbank herauszusuchen.
TreeListener treeListener = TreeListener.getInstance();
if (treeListener.getSelectedShop().equals("") == false) {
showShopDetails(parent, treeListener);
}
else if (treeListener.getSelectedClosedShop().equals("") == false) {
showClosedShopDetails(parent, treeListener);
}
else if (treeListener.getSelectedHardware().equals("") == false) {
showHardwareDetails(parent, treeListener);
}
else if (treeListener.getSelectedCountry().equals("") == false) {
showCountryDetails(parent, treeListener);
}
4.5.11.1. showShopDetails()
Diese
Funktion
wird
erst
aufgerufen,
wenn
die
Funktion
„treeListener.getSelectedShop()“ eine SAP-Nummer zurückgibt. Hier wird zu
Beginn eine Verbindung zur Datenbank hergestellt und alle Shops mit der
übergebenen SAP-Nummer werden eingelesen und in einer Liste gespeichert. Da
die Shops mittels SAP-Nummer ausgefiltert werden und die SAP-Nummer in der
Datenbank als Primary Key verwendet wird, dürfte jedoch maximal nur ein Shop
gefunden werden. Aus Einfachheitsgründen wird hier aber die gleiche Funktion
angewandt, wie wenn nach mehreren Shops gesucht werden würde. Da also nur
Seite 59
Diplomarbeit
Lanzanasto, Neumann, Plattner
ein Eintrag in der Liste vorhanden ist, wird beim Eintragen in die TextBoxes mit
der „get(0)“-Funktion immer der erste Eintrag verwendet.
Im Anschluss wird für jedes Detail des Shops jeweils ein Label, das die
Beschreibung anzeigt, und, wie schon erwähnt, eine TextBox, die mit dem
passenden Detail befüllt wird, innerhalb einer ContentGroup generiert. Der
„editable“-Status der TextBoxes wird dabei auf „false“ gesetzt, somit kann der
Inhalt nicht verändert, aber trotzdem markiert und kopiert werden.
List<Shop> shop;
shop = db_con.getShops(treeListener);
Label labelShopname = new Label(contentGroupShop, SWT.NONE);
labelShopname.setText("Store Name: ");
final Text textShopname = new Text(contentGroupShop, SWT.SINGLE);
textShopname.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
textShopname.setText(shop.get(0).getStoreName());
textShopname.setEditable(false);
Label labelSAP = new Label(contentGroupShop, SWT.NONE);
labelSAP.setText("SAP - Ship to: ");
final Text textSAP = new Text(contentGroupShop, SWT.SINGLE);
textSAP.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
textSAP.setText(shop.get(0).getSapShipTo());
textSAP.setEditable(false);
.
.
.
Am unteren Ende der Gruppe befinden sich zwei Buttons, einer zum Verändern
der Details und einer zum Schließen des Shops. Noch eine Zeile weiter unten
befindet sich eine unsichtbare TextBox, in der die derzeitige SAP-Nummer des
Shops noch einmal hinterlegt ist, diese versteckte Information ist für den Benutzer
nicht zu sehen und wird beim Editieren von Shop-Informationen benötigt.
Seite 60
Diplomarbeit
Lanzanasto, Neumann, Plattner
Editieren
Beim Klick auf den „Edit“-Button wird der „editable“-Status aller TextBoxes auf
„true“ gesetzt. Ausnahmen bilden dabei die Informationen „Country“ und „VG-Nr.“.
Diese beiden Informationen kommen nicht aus der „shops“-Tabelle der
Datenbank, sondern sind Informationen, die über den Country-Code aus der
„country“-Tabelle ausgelesen werden. Diese beiden Einträge können also nur in
Verbindung mit dem Country-Code verändert werden.
Außerdem wird der Hintergrund der Einträge „Store Name“, „SAP – Ship to“,
„Type“ und „Country Code“ gelb eingefärbt, da es sich hierbei um Pflichtfelder
handelt. Weiters wird der „Edit“-Button in einen „Save“-Button umgewandelt,
indem die Beschriftung des Buttons verändert wird. Daher wird auch bei jedem
Klick auf den Button mittels If-Abfrage auf die Buttonbeschriftung ausgewählt,
welche Funktionen ausgeführt werden sollen.
buttonEditSave.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
.
.
.
if (buttonEditSave.getText().equals("Edit")) {
textShopname.setEditable(true);
textShopname.setBackground(ColorLightYellow);
textSAP.setEditable(true);
textSAP.setBackground(ColorLightYellow);
.
.
.
} else if (buttonEditSave.getText().equals("Save")) {
.
.
.
}
}
});
Nachdem der Benutzer die gewünschten Daten geändert hat und den „Save“Button geklickt hat, werden manche der neuen Einträge überprüft, um Fehler in
der Datenbank zu verhindern. Überprüft werden dabei die gelb markierten
Pflichtfelder und alle Datumsfelder. Bei den Feldern „Store Name“ und „Type“
wird lediglich überprüft, ob ein Eintrag in dem Feld vorhanden ist. Beim Eintrag
Seite 61
Diplomarbeit
Lanzanasto, Neumann, Plattner
„SAP – Ship to“ wird überprüft, ob die eingetragene SAP-Nummer bereits in der
Datenbank vorhanden ist. Falls dieser Eintrag beim Editieren jedoch nicht
verändert wurde, befindet sich klarerweise bereits ein Datensatz mit diesem
Primary Key in der Datenbank, hier kommt das versteckte „Current SAP“-Textfeld
zum Einsatz. Falls die beiden Einträge übereinstimmen, liegt hier natürlich kein
ungültiger Eintrag vor.
Beim Eintrag „Country Code“ muss überprüft werden, ob der angegebene Code
auch wirklich ein Eintrag in der „country“-Tabelle ist, damit eine gültige
Verknüpfung der Tabellen gewährleistet werden kann.
// Check "SAP-Ship to"
sSQLStatement = "SELECT COUNT(sap_ship_to) FROM shopinfo.shops WHERE sap_ship_to='";
sSQLStatement = sSQLStatement + textSAP.getText();
sSQLStatement = sSQLStatement + "'";
if (((Integer.parseInt(db_con.getSingleCount(sSQLStatement)) > 0)
&& (textCurrentSAP.getText().equals(textSAP.getText()) == false))
|| (textSAP.getText().equals(""))) {
bFailed = true;
textSAP.setBackground(ColorLightRed);
} else {
textSAP.setBackground(ColorLightYellow);
}
.
.
.
// Check "Country-Code"
sSQLStatement = "SELECT COUNT(country_code) FROM shopinfo.country WHERE
country_code='";
sSQLStatement = sSQLStatement + textCountryCode.getText();
sSQLStatement = sSQLStatement + "'";
if ((Integer.parseInt(db_con.getSingleCount(sSQLStatement)) != 1)
|| (textCountryCode.getText().equals(""))) {
bFailed = true;
textCountryCode.setBackground(ColorLightRed);
} else {
textCountryCode.setBackground(ColorLightYellow);
}
Da in den einzelnen Tabellen des Öfteren Datumseinträge vorkommen, wurde für
diese Überprüfung eine eigene Funktion angelegt, die „isDateFormatCorrect()“Funktion. Hier wird der Datumswert als String übergeben und eine bool’sche
Variable zurückgegeben. Innerhalb der Funktion wird der übergebene String in
die Anteile für Jahr, Monat und Tag zerlegt. Diese Werte müssen durch einen
Bindestrich getrennt sein. Anschließend wird überprüft, ob die Einträge plausibel
sind, wobei die Werte nicht genau überprüft werden. Beispielsweise würde die
Seite 62
Diplomarbeit
Lanzanasto, Neumann, Plattner
Funktion den Eintrag „2013-02-30“ als gültig einstufen, obwohl dieses Datum
natürlich nicht korrekt wäre.
boolean isDateFormatCorrect(String sDate) {
boolean bCorrect = true;
String sYear;
String sMonth;
String sDay;
int iYear;
int iMonth;
int iDay;
if (sDate.length() != 10)
bCorrect = false;
if (bCorrect) {
sYear = sDate.substring(0, 4);
sMonth = sDate.substring(5, 7);
sDay = sDate.substring(8, 10);
if (sDate.substring(4, 5).equals("-") == false)
bCorrect = false;
if (sDate.substring(7, 8).equals("-") == false)
bCorrect = false;
try {
iYear = Integer.valueOf(sYear).intValue();
iMonth = Integer.valueOf(sMonth).intValue();
iDay = Integer.valueOf(sDay).intValue();
if (iYear < 1 || iYear > 9999)
bCorrect = false;
if (iMonth < 1 || iMonth > 12)
bCorrect = false;
if (iDay < 1 || iDay > 31)
bCorrect = false;
} catch (NumberFormatException e1) {
bCorrect = false;
}
}
return bCorrect;
}
Sollten bei den überprüften Einträgen ein oder mehrere ungültige entdeckt
worden sein, werden die entsprechenden TextBoxes rot hinterlegt und ein PopupFenster wird geöffnet, welches den User auf diese Felder hinweist. Falls jedoch
alle Einträge als korrekt anerkannt wurden, wird versucht, die nun generierte
UPDATE-Abfrage auf der Datenbank auszuführen. Sollte hierbei ein, trotz der
Überprüfungen, Fehler auftreten, wird ein Popup-Fenster geöffnet, das die
Fehlernachricht der Datenbank anzeigt. Solche Fehler können beispielsweise ein
Seite 63
Diplomarbeit
Lanzanasto, Neumann, Plattner
Datumswert sein oder ein zu langer Eintrag. Diese Einträge können aber vom
Programm leider nicht gekennzeichnet werden, sie müssen also vom Benutzer
selbst gefunden werden, was mit Hilfe der Error-Message jedoch kein Problem
darstellen sollte.
Nun wird noch überprüft, ob die SAP-Nummer des Shops verändert wurde. Ist
dies der Fall, muss auch die SAP-Nummer der verknüpften HardwareKomponenten geändert werden, um die Verknüpfung nicht zu verlieren.
Sollten all diese Prozesse ohne Fehler abgelaufen sein, werden alle TextBoxes
wieder auf den ursprünglichen Status zurückgesetzt und der „Save“-Button wird
wieder zum „Edit“-Button umgewandelt. Außerdem muss für die nächste
Änderung der Eintrag für die „CurrentSAP“ aktualisiert werden.
Shop schließen
Der „Close this shop“-Button ermöglicht es dem Benutzer einen Shop zu
schließen. Aus Sicht der Datenbank wird der Shop nicht gelöscht, sondern der
Datensatz lediglich von der „shops“-Tabelle in die „closed_shops“-Tabelle
übertragen. Beim Klick auf diesen Button wird zuerst ein Popup-Fenster geöffnet,
in dem der User seine Absicht den Shop zu schließen bestätigen muss.
Als Erstes wird überprüft, ob der gerade betrachtete Shop wirklich in der „shops“Tabelle gespeichert ist und nicht schon vorher geschlossen wurde. Anschließend
werden die Daten in die „closed_shops“-Tabelle eingetragen, das sollte unbedingt
geschehen, bevor der Shop aus der „shops“-Tabelle entfernt wird, damit es bei
einem Fehler zu keinem Datenverlust kommt. Danach wird der Shop aus der
„shops“-Tabelle gelöscht.
Sollte während der Übertragung ein Fehler auftreten, wird ein Popupfenster
geöffnet, welches Informationen über den Zeitpunkt des Fehlers enthält und die
Fehlermessage der Datenbank wiedergibt.
Seite 64
Diplomarbeit
Lanzanasto, Neumann, Plattner
if (bFailed == false) {
// Check if shop is already closed
sSQLStatement = "SELECT COUNT(sap_ship_to) FROM shopinfo.shops ";
sSQLStatement = sSQLStatement + "WHERE sap_ship_to='";
sSQLStatement = sSQLStatement + textSAP.getText();
sSQLStatement = sSQLStatement + "'";
if ((Integer.parseInt(db_con.getSingleCount(sSQLStatement)) == 0)) {...}
}
if (bFailed == false) {
// Insert shop into closed_shop - table
sSQLStatement = "INSERT INTO shopinfo.closed_shops ";
sSQLStatement += "(sap_ship_to, country_code,...) VALUES ('";
sSQLStatement += textSAP.getText();
sSQLStatement += "', '";
sSQLStatement += textCountryCode.getText();
sSQLStatement += "', '";
.
.
.
try {
db_con.editDatabaseWithException(sSQLStatement);
} catch (SQLException e2) {...}
// Delete shop from shops - table
if (bFailed == false) {
sSQLStatement = "DELETE FROM shopinfo.shops WHERE sap_ship_to=\"";
sSQLStatement += textSAP.getText();
sSQLStatement += "\"";
try {
db_con.editDatabaseWithException(sSQLStatement);
} catch (SQLException e2) {...}
}
}
Bei der Darstellung der Shop-Details werden auf der rechten Seite der
Arbeitsfläche in einem TabFolder die Details der verlinkten Hardware angezeigt.
Dabei stellt jeder Tab des Folders eine Hardewarekomponente dar, die einzelnen
Datensätze werden dabei mittels SAP-Nummer aus der „hardware“-Tabelle der
Datenbank herausgefiltert. Der Inhalt eines solchen Tabs wird im Prinzip gleich
generiert, wie wenn nur eine Hardwarekomponente einzeln dargestellt wird (siehe
4.5.11.3 showHardwareDetails()).
Abschließend wird nun noch die Selection des Tabfolders, in dem die Hardware
dargestellt wird, ausgewählt. Bei normaler Auswahl des Shops wird einfach das
erste Element des Folders angezeigt. Wurde jedoch eine spezielle Hardware über
die Suche ausgewählt (siehe 4.5.9 Search), welche mit einem Shop verknüpft ist,
Seite 65
Diplomarbeit
Lanzanasto, Neumann, Plattner
wird jener Tab gesucht, welcher der gesuchten Hardware entspricht und
ausgewählt.
int iIndex = 0;
int iLoop;
for (iLoop = 0; iLoop < folder.getItemCount(); iLoop++) {
if (folder.getItem(iLoop).getText().
equals(treeListener.getSelectedHWHostname())) {
iIndex = iLoop;
}
}
folder.setSelection(iIndex);
4.5.11.2. showClosedShopDetails()
Diese Funktion wird nur dann ausgeführt, wenn die Details eines geschlossenen
Shops angezeigt werden sollen. Das wiederum kann nur dann sein, wenn ein
solcher Shop mit Hilfe der Suchfunktion ausgewählt wurde. Die Funktion an sich
ähnelt sehr der Funktion „showShopDetails()“, es gibt nur wenige kleine
Unterschiede.
Zum einen befindet sich eine Zeile mehr in der Arbeitsfläche, nämlich die für die
automatisch vergebene ID. Diese Nummer ist aber auch nach Klicken des „Edit“Buttons nicht veränderbar, da es erstens nicht notwendig ist und zweitens die
Handhabung einer UPDATE-Abfrage um einiges vereinfacht wird.
Ein weiterer Unterschied ist der zweite Button neben dem „Edit“-Button, der „ReOpen this Shop“-Button. Diese Schaltfläche bildet das Gegenstück zum „Close
this Shop“-Button aus der „showShopDetails()“-Funktion. Hiermit kann ein
geschlossener Shop wieder geöffnet werden, indem der Datensatz von der
„closed_shops“-Tabelle der Datenbank in die „shops“-Tabelle verschoben wird.
Der dritte und letzte Unterschied ist, dass in der Anzeige immer nur die Details
eines Shops dargestellt werden und nie die dazugehörigen Hardwarekomponenten, da Hardware-Datensätze nicht mit einem geschlossenen Shop verlinkt
werden können.
Ansonsten funktioniert die Darstellung und Veränderung von Einträgen gleich wie
bei einem normalen Shop.
Seite 66
Diplomarbeit
Lanzanasto, Neumann, Plattner
4.5.11.3. showHardwareDetails()
Diese Funktion wird immer dann ausgeführt, wenn eine Hardwarekomponente
einzeln dargestellt werden soll. Das passiert aber nur dann, wenn über das
Suchmenü ein Datensatz ausgewählt wurde, der mit keinem Shop verlinkt ist.
Falls eine Verknüpfung vorliegt, wird immer der gesamte Shop inklusive aller
Hardwarekomponenten angezeigt. Da aber die einzelnen Tabs in der ShopDarstellung für die Hardwaredetails gleich generiert werden wie in dieser
Funktion, wird diese Funktion nun auch genauer erklärt.
Die Darstellung der einzelnen Details findet ähnlich wie bei der Anzeige der
Shop-Details statt. Für eine bessere Übersicht werden TextBoxes eingefügt,
deren „enable“-Status auf „false“ gesetzt wird, die eine Unterteilung in allgemeine
Informationen, Software-spezifische Details und bisherige Standorte andeuten.
Auch bei dieser Darstellung wurde wieder eine TextBox versteckt, die die
derzeitige Seriennummer speichert. Hier befindet sich die TextBox direkt neben
der „General“-Überschrift. Diese Nummer wird wie schon bei den Shops für
Veränderungen der Details benötigt.
Der „Edit“-Button funktioniert auch gleich wie bei den Shops, einziger kleiner
Unterschied ist, dass manche Überprüfungen der Einträge nach einem etwas
anderen Muster ablaufen.
Bei der Seriennummer wird wieder überprüft, ob diese eindeutig ist, da es sich
hierbei um den Primary Key in der Datenbank-Tabelle handelt, beim Hostnamen
muss lediglich ein Eintrag vorhanden sein.
Der Eintrag im Feld „Ship to“ muss entweder auf einen geöffneten Shop
verweisen oder komplett leer sein. Ein leeres Feld gibt an, dass diese Hardware
zu keinem Shop verlinkt ist. Auf Grund dieser Überprüfung kann es jedoch
passieren, dass es Hardwarekomponenten gibt, die zwar nach dem Importieren
aus der Excel-Tabelle eine SAP-Nummer eingetragen haben, diese aber zu
keinem gültigen Shop eine Verknüpfung darstellt. Ein solcher Datensatz wird in
der Datenbank zwar akzeptiert, kann aber nur verändert werden, wenn die
eingetragene SAP-Nummer heraus gelöscht wird oder zu einer gültigen Nummer
geändert wird.
Seite 67
Diplomarbeit
Lanzanasto, Neumann, Plattner
4.5.11.4. showCountryDetails()
Die vierte und letzte „showDetails“-Funktion ist den vorhergehenden ziemlich
ähnlich. Diese Funktion wird immer dann ausgeführt, wenn die Details eines
Landes angezeigt werden sollen. Ein Land kann ausgewählt werden, indem man
entweder links in der Baumstruktur auf die entsprechende Verzweigung klickt,
oder indem man in der Gesamttabelle für die Länder eines auswählt.
Die Anzeige der Details funktioniert im Prinzip gleich wie bei den anderen
Funktionen. Um die Details veränderbar zu machen, wird wieder ein „Edit“-Button
angezeigt. Eine kleine Besonderheit ist hier, dass im Feld „Region“ kein beliebiger
Eintrag eingefügt werden kann. Hier wird also keine TextBox verwendet, sondern
eine
sogenannte
ComboBox.
Sie
hat
mehrere
verschiedene
Auswahl-
möglichkeiten, die programmtechnisch festgelegt werden, in unserem Fall kann
via „DropDown“-Funktion
zwischen
„Europe“, „Americas“ und „Asia Pacific“
gewählt werden.
Label labelRegion = new Label(contentGroupMain, SWT.NONE);
labelRegion.setText("Region: ");
final Combo comboRegion = new Combo(contentGroupMain, SWT.READ_ONLY);
comboRegion.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
comboRegion.setItems(new String[] { "Europe", "Americas", "Asia Pacific" });
comboRegion.setText(country.get(0).getRegion());
comboRegion.setEnabled(false);
Sonstige Maßnahmen zur Vorbeugung von fehlerhaften Einträgen werden bei
den Feldern „Country-Code“, „Country“ und „VG-Nummer“ getroffen, wobei hier
nur überprüft wird, ob ein Eintrag vorhanden ist bzw. ob dieser eine vorgegebene
Länge einhält.
Um Änderungen des „Country-Code“-Eintrags zu ermöglichen, wird wieder in
einer versteckten TextBox der derzeitige Country-Code zwischengespeichert, da
dieser den Primary Key in der Datenbanktabelle bildet, gleich wie die SAPNummer bei Shops bzw. die Seriennummer bei Hardware-Datensätzen.
Seite 68
Diplomarbeit
4.5.12.
Lanzanasto, Neumann, Plattner
Add
Beim Erschaffen einer Instanz dieser Klasse wird ein TabFolder im Part platziert.
Über diese Tabs kann ausgewählt werden, welche Art von neuem Eintrag
gemacht werden soll. Es kann zwischen Shop, Hardware und Country gewählt
werden. In allen drei Tabs wird, gleich wie bei der Anzeige von Details, eine
ContentGroup erstellt, in der sich sämtliche TextBoxes für die einzelnen Einträge
befinden. Alle diese TextBoxes sind standardmäßig mit einem Leerstring gefüllt,
außer jene, in denen ein Datumswert eingetragen werden soll. In diesen Feldern
wird als Default-Wert „0001-01-01“ verwendet, um dem User auch gleich die
richtige Datumsformatierung anzuzeigen.
Um das richtige Verknüpfen von Datensätzen für den User zu erleichtern, werden
die relevanten Einträge automatisch ausgefüllt. Dieser Eintrag wird aus der
zurzeit getätigten Auswahl im treeListener abgeleitet. Falls der User beispielsweise ein Land ausgewählt hat, wird beim Klick auf den „Add“-Button im
neu geöffneten Part sofort der „Add Shop“-Tab ausgewählt und der passende
„Country-Code“ für des ausgewählte Land eingetragen. Diese Funktion ist vor
allem beim Hinzufügen von Hardware sehr hilfreich, da der User so nicht die
meist siebenstellige SAP-Nummer des dazugehörigen Shops eintragen muss. So
wird fehlerhaften Verknüpfungen vorgebeugt.
if (treeListener.getSelectedCountry() != "")
folder.setSelection(itemShop);
else if (treeListener.getSelectedShop() != "")
folder.setSelection(itemHW);
else if (treeListener.getSelectedRegion() != "")
folder.setSelection(itemCountry);
Falls bei der Eingabe Felder trotzdem falsch befüllt werden, werden diese Fehler
beim Klick auf den „Save“-Button erkannt und gleich wie beim Editieren in der
Detail-Ansicht farblich markiert. Es werden hier die gleichen Felder überprüft wie
beim Editieren von Einträgen.
Seite 69
Diplomarbeit
Lanzanasto, Neumann, Plattner
5. Manual/Bedienungsanleitung
In diesem Kapitel wird das User Interface Punkt für Punkt beschrieben und
erklärt, wie man es bedient und zu einem gewünschten Ergebnis kommt.
5.1.
Oberfläche
Startet man das Programm, so erscheint folgende Oberfläche (hier mit gekennzeichneten Flächen):
Menü
Arbeitsfläche
Abb. 10: Oberflächen Übersicht
Tree
Seite 70
Diplomarbeit
5.2.
Lanzanasto, Neumann, Plattner
Menü
Abb. 11: Menü
Das Menü befindet sich in der oberen linken Ecke und ist dort immer zu sehen.
Die Icons öffnen entweder einen neuen Tab in der Arbeitsfläche oder ein kleines
Dialogfenster.
Die Funktion der Icons von links nach rechts beschrieben:
 Suche: Es öffnet sich der Suche-Tab. Weitere Informationen bei 5.5 Suche.
 Neues Element hinzufügen: Es öffnet sich ein neuer Tab zur Erstellung
eines neuen Elements. Weitere Informationen bei 5.6 Neues Element
hinzufügen.
 Statistiken: Es öffnet sich ein neuer Tab mit diversen Statistiken. Weitere
Informationen bei 5.7 Statistiken.
 Details aufrufen: Es öffnet sich ein neuer Tab mit den Details des ausgewählten Objekts. Weiter Informationen bei 5.8 Details.
 Über: Es öffnet sich eine Messagebox mit Informationen über das
Programm.
 Beenden: Es wird eine „Beenden“-Dialogbox aufgerufen.
Seite 71
Diplomarbeit
5.3.
Lanzanasto, Neumann, Plattner
Tree
Der Tree soll einen schnellen Überblick und Zugriff auf alle Inhalte der Datenbank
liefern.
Mit den zwei Tabs am oberen Rand
des Trees kann ausgewählt werden,
ob bestehende oder aufgelöste Shops
angezeigt werden sollen.
Das Textfeld darunter bietet einen
Quick search, mit dem man sofort
einen bestimmten Shop über die SAPNummer auswählen kann. Der Tree an
sich besteht aus fünf Ebenen.
Abb. 12: Tree
Die Ebenen sind folgende: Kontinent – Land – Shoptyp – Shop – Hardware.
So kann man sich intuitiv und hierarchisch von oben herab zum gewünschten
Shop klicken und dort sofort auch die Hardware einsehen.
5.4.
Arbeitsfläche
In der Arbeitsfläche werden mittels Tabs die gewünschten Anfragen angezeigt.
Beim Programmstart sind drei nicht schließbare Tabs standardmäßig geöffnet: Es
werden die Tabs Country, Shop und Closed Shop mit deren Informationen jeweils
in Tabellenform angezeigt. Die Arbeitsfläche ist der einzige Bereich, in dem der
Benutzer Änderungen vornehmen kann, wie zum Beispiel Einträge von der
Datenbank editieren.
Jede Aktion in der Toolbar öffnet einen neuen Tab in der Arbeitsfläche, der auch
wieder geschlossen werden kann.
Seite 72
Diplomarbeit
5.5.
Lanzanasto, Neumann, Plattner
Suche
Mit der Suche kann man nach speziellen Elementen in der Datenbank suchen,
auch wenn man nicht ganz genau weiß, was man sucht. Es kann nicht nur nach
einem Element gesucht werden, sondern auch nach mehreren.
Um die Suche aufzurufen, drückt man den „Suche“-Button im Menü (siehe 5.2
Menü). Es öffnet sich dann folgender Tab:
Abb. 13 Suche
Mit den zwei Tabs in der linken oberen Ecke kann ausgewählt werden, ob man
nach Shops oder Hardware suchen will. Darunter befinden sich einige
Suchparameter, die eingegeben werden können, um die Suche zu spezialisieren.
Es müssen keine vollständigen Suchparameter sein, es können auch nur
Wortphrasen eingegeben werden. Wird in mehreren Feldern etwas eingetragen,
so
liefert
das
Suchergebnis
nur
Elemente,
die
allen
Suchparametern
entsprechen.
Ist die Checkbox „Closed Shop“ aktiviert, so wird nur nach aufgelösten Shops
gesucht.
Seite 73
Diplomarbeit
5.6.
Lanzanasto, Neumann, Plattner
Neues Element hinzufügen
Abb. 14: Hinzufügen einer Hardware
Da das Unternehmen nicht schläft und sich im Bereich der Shops und Hardware
immer etwas ändert, kann man mit diesem „Wizard“ ein neues Land, einen neuen
Shop oder eine neue Hardware hinzufügen.
Mit den drei Tabs am oberen Rand kann ausgewählt werden, ob nun ein Shop,
eine Hardware oder ein Land hinzugefügt wird. Es erscheint dann ein Formular, in
das alle Informationen eingetragen werden können, die das Element betreffen.
Die gelben Felder zeigen Pflichtfelder an, die unbedingt ausgefüllt werden
müssen. Die anderen Felder können, müssen aber nicht gefüllt werden.
Datumsfelder müssen in folgendem Format eingetragen werden: YYYY-MM-DD.
Wenn kein Datum eingetragen werden kann, so bleibt das Default-Datum im Feld
stehen. Dies ist programmtechnisch bedingt. Zum Abschließen des Vorgangs
drückt man den Save-Button am unteren Rand des Formulars.
Seite 74
Diplomarbeit
5.7.
Lanzanasto, Neumann, Plattner
Statistiken
Mit dieser Funktion erhält man einen Überblick über die Kontinente und Länder
z.B. in Bezug auf die Anzahl der Shops und Hardware in einem Land.
Abb. 15: Statistiken
Mit den vier Tabs am oberen Rand kann man die gewünschte Region auswählen.
Es werden dann jeweils die verschiedenen Shoptypen und weitere Elemente
aufgelistet.
5.8.
Details
Mit den Details ruft man die speziellen Eigenschaften eines Elements auf, man
erhält alle eingetragenen Informationen auf einen Blick. Um die Details
aufzurufen, wählt man das gewünschte Element im Tree, aus der Liste oder
mittels der Suche aus und drückt anschließend den „Details“-Button im Menü
(siehe 5.2 Menü). Es öffnet sich folgender Tab, wobei der Tabname aus „Shop
Details: SAP-Nummer“ besteht, um den Überblick über die geöffneten Tabs zu
behalten:
Seite 75
Diplomarbeit
Lanzanasto, Neumann, Plattner
Abb. 16: Shop Details
Ruft man einen Shop auf, so wie in Abb. 16: Shop Details, so sieht man auf der
linken Seite der Arbeitsfläche die Details, die den Shop an sich betreffen. Auf der
rechten Seite befindet sich die Hardware, die im Shop vorhanden ist. Bei
mehreren Teilen kann man über die Tabs direkt oberhalb der Hardware zwischen
den einzelnen Hardwarekomponenten wählen. Am unteren Ende beider Seiten
befindet sich der Button „Edit“. Dieser wird zum Editieren der Elemente
verwendet.
Wird ein Shop aufgelöst, so kann man ihn im Programm mit dem „Close this
Shop“-Button am unteren Ende des Formulars als geschlossen kennzeichnen.
Der Shop ist nun nur noch unter den „Closed Shops“ im Programm zu finden.
Seite 76
Diplomarbeit
Lanzanasto, Neumann, Plattner
Editieren
Ändert sich irgendeine Information zu einem Element, so kann man einfach mit
dem Button „Edit“ in der Details-Ansicht (siehe 5.8 Details) das Element editieren.
Dabei bleibt der Tab derselbe, die Informationen lassen sich aber nun verändern.
Abb. 17: Shop Editieren
So wie beim Hinzufügen eines neuen Elements erscheinen auch hier Textfelder,
die zum Eintragen der Informationen genutzt werden. Die gelben Textfelder
zeigen Pflichtfelder an, die unbedingt ausgefüllt werden müssen. Sind alle
Änderungen vorgenommen, so schließt man das Editieren mit einem Klick auf
den Save-Button am unteren Ende des Formulars ab. Die Änderungen werden
nun in der Datenbank übernommen.
Seite 77
Diplomarbeit
Lanzanasto, Neumann, Plattner
Bilder-Verzeichnis
Abb. 1: Grundaufbau .................................................................................................. 8
Abb. 2: Firmenlogo Swarovski .................................................................................... 9
Abb. 3: Ordnerstruktur .............................................................................................. 28
Abb. 4 Application Model .......................................................................................... 32
Abb. 5: Fenster-Struktur ........................................................................................... 35
Abb. 6: Toolbar ......................................................................................................... 35
Abb. 7: Handlers ....................................................................................................... 36
Abb. 8: Commands ................................................................................................... 36
Abb. 9: Grundstruktur ............................................................................................... 36
Abb. 10: Oberflächen Übersicht ................................................................................ 70
Abb. 11: Menü .......................................................................................................... 71
Abb. 12: Tree ............................................................................................................ 72
Abb. 13 Suche .......................................................................................................... 73
Abb. 14: Hinzufügen einer Hardware ........................................................................ 74
Abb. 15: Statistiken ................................................................................................... 75
Abb. 16: Shop Details ............................................................................................... 76
Abb. 17: Shop Editieren ............................................................................................ 77
Seite 78