| About Community Docs Tools Comparisons Site Translations | 
      | Acerca de esta guía |  | 
         
                                    
La Guía del usuario de Velocity busca ayudar a los diseñadores de páginas y a
los proveedores de contenido a sentirse a gusto con Velocity y con la sintáxis
de su simple pero poderoso lenguaje de script, el Lenguaje de Plantillas de
Velocity (VTL por sus siglas en inglés).  Muchos de los ejemplos de esta guía
muestran como usar Velocity para incluir contenidos dinámicos en sitios web,
pero todos los ejemplos de VTL son igualmente aplicables a otras páginas y
plantillas.
 Gracias por escoger Velocity! |  | 
 |  
      | ¿Qué es Velocity? |  | 
         
                                    
Velocity es un motor de plantillas basado en Java. Le permite a los diseñadores
de páginas hacer referencia a métodos definidos dentro del código Java. Los
diseñadores Web pueden trabajar en paralelo con los programadores Java para
desarrollar sitios de acuerdo al modelo de Modelo-Vista-Controlador (MVC),
permitiendo que los diseñadores se concentren únicamente en crear un sitio bien
diseñado y que los programadores se encarguen solamente de escribir código de
primera calidad. Velocity separa el código Java de las páginas Web, haciendo el
sitio más mantenible a largo plazo y presentando una alternativa viable a Java Server Pages (JSP) o PHP.
 
Velocity se puede utilizar para crear páginas web, SQL, PostScript y cualquier
otro tipo de salida de plantillas. Se puede utilizar como una aplicación
independiente para generar código fuente y reportes, o como un componente
integrado en otros sistemas. Cuando este completo Velocity proveerá servicios
para el conjunto de aplicaciones web de Turbine.  Velocity+Turbine
proveerá un servicio de plantillas que facilitará el desarrollo de aplicaciones
web de acuerdo a un verdadero modelo MVC.
 |  | 
 |  
      | ¿Qué puede hacer Velocity por mi? |  | 
         
                                        
      | El Ejemplo de la tienda de Lodo |  | 
                                    
Suponga que usted es un diseñador para una tienda en línea que se especializa
en vender lodo a la que llamaremos "La Tienda de Lodo en línea". Los negocios
están muy bien. Sus clientes ordenan diferentes tipos y cantidades de
lodo.
Ellos ingresan en su sitio con su nombre de usuario y su clave secreta, lo que
les permite ver sus órdenes y pedir más lodo. En estos momentos el Lodo
Terracota, que es muy popular, esta en oferta. Una minoría de sus clientes
usualmente compra Lodo Rojo Brillante, que también esta en oferta, pero no es
tan popular y usualmente esta relegado al márgen de su página web. La
información sobre cada cliente esta dentro de su base de datos por lo que surge
la pregunta: ¿Por qué no usar Velocity para enfocar las ofertas especiales para
los clientes que están más interesados en ciertas clases de lodo?
 
Velocity hace fácil el personalizar las páginas para sus visitantes.  Como un
diseñador dentro de "El Cuarto de Lodo", usted quiere crear la página que sus
usuarios verán después de entrar a su sitio.
 
Usted se encuentra con los ingenieros de su compañía, y todos acuerdan que
$cliente contendrá la información pertienente al cliente que está
dentro de la página en un momento dado, que $lodosEnOferta contendrá
todos los tipos de lodo que están en oferta hoy en día.  Además, el objeto
$flogger contendrá métodos para ayudar con la promoción. Para la tarea
actual, solo se utilizarán estas tres referencias. Recuerde, usted no necesita
preocuparse por como los ingenieros de software extraen la información
necesaria de la base de datos; sólo tiene que saber que funciona. Esto le
permite a usted continuar con su trabajo a la vez que deja a los ingenieros
hacer el de ellos.
 Usted podría incluir el siguiente código VTL dentro de su página: 
    
    
      |  |  |  |  
      |  | 
<HTML>
<BODY>
Hello $cliente.Nombre!
<table>
#foreach( $lodo in $lodosEnOferta )
#if ( $cliente.haComprado($lodo) )
<tr>
<td>
$flogger.obtenerPromocion( $lodo )
</td>
</tr>
#end
#end
</table>
 |  |  
      |  |  |  |  
Los detalles exactos de la sentencia foreach serán descritos en
profundidad próximamente; lo que es importante es el impacto que este pequeño
script pueda tener en su sitio.  Cuando un cliente con una debilidad por el
Lodo Rojo Brillante ingrese, si el Lodo Rojo Brillante esta en oferta, eso
será lo que el cliente verá, de manera prominente. Si otro cliente, con una
historia larga de compras de Lodo Terracota ingresa, entonces para él la
noticia de un rebaja de Lodo Terracota estará en un lugar muy importante. La
flexibilidad de Velocity es enorme y sólo esta limitada por su creatividad.
 
En la  referencia de VTL están documentados muchos otros elementos de Velocity
que, colectivamente le dan el poder y la flexibilidad que usted necesita para
hacer de su sitio en la red una presencia en la red. A medida que
usted se familiarice con estos elementos usted comenzará a aprovechar el poder
de Velocity.
 |  | 
 |  |  | 
 |  
      | El Lenguaje de Plantillas de Velocity (VTL): Una Introducción |  | 
         
                                    
  El Lenguaje de Plantillas de Velocity (VTL) fue creado para prover la
  manera mas fácil, simple y limpia de incorporar contenido dinámico
  dentro de una página web. Incluso un desarrollador de páginas web con
  poca y ninguna experiencia puede rápidamente ser capaz de utilizar VTL
  para incluir contenido dinámico en un sitio web.
  
 	VTL usa referencias para incluir contenido dinámico dentro
	de un sitio web. Una variable es un tipo de referencia que puede
	referirse a algo definido dentro del código Java o obtener su valor
	de un enunciado VTL en la página misma. A continuación hay
	un ejemplo de un enunciado VTL que se puede incluir en un documento
	HTML:
  
  	Este enunciado VTL, como todos los enunciados VTL comienza con el
	caracter # y contiene una directiva: set. Cuando
	un visitante solicita su página, el Motor de Plantillas de Velocity
	buscará dentro del contenido de su página y encontrará todos los
	símbolos #, para luego determinar cuáles marcan el comienzo
	de enunciados VTL y cuáles no tienen nada que ver con VTL.
  
 El caracter # viene seguido por una directiva set.
 La directiva set utiliza una expresión (encerrada entre
 paréntesis) -- una ecuación que asigna un valor a una
 variable.
 La variable se encuentra en el lado derecho y el valor está en el lado
 izquierdo; los dos se encuentran separados por un signo igual
 (=).
  
 En el ejemplo en la parte superior, la variable es $a y el
 valor es Velocity. Esta variable, al igual que todas las
 referencias, comienza con el caracter $. Los valores siempre
 se encuentran ente comillas; con Velocity no hay confusión acerca de
 los tipos de datos, ya que solamente cadenas (información basada en
 texto) pueden ser pasados a las variables.
  
 La siguiente regla puede ser útil para entender mejor como funciona
 Velocity: Las Referencias comienzan con $ y se
	 utilizan para obtener algo. Las directivas comienzan con #
	 y se utilizan para hacer algo
  
 En el ejemplo anterior #set se utilizó para asignarle un valor
 a una variable. La variable, $a, puede utilizarse dentro de la
 plantilla para escribir la palabara "Velocity".
  |  | 
 |  
      | Referencias |  | 
         
                                    
	Existen tres tipos de referencias en VTL: variables, propiedades y
	métodos. Como un diseñador que utilizar VTL, usted y sus ingenieros
	deben llegar a un acuerdo respecto a los nombres de las referencias
	para que usted pueda utilizarlas correctamente en sus plantillas.
  
 	Todo lo que entra y sale de una referencia se trata como una cadena
	de caracteres (un objeto String). Si existe un objeto que representa
	$foo (por ejemplo, un objeto Integer), entonces Velocity
	llamará el método .toString()de ese objeto para
	convertirlo en una cadena de caracteres. 
 Variables
 La notación breve de una variable esta compuesta por un signo "$"
	inicial seguido de un Identificador. Un identificador VTL
	debe comenzar con un caracter alfabético (a .. z ó A .. Z). El resto
	de los caracteres deb ser de alguno de los siguiente tipos:
 
    
     alfabético (a .. z, A .. Z)numérico (0 .. 9)línea ("-")underscore ("_") 
 	A continuación hay algunos ejemplos de referencias válidas en VTL:
  
    
    
      |  |  |  |  
      |  | 
$foo
$lanzaLodo
$lanza-lodo
$lanza_lodo
$lanzaLodo1
 |  |  
      |  |  |  |  
	Cuando VTL hace referencia una variable, po ejemplo, $foo,
	la variable puede obtener su valor de una directiva set
	dentro de la plantilla, o del código Java. Por ejemplo, si la
	variable de Java $foo tiene el valor bar en el
	momento en que se solicita la plantilla, entonces bar
	reemplaza todas las ocurrencias (o instancias) de $foo
	dentro de la página web. De manera alterna, si se incluye el
	enunciado
  
	La salida será la misma para todas las instancias de $foo
	que se encuentren a continuación es esta directiva.
  
 Propiedades
 El segundo sabor de referencias VTL son las propiedades; las
	propiedades tienen un formato particular. La versión corta se
	compone de un signo $ seguido de un identificador VTL,
	seguido de un punto y de otro identificador VTL. A continuación hay
	ejemplos de referencias de propiedades válidas en VTL:
 
    
    
      |  |  |  |  
      |  | 
$cliente.Direccion
$compra.Total
 |  |  
      |  |  |  |  
	Tome el primer ejemplo, $cliente.Direccion. Puede tener dos
	significados. Puede significar, Busque en la tabla de hashing
	identificada como cliente y devuelva el valor asociado con
	la llave Direccion. Pero $customer.Address puede
	también referirse a un método (las referencias que se relacionan con
	métodos se discutirán en la sección siguiente);
	$customer.Address puede ser una manera corta de escribir
	$customer.getAddress(). Cuando su página sea solicitada
	Velocity determinará cuál de las dos posibilidades tiene sentido, y
	luego devolverá el valor apropiado.
  
 Methods
 Un método esta definido dentro del código de Java y es capaz de
	hacer algo útil, como desarrollar un cálculo o llegar a una
	decisión. Los métodos son referencias compuestas de un signo "$"
	inicial seguido en un identificador VTL, seguido de un Cuerpo de
		Método VTL. Un cuerpo de método VTL, a su vez esta formado
	por un identificador VTL seguido por un paréntesis izquierdo ("("),
	seguido, opcionalmente, por una lista de parámetros, para terminar
	en un paréntesis derecho. A continuación hay ejemplos de referencias
	de métodos válidas dentro de VTL:
 
    
    
      |  |  |  |  
      |  | 
$cliente.getDireccion()
$compra.getTotal()
$pagina.setTitulo( "My Página Principal" )
$persona.establecerAtributos( ["Extraño", "Raro", "Excitado"] )
 |  |  
      |  |  |  |  
	Los primeros dos ejemplos -- $cliente.getDireccion() y
	$compra.getTotal() -- pueden parecer similares a aquellos
	utilizados en la sección de propiedades, $cliente.Direccion
	y $compra.Total. Si usted supuso que estos ejemplos están
	relacionados de alguna manera, usted esta en lo cierto.
  
 	Las Propiedades VTL pueden utilizarse como notación abreviada para
	los métodos de VTL. La propiedad $cliente.Direccion tiene
	exactamente el mismo efecto que el método
	$cliente.getDireccion() (Nótese el uso de la palabra
	inglesa get en lugar de la castellana obtener).
	Generalmente es preferible utilizar una Propiedad si esta
	disponible. La diferencia principal entre las propiedades y los
	métodos es que usted le puede dar una lista de parámetros a un
	Método.
  
 La notación breve se puede utilizar en los Métodos siguientes:
  
    
    
      |  |  |  |  
      |  | 
$sol.getPlanetas()
$anhelido.getMugre()
$album.getFoto()
 |  |  
      |  |  |  |  
	Podríamos esperar que estos métodos devolvieran los nombres de los
	planetas que giran alrededor del sol, alimentaran un gusano de
	tierra y extrajeran una foro de un album. Los siguientes Métodos
	solo se pueden referenciar por medio de la notación larga:
  
    
    
      |  |  |  |  
      |  | 
$sol.getPlaneta( ["Tierra", "Marte", "Neptuno"] )
## No es posible pasar una lista de parámetros con $sun.Planets
$sisifo.empujarPiedra()
## Si dijera $sisifo.piedra Velocity asumiría $sisifo.pushPiedra()
$libro.setTitulo( "Homenaje a Colombia" )
## No se puede pasar un parámetro en la notación abreviada.
 |  |  
      |  |  |  |  
 Notación Formal de
		 Referncias
 La notación abreviada para referencias fue utilizada en los ejemplos
 anteriores, pero también existe una notación formal para referencias,
 que se demuestra a continuación:
 
    
    
      |  |  |  |  
      |  | 
${lanzaLodo}
${cliente.Direccion}
${compra.getTotal()}
 |  |  
      |  |  |  |  
Casi en todos los casos usted utilizará la notación abreviada, pero
existen escenarios en los cuales la notación formal se requiere para
procesar corectamente la plantilla.
  
 Suponga que usted estuviera creando una frase en la que $vicio
 se utilizará como prefijo para el ajetivo de una clase. La idea es
 permitir a alguién escoger la palabra base para producir uno de los dos
 siguientes resultados: "Juan es un pirómano." ó "Juan es un
 cleptómano.". En este caso la notación abreviada no es apropiada;
 considere el siguiente ejemplo:
  
Hay ambigüedad aquí, y Velocity asume que $viciomano, no
$vicio, es el Identificador que usted quería utilizar. Al no
encontrar ningún valor para $viciomano Velocity escribirá
simplemente $viciomano. Este problema se resueklve usando
notación formal.
  
	Ahora Velocity save que la referencia es $vicio y no
	$viciomano. La notación formal es útil cuando las
	referencias están ubicadas directamente al lado del texto dentro de
	una plantilla.
  
 Notación de Referenias
		 Silenciosas
 Cuando Velocity encuentra una referencia indefinida, su
	comportamiento normal es es de escribir el nombre de la referencia.
	Por ejemplo, suponga que la siguiente referencia aparece como parte
	de una plantilla VTL.
 
    
    
      |  |  |  |  
      |  | 
<input type="text" name="correo" value="$correo"/>
 |  |  
      |  |  |  |  
	Cuando el formulario se carga por primera vez la referencia
	$correo no tiene valor, pero usted probablemente preferiría
	un texto en blanco a uno con el valor de "$correo". Usando la
	notación de referencias silenciosa se pasa por alto el
	comportamiento normal de Velocity. Para lograr eso en lugar de
	$correo en el VTL usted utilizaría $!correo. Con
	esta modificación el ejemplo anterior quedaría así:
  
    
    
      |  |  |  |  
      |  | 
<input type="text" name="correo" value="$!correo"/>
 |  |  
      |  |  |  |  
	Ahora cuando el formulario se carga por primera vez y $correo no
	tenga valor una cadena vacía se escribirá en lugar de "$correo".
  
 	La notación formal y la silenciosa se puede usar juntas como se
	muestra en el ejemplo siguiente:
  
    
    
      |  |  |  |  
      |  | 
<input type="text" name="correo" value="$!{correo}"/>
 |  |  
      |  |  |  |  |  | 
 |  
      | Directivas |  | 
         
                                    
	Las Referencias le permiten a los diseñadores de plantillas generar
	contenido dinámico para sitios web, mientras que las
	directivas -- elementos de script fáciles de usar que se
	pueden usar para manipular de manera creativa la salida del código
	Java -- les permiten a los diseñadores realmente estar a cargo de la
	apariencia y en contenido del sitio web.
 #set 
 La directiva #set se utiliza para establecer el valor de una
 referencia. El valor se puede asignar a una referencia de variable o
 una referencia de propiedad, siempre entre paréntesis, como se muestra
 a continuación:
  
    
    
      |  |  |  |  
      |  | 
#set( $primate = "mono" )
#set( $cliente.Comportamiento = $primate )
 |  |  
      |  |  |  |  
	El lado izquierdo (LI) de la asignación debe ser una referencia de
	variable o una referencia de propiedad. El lado derecho (LD) puede
	ser de alguno de los siguientes tipos:
  
     
		Referencia de VariableConstante de CadenaReferencia de PropiedadReferencia de MétodoLiteral NuméricoLista de elementos como arreglo 
    These examples demonstrate each of the aforementioned types:
  
    
    
      |  |  |  |  
      |  | 
#set( $mono = $pedro ) ## Referencia de Variable
#set( $mono.Amigo = "monica" ) ## Constante de Cadena
#set( $mono.Culpar = $casablanca.Fuga ) ## referencia de propiedad
#set( $mono.Plan = $doctor.llamar($web) ) ## referencia de método
#set( $mono.Numero = 123 ) ##Literal Numérico
#set( $mono.Decir = ["No", "es", $mi, "culpa"] ) ##Arreglo
 |  |  
      |  |  |  |  
 NOTA: En el último ejemplo los elementos definidos con el operador
 [..] son accesibles usando los métodos definidos en la clase ArrayList.
 Así, por ejemplo, usted podría acceder el primer elemento del arreglo utilizando $mono.Decir.get(0), con lo que obtendría la palabra "No".
  
 El lado derecho también puede ser una expresión aritmética sencilla:
  
    
    
      |  |  |  |  
      |  | 
#set( $value = $foo + 1 )
#set( $value = $bar - 1 )
#set( $value = $foo * $bar )
#set( $value = $foo / $bar )
 |  |  
      |  |  |  |  
	Si el Lado Derecho es una propiedad o referencia de método que se
	evalúa como null, no será asignada al lado
	izquierdo. No es posible remover una referencia existente del
	contexto utilizando este mecanismo. Esto puede ser confuso para los
	recién llegados a Velocity. Por ejemplo:
  
    
    
      |  |  |  |  
      |  | 
#set( $resultado = $consulta.criterio("nombre") )
El resultado de la primera consulta en $resultado
#set( $resultado = $consulta.criterio("direccion") )
El resultado de la segunda consulta es $resultado
 |  |  
      |  |  |  |  
	Si $consulta.criterio("nombre") retorna la cadena "pedro",
	y $consulta.criterio("direccion") retorna null, el
	VTL anterio se mostraría de la siguiente manera:
  
    
    
      |  |  |  |  
      |  | 
El resultado de la primera consulta en pedro
El resultado de la primera consulta en pedro
 |  |  
      |  |  |  |  
	Esto tiende a confundir a quines están comenzando, que construyen
	ciclos #foreach que intentan hacer #set de una
	referencia por medio de una propiedad o un método e inmediatamente
	evalúan la referencia con una directiva #if. Por ejemplo:
  
    
    
      |  |  |  |  
      |  | 
#set( $criterios = ["nombre", "direccion"] )
#foreach( $criterio in $criterios )
    #set( $resultado = $consulta.criterios($criterio) )
    #if( $result )
	La consulta tuvo éxito
    #end
#end
 |  |  
      |  |  |  |  
	En el ejemplo anterior, no sería inteligente confiar en la
	evaluación de $resultado para determinar si una consulta
	tuvo éxito. Después de que $result ha sido agregado al
	contexto (por medio de una directiva #set), no puede volver
	a establecerse a null (quitarse del contexto). Los detalles
	de las directivas #if y #foreach son cubiertos con
	mayor detalle posteriormente en esta guía.
  
 	Una solución para este problema puede ser predefinir
	$resultado a false. Luego, si la llamada a
	$consulta.criterios() falla, es posible verificar.
  
    
    
      |  |  |  |  
      |  | 
#set( $criterios = ["nombre", "direccion"] )
#foreach( $criterio in $criterios )
    #set( $resultado = false )
    #set( $resultado = $consulta.criterios($criterio) )
    #if( $resultado )
		La consulta tuvo éxito
    #end
#end
 |  |  
      |  |  |  |  
	A diferencia de algunas de las otras directivas de Velocity, la
	directiva #set no tiene un enunciado #end.
 Cadenas de Caracteres 
 	Cuando se utiliza la directiva #set, los literales de
	cadena que están encerrados en comillas dobles serán evaluados y
	mostrados en la plantilla, como se demuestra a continuación:
  
    
    
      |  |  |  |  
      |  | 
#set( $directorioRaiz = "www" )
#set( $nombrePlantilla = "indice.vm" )
#set( $plantilla = "$directorioRaiz/$nombrePlantilla" )
$plantilla
 |  |  
      |  |  |  |  
 La salida será:
  
	Sin embargo, cuando la cadena de caracteres esta encerrada en
	comillas sencillas, no será evaluada:
  
    
    
      |  |  |  |  
      |  | 
#set( $foo = "bar" )
$foo
#set( $blarg = '$foo' )
$blarg
 |  |  
      |  |  |  |  Se muestra como: 
	Por defecto, la característica de las comillas sencillas para
	mostrar texto sin evaluar esta disponible en Velocity; sin embargo
	este valor por defecto se puede cambiar editando el archivo
	velocity.propertiesde tal manera questringliterals.interpolate=false. |  | 
 |  
      | Sentencias If-Else |  | 
         
                                    Condicionales
                                                
	La directiva #if en Velocity permite que se incluya texto
	dentro de la plantilla generada, con la condición de que el
	enunciado condicional evalue a verdadero. Por ejemplo:
 
    
    
      |  |  |  |  
      |  | 
#if( $foo )
   <strong>Velocity!</strong>
#end
 |  |  
      |  |  |  |  
	La variable $foo se evalúa para determinar si es verdadera,
	cosa que ocurrirá bajo una de dos circunstancias: (i) $foo
	es un valor booleano (verdadero ó falso) que tiene un valor de
	verdadero, ó (ii) el valor no es null. Recuerde que el
	contexto de Velocity solamente contiene objetos, por lo que cuando
	se dice 'booleano' se habla en realidad de la clase Boolean. Esto es
	cierto incluso para los métodos que devuelven un valor de tipo
	boolean- la infraestructura de introspección devolverá
	unBooleandel mismo valor lógico. 
	El contenido que se encuentra entre el enunciado #if y el
	enunciado #end es lo que se escribe en la plantilla si la
	evaluación resulta en un valor verdadero. En este caso, si
	$foo es verdadero, la salida será: "Velocity!". De manera
	análoga, si $foo tiene un valor null, o evalua a
	falso, entonces el enunciado completo es falso y no se escribe nada.
 
	Un elemento #elseif ó #else puede utilizarse junto
	con una sentencia #if para indicar condiciones adicionales
	o la labor por defecto. Note que el Motor de Plantillas de Velocity
	parará en la primera expresión que evalue a verdadero. En el ejemplo
	siguiente suponga que $foo tiene un valor de 15 y
	$bar tiene un valor de 6.
 
    
    
      |  |  |  |  
      |  | 
#if( $foo < 10 )
	<strong>Vaya hacía el Norte</strong>
#elseif( $foo == 10 )
    <strong>Vaya hacía el Este</strong>
#elseif( $bar == 6 )
	<strong>Vaya al Sur</strong>
#else
    <strong>Vaya al Oeste</strong>
#end
 |  |  
      |  |  |  |  En este ejemplo, $foo es mayor que diez, por lo que las
	dos primeras comparaciones fallan. A continuación se compara
	$bar con 6, como son iguales, la salida es Vaya al
		Sur
     
	Operadores
			Lógicos y Relacionales
     
	Velocity usa el operador de equivalencia para determinar las
	relaciones entre las variables. A continuación hay un ejemplo
	sencillo para ilustrar como se utiliza el operador de igualdad.
     
    
    
      |  |  |  |  
      |  | 
#set ($foo = "ácido desoxiribonucleico")
#set ($bar = "ácido ribonucleico")
#if ($foo == $bar)
	En este caso es claro que no son equivalentes por lo que....
  In this case it's clear they aren't equivalent. So...
#else
	No son equivalentes y esta será la salida.
#end
 |  |  
      |  |  |  |  
	Velocity tiene también operadores lógicos para el Y, el O y el NO
	(AND, OR y NOT). Para mayor información vea la Guía de Referencia VTL.
	A continuación se encuentran ejemplos que demuestran la utilización
	de los operadores lógicos AND, OR y NOT.
     
    
    
      |  |  |  |  
      |  | 
## Y lógico
#if( $foo && $bar )
	<strong>Esto Y aquello</strong>
#end
 |  |  
      |  |  |  |  
	La directiva #if() solamente evaluará a verdadero si tanto
	$foo como $bar son ciertos. Si $foo es
	falso la expresión evaluará a falso; $bar no será evaluada.
	Si $foo es verdadero el Motor de Plantillas de Velocity
	verificará el valor de $bar; si $bar es cierto,
	entonces toda la expresión es cierto y la salida es Esto Y
		aquello. Si $bar es falso, entonces no habrá
	ninguna salida porque toda la expresión es falsa.
     
	El O lógico trabaja de la misma manera, pero sólo una de las
	referencias debe evaluar a verdadero para que toda la expresión
	evalue a verdadero. Considere el ejemplo siguiente.
     
    
    
      |  |  |  |  
      |  | 
## O lógico
#if( $foo || $bar )
    <strong>Esto O Aquello</strong>
#end
 |  |  
      |  |  |  |  
	Si $foo es verdadero, el Motor de Plantillas de Velocity no
	necesita consultar $bar,; sin importar si $bar es
	cierto o falso, la expresión será cierta, y Esto O
		Aquello será la salida. Si $foo es falso, en
	cambio, es necesario verificar $bar. En este caso, si
	$bar es falso, entonces la expresión es falsa y no se
	escribe nada. De otro lado, si $bar es verdadero, entonces
	toda la expresión es verdadera y el resultado es Esto O
		Aquello
     
	Con el operador lógico NO, solo hay un argumento :
     
    
    
      |  |  |  |  
      |  | 
## NO lógico
#if( !$foo )
<strong>eso NO</strong>
#end
 |  |  
      |  |  |  |  
	Aquí si $foo es cierto, entonces !$foo es falso, y
	no se escribe nada. Por el contrario, si $foo es falso,
	entonces !$foo será verdadero y eso NO
	será escrito. Tenga cuidado de no confundir este operador con la
	referencia sileciosa $!foo, que es algo completamente
	distinto.
     |  | 
 |  
      | Ciclos Foreach |  | 
         
                                    Ciclo Foreach
                                                
   	El elemento #foreach permite la construcción de ciclos. Por
	ejemplo:
     
    
    
      |  |  |  |  
      |  | 
<ul>
#foreach( $producto in $todosProductos )
    <li>$producto</li>
#end
</ul>
 |  |  
      |  |  |  |  
	Este cilco #foreach hace que el objeto correspondiente a la
	lista de $todosProductos sea iterado buscando todos los productos de
	la lista. En cada iteración del ciclo, el valor de
	$todosProductos se asigna a la variable $producto.
     
	El contenido de la variable $todosProductos es un Vector,
	una tabla de Hashing (Hashtable) o un arreglo (Array). El valor
	asignado a la variable $producto es un objeto Java y se
	puede referenciar desde una variabkle como tal. Por ejemplo, si
	$product fuera realmente un elemento de la clase Producto
	en Java, su nombre se podría obtener referenciando el método
	$producto.Nombre (ie: $Product.getName()).
     
	Ahora supongamos que $todosProductos es una tabla de
	Hashing. Si usted quisiera recuperar los valores de las llaves de la
	tabla de Hashing, al igual que los objetos dentro de esta, usted
	podría utilizar código como el siguiente:
     
    
    
      |  |  |  |  
      |  | 
<ul>
	#foreach( $llave in $todosProductos.keySet() )
	<li>Llave: $llave -> Valor: $todosProductos.get($llave)</li>
#end
</ul>
 |  |  
      |  |  |  |  
	Velocity proporciona una manera sencilla de obtener el contador del
	ciclo para que usted pueda hacer algo como lo siguiente:
 
    
    
      |  |  |  |  
      |  | 
<table>
	#foreach( $cliente in $listaClientes )
    <tr><td>$velocityCount</td><td>$cliente.Nombre</td></tr>
#end
</table>
 |  |  
      |  |  |  |  
	El nombre por defecto para la referencia de la variable contador del
	ciclo, que se especifica en el archivo
	velocity.properties, es
	$velocityCount. Por defecto el contador comienza en 1, pero esto se
	puede hacer 0 o 1 en el archivovelocity.properties. A
	continuación se muestra el fragmento de este archivo que corresponde
	al contador de ciclo (en inglés, tal como aparece en el archivo
	original): 
    
    
      |  |  |  |  
      |  | 
# Default name of the loop counter
# variable reference.
directive.foreach.counter.nombre = velocityCount
# Default starting value of the loop
# counter variable reference.
directive.foreach.counter.initial.value = 1
 |  |  
      |  |  |  |  |  | 
 |  
      | Include |  | 
         
                                    
	El elemento de script #include le permite al diseñador de
	plantillas importar un archivo local, que después es insertado en la
	localización donde se encuentra la sentencia #include. Los
	contenidos del archivo no se muestran por intermedio del motor de
	plantillas por lo que si se hacen referencias dentro del archivo,
	estas no serán reemplazadas. Por motivos de seguridad el archivo que
	va a ser incluido debe encontrarse en el directorio indicado por la
	propiedad TEMPLATE_ROOT.
     
	El archivo al que se refiere la directiva #include se
	encierra entre comillas. Si mas de un archivo será incluido, los
	nombres de los archivos a incluir deben ir separados por comas.
     
    
    
      |  |  |  |  
      |  | 
#include( "uno.gif","dos.txt","tres.htm" )
 |  |  
      |  |  |  |  
	El archivo a incluir no tiene que ser referenciado por nombre, de
	hecho, muchas veces es preferible usar una variable, en lugar de un
	nombre de archivo. Esto puede ser útil para dirigir la salida de
	acuerdo a criterios determinados cuando la solicitud de la página es
	enviada, es decir, que dependa de factores como los datos del
	usuario que visita la página, el momento del día, etc. A
	continuación se muestra un ejemplo en el que se usan tanto un nombre
	como una variable.
     
    
    
      |  |  |  |  
      |  | 
#include( "greetings.txt", $seasonalstock )
 |  |  
      |  |  |  |  |  | 
 |  
      | Parse |  | 
         
                                    
	El elemento de script #parse le permite al diseñadore de
	plantillas importar un archivo local que contiene VTL. Velocity
	procesará el VTL y mostrará la plantilla especificada.
 
	Al igual que la directiva #include, #parse puede
	utilizar una variable, en lugar de una plantilla. Todas las
	plantillas a las que #parse se refiera deben incluirse bajo
	TEMPLATE_ROOT. A diferencia de la directva #include,
	#parse solo recibe un argumento.
 
	Las plantillas de VTL puede tener sentencias #parse que se
	refieran a plantillas que a su vez tengan sentencias
	#parse. La línea parse_directive.maxdepth del
	archivo velocity.properties, cuyo valor por defecto es
	10, permite a los usuarios configurar el máximo número de
	referencias a #parse que pueden ocurrir desde una única
	plantilla. (Nota: Si la propiedad parse_directive.maxdepth
	no esta dentro del archivovelocity.properties,
	Velocity establecerá el valor por defecto en 10.) La recursión esta
	permitida, por ejemplo, si la plantillahacerfoo.vmcontiene las siguientes líneas: 
    
    
      |  |  |  |  
      |  | 
Cuenta Regresiva.
#set( $cuenta = 8 )
#parse( "parsefoo.vm" )
Listo hacerfoo.vm!
 |  |  
      |  |  |  |  
	Hay una referencia a la plantilla parsefoo.vm, que
	contiene el siguiente código VTL: 
    
    
      |  |  |  |  
      |  | 
$cuenta
#set( $cuenta = $cuenta - 1 )
#if( $cuenta > 0 )
    #parse( "parsefoo.vm" )
#else
    Listo parsefoo.vm!
#end
 |  |  
      |  |  |  |  
	Después de que se muestra "Cuenta Regresiva.", Velocity pasa por
	parsefoo.vm, contando hacía abajo desde 8. Cuando el
	conteo llegue a 0, mostrará el mensaje "Listo parsefoo.vm!". En este
	punto Velocity volverá adofoo.vmy escribirá el
	mensaje "Listo hacerfoo.vm!". |  | 
 |  
      | Stop |  | 
         
                                    
El elemento de script #stop permite al diseñador parar la
ejecución del motor de plantillas y volver. Esto es útil para propósitos
de corrección de errores.
 |  | 
 |  
      | Velocimacros |  | 
         
                                    
	El elemento de script #macro script permite definir un
	segmento de plantilla VTL repetitivo. Los Velocimacros son muy
	útiles en una amplia gama se situaciones, tanto simples como
	complejas. El siguiente Velocimacro, creado con el único propósito
	de ahorrar tecleo y minimizar errores tipográficos, provee una
	introducción al concepto de Velocimacros
	element allows template designers to.
     
    
    
      |  |  |  |  
      |  | 
#macro( d )
<tr><td></td></tr>
#end
 |  |  
      |  |  |  |  
	El Velocimacro que se define en este ejemplo es d, y se
	puede llamar de manera similar a cualquier otra directiva VTL:
     
Cuando esta plantilla sea solicitada, Velocity reemplazará #d()
por una fila conteniendo un única celda vacia.
 
Un Velocimacro puiede tomar cualquier número de argumentos -- no tener
ningún argumento, como se mostró en el primer ejemplo, es una opción --
pero cuando sea invocado el Velocimacro debe ser llamado con el mismo
número de argumentos con el que fue definido. Muchos Velocimacros se
relacionan con el entorno mucho más con su entorno que el ejemplo
demostrado anteriormente. Aquí hay un Velocimacro que recibe dos
argumentos, un color y un arreglo.
 
    
    
      |  |  |  |  
      |  | 
#macro( filastabla $color $algunalista )
#foreach( $algo in $algunalista )
    <tr><td bgcolor=$color>$algo</td></tr>
#end
#end
 |  |  
      |  |  |  |  
El Velocimacro que se define en este ejemplo, filastabla, toma
dos argumentos. El primer argumento toma el lugar de $color, y
el segundo argumento el de $algunalista
     
Cualquier cosa que se pueda incluir dentro de una plantilla VTL puede
formar parte delcuerpo de un Velocimacro. El Velocimacro
filastabla es una sentencia foreach. Hay dos
sentencias #end dentro del Velocimacro; la primera pertenece al
foreach y a segunda termina la definición del Velocimacro.
     
    
    
      |  |  |  |  
      |  | 
#set( $grandeslagos = ["Superior","Michigan","Huron","Erie","Ontario"] )
#set( $color = "blue" )
<table>
	#filastabla( $color $grandeslagos )
</table>
 |  |  
      |  |  |  |  
	Note que $grandeslagos toma el lugar de
	$algunalista. Cuando el Velocimacro es llamado en esta
	situación, la siguiente salida es generada:
     
    
    
      |  |  |  |  
      |  | 
<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>
 |  |  
      |  |  |  |  
Los Velocimacro pueden ser definidos inline dentro de una
plantilla. Esto quiere decir que la definición del macro no esta
disponible para otras plantillas dentro del mimso sitio Web. Definir un
Velocimacro de tal forma que sea compartido por todas las plantillas
tiene ventajas obvias: Reduce la necesidad de redefinir el macro en
varias plantillas, ahorrando trabajo y disminuyendo las posiblidades de
error, además de asegurar que un único cambio en un archivo quedará
disponible para todas las plantillas.
 
Si el Velocimacro #filastabla($color $lista) fuera definido en
una librería, se podría utilizar en cualquiera de la plantillas
normales; se podría utilizar muchas veces con propósitos distintos. En
la plantilla vegetal.vmdedicado a todas las plantas, el
Velocimacro #filastabla podría invocarse para listar las partes
de un vegetal típico: 
    
    
      |  |  |  |  
      |  | 
#set( $partes = ["raíz","tallo","hojas","flores","frutos"] )
#set( $colorCelda = "#CC00FF" )
<table>
	#filastabla( $colorCelda $parts )
</table>
 |  |  
      |  |  |  |  
Cuando atendiera ls solicitud de vegetal.vm, Velocity
encontraría el macro #filastabla en la librería de plantillas
(definida en el archivovelocity.properties) y generaría el
siguiente resultado: 
    Argumentos de un Velocimacro
    
      |  |  |  |  
      |  | 
<table>
    <tr><td bgcolor="#CC00FF">raíz</td></tr>
    <tr><td bgcolor="#CC00FF">tallo</td></tr>
    <tr><td bgcolor="#CC00FF">hojas</td></tr>
    <tr><td bgcolor="#CC00FF">flores</td></tr>
    <tr><td bgcolor="#CC00FF">frutos</td></tr>
</table>
 |  |  
      |  |  |  |  
Los Velocimacros pueden recibir como argumentos cualquiera de los
siguientes elementos de VTL:
   
    
	Referencia : cualquier cosa que comience con '$'
    
	Cadena de caracteres : algo como "$foo" u 'hola'
    
      Número : 1, 2 etc
    
		Rango de enteros : [ 1..2] ó [$foo .. $bar]
    
      	ObjectArray : [ "a", "b", "c"]
    
       El valor booleano "verdadero"
    
	   El valor booleano "falso"
     
  	Cuando pase referencias como argumentos para los Velocimacros tenga
	en cuenta que las referencias se pasan 'por nombre'. Esto quiere
	decir que su valor es 'generado' cada vez que se usa dentro del
	Velocimacros. Esta característica le permite pasar referencias con
	las llamadas de método y hacer que el método se llame cada vez. Por
	ejemplo, cuando llame el siguiente Velocimacro
    
    
    
      |  |  |  |  
      |  | 
   #macro( llamame $a )
         $a $a $a
     #end
#llamame( $foo.bar() )
    |  |  
      |  |  |  |  
   	Esa llamada hace que el método bar() de la referencia $foo sea
	llamado 3 veces.
     
	A primera vista, esta característica parece sorprendente, pero
	cuando se tiene en cuenta la motivación original de los Velocimacros
	-- eliminar la duplicación de "copiar y pegar" del VTL usado varias
	veces -- tiene mucho sentido. Permite pasar al Velocimacro objetos
	con estado, como un objeto que genera colores en una secuencia
	repetitiva para colorear las filas de una tabla.
     
	Si usted no desea utilizar esta característica siempre es posible
	simplemente obtener el valor del método como una nueva referencia y
	pasar ese valor:
     
    Propiedades de un Velocimacro
    
      |  |  |  |  
      |  | 
	#set( $mivalor = $foo.bar() )
	#llamame( $mivalor )
    |  |  
      |  |  |  |  
   Varias líneas en al archivo velocity.propertiespermiten
   flexibilizar la implementación de los Velocimacro. Tenga en cuenta
   que estas propiedades también están documentadas en la Guía de Desarrolladores. 
   velocimacro.library- Una lista, separada por comas de
   todas la librerias de plantillas de Velocimacros. Por defecto,
   Velocity busca una sola librería: VM_global_library.vm. El
   directorio en el que se buscan las plantillas también se utiliza para
   localizar las librerías. 
	velocimacro.permissions.allow.inline- Esta propiedad,
	que tiene como valores posibles verdadero y falso (true y false),
	determina si los Velocimacros pueden ser definidos dentro de las
	plantillas normales.
	El valor por defecto, verdadero, le permite a los diseñadores
	definir por si mismos macros en las plantillas. 
    velocimacro.permissions.allow.inline.to.replace.global-
	Con valores posibles verdadero y falso (true y false), esta
	propiedad le permite al usuario decidir si un Velocimacro definido
	inline dentro de una plantilla puede reemplazar a la plantilla
	global, que fue cargada al comienzo por medio de la propiedadvelocimacro.library. El valor por defecto, falso
	(false), evita que los Velocimacros definidos en una
	plantilla reemplacen a los que fueron cargados al inicio. 
   velocimacro.permissions.allow.inline.local.scope-
	Con valores posibles verdadero y falso (true y false), valor por
	defecto falso, esta propiedad dice si los Velocimacros definidos
	inline son 'visibles' únicamente para la plantilla que los define.
	Usted puede usar esta característica para hacer algunos trucos de
	VM - si un VM global llama a otro VM global, con ancance inline, una
	plantilla puede definir una implementación privada del segundo VM,
	que será llamada por el primer VM cuando sea invocado en esa
	plantilla. Ninguna de las otras templates es afectada. 
	velocimacro.context.localscope-
	Con valores posibles verdadero y falso (true y false), valor por
	defecto falso. Cuando es verdadera cualquier modificación al
	contexto por medio de un #set() dentro de un Velocimacro se
	considera local a ese Velocimacro y no afecta permanentemente al
	contexto. 
	Cosas y Casos de Velocimacrosvelocimacro.library.autoreload- Esta propiedad
	controla el cargado automático de la libreria de Velocimacros. El
	valor por defecto esfalse. Cuando es verdadero
	(true) la librería fuente de un Velocimacro que ha sido
	invocado será verificada para comprobar que no haya cambiado, y si
	lo ha hecho será recargada. Esta característica le permite cambiar y
	probar librerías de macros sin necesidad de reiniciar la aplicación
	o el contenedor de servlets, de la misma manera que se hace con
	plantillas normales.
	Este modo solo funciona cuando el caché esta apagado
	en los cargadores de recursos( e.g.file.resource.loader.cache
		= false).
	Esta característica esta pensada para el proceso de desarrollo, no
	el de producción.
	This property 
	Actualmente los Velocimacros deben ser definidos antes de ser
	utilizados por primera vez dentro de una plantilla. Esto significa
	que sus declaraciones de #macro() deben aparecerantes de que usted
	utilice los Velocimacros.
     
	Esto es importante recordarlo cuando usted intenta hacerle #parse()
	a una plantilla que contiene directivas #macro(). Como el #parse()
	ocurre en tiempo de ejecución, y el parser decide si un elemento que
	parece una VM es realmente un VM cuando esta haciendo el #parse(),
	entonces probablemente el #parse() de un conjunto de declaraciones
	no funciona como se esperaría. Para evitar este problema,
	simplemente utilice la propiedad
	velocimacro.librarypara cargar todos sus VM cuando se
	inicie la aplicación. |  | 
 |  
      | Escapando Directivas VTL |  | 
         
                                    
Las directivas de VTL se pueden escapar con el palote invertido o
backslash ("\") de manera similar a como se escapan las referencias de
VTL válidas.
 
    
    
      |  |  |  |  
      |  | 
## #include( "a.txt" ) se muestra como <contenidos of de a.txt>
#include( "a.txt" )
## \#include( "a.txt" ) se muestra como #include( "a.txt" )
\#include( "a.txt" )
## \\#include ( "a.txt" ) se muestra como \<contenidos de a.txt>
\\#include ( "a.txt" )
 |  |  
      |  |  |  |  
Se debe tener especial cuidado cuando se escapan directivas de VTL que
contienen varios elementos de script en una misma directiva (como en las
sentencias if-else-end). A continuación seencuentra un ejemplo de un
condicional típico de VTL:
   
    
    
      |  |  |  |  
      |  | 
#if( $jazz )
    Vyacheslav Ganelin
#end
 |  |  
      |  |  |  |  
  Si $jazz es cierto la salida es
   
  Si $jazz es fals, no hay salida. Escapar elementos de script
  altera la salida. Considere el siguiente caso:
   
    
    
      |  |  |  |  
      |  | 
\#if( $jazz )
    Vyacheslav Ganelin
\#end
 |  |  
      |  |  |  |  
Sin importar si $jazz es verdadero o falso, la salida será:
 
    
    
      |  |  |  |  
      |  | 
 #if($ jazz )
     Vyacheslav Ganelin
 #end
  |  |  
      |  |  |  |  
 De hecho, como todos los elementos de script están escapados,
 $jazz nunca se evalúa por su valor booleano.
 Suponga que los palotes invertidos preceden a elementos de script que
 están legitimamente escapados:
   
    
    
      |  |  |  |  
      |  | 
\\#if( $jazz )
   Vyacheslav Ganelin
\\#end
 |  |  
      |  |  |  |  
En este caso, si $jazz es verdadero, la salida es
 
Para entender esto tenga en cuenta que #if( arg ), cuando
es terminado por un caracter de fin de línea (retorno) omitirá ese
caracter de la salida. Por lo tanto, el cuerpo del bloque#if()va a continuación del primer '\', que se generó a
partir del '\\' que precedía el#if()dentro de la
pantilla. El último \ está en una línea distinta que el texto porqué hay
un retorno después de 'Ganelin', por lo que el \\ final, que precede el#endhace parte del cuerpo del bloque. 
  Si $jazz es falso, la salida es
   
  Tenga en cuenta que las
  cosas dejan de funcionar si los elementos de script no son escapados
  de manera correcta.
   
    
    
      |  |  |  |  
      |  | 
\\\#if( $jazz )
    Vyacheslave Ganelin
\\#end
 |  |  
      |  |  |  |  
  Aquí el #if esta escapado, pero hay un #end que
  sobra; al haber demasiados cierres (end) sin sus correspondientes
  aperturas (foreach ó if) se generará un error de procesamiento.
   |  | 
 |  
      | Otras Características y Miscelánea |  | 
         
                                        
                                                    
                                                    
                                                    
      | Miscelánea de Velocimacro |  | 
                                    
Esta sección contiene un conjunto de preguntas frecuentes (FAQ)
relacionadas con Velocimacros. Esta sección cambiará con el tiempo, por
lo que es bueno revisar si hay información nueva de cuando en cuando.
 
Nota : A través de esta sección 'Velocimacro' será abreviado como 'VM'.
¿Puedo usar una directiva u otro VM como argumento para un VM? 
Ejemplo : #center( #bold("hola") ) 
No.  Una directiva no es un argumento válido para una directiva y, para
la mayoría de los propósitos prácticos, un VM es una directiva.
 
Sin embargo..., hay cosas que usted puede hacer. Una solución
sencilla es aprovechar el hecho de que la doble comilla (") muestra sus
contenidos, por lo que usted puede hacer algo como
 
    
    
      |  |  |  |  
      |  | 
#set($cosas = "#bold('hola')" )
#center( $cosas )
 |  |  
      |  |  |  |  
Puede tener un paso...
 
    
    
      |  |  |  |  
      |  | 
#center( "#bold( 'hola' )" )
 |  |  
      |  |  |  |  
Tenga en cuenta que en segundo ejemplo el argumentos es evaluado 
	dentro de la VM, no a nivel del llamador. En otras palabras, el
argumento para el VM es pasado completo y evaluado dentro del VM al que
se le pasa. Esto le permite hacer cosas como :
 
    
    
      |  |  |  |  
      |  | 
#macro( interno $foo )
  interno : $foo
#end
#macro( externo $foo )
   #set($bar = "externolala")
   externo : $foo
#end
#set($bar = 'calltimelala')
#externo( "#interno($bar)" )
 |  |  
      |  |  |  |  
Donde la salida es
 
    
    
      |  |  |  |  
      |  | 
externo : interno : externolala
 |  |  
      |  |  |  |  
la evaluación de "#interno($bar)" se lleva a cabo dentro de #externo(),
por lo que el valor $bar establecido dentro de #externo() es el que se
utiliza.
 
Estas es una característica intencional y celosamente protegina - los
argumentos se pasan por nombre a los VM para que usted le pueda
'entregar' a los VMs referencias con estado como
 
    
    
      |  |  |  |  
      |  | 
#macro( foo $color )
  <tr bgcolor=$color><td>Hola</td></tr>
  <tr bgcolor=$color><td>Todos</td></tr>
#end
#foo( $bar.colorFila() )
 |  |  
      |  |  |  |  
Y lograr que colorFila() se llame varias veces, en lugar de solo una.
Par evitar que eso ocurra invoque el método fuera del VM y pásele el
valor al VM.
 
    ¿Puedo registrar Velocimacros por medio de #parse() ?
    
      |  |  |  |  
      |  | 
#set($color = $bar.colorFila())
#foo( $color )
 |  |  
      |  |  |  |  
Actualmente, los Velocimacros deben ser definidos antes de ser usados
por primera vez dentro de una plantilla. Esto significa que sus
declaraciones de #macro() deben venir antes de que usted use los
Velocimacros.
 
	Esto es importante recordarlo cuando usted intenta hacerle #parse()
	a una plantilla que contiene directivas #macro(). Como el #parse()
	ocurre en tiempo de ejecución, y el parser decide si un elemento que
	parece una VM es realmente un VM cuando esta haciendo el #parse(),
	entonces probablemente el #parse() de un conjunto de declaraciones
	no funciona como se esperaría. Para evitar este problema,
	simplemente utilice la propiedad
	¿Qué es la auto recarga de Velocimacros?velocimacro.librarypara cargar todos sus VM cuando se
	inicie la aplicación. 
	Existe una propiedad, pensada para usarse en desarrollo, no
	en producción :
   
  velocimacro.library.autoreload 
  que tiene como valor por defecto falso. Cuando se hace verdadera
  junto con <tipo>.resource.loader.cache = false(where <tipo> es el nombre del cargador de recursos que usted
  esta utilizando, como 'file' para archivos) entonces el motor de
  Velocity recargará automáticamente los cambios en su librerías en el
  momento en que los haga para que usted no tenga que reinicar el motor
  de servlets o la aplicación, o hacer otros trucos para lograr que sus
  Velocimacros se recarguen. 
	A continuación se muestra un conjunto sencillo de propiedades de
	configuración.
     
    
    
      |  |  |  |  
      |  | 
    file.resource.loader.path = templates
    file.resource.loader.cache = false
    velocimacro.library.autoreload = true
     |  |  
      |  |  |  |  No utilice esto en producción |  | 
 |  |  | 
 |  |