• Keine Ergebnisse gefunden

3.5 Externe Klassendiagramme

3.5.5 Beispielzugriffe auf die Werte

In diesem Abschnitt wird beispielhaft aufgezeigt, wie Zugriffe auf die Attribute von M1-Elementen in JGraLab durchgef¨uhrt werden k¨onnen.

Zun¨achst wird der generierte Java-Code der Ebene M1 gezeigt. Dieser Code wird durch

3.5. Externe Klassendiagramme die commit-Methode der Schema-Klasse automatisch erstellt, damit der Anwender di-rekt Getter und Setter benutzen kann, um Attributwerte lesen und schreiben zu k¨onnen.

Dieser Code ist jedoch so noch nicht vollst¨andig lauff¨ahig: In Kapitel 4.2.2 wird die objektorientierte Zugriffsschicht genauer beschrieben, welche f¨ur die Funktionalit¨at im JGraLab notwendig ist. Es sind hier nur die wichtigsten Ausschnitte zu sehen, welche die Deklaration der Attribute veranschaulichen.

F¨ur die automatische Generierung der M1 Klassen gelten die folgenden Regeln: Jedes Attribut wird in seiner M1-Klasse als private deklariert, so dass es vor Zugriffen von außen abgekapselt ist. Um die Werte ¨andern und auslesen zu k¨onnen, existiert je-weils eineset-Methode, welche den Wert des Attributs speichern kann und eine get-Methode, welche diesen Wert wieder auslesen kann.

Um die Attributzugriffe beispielhaft aufzuzeigen, wird f¨ur jeden Datentyp ein kurzes Beispiel eingef¨uhrt. Der Anwender generiert zun¨achst ein Element der M2-Ebene, in-dem er Methoden der M3-Ebene (vgl. Abb. 3.14 und 3.15) aufruft. Es wird der durch die commit-Methode in der Schema-Klasse generierte Code f¨ur dieses M2-Element gezeigt, gefolgt von Code des Anwenders, welcher aus diesen M1-Java-Klassen eine M1-Instanz generiert (vgl. Abb. 3.16), anschließend die Attribute ausliest und eine typische Opera-tion darauf ausf¨uhrt.

Anhand des folgenden Flussdiagramms (Abb. 3.18) wird nochmals der Vorgang der Generierung der Attributklassen beschrieben.

Beschreibung des Beispiels

Folgendes Beispiel soll bei den atomaren Attributen verwendet werden:

Das Schema AttributeTest soll die bekannte Graphklasse namens CityMap beinhalten.

Innerhalb dieser Graphklasse existiert als weiteres M2-Element ein CarPark als Kno-tenklasse mit folgenden Attributen:

• Int: Ein Attribut namens capacity soll die Anzahl der Parkpl¨atze innerhalb des CarParks angeben.

• Boolean: Das Attribut open gibt an, ob der CarPark gerade ge¨offnet ist.

• Double: Width gibt an, welche Breite in Metern ein einzelner Parkplatz besitzt.

• String: Das Attribut name gibt den Namen des CarParks an.

Anwender JGraLab

Erstellung der M1-Ebene ( ...createVertex(…),

...setAttribute1(…), ...getAttribute2(…) ) Festschreibung des Schemas

( schema.commit(...) ) Erstellung des Schemas (M2-Elemente)

( ...createVertexClass(…), ...addAttribute(…), etc. )

Generierung der Javaklassen zur Attributierung ( pro M2-Element 1 Klasse, für jedes Attribut

1 Getter und 1 Setter )

Ausgabe

Abbildung 3.18: Flussdiagramm zur Erstellung der Attribute

3.5. Externe Klassendiagramme

• Object: Dieses Attribut mit dem Namen usage beinhaltet eine Java-Map5 der Form ParkingNumber:IntegerUsed:Boolean f¨ur die aktuelle Belegung des Parkplatzes.

• Set: Ein Attribut namens numberPlate beinhaltet alle Kennzeichen der Autos, die sich gerade im Parkhaus befinden. Da die Kennzeichen, welche hier den Datentyp String besitzen, eindeutig sind, kann hier als Datentyp ein Set gen¨ugen (es sind keine Duplikate erlaubt und eine Ordnung ist nicht notwendig).

• List: Um die Kaskadierung von Attributen zu zeigen, speichert diese Liste Ele-mente vom Typ Set. In unserem Beispiel werden so f¨ur jeden einzelnen Tag alle Kennzeichen gespeichert, welche sich im Parkhaus aufgehalten haben. Das Attri-but wird numberPlateHistory genannt.

• Record: Ein Parkvorgang im Kassenautomat speichert das Datum, die Dauer und den bezahlten Betrag. Entsprechend nennen wir den Vorgang parking, das Datum date (ein String), die Dauer in Minuten duration (ein Integer) und den Betrag cost (ein Double).

• Enum: Der Zustand der Schranke gate am Parkhaus darf nuropenoderclose betragen.

Die Abbildung 3.19 zeigt dieses Beispiel nochmals als Diagramm auf Ebene M2. Hierzu wird in die obere linke Ecke des Diagramms das Schema und die Graphenklasse in der Form Schema.GraphClass notiert.

-capacity : int -open : bool -width : double -name : string -usage : Object -numberPlate : Set -numberPlateHistory : List -parking : Record -gate : Enum

CarPark AttributeTest.CityMap

Abbildung 3.19: M2-Beispiel zur Demonstration der Attributzugriffe

5Map: Eine Liste aus injektiven Schl¨ussel→Wert Paaren

Anwender-Code zur Erstellung des M2-Graphenschemas sowie der M1-Java-Klassen

Um einen CarPark mit den angesprochenen Attributen erstellen zu k¨onnen, muss nach-folgender Code vom Anwender implementiert werden.

Als erstes wird das Schema AttributeTest generiert.

// generate schema

Schema attrTest = SchemaImpl.create("AttributeTest");

Als n¨achstes werden die Dom¨anen des Schemas deklariert.

// get / generate domains

Domain numbers = attrTest.getIntDomain();

Domain bool = attrTest.getBooleanDomain();

Domain real = attrTest.getDoubleDomain();

Domain string = attrTest.getStringDomain();

Domain object = attrTest.getObjectDomain();

Domain set = attrTest.createSetDomain(string);

Domain listOfSet = attrTest.createListDomain(set);

Domain record = attrTest.createRecordDomain("Parking");

record.addComponent("date", string);

record.addComponent("duration", numbers);

record.addComponent("cost", real);

Domain enumeration = attrTest.createEnumDomain("Gate");

enumeration.addConst("open");

enumeration.addConst("close");

Im Folgenden wird die Graphklasse CityMap definiert.

// generate graphclass

GraphClass cityMap = attrTest.createGraphClass("CityMap");

Die Knotenklasse CarPark, welche die Attribute beinhalten soll, wird an dieser Stelle erstellt.

3.5. Externe Klassendiagramme // generate vertexclass

VertexClass carPark = cityMap.createVertexClass("CarPark");

Es folgt die Deklaration der Attribute der Knotenklasse CarPark.

// generate attributes

carPark.addAttribute("Capacity", numbers);

carPark.addAttribute("Open", bool);

carPark.addAttribute("Width", real);

carPark.addAttribute("Name", string);

carPark.addAttribute("Usage", object);

carPark.addAttribute("NumberPlate", set);

carPark.addAttribute("NumberPlateHistory", listOfSet);

carPark.addAttribute("Parking", record);

carPark.addAttribute("Gate", enumeration); // optional

Mittels des folgenden Methodenaufrufs werden die Javaklassen zur Attributierung au-tomatisch generiert.

// generate m1 classes at some location attrTest.commit("c://attrTest");

Automatisch generierter M1-Code aus dem M2-Graphenschema

Der folgende Code-Abschnitt zeigt einen Ausschnitt des Codes der M1-Ebene, welcher durch den Aufruf der commit-Methode automatisch generiert wird. Deutlich zu erken-nen sind die Attribute, welche als private deklariert wurden. Der Zugriff auf sie geschieht, wie in der Objektorientierung ¨ublich, ¨uber Getter und Setter.

Eine genauere Erkl¨arung der Funktionsweise der M1-Klassen-Generierung findet sich sp¨ater im Implementierungskapitel 4.2.2.

private boolean Open;

public boolean getOpen(){

return Open;

}

public void setOpen(boolean Open){

this.Open = Open;

public void setName(String Name){

this.Name = Name;

public void setWidth(double Width){

this.Width = Width;

public void setUsage(Object Usage){

this.Usage = Usage;

public void setCapacity(int Capacity){

this.Capacity = Capacity;

public void setParking(Parking Parking){

this.Parking = Parking;

}

private java.util.Set<String> NumberPlate;

public java.util.Set<String> getNumberPlate(){

return NumberPlate;

3.5. Externe Klassendiagramme }

public void setNumberPlate(java.util.Set<String>

NumberPlate){

this.NumberPlate = NumberPlate;

}

private java.util.List<java.util.Set<String>>

NumberPlateHistory;

public java.util.List<java.util.Set<String>>

getNumberPlateHistory(){

return NumberPlateHistory;

}

public void setNumberPlateHistory(

java.util.List<java.util.Set<String>> NumberPlateHistory){

this.NumberPlateHistory = NumberPlateHistory;

}

private Enum Gate;

public Enum getGate(){

return Gate;

}

public void setGate(Enum Gate){

this.Gate = Gate;

}

Bis auf Record- und Enum-Attribute wurden alle M2-Elemente innerhalb der CarPark.-java-Klasse erstellt. Die beiden fehlenden Attribute werden als eigenst¨andige Klassen innerhalb des AttributeTest-Schemas generiert.

Die Enum-KlasseGate.javabesteht nur aus einer einzigen Zeile:

public enum Gate{open, close}

Die Record-KlasseParking.javahingegen definiert ihre Attribute und ihren Kon-struktor innerhalb einer eigenen Klasse:

public class Parking { public String date;

public int duration;

public double cost;

public Parking() {}

public Parking(String date, int duration, double cost) {

Alternativ kann dieser gesamte Code folgendermaßen (Abb. 3.20) als UML-Diagramm notiert werden.

+getOpen() : boolean +setOpen( Open : boolean) +getName() : String +setName( Name : String) +getWidth() : double +setWidth( Width : double) +getUsage() : Object +setUsage( Usage : Object) +getCapacity() : int +setCapacity( Capacity : int) +getParking() : Parking +setParking( Parking : Parking) +getNumberPlate() : java.util.Set<String>

+setNumberPlate( NumberPlate : java.util.Set<String>) +getNumberPlateHistory() : java.util.List<java.util.Set<String>>

+setNumberPlateHistory( NumberPlateHistory : java.util.List<java.util.Set<String>>) +getGate() : Enum

+setGate( Gate : Enum) -Open : boolean

+Parking( date : String, duration : int, cost : double) : Parking +date : String

Abbildung 3.20: Klassendiagramm des Beispiels zur Generierung der Attribute

Die Attribute sind jetzt auf Ebene M2 vollst¨andig erstellt worden. Im folgenden werden diese M2-Elemente instanziiert, was M1-Elemente (also echte Graphen und Kanten) zur Folge hat.

3.5. Externe Klassendiagramme Anwender-Code zur Erstellung der M1-Ebene

Beispielhaft generieren wir hier genau einen CarPark und f¨ullen die Attribute mit zuf¨allig gew¨ahlten Beispiel-Werten auf. Dazu haben wir zwei M¨oglichkeiten: Entweder einzeln f¨ur jedes Attribut (wie folgt) oder alle zusammen im Konstruktor.

Die Beispielwerte des Beispielknotens loehrCenter im Beispielgraph koblenz sind die Folgenden:

• Das int-Attribut Capacity wird auf 2500 gesetzt.

• Der boolesche Wert Open wird auf true gesetzt.

• Das Fließkommazahl-Attribut Width bekommt den Wert 2,75.

• Die Zeichenkette Name bekommt den Wert

”L¨ohr-Center“.

• Das Java-Objekt Usage erh¨alt eine Map als Inhalt, welche Werte von Integer auf Boolean abbildet. In diesem Beispiel bekommt diese Map zwei Eintr¨age, einmal die Abbildung von 1 auf false und einmal von 2 auf true.

• Das Set NumberPlate bekommt zwei Eintr¨age von Zeichenketten:

”SIM-E-1337“

und”JG-RA-146“.

• Die Liste NumberPlateHistory erh¨alt auch zwei Eintr¨age: Einmal das eben defi-nierte Set und einmal ein zweites Set, welches lediglich die Zeichenfolge

” AB-C-0815“ enth¨alt.

• Der Record Parking bekommt als Daten die date-Zeichenkette

”08.03.2006“, den duration-int-Wert 90 und den cost-double-Wert 3.5 zugewiesen.

• Der Enumeration-Wert Gate erh¨alt den Wert open.

Zun¨achst wird der Beispielgraph koblenz erstellt.

// generate a graph (initial vertices=1, initial edges=0) CityMap koblenz = CityMapImpl.create(attrTest, 1,0);

Anschließend kann der Knoten loehrCenter erstellt werden.

// build a carpark

CarPark loehrCenter = koblenz.createCarPark();

Im Folgenden wird der erstellte Knoten mit Attributwerten aufgef¨ullt.

// fill in the attribute values // int

loehrCenter.setCapacity(2500);

// boolean

loehrCenter.setOpen(true);

// double

loehrCenter.setWidth(2.75);

// string

loehrCenter.setName("L¨ohr-Center");

// object

Map<Integer, Boolean> usage =

new HashMap<Integer, Boolean>();

usage.put(1, false);

usage.put(2, true);

// to save time, we do not generate all 2498 other entries loehrCenter.setUsage(usage);

// set (of string)

Set<String> numberPlates = new HashSet<String>();

numberPlates.add("SIM-E-1337");

numberPlates.add("JG-RA-146");

loehrCenter.setNumberPlate(numberPlates);

// list (of set (of string))

List<Set<String>> numberPlateHistory =

new LinkedList<Set<String>>();

Set<String> numberPlates2 = new HashSet<String>();

numberPlates2.add("AB-C-0815");

numberPlateHistory.add(numberPlates);

numberPlateHistory.add(numberPlates2);

loehrCenter.setNumberPlateHistory(numberPlateHistory);

// record (of string, int, double)

Parking p = new Parking("08.03.2006", 90, 3.5);

3.5. Externe Klassendiagramme

loehrCenter.setParking(p);

// enum

Enum gate = Gate.open;

loehrCenter.setGate(gate);

Bei Ausf¨uhrung des Codes entstehen die Elemente des Objektdiagramms 3.21.

Open : boolean = true Name : String = Löhr-Center Width : double = 2.75

Usage : Object = java.lang.Map(1->false,2->true) Capacity : int = 2500

Parking : Parking = Parking

NumberPlate : java.util.Set<String> = <SIM-E-1337,JG-RA-146>

NumberPlateHistory : java.util.List<java.util.Set<String>> = <(SIM-E-1337,JG-RA-146),(AB-C-0815)>

Gate : Enum = open

loehrCenter : CarPark

date : String = 08.03.2006 duration : int = 90 cost : double = 3.5

Parking : Parking uses

Abbildung 3.21: Objektdiagramm zur Darstellung der Attribute

Der CarPark loehrCenter wurde nun generiert, es werden im folgenden beispielhaft Zugriffe auf diese Attribute gezeigt:

// print out all the attributes // string

String name = loehrCenter.getName();

// int + string

System.out.println( "capacity of " + name + " is: " +

loehrCenter.getCapacity() );

// boolean + string

if (loehrCenter.getOpen())

System.out.println(name + " is open");

else

System.out.println(name + " is closed");

// double

System.out.println( "width of parking lots is " +

loehrCenter.getWidth() + "m");

// object (of map (of integer, boolean)) Map<Integer, Boolean> currentUsage =

(Map<Integer, Boolean>) loehrCenter.getUsage();

for (Entry<Integer, Boolean> e : currentUsage.entrySet()) { System.out.print("parking lot number "+e.getKey()+" is");

if (!e.getValue())

System.out.print(" not ");

System.out.println(" in use");

}

// set (of string)

Set<String> currentNumberPlates =

loehrCenter.getNumberPlate();

System.out.print("number plates of the day: ");

for (String numberPlate : currentNumberPlates) System.out.print(numberPlate + " ");

// list (of set (of string)) List<Set<String>> history =

loehrCenter.getNumberPlateHistory();

System.out.print("\nnumber plate history: ");

int day = 1;

for (Set<String> dailyNumberPlates : history) { System.out.print("day " + day++ + ": ");

for (String numberPlate : dailyNumberPlates) System.out.print(numberPlate + " ");

}

// record (of string, int, double) Parking pr = loehrCenter.getParking();

3.5. Externe Klassendiagramme System.out.println("\nuser parked on " + pr.date +

" for " + pr.duration + " minutes with a cost of " + pr.cost + " euros");

// enum

Enum gates = loehrCenter.getGate();

System.out.println("gate is " + gates);

Dieser Code generiert die folgende fiktive Ausgabe:

capacity of L¨ohr-Center is: 2500 L¨ohr-Center is open

width of parking lots is 2.75m parking lot number 2 is in use parking lot number 1 is not in use

number plates of the day: JG-RA-146, SIM-E-1337 number plate history: day 1: JG-RA-146, SIM-E-1337,

day 2: AB-C-0815.

user parked on 08.03.2006 for 90 minutes with a cost of 3.5 euros

gate is open

Zusammenfassung des Entwurfs

Der Entwurf von JGraLab ist an dieser Stelle im Groben abgeschlossen. Es wurde die Begriffswelt der Metaebenen gekl¨art, ein passendes Metamodell f¨ur JGraLab entwickelt und die externen Klassendiagramme zur Erstellung von Schema und Graphen eingef¨uhrt und beschrieben.

W¨ahrend der im n¨achsten Kapitel beschriebenen Implementierungsphase werden nur noch leichte Verfeinerungen an den Klassendiagrammen eingef¨uhrt.

In diesem Kapitel wird die Implementierungsphase von JGraLab beschrieben. An den im Entwurf festgelegten Klassendiagrammen werden nur noch leichte Ver¨anderungen durchgef¨uhrt. Diese minimalen Erweiterungen sind notwendig, da in diesem Kapitel vor allem Optimierungen bez¨uglich der Geschwindigkeit eingef¨uhrt werden.

Der Fokus des ersten Abschnitts dieses Kapitels (4.1) liegt im laufzeitoptimierten Ver-halten des JGraLab-Kerns. Im zweiten Abschnitt (4.2) wird die objektorientierte Zu-griffsschicht eingef¨uhrt und detailliert beschrieben. Anschließend (4.3) wird die Per-sistenz von Schemata und Graphen in JGraLab behandelt und das Kapitel mit einer Beschreibung der Ausnahmebehandlung (4.4) abgeschlossen.

4.1 Experimente bez ¨ uglich des Speicher- und Laufzeitverhaltens

In diesem Kapitel werden die in der Anforderungsliste (vgl. Abschnitt 2.1) erw¨ahnten zwei Experimente beschrieben und Tests durchgef¨uhrt. Es soll eine effiziente Daten-struktur gefunden werden, welche an erster Stelle schnell in der Durchf¨uhrung sein und an zweiter Stelle Speicher sparen soll. In diesem Abschnitt soll sich zwischen diesen beiden Implementierungen entschieden werden (Auszug aus der Anforderungsliste):

7.1.1 Kanten und Knoten werden durch Java-Objekte dargestellt.

7.1.2 Kanten- und Knoten-Objekte entstehen nur tempor¨ar f¨ur den Zugriff, intern wer-den sie als Inziwer-denztabelle repr¨asentiert.

Die in den n¨achsten Abschnitten gezeigten zwei Beispiele dienen nur der Verst¨and-lichkeit, zum Test m¨ussen mehrere zuf¨allig erstellte Graphen dienen, da nur diese groß genug sein k¨onnen, um die Performanz effektiv messen zu k¨onnen.

4.1. Experimente bez ¨uglich des Speicher- und Laufzeitverhaltens