2.5 Assoziative Arrays

An jedem Objekt kann der Dialogdesigner eigene Attribute, sogenannte benutzerdefinierte Attribute, angeben. Diese können dazu benutzt werden, um Statusinformation oder sonstige Daten direkt am Objekt abzulegen. Der Dialog Manager bietet hier die Möglichkeit der einfachen Attribute, der Feldattribute und assoziative Arrays.

Assoziative Felder werden hier detailliert beschrieben und anhand von Beispielen Anwendungsmöglichkeiten dargeboten.

2.5.1 Assoziationen und assoziative Arrays

Eine Assoziation ist eine gedankliche Verbindung zwischen Dingen oder Tätigkeiten, die per se nichts miteinander zu tun haben. Als Beispiel für Assoziationen kann ein Fernsehsender dienen, mit "RTL" verbindet oder assoziiert ein Zuschauer "Spielfilme", ein Jurist "Privatfernsehen", ein Werbefachmann "Quoten" und ein Fernsehtechniker den Kanal "65". In einem Programm können diese Assoziationen entsprechend programmiert werden, sodass ein Fernsehtechniker sich selbst nicht mehr den Kanal merken muss, sondern nur noch "RTL", das Programm unterstützt und entlastet ihn von unnötiger Arbeit. Die Umrechnung muss das Programm übernehmen. Hierbei ist Voraussetzung, dass sich die Assoziationen programmieren lassen. Der Dialog Manager unterstützt den Dialogprogrammierer, indem er ihm ein mächtiges Strukturierungselement an die Hand gibt; die assoziativen Arrays. Im allgemeinen ist eine Assoziation gerichtet, d.h. sie ist nicht unbedingt umkehrbar, so denkt der Fernsehtechniker bei "65" eher an Rente als einen Fernsehsender oder der Jurist bei "Privatfernsehen" eher an viel Arbeit und Verträge als an "RTL". Eine einzelne Assoziation lässt sich im Dialog Manager bereits mit normalen Attributen leicht definieren beziehungsweise ist unnötig zu definieren, da diese Assoziation im Normalfall direkt in den Code hineinprogrammiert wird. Zum Beispiel wird der Fernsehtechniker auch bei anderen Sendern gewisse Kanäle assoziieren. Der Dialog Manager bietet für solche Gruppen oder Reihen von gleichartigen Assoziationen das Mittel der assoziativen Arrays. Diese Beziehung könnte auch als Funktion aufgefasst werden, als Parameter wird die Quelle der Assoziation wie zum Beispiel "RTL" übergeben und als Ergebnis erhält man den Kanal 65. Diese Funktion zu programmieren ist sehr aufwendig, da in einer Regel ein "case" über alle Werte programmiert werden und die Funktion den möglichen Wertebereich abdecken muss oder nur statische Assoziationen besitzt. Der Wartungsaufwand ist unverhältnismäßig hoch im Gegensatz zu den assoziativen Arrays. Bei diesen Arrays oder Feldern kann mit der Quelle der Assoziation indiziert werden; der Inhalt dieses Feldes ist der entsprechende Endpunkt der Assoziation. In dem Senderbeispiel wurde mit dem String "RTL" indiziert und als Ergebnis wurde 65, also der Inhalt des Arrays, zurückgeliefert.

Der Dialog Manager kann an jedem beliebigen Objekt (Fenster, Poptext, Pushbutton, aber auch Dialog, Module oder Applikation) solche assoziativen Arrays definieren und benutzen. Diese assoziativen Arrays können fast wie normale Arrays von benutzerdefinierten Attributen definiert werden. Der Index wird jedoch als Datentyp angegeben und nicht als Bereich eingetragen.

Assoziative Arrays werden wie folgt definiert:

<DM Datentyp 1> <Attribute Name> [ <DM Datentyp 2> ];
.<Attribute Name>[ <Wert 2> ] := <Wert 1>;

Assoziative Arrays können maximal 65.528 Einträge aufnehmen. Wenn versucht wird mehr Einträge anzulegen, wird dies als "[SV] FAILED (IDM-E-IndexRange)" protokolliert.

Beispiel

window WMain

{

integer Kanal [ string ];

  .Kanal [ "RTL" ] := 65;

  .Kanal [ "ARD" ] := 14;

  .Kanal [ "ZDF" ] := 11;

}

Im Beispiel besitzt das Fenster ein assoziatives Array, in dem zu verschiedenen Strings, den Sendern, die entsprechenden Kanäle gespeichert werden.

Das obige Beispiel kann zu einem funktionsfähigen Dialog ausgebaut werden.

dialog SenderWahl

 

window WMain

{

integer Kanal [ string ];

  .Kanal [ "RTL" ] := 65;

  .Kanal [ "ARD" ] := 14;

  .Kanal [ "ZDF" ] := 11;

  child poptext Sender

  {

    .text [ 1 ]  "ARD";

    .text [ 2 ]  "ZDF";

    .text [ 3 ] "RTL";

    on select

    {

      print WMain.Kanal [ this.content ];

    }

  }

  on close { exit(); }

}

Wählt der Benutzer aus dem Poptext einen Sender aus, dann wird der aktuell gewählte String aus dem Poptext (this.content) als Index für den assoziativen Array Kanal benutzt. So erhält man auf elegante Art und Weise den zugehörigen oder assoziierten Kanal.

Man beachte, dass auf den assoziativen Arrays keine Ordnung besteht. Eine Ordnung ist oftmals nicht gegeben bzw. schwer berechenbar. Auch hier im Beispiel besteht bei den Sendern keine Ordnung, abgesehen von historischen Gründen bei ARD, ZDF und den "dritten" Regionalprogrammen.

2.5.2 Dynamische Verwaltung

Der Dialog Manager übernimmt die vollständige Verwaltung der assoziativen Felder. Für das Anlegen eines neuen Eintrages muss keine Vergrößerung des Arrays oder sonstige Verwaltungsarbeit vorgenommen werden. Es genügt die einfache Zuweisung eines Inhaltes an ein Feld; ist der Index noch nicht vorhanden, dann wird das Feld automatisch angelegt. Es ist also kein Aufruf einer :insert() Methode nötig.

Hierzu ein Beispiel eines Stacks oder Kellerspeichers, der beliebige Dialog Manager Daten (anyvalue) speichern kann:

dialog StackVerwaltung

record Stack

{

      integer Top := 0;

      anyvalue  Entry[ integer ];

      object Push := Rule_Push;

      object Pop := Rule_Pop;

}

rule void Rule_Push ( anyvalue Value)

{

      Stack.Entry[Stack.Top] := Value;

      Stack.Top := Stack.Top + 1;

}

rule anyvalue Rule_Pop ()

{

       if Stack.Top = 0

       then

              !! Error, stack is empty

        else

              Stack.Top := Stack.Top - 1;

        endif

        return (Stack.Entry[ Stack.Top ]);

}

on dialog Start

{

 

     Stack.Push( "Eintrag" );    !! "Eintrag"

     Stack.Push( "String" );     !! "Eintrag" - "String"

     Stack.Push( 42 );           !! "Eintrag" - "String" - 42

     Stack.Push( .visible );     !! "Eintrag" - "String" - 42
                                - .visible

     print Stack.Pop();          !! "Eintrag" - "String" - 42

     Stack.Push( .width );       !! "Eintrag" - "String" - 42
                                - .width

     print Stack.Pop();          !! "Eintrag" - "String" - 42

     print Stack.Pop();          !! "Eintrag" - "String"

     print Stack.Pop();          !! "Eintrag"

}

Mit Hilfe des obigen, funktionsfähigen Beispiels kann sehr leicht eine eigene Stackverwaltung aufgebaut werden. In Zeile 11 wird ein neuer Eintrag angelegt, ohne dass hierzu Verwaltungsaufwand getrieben werden muss. Im Beispiel wird nicht mit Strings indiziert oder Assoziationen aufgebaut, sondern es werden hier die integer Zahlen benutzt. Hier wird aber nicht die natürliche Ordnung der Zahlen im Array angewendet, es wird nur zu bestimmten Zahlen eine Beziehung oder Assoziation aufgebaut. Das Beispiel kann so abgewandelt werden, dass statt in Einer-Schritten in verschiedenen Schrittweiten hoch- bzw. runtergezählt wird. Das Verhalten bleibt identisch.