• Keine Ergebnisse gefunden

3.5 Externe Klassendiagramme

4.3.5 Das JGraLab-Dateiformat

In den folgenden Kapiteln wird das neue JGraLab-Dateiformat mit der Dateiendung .TG beschrieben. Als Basis f¨ur die Speicherung des Schemas werden die in den Abschnitten 4.3.4 und 4.3.2 beschriebenen Dateiformate .TED und .G genommen.

Wie bereits angesprochen, muss das neue JGraLab-Dateiformat in einigen Punkten er-weitert werden. TED bietet keine Graphklassen und keine selbst definierbaren Dom¨anen an. Auch die Angabe von Rollennamen und die explizite Definition von Kompositionen und Aggregationen anstelle einfacher relationships ist dort nicht m¨oglich. Aus diesem Grunde wird TED nur ansatzweise f¨ur die Definition des neuen Formats heran gezogen.

Zus¨atzlich soll die Lesbarkeit des Dateiformats verbessert werden. Dazu werden Do-m¨anennamen m¨oglichst ganz ausgeschrieben und Schl¨usselw¨orter bekommen dieselbe Schreibweise wie die entsprechenden Klassen in JGralab.

Dieses Kapitel f¨uhrt zun¨achst ein Beispiel ein, bevor die Definition mittels der EBNF erfolgt.

Beispiel f ¨ur ein .TG-Schema

Es folgt die Beschreibung des Schema-Beispiels des Abschnitts 4.3.1 als .TG-Datei.

Zur Beschreibung ist jede Zeile nummeriert (die Nummern befinden sich nicht im TG-Format selbst).

1 Schema test.generated.TGTest;

2 RecordDomain Parking

( date: String, duration: Integer, cost: Double );

3 EnumDomain Gate ( open, close );

4 GraphClass CityMap;

5 abstract VertexClass Junction;

6 VertexClass Intersection: Junction;

7 VertexClass CarPark: Junction

{ capacity: Integer, open: Boolean, width: Double, name: String, usage: Object, numberPlate: Set

<String>, numberPlateHistory: List<Set<String>>, parking: Parking, gate: Gate };

8 EdgeClass Street from Junction (1,6) to Junction (1,6) { streetName: String };

Jede Zeile wird mittels eines Semikolons abgeschlossen. Dabei ist es egal, wie viele Leerzeichen oder -zeilen sich zwischen den einzelnen W¨ortern befinden.

Eine nat¨urlichsprachliche Erl¨auterung der jeweiligen Zeilen gestaltet sich wie folgt:

1. Das Schema wird TGTest genannt und ist unter dem Pr¨afix test.generated zu fin-den.

2. Es existiert eine RecordDomain mit dem Namen Parking. Ihre in Klammern ste-henden Komponenten besitzen die Namen date, duration und cost, die durch einen Doppelpunkt eingeleiteten Dom¨anen dieser Komponenten sind String, In-teger und Double.

3. Des Weiteren existiert eine EnumDomain mit dem Namen Gate. Ihre m¨oglichen Werte werden in Klammern angegeben und sind in diesem Fall open und close.

4. Die Graphklasse, welche im folgenden beschrieben wird, nennt sich CityMap. Sie besitzt keinerlei Attribute. Alle folgenden Knoten- und Kantenklassen geh¨oren zu CityMap.

5. Die Knotenklasse mit dem Namen Junction ist als abstrakte Klasse markiert.

6. Eine weitere Knotenklasse namens Intersection ist eine Subklasse von Junction.

Dies wird durch den Doppelpunkt hinter dem Klassennamen und die anschließen-de Auflistung anschließen-der entsprechenanschließen-den Superklassen angezeigt.

7. Auch CarPark ist eine Knotenklasse und eine Subklasse von Junction. Sie be-sitzt jedoch eine ganze Reihe von Attributen, welche innerhalb von geschweiften Klammern angezeigt werden. Jedes Attribut wird ¨ahnlich wie die Komponenten der in Zeile 2 definierten RecordDomain abgelegt, und zwar durch seinen Namen und seiner durch einen Doppelpunkt abgetrennten Dom¨ane. Alle Dom¨anen wer-den direkt referenziert, lediglich Record und Enum werwer-den durch ihre in Zeile 2 und 3 definierten Namen referenziert. Die Basisdom¨anen von List und Set werden in spitzen Klammern angegeben.

8. Es existiert eine Kantenklasse mit dem Namen Street. Diese verl¨auft von einer Junction zu einer weiteren Junction. Die Multiplizit¨aten werden in Klammern an-gegeben (in diesem Falle von 1 bis 6). Sie besitzt ein Attribut mit dem Namen StreetName, welches den Typ String besitzt.

4.3. Eingabe/Ausgabe EBNF-Definition des .TG-Schemas

Eine TG-Datei (TGFile) speichert immer genau ein Schema und beliebig viele Gra-phen (GraphStructure), welche alle zu diesem Schema geh¨oren m¨ussen.

TGFile = Schema

{ GraphStructure };

Das Schema der TG-Datei (Schema) beginnt mit dem Schl¨usselwortSchema, gefolgt von seinem vollst¨andigen Namen. Dies bedeutet, dass optional auch ein Package-Pr¨afix (Prefix) f¨ur die generierbaren M1 Klassen vor dem Schemanamen stehen kann. Da innerhalb eines Schemas die Dom¨anen immer eindeutig sind, werden diese zu Beginn definiert. Anschließend werden alle Graphklassen des Schemas nacheinander persis-tent gemacht. Die Definition des Schemas wird durch das Dateiende abgeschlossen, ein Schl¨usselwort wieendin TED ist nicht n¨otig.

Schema = "Schema" SchemaName ";"

{ DomDef }

{ CompleteGraphClass } ; SchemaName = Prefix "." String ;

Prefix = String ;

Die Definition der Dom¨anen (DomDef) geschieht ¨ahnlich wie die Definition im G-Format, welches im Abschnitt 4.3.2 beschrieben wurde. Hier werden die Dom¨anen al-lerdings aus Lesbarkeitsgr¨unden vollst¨andig ausgeschrieben. Bei zusammengesetzten Dom¨anen werden die Komponenten eingeklammert und durch Kommata voneinander getrennt. Jede Zeile wird mittels eines Semikolons beendet.

Da die Dom¨anen Boolean, Integer, Double, String und Object in jedem Schema exis-tieren, m¨ussen diese nicht extra definiert werden. Lediglich Records und Enums werden durch ihren Namen beschrieben und sp¨ater auch referenziert.

DomDef = RecordDom | EnumDom ";" ;

RecordDom = "RecordDomain" DomName RecordDescr ; DomName = String ;

RecordDescr = "(" RecComp { "," RecComp } ")" ; EnumDom = "EnumDomain" DomName EnumDescr ; EnumDescr = "(" EnumComp { "," EnumComp } ")" ; EnumComp = String ;

RecComp = String ":" DomIdx ;

Eine komplette Graphklasse (CompleteGraphClass) wird im TG-Dateiformat in-klusive ihrer Graphelementklassen (GraphElementClass) gespeichert. Zuallererst wird die Graphklasse selbst abgespeichert. Anschließend folgen ihre Knotenklassen, Kantenklassen, Aggregationsklassen und Kompositionsklassen.

Dabei kann jede Klasse durch das optionale Schl¨usselwortabstractals abstrakt aus-gewiesen werden.

CompleteGraphClass = ["abstract"] GraphClass

{ ["abstract"] GraphElementClass } ; GraphElementClass = { VertexClass }

{ EdgeClass }

{ AggregationClass } { CompositionClass } ;

Eine Graphklasse (GraphClass) wird durch das Schl¨usselwort GraphClass ein-geleitet. Sie definiert ¨ahnlich wie die im TED-Format spezifizierten Entit¨aten ihren Namen, ihre eigene Hierarchie sowie ihre Attribute. Auch diese Zeile wird durch ein Semikolon abgeschlossen.

GraphClass = "GraphClass" GraphClassName

[ Hierarchy ] [ Attributes ] ";" ; GraphClassName = String ;

Knotenklassen (VertexClass) werden im TG-Format wie Graphklassen selbst ab-gespeichert. Der einzige Unterschied besteht im verwendeten Schl¨usselwort Vertex-Class. Es existieren hier also Name, Angabe der Superklassen sowie die Attribute der Klasse.

VertexClass = "VertexClass" VertexClassName

[ Hierarchy ] [ Attributes ] ";" ; VertexClassName = String ;

Die Definition der Hierarchie (Hierarchy) geschieht durch eine Angabe aller direkten Superklassen. Sie leitet sich durch einen Doppelpunkt ein und benutzt Kommata zur Aufz¨ahlung.

Hierarchy = ":" String { "," String } ;

4.3. Eingabe/Ausgabe Attribute (Attributes) werden mit einer ¨Anderung zu TED abgespeichert: Es wird hier nur bei den Wertebereichen (AttrDomain) Boolean, Int, Double, String, Object, List und Set direkt die Dom¨ane angegeben, bei Record und Enum wird die Dom¨ane ¨uber den vorher definierten Bezeichner referenziert.

Attributes = "{" Attribute { "," Attribute } "}" ; Attribute = AttrName ":" AttrDomain ;

AttrDomain = DomName | "Boolean" | "Integer" | "Double"

| "String" | "Object"

| ( "List" | "Set" "<" AttrDomain ">" ) ; AttrName = String ;

Die Definition von Kanten- (EdgeClass), Aggregations- (AggregationClass) und Kompositionsklassen (CompositionClass) ist nahezu gleich. Sie lehnen sich alle drei an die Definition derrelationshipsdes TED-Dateiformats an. Als Schl¨us-selwort wird jedoch relationshipabgel¨ost, die eingef¨uhrten Schl¨usselw¨orter sind EdgeClass,AggregationClassundCompositionClass.

Zus¨atzlich ist die optionale Angabe eines Rollennamens (RoleName) erlaubt. Auch hier wird die Zeile mittels der Angabe eines Semikolons beendet.

Bei Aggregationen und Kompositionen wird zus¨atzlich angegeben, von welcher Seite aus die Aggregation bzw. Komposition erfolgt. Diese Angabe wird durchaggregate und der anschließenden Wahl des Bezeichnersfromodertobewerkstelligt.

EdgeClass = "EdgeClass" ECName [ Hierarchy ]

"from" ECName Multiplicity [ RoleName ]

"to" ECName Multiplicity [ RoleName ] [ Attributes ] ";" ;

ECName = String ;

AggregationClass = "AggregationClass" ACName [ Hierarchy ]

"from" ACName Multiplicity [ RoleName ]

"to" ACName Multiplicity [ RoleName ]

"aggregate" "from" | "to"

[ Attributes ] ";" ; ACName = String ;

CompositionClass = "CompositionClass" CCName [ Hierarchy ]

"from" CCName Multiplicity [ RoleName ]

"to" CCName Multiplicity [ RoleName ]

"aggregate" "from" | "to"

[ Attributes ] ";" ; CCName = String ;

Die Angabe der Multiplizit¨at (Multiplicity) erfolgt etwas anders als im TED-Dateiformat, hier werden immer zwei Angaben (minimale + maximale Multiplizit¨at) gefordert. Ein Rollenname darf zudem durch einen beliebigen String repr¨asentiert wer-den.

Multiplicity = "(" Number "," Number | "*" ")" ; RoleName = String ;

Beispiel f ¨ur einen .TG-Graphen

Das .TED-Dateiformat erlaubt nur die Abspeicherung eines Typsystems, nicht jedoch die Persistenzmachung von Graphen. Aus diesem Grunde wird sich am alten .G-Datei-format orientiert und dieses an minimalen Stellen erweitert. Diese Stellen umfassen die in 4.3.3 angesprochenen Punkte der Speicherung mehrerer attributierbarer Graphen innerhalb einer Datei, sowie die Unterst¨utzung von Java-Objects.

Die Speicherung des Graphen aus Abbildung 4.11 wird mittels des folgenden Code aus-gedr¨uckt. Auch hier sind die Zeilen wieder nummeriert, um eine anschließende Erl¨aute-rung zu erm¨oglichen. Diese Zeilennummern sind auch hier nicht Bestandteil des .TG-Dateiformates.

1 Graph d40f83c5606f6487482be3ae385a34d6 CityMap (6 3 2 1) 2 1 CarPark (1)

3 2500, true, 2.75, "L\u00f6hr-Center", rO0ABXNyABFqYXZhLn V0aWwuSGFzaE1hcAUH2sHDFmDRAwACRgAKbG9hZEZhY3RvckkACXRocm VzaG9sZHhwP0AAAAAAAAx3CAAAABAAAAACc3IAEWphdmEubGFuZy5Jbn RlZ2VyEuKgpPeBhzgCAAFJAAV2YWx1ZXhyABBqYXZhLmxhbmcuTnVtYm VyhqyVHQuU4IsCAAB4cAAAAAJzcgARamF2YS5sYW5nLkJvb2xlYW7NIH KA1Zz67gIAAVoABXZhbHVleHABc3EAfgACAAAAAXNxAH4ABQB4,

{"JG-RA-146","SIM-E-1337"}, <{"JG-RA-146","SIM-E-1337"}, {"AB-C-0815"}>, ("08.03.2006", 90, 3.5), open

4 2 Intersection (-1)

4.3. Eingabe/Ausgabe 5 1 Street

6 "L\u00f6hrstra\u00dfe"

1. Der Graph mit der ID d40..4d6 wird durch das Schl¨usselwort Graph eingeleitet.

Seine Graphklasse hat den Namen CityMap. In Klammern erfolgt nun nacheinan-der die Angabe des aktuellen Speicherplatzes f¨ur die Aufnahme von Knoten und Kanten sowie die Anzahl der aktuellen Knoten und Kanten im Graphen.

2. Der erste Knoten mit der Nummer 1 ist von der Klasse CarPark. In Klammern werden hier die Inzidenz-IDs10angegeben, mit denen der Knoten verbunden ist.

3. Es folgen die Attribute des Knotens 1. Nacheinander werden hier durch Kom-mata getrennt alle Inhalte der Attribute abgelegt. Die Reihenfolge entspricht der im Schema definierten Reihenfolge. Auff¨allig ist hier die Speicherung des Ob-jects: Es wird nicht nur serialisiert, sondern das Bytefeld anschließend als Base64-codierte Zeichenfolge abgespeichert. Ein String wird zudem im UTF-Format ge-sichert. Ein Record wird durch runde Klammern eingeleitet, eine List durch spitze Klammern und ein Set durch geschweifte Klammern.

4. Es existiert ein weiterer Knoten, diesmal mit der ID 2, welcher der Intersection-Klasse angeh¨ort. Als Inzidenz-ID ist die -1 angegeben.

5. Nach den beiden Knoten folgt nun die Kante. Sie besitzt die ID 1 und geh¨ort der Street-Klasse an. Eine Angabe von Alpha und Omega Knoten ist hier nicht mehr notwendig, da diese aus den an den Knoten angegebenen Inzidenz-IDs abgeleitet werden k¨onnen.

6. Das einzige Attribut der Street wird in dieser Zeile mit seinem Wert gef¨ullt. Die Schreibweise der Unicode-Zeichenfolge entspricht der m¨oglichen Schreibweise in Java.

EBNF-Definition der .TG-Graphen

Die Beschreibung eines Graphen (GraphStructure) wird durch das Schl¨usselwort Graph, seiner ID und die Angabe seiner Graphklasse eingeleitet. Anschließend befin-den sich in Klammern die Anzahl an Speicherpl¨atzen f¨ur Kanten und Knoten, mit der der Graph initialisiert wird. Als weitere Werte befinden sich innerhalb dieser Klammern die Anzahl der tats¨achlichen Knoten und Kanten des Graphen.

10Genauer: Es wird die ID der zugeh¨origen Kante angegeben. Das Vorzeichen dieser ID entscheidet, ob die Kante einlaufend oder auslaufend ist.

Die Attributwerte (Value) des Graphen werden nach diesen Klammern angegeben, dies war in .G bisher nicht m¨oglich.

Nach einer Leerzeile werden zun¨achst alle Knoten (VertexDesc) und dann alle Kan-ten (EdgeDesc) des Graphen beschrieben.

GraphStructure = "Graph" GraphId GCName

"(" NMax MMax NCnt MCnt ")"

{ Value }

{ VertexDesc } { EdgeDesc } ;

GraphId = String ;

GCName = String ;

NMax = Number ;

MMax = Number ;

NCnt = Number ;

MCnt = Number ;

Jeder Knoten wird durch seine (selbstdefinierte oder automatisch generierte) ID identi-fiziert. Die Angabe der Knotenklasse, von der er instanziiert wurde, wird nicht wie in .G mittels einer Zahl angegeben, sondern direkt mittels des Namens der entsprechenden Klasse. Als weitere Angabe gibt der Knoten seine Attributwerte an.

Die Liste der Inzidenzen eines Knotens (Iseq) wird auch hier bereits nach dem Namen angegeben.

VertexDesc = VIdx VCName IncidentEdges { Value } ;

VIdx = Number ; VCName = String ;

Die inzidenten Kanten eines Knotens (IncidentEdges) werden in Klammern notiert und durch Kommata getrennt. Dabei wird die ID der Kante angegeben. Zus¨atzlich ent-scheidet das Vorzeichen der ID, welche Richtung die zugeh¨origen Inzidenzen besitzen.

IncidentEdges = "(" [ DirectedEdge

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

4.3. Eingabe/Ausgabe Jede Kante, egal ob sie von einer Kanten-, Aggregations- oder Kompositionsklasse instanziiert wurde, wird mittels der Angabe ihrer ID und der Angabe ihres zugeh¨ori-gen Klassennamens (ClassName) abgespeichert. Zus¨atzlich werden die Attributwerte (Value) angegeben.

EdgeDesc = EIdx ClassName { Value } ; EIdx = Number ;

ClassName = ECName | ACName | CCName ; ECName = String ;

ACName = String ; CCName = String ;

Die Attributwerte werden nicht wie in .G mittels einer Zahl eingeleitet, welche die An-zahl ihrer Attribute angibt, denn diese AnAn-zahl ist bereits durch die Klasse des Graphele-ments festgelegt.

Ein Attributwert muss bei der Speicherung der Graphen auch nicht durch seinen Na-men eingeleitet werden, denn per Definition ist die Reihenfolge des Speicherns und des Ladens fest. Sie erfolgt genau so, wie die Attribute innerhalb des Schemas definiert wurden.

Die Speicherung der Werte selbst erfolgt ¨ahnlich wie in .G. Das Tupel entf¨allt hierbei.

Neu hinzugekommen ist einerseits die Persistenzmachung eines Java Objektes, welches durch Serialisierung gespeichert wird. Da bei der Serialisierung in Bin¨ardaten auch Zei-lenumbr¨uche auftreten k¨onnen (und diese evtl. durch Kopieren der TG-Dateien unter verschiedenen Betriebssystemen ver¨andert werden k¨onnten), wird das Java Objekt nicht als Byte-Array gespeichert, sondern als Base64-codierte Zeichenfolge.

Andererseits wird die Speicherung eines Set zus¨atzlich eingef¨uhrt. Dabei unterscheidet sich das Set von der Liste durch die Verwendung anderer Klammern ([]statt<>). Die Persistenzmachung eines Enumeration-Wertes geschieht nicht mehr durch Angabe einer Zahl, sondern durch Repr¨asentation des Wertes der Zeichenkette selbst.

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

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

Object = ? serialisiertes Java Objekt, Base64 codiert ?;

Value = (* boolean *) "false" | "true"

| (* integer *) Integer

| (* double *) Double

| (* string *) String

| (* list *) Number "<" [Value { "," Value }] ">"

| (* set *) Number "{" [Value { "," Value }] "}"

| (* record *) "(" [Value { "," Value }] ")"

| (* enumeration *) String

| (* object *) Object ;