En esta entrada vamos a detallar un ejemplo de uso de Apache Velocity. Esta herramienta nos permite generar fácilmente documentos xml, html, sql, csv, txt, etc.
Apache Velocity renderiza una plantilla con ciertos datos. Las plantillas deberán ser generadas previamente en base al lenguaje VTL (Velocity Template Language).
VTL nos permite generar informes muy grandes con poco esfuerzo.
Supongamos que nos interesa enviar el informe siguiente por correo electrónico:
+------+------------+--------+
| Año | Trimestre | Ventas |
+------+------------+--------+
| 2005 T1 1000 |
| 2005 T2 200 |
| 2005 T3 50 |
| 2005 T4 5 |
+------+------------+--------+
Como primera aproximación montaríamos una plantilla simple, donde las líneas de contenido fijo aparecen tal cual, mientras que en aquellas líneas donde hay conenido variable (año, trimestre y unidades) hemos insertado unas variables respetando los espacios en blanco que mantienen el encolumnado.
Las diferentes líneas del informe se generan recorriendo los elementos de la lista $listaVentas, cada elemento de la lista se carga en la variable $venta, y cada venta tiene dos atributos: $venta.trim y $venta.unidaddes.
#***************
Plantilla simple
***************#
+------+------------+--------+
| Año | Trimestre | Ventas |
+------+------------+--------+
#foreach($venta in $listaVentas)
| $anno $venta.trim $venta.unidades |
#end
+------+------------+--------+
Seguidamente montaríamos el código java, en donde cabe destacar que iniciamos el motor velocity fijando el encoding tanto de la plantilla de entrada como del documento renderizado a generar:
package org.edu.velocity.app;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.VelocityEngine;
public class Test {
public static void main(String[] args) {
//Instanciamos el motor velocity
final VelocityEngine ve = new VelocityEngine();
//Definimos el encoding de entrada y salida
final Properties props = new Properties();
props.put("output.encoding","UTF-8");
props.put("input.encoding","UTF-8");
//Inicializamos el motor velocity con el encoding deseado
ve.init(props);
//Cargamos la plantilla
final Template t = ve.getTemplate("informe-simple.vm");
//final Template t = ve.getTemplate("informe-alineado.vm");
//Preparamos los datos
final List<Object> listaVentas = new ArrayList<Object>();
Map<String, String> map = new HashMap<String, String>();
map.put("trim", "T1");
map.put("unidades", "1000");
listaVentas.add(map);
map = new HashMap<String, String>();
map.put("trim", "T2");
map.put("unidades", "200");
listaVentas.add(map);
map = new HashMap<String, String>();
map.put("trim", "T3");
map.put("unidades", "50");
listaVentas.add(map);
map = new HashMap<String, String>();
map.put("trim", "T4");
map.put("unidades", "5");
listaVentas.add(map);
//Creamos el contexto y le metemos los datos
final VelocityContext context = new VelocityContext();
context.put("listaVentas", listaVentas);
context.put("anno", "2005");
//Renderizamos la plantilla
final StringWriter writer = new StringWriter();
t.merge( context, writer );
//Visualizamos la plantilla
System.out.println(writer.toString());
}
Al ejecutar este código tendríamos la siguiente salida:
+------+------------+--------+
| Año | Trimestre | Ventas |
+------+------------+--------+
| 2005 T1 1000 |
| 2005 T2 200 |
| 2005 T3 50 |
| 2005 T4 5 |
+------+------------+--------+
La salida es casi lo que queríamos, pero al variar la longitud de los números de la última columna, tiene un aspecto incorrecto. Vamos a reajustar la plantilla con un control del tamaño de la variable $venta.unidades. Con lo que la plantilla alineada quedaría:
#*****************
Plantilla alineada
*****************#
+------+------------+--------+
| Año | Trimestre | Ventas |
+------+------------+--------+
#foreach($venta in $listaVentas)
#if($venta.unidades.length()==4)
| $anno $venta.trim $venta.unidades |
#{elseif}($venta.unidades.length()==3)
| $anno $venta.trim $venta.unidades |
#{elseif}($venta.unidades.length()==2)
| $anno $venta.trim $venta.unidades |
#{else}
| $anno $venta.trim $venta.unidades |
#end
#end
+------+------------+--------+
Si ejecutamos de nuevo el informe tendremos la salida corregida:
+------+------------+--------+
| Año | Trimestre | Ventas |
+------+------------+--------+
| 2005 T1 1000 |
| 2005 T2 200 |
| 2005 T3 50 |
| 2005 T4 5 |
+------+------------+--------+
Librerías.
Para lanzar este ejemplo hemos necesitado las librerías:
velocity-1.7.jar
commons-lang-2.4.jar
commons-collections-3.2.1.jar
Enlaces.
Más información sobre Apache Velocity y VTL en:
http://velocity.apache.org/
http://velocity.apache.org/engine/devel/vtl-reference-guide.html
Conclusiones.
Para generar documentos xml, html, sql, csv y txt, es una herramienta muy potente. La única limitación que le encuentro (sin haberle dedicado mas de una hora al tema), es que si pretendemos generar txt habrá que limitarse a cosas muy simples, dado que en cuanto el documento objetivo es un poco mas complejo la cosa se complica.
No quiero ni pensar qué habría que meter en VTL para generar un informe con varias columnas numéricas que tuviesen que salir alineadas como en el siguiente ejemplo:
+------+-----------+----------+---------+-------+
| Año | Trimestre | Entradas | Salidas | Stock |
+------+-----------+----------+---------+-------+
| 2005 | T1 | 1000 | 100 | 900 |
| 2005 | T2 | 200 | 50 | 150 |
| 2005 | T3 | 50 | 20 | 30 |
| 2005 | T4 | 5 | 3 | 2 |
+------+-----------+----------+---------+-------+
La cosa también sería muy compleja si alguien quiere que se generen documentos en txt con justificación completa (es un ejemplo muy rebuscado, me doy cuenta), similares al siguiente ejemplo:
Estimado Juan Español Español.
Nos dirigimos a vd. para comunicarle que el
día 17 de Abril de 2013 a transferiremos a
la cuenta 0182-0098-XX-XXXXXXXXXX la cantidad
de 1.355,22€ liquidando de ese modo la deuda
pendiente.
En Madrid a 01 de Enero de 2013.
Supongo que las librerías velocity-tools y .
No hay comentarios:
Publicar un comentario