© DrHitch/Shutterstock.com
DSL mit Xtext/Xtend

3 Initialerstellung einer Erfassungsmaske - und vieles mehr


In Kapitel 1 und 2 haben wir eine bestehende Schnittstelle zum Austausch von CASE-Informationen in unserer 4GL benutzt, um in unserem 4GL Repository den zum Datenmodell gehörenden Bereich anzulegen und zu verändern. Den weitaus größeren und sehr viel aktiveren Teil bei der Entwicklung mit unserer 4GL stellen Eingabemasken und Hintergrundverarbeitungen dar, die die eigentliche Programmierung enthalten. Für diese steht unter anderem ein grafischer „Screenpainter“ zur Verfügung, in dem alle beteiligten Datensätze und -felder einzeln anzugeben sind. Die 4GL-Umgebung bietet neben der CASE-Austauschdatei auch eine XML-basierte Möglichkeit zum Export und Import von Daten des Repositorys an. Wir werden jetzt die in Kapitel 1 und 2 gewonnenen Erfahrungen erweitern und statt der CIF-Datei eine Exportdatei mit den wichtigsten Bestandteilen für die Rohfassung einer Erfassungsmaske erstellen.

Nachdem wir die standardisierte Rohfassung erarbeitet haben, wird dieses Konzept erweitert, um Ausschnitte aus bestehenden Masken miteinander zu verbinden und so mit geringstem Aufwand standardisierte Layouts umzusetzen. Ferner wird das Prinzip einer „dummen“ Ladedatei vorgestellt, mit der wir gezielt einzelne Datenfelder des Repositorys für Eingabemasken verändern können.

In Kapitel 1 und 2 haben wir das Datenmodell im 4GL Repository bearbeitet. Dieses Datenmodell enthält in meiner 4GL neben Default-Vorgaben für Texte auch solche für Programmcode. Nach einer hektischen Anfangsphase wird in der Regel schnell ein recht stabiler Zustand des Datenmodells erreicht.

Der Hauptteil der Entwicklungsarbeit in meiner 4GL besteht in der Erzeugung und Änderung von Masken, die dort als Komponenten bezeichnet werden. Ähnlich wie bei der Erzeugung des Datenmodells ist auch hier der anfängliche Arbeitsaufwand bei der Erstellung einer solchen Komponente recht hoch, da die wenigen wirklich notwendigen Eingaben in einer großen Zahl von Fenstern versteckt sind und der grafische Maskeneditor jeweils nur ein einzelnes Objekt zur Neuanlage zulässt.

Wie wir schon beim Datenmodell gesehen haben, lässt sich dieser initiale Großaufwand durch eine geeignete DSL erheblich reduzieren, wenn wir in einer einfachen Textdatei lediglich die uns bekannten Informationen angeben müssen. Auch jetzt dient diese zusammen mit der Fachabteilung erstellte DSL-Datei wieder zugleich als Diskussionsgrundlage, Dokumentation des Besprochenen und Basis der Generierung.

Zielvorgabe 1: Rohfassung Datenfelder und ihre Position in einer Erfassungsmaske

Bei Erfassungsmasken sind die dargestellten Felder samt ihrer Positionierung in meiner 4GL unter Verwendung eines grafischen Formpainters zu definieren. Diese Position kann später noch durch Drag and Drop im Rahmen gewisser Regeln verändert werden.

Da der Aufwand für das Neupositionieren der darzustellenden Felder gemessen am erstmaligen Spezifizieren recht gering ist, werden wir bei der Generierung zuerst einmal ein allgemeines Darstellungsprinzip wählen: Nach einer Zeile für die Entity wird jedes Feld samt Feldführungstext in einer eigenen Zeile positioniert.

Also mal ganz einfach anfangen

Die DSL für unser Beispiel ist ganz schlicht:

form simpleform { entity T1.Model2 fields=Field1,Field2 }

Das Resultat des Formpainters wird als verschlüsselter Text abgespeichert, wobei eine dieser Textzeilen einer Zeile in der Eingabemaske entspricht. Dieses Teilstück einer Exportdatei und seine Entsprechung im Formpainter:

<DAT name="FORMPIC" xml:space='preserve'>&uFRM;TYP=E&uSEP;NAM=T1.MODEL2&uSEP;WID=50&uSEP;HEI=3&uFRM;
&uFRM;TYP=L&uSEP;NAM=FIELD1.T1&uSEP;WID=20&uSEP;HEI=1&uFRM; &uFRM;TYP=F&uSEP;NAM=FIELD1&uSEP;WID=20&uSEP;HEI=1&uFRM;
&uFRM;TYP=L&uSEP;NAM=FIELD2.T1&uSEP;WID=20&uSEP;HEI=1&uFRM; &uFRM;TYP=F&uSEP;NAM=FIELD2&uSEP;WID=20&uSEP;HEI=1&uFRM;
</DAT>

Wenn wir also eine Exportdatei (Details siehe Kasten: „Die Import/Exportschnittstelle und das 4GL Repository“) generieren wollen, ist die knifflige Aufgabe die Nachbildung dieses Formpainters (Abb. 3.1).

merkel_3_1.png

Abbildung 3.1: Formpainter einer einfachsten Maske

In unserem Generator wird die gesamte Arbeit von folgender Routine geleistet:

def makeUformFormpic(Form form) {
'''«FOR Entity entity : form.entities»
&uFRM;TYP=E&uSEP;NAM=«entity.name.toUpperCase».«entity.model.toUpperCase»&uSEP;WID=50&uSEP;HEI=«1+entity.fields.length»&uFRM;
«FOR Field field : entity.fields»
&uFRM;TYP=L&uSEP;NAM=«field.name.toUpperCase».«entity.name.toUpperCase»&uSEP;WID=20&uSEP;HEI=1&uFRM;&uFRM;TYP=F&uSEP;NAM=«field.name.toUpperCase»&uSEP;WID=20&uSEP;HEI=1&uFRM;
«ENDFOR»
«ENDFOR»'''}

Die Entity, der wir eine eigene Zeile spendiert haben, muss in ihrer Höhenangabe die zugehörigen Zeilen ihrer Felder umfassen. Deshalb wird bei ihrer Angabe auch die Anzahl der Felder benötigt:

HEI=«1+entity.fields.length»

Die Import/Exportschnittstelle und das 4GL Repository

Zum allgemeinen Austausch von Repository-Informationen bietet die 4GL-Umgebung ein XML-basiertes Austauschformat an, das unser Vorbild für die Generierung der Ausgabedatei wird, ähnlich wie die CIF-Datei für unser Datenmodell genutzt wurde. Beispielsweise werden die in der Maske eingegebenen Daten in der Datenbank gespeichert und beim Export in folgende XML-Datei umgewandelt:


<?xml version='1.0' encoding='UTF-8' ?>
-snip-
<TABLE>
<DSC name="EXPORTENT1" model="EXPORTDEMO" system="S" pseudo ="90" level="1" noupdate="0" rbk="0" ffsql="0" transnr="0" segsize="0" ufocc="0">
<FLD name="PRIMEKEY" seqno="1" type="S" level="2" pack="0" scale="0" length="2" pointer="0" inum="1" ufocc="0" mandatory="yes" idxnum="1" idxsnr="101" />
<FLD name="ADATE" seqno="2" type="D" level="2" pack="0" scale="0" length="8" pointer="0" inum="0" ufocc="0" />
<FLD name="ALONGTEXT" seqno="3" type="S" level="2" pack="128" scale="0" length="0" pointer="0" inum="0" ufocc="0" varinfo=",0,0,0,,0,0,0,,0,0,0,," />
</DSC>
<OCC>
<DAT name="PRIMEKEY">A</DAT>
<DAT name="ADATE">2014-02-12<...

Neugierig geworden? Wir haben diese Angebote für dich:

Angebote für Gewinner-Teams

Wir bieten Lizenz-Lösungen für Teams jeder Größe: Finden Sie heraus, welche Lösung am besten zu Ihnen passt.

Das Library-Modell:
IP-Zugang

Das Company-Modell:
Domain-Zugang