Die Schablone


... [ Was ist Velocity? ] ... [ Die Schablone ] ... [ Die Java-Klasse ] ... [ Inhaltsverzeichnis ] ...

Übersicht: Die Schablone


Was beinhaltet die Schablone?

Die Schablone beinhaltet die View aus dem MVC-Modell. Sie soll die Daten in einer bestimmten Form aufbereiten und diese darstellen. Ein Velocity-Servlet würde z.B. in der Schablone ein HTML-Dokument hinterlegen, welches Daten in einem Browser darstellen kann. Das Dokument benötigt natürlich Markierungen, die anzeigen, dass an bestimmten Stellen Daten eingefügt werden sollen. Dieses geschieht in Velocity mit der Velocity Template Language (VTL). Die VTL ist sehr einfach zu erlernen, so dass selbst Personen mit geringer oder keiner Programmierkenntnis diese benutzen können. Dieses ist ein großer Vorteil, da die Gestaltung von Daten nicht zwingend von Programmierern getätigt werden braucht. Vor der Entwicklung sind lediglich die Schnittstellen zu definieren, während die Entwicklung von View und Controller vollständig parallel vollzogen werden kann.


Die Velocity Template Language (VTL)

Einleitung
Die VTL ist die Schnittstelle zwischen der Schablone und der Java-Klasse. Sie kann Bereiche in der Schablone markieren, so dass an diesen Stellen später Inhalte eingefügt werden.
Die VTL besteht aus Referenzen (Verweisen) und Direktiven (Anweisungen). Referenzen starten immer mit einem "$" während Direktiven mit einem "#" beginnen.

Referenzen
Es gibt drei Typen von Referenzen: Variablen, Eigenschaften und Methoden. Jede Referenz verweißt auf ein beliebiges Objekt. Wird in einer Referenz auf ein anderes Objekt als das "String"-Objekt verwiesen, wird automatisch die "toString"-Methode des Objektes aufgerufen, da die VTL nur Text darstellen kann.

Variablen:

  • starten immer mit einem"$" gefolgt von einem Buchstaben (a..z, A..Z)
  • alle folgenden Zeichen dürfen Buchstaben, Ziffern, Unterstrich oder Bindestrich sein
  • können mit der Anweisung "#set" (siehe unten) innerhalb der Schablone ( #set ($Variable="Wert") ) oder in der Java-Klasse gesetzt werden
  • Eigenschaften:
  • werden einer Variable zugeordnet
  • Notation: $Variable.Eigenschaft
  • kann zwei Bedeutungen haben:
    1. gebe den Wert zurück, der im Hashtable "Variable" unter dem Schlüssel "Eigenschaft" zu finden ist
    2. Kurzform des Methodenaufrufs "$Variable.getEigenschaft()"
    Velocity überprüft zur Laufzeit, welche der beiden Möglichkeiten sinnvoll ist und führt diese aus.


  • Methoden:
  • ähneln der Notation von Eigenschaften ( "$Variable.Methode()" )
  • können Parameter übergeben bekommen
  • ruft die "Methode" der "Variable" auf
  • Formale Referenzen-Notation
    Die oben beschriebene Notation ist die kurze Notation, die auch meistens in der Schablone benutzt wird. Das folgende Beispiel beschreibt aber eine Problematik, die mit dieser Notation in einigen Fällen auftreten könnte:
    Die Variable "$studienrichtung" beinhaltet einen der folgenden Werte: "Wirtschafts" oder "Medien". In einer Schablone soll der Satz "Er studiert "Wirtschafts/Medien"informatik" angezeigt werden. Da es sich dabei um ein zusammenhängendes Wort handelt, darf kein Leerzeichen zwischen der Variable und dem Rest des Satzes stehen. In der Schablone würde der Satz so aussehen: "Er studiert $studienrichtunginformatik" Velocity kennt den so angegebenen Variablennamen aber nicht. Die formale Notation für Referenzen bereinigt dieses Problem. Sie besagt, dass alles hinter dem "$"-Zeichen in "{ }" zu stehen hat:
    ${studienrichtung}
    ${Variable.Eigenschaft}
    ${Variable.Methode()}

    Direktiven
    #set
    Die Anweisung "#set" ordnet einer Variable oder einer Eigenschaft "$a" einen Wert "Wert" zu.

    
    #set ( $a = Wert )
    
    Auf der linken Seite des "="-Zeichens steht immer ein Variablenname oder eine Eigenschaft. Die rechte Seite enthält eine der folgenden sieben Möglichkeiten:
    Inhalt einer Variable#set( $value = $value2)
    Wert einer Eigenschaft#set( $value = $value3.value)
    Ergebnis eines Methodenaufrufs#set( $value = $value4.getValue())
    ein String (in "")#set( $value = "Wert")
    eine Zahl#set( $value = 123)
    eine Aufzählung#set( $value = ["Wert1", "Wert2"])
    ein einfacher arithmetischer Ausdruck#set( $value = $value2 + 1)

    Wenn der Ausdruck, der zugewiesen werden soll, nicht ermittelt werden kann bzw. sein Ergebnis "null" ist, weist Velocity der Variable bzw. Eigenschaft nichts zu.

    #if
    Die if-Bedingung beginnt mit "#if" gefolgt von einer Bedingung, die in "( )" steht. "#end" markiert das Ende der Bedingung.
    
    #if ( $value )
          Alles klar!
    #end
    Die im Beispiel stehende Bedingung in den runden Klammern kann zwei Bedeutungen haben:
    1. der Typ von $value ist boolean (true => Ausgabe des Textes; sonst keine Ausgabe)
    2. der Typ von $value ist nicht boolean (Ausgabe des Textes, wenn der Wert von $value ungleich "null" ist)
    Vor dem "#end" kann mittels eines "#elseif" eine weitere Bedingung gestellt werden, die geprüft wird, wenn die erste Bedingung (hinter "#if") zu "false" ausgewertet wurde. Einem "#elseif" können weitere "#elseif"s folgen. Wenn der "else"-Teil an keine weitere Bedingung geknüpft sein soll, kann auch ein einfaches "#else" benutzt werden.
    
    #if( $value < 10 )
          kleiner als 10
    #elseif( $value == 10 )
          gleich 10
    #elseif( $value == 16 )
          gleich 16
    #else
          was anderes
    #end 
    Wie das Beispiel zeigt, können Bedingungen auch Vergleiche beinhalten. Auch logische Operatoren sind möglich. Die Notation ist dabei dieselbe wie in Java.
    
    #if( ($value < 10 && $value > 5) || ($value == 42) )

    #foreach
    Die "#foreach"-Schleife ist eine besonders wichtige Anweisung in der VTL. Häufig wird der Ersteller der Schablone nicht wissen, wie viele Elemente sich in einer Liste o.ä. befinden, die ausgegeben werden soll. In diesem Fall wird die "#foreach"-Schleife verwendet. Sie durchläuft automatisch eine Liste und gibt in jedem Durchlauf einen Wert an eine Variable zurück.
    
    #foreach( $product in $allProducts )
        $product
    #end
    Das Beispiel zeigt eine Schablone, in der eine Liste von Produkten ausgegeben werden soll. Die verschiedenen Produkte sind in der Variable "$allProducts" gespeichert. Mit jedem Schleifendurchlauf wird ein Eintrag aus "$allProducts" herausgelesen und in der Variable "$product" gespeichert.
    Als Listentyp erlaubt Velocity drei verschiedene Arten:
    1. eine Referenz auf eine Liste (z.B. Hashtable, Vector, Object-Array …)
    #foreach( $product in $allProducts )
    2. eine Array-Liste
    #foreach( $product in ["Produkt1","Produkt2","Produkt3"] )
    3. einen Range-Operator
    #foreach( $product in [1..3] )

    Das Durchlaufen einer Liste erfolgt bei Velocity, indem intern ein Schleifen-Index inkrementiert wird. Über die Variable "$velocityCount" kann auf den momentanen Wert dieses Indizes zugegriffen werden.
    
    #foreach( $product in $allProducts )
        Produktnummer = $velocityCount Produktname = $product
    #end
    Der Variablenname ("$velocityCount") und der Startwert der Schleife (Standard=1) sind in der Velocity-Eigenschaften-Datei "velocity.properties" festgelegt.
    
    # Default name of the loop counter
    # variable reference
    directive.foreach.counter.name = velocityCount
    
    # Default starting value of the loop
    # counter variable reference
    directive.foreach.counter.initial.value = 1
    Die Einstellungen in dieser Datei beziehen sich auf alle Schleifen innerhalb der Schablone.

    #include
    Die Anweisung "#include" erlaubt es, an einer Stelle in der Schablone eine weitere Datei einzufügen. Velocity ersetzt hierfür einfach die Anweisung durch den Inhalt der angegebenen Datei(en). Aus Sicherheitsgründen können nur Dateien angegeben werden, die sich im Verzeichnis der Schablone befinden.
    
    #include( "one.txt" )
    #include( "one.txt","two.txt","three.htm" )
    Auch Variablen, die einen Dateinamen beinhalten, können angegeben werden:
    
    #include( "one.txt", $filename )

    #parse
    Die "#parse"-Anweisung funktioniert genauso wie die "#include"-Anweisung. Der Unterschied ist, dass bei "#parse" die VTL-Teile in der angegebenen Datei vonVelocity bearbeitet werden. Ein weiterer Unterschied ist, dass "#parse" nur einen Dateinamen übergeben werden kann.
    Eine Datei, die mittels "#parse" eingebunden wird kann wiederum "#parse"-Anweisungen enthalten. Dadurch kann Rekursion erzeugt werden (siehe Beispiel unten). Damit es zu keiner Endlosrekursion kommt, ist in der Datei "velocity.properties" ein Wert angegeben, der die maximale Anzahl von Rekursionsstufen festlegt (Standard=10)
    
    directive.parse.max.depth = 10

    Beispiel für eine Rekursion mit "#parse":
    Datei countDown.vm:
    
    01 Count down.
    02 #set( $count = 8 )
    03 #parse( "rekursion.vm" )
    04 All done with dofoo.vm!
    

    Datei rekursion.vm
    
    01 $count
    02 #set( $count = $count - 1 )
    03 #if( $count > 0 )
    04     #parse( "rekursion.vm" )
    05 #else
    06     Alles klar!
    07 #end
    

    die Ausgabe:
    
    Count down
    8
    7
    6
    5
    4
    3
    2
    1
         Alles klar.
    

    #stop
    "#stop" beendet die Ausführung einer Schablone. Dieses kann sehr hilfreich beim Finden von Fehlern sein.

    #macro
    Häufig wiederkehrende Abschnitte in einer Schablone können in einem Velocimacro (Makro) definiert und dann beliebig oft ausgeführt werden.
    
    #macro( beispiel )
    --------T-R-E-N-N-L-I-N-I-E--------
    #end
    Der Aufruf des Makros erfolgt im Beispiel über "#beispiel()". Velocity ersetzt jedes "#beispiel()" durch den definierten Teil des Makros. Ein Makroaufruf kann beliebig viele Argumente (getrennt durch Leerzeichen) enthalten, solange diese in der Makrodefinition definiert sind. Folgende Typen sind als Argument erlaubt:
  • Referenz: alles was mit "$" startet
  • String : "Text"
  • Zahl : 1, 2 etc
  • IntegerRange : [ 1..2] oder [$value1 .. $value2]
  • ObjectArray : [ "a", "b", "c"]
  • boolscher Wert (true oder false)

  • 
    01 #macro( tablerows $somelist )
    02 #foreach( $something in $somelist )
    03     $something
    04 #end
    05 #end
    06
    07 #set( $greatlakes = ["Superior","Michigan","Huron","Erie","Ontario"] )
    08
    09 #tablerows( $greatlakes )
    
    Das Beispiel ist ein Teil einer Schablone. Nachdem Velocity die Schablone bearbeitet hat, wird folgendes dargestellt:
    
    Superior
    Michigan
    Huron
    Erie
    Ontario
    
    Wie man erkennt, wird die Ausgabe der Listeneinträge vom Makro übernommen, welches eine Liste an Einträgen übergeben bekommt. Das Beispiel zeigt, dass Makros immer vor dem ersten Aufruf definiert werden müssen, damit Velocity diese erkennt.
    Dem Beispiel kann man außerdem entnehmen, dass Makros "inline" in einer Schablone definiert werden können. Der Nachteil daran ist, dass man von verschiedenen Schablonen aus nicht auf dieses Makro zugreifen kann. Mehr Sinn macht da das Ablegen der Makros in Bibliotheken, auf die von jeder Schablone aus zugegriffen werden kann. Diese Bibliotheken werden in der Datei "velocity.properties" definiert:
    velocimacro.library = VM_global_library.vm
    Velocity erlaubt es, mehrere Dateinamen (getrennt mit Kommata) hintereinander anzugeben.
    Weiterhin wird in dieser Datei definiert, ob "inline"-Makros erlaubt sind (velocimacro.permissions.allow.inline = true) und ob Makros aus Bibliotheken in Schablonen überschrieben werden können (velocimacro.permissions.allow.inline.to.replace.global = false).
    Weitere Optionen sind:
    velocimacro.permissions.allow.inline.local.scope Werte sind true/false (Standard)
    Wird der Wert auf "true" gesetzt, kann nur aus der aktuellen Schablone auf dieses Makro zugegriffen werden. Für andere Schablonen ist dieses Makro unsichtbar.
    velocimacro.context.localscope Werte sind true/false (Standard)
    Wird der Wert auf "true" gesetzt, sind alle Variablenänderungen (gesetzt mit #set) nur lokal auf das Makro begrenzt.
    velocimacro.library.autoreload Werte sind true/false (Standard)
    Wird der Wert auf "true" gesetzt, prüft Velocity vor dem Aufruf eines Makros in einer Bibliothek, ob sich das Makro verändert hat und lädt dieses notfalls erneut.
    Diese Option ist nur für die Entwicklung vorgesehen, damit bei einer Änderung einer Bibliothek nicht das gesamte Servlet neu gestartet werden muss.

    Kommentare
    Die VTL unterstützt auch Kommentare. Ein Zeilenkommentar wird mit "##" eingeleitet. Mehrzeilige Kommentare starten mit "#*" und enden mit "*#".

    Sonderzeichen
    Wenn definierte Variablen ausgegeben werden sollen (NICHT deren Wert) benötigt Velocity einen Hinweis, dass der Name und nicht der Wert gemeint ist.
    Dieses geschieht durch das "\"-Zeichen:

    
    ( #set ($name= "Hans")
    $name
    \$name
    \\$name

    Ausgabe:
    
    Hans
    $name
    \Hans
    Das Beispiel zeigt, dass "\\" von Velocity zu "\" ausgewertet wird ("\" ist "linksgebunden").


    ... [ Was ist Velocity? ] ... [ Die Schablone ] ... [ Die Java-Klasse ] ... [ Inhaltsverzeichnis ] ...