Externer Typ für JavaScript-Code

Mit EGL kann eine Rich-UI-Anwendung auf nicht generierten JavaScript-Code zugreifen. Sie wollen vielleicht allgemeine Logik, zum Beispiel einen Zufallszahlengenerator, bereitstellen oder auf ein Nicht-EGL-Widget verweisen, zum Beispiel um ein Dojo-Widget in Ihrem Code verwenden zu können. In beiden Fällen hat die Aufgabe zwei Teile:
  1. Entwicklung eines externen EGL-Typs, der die JavaScript-Logik für eine Rich-UI-Anwendung verfügbar macht. Der JavaScript-Code wird als Implementierung des externen Typs bezeichnet.
  2. Schreiben einer nicht generierten JavaScript-Klasse, sofern der externe Typ nicht auf eine integrierte JavaScript-Klasse wie 'Math' oder 'Number' verweist.
Wenn Ihr externer Typ durch eine JavaScript-Quellendatei implementiert ist, gelten die folgenden Anweisungen:

Wenn Ihr externer Typ durch eine integrierte JavaScript-Klasse implementiert wird, legen Sie die Eigenschaft relativePath des externen Typs nicht fest.

Unabhängig von Ihrer Implementierung des externen Typs gilt, dass Sie, wenn sich der Name der JavaScript-Klasse von dem Namen des externen Typs unterscheidet, die Eigenschaft javaScriptName auf den Namen der Klasse setzen müssen.

Zur Vermeidung von Fehlern während der Ausführung sollten Sie nicht mehrere Versionen derselben Laufzeitbibliothek in einer Rich-UI-Anwendung verwenden.

In diesem Abschnitt wird die Verwendung der Funktion egl.defineClass beschrieben. Details zur Definition eines neuen Widgets finden Sie in “Rich-UI-Widgetgruppe erweitern”.

Struktur eines JavaScript-Codes für allgemeine Zwecke

Wenn Sie allgemeine Logik verfügbar machen wollen, zum Beispiel einen Zufallszahlengenerator, platzieren Sie Ihre JavaScript-Datei in einem Unterverzeichnis des Ordners 'WebContent'. Die Datei ruft die JavaScript-Funktion egl.defineClass auf:
egl.defineClass(
   'packageName', 'className',
   'superclassPackageName', superclassName,
    {
      "constructor": function() 
      { },

      "otherFunction": function(parameterList)
      { }
    }
);
Die Parameter haben die folgende Bedeutung:
packageName
Der Name des Pakets, in dem sich der angepasste JavaScript-Code befindet. Der Paketname ist erforderlich, von der Groß-/Kleinschreibung abhängig und gibt den WebContent-Unterordner an. Fügen Sie Punkte anstelle von Schrägstrichen für jeden Unterordner unter dem ersten ein. Beispiel: Wenn sich Ihr JavaScript-Code im Ordner WebContent/myPkg/test befindet, muss 'paketName' den Wert myPkg.test haben.
className
Eine Kennung, die Sie als Name der JavaScript-Klasse zuordnen. Die Klasse ist eine vordefinierte Sammlung von Funktionen. Der Name muss der Name der Eigenschaft JavaScriptName des externen EGL-Typs sein, der standardmäßig der Name des externen Typs ist. Der Klassenname ist von der Groß-/Kleinschreibung abhängig und ist erforderlich.
superclassPackageName
Optional. Der Name des Pakets, in dem sich der externe EGL-Typ für eine Superklasse befindet. Der Paketname ist von der Groß-/Kleinschreibung abhängig. Wenn Sie diesen Wert angeben, müssen Sie auch den Wert 'superclassName' angeben.
superclassName
Optional. Der Name einer Superklasse, die gleichzeitig der Name eines externen EGL-Typs ist, der die Superklasse für den EGL-Quellcode verfügbar macht. Der Wert für 'superclassName' ist von der Groß-/Kleinschreibung abhängig. Wenn Sie diesen Wert angeben, müssen Sie auch den Wert 'superclassPackageName' angeben.
otherFunction
Eine Funktion, die zusätzlich zur Funktion mit dem Namen "constructor" verwendet wird, die später beschrieben wird. Sie können eine beliebige Anzahl zusätzlicher Funktionen angeben.
parameterList
Eine Liste von Funktionsparametern.

Die Funktion mit dem Namen "constructor" ist optional und wird, wenn sie vorhanden ist, ausgeführt, sobald Sie eine EGL-Variable des externen Typs deklarieren. Diese Funktion kann keine Parameter haben und kann sich an einer beliebigen Position in der Funktionsliste befinden.

Sie können mehrere Klassen in einer einzelnen JavaScript-Datei definieren, jedoch ist es Konvention, nur eine Klasse einzuschließen, die denselben Namen wie die Datei hat. Das folgende Beispiel zeigt den Code in der Datei RandomNumberGenerator.js, die einen Zufallszahlengenerator zur Verfügung stellt:
egl.defineClass(
   'randomNumber', 'RandomNumberGenerator',	

   {	
	     "constructor" : function()
      {
         this.upperLimit = 100;
      },

      "setUpperLimit" : function(limit)
      {
         this.upperLimit = limit;
      },

      "getUpperLimit" : function()
      {
         return this.upperLimit;
      },

      "generateRandomNumber" : function()
      {
         return Math.floor(Math.random()*this.upperLimit);
      }
   }
);

Stereotyp für den externen Typ

In Bezug auf JavaScript ist der EGL-Stereotyp für den externen Typ JavaScriptObject, wie im folgenden Beispiel gezeigt:
package randomNumber;

import com.ibm.egl.rui.JavaScriptObject;
import com.ibm.egl.rui.JavaScriptProperty;

ExternalType RandomNumberGenerator type JavaScriptObject
   {
      relativePath = "randomnumber",
      javaScriptName = "RandomNumberGenerator"
   }

   upperLimit int {@JavaScriptProperty{getMethod = "getUpperLimit", 
                                       setMethod = "setUpperLimit"}};
  
   function generateRandomNumber() returns(int);
end
Der externe Typ kann die Klausel extends enthalten, um einen externen Typ anzugeben, der eine Superklasse darstellt, wie im folgenden Beispielentwurf:
ExternalType MyType extends OtherType type JavaScriptObject

end
Der externe Typ kann auch die folgenden Eigenschaften auf Abschnittsebene enthalten, die jeweils eine Zeichenfolge akzeptieren:
relativePath
Die Position der JavaScript-Datei in Relation zum Ordner 'WebContent'. Die Einstellung dieser Eigenschaft ist optional. Falls die JavaScript-Datei direkt im Ordner 'WebContent' und nicht in einem Unterordner gespeichert ist, setzen Sie die Eigenschaft relativePath auf eine leere Zeichenfolge. Schließen Sie auf keinen Fall einen Dateinamen in den Eigenschaftswert ein.

Wenn der externe Typ durch eine JavaScript-Datei implementiert wird, müssen Sie die Eigenschaft relativePath festlegen. Wenn der externe Typ durch eine integrierte Klasse implementiert wird, geben Sie die Eigenschaft nicht an.

javaScriptName
Gibt den Namen der JavaScript-Klasse an. Geben Sie nicht die Dateierweiterung .js an, da diese vorausgesetzt wird.

Die Einstellung dieser Eigenschaft ist optional. Wenn Sie keinen Wert angeben, wird angenommen, dass der Name der JavaScript-Klasse der Name des externen Typs ist.

Sie können die Eigenschaft javaScriptName zum Beispiel dazu verwenden, auf eine JavaScript-Klasse zuzugreifen, deren Name ein reserviertes Wort in EGL ist. Beispiel: Der folgende externe Typ ermöglicht den Zugriff auf eine JavaScript-Klasse mit dem Namen add, die sich in der Datei WebContent/part1/part2/add.js befindet:
ExternalType SumType type JavaScriptObject 
                          {relativePath = "part1/part2", javaScriptName = "add" }
    ;
end
includeFile
Gibt eine HTML-Datei oder andere CSS- oder JavaScript-Dateien an, die während der Ausführung verfügbar gemacht werden. Der in includeFile angegebene Pfad ist relativ zum Verzeichnis 'WebContent'. Beispiel: "JS/myFile.js".
Die folgende Datei könnte verwendet werden, wenn Sie den externen Typ zum Referenzieren eines Dojo-Widgets verwenden:
<script type="text/javascript" src="http://o.aolcdn.com/dojo/1.0.0/dojo/dojo.xd.js">
</script>

<style type="text/css">
   @import "http://o.aolcdn.com/dojo/1.0.0/dijit/themes/dijit.css";
   @import "http://o.aolcdn.com/dojo/1.0.0/dijit/themes/tundra/tundra.css";
   @import "http://o.aolcdn.com/dojo/1.0.0/dojo/resources/dojo.css"
</style>
        
<script>
   dojo.require("dijit.form.Button");
   dojo.require("dijit.form.Slider");
</script>

Diese Datei lädt die Dojo-Widget-Bibliothek und Dojo-CSS-Dateien und startet die Dojo-Laufzeit.

Wie im Beispiel für einen externen Typ gezeigt, kann ein Feld in diesem Typ die folgende Eigenschaft auf Feldebene enthalten:
@JavaScriptProperty
Diese komplexe Eigenschaft ist erforderlich, wenn Sie aus Ihrem EGL-Code heraus auf ein globales JavaScript-Feld (ein Feld der Form this.myField) zugreifen wollen. Wenn Sie einen Wert aus Ihrem EGL-Code zuordnen wollen, muss der JavaScript-Code das Feld in der Funktion mit dem Namen "constructor" definieren. Sie können jedoch einen Wert aus dem JavaScript-Feld abrufen, unabhängig davon, wo das Feld im JavaScript-Code definiert ist.
Im Allgemeinen gibt @JavaScriptProperty JavaScript-Funktionen an, die den JavaScript-Feldwert abrufen und festlegen. Sie können diese Eigenschaft verwenden, ohne Funktionsnamen anzugeben, wenn die Namen der Funktionen mit dem Wort get oder set, gefolgt von dem Variablennamen, gebildet werden. Beispiel: Wenn es sich um die Variable UpperLimit handelt und die JavaScript-Klasse Funktionen mit den Namen getUpperLimit() und setUpperLimit() enthält, müssen Sie nur die komplexe Eigenschaft wie im folgenden Beispiel hinzufügen:
UpperLimit INT { @JavaProperty{} };
Die folgenden Eigenschaftsfelder befinden sich in @JavaScriptProperty:
getMethod
Eine Zeichenfolge (in Anführungszeichen), die den Namen der Get-Methode für die angegebene Variable enthält (geben Sie keine Klammern an). Die Methode hat keine Parameter und ihr Rückgabewert hat denselben Typ wie das Feld.
setMethod
Eine Zeichenfolge (in Anführungszeichen), die den Namen der Set-Methode für die angegebene Variable enthält (geben Sie keine Klammern an). Die Methode hat einen Parameter, der denselben Typ wie das Feld hat. Üblicherweise hat die Set-Methode keinen Rückgabewert, aber es resultiert auch keine Fehlerbedingung, wenn die Methode einen Wert zurückgibt.

Wenn Sie nur eines der beiden Eigenschaftsfelder angeben, geht EGL davon aus, dass die nicht angegebene Funktion nicht verfügbar ist. Ein Fehler tritt nur auf, wenn ein Ausdruck einen Aufruf der Funktion zur Folge hat, die als nicht vorhanden angenommen wird.

Bei JavaScript-Feldnamen wird ebenso wie beim Feldnamen des externen Typs die Groß-/Kleinschreibung unterschieden.

Beziehung zwischen EGL- und JavaScript-Datentypen

Tabelle 1. EGL- und JavaScript-Datentypen
EGL-Typ JavaScript-Typ (mit Unterscheidung der Groß-/Kleinschreibung)
STRING String (Zeichenfolge)
BOOLEAN Boolean (boolescher Wert)
SMALLINT, INT, FLOAT, SMALLFLOAT Number (Zahl)
BIGINT, DECIMAL, MONEY, NUM egl.javascript.BigDecimal (wie in einem nachfolgenden Abschnitt beschrieben)
DATE, TIME, TIMESTAMP Date (Datum)

EGL-Feldgruppen werden an JavaScript als JavaScript-Feldgruppen (Arrays) übergeben. Wenn ein EGL-Typ (z. B. eine Feldgruppe) auf den Wert 'null' gesetzt wird, empfängt der JavaScript-Code einen JavaScript-Wert 'null'.

egl.javascript.BigDecimal

Die bereitgestellte JavaScript-Klasse 'egl.javascript.BigDecimal' kann Zahlen mit einer großen Anzahl von Stellen präzise darstellen. Diese Klasse besitzt außerdem Methoden zur Ausführung mathematischer Operationen mit BigDecimal-Werten.

Der native numerische Typ in JavaScript ist die Klasse 'Number', die eine Gleitkommadarstellung von Zahlen ermöglicht. Diese Klasse ist nicht präzise und kann nicht viele Werte darstellen. Bei der Verwendung von Werten der Klasse 'Number' können Rundungsfehler in mathematischen Operationen auftreten.

Ein BigDecimal-Objekt kann nach seiner Erstellung nicht mehr geändert werden. Beispiel: Wenn Sie zwei BigDecimal-Werte addieren wollen, schreiben Sie den Code wie folgt:
   var result = bigDecimal1.add( bigDecimal2 ); 
Das Ergebnis geht verloren, wenn Sie den Code wie folgt schreiben:
   bigDecimal1.add( bigDecimal2 ); 
Der Konstruktor 'egl.javascript.BigDecimal' akzeptiert ein Argument, das eine Zeichenfolge ist, die den gewünschten Wert für 'BigDecimal' enthält. Zahlen in Zeichenfolgeform müssen mindestens eine Stelle haben und dürfen kein Leerzeichen enthalten. Sie können ein führendes Vorzeichen und ein Dezimaltrennzeichen haben und können in Exponentialschreibweise angegeben werden. Einige Beispiele für gültige Argumente:
  • "0"
  • "12"
  • "-76"
  • "12.70"
  • "+0.003"
  • "17."
  • ".5"
  • "4E+9"
  • "0.73e-7"
Die folgenden JavaScript-Methoden verwenden Objekte von 'egl.javascript.BigDecimal' (solche Objekte werden mit bd angegeben, während Objekte vom Typ 'Number' mit n angegeben werden):
  • abs(): Gibt den absoluten Wert des BigDecimal-Werts zurück.
  • add(bd): Gibt die Summe des aktuellen Objekts und des Arguments zurück.
  • compareTo(bd): Gibt den Wert -1 zurück, wenn das aktuelle Objekt kleiner als das Argument ist, gibt den Wert 1 zurück, wenn das aktuelle Objekt größer als das Argument ist, oder gibt den Wert 0 zurück, wenn beide gleich sind.
  • divide(bd): Gibt das Ergebnis der Division des aktuellen Objekts durch das Argument zurück.
  • divideInteger(bd): Gibt den ganzzahligen Teil der Division des aktuellen Objekts durch das Argument zurück.
  • equals(obj): Gibt den Wert 'true' zurück, wenn das Argument, das ein beliebiges Objekt sein kann, ein BigDecimal mit demselben Wert und derselben Anzahl der Dezimalstellen wie das aktuelle Objekt ist. Diese Methode gibt den Wert 'false' zurück, wenn das Argument kein BigDecimal ist oder wenn es ein BigDecimal mit einem anderen Wert oder einer anderen Anzahl Dezimalstellen ist. Der Parameter 'obj' ist ein beliebiges Objekt.
  • max(bd): Gibt das aktuelle Objekt oder Argument zurück, je nachdem, welcher Wert größer ist.
  • min(bd): Gibt das aktuelle Objekt oder Argument zurück, je nachdem, welcher Wert kleiner ist.
  • movePointLeft(n): Gibt einen BigDecimal-Wert zurück, der zum aktuellen Objekt (Zahl) äquivalent ist, jedoch mit dem Dezimaltrennzeichen um die angegebene Anzahl von Stellen nach links verschoben.
  • movePointRight( n): Gibt einen BigDecimal-Wert zurück, der zum aktuellen Objekt (Zahl) äquivalent ist, jedoch mit dem Dezimaltrennzeichen um die angegebene Anzahl von Stellen nach rechts verschoben.
  • multiply(bd): Gibt das Ergebnis der Multiplikation des aktuellen Objekts mit dem Argument zurück.
  • negate(): Gibt die Negation des aktuellen Objekts zurück.
  • pow(bd): Gibt das Ergebnis der Erhebung des aktuellen Objekts in die angegebene Potenz zurück. Die Potenz muss im Bereich von -999999999 bis 999999999 liegen und muss einen Dezimalteil von null haben.
  • remainder(bd): Dividiert das aktuelle Objekt durch das Argument und gibt den Rest zurück.
  • setScale(n, mode): Gibt einen BigDecimal-Wert mit der angegebenen Anzahl von n Dezimalstellen zurück. Das Argument n ist eine Zahl und das optionale Argument mode ist eine Konstante, die nachfolgend beschrieben wird.
    Wenn n größer als die aktuelle Anzahl von Dezimalstellen ist, fügt die Methode abschließende Nullen an den Dezimalteil der Zahl an. Wenn n kleiner als die aktuelle Anzahl von Dezimalstellen ist, entfernt die Methode abschließende Stellen aus dem Dezimalteil der Zahl und mode gibt an, wie die verbleibenden Stellen gerundet werden. Die Konstante mode kann die folgenden Werte haben:
    • Der Standardwert (egl.javascript.BigDecimal.prototype.ROUND_UNNECESSARY) gibt an, dass keine Rundung erforderlich ist.
    • Der Wert egl.javascript.BigDecimal.prototype.ROUND_CEILING bewirkt eine Rundung auf eine positivere Zahl.
    • Der Wert egl.javascript.BigDecimal.prototype.ROUND_DOWN bewirkt eine Rundung gegen null.
    • Der Wert egl.javascript.BigDecimal.prototype.ROUND_FLOOR bewirkt eine Rundung auf eine negativere Zahl.
    • Der Wert egl.javascript.BigDecimal.prototype.ROUND_HALF_DOWN bewirkt eine Rundung auf den nächsten Nachbarwert, wobei bei gleichem Abstand abgerundet wird.
    • Der Wert egl.javascript.BigDecimal.prototype.ROUND_HALF_EVEN bewirkt eine Rundung auf den nächsten Nachbarwert, wobei der Wert bei gleichem Abstand auf den nächsten geradzahligen Nachbarwert gerundet wird.
    • Der Wert egl.javascript.BigDecimal.prototype.ROUND_HALF_UP bewirkt eine Rundung auf den nächsten Nachbarwert, wobei bei gleichem Abstand aufgerundet wird.
    • Der Wert egl.javascript.BigDecimal.prototype.ROUND_UP bewirkt eine Rundung von null weg.

  • scale(): Gibt die Anzahl der Stellen nach dem Dezimaltrennzeichen als Zahl (Number) zurück.
  • signum(): Gibt den Wert -1 zurück, wenn die Zahl negativ ist, den Wert null, wenn die Zahl null ist, und den Wert 1, wenn die Zahl positiv ist.
  • subtract(bd): Gibt das Ergebnis der Subtraktion des Parameters vom aktuellen Objekt zurück.
  • toString(): Gibt eine Zielzeichenfolgedarstellung des BigDecimal-Objekts zurück.
Die folgenden Konstanten werden ebenfalls durch BigDecimal definiert:
  • egl.javascript.BigDecimal.prototype.ZERO ist ein BigDecimal mit dem Wert null.
  • egl.javascript.BigDecimal.prototype.ONE ist ein BigDecimal mit dem Wert 1.
  • egl.javascript.BigDecimal.prototype.TEN ist ein BigDecimal mit dem Wert 10.

JavaScriptObjectException

Wenn eine nicht generierte JavaScript-Funktion unter Verwendung eines externen Typs aufgerufen wird und wenn die Funktion einen Fehler auslöst, verursacht der Aufruf eine EGL-Ausnahmebedingung JavaScriptObjectException. Wie jede EGL-Ausnahmebedingung enthält JavaScriptObjectException die Felder message und messageID.

Wenn ein JavaScript-Fehlerobjekt abgefangen wird, wird das Feld message mit dem Wert aus dem äquivalenten Feld des Fehlerobjekts festgelegt. Andernfalls empfängt das Feld message eine Zeichenfolge, die mit dem Wert äquivalent ist, der von der JavaScript-Funktion ausgegeben wird.

Die Ausnahmebedingung JavaScriptObjectException hat das folgende zusätzliche Feld:
name
Wenn ein JavaScript-Fehlerobjekt abgefangen wird, wird das Feld name mit dem Wert aus dem äquivalenten Feld des Fehlerobjekts festgelegt. Andernfalls empfängt das Feld name eine leere Zeichenfolge.

Feedback