• Keine Ergebnisse gefunden

3.5 Externe Klassendiagramme

4.3.2 Das GraLab-Dateiformat .G

Es folgt eine Beschreibung des .G-Dateiformats f¨ur die Persistenz von Typsystem und Graphen. Diese Beschreibung erfolgt zun¨achst anhand eines Beispiels. Um das Datei-format auch formal zu definieren, wird die Beschreibung durch die Definition einer

Junction {abstract}

Intersection

-streetName : String Street

StreetEnd

1..6 StreetStart

-capacity : Integer -open : Boolean -width : Double -name : String -usage : Object

-numberPlate : Set<String>

-numberPlateHistory : List<Set<String>>

-parking : Record -gate : Enum

CarPark JGTest.CityMap

1..6

Abbildung 4.10: Beispiel f¨ur ein Schema EBNF8erg¨anzt. Die Beschreibung basiert auf [DaWi03].

Beispiel f ¨ur ein Typsystem in .G

Im folgenden wird das Beispiel-Schema (Abb. 4.10) mittels des Dateiformats .G ausge-dr¨uckt.

8 DOMAINS:

0 I 12 B 24 D 36 S 48 L(S) 60 L(L(S)) 72 R(S,I,D)

8EBNF: Extended Backus Naur Form, eine Sprache zur Beschreibung von Textformaten mittels re-gul¨arer Ausdr¨ucke

4.3. Eingabe/Ausgabe

:CityMap

maxV = 6 maxE = 3 vCount = 2 eCount = 1

:Intersection :CarPark

ID = 1

streetName = Löhr-Straße :Street

ID = 1 capacity = 2500 open = true width = 2.75 name = Löhr-Center

usage = java.lang.Map(1->false, 2->true) numberPlate = {JG-RA-746, SIM-E-1337}

numberPlateHistory = <{JG-RA-746, SIM-E-1337}, AB-C-0815>

parking = (08.03.2006, 90, 3.5) gate = open

ID = 2

Abbildung 4.11: Beispiel f¨ur einen Graphen

84 E(4 open,5 close) 9 ATTRIBUTEDEFINITIONS:

0 8 capacity 0 12 4 open 12 24 5 width 24 36 4 name 36

48 11 numberPlate 48

60 18 numberPlateHistory 60 72 7 parking 72

84 4 gate 84

96 10 streetName 36 5 TYPES:

0 8 TypeNull . 12 6 Street (96).

24 8 Junction .

36 12 Intersection .

48 7 CarPark (0,12,24,36,48,60,72,84).

0 isa 0.

12 isa 0.

24 isa 0.

36 isa 0,24.

48 isa 0,24.

0 isExported 1 12 isExported 1 24 isExported 1 36 isExported 1 48 isExported 1

Zu Beginn werden die Dom¨anen definiert (DOMAINS), in diesem Beispiel sind es acht, wie die vorangehende Zahl anzeigt. Diese werden lediglich durch einen Buchstaben abgek¨urzt (z.b.Sf¨ur String,Df¨ur Double, etc.). Nicht modelliert werden kann hier die Dom¨ane Object, da diese Dom¨ane im alten GraLab nicht existiert. Das Set wird hier durch eine Liste (L) dargestellt, da es auch keine eigenst¨andige Set-Dom¨ane gibt. Die Ziffern vor den Dom¨anen werden benutzt, um sp¨ater auf sie referenzieren zu k¨onnen.

Bei der Enum-Dom¨ane (die letzte im Dom¨anen-Block) sieht man, wie Strings in .G abgelegt werden: Die Anzahl der Zeichen des Strings wird vor den eigentlichen String gestellt.

4.3. Eingabe/Ausgabe Im n¨achsten Block (ATTRIBUTEDEFINITIONS) werden alle (neun) Attribute defi-niert, zun¨achst unabh¨angig von ihren Typen. Sie bekommen einen Namen, sowie eine Dom¨ane ¨uber die im AbschnittDOMAINS definierte ID zugewiesen. Auch auf die At-tribute selbst kann sp¨ater wiederum durch die vor der Zeile stehende ID referenziert werden.

Der Block TYPES definiert in drei Schritten die Typen. Erstens bekommen sie einen Namen und in Klammern ihre Attribute, zweitens bekommen sie mittels des Schl¨ussel-wortesisaihre Obertypen zugewiesen und drittens wird notiert, ob der Typ exportiert wurde (isExported). Auff¨allig ist hier, das es automatisch einen TypeNull gibt, von dem alle anderen Typen erben.

Das Dateiformat besitzt einige Nachteile und kann nicht alle Funktionen von JGraLab ausdr¨ucken. Diese werden sp¨ater in Abschnitt 4.3.3 detailliert aufgelistet.

Ubergreifend g ¨¨ ultige EBNF-Definitionen

In den folgenden Zeilen werden mittels EBNF einige Ausdr¨ucke definiert, welche all-gemein innerhalb dieses Dokuments gelten sollen. Sie gelten also sowohl f¨ur das .G- als auch f¨ur das .TED-Dateiformat.

Ein einzelnes Leerzeichen:

SP = " " ;

Ein einzelner Zeilenumbruch:

NL = "\n" ;

Damit besteht der Zeilenumbruch aus lediglich einem einzigen Byte, dem NewLine-Zeichen (1010 = A16), also kein CarriageReturn gefolgt von NewLine (13101010 = D16A16) wie unter DOS und kein NewLine gefolgt von CarriageReturn (10101310 = A16D16) wie unter MacOS.

Ein String wird in GraLab anders definiert als in Programmiersprachen. Er beginnt mit einer Zahl, die die Anzahl seiner Zeichen angibt. Dies hat den Vorteil, innerhalb einer Zeichenkette jegliche Art von Zeichen benutzen zu d¨urfen, die der Rechner darstellen kann (bis auf EOF und NewLine). Auch Leerzeichen und Anf¨uhrungszeichen innerhalb der Zeichenkette sind damit kein Problem.

Number = ? alle nat¨urlichen Zahlen inklusive der 0 ? ;

StringInhalt = { ? alle im Rechner darstellbaren Zeichen ? } ;

String = Number StringInhalt ;

Nacheinander werden innerhalb einer .G-Datei das Typsystem sowie die Graphen selbst gespeichert.

GraphFile = TypeSysFile

GraphStructure ;

EBNF-Definition des .G-Typsystems

Ein Typsystem besteht aus den benutzten Wertebereichen, den Attributen sowie den Typen inklusive ihrer Vererbungshierarchie.

TypeSysFile = UsedDomains NL AttrDefs NL TypeDefs NL ;

Die Definition der Wertebereiche (UsedDomains) wird durch eine Zahl angef¨uhrt.

Diese gibt die Anzahl der Dom¨anen an. In jeder Zeile wird ein Wertebereich beschrie-ben, dabei bekommt er eine Nummer, ¨uber die sp¨ater die Adressierung funktioniert.

Der Buchstabe, welcher einen Wertebereich einleitet, definiert seinen Typ. Bei zusam-mengesetzten Wertebereichen (Liste, Tupel, Verbund) kommen weitere Informationen

¨uber die Basisdom¨ane oder die Komponentendom¨anen hinzu.

UsedDomains = Number SP "DOMAINS:" NL { DomDef } ;

DomDef = DomIdx SP DomDescr NL ; DomIdx = Number ;

DomDescr = (* boolean *)

"B"

(* integer *)

| "I"

4.3. Eingabe/Ausgabe (* string *)

| "S"

(* double *)

| "D"

(* list *)

| "L(" DomIdx ")"

(* tuple *)

| "T(" DomIdx { "," DomIdx } ")"

(* record *)

| "R(" RecComp { "," RecComp } ")"

(* enumeration *)

| "E(" String { "," String } ")" ; RecComp = String ":" DomIdx ;

Attribute (AttrDefs) werden ¨ahnlich behandelt wie Dom¨anen: Eine f¨uhrende Zahl beschreibt die Anzahl der Attribute, gefolgt von einem Schl¨usselwort sowie den Attri-buten selbst. Attribute besitzen eine ID, ¨uber die sie sp¨ater adressiert werden k¨onnen.

Des Weiteren besteht ein Attribut (AttrDef) aus einem Namen sowie einer Dom¨ane.

AttrDefs = Number SP "ATTRIBUTEDEFINITIONS:" NL { AttrDef } ;

AttrDef = AttrIdx SP String SP DomIdx NL ; AttrIdx = Number ;

Die Definition der Typen selbst (TypeDefs) beginnt gleich wie die Attribute und die Dom¨anen: mit der Anzahl der Typen und einem Schl¨usselwort. Die Beschreibungen der Typen, sowie die Vererbungshierarchie der Attribute folgt anschließend. Zum Schluss werden Information ¨uber den stattgefundenen Export der Typen angegeben.

TypeDefs = Number SP "TYPES:" NL { TypeDesc }

{ TypeIsA }

{ TypeExport } ;

Jeder Typ (TypeDesc) bekommt eine ID, um sp¨ater adressiert werden zu k¨onnen. Der Typ wird nun inklusive seiner Attribute definiert. Vererbte Attribute tauchen zus¨atzlich innerhalb der Untertypen auf, die Vererbung ist dabei also bereits abgeschlossen.

TypeDesc = TypeIdx SP String SP

[ "(" AttrIdx { "," AttrIdx } ")" ]

"." NL ; TypeIdx = Number ;

Um die Subtyp-Relation (TypeIsA) zu beschreiben, wird die Typnummer, ein Schl¨ussel-wort und eine Liste von Obertypen angegeben. Jeder Typ enth¨alt sich selbst als Obertyp, da die Relation per Definition reflexiv ist.

TypeIsA = TypeIdx SP "isa" SP TypeIdx { "," TypeIdx }

"." NL ;

Der Export der Typen (TypeExport) folgt zum Schluss. Dies gibt an, ob der Typ nach dem Laden des Typsystem noch ver¨andert werden darf.

TypeExport = TypeIdx SP "isExported" SP ( "0" | "1" ) NL ;

Beispiel f ¨ur einen Graphen in .G

In den n¨achsten Zeilen wird der Graph aus Abbildung 4.11 mittels des .G-Dateiformats beschrieben.

GRAPH:(6 3 2 1) 1 48 (1)

7

0: 2500 12: true 24: 2.75

36: 11 Loehr-Center

48: 2 <9 JG-RA-746,10 SIM-E-1337>

60: 2 <<9 JG-RA-746,10 SIM-E-1337>,9 AB-C-0815>

72: (10 08.03.2006,90,3.5) 84: 4 open

2 36 (-1) 0

4.3. Eingabe/Ausgabe

1 12 1

96: 11 Loehr-Strasse

Die Beschreibung des Graphen beginnt mit dem Schl¨usselwort GRAPH. In Klammern finden sich die maximale Anzahl von Knoten und Kanten sowie die aktuelle Anzahl wieder.

Nacheinander werden die Listen Vseq und Eseq im .G-Format abgelegt. Nach jeder ID eines Knotens bzw. einer Kante folgt die ID seines Typs (beim ersten 48, beim zweiten Knoten36, bei der Kante12), beim Knoten zus¨atzlich in Klammern die ID der Inzidenzen (beim ersten Knoten einmal 1 und beim zweiten Knoten einmal -1). Das Vorzeichen gibt die Richtung der Inzidenz an, eine positive Zahl steht f¨ur die Richtung out, eine negative Zahl f¨ur die Richtung in.

Anschließend gibt die Zahl unter der ID des Knotens bzw. der Kante an, wie viele Attribute das Graphelement besitzt. Jedes Attribut wird mit seiner ID eingeleitet, von einem Doppelpunkt gefolgt, bis schließlich der Wert des Attributs selbst festgeschrieben wird, je nach Dom¨ane jeweils nach einer anderen Konvention (z.B. wird bei Listen die Anzahl der Elemente vorangestellt).

Auch hier erkennt man, dass die ¨uberm¨aßige Verwendung von IDs dazu f¨uhrt, dass das Dateiformat nicht mehr auf den ersten Blick ersichtlich wird. Die Angabe der Attribute eines Graphelements ist zus¨atzlich nicht n¨otig, da sie bereits im Typsystem festgesetzt wurde. Attributierte und typisierte Graphen k¨onnen im .G-Format nicht abgelegt wer-den.

EBNF-Definition der .G-Graphen

Es folgt an dieser Stelle die Definition der Graphen selbst in EBNF. Da es keine Graphen ohne ein passendes Typsystem geben kann, wird dies, wie in Abschnitt 4.3.2 beschrie-ben, mit in derselben Datei abgespeichert.

Nach dem einleitenden Schl¨usselwort folgen die Gr¨oßen der internen Tabellen f¨ur Kno-ten und KanKno-ten, sowie die echte Anzahl der KnoKno-ten und KanKno-ten im Graphen (Graph-Structure). Als erstes werden die Knoten in ihrer Vseq-Reihenfolge beschrieben, gefolgt von den Kanten in ihrer Eseq-Reihenfolge.

GraphStructure = "GRAPH:(" NMax SP MMax SP NCnt SP

MCnt ")" NL NL { VertexDesc } NL { EdgeDesc } NL ;

NMax = Number ;

MMax = Number ;

NCnt = Number ;

MCnt = Number ;

Uber eine f¨uhrende ID wird ein Knoten (VertexDesc) identifiziert. Es werden sein¨ Typ, die Liste der inzidenten Kanten und seine Attribute angegeben.

VertexDesc = VIdx SP TypeIdx SP IncidentEdges NL AttrValues NL ;

VIdx = Number ;

Die Inzidenzliste (IncidenceEdges) beschreibt alle Kanten, die mit dem Knoten verbunden sind. Auch die Richtung der Kanten wird abgespeichert, angegeben durch das Vorzeichen (eingehende Kanten besitzen das Vorzeichen

”-“, ausgehende Kanten besitzen kein Vorzeichen). Hier spiegelt die Reihenfolge der Definitionen die Inzidenz-liste Iseq wieder. Laut folgender Definition sollen isolierte Knoten damit die leere Inzi-denzliste

”()“ bekommen, jedoch sind auch Graphdateien mit

”(0)“ zu finden, da dies-bez¨uglich in einer alten GraLab-Version ein Bug existierte.

IncidentEdges = "(" [ DirectedEdge

{ "," DirectedEdge } ] ")" ; DirectedEdge = EIdx | "-" EIdx ;

Auch jede Kante (EdgeDesc) besitzt eine ID f¨ur die Adressierung. Sie wird genau wie ein Knoten durch ihren Typ und ihre Attribute beschrieben. Die Anfangs- und Endkno-ten Alpha bzw. Omega werden hier nicht aufgef¨uhrt, da sie bereits durch die Inzidenz-liste der Knoten festgelegt wurden.

EdgeDesc = EIdx SP TypeIdx NL AttrValues NL ; EIdx = Number ;

Zu jedem Element des Graphen werden die Anzahl der Attributwerte sowie die Attri-butwerte selbst (AttrValues) abgespeichert. Durch die ID des Attributs kann der Attributwert (AttrValue) adressiert werden.

4.3. Eingabe/Ausgabe AttrValues = Number NL

{ AttrValue } ;

AttrValue = AttrIdx ":" SP Value NL ;

Die Werte selbst werden mittels eigener Regeln abgespeichert. Boolean, Integer und Double werden wie in vielen bekannten Programmiersprachen (z.B. C++, Java, C#) ge-speichert, String genau so, wie es in 4.3.2 beschrieben wurde. Bei List wird die Anzahl der Elemente und anschließend jedes Element einzeln abgespeichert. Bei Tuple und Re-cord steht die Anzahl der Elemente allerdings von vorne herein fest, daher ben¨otigen diese keine explizite Angabe dieser Anzahl.

Integer = ? alle vorzeichenbehafteten nat¨urlichen Zahlen von 4 Byte L¨ange ? ;

Double = ? alle vorzeichenbehafteten Gleitkommazahlen von 8 Byte L¨ange ? ;

Value = (* boolean *)

"false" | "true"

(* integer / enumeration *)

| Integer (* double *)

| Double (* string *)

| String (* list *)

| Number SP "<" [ Value { "," Value } ] ">"

(* tuple / record *)

| "(" [ Value { "," Value } ] ")" ;