You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@velocity.apache.org by "Kulinski, Artur" <Ar...@eu.sony.com> on 2002/07/12 16:10:00 UTC
Polish version of user guide
Following is translation of users guide to polish. It is encoded in UTF-8
becouse of
polish special characters. Feel free to use it or request for changes.
----------------------------------------------------------------------------
----------------------
<?xml version="1.0" encoding="UTF-8"?>
<document>
<properties>
<title>Velocity User Guide</title>
<author email="jvanzyl@zenplex.com">Velocity Documentation Team</author>
<author email="jcastura@kw.igs.net">John Castura</author>
<author email="akulinsk@eu.sony.com">Artur Kulinski</author>
</properties>
<body>
<section name="Spis treści">
<ol>
<li><a href="#O dokumencie">O dokumencie</a></li>
<li><a href="#Czym jest Velocity ?">Czym jest Velocity ?</a></li>
<li><a href="#Co Velocity może mi zaoferować ?">Co Velocity może mi
zaoferować ?</a>
<ol>
<li><a href="#Przykład Sklepu z Błotem">Przykład Sklepu z
Błotem</a></li>
</ol>
</li>
<li><a href="#Velocity Template Language (VTL): Wprowadzenie">Velocity
Template Language (VTL):
Wprowadzenie</a></li>
<li><a href="#Hello Velocity World!">Hello Velocity World!</a></li>
<li><a href="#Komentarze">Komentarze</a></li>
<li><a href="#Odwołania">Odwołania</a>
<ol>
<li><a href="#Zmienne">Zmienne</a></li>
<li><a href="#Własności">Własności</a></li>
<li><a href="#Metody">Metody</a></li>
</ol>
</li>
<li><a href="#Formalna Notacja Odwołań">Formalna Notacja Odwołań</a></li>
<li><a href="#Cicha Notacja Odwołań">Cicha Notacja Odwołań</a></li>
<li><a href="#Uzyskiwanie literału">Uzyskiwanie literału</a>
<ol>
<li><a href="#Waluta">Waluta</a></li>
<li><a href="#Cytowania Odwołań VTL">Cytowania Odwołań VTL</a></li>
</ol>
</li>
<li><a href="#Case Substitution">Case Substitution</a></li>
<li><a href="#Dyrektywy">Dyrektywy</a>
<ol>
<li><a href="#Set">Set</a></li>
<li><a href="#Literały łańcuchowe">Literały łańcuchowe</a></li>
<li><a href="#konstrukcja If-Else">konstrukcja If-Else</a>
<ol>
<li><a href="#Operatory relacyjne i logiczne">Operatory
relacyjne
i logiczne</a></li>
</ol>
</li>
<li><a href="#Pętle foreach">Pętle foreach</a></li>
<li><a href="#Include">Include</a></li>
<li><a href="#Parse">Parse</a></li>
<li><a href="#Stop">Stop</a></li>
<li><a href="#Velocimakra">Velocimakra</a></li>
</ol>
</li>
<li><a href="#Cytowanie dyrektyw VTL">Cytowanie dyrektyw VTL</a></li>
<li><a href="#VTL: zagadnienia związane z formatowaniem">VTL: zagadnienia
związane z formatowaniem</a></li>
<li><a href="#Różności">Różności</a>
<ol>
<li><a href="#Obliczenia">Obliczenia</a></li>
<li><a href="#Operator zakresu">Operator zakresu</a></li>
<li><a href="#Zagadnienia zaawansowane: Cytowanie i znak
!">Zagadnienia zaawansowane: Cytowanie i znak
!</a></li>
<li><a href="#Różności Velocimakr">Różności Velocimakr</a></li>
<li><a href="#Łączenie (konkatenacja) łańcuchów">Łączenie
(konkatenacja) łańcuchów</a></li>
</ol>
</li>
<li><a href="#Uwagi czytelników">Uwagi czytelników</a></li>
</ol>
</section>
<section name="O dokumencie">
<p>
Velocity - przewodnik użytkownika ma na celu zaznajomienie
projektantów stron i dostawców treści z Velocity oraz ze składnią
jego prostego, aczkolwiek niezwykle użytecznego języka skryptowego -
Velocity Template Language (VTL). Wiele z zamieszczonych w tym
przewodniku
przykładów dotyczy zamieszczania dynamicznej treści w serwisach WWW,
jednakże wszystkie zamieszczone przykłady VTL mogą zostać użyte
do innych zastosowań.
</p>
<p>
Dziękujemy za wybór Velocity !
</p>
</section>
<section name="Czym jest Velocity ?">
<p>
Velocity jest o opartym o język Java mechanizmem szablonów. Pozwala
projektantom stron na odwołania do metod zdefiniowanych w kodzie Javy.
Dzięki temu projektanci stron mogą pracować równolegle z programistami
Javy
nad tworzeniem serwisów zgodnych ze wzorcem Model-Widok-Kontroler
(Model-View-Controller MVC), co w praktyce oznacza, że projektanci mogą
się
skoncetrować nad tworzeniem dobrze zaprojektowanych serwisów, a programiści na tworzeniu wysokiej jakości kodu. Velocity separuje kod
Javy
od samej strony WWW, dzięki czemu konserwacja serwisu WWW podczas
działania
staje się znacznie łatwiejsza. Velocity stanowi dobrą alternatywę dla
<a href="http://java.sun.com/products/jsp/">Java Server Pages</a>
(JSPs) i <a href="http://www.php.net/">PHP</a>.
</p>
<p>
Velocity może być wykorzytane do generacji stron WWW, zapytań SQL,
plików PostScript oraz wielu innych formatów. Velocity może
być wykorzystywane jako samodzielne narzędzie do generacji kodów
źródłowych
i raportów lub jako komponent zintegrowany z innym systemem. Po
zakończeniu
projektu Velocity dostarczy mechanizm szablonów dla projektu <a
href="http://java.apache.org/turbine/">Turbine</a> - framework'a
(szkieletu)
dla aplikacji WWW. Velocity+Turbine dostarczą narzędzia, które umożliwi
tworzenie
aplikacji WWW w pełni zgodnych z modelem MVC </p>
</section>
<section name="Co Velocity może mi zaoferować ?">
<subsection name="Przykład Sklepu z Błotem">
<p>
Załóżmy, że jesteś projektantem tworzącym skelp internetowy
specjalizujący się w sprzedaży błota. Nazwijmy go "The Online Mud
Store".
Interes się rozwija. Klienci składają zamówienia na różne rodzaje i
ilości błota,
rejestrując się w systemie za pomocą nazwy użytkownika i hasła. Po
rejestracji
mają możliwość przeglądania swoich zamówień i składania nowych.
Aktualnie sprzedajesz Błoto Terracotta, które jest niezwykle popularne.
Mniejsza
liczba klientów kupuje także regularnie Czerwone Błoto, które jednak nie
jest aż tak popularne
i w związku z tym nie zajmuje pierwszoplanowego miejsca w serwisie.
Informacje o klientach
są skłądowane w bazie danych. Pewnego dnia przez myśl przebiega Ci
pytanie: "Dlaczego
nie wykorzytsać Velocity, aby skierować specjalną ofertę do klientów
zainteresowanych
właśnie tym typem błota ?"
</p>
<p>
Velocity umożliwia łatwe dostosowanie stron WWW do preferencji klientów
on-line'owych. Jako projektant w The Mud Room, chcesz wykonać stronę,
która pojawi sie po zalogowaniu klienta do Twojego serwisu.
</p>
<p>
Na spotkaniu z programistami w twojej firmie ustaliliście, że <em>$customer</em> będzie przechowywać informacje związane z
aktualnie zalogowanym klientem, <em>$mudsOnSpecial</em> będzie
przechowywać wszystkie typy błota dostępne aktualnie w sprzedaży.
Obiekt <em>$flogger</em> udostępnia metody użyteczne dla promocji.
Z tak sprecyzowanym zadaniem, skupmy sie na razie na trzech powyższych
odwołaniach. Pamiętaj, że zupełnie nie musisz zastanawiać się nad tym,
jak
programiści napełnią te obiekty danymi, po prostu zakładasz że to
zrobili.
Dzięki temu możesz się skupić na swoich zadaniach i pozwolić
programistom
wykonywać ich pracę.
</p>
<p>
Możesz umieścić w źródle swojej strony następujący element VTL:
</p>
<source><![CDATA[
<HTML>
<BODY>
Hello $customer.Name!
<table>
#foreach( $mud in $mudsOnSpecial )
#if ( $customer.hasPurchased($mud) )
<tr>
<td>
$flogger.getPromo( $mud )
</td>
</tr>
#end
#end
</table>
]]></source>
<p>
Więcej szczegółow na temat wyrażenia <em>foreach</em> zostanie
przedstawione
w dalszej części tekstu, ważny jest wpływ tego krótkiego kawałka skryptu
na Twoją stronę. Gdy do serwisu zaloguje się klient zainteresowany
zakupem
Czerwonego Błota, zobaczy wyraźnie, że jest ono dostępne. Jeżeli
zaloguje się
klient z obszerną historią zakupów Błota Terracotta, zobaczy informację
o tym
produkcie wyśrodkowaną na pierwszym planie. Elastyczność Velocity jest
ogromna i ograniczona jedynie twoją kreatywnością.
</p>
<p>
W dokumentacji VTL wymienionych jest znacznie więcej elementów, które
wspólnie dają ci siłę i elastyczność potrzebną, aby nadać Twoim stroną
odpowiednią
dla rozwiązania WWW <em>prezencję</em>. Im lepiej zapoznasz się z tymi
elementami,
tym bardziej odkryjesz potęgę Velocity.
</p>
</subsection>
</section>
<section name="Velocity Template Language (VTL): Wprowadzenie">
<p>
Celem Velocity Template Language (VTL) jest dostarczenie najprostszego,
najłatwiejszego i najczystszego sposobu na dołączanie dynamicznej
zawartości
do stron WWW, tak aby nawet projektant stron bez, lub z minimalną
znajomością
programowania, był w stanie w krótkim czasie wykorzystywać VTL do
dostarczania
dynamicznej treści.
</p>
<p>
VTL wykorzystuje <em>odwołania</em> do umieszczania dynamicznej treści
w serwisie WWW. Jednym z typów odwołań są zmienne. Zmienne pozwalają
na odwołanie do wartosći zdefiniowanych w kodzie Javy lub mogą uzyskać
wartość
z <em>wyrażenia</em> VTL zawartego w źródle strony. Poniżej
przedstawiony jest
przykad wyrażenia VTL, które może znajdować się w źródle HTML strony:
</p>
<source><![CDATA[
#set( $a = "Velocity" )
]]></source>
<p>
Powyższy przykład wyrażaenia VTL zaczyna się (jak każde wyrażenie VTL)
znakiem <em>#</em> i zawiera dyrektywę: <em>set</em>. Gdy odwiedzający
zażąda Twojej strony mechanizm Velocity (Velocity Templating Engine)
odszuka
w źródle wszystkie znaki <em>#</em>, a następnie stwierdzi, któe znaki
<em>#</em>
rozpoczynają wyrażenia VTL, a które nie mają z VTL nic wspólnego.
</p>
<p>
Po znaku <em>#</em> występuje dyrektywa <em>set</em>.
Dyrektywa <em>set</em> wykorzystuje wyrażenie (ujęte w nawiasy)
-- przypisanie, które nadaje <em>wartość</em> <em>zmiennej</em>.
Zmienna występuje po lewej stronie, a jej wartość po prawej stronie,
względem
znaku <em>=</em>.
</p>
<p>
W powyższym przykładzie zmienną jest <em>$a</em>, a wartością
<em>Velocity</em>. Zmienna, jak wszystkie odwołania, rozpoczyna się
znakiem <em>$</em>. Wartości zawsze ujęte są w cudzysłowy, w przypadku
Velocity nie trzeba przejmować się typem zmiennych, ponieważ do
zmiennych
można przekazywać jedynie łańcuchy (informację tekstową).
</p>
<p>
Następująca, prosta zasada może ułatwić zrozumienie jak działa Velocity:
<strong>Odwołania rozpoczynają się od znaku <em>$</em> i pozwalają
coś uzyskać (jakąś wartość), natomiast dyrektywy rozpoczynają się od
<em>#</em> i pozwalaja coś zrobić.</strong>
</p>
<p>
W powyższym przykładzie dyrektywa <em>#set</em> została wykorzystana,
aby przypisać wartość zmiennej. Zmienna <em>$a</em> może być po tym
użyta do
wypisania "Velocity".
</p>
</section>
<section name="Hello Velocity World!">
<p>
Po przypisaniu wartości do zmiennej, możesz ją wykorzystywać
w dowolnym miejscu Twojego dokumentu HTML. W poniższym przykładzie
wartość zostaje przypisana do zmiennej <em>$foo</em>, a następnie
wykorzystania.
</p>
<source><![CDATA[
<html>
<body>
#set( $foo = "Velocity" )
Hello $foo World!
</body>
<html>
]]></source>
<p>
Rezultatem jest strona WWW wypisująca "Hello Velocity World!".
</p>
<p>
Dla zwiększenia czytelności wyrażeń zawierających dyrektywy VTL
zaleca się rozpoczynanie każdego wyrażenia VTL od nowej linii, jednakże
nie jest to wymogiem formalnym. Dyrektywą <em>set</em> zajmiemy się
ponownie, bardziej szczegółowo później.
</p>
</section>
<section name="Komentarze">
<p>
Komentarze pozwalają na zamieszczanie opisów tekstowych, które nie
będę zawarte w wyniku działania mechanizmu szablonów. Komentarze
pomagają Ci opisać, co tak naprawdę robią Twoje wyrażenia VTL, zarówno
dla własnego przypomnienia w przyszłości, jak i dla innych którzy będą
korzystać
z Twoich szablonów. Możesz także wykorzystać komentarze dla innych
celów,
które uznasz za stosowne. Poniżej znajduje się przykład komentarza w
VTL:
</p>
<source><![CDATA[
## To jest komentarz jednowierszowy.
]]></source>
<p>
Jendowierszowy komentarz rozpoczyna się znakami <em>##</em>
i kończy z końcem linii. Jeżeli chcesz umieścić komentarz wielolinijkowy
nie muszisz powtarzać wielokrotnie zanków <em>##</em>, w tym celu
możesz zastosować komentarz wielowierszowy zaczynający się od
<em>#*</em>, a kończący <em>*#</em>.
</p>
<source><![CDATA[
To jest tekst poza komentarzem.
Widoczny dla odwiedzających stronę.
#*
Tutaj zaczyna się komentarz wielowierszowy.
Zostanie zignoworwany przez mechanizm Velocity i odwiedzający stronę
nie zobaczą go !
*#
To jest tekst poza komentarzem. Widoczny dla odwiedzających.
]]></source>
<p>
Poniżej kilka przykładów pokazujących zastosowanie jedno i
wielowierszowych komentarzy:
</p>
<source><![CDATA[
Ten tekst jest widoczny. ## A ten nie !
Ten tekst jest widoczny.
Ten też. #* Ten tekst jest częścią komentarza wielowierszowego
i jest niewidoczny. Ten tekst też jest niewidoczny i też jest częścią
komentarza wielowierszowego. Ciągle niewidoczny. *# Ten tekst jest poza
komentarzem
Jest więc widoczny.
## A ten nie.
]]></source>
<p>
Jest jeszcze trzeci typ komentarza, komentarz blokowy VTL.
Może byc użyty do zawarcia informacji, takich jak: autor dokumentu,
informacje o wersji.
</p>
<source><![CDATA[
#**
To jest komentarz blokowy VTL.
Może zawierać informacje
o autorze i wersji dokumentu.
Informacje:
@author
@version 5
*#
]]></source>
</section>
<section name="Odwołania">
<p>
W VTL występują trzy typy odwołań: zmienne, własności
i metody. Jako projektant wykorzystujący VTL musisz dojść
do porozumienia z programistami w kwestii nazewnictwa odwołań,
abyś mógł wykorzystywać je poprawnie w tworzonych przez siebie
szablonach.
</p>
<p>
Cokolwiek jest pobierane lub przekazywane do odwołania jest
traktowane jako łańcuch (String). Jeżeli pojawi się obiekt <em>$foo</em>
reprezentujący np. obiek typu Integer, Velocity wywoła jego metodę
<code>.toString()</code> abyuzyskać typ String.
</p>
<p>
<a name="Zmienne"><strong>Zmienne</strong></a>
<br/>
Notacja zmiennych składa się z prefiksu "$" po którym natępuje
<em>identyfikator</em> VTL. Identyfikator VTL musi rozpoczynać się
literą (a .. z lub A .. Z). Pozostałe znaki są ograniczone do:
</p>
<p>
<ul>
<li>liter (a .. z, A .. Z)</li>
<li>cyfr (0 .. 9)</li>
<li>myślnika ("-")</li>
<li>podkreślenia("_")</li>
</ul>
</p>
<p>
Kilka przykładów poprawnych identyfikatorów VTL:
</p>
<source><![CDATA[
$foo
$mudSlinger
$mud-slinger
$mud_slinger
$mudSlinger1
]]></source>
<p>
Gdy VTL odwołuje się do zmiennej, takiej jak <em>$foo</em>, może ona
uzyskać
wartość z dyrektywy <em>set</em> umieszczonej w szablonie lub z kodu Javy. Na przykłąd, jeżeli zmienna Javy
<em>$foo</em> ma wartość <em>bar</em> w momencie żądania wzorca,
<em>bar</em> zastępuje wszystkie wystąpienia <em>$foo</em> na stronie.
Jeżeli natomiast w szablonie umieścimy wyrażenie:
</p>
<source><![CDATA[
#set( $foo = "bar" )
]]></source>
<p>
Wynik będzie taki sam dla wszystkich wystąpień <em>$foo</em>
znajdujących
się po tej dyrektywie.
</p>
<p>
<a name="Własności"><strong>Własności</strong></a>
<br/>
Drugim rodzajem odwołań w VTL są własności (properties).
Notacja własności składa się z prefiksu <em>$</em>, po którym
następuje identyfikator VTL, po którym następuje kropka ("."), po
której pojawia się kolejny identyfikator VTL. Poniżej znajdują się
przykłady
prawidłowych własności w VTL:
</p>
<source><![CDATA[
$customer.Address
$purchase.Total
]]></source>
<p>
Przyjżyjmy się pierwszemu przykładowi <em>$customer.Address</em>.
Można go interpretować na dwa sposoby. Może oznaczać, Zajrzyj do
tablicy asocjacyjnej (Hashtable) <em>customer</em> i zwróć wartość
odpowiadającą kluczowi o wartości <em>Address</em>, ale
<em>$customer.Address</em>
może także oznaczać wywołanie metody (odwołania do metod zostanę
omówione
w następnej sekcji) <em>$customer.Address</em>, czyli być skrótem
wywołania
<em>$customer.getAddress()</em>. Gdy przychodzi żądanie strony,
mechanizm Velocity
określa, która z interpretacji ma sens i zwraca poprawną wartość.
</p>
<p>
<a name="Metody"><strong>Metody</strong></a>
<br/>
Metody są definiowane w kodzie Javy i wykonują pożyteczne czynności,
jak np. obliczenia lub podjęcie decyzji. Odwołania do metod składają się
z
prefiksu "$", po któym następuje identyfikatorVTL, po którym następuje
<em>Ciało Metody (Method Body)</em>. Ciało Metody w VTL składa się z
identyfikaotra po którym nastepuje lewy nawias ("("), po którym występuje
opcjonalnie lista parametrów wywołania, po której następuje pray nawias
(")").
Oto przykłady poprawnych odwołań do metod w VTL:
</p>
<source><![CDATA[
$customer.getAddress()
$purchase.getTotal()
$page.setTitle( "My Home Page" )
$person.setAttributes( ["Strange", "Weird", "Excited"] )
]]></source>
<p>
Dwa pierwsze przykłady -- <em>$customer.getAddress()</em>
i <em>$purchase.getTotal()</em> -- moga wyglądać podobnie do zamieszczonych w opisie własności, <em>$customer.Address</em> i
<em>$purchase.Total</em>. Jak zapewne zgadłeś, muszą być one
w jakiś sposób powiązane. I masz rację !
</p>
<p>
Notacja dla własności VTL może być używana jako skrótowa notacja
dla metod. Własność <em>$customer.Address</em> ma dokładnie taki
sam efekt jak metoda <em>$customer.getAddress()</em>. Generalnie
zaleca się używania własności, jeżeli jest to możliwe. Podstawową
różnicą pomiędzy metodami, a własnościami jest możliwość
wyspecyfikowania
listy parametów dla metody.
</p>
<p>
Skróconej notacji można użyć dla poniższych metod:
</p>
<source><![CDATA[
$sun.getPlanets()
$annelid.getDirt()
$album.getPhoto()
]]></source>
<p>
Możemy się spodziewać, że powyższe odwołania zwrócą listę planet,
nakarmią dżdżownicę (?), lub zwrócą fotografię z albumu. Natomiast dla
poniższych metod możliwe jest zastosowanie tylko pełnej notacji:
</p>
<source><![CDATA[
$sun.getPlanet( ["Earth", "Mars", "Neptune"] )
## Nie można przekazać parametrów z użyciem $sun.Planets
$sisyphus.pushRock()
## Velocity uzna, że mam na myśli $sisyphus.getRock()
$book.setTitle( "Homage to Catalonia" )
## Nie można przekazać listy parametrów
]]></source>
<p>
<a name="Formalna Notacja Odwołań"><strong>Formalna Notacja
Odwołań</strong></a>
<br/>
We wszystkich powyższych przykładach wykorzystywaliśmy notację
sróconą dla odwołańi. Istnieje jednak także notacja formalna, pokazana
poniżej:
</p>
<source><![CDATA[
${mudSlinger}
${customer.Address}
${purchase.getTotal()}
]]></source>
<p>
W większości przypadków będziesz używał notacji skróconej,
jednak może się zdażyć, że notacja formalna będzie konieczna
dla prawidłowego przetwarzania.
</p>
<p>
Wyobraź sobie, że budujesz w locie zdanie, gdzie
<em>$vice</em> ma zostać użyte jako podstawa słowotwórcza dla
rzeczownika.
Celem jest umożliwić wybór podstawy słowotwórczej i uzyskać jeden z
dwóch
możliwych rezultatów: "Jacek jest piromanem" lub "Jacek jest
kelptomanem".
Użycie notacji skróconej nie umożliwi realizacji tego zadania. Popatrz
na przykład:
</p>
<source><![CDATA[
Jacek jest $vicemanem.
]]></source>
<p>
Pojawia się niejednoznaczność i Velocity uzna, że zmienną jest
<em>$vicemanem</em>, a nie <em>$vice</em>, jak zamierzałeś.
Velocity nie odnajdzie wartości dla <em>$vicemanem</em> i zwróci
<em>$vicemanem</em> (tekst). Zastosowanie notacji formalnej
rozwiązuje ten problem.
</p>
<source><![CDATA[
Jacek jest ${vice}manem.
]]></source>
<p>
Teraz Velocity doskonale wie, że odwołaniem jest <em>$vice</em>,
a nie <em>$vicemanem</em>. Notacja formalna jest szczególnie przydatna,
gdy referencje w szablonie są "doklejane" bezpośrednio do tekstu.
</p>
<p>
<a name="Cicha Notacja Odwołań"><strong>Cicha Notacja
Odwołań</strong></a>
<br/>
Gdy mechaniz Velocity napoty podczas przetwarzania niezdefiniowane
odwołanie, domyślnym zachowaniem jest przeniesienie do wyniku "obrazu" referencji. Np. załóżmy, że poniższa referencja pojawia się w
treści szablonu:
</p>
<source><![CDATA[
<input type="text" name="email" value="$email"/>
]]></source>
<p>
Przy ładowaniu formularza refrencja do zmiennej
<em>$email</em> nie ma przypisanej wartości, jednak Twoją intencją
w tej sytuacji jest wyświtlenie pustego pola bez tekstu "$email". W tej sytuacji możesz użyć "Cichej" notacji, która zmieni domyślne
zachowanie Velocity. Zamiast użyć notacji <em>$email</em>
powinieneś napisać <em>$!email</em>. Tak, aby
powyższy przykład przyjął postać:
</p>
<source><![CDATA[
<input type="text" name="email" value="$!email"/>
]]></source>
<p>
Teraz, podczas ładowania formularza <em>$email</em> nadal
nie ma przypisanej wartości, jednak w wyniku pojawi się puste
pole zamiast pola z wartością "$email".
</p>
<p>
Poniższy przykład pokazuje jednoczesne wykorzytanie
notacji formalnej i "cichej".
</p>
<source><![CDATA[
<input type="text" name="email" value="$!{email}"/>
]]></source>
</section>
<section name="Uzyskiwanie literału">
<p>
VTL tarktuje specjalnie znaki <em>$</em> i <em>#</em>. Dlatego
powinieneś zwrócić szczególną uwagę na ich stosowanie w szablonie.
Ta sekcja poświęcona jest cytowaniu znaku <em>$</em>.
</p>
<p>
<a name="Waluta"><strong>Waluta</strong></a>
<br/>
Umieszczenie w tekście szablonu zdania "Kupiłem od farmera
worek ziemniaków za $2.50 !" nie stanowi problemu, ponieważ identyfikatory VTL zaczynają się zawsze od małej lub dużej litery.
Dlatego też $2.50 nie zostanie uznane przez Velocity za referencję.
</p>
<p>
<a name="Cytowania Odwołań VTL"><strong>Cytowania Odwołań
VTL</strong></a>
<br/>
Problem pojawia się, gdy istnieje szansa, że Velocity napotka
niejednoznaczność.
<em>Cytowanie</em> jest najlepszym sposobem obsługi specjalnych znaków
w treści szablonu. Do cytowania wykorzystywany jest znak odwróconego
ukośnika
(<em>\</em>).
</p>
<source><![CDATA[
#set( $email = "foo" )
$email
]]></source>
<p>
Jeżeli Velocity napotka w Twoim szablonie odwołania do
<em>$email</em>, postara się odszukać w kontekście
odpowiadającej mu wartości. W tym przypadku wynikiem będzie
<em>foo</em>, ponieważ <em>$email</em> jest zdefiniwane.
Jeżeli <em>$email</em> nie jest zdefiniowane, wyświetlony
zostanie tekst <em>$email</em>.
</p>
<p>
Przypuśćmy, że <em>$email</em> jest zdefiniowany (i ma wartość np.:
<em>foo</em>),
a Ty chcesz wyświetlić tekst <em>$email</em>. Jest kilka metod na
rozwiązanie tego
problemu, ale najprościej jest zacytować znak specjalny:
</p>
<source><![CDATA[
## Poniższa linia definiuje $email w szablonie
#set( $email = "foo" )
$email
\$email
\\$email
\\\$email
]]></source>
<p>
uzyskujemy rezultat:
</p>
<source><![CDATA[
foo
$email
\foo
\$email
]]></source>
<p>
Zauważ, że znak <em>\</em> jest przywiązaywany do <em>$</em>
od lewej strony. Zasada przywiązywania od lewej powoduje, że
<em>\\\$email</em>
w wyniku daje <em>\\$email</em>. Porównaj przykład z tym, w którym
<em>$email</em>
nie jest zdefiniowany:
</p>
<source><![CDATA[
$email
\$email
\\$email
\\\$email
]]></source>
<p>
uzyskujemy rezultat:
</p>
<source><![CDATA[
$email
\$email
\\$email
\\\$email
]]></source>
<p>
Zauważ, że Velocity inaczej traktuje refrencje zdefiniowane,
a inaczej niezdefiniowane. Poniżej dyrektywa set ustawia wartość
<em>$foo</em> na <em>gibbous</em>.
</p>
<source><![CDATA[
#set( $foo = "gibbous" )
$moon = $foo
]]></source>
<p>
W wyniku otrzymamy: <em>$moon = gibbous</em> -- gdzie <em>$moon</em>
zostało wyświetlone jako literał ponieważ <em>gibbous</em>
zostało podstawione zamiast <em>$foo</em>.
</p>
<p>
Możliwe jest także cytowanie dyrektyw VTL, co zostanie omówione
bardziej szczegółowo w sekcji Dyrektywy.
</p>
</section>
<section name="Case Substitution">
<p>
Teraz, gdy zapoznałeś się z odwołaniami, możesz wykorzystać
je efektywnie w swoich szablonach. Odwołania Velocity wykorzystują
kilka zalet języka Java, wygodnych do użycia podczas tworzenia szablonów.
Na przykład:
</p>
<source><![CDATA[
$foo
$foo.getBar()
##to samo co
$foo.Bar
$data.getUser("jon")
##to samo co
$data.User("jon")
$data.getRequest().getServerName()
## to samo co
$data.Request.ServerName
## to samo co
${data.Request.ServerName}
]]></source>
<p>
Przykłady te pokazują różne wykorzystanie tego samego odwołania.
Velocity wykorzytuje zalety mechanizmu introspekcji w Javie i możliwość
rozwiązania nazw odwołań zarówno na obiekty umieszczone w obiekcie
Context jaki i metody tych obiektów. Możliwe jest umieszczenie i
obliczenie
odwołań praktycznie w każdym miejscu szablonu.
</p>
<p>
Velocity, oparte o specyfikację Ziaren Javy (Beans) zdefiniowaną
przez Sun Microsystems, jest wrażliwe na wielkość liter. Jednakże
programiści Velocity włożyli dużo wysiłku aby przechwycić i skorygować
błędy użytkownika tam, gdzie tylko jest to możliwe.
Jeżeli w szablonie pojawia się odwołanie do metody <em>getFoo()</em>
w postaci <code>$bar.foo</code>, Velocity w pierwszej kolejnośc spróbuje
znaleźć metodę <code>$getfoo</code>, następnie (jeżeli próba się nie
powiedzie)
<code>$getFoo</code>. Podobnie jeżeli w szablonie znajduje się
odwołanie do
<code>$bar.Foo</code>, Velocity spróbuje <em>$getFoo()</em>, a następnie
<em>getfoo()</em>.
</p>
<p>
Uwaga: <em>Odwołania w szablonie do zmiennych instancji
nie są rozwiązywane. </em> Rozwiązywane są jedynie referencje do atrybutów odpowiadających metodom
ustawiającym/pobierającym (getters/setters) ziarna JavaBeans.
(np: <code>$foo.Name</code> jest rozwiązywane na metodę
<code>getName()</code> instancji obiektu Foo, a nie na zmienną publiczną
<code>Name</code> instancji Foo).
</p>
</section>
<section name="Dyrektywy">
<p>
Odwołania pozwalają twórcom szablonów na generację dynamicznej
zawartości dla serwisów WWW, podczas gdy <em>Dyrektywy</em>
-- proste do użycia elementy skryptowe pozwalające na modyfikacje
rezultatów uzyskiwanych z kodu Javy -- pozwalają projektantowi WWW
uzyskać rzeczywisty wpływ na wygląd i zawartość strony.
</p>
<a name="Set"><strong>#set</strong></a>
<p>
Dyrektywa <em>#set</em> pozwala przypisać wartość do
odwołania(referencji).
Wartość może być przypisana zarówno do zmiennej jak i własności i ma to
miejsce
wewnątrz nawiasów, jak na poniższym przykładzie:
</p>
<source><![CDATA[
#set( $primate = "monkey" )
#set( $customer.Behavior = $primate )
]]></source>
<p>
Lewa strona przypisania musi być odwołaniem do zmiennej lub własności.
Prawa strona natomiast może być jednego z niżej wymienionych typów:
</p>
<p>
<ul>
<li>Odwołanie do zmiennej</li>
<li>Łańcuch (String literal)</li>
<li>Odwołanie do własności</li>
<li>Odwołanie do metody</li>
<li>Wartość liczbowa (number literal)</li>
<li>ArrayList</li>
</ul>
</p>
<p>
Poniższe przykłady pokazują każdy z wymienionych typów.
</p>
<source><![CDATA[
#set( $monkey = $bill ) ## odwołanie do zmiennej
#set( $monkey.Friend = "monica" ) ## łańcuch
#set( $monkey.Blame = $whitehouse.Leak ) ## odwołanie do własności
#set( $monkey.Plan = $spindoctor.weave($web) ) ## odwołanie do metody
#set( $monkey.Number = 123 ) ##wartość liczbowa
#set( $monkey.Say = ["Not", $my, "fault"] ) ## ArrayList
]]></source>
<p>
UWAGA: W ostatnim przykładzie elementy zdefiniowane za pomocą operatora [..] są dostępne za pomocą metod zdefiniowanych w klasie
ArrayList.
Tak więc aby uzyskać pierwszy z elementów trzeba użyć:
$monkey.Sey.get(0).
</p>
<p>
Prawa strona wyrażenia może także być prostym wyrażeniem arytmetycznym:
</p>
<source><![CDATA[
#set( $value = $foo + 1 )
#set( $value = $bar - 1 )
#set( $value = $foo * $bar )
#set( $value = $foo / $bar )
]]></source>
<p>
Jeżeli prawa strona wyrażenia jest odwołaniem do własności lub metody
zwracającej wartość <em>null</em>, to <b>nie</b> zostanie ona przypisana
do
lewej strony wyrażenia. Za pomocą tego mechanizmu nie jest możliwe
usunięcie
z kontekstu referencji. Może to być mylące dla nowicjuszy Velocity. Na
przykład:
</p>
<source><![CDATA[
#set( $result = $query.criteria("name") )
Rezultatem pierwszego zapytania jest $result
#set( $result = $query.criteria("address") )
Rezultatem drugiego zapytania jest $result
]]></source>
<p>
Jeżeli <em>$query.criteria("name")</em> zwróci łańcuch
"bill" i <em>$query.criteria("address")</em> zwróci
<em>null</em>, rezultatem przetwarzania takiego szablonu
będzie:
</p>
<source><![CDATA[
Rezultatem pierwszego zapytania jest bill
Rezultatem drugiego zapytania jest bill
]]></source>
<p>
Taka sytacja może zdezorientować nowicjuszy, którzy w pętli
<em>#foreach</em> użyją <em>#set</em> do ustawienia wartości
poprzez odwołanie do własności lub metody, następnie bezpośrednio
po tym dokonają testu z użyciem dyrektywy <em>#if</em>, jak w
przykładzie:
</p>
<source><![CDATA[
#set( $criteria = ["name", "address"] )
#foreach( $criterion in $criteria )
#set( $result = $query.criteria($criterion) )
#if( $result )
Query was successful
#end
#end
]]></source>
<p>
W powyższym przykładzie nie jest szczęśliwym pomysłem polegać
na sprawdzeniu <em>$result</em>, by stwierdzić, że zapytanie zostało wykonane poprawnie. Po tym jak <em>$result</em> uzyskała
wartość (została dodana do kontekstu), nie można ponownie ustawić
jej wartości na <em>null</em> (czyli usunąć z kontekstu).
Szczegóły dotyczące dyrektyw <em>#if</em> oraz <em>#foreach</em>
są opisane w dalszej części tego dokumentu.
</p>
<p>
Jednym z rozwiązań tego problemu jest zainicjowanie
<em>$result</em> wartością <em>false</em>. W tym przypadku
gdy zawiedzie wywołanie <em>$query.criteria()</em> sprawdzenie
da oczekiwany rezultat.
</p>
<source><![CDATA[
#set( $criteria = ["name", "address"] )
#foreach( $criterion in $criteria )
#set( $result = false )
#set( $result = $query.criteria($criterion) )
#if( $result )
Query was successful
#end
#end
]]></source>
<p>
W odróżnieniu od wielu innych dyrektyw Velocity, <em>#set</em>
nie wymaga odpowiadającego <em>#end</em>.
</p>
<a name="Literały łańcuchowe"><strong>Literały łańcuchowe</strong></a>
<p>
Podczas użycia w dyrektywie <em>#set</em> łańcuchów ujętych
w cudzysłowym, wynik przetwarzania będzie miał postać jak w przykładzie:
</p>
<source><![CDATA[
#set( $directoryRoot = "www" )
#set( $templateName = "index.vm" )
#set( $template = "$directoryRoot/$templateName" )
$template
]]></source>
<p>
Rezultatem będzie
</p>
<source><![CDATA[
www/index.vm
]]></source>
<p>
Jeżeli natomiast łańcuch ujęty zostanie w apostrofy ('), nie będzie
przetworzony:
</p>
<source><![CDATA[
#set( $foo = "bar" )
$foo
#set( $blargh = '$foo' )
$blargh
]]></source>
<p>
Rezultatem będzie:
</p>
<source><![CDATA[
bar
$foo
]]></source>
<p>
Domyślnie opcja użycia apostrofów jest w Velocity włączona.
Domyślne zachowanie w tym względzie można zmienić edytując plik
<code>velocity.properties</code> ustawiając odpowiedni wpis na:
<code>stringliterals.interpolate=false</code>.
</p>
</section>
<section name="konstrukcja If-Else">
<strong>If / ElseIf / Else</strong>
<p>
Dyrektywa <em>#if</em> w Velocity pozwala umieścić tekst w wyniku
wtedy, gdy wyrażenie if przyjmie wartość true(prawda). Na przykład:
</p>
<source><![CDATA[
#if( $foo )
<strong>Velocity!</strong>
#end
]]></source>
<p>
Zmienna <em>$foo</em> jest testowan, dla sprawdzenia, czy
jej wrtością jest true (prawda), co mam miejsce przy spełnieniu
jednego
z dwóch waruków:(i) <em>$foo</em> jest typu boolean i posiada
wartość
true lub (ii) wartość nie jest wartością null. Należy zwrócić uwagę,
że Context
Velocity może zawierać jedynie obiekty, w związku z tym pisząc o
wartości
boolean mamy na myśli instancję klasy Boolean. Dotyczy to także
metod
zwracających wartości typu <code>boolean</code> - dzięki mechanizmą
introspekcji, zwrócona zostanie instancja <code>Boolean</code> z
taką samą
wartością logiczną.
</p>
<p>
Treść zawarta pomiędzy <em>#if</em> i odpowiadającym mu <em>#end</em>
zostanie dołączona do wyniku przetwarzania jeżeli testowana wartość
będzie
true (prawdą). W powyższym przykładzie jeżeli <em>$foo</em> posiada
wartość
logiczną true, to wynikiem będzie "Velocity!" w innym przypadku gdy
jest null lub
posiada wartość logiczną false, to wynik będzie pusty.
</p>
<p>
Elementy <em>#elseif</em> oraz <em>#else</em> mogą być wykorzystane
w połączeniu z <em>#if</em>. Zauważ, że Velocity Templating Engine
kończy
sprawdzanie warunków po znalezieniu pierwszego prawdziwego warunku.
W poniższym przykładzie załóżmy, że <em>$foo</em> posiada wartość 15
i <em>$bar</em> posiada wartość 6:
</p>
<source><![CDATA[
#if( $foo < 10 )
<strong>Go North</strong>
#elseif( $foo == 10 )
<strong>Go East</strong>
#elseif( $bar == 6 )
<strong>Go South</strong>
#else
<strong>Go West</strong>
#end
]]></source>
<p>W tym przykładzie <em>$foo</em> jest większe niż 10, dlatego też
pierwsze
dwa warunki zawiodąl. Następnie <em>$bar</em> jest porównywany z 6, co
daje prawdę
dlatego też wynikeim jest <strong>Go South</strong>.
</p>
<p>
Zwróć uwagę, że obecnie w Velocity porównania wartości liczbowych
są ograniczone do liczb całkowitych (Integers) - inne porównania zawsze
zwrócą <em>false</em>.
Jedynym wyjątkiem jest operator równości '==', w tym przypadku Velocity
wymaga, aby po
jednej i drugiej stroni wyrażenia znajdował się obiekt <em>tej
samej</em> klasy.
</p>
<p>
<a name="Operatory relacyjne i logiczne"><strong>Operatory relacyjne i
logiczne</strong></a>
</p>
<p>
Velocity wykorzystuje operator równości do ustalenia związku pomiędzy
zmiennymi.
Prosty przykład wykorzystania operatora równości zamieszczony jest
poniżej:
</p>
<source><![CDATA[
#set ($foo = "deoxyribonucleic acid")
#set ($bar = "ribonucleic acid")
#if ($foo == $bar)
W tym przypadku jest jasne, że nie są równe. Więc...
#else
Nie są równe i to będzie rezultat...
#end
]]></source>
<p>
Velocity udostępnia także operatory logiczne AND, OR i NOT.
Więcej informacji na ten temat zamieszczonych jest pod adresem:
<a href="vtl-reference-guide.html">VTL Reference Guide</a>
Poniżej zamieszczone są przykłady użycia wymienionych operatorów
logicznych:
</p>
<source><![CDATA[
## logical AND
#if( $foo && $bar )
<strong> This AND that</strong>
#end
]]></source>
<p>
Dyrektywa <em>#if()</em> uzyska wartość true tylko gdy
zarówno <em>$foo</em> jak i <em>$bar</em> będą miały wartość true.
Jeżeli <em>$foo</em> ma wartość false, całe wyrażenie przyjmie wartość
false. W tym przypadku wartość <em>$bar</em> nie będzie sprawdzana.
Jeżeli <em>$foo</em> ma wartość true to Velocity Templating Engine
sprawdzi wartość <em>$bar</em>. Jeżeli <em>$bar</em> ma wartość true,
to całe wyrażenie przyjmuje wartość true i na wyjściu pojawia się
<strong>This AND that</strong> Jeżeli <em>$bar</em>ma wartość false,
to całe wyrażenie przyjmuje wartość false i nic nie pojawia się na
wyjściu.
</p>
<p>
Operator logiczny OR działa podobnie, z tą różnicą, że wyrażenie
uzyskuje
wartość true, już gdy jeden z operandów ma wartość true.
Popatrzmy na przykład:
</p>
<source><![CDATA[
## logical OR
#if( $foo || $bar )
<strong>This OR That</strong>
#end
]]></source>
<p>
Jeżeli <em>$foo</em> ma wartość true, to Velocity Templating Engine
nie
potrzebuje sprawdzać wartości <em>$bar</em>. Niezależnie od wartości
<em>$bar</em> całe wyrażenie przyjmie wartość true i na wyjściu
pojawi się
<strong>This OR That</strong>. Gdy <em>$foo</em> ma wartość false,
musi nastąić sprawdzenie wartości <em>$bar</em>. Jeżeli
<em>$bar</em>
ma wartość false, to całe wyrażenie przyjmuje wartość false i nic
nie pojawia
się na wyjściu. Jeżeli <em>$bar</em> ma wartość true to całe
wyrażenie ma
wartość true i na wyjściu pojawi się <strong>This OR That</strong>.
</p>
<p>
Operator logiczny NOT przyjmuje tylko jeden argument:
</p>
<source><![CDATA[
##logical NOT
#if( !$foo )
<strong>NOT that</strong>
#end
]]></source>
<p>
Jeżeli <em>$foo</em> ma wartość true to <em>!$foo</em> uzyskuje
wartość false i nic nie pojawia się na wyjściu. W innym przypadku, gdy
<em>$foo</em>posiada wartość false, <em>!$foo</em> przyjmuje wartość
true
i na wyjściu pojawia się <strong>NOT that</strong>. Bądź ostrożny i nie
pomyl
tego operatora z <em>cichym odwołaniem $!foo</em>, które jest czymś
zupełnie innym.
</p>
</section>
<section name="Pętle foreach">
<strong>Pętle foreach</strong>
<p>
Element <em>#foreach</em> pozwala na tworzenie pętli. Na przykład:
</p>
<source><![CDATA[
<ul>
#foreach( $product in $allProducts )
<li>$product</li>
#end
</ul>
]]></source>
<p>
Pętla <em>#foreach</em> pozwala na iteracje po wszystkich produktach
zawartych w liście(obiekcie) <em>$allProducts</em>. Dla każdej iteracji
kolejna wartość z <em>$allProducts</em> jest pobierana i umieszczana
w zmiennej <em>$product</em>.
</p>
<p>
Zawartością zmiennej <em>$allProducts</em> jest Vector, Hashtable
lub tablica. Wartość przypisana <em>$product</em> jest obiektem
Javy i jako do takiego możemy się do niego odwoływać poprzez zmienną.
Na przykład: jeżeli <em>$product</em> byłby instancją klasy Product w
kodzie
Javy, moglibyśmy uzyskać jego nazwę poprzez odwołanie do metody
<em>$product.Name</em> (czyli: <em>$Product.getName()</em>).
</p>
<p>
Jeżeli <em>$allProducts</em> jest instancją Hashtable i chcesz
uzyskać zarówno klucze jak i odpowiadające im wartości, możesz
użyć takiego kawałka kodu:
</p>
<source><![CDATA[
<ul>
#foreach( $key in $allProducts.keySet() )
<li>Key: $key -> Value: $allProducts.get($key)</li>
#end
</ul>
]]></source>
<p>
Velocity udostępnia w pętli licznik iteracji, dzięki czemu możesz
zrobić coś takiego:
</p>
<source><![CDATA[
<table>
#foreach( $customer in $customerList )
<tr><td>$velocityCount</td><td>$customer.Name</td></tr>
#end
</table>
]]></source>
<p>
Domyślną nazwą licznika iteracji, zdefiniowaną w pliku
velocity.properties,
jest $velocityCount. Domyślnie licznik iteracji zaczyna liczenie od 1,
jednak
w pliku <code>velocity.properties</code> możesz zmienić tą wartość na 0.
Poniżej przedstawiamy odpowiednią sekcję w pliku
<code>velocity.properties</code>:
</p>
<source><![CDATA[
# Domyśłna nazwa licznika iteracji
directive.foreach.counter.name = velocityCount
# Domyślna wartość początkowa licznika iteracji
directive.foreach.counter.initial.value = 1
]]></source>
</section>
<section name="Include">
<p>
Element <em>#include</em> pozwala na włączenie do wyniku przetwarzania
pliku z systemu plików, w miejscu wystąpienia dyrektywy
<em>#include</em>,
Zawartość pliku nie jest przetwarzana przez mechanizm Velocity. Z
powodów
bezpieczeństwa włączane pliki mogą znajdować się jedynie w
TEMPLATE_ROOT.
</p>
<source><![CDATA[
#include( "one.txt" )
]]></source>
<p>
Pliki które mają być włącznone za pomocą dyrektywy <em>#include</em>
są ujmowane w cudzysłowy. Jeżeli włączony ma być więcej niż jeden plik
nazwy plików należy oddzielić przcinkami.
</p>
<source><![CDATA[
#include( "one.gif","two.txt","three.htm" )
]]></source>
<p>
Nie jest wymagane podawanie bezpośrednio nazw plików, zamiast
tego można posłużyć się zmiennymi, co jest zalecane. Dzięki temu można
łatwo modyfikować wynik przetwarzania na podstawie parametrów
dostarczonych w żądaniu. Poniższy przykład pokazuje jednocześnie
zastosowanie nazwy pliku i zmiennej:
</p>
<source><![CDATA[
#include( "greetings.txt", $seasonalstock )
]]></source>
</section>
<section name="Parse">
<p>
Element <em>#parse</em> pozwala projektantowi szablonu
zaimportować lokalny plik zawierający elementy VTL. Velocity
przetworzy elementy VTL i dołączy do wyniku przetwarzanego szablonu.
</p>
<source><![CDATA[
#parse( "me.vm" )
]]></source>
<p>
Tak samo jak <em>#include</em> dyrektywa, <em>#parse</em> może przyjąć
zmienną zamiast nazwy szablonu. Wszystkie szablony do których odwołuje
się
<em>#parse</em> muszą znajdować się w TEMPLATE_ROOT. W odróżnieniu
od <em>#include</em> dyrektywa <em>#parse</em> przyjmuje tylko
pojedynczy
argument.
</p>
<p>
Szablony VTL mogą zawierać dyrektywę <em>#parse</em> odwołującą
się do szablonów zawierających dyrektywę <em>#parse</em> i tak dalej.
Linia <em>parse_directive.maxdepth</em>, domyślnie ustawiona na wartość
10,
w pliku <code>velocity.properties</code> określa maksymalną głebokość
odwołań
<em>#parse</em> z pojedynczego szablonu. (Uwaga: w przypadku braku wpisu
<em>parse_directive.maxdepth</em> w pliku
<code>velocity.properties</code>,
Velocity przyjmie wartość domyślną 10.) Dopuszczalna jest także rekursja
(rekurencja):
na przykład szablon <code>dofoo.vm</code> zawiera linie:
</p>
<source><![CDATA[
Count down.
#set( $count = 8 )
#parse( "parsefoo.vm" )
All done with dofoo.vm!
]]></source>
<p>
Następuje tu odwołanie do szablonu <code>parsefoo.vm</code>, który
zawiera następujący VTL:
</p>
<source><![CDATA[
$count
#set( $count = $count - 1 )
#if( $count > 0 )
#parse( "parsefoo.vm" )
#else
All done with parsefoo.vm!
#end
]]></source>
<p>
Po wyświetleniu "Count down." Velocity przetworzy
<code>parsefoo.vm</code>,
zliczając od 8 w dół. Gdy licznik osiągnie wartość 0, wyświetlone
zostanie
"All done with parsefoo.vm". Velocity powróci do <code>dofoo.vm</code>
i wyświetli "All done with dofoo.vm!".
</p>
</section>
<section name="Stop">
<p>
Element <em>#stop</em> pozwala na zatrzymanie przetwarzania wzorca
i wyjście. Dyrektywa ta jest przydatna podczas usuwania błędów
(debuggingu).
</p>
<source><![CDATA[
#stop
]]></source>
</section>
<section name="Velocimakra">
<p>
Element <em>#macro</em> pozwala projektantowi zdefiniować
powtarzający się segment szablonu VTL. Velocimakra są użyteczne
w bardzo wielu zastosowaniach. Poniższe Velocimakro zostało zdefiniowane w celi uniknięcia klepania w klawisze i literówek oraz
dla wprowadzenia w zagadnienie Velocimakr.
</p>
<source><![CDATA[
#macro( d )
<tr><td></td></tr>
#end
]]></source>
<p>
W tym przykładzie zdefiniowano makro <em>d</em>. Teraz można się do
niego odwolywać w sposób analogiczny jak do innych dyrektyw VTL:
</p>
<source><![CDATA[
#d()
]]></source>
<p>
Podczas przetwarzania szabonu Velocity zastąpi <em>#d()</em>
wierszem tabeli z jedną pustą komórką.
</p>
<p>
Velocimakro może przyjmować dowolną liczbę argumentow -- także
zero jak w powyższym przykładzie -- jednak wywołanie makra musi się
odbyć z dokładnie taką samą liczbą argumentów jak w definicji makra.
Velocimakra mogą być znacznie bardziej skomplikowane niż w pokazanym
powyżej przykładzie. Poniżej pokazano makro przyjmujące dwa argumenty:
kolor i tablicę:
</p>
<source><![CDATA[
#macro( tablerows $color $somelist )
#foreach( $something in $somelist )
<tr><td bgcolor=$color>$something</td></tr>
#end
#end
]]></source>
<p>
Zdefiniowane powyżej makro <em>tablerows</em> pobiera dwa argumenty.
Pierwszy zostaje podstawiony za <em>$color</em>, drugi za
<em>$somelist</em>
</p>
<p>
Wszystko co może znaleźć się w szablonie VTL może także zostać
umieszczone
w ciele Velocimakra. W pokazanym makrze <em>tablerows</em> znajduje się
pętla <em>foreach</em> oraz dwa elementy <em>#end</em>. Pierwszy zamyka
pętlę <em>foreach</em> drugi definicję makra.
</p>
<source><![CDATA[
#set( $greatlakes = ["Superior","Michigan","Huron","Erie","Ontario"] )
#set( $color = "blue" )
<table>
#tablerows( $color $greatlakes )
</table>
]]></source>
<p>
Zauważ, że <em>$greatlakes</em> zostaje podstawione za
<em>$somelist</em>. Efektem przetworzenia szablonu z takim
wywołaniem makra <em>#tablerows</em> jest:
</p>
<source><![CDATA[
<table>
<tr><td bgcolor="blue">Superior</td></tr>
<tr><td bgcolor="blue">Michigan</td></tr>
<tr><td bgcolor="blue">Huron</td></tr>
<tr><td bgcolor="blue">Erie</td></tr>
<tr><td bgcolor="blue">Ontario</td></tr>
</table>
]]></source>
<p>
Velocimakro może być zdefiniowane <em>wewnątrz</em> szablonu
i w takiej sytuacji nie jest ono dostępne dla innych szablonów tej
samej aplikacji. Zdefiniowanie Velocimakra tak, aby było współdzielone
niesie ze sobą oczywiste korzyści: ogranicza konieczność definiowania
Velocimakra wielokrotnie w różnych szablonach, co redukuje szanse
na popełnienie błedu, zmniejsza pracochłonność i pozwala na dokonywanie
modyfikacji w jednym miejscu dla wielu szablonów.
</p>
<p>
Jeżeli zdefiniujemy makro <em>#tablerows($color $list)</em> w bibliotece
Velocimakr, to makro będzie mogło być wykorzystywane w dodwolnym
szablonie. Można je wykorzystywać wielokrotnie i w różnych celach.
W szablonie <code>mushroom.vm</code> poświęconemu grzybom,
makro <em>#tablerows</em> może być użyte do wypisania elementów
typowego muchomora:
</p>
<source><![CDATA[
#set( $parts = ["volva","stipe","annulus","gills","pileus"] )
#set( $cellbgcol = "#CC00FF" )
<table>
#tablerows( $cellbgcol $parts )
</table>
]]></source>
<p>
Podczas obsługi żądania o <code>mushroom.vm</code> Velocity
odszuka definjicję makra <em>#tablerows</em> w bibliotece
(zdefiiowanej w pliku <code>velocity.properties</code>) i wygeneruje
następujący wynik:
</p>
<source><![CDATA[
<table>
<tr><td bgcolor="#CC00FF">volva</td></tr>
<tr><td bgcolor="#CC00FF">stipe</td></tr>
<tr><td bgcolor="#CC00FF">annulus</td></tr>
<tr><td bgcolor="#CC00FF">gills</td></tr>
<tr><td bgcolor="#CC00FF">pileus</td></tr>
</table>
]]></source>
<strong>Argumenty Velocimakr</strong>
<p>
Velocimakra mogą przyjmować jako argumenty następujące
elementy VTL:
</p>
<ul>
<li>
Odwołania : wszystko zaczynające się od '$'
</li>
<li>
Łańcuch : coś jak "$foo" lub 'hello'
</li>
<li>
Wartość liczbową : 1, 2 etc
</li>
<li>
zakres liczb całkowitych : [ 1..2] lub [$foo .. $bar]
</li>
<li>
tablicę obiektów : [ "a", "b", "c"]
</li>
<li>
logiczne true (prawda)
</li>
<li>
logiczne false (fałsz)
</li>
</ul>
<p>
Przekazując odwołanie jako argument do Velocimakra
zwróć uwagę, że przekazanie odbywa się "przez nazwę",
Oznacza to, że wartość odwołania jest "generowana" przy
każdym użyciu w Velocimakrze. Pozwala to po przekazaniu do makra odwołania do metody, na jej wywołanie przy każdym wystąpieniu
odwołania w makrze. Na przykład wywołanie następującego makra:
</p>
<source><![CDATA[
#macro( callme $a )
$a $a $a
#end
#callme( $foo.bar() )
]]></source>
<p>
powoduje trzykrotne wywołanie metody bar() do
której odwołaniem jest $foo.
</p>
<p>
Na pierwszy rzut oka wydaje się to zaskakujące, jednak
gdy zastanowisz się nad intecjami leżącymi u podstaw
Velocimakr -- wyeliminowaniu powielania powtarzających
się fragmentów VTL metodą kopiuj wklej -- nabiera to sensu.
Pozwala to np. na na przekazywanie obiektu pamiętającego swój
stan, jak np. obiekt zwracający naprzemiennie kolory do kolorowania
tabelki, jako argumentu makra.
</p>
<p>
Jeżeli chcesz ominąć to zachowanie makr, możesz zawsz
przypisać wartość zwracaną przez metodę do nowego
odwołania i użyć go jako argumentu makra:
</p>
<source><![CDATA[
#set( $myval = $foo.bar() )
#callme( $myval )
]]></source>
<strong>Własności Velocimakr</strong>
<p>
Kilka linii w pliku <code>velocity.properties</code> ułatwia elstyczną
implementację Velocimakr. Są one także udokumentowane w <a href="developer-guide.html">Developer Guide</a>.
</p>
<p>
<code>velocimacro.library</code> - lista oddzielonych przecinkamil
bibliotek Velocimakr. Domyślnie Velocity szuka jednej biblioteki:
<em>VM_global_library.vm</em>. Ścieżka szablonów jest używana
do odszukania bibliotek Velocimakr.
</p>
<p>
<code>velocimacro.permissions.allow.inline</code> - ta własność,
przyjmująca wartości true lub false, okreśła, czy Velocimakra mogą
być definiowane w zwykłych szablonach. Domyślna wartość true pozwala
projektantowi umieszczać makra wewnątrz zwykłych szablonów.
</p>
<p>
<code>velocimacro.permissions.allow.inline.to.replace.global</code> -
przyjmująć wartość true lub false określa, czy makro zdefiniowane
wewnątrz szablonu może nadpisać makro zdefiniowane globalnie,
w szablonie załadowanym przy starcie, zgodnie z własnością
<code>velocimacro.library</code>. Domyślnie ustawiona wartość
<code>false</code>, zapobiega nadpisywaniu makr globalnych przez
makra zdefiniowane wewnątrz szablonu.
</p>
<p>
<code>velocimacro.permissions.allow.inline.local.scope</code> -
przyjmując wartości true lub false określa, czy makra zdefiniowane
w szablonie są "widoczne" tylko w obrębie definiującego szablonu.
Innymi słowy: wartość ustawiona na true powoduje, że makro może
być użyte tylko w obrębie szablonu, w którym jest zdefiniowane.
Tej funkcjonalności można użyć do ciekawych trików. Jeżeli makro
globalne wywołuje inne makro globalne, możesz zdefiniować w szablonie
inną implementację drugiego makra, która zostanie wywołana przez
pierwsze
makro. W pozostałych szablonach wykonana zostanie globalna definicja
drugiego makra.
</p>
<p>
<code>velocimacro.context.localscope</code> - przyjmuje wartości
true lub false - domyślnie false. Ustawienie wartości true powoduje, że
dyrektywy w #set() są traktowane jako lokalne w obrębie makra i nie
wpływają
na kontekst.
</p>
<p>
<code>velocimacro.library.autoreload</code> - ta własność kontroluje
automatyczne ładowanie bibliotek Velocimakr. Domyślną wartością jest
<code>false</code>. Jeżeli ustawimy wartość <code>true</code>
biblioteka zawierająca wywoływane makro jest sprawdzana pod kątem
zmian i w razie potrzeby przeładowywana. Pozwala to na modyfikację
i testowanie makr "w biegu" bez konieczności restartu aplikacji i
kontenera
serwletów, jak w przypadku zwykłych szablonów. Ten tryb będzie działał
tylko z <i>wyłączonym</i> cachingiem resource loadera
(tzn. <code>file.resource.loader.cache = false</code>). Funkcja ta
przeznaczona
jest raczej do celów developerskich niż produkcyjnych.
</p>
<strong>Velocimacro Trivia</strong>
<p>
Obecnie Velocimakro musi być zdefiniowane przed pierwszym
wykorzystaniem w szablonie. W praktyce oznacza to, że Twoje
deklaracje #macro() musząi wystąpić przed wykorzystaniem Velocimakr.
</p>
<p>
Trzeba o tym pamiętać, gdy wywołujesz w szablonie
#parse() do włączenia szablonu posiadającego makra.
#parse jest wywoływane w trakcie przetwarzania , natomiast
analizator(parser) decyduje, co jest odwołaniem do makra
w czasie analizy(parsowania) (tłum.: czyli wcześniej) szablonu.
W związku z tym w takiej sytuacji możesz uzyskać nieoczekiwane
rezultaty. Obejście tego problemu polega na zastosowaniu
<code>velocimacro.library</code>, czyli załadowaniu Twoich makr
przy starcie.
</p>
</section>
<section name="Cytowanie dyrektyw VTL">
<p>
Dyrektywy VTM moga być cytowane przy użyciu znaku ("\")
podobnie jak odwołania VTL.
</p>
<source><![CDATA[
## #include( "a.txt" ) daje w wyniku <zawartość a.txt>
#include( "a.txt" )
## \#include( "a.txt" ) rdaje w wyniku \#include( "a.txt" )
\#include( "a.txt" )
## \\#include ( "a.txt" ) daje w wyniku \<zawartość a.txt>
\\#include ( "a.txt" )
]]></source>
<p>
Należy zwrócić szczególną uwagę na cytowanie dyrektyw VTL zawierających
wiele elementów skryptowych w jednej dyrektywie (takich jak if-else-end).
Typowe wyrażenie if VTL:
</p>
<source><![CDATA[
#if( $jazz )
Vyacheslav Ganelin
#end
]]></source>
<p>
Jeżeli <em>$jazz</em> jest prawdą, na wyjściu pojawi się:
</p>
<source><![CDATA[
Vyacheslav Ganelins
]]></source>
<p>
Jeżeli <em>$jazz</em> jest fałszem, nic nie pojawi się na wyjściu.
Cytowanie elementów
może zmienić rezultat. Rozpatrzmy następujący przypadek.
</p>
<source><![CDATA[
\#if( $jazz )
Vyacheslav Ganelin
\#end
]]></source>
<p>
Niezależnie od wartości <em>$jazz</em> wynikiem będzie:
</p>
<source><![CDATA[
#if($ jazz )
Vyacheslav Ganelin
#end
]]></source>
<p>
W rzeczywistości ze względu na zacytowanie wszystkich dyrektyw
wartość <em>$jazz</em> nie jest rozpatrywana. Załóżmy, że backslash
poprzedza zacytowaną dyrektywę:
</p>
<source><![CDATA[
\\#if( $jazz )
Vyacheslav Ganelin
\\#end
]]></source>
<p>
W tym przypadku jeżeli <em>$jazz</em> ma wartość true, wynikiem jest:
</p>
<source><![CDATA[
\ Vyacheslav Ganelin
\
]]></source>
<p>
Dla zrozumienia tego faktu, zwróć uwagę, że <code>#if( arg ) </code>
jest zakończone znakiem nowej linii (enterem), ale nie zamieści znaku
nowej
linii w wyniku. Ciało <code>#if()</code> znajduje się za pierwszym "\"
otrzymanym z cytowania "\\" porzedzającego <code>#if()</code>.
Ostatni "\" jest w innej lini niż tekst, ponieważ za "Ganelin" znajduje
sie znak nowej
linii. Ostatnie "\\" poprzedazające <code>#end</code> jest więc częścią
bloku.
</p>
<p>
Jeżeli <em>$jazz</em> jest fałszem, nic nie pojawi się w wyniku. Zwróć
uwagę, że wynik zaczyna się "rozsypywać" gdy nieprawidłowo zacytujesz
dyrektywy.
</p>
<source><![CDATA[
\\\#if( $jazz )
Vyacheslave Ganelin
\\#end
]]></source>
<p>
W tym przykładzie <em>#if</em> jest zacytowane, a <em>#end</em> nie jest.
Spowoduje to błedy przy analizie(parsowaniu) szablonu. Ze względu na
brakujące
<em>#end</em>.
</p>
</section>
<section name="VTL: zagadnienia związane z formatowaniem">
<p>
Jakkolwiek VTL przedstawiany w tym przewodniu jest pokazywany
ze znakami nowej linii i spacjami, to poniższy VTL:
</p>
<source><![CDATA[
#set( $imperial = ["Munetaka","Koreyasu","Hisakira","Morikune"] )
#foreach( $shogun in $imperial )
$shogun
#end
]]></source>
<p>
jest tak samo poprawny jak poniższy kawałek kodu
nadesłany do gupy dsykusyjnej velocity przez Geir Magnusson Jr.
w związku z zupełnie innym problemem:
</p>
<source><![CDATA[
Send me #set($foo = ["$10 and ","a cake"])#foreach($a in $foo)$a #end
please.
]]></source>
<p>
W rzeczywistości Velocity "zjada" nadmiar spacji i znaków
niedrukowanych (whitespaces).
Powyższy przykład może być zapisany jako:
</p>
<source><![CDATA[
Send me
#set( $foo = ["$10 and ","a cake"] )
#foreach( $a in $foo )
$a
#end
please.
]]></source>
<p>
lub jako
</p>
<source><![CDATA[
Send me
#set($foo = ["$10 and ","a cake"])
#foreach ($a in $foo )$a
#end please.
]]></source>
<p>
W każdym przypadku uzyskamy identyczny rezultat.
</p>
</section>
<section name="Różności">
<subsection name="Obliczenia">
<p>
Velocity dysponuje zestawem użytecznych funkcji matemtycznych
do użycia z dyrektywą <em>set</em>. Poniższe przykłady pokazują kolejno
dodawanie, odejmowanie, mnożenie i dzielenie:
</p>
<source><![CDATA[
#set( $foo = $bar + 3 )
#set( $foo = $bar - 4 )
#set( $foo = $bar * 6 )
#set( $foo = $bar / 2 )
]]></source>
<p>
Rezultatem dzielenia jest zawsze liczba całkowita.
Reszta z dzielenia może byc uzyskana za pomocą operatora
dzielenia modulo: (<em>%</em>).
</p>
<source><![CDATA[
#set( $foo = $bar % 5 )
]]></source>
<p>
W Velocity w działaniach matematycznych dopuszczalne są
jedynie wartości całkowite (...-2, -1, 0, 1, 2...) Jeżeli użyte zostaną
wartości niecałkowite zosatanie to odnotowane w logu i rezultatem
będzie wartość pusta (null).
</p>
</subsection>
<subsection name="Operator zakresu">
<p>
Operatory zakresu mogą być wykorzystywane w połączeniu
z dyrektywą <em>#set</em> i <em>#foreach</em>. Operator zakresu
umozliwia łatwe wygenerowanie tablicy zawierającej kolejne wartości
całkowite. Poniżej przedstawiono konstrukcję operatora zakresu:
</p>
<source><![CDATA[
[n..m]
]]></source>
<p>
Zarówno <em>n</em> i <em>m</em> muszą być wartościami całkowitymi
lub dawać wartość całkowitą. Nie ma znaczenia, która wartość m czy n
będzie większa. Jeżeli n będzie większe Velocity będzie odliczać w dół.
Poniżej przedstawione są przykłady użycia operatora zakresu:
</p>
<source><![CDATA[
Pierwszy przykład:
#foreach( $foo in [1..5] )
$foo
#end
Drugi przykład:
#foreach( $bar in [2..-2] )
$bar
#end
Trzeci przykład:
#set( $arr = [0..1] )
#foreach( $i in $arr )
$i
#end
Czwarty przykład:
[1..3]
]]></source>
<p>
Wynikami będą:
</p>
<source><![CDATA[
Pierwszy przykład:
1 2 3 4 5
Drugi przykład:
2 1 0 -1 -2
Trzeci przykład:
0 1
Czwarty przykład:
[1..3]
]]></source>
<p>
Wynikiem działania operatora zakresu jest tablica tylko w połączeniu
z dyrektywą <em>#set</em> i <em>#foreach</em>, jak w czwartym
przykładzie.
</p>
<p>
Operator zakresu jest bardzo użyteczny, gdy tworzymy tabelę o stałym rozmiarze, jednak nie zawsze posiadamy dane, aby ją w całości wypełnić.
</p>
</subsection>
<subsection name="Zagadnienia zaawansowane: Cytowanie i znak !">
<p>
Jeżeli odwołanie występuje z opcją "ciechego cytowania" <em>!</em>
i znak <em>!</em> jest poprzedzony znakiem cytowania <em>\</em> to
odwołanie jest traktowane w specjalny sposób. Zauważ różnicę, pomiędzy
zwyklym cytowaniem, a takim w którym <em>\</em> poprzedza <em>!</em>:
</p>
<source><![CDATA[
#set( $foo = "bar" )
$\!foo
$\!{foo}
$\\!foo
$\\\!foo
]]></source>
<p>
Wynikiem jest:
</p>
<source><![CDATA[
$!foo
$!{foo}
$\!foo
$\\!foo
]]></source>
<p>
Porównaj to ze zwykłym cytowaniem, gdzie <em>\</em> poprzedza
<em>$</em>:
</p>
<source><![CDATA[
\$foo
\$!foo
\$!{foo}
\\$!{foo}
]]></source>
<p>
Wynikiem jest:
</p>
<source><![CDATA[
\$foo
\$!foo
\$!{foo}
\bar
]]></source>
</subsection>
<subsection name="Różności Velocimakr">
<p>
Poniższa sekcja stanowi mini-FAQ na tematy związane z Velocimakrami.
Będzię się ona zminiała, więc warto czasami poszukać tutaj nowych
informacji.
</p>
<p>
Uwaga : w tej sekcji będziemy często odwoływać się do 'Velocimakro'
poprzez skrót 'VM'.
</p>
<strong>Czy mogę użyć dyrektywy lub innego VM jako argumentu dla VM
?</strong>
<p>
Przykład : <code>#center( #bold("hello") )</code>
</p>
<p>
Nie, dyrektywa nie jest poprawnym argumentem dyrektywy, a z przyczyn
praktycznych VM jest dyrektywą.
</p>
<p>
<i>Jakkolwiek...</i>, można sobie poradzić. Jednym z prostszych rozwiązań
jest uwzględnienie faktu, że 'ujęcie w apostrofy' (") przetwarza ich
zawartość. Możesz
więc zrobić coś takiego:
</p>
<source><![CDATA[
#set($stuff = "#bold('hello')" )
#center( $stuff )
]]></source>
<p>
Lub oszczędniej...
</p>
<source><![CDATA[
#center( "#bold( 'hello' )" )
]]></source>
<p>
Warto zauważyć, że w ostatnim przykładzie argument
jest wyliczany <i>wewnątrz</i> VM, a nie przy wywołaniu.
Czyli argument jest przekazywany w całości do VM
i obliczany wewnątrz VM. Dzięki temu można zrobić tak:
</p>
<source><![CDATA[
#macro( inner $foo )
inner : $foo
#end
#macro( outer $foo )
#set($bar = "outerlala")
outer : $foo
#end
#set($bar = 'calltimelala')
#outer( "#inner($bar)" )
]]></source>
<p>
Na wyjściu pojawi się:
</p>
<source><![CDATA[
Outer : inner : outerlala
]]></source>
<p>
ponieważ obliczenie "#inner($bar)" następuje wewnątrz #outer(),
dlatego też użyta zostanie wartość $bar ustawiona wewnątrz #outer().
</p>
<p>
Jest to zaplanowana i pilnie strzeżona funkcja Velocity - argumenty są
przekazywane "przez nazwę". Dzięki temu można je traktować jako
odwołania z zachowniem stanu:
</p>
<source><![CDATA[
#macro( foo $color )
<tr bgcolor=$color><td>Hi</td></tr>
<tr bgcolor=$color><td>There</td></tr>
#end
#foo( $bar.rowColor() )
]]></source>
<p>
Dzięki temu rowColor() jest wywoływane wielokrotnie, a nie tylko raz.
Jeżli chcesz tego uniknąć, to wywołaj metodę na zewnątrz makra
i przekaż do niego wartość.
</p>
<source><![CDATA[
#set($color = $bar.rowColor())
#foo( $color )
]]></source>
<strong>Czy mogę zarejestrować Velocimakro via #parse() ? </strong>
<p>
Obecnie Velocimakram, muszą być zdefiniowane przed pierwszym
użyciem w szblonie, w związku z tym Twoje #macro() musi się pojawić
przed użyciem VM.
</p>
<p>
Trzeba o tym pamiętać, gdy wywołujesz w szablonie
#parse() do włączenia szablonu posiadającego makra.
#parse jest wywoływane w trakcie przetwarzania , natomiast
analizator(parser) decyduje, co jest odwołaniem do makra
w czasie analizy(parsowania) (tłum.: czyli wcześniej) szablonu.
W związku z tym w takiej sytuacji możesz uzyskać nieoczekiwane
rezultaty. Obejście tego problemu polega na zastosowaniu
<code>velocimacro.library</code>, czyli załadowaniu Twoich makr
przy starcie.
</p>
<strong>Co to jest Velocimacro Autoreloading?</strong>
<p>
Istnieje własność przeznaczona do użycia podczas
<i>tworzenia i testowania</i>, nie w produkcji:
</p>
<p>
<code>velocimacro.library.autoreload</code>
</p>
<p>
Domyślnie jest ustawiona na false. Jeżeli ustawisz ją na true <em>razem
z</em>
</p>
<p>
<code><type>.resource.loader.cache = false</code>
</p>
<p>
(gdzie <type> jest nazwą resource loader'a którego używasz,
np. 'file') wtedy Velocity przeładuje zmiany których dokonałeś w
bibliotekach Velocimakr tak, że nie będziesz musiał restartować
kontenera serwletów czy też aplikacji, lub wykonywać inne
kombinacje aby udostępnić zmiany.
</p>
<p>
Poniżej prosty przykład zestawu parametrów konfiguracyjnych.
</p>
<source><![CDATA[
file.resource.loader.path = templates
file.resource.loader.cache = false
velocimacro.library.autoreload = true
]]></source>
<p>
Nie pozostawiaj takiego zestawu w środowisku produkcyjnym.
</p>
</subsection>
<subsection name="Łączenie (konkatenacja) łańcuchów">
<p>
Często zadawanym przez twórców pytaniem jest:
<i>W jaki sposób dokonać konkatenacji łańcuchów ?
Czy istnieje coś analogicznego do operatora "+" w Javie ?</i>
</p>
<p>
Aby dokonać konkatenacji odwołań VTL musisz je
zestawić razem. Przy czym istotny jest kontekst
w którym tego dokonasz, dlatego też zilustrujemy
to przykładami.
</p>
<p>
W typowej 'mieszance' szablonu (gdy mieszasz VTL ze
zwykłą zawartością) :
</p>
<source><![CDATA[
#set( $size = "Big" )
#set( $name = "Ben" )
The clock is $size$name.
]]></source>
<p>
wynikiem będzie 'The clock is BigBen'.
Ciekawszy przykład pokazuje przypadek, gdy chcesz połączyć łańcuchy
aby przekazać wynik połączenia do metody lub ustawić wartość
nowego odwołania. Zróbmy po prostu tak:
</p>
<source><![CDATA[
#set( $size = "Big" )
#set( $name = "Ben" )
#set($clock = "$size$name" )
The clock is $clock.
]]></source>
<p>
Co zaowocuje identycznym rezultatem. W finalnym przykładzie,
jeżeli chcesz mieszać "statyczne" łańcuchy z odwołaniami, być
może będziesz musiał użyć odwołań formalnych:
</p>
<source><![CDATA[
#set( $size = "Big" )
#set( $name = "Ben" )
#set($clock = "${size}Tall$name" )
The clock is $clock.
]]></source>
<p>
Wynikiem jest 'The clock is BigTallBen'. Odwołanie formalne
jest potrzebne aby parser wiedział, że chodzi Ci o odwołanie
"$size", a nie "$sizeTall", co by się stało bez umieszczenia znaków "{}".
</p>
</subsection>
</section>
<section name="Uwagi czytelników">
<p>
Jeżeli znalazłeś błędy w tym dokumencie lub chcesz przekazać
inne uwagi związane z Velocity User Guide, napisz na adres:
<a href="mailto:velocity-user@jakarta.apache.org">Velocity user
list</a>.
Dzięki !
</p>
</section>
</body>
</document>
-------------------------------------------
Artur Konrad Kuliński
-------------------------------------------
***********************************************************************************************
The information contained in this message or any of its attachments may be confidential and is intended for the exclusive use of the addressee(s). Any disclosure, reproduction, distribution or other dissemination or use of this communication is strictly prohibited without the express permission of the sender. The views expressed in this email are those of the individual and not necessarily those of Sony or Sony affiliated companies. Sony email is for business use only.
This email and any response may be monitored by Sony United Kingdom Limited.
(04)
***********************************************************************************************
--
To unsubscribe, e-mail: <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>
Re: Polish version of user guide
Posted by "Geir Magnusson Jr." <ge...@adeptra.com>.
On 7/12/02 10:10 AM, "Kulinski, Artur" <Ar...@eu.sony.com> wrote:
> Following is translation of users guide to polish. It is encoded in UTF-8
> becouse of
> polish special characters. Feel free to use it or request for changes.
Very cool! Thanks so much!
[snip]
--
To unsubscribe, e-mail: <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>
Re: Polish version of user guide
Posted by "Geir Magnusson Jr." <ge...@adeptra.com>.
On 7/12/02 10:10 AM, "Kulinski, Artur" <Ar...@eu.sony.com> wrote:
> Following is translation of users guide to polish. It is encoded in UTF-8
> becouse of
> polish special characters. Feel free to use it or request for changes.
Can you review what appeared on the list and confirm it's ok?
If not, is it possible that you either attach the doc as an attachment (not
inline text) or send me a copy?
Thanks
--
To unsubscribe, e-mail: <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>