Datenbank Framework CogniX

Werbung
Datenbank Framework CogniX
Herbert Liechti, <[email protected]>
19. Februar 2001
Mit dem Einstieg in die Web-Programmierung vor ca 3 Jahren störte mich immer wieder, daß die sogenannten Embedded-Sprachen wie HTML::EP, Embperl,
HTML::Mason, php, asp usw keine richtigen Applikationen zulassen. Die EmbeddedSprachen haben zwar klar den Vorteil, rasch eine Layout-Vorgabe in ein dynamisches Umfeld zu integrieren, versagen aber meiner Meinung nach bei der Bildung
einer Applikation und eines konsistenten Benutzer-Interfaces.
Eine konsistente Entwicklung, wie man sie aus der klassischen Client/ServerProgrammierung kennt, ist einfach nicht gewährleistet. Das Programmieren der
Datenbank-Interfaces ist trotz der sehr guten DBI/DBD Libraries eher mühsam und
langweilig, weil man stets die gleiche Funktionalität wieder programmiert. Wenn in
einem Projekt Automaten (Dämonen, Scheduler etc) notwendig werden, implementiert man die Programme nochmals neu. Business- und Datenlogik sind da zumeist
in den CGI-Programmen fest integriert und lassen sich nicht ohne weiteres ohne
Benutzer-Interface betreiben.
Die Idee ein Objekt-orientiertes Framework zu entwickeln, war da ziemlich rasch
geboren und in den letzten zwei Jahren ist ein gutes Werkzeug entstanden, welches
erlaubt, rasch und effizient Datenbank-Applikationen zu erstellen, die vollständig
über ein Browser-Interface bedienbar sind.
Auf den nachfolgenden Seiten stelle ich die wichtigsten Features des Frameworks
vor. CogniX ist umfassend dokumentiert, in diesem Dokument können die Möglichkeiten von CogniX nur im Überblick beschrieben werden.
1
Inhaltsverzeichnis
1
Key features
3
2
Bezugsquelle
5
3
Architektur
3.1
3.2
3.3
3.4
3.5
3.6
3.7
3.8
3.9
3.10
4
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
6
7
9
10
10
11
12
12
13
14
6
7
Klassendefinition . . . . . . .
Technische Dokumentation . .
Erstellen der Tabelle in der DB
Sprach-Unabhängigkeit . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
14
15
16
17
Bilden von Präsentations Klassen
18
5.1
5.2
Konfiguration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Weiterführende Anpassungen . . . . . . . . . . . . . . . . . . . . . . . . . . .
18
19
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
14
Dokumentation CogniX
19
Tools
7.1
7.2
7.3
7.4
7.5
7.6
8
.
.
.
.
.
.
.
.
.
.
Bilden von Datenbank-Klassen
4.1
4.2
4.3
4.4
5
5
Datenlogik . . . . . . .
Präsentations-Logik . .
Berechtigungen . . . .
Event-Handling . . . .
Formatierung der Daten
Ausgabe . . . . . . . .
Exception Handling . .
Dokumentation . . . .
Tools . . . . . . . . . .
Perl Module . . . . . .
createTemplate
crebas . . . . .
prepLanguage .
heinzelmann . .
load . . . . . .
checkIntegrity .
20
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
Showcases
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
20
20
20
20
20
20
21
2
Abbildungsverzeichnis
1
2
3
4
5
1
Architektur CogniX . . . . . . . . . . . . . . . . . . . . . . . . . .
Tabellensicht . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Abhängige Datensätze werden automatisch angezeigt . . . . . . . . . .
Erfassung eines neuen Datensatzes . . . . . . . . . . . . . . . . . . .
Datenbankmodell und -Dokumentation über den Browser verfügbar
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
5
7
8
8
13
Key features
Die Key Features von CogniX sind:
• Schnelles Erstellen von Datenbank gestützten Web-Anwendungen
– Daten- und Business-Logik sind getrennt von der Präsentations-Logik. Die Teile
können unabhängig voneinander betrieben werden. So ist es möglich, Programme zu
schreiben, die ohne menschliche Interaktion ablaufen (Dämonen), welche die gleichen Daten-Klassen benutzen, wie die Benutzerprogramme
– Generierung von Default-Präsentationsklassen
– Unterstützung von Mehrsprachigkeit zum Beispiel in Abhängigkeit des aktuellen
Benutzers
– Automatische Unterstützung von referentieller Integrität, wenn nicht auf der Datenbank definiert
– Vergabe von Benutzerrechten auf Tabellenebene sowohl für einzelne Benutzer als
auch für ganze Benutzer-Gruppen
– Default Web Schnittstelle
* Browsing in der kompletten Datenbank-Struktur (Geeignet auch für große Datenmengen)
* Fremdschlüssel können mit automatisch generierten Hyperlinks verfolgt werden (intuitive Navigation in der Datenbank-Struktur)
* Freie Eingabe von Suchkriterien für Queries
* Datenbankverkehr (insert, update, delete) mit Sicherstellung der referentiellen
Integrität
* Cascading-Deletes (Konfigurierbar)
– Datenbank-Modell mit POD Dokumentation über Browser abrufbar
– Generierung von SQL-Scripts für die Erstellung der Datenbank.
• Unterstützung der folgenden Datenbanken:
3
– Postgres ab Version 6.5.3
Frei verfügbares objekt-relationales Datenbank-Management-System (www.postgresql.org)
– Informix mit Universal Data Option
Kommerzielles Datenbank-Produkt (www.informix.com)
– Oracle ab 8.1.6
Kommerzielles Datenbank-Produkt (www.oracle.com)
– DBD::Proxy
Über einen Proxy Modus können beliebige Datenbanken auf fernen Rechnern angesprochen werden, aufwendige Installationen von Datenbank spezifischen Client- und
Netz-Produkten entfällt somit komplett. Die jeweiligen Datenbank-Treiber müssen
nur auf dem Datenbank-Server installiert sein.
Weitere Datenbanken können mit geringem Aufwand in das Framework integriert werden.
• Rasche Entwicklung von Internet-/Intranet-Applikationen
– Konfiguration des Benutzer-Interfaces
– Unterstützung für mehrsprachige Applikationen
– Einfaches Hinzufügen von Business-Logik wo notwendig
– Einfaches User/Session Handling (Apache::Session)
– Unterstützung bei komplexen DB-Abfragen
– Wiederverwendbarkeit von Codeteilen
– Einfaches Einbinden von Client seitigem Java-Script-Code
• Perl
– Strikter Einsatz des objektorientierten Paradigmas von Perl
– Verwendung von Perl-Libraries aus dem CPAN (z.Bsp. CGI, CGI::FastTemplate,
DBI, Apache::Session)
– mod-perl für einen nativen Zugriff via Web-Server auf die Applikation
– Einfache Realisierung von Schnittstellen (z.Bsp. XML) Dank den frei verfügbaren
Bibliotheken.
• Kombinierbar
Mit dem Framework können Applikationen erstellt werden, die sich hervorragend für das
Verwalten von Daten über ein Web-Interface eignen. Das war die treibende Kraft für die
Entwicklung von CogniX. Für Layout geprägte Anwendungen, die meist nur einen lesenden Zugriff auf eine Datenbank ausüben, sind Produkte wie ePerl, HTML::Mason sehr
gut mit dem Framework kombinierbar.
4
• Dokumentation
Vollständig dokumentiert inkl. Beispiel-Anwendung. Gesamtdokumentation als pdf erhältlich.
2
Bezugsquelle
Mit Erscheinen dieser Dokumentation sollte CogniX über das CPAN verfügbar sein. Über unsere
Web-Site http://www.thinx.ch kann die jeweils neueste Version abgeholt werden.
3
Architektur
Beim Design von CogniX wurde konsequent darauf geachtet, daß Daten-, Business- und PräsentationsLogik vollständig getrennt sind. Dadurch eignet sich CogniX unter Verwendung der Datenund Business-Logik Schicht auch hervorragend für Automaten (Dämonen, Scheduler, Cron jobs
etc.).
Die nachfolgende Abbildung zeigt die Architektur auf.
DBI
DB
DBD
Presentati on l ogi c
Data and busi ness l ogi c
Abstract l ayer
dbView
wwwBase
DbBase
I mpl ementati on l ayer
Table.pm
wwwTable.pm
Busi ness l ogi c and appli cati on l ayer
blmModule
applModule
Uses
I nheri ts
Abbildung 1: Architektur CogniX
5
3.1
Datenlogik
Jede Tabelle einer Datenbank wird in CogniX mit einer eigenen Klasse repräsentiert. Eine solche Klasse erbt von der Klasse DbBase. DbBase implementiert die grundsätzlichen Funktionen
für den Verkehr mit der Datenbank (Select, Update, Insert, Delete) und stellt jederzeit die referentielle Integrität sicher. Validierungsfunktionen für die diversen Datentypen sind ebenfalls
Bestandteil von DbBase.
DbBase wiederum erbt von einer Klasse, die Datenbank abhängige Besonderheiten implementiert hat, soweit die Besonderheiten nicht über den DBD Driver abgehandelt sind (z.Bsp.
SERIAL, DATETIME Datentypen).
DbBase stellt diverse Hooks oder Insertion-Methoden zur Verfügung, die in der abgeleiteten
Klasse implementiert werden können. So können z.Bsp. mit der Methode setDefaultsAfterInsert
nach dem Einfügen eines neuen Datensatzes in der Daten-Klasse Aktionen durchgeführt werden,
ohne daß die Insert Methode verändert werden muß. Hier ein kleines Beispiel dazu. Angenommen, zu einem geänderten Tupel in der DB muß jedesmal ein History-Eintrag erfolgen.
=head2 setDefaultsAfterUpdate
Ueberschriebene Methode aus DbBase.
Wird gerufen, wenn ein Artikel-Record aktualisiert wurde.
Es muß ein History Eintrag für jede Aenderung bei der
Tabelle Artikel erstellt werden.
Ein Eintrag in PublishHistory wird nur erstellt, wenn
der Artikel einen Wert in ArtikelStatusId hat.
=cut
sub setDefaultsAfterUpdate {
my $self = shift;
$self->SUPER::setDefaultsAfterUpdate; # Zuerst die Methode der SUPER Klasse rufen
if ($self->getValue(’ArtikelStatusId’)) {
$main::msg->ignoreMessage(’message’, ’ok’);
# Standardmeldungen unterdrücken
# Neues Objekt der Klasse PublishHistory instanzieren.
my $PublishObj = PublishHistory->newEmpty(
{
artikelId
=> $self->getId,
ArtikelStatusId
=> $self->getValue(’ArtikelStatusId’),
MitarbeiterId
=> $self->getValue(’MitarbeiterId’),
Comments
=> ’Update Artikel’,
JobDone
=> ’f’,
rubrikId
=> $self->getValue(’rubrikId’),
}
);
$PublishObj->sqlInsert; # Wert in DB schreiben
$main::msg->acceptMessage(’message’, ’ok’);
}
}
Solche Hooks stehen für jede mögliche Aktion (Insert, Update und Delete) zur Verfügung,
bevor und nachdem die Aktion ausgeführt wird/wurde.
6
3.2
Präsentations-Logik
Analog zur Datenlogik wird jede Datenbank-Tabelle mit einer Präsentations-Klasse implementiert. In einem hohen Masse kann das Benutzerinterface mit Properties einfach konfiguriert werden. Eine solche Klasse erbt von wwwBase. wwwBase stellt über ein CGI-Interface die wesentlichen Funktionen für ein Benutzer-Interface zur Verfügung:
• Browsing in den Datenbeständen
– Tabellensicht
Abbildung 2: Tabellensicht
Anzeige der Tabellensicht. Mehrere Datensätze einer Tabelle werden angezeigt. Die
Funktion für das Seitenweise Blättern in den Datensätzen steht zur Verfügung.
– Record View
7
Abbildung 3: Abhängige Datensätze werden automatisch angezeigt
Anzeige eines einzelnen Datensatzes. Die abhängigen Datensätze werden automatisch angezeigt. Diese können per Parameter auch ausgeblendet werden.
– Neu Erfassung eines Datensatzes
Abbildung 4: Erfassung eines neuen Datensatzes
8
Ein Formular für die Erfassung eines neuen Datensatzes. Analog steht für das Editieren das gleiche Formular zur Verfügung.
– Editieren eines Datensatzes
– Löschen eines Datensatzes
– Suchen von Datensätzen
• Navigation
Mit Hyperlinks kann die Datenbank-Struktur verfolgt werden. Fremdschlüssel werden
automatisch aufgelöst und können bei der Eingabe mit Listboxen, Radioboxen oder einer
erweiterten Suche konfiguriert werden. Über die konfigurierten Benutzer-Berechtigungen
(siehe weiter unten) können Zugriffe auf andere Tabellen eingeschränkt werden.
• Scrolling
Bei grösseren Datenbeständen in einer Tabelle wird ein Seitenweises vorwärts und rückwärts Blättern angeboten. Der angezeigte Ausschnitt kann konfiguriert werden.
• Generelle Konfiguration Benutzerinterface
Das Aussehen des Benutzerinterface kann im hohen Masse über Systemparameter, Templates und Cascading Style Sheets konfiguriert werden.
3.3
Berechtigungen
Berechtigungen können in einer C/S Applikation bequem mit Datenbank eigenen Mitteln (grants)
bewerkstelligt werden. Da in einer CGI-Umgebung die Datenbank jeweils nur mit einem bestimmten Benutzer angesprochen wird, funktioniert die Vergabe von Berechtigungen nicht. CogniX unterstützt deshalb die Vergabe von Benutzerrechten auf der Datenbank mit einem Modul,
mit der für Benutzer und Benutzergruppen Rechte auf einer bestimmten Tabelle vergeben werden können:
package grantTable;
# available user groups
@grantTable::groups = qw(
admin user readonly
);
# Assignment of the user to the group
%grantTable::groupMember = (
user
=> ’user’,
patrick
=> ’admin’,
peter
=> ’admin’,
herbie
=> ’admin’,
mzaugg
=> ’admin’,
admin
=> ’admin’,
guest
=> ’readonly’,
9
);
%grantTable::Abo =
#user group
user
=>
admin
=>
readonly
=>
);
(
Read
[1,
[1,
[1,
%grantTable::Agenda = (
#user group
Read
user
=> [1,
admin
=> [1,
readonly
=> [1,
);
New record
1,
1,
0,
Update
1,
1,
0,
Delete
1,
1,
0,
Lookup
1,
1,
1,
],
],
],
New record
1,
1,
0,
Update
1,
1,
0,
Delete
1,
1,
0,
Lookup
1,
1,
1,
],
],
],
Der Benutzer mit dem Login patrick zum Beispiel wird über das Hash %grantTable::groupMember
der Benutzergruppe admin zugeordnet. Der Benutzer erhält so zum Beispiel auf der Tabelle Abo
das Recht, Daten zu lesen, Inserts, Updates und Deletes durchzuführen und bestimmte Werte
(lookup) aus der Tabelle zu lesen.
CogniX setzt diese Definitionen automatisch in der Applikation richtig um. So erhält die
Gruppe readonly zum Beispiel in keiner der Tabellen die Möglichkeit, Datensätze zu erfassen,
ändern oder löschen.
3.4
Event-Handling
Gestartet wird die Applikation über ein kurzes CGI Script. Das CGI Script führt lediglich
die Datenbank Connects durch und übergibt die Kontrolle danach dem aus der Klasse CogniX::CgiMain instanzierten Objekt. Das CogniX::CgiMain-Objekt bestimmt anhand der CGIParameter und der Sessionvariablen, welche Aktion ausgelöst werden muss (z.Bsp. neuer Datensatz erfassen in Tabelle Artikel). Es instanziert von der korrekten wwwKlasse (Präsentationsklasse) ein Objekt und ruft dort die notwendigen Methoden auf.
3.5
Formatierung der Daten
Die Formatierung der Ausgabe in HTML erfolgt über die Klasse CogniX::htmlStyle. Zur Startzeit der Applikation wird ein Objekt dieser Klasse instanziert. Jedes CogniX Projekt besitzt eine
zentrale Konfigurationsdatei, welche per Definition param.pm genannt wird. Dort werden unter
anderem die Parametrierungen für die Klasse CogniX::htmlStyle vorgenommen. Aussehen der
formatierten Ausgabe kann hier massgeblich beeinflusst werden. Hier sehen Sie ein Beispiel
einer solchen Konfiguration:
# Formatting of table elements in HTML output
%main::elements = (
# Tabellenformatierung (<TABLE> Tag)
dataViewTABLE => {-cellpadding => 2,
-cellspacing => 1,
10
-border
-width
},
# Formatierung <TH> Element
dataViewTH
=> {-align
-valign
-class
},
=> 0,
=> ’100%’,
=>
=>
=>
’left’,
’middle’,
’th1’,
# Formatierung <TD> Element
dataViewTD
=> {-align
=>
’left’,
-valign
=>
’top’,
-class
=>
’td1’,
},
# Formatierung <TD> Element. Zwischen dataViewTD und dataViewTD2
# wird bei Tabellensichten immer abgewechselt.
dataViewTD2
=> {-align
=>
’left’,
-valign
=>
’top’,
-class
=>
’td2’,
},
# Formatierung für Alert Formatierungen
dataViewAlert => {-align
=>
’left’,
-valign
=>
’top’,
-bgcolor
=>
’#FF0000’,
},
);
Nebst den hier angegeben Werten kann das Aussehen der Applikation durch CascadingStyle-Sheets (css) beeinflusst werden. Zum Beispiel ist oben das Element dataViewTH durch
den class Parameter th1 referenziert. Im css ist dann die folgende Definition abgebildet:
TH.th1
3.6
{
font-size:12pt;
color:white;
font-family:Helvetica,sans-serif;
font-weight:bold;
background-color:#778899;
text-align:left;
}
Ausgabe
Während der Verarbeitung erfolgt die Ausgabe der Ergebnisse nicht unmittelbar über STDOUT
sondern wird in einem Objekt der Klasse CogniX::htmlStyle zwischengespeichert. Die Präsentationsklassen, die von wwwBase abgeleitet sind, leiten die Ausgabe also an dieses Objekt weiter. Erst wenn die Verarbeitung komplett abgeschlossen ist, wird mit dem CGI::FastTemplate
Module ein Template mit dem fertigen Inhalt befüllt. Im Template selber gibt es vordefinierte
Platzhalter, die durch die Inhalte ersetzt werden. Layout Anpassungen sind deshalb sehr einfach
zu bewerkstelligen.
11
3.7
Exception Handling
Treten während der Verarbeitung Fehler auf, erhält der Benutzer nicht einfach eine Fatal Meldung des Web-Servers. CogniX nutzt intensiv den try, catch, throw Mechanismus (eval) von Perl.
Ausnahmesituationen werden also behandelt und Fehlermeldungen, Warnungen, Messages werden in einem Objekt der Klasse CogniX::message gesammelt und über das Ausgabe Objekt der
Klasse CogniX::htmlStyle ausgegeben.
3.8
Dokumentation
Über ein CGI-Interface dbmodel.pl haben die Entwickler und falls gewünscht die Benutzer Zugang zu der technischen Dokumentation. Es werden die Definitionen aus den Datenklassen und
allenfalls vorhandene POD-Dokumentation für die Aufbereitung verwendet.
Zur Laufzeit wird eine Tabellenbeschreibung aufbereitet, die einerseits die Definitionen der
Tabelle enthält und andererseits die aufbereitete POD-Dokumentation:
12
Abbildung 5: Datenbankmodell und -Dokumentation über den Browser verfügbar
Die über- und untergeordneten Tabellen können per Hyperlink verfolgt werden. Ein Beispiel,
wie die Dokumentation und die Tabellenstruktur definiert wird, erfolgt weiter unten im Abschnitt
’Bilden von Datenbank-Klassen’.
3.9
Tools
In den zwei Jahren sind zahlreiche Tools rund um CogniX entstanden, die den Entwicklungsprozess optimal unterstützen. Eine Auflistung der Tools finden Sie am Schluß des Dokumentes.
13
3.10 Perl Module
CogniX läuft unter mod_perl, kann aber auch über ein normales CGI Interface betrieben werden.
CogniX verwendet viele Libraries aus dem CPAN:
• CGI
• CGI::FastTemplate
• DBI
• DBD
Die jeweiligen Driver für eine spezifische Datenbank
• Apache::Session
4
Bilden von Datenbank-Klassen
In den Datenbank-Klassen werden die Struktur einer Tabelle definiert, die Beziehungen der Tabelle zu anderen Klassen (Relationship) definiert, Index-Definitionen vorgenommen. Übersetzungen in die Zielsprache(n) der Attribute und Tabellennamen erfolgt ebenfalls in der DatenbankKlasse. Für die Erstellung einer solchen Klasse steht das Tool createTemplate zur Verfügung.
Per Definition muß eine Datenklasse genauso heißen wie die entsprechende Tabelle in der Datenbank.
4.1
Klassendefinition
package Artikel;
use strict;
@Artikel::ISA = (’CogniX::DbBase’);
%Artikel::attribute = (
# order/type
length/mandatory/foreign key
ArtikelId
=> [ 1, ’SERIAL’,
0, 1, 0 ],
Zeitstempel
=> [ 2, ’DATETIME’,
0, 1, 0 ],
RubrikId
=> [ 3, ’INTEGER’,
0, 1, ’Rubrik.RubrikId’ ],
Haupttitel
=> [ 4, ’VARCHAR’,
80, 1, 0 ],
Untertitel
=> [ 5, ’VARCHAR’,
600, 1, 0 ],
Body
=> [ 6, ’OID’,
0, 1, 0 ],
Reihenfolge
=> [ 7, ’INTEGER’,
0, 0, 0 ],
MandantId
=> [ 8, ’INTEGER’,
0, 1, ’Mandant.MandantId’ ],
PersonId
=> [ 9, ’INTEGER’,
0, 1, ’Person.PersonId’ ],
ArtikelStatusId => [ 10, ’INTEGER’,
0, 1, ’ArtikelStatus.ArtikelStatusId’ ],
FlagFrontSide
=> [ 14, ’BOOLEAN’,
0, 1, 0 ],
);
# Detail tables
@Artikel::detail = qw(ArtikelLink.oberId
ArtikelLink.unterId
Bild.ArtikelId
14
SlArtikel.ArtikelId
);
$Artikel::pk
= ’ArtikelId’;
# Name of the primary key
$Artikel::timestamp
= ’Zeitstempel’;
$Artikel::sequenz
= ’artikelid_seq’;
$Artikel::cascadingDelete = 1;
%Artikel::indexes = (
fk_Artikel_1 => [’IX’, [’RubrikId’]],
fk_Artikel_2 => [’IX’, [’MandantId’]],
fk_Artikel_3 => [’IX’, [’PersonId’]],
fk_Artikel_4 => [’IX’, [’ArtikelStatusId’]],
);
1;
Die Attribute einer Tabelle sind als Keys im Hash %Artikel::atribute abgelegt und auf jeden
Key im Hash besteht eine Referenz auf ein anonymes Array als Value. Das anonyme Array
enthält die Position des Attributes in der Tabelle, den Datentyp, falls notwendig die Datenlänge,
die Angabe, ob es sich um ein optionales oder obligatorisches Feld handelt und die Definitionen
der Fremdschlüssel.
Im Array @Artikel::detail wird definiert, was für Child-Relationships die Tabelle hat. Im
obigen Beispiel sind das vier Beziehungen.
Die Definition $Artikel::pk gibt an, welches Feld der Primary Key ist. $Artikel::timestamp
definiert das Feld mit dem Zeitstempel. Das Feld wird verwendet, um automatisch den Zeitstempel der letzten Änderung festzuhalten. CogniX überprüft damit, ob ein Datensatz von einem
anderen Benutzer in der Zwischenzeit verändert wurde.
$Artikel::sequenz legt den Sequenz Namen für den SERIAL Datentyp fest für die DBSysteme Postgres und Oracle.
Hat die Variable $Artikel::cascadingDelete einen wahren Wert, führt CogniX bei der Löschung eines Datensatzes einen Cascading-Delete durch; alle direkt abhängigen Datensätze werden vor dem eigentlichen Datensatz gelöscht.
Mit dem Hash %Artikel::indexes werden die Indexe auf der Tabelle definiert. Der Index für
den Primary Key wird automatisch erstellt.
4.2
Technische Dokumentation
Die Klasse kann und soll dokumentiert werden. Natürlich ist POD das Mittel der Wahl. Hier ein
kleines Beispiel:
=head1 NAME
Artikel.pm - Artikel Klasse
=head1 DESCRIPTION
Beinhaltet die Daten eines Artikels. Ein Artikel wird
zwingend einer Rubrik zugeordnet. Die Zuodnung zu einem
Mandanten ist redundant geführt. Aus Performance-Gründen und weil
15
über den Mandant praktisch in jeder Query eingeschränkt
werden muss, wurde die Redundanz hier bewusst eingegangen.
Diese Beziehung ergäbe sich auch indirekt über die Rubrik.
=head1 CVS Infos
Version:
Datum :
von
:
Source :
$Revision: 1.12 $
$Date: 2001/02/17 21:23:40 $
$Author: herbie $
$Source: /home/cvs/zeitix/zeitix/Artikel.pm,v $
=cut
Die POD-Dokumentation wird für die Aufbereitung der Dokumentation über dbmodel.pl
ebenfalls als HTML aufbereitet und angezeigt (siehe weiter oben).
4.3
Erstellen der Tabelle in der DB
Mit den Definitionen in der Daten-Klasse kann mit dem Tool crebas direkt ein SQL-Script für
die Erstellung der Tabelle in der Datenbank erstellt werden.
herbie@uranus:~/ws/zeitix/zeitix > crebas Artikel.pm
/* ****************************************************************************
*
CREATE DATABASE SCRIPT /opt/perl5.6.0/bin/crebas
*
* Datum
: Wed Jan 17 11:54:33 2001
* Klassen : Artikel.pm
* ****************************************************************************
*/
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
TABLE DEFINITION FOR TABLE Artikel
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*/
create sequence artikelid_seq START 1;
create table Artikel
(
ArtikelId
INTEGER
NOT NULL
DEFAULT NEXTVAL(’artikelid_seq’),
Zeitstempel
DATETIME
NOT NULL,
RubrikId
INTEGER
NOT NULL,
Haupttitel
VARCHAR(80)
NOT NULL,
Untertitel
VARCHAR(600) NOT NULL,
Body
OID
NOT NULL,
Reihenfolge
INTEGER
,
MandantId
INTEGER
NOT NULL,
PersonId
INTEGER
NOT NULL,
ArtikelStatusId
INTEGER
NOT NULL,
FlagFrontSide
BOOLEAN
NOT NULL
);
/* ---------------------------------------------------------------------------*
INDEXES grants and functions FOR TABLE Artikel
16
* ---------------------------------------------------------------------------*/
Create unique Index ArtikelId_ix ON Artikel(ArtikelId);
Create index fk_Artikel_1 ON Artikel(RubrikId);
Create index fk_Artikel_2 ON Artikel(MandantId);
Create index fk_Artikel_3 ON Artikel(PersonId);
Create index fk_Artikel_4 ON Artikel(ArtikelStatusId);
CREATE FUNCTION Artikel_id_max() RETURNS INT4
AS ’Select max(ArtikelId) FROM Artikel’
LANGUAGE ’sql’;
grant all on Artikel to public;
grant all on artikelid_seq to public;
Das funktioniert problemlos auch für mehrere Klassen gleichzeitig. Das oben aufgeführte
Beispiel ist die Definition für Postgres.
4.4
Sprach-Unabhängigkeit
Ist die Klassen Definition einmal gemacht, kann mit dem Tool prepLanguage eine Struktur
vorbereitet werden, mit der die Attribute und Tabellen-Namen in mehrere Sprachen übersetzt
werden können:
%Artikel::langTable = (
de => ’Artikel’,
en => ’Article’,
);
%Artikel::langAttribute = (
ArtikelId
=> {
de => ’Schlüssel’,
en => ’Key’,
},
ArtikelStatusId
=> {
de => ’Artikel Status’,
en => ’Article status’,
},
Body
=> {
de => ’Textkörper’,
en => ’Body’,
},
Erstelldatum
=> {
de => ’Erstelldatum’,
en => ’Creation date’,
...
..
Die Struktur wird in der Klasse abgelegt. CogniX verwendet jetzt automatisch anstelle der
Attribut-Namen die sprach-abhängigen Texte.
17
5
Bilden von Präsentations Klassen
Analog zu der Datenklasse muß jetzt eine Präsentations Klasse gebildet werden. Per Konvention
erhält eine solche Klasse als Prefix das Kürzel www. Aus der Klasse Artikel.pm wird also die
Klasse wwwArtikel.pm gebildet. Dazu steht ebenfalls ein Tool (heinzelmann) zur Verfügung,
das initial die notwendigen Definitionen aus der Datenklasse generiert.
5.1
Konfiguration
package wwwArtikel;
@wwwArtikel::ISA
= (’CogniX::wwwBase’);
use strict;
use CogniX::htmlStyle;
use CogniX::validate;
#
#
#
#
#
tab[O|V]
= TableView
rec[O|V]
= RecordView
con[O|V]
= Construct (search form)
input[O|V] = Input form
where O means Order and V means View 0=no 1=yes
%wwwArtikel::def = (
# Spalte
0
1
2
3
4
5
6
7
8
# Sort tabO tabV recO recV align conO conV inputO
ArtikelId
=> [ 0,
5,
0,
5,
1, ’l’ , 5,
0,
5,
Zeitstempel
=> [ 0, 10,
0, 10,
1, ’l’, 10,
0, 10,
RubrikId
=> [ 1, 15,
1, 15,
1, ’l’, 15.2, 1, 15.2,
sub { &wwwArtikel::getRubrikenForMandant() } ],
Haupttitel
=> [ 0, 20,
1, 20,
1, ’hl’, 20,
1, 20,
Untertitel
=> [ 0, 25,
0, 25,
1, ’l’, 25,
1, 25,
Body
=> [ 0, 30,
0, 30,
1, ’l’, 30,
0, 30,
Reihenfolge
=> [ 2, 35,
1, 35,
1, ’l’, 50.2, 1, 50.2,
MandantId
=> [ 0, 40,
0, 40,
1, ’l’, 91,
0, 91,
PersonId
=> [ 0, 45,
1, 45,
1, ’l’, 15.2, 1, 15.2,
ArtikelStatusId => [ 0, 50,
0, 50,
1, ’l’, 50.1, 1, 50.1,
FlagFrontSide
=> [ 0, 70,
1, 70,
1, ’l’, 70,
1, 70,
);
$wwwArtikel::table = ’Artikel’;
# scrollSize
# How many records are displayed per page in the table view
$wwwArtikel::scrollSize = 50;
9
inputV
’HIDDEN’,
’HIDDEN’,
’LISTBOX’,
10
11
lookup domain
[],
0, ],
[],
0, ],
[’Rubrik.Rubrik’],
80,
[],
0, ],
’TEXTAREA(4,80)’,[],
0, ],
’TEXTAREA(8,80)’,[],
0, ],
1,
[],
0, ],
’HIDDEN’,
[’Mandant.Name’], 0, ],
’LISTBOX’,
[’Person.Name’], 0, ],
’LISTBOX’,
[’ArtikelStatus.Text’], 0, ],
’RADIOBOX’,
[],
\%main::boolean, ],
# Determining the invisible detail tables
# If you don’t wish to show up the detail records of a depending table add these tables
# to this array
@wwwArtikel::doNotShowDetails = ();
Ähnlich wie die Datenklasse wird für jedes Attribut die Ansicht eingestellt, wie es im Browser angezeigt werden soll. Zum Beispiel wird beim Attribut PersonId definiert, daß eine Listbox
mit den Werten aus der Tabelle Person aufbereitet wird. Als Schlüssel wird die PersonId geführt
und als Anzeigewert das Attribut Person.Name. Dass die PersonId als Schlüssel geführt wird,
18
ergibt sich aus den Definitionen in der Datenklasse Artikel.pm und muss hier nicht mehr extra
definiert werden.
Für jede mögliche Sicht (Tabellensicht, Datensatz-Sicht, Eingabemaske, Suche etc.) auf die
Daten erfolgt also hier lediglich die Konfiguration, wie die Anzeige zu erfolgen hat. Felder können in der Eingabemaske und in der Datensatz-Sicht nebeneinander angeordnet werden. Die
Felder ArtikelStatusId und Reihenfolge im obigen Beispiel werden mit Angabe von Dezimalstellen (50.1 und 50.2) auf der gleichen Zeile angeordnet.
Mit der lookup Spalte 10 werden die Foreign Keys aufgelöst. Es wird die fremde Tabelle
referenziert und das gewünschte Anzeigefeld für die Listbox/Radiobox. Es sind auch mehrere
Felder möglich, die dann konkateniert werden.
Anstelle eines lookups können auch Domain-Values referenziert werden, wie das bei FlagFrontSide der Fall ist. Dort wird eine Referenz auf das Hash %main::boolean abgelegt. In der
zentralen Konfigurationsdatei param.pm ist da folgendes Hash definiert:
# Domains Boolean
%main::boolean = (
1
=> ’Yes’,
0
=> ’No’,
);
Sind Domain Values abhängig von einer Business-rule, kann anstelle von fremden Tabellen
oder festen Domain-Values auch eine Callback-Routine (siehe Attribut RubrikId im Beispiel)
definiert werden. Bei der Aufbereitung der entsprechenden Felder wird dann immer diese Routine gerufen. So ist es ein Leichtes, Listboxen im korrekten Kontext zu erstellen.
5.2
Weiterführende Anpassungen
Mit den im vorgehenden Abschnitt beschriebenen Konfiguration hat man bereits eine vollständig
bedienbare Applikation zur Verfügung. CogniX stellt mit wwwBase wiederum diverse Hooks
oder Insertion-Points zur Verfügung, die in der Präsentationsklasse implementiert werden können. So gibt es diverse setDefaults Methoden, die zum Beispiel bei der Neuerfassung eines
Datensatzes verwendet werden können, um bestimmte Defaults in der Erfassung vorzugeben.
Daneben kann man für jedes Attribut eine Methode definieren, die so heißt wie das Attribut.
Ist eine solche Methode definiert, ruft CogniX diese anstelle der Standard Bildungsroutinen für
Felder. D.h. man kann für ein Feld ein spezifisches Verhalten implementieren.
Selbstverständlich können auch die diversen Basismethoden überschrieben werden oder falls
notwendig um Funktionalität erweitert werden. Die Dokumentation beschreibt die einzelnen
Methoden ausführlich.
6
Dokumentation CogniX
Das Framework ist komplett in POD dokumentiert worden. Zusätzlich gibt es ergänzende Dokumentation in Latex. Die Gesamtdokumentation ist als pdf File der Distribution beigepackt und
19
kann auch von unserem Web Server geladen werden.
Ein Beispiel Projekt kann ebenfalls ab unserem Server geladen werden.
7
Tools
Mit der Distribution werden mehrere nützliche Tools mitgeliefert, die das Arbeiten mit CogniX
erleichtern. Die Tools werden mit dem make install der Distribution in ein /bin Verzeichnis
installiert.
7.1
createTemplate
Mit dem Tool können initial diverse Gerüste für Klassen und komplett neue Projekte erstellt
werden.
7.2
crebas
Erstellt aufgrund der Daten Klassen Definitionen ein ausführbares SQL Script, welches für die
Erzeugung der Tabellen in der Datenbank verwendet werden kann.
7.3
prepLanguage
Erstellt aus der Klassendefinition für eine Datenklasse die notwendigen Strukturen für die Übersetzung der Attribute und Tabellen-Namen in verschiedene Sprachen
7.4
heinzelmann
Erstellt aus der Daten Klasse eine Default-Präsentations www-Klasse. Das Script spart ein schönes Stück Tipparbeit. Ist eine www-Klasse mit dem heinzelmann Script erstellt, muß nur noch
die Konfiguration vorgenommen werden.
7.5
load
Tool zum Laden von Datenbanken. Mit dem Script können z.Bsp. Stammdaten in die Datenbank
geladen werden.
7.6
checkIntegrity
Prüft für eine Tabelle, ob die Datensätze die Bedingungen der referentiellen Integrität erfüllen. Das Tool ist nur für Datenbanken interessant, die keine referentielle Integrität unterstützen
(z.Bsp. Postgres vor Version 7.0.0).
20
8
Showcases
CogniX steht mehrfach im produktiven Einsatz. Unter anderem haben wir für die zweitgrößte
Tageszeitung der Schweiz (http://www.tagesanzeiger.ch) die Umsetzung einer Datenbank gestützten Online Zeitung realisiert. Ein Content Management System also. Benutzerschnittstelle
für die Redaktion sowie Schnittstellen zu Fremdsystemen sind komplett mit CogniX implementiert.
Ferner haben wir eine Sales Applikation für die Verwaltung von großen Adressbeständen,
eine Administrations-Lösung für Privat- und Waldorfschulen, ein Projekt-Management-Tool,
eine Konfigurations- und Kundendatenbank für einen Internet Provider, eine Buchhaltung mit
Debitoren-Teil, ein einfaches Trouble-Ticketing System sowie weitere kleinere Tools erstellt.
Im Moment sind wir an der Einführung eines eigenen CMS Systems in Kombination mit
HTML::Mason. Das CMS System soll als ASP Service betrieben werden können. Details auf
unserer Homepage.
21
Herunterladen