Dinámica Biblioteca Técnica

Anuncio
Dinámica
El framework RADical
…J2EE sin complicaciones
Producido por:
Martín Córdova y Asociados C.A.
www.martincordova.com
martin.cordova@gmail.com
Biblioteca Técnica: plantilla de solución PL010
HGrid (Galerías de imágenes)
Última actualización: 2008-02-08
Requiere framework v2.1.4 en adelante
Contenido
Sumario ............................................................................................................................ 2
Demo online permanente.................................................................................................. 2
Screenshots....................................................................................................................... 3
Arquitectura de la solución................................................................................................... 4
Diagrama de Actions ........................................................................................................ 4
Diagramas de clases ........................................................................................................... 5
Estructura de directorios ..................................................................................................... 6
Cómo instalar la demo ........................................................................................................ 7
Cómo funciona el sistema .................................................................................................... 7
Aspectos relevantes ............................................................................................................ 8
Mecanismo para crear el mosaico de imágenes.................................................................... 8
template.htm .................................................................................................................. 9
row.htm ....................................................................................................................... 10
col.htm para imágenes (BLOBs) ...................................................................................... 10
Reducción dinámica de imágenes..................................................................................... 11
Cómo reutilizar y adaptar la plantilla................................................................................... 12
Notas importantes ......................................................................................................... 12
Procedimiento paso a paso.............................................................................................. 12
Biblioteca técnica
Página 1 de 14
Dinámica
El framework RADical
…J2EE sin complicaciones
Producido por:
Martín Córdova y Asociados C.A.
www.martincordova.com
martin.cordova@gmail.com
Sumario
Esta plantilla contiene un grid paginado con orientación horizontal, tipo "thumbnail" o mosaico,
ideal para galerías de imágenes o catálogos.
Esta solución es 100% libre de código, se apoya en las clases genéricas del framework y su
reutilización es muy simple.
La funcionalidad de esta plantilla es extraer imágenes de la base de datos y mostrarlas en un grid
paginado, usando funcionalidades de la plantilla PL009, por lo tanto esta orientada a aplicaciones
de negocios.
Para entender esta plantilla es necesario que esté familiarizado con la plantilla PL009 (BLOBs).
Este documento se apoya en las facilidades de esta plantilla, y no repite lo que ya se explicó en el
documento respectivo.
Para reutilizar esta plantilla requiere de conocimientos elementales de programación en Dinámica,
además de conocimientos básicos de SQL, DHTML y JavaScript.
Demo online permanente
Si desea probar como funciona esta plantilla, puede visitarla en este URL:
http://209.85.104.97/action/demo/hgrid/form
Corre con Tomcat 6, Java 6 y PostgreSQL 8.2.4.
Biblioteca técnica
Página 2 de 14
Dinámica
El framework RADical
…J2EE sin complicaciones
Producido por:
Martín Córdova y Asociados C.A.
www.martincordova.com
martin.cordova@gmail.com
Screenshots
Biblioteca técnica
Página 3 de 14
Dinámica
El framework RADical
…J2EE sin complicaciones
Producido por:
Martín Córdova y Asociados C.A.
www.martincordova.com
martin.cordova@gmail.com
Arquitectura de la solución
Diagrama de Actions
Biblioteca técnica
Página 4 de 14
Dinámica
El framework RADical
…J2EE sin complicaciones
Producido por:
Martín Córdova y Asociados C.A.
www.martincordova.com
martin.cordova@gmail.com
Diagramas de clases
Todas las clases requeridas por esta plantilla son genéricas, provistas por el framework.
Biblioteca técnica
Página 5 de 14
Dinámica
El framework RADical
…J2EE sin complicaciones
Producido por:
Martín Córdova y Asociados C.A.
www.martincordova.com
martin.cordova@gmail.com
Estructura de directorios
Biblioteca técnica
Página 6 de 14
Dinámica
El framework RADical
…J2EE sin complicaciones
Producido por:
Martín Córdova y Asociados C.A.
www.martincordova.com
martin.cordova@gmail.com
Cómo instalar la demo
1) Para correr la demo tal como está, requiere de la base de datos de demo de Dinámica, la
aplicación donde instale esta demo debe estar configurada para conectarse a esta base de
datos.
2) Se recomienda haber montado una aplicación Dinámica como un proyecto en Eclipse, para
que todo esté en su lugar y se compile automáticamente a medida que hace cambios o
añade clases.
3) Copiar el directorio “/templates/hgrid” a “/WEB-INF/action”, también lo puede copiar
dentro de un subdirectorio de “/action”, como “/action/demo” por ejemplo.
4) Navegar a: http://localhost/MiContexto/action/hgrid/form
donde “MiContexto” es el nombre de su aplicación o contexto.
Cómo funciona el sistema
1) El mecanismo arranca con la acción “form”, esta sirve
la página que inicializa todo el mecanismo, contiene los
DIVs donde irán apareciendo los resultados, así como todo
el javascript requerido por esta plantilla.
2) Cuando la página se carga invoca a la acción “search”
la cual hace una llamada ajax y muestra nuevamente el
indicador de progreso. Cuando el resultado llega, la
función que procesa la respuesta evalúa si se trata de una
respuesta JavaScript o un bloque de HTML, en este último
caso se esconde el DIV de progreso y se muestra el DIV
de resultado, sino se ejecuta el javascript recibido, que
invocará funciones ya residentes en la página para mostrar el resultado apropiadamente, por
ejemplo, hacer visible el panel de navegación y solicitar la primera página. Si la búsqueda no
arroja resultados, entonces se muestra un mensaje de “Datos no encontrados” servido por la
acción “notfound”.
3) Cuando retorna la repuesta de la acción “view”, se ejecuta un INCLUDE de la acción “hgrid”, la
cual ejecuta la clase genérica “HGridPagedOutput”. Esta clase leerá el query almacenado en
sesión e inyectara donde se encuentre marcadores especiales los registros encontrados, todo
previamente configurado en un archivo “confi.xml”.
Biblioteca técnica
Página 7 de 14
Dinámica
El framework RADical
…J2EE sin complicaciones
Producido por:
Martín Córdova y Asociados C.A.
www.martincordova.com
martin.cordova@gmail.com
Aspectos relevantes
Mecanismo para crear el mosaico de imágenes
La acción “view” ejecuta un INCLUDE hacia la acción “Hgrid”, la cual genera dinámicamente el
código para crear el efecto deseado.
<center>
${inc:${def:actionroot}/hgrid}
</center>
En la acción “hgrid” específicamente el archivo “config.xml”. La salida ejecuta la clase
“HGridPagedOutput”, la cual se alimenta de los elementos de configuración del hgrid y del
query.sql almacenado en sesión.
<?xml version='1.0' encoding='ISO-8859-1'?>
<config>
<summary>
Crea HGrid de los documentos cargados
</summary>
<log>false</log>
<output>
<classname>dinamica.HGridPagedOutput</classname>
<template>template.htm</template>
<set-http-headers>true</set-http-headers>
<content-type>text/plain; charset=iso-8859-1</content-type>
</output>
<!--hgrid config-->
<row-template>row.htm</row-template>
<col-template>col.htm</col-template>
<cols>3</cols>
<hgrid-recordset>query.sql</hgrid-recordset>
<!--end hgrid config-->
</config>
public void print(TemplateEngine te, GenericTransaction data)
throws Throwable
{
//read config values
String rsName = getConfig().getConfigValue("hgrid-recordset");
Biblioteca técnica
Página 8 de 14
Dinámica
El framework RADical
…J2EE sin complicaciones
Producido por:
Martín Córdova y Asociados C.A.
www.martincordova.com
martin.cordova@gmail.com
int cols = Integer.parseInt(getConfig().getConfigValue("cols"));
Recordset rs = (Recordset)getRequest().getAttribute(rsName);
String tRow = getResource(getConfig().getConfigValue("row-template"));
String tCol = getResource(getConfig().getConfigValue("col-template"));
//navigate recordset and create String containing
//hgrid body
StringBuffer hgrid = new StringBuffer();
rs.top();
for (int k=0;k<rs.getRecordCount();k=k+cols)
{
StringBuffer colsBuf = new StringBuffer();
for (int i=0;i<cols;i++)
{
if (k+i==rs.getRecordCount()) {
for (int j=i;j<cols;j++) {
colsBuf.append("<td></td>");
}
break;
}
rs.setRecordNumber(k+i);
TemplateEngine t = new
TemplateEngine(getContext(),getRequest(),tCol);
t.replace(rs, " ");
colsBuf.append(t.toString());
}
hgrid.append(StringUtil.replace(tRow,"${cols}", colsBuf.toString()));
}
//replace hgrid body into main template
te.replace("${hgrid}", hgrid.toString());
System.out.println(te.toString());
// let parent class execute normal processing of config.xml
super.print(te, data);
}
template.htm
Contiene un INCLUDE para poder añadirle controles de paginación al grid de imágenes. A su vez
contiene un marcador “${hgrid}“ en el cual se inyectará el bloque HTML que contendrá el grid de
imágenes.
<!--panel de control de navegacion-->
<div style="width:400px">
<span id="grid-progress" style="float:right;margin-right:20px;display:none">
Biblioteca técnica
Página 9 de 14
Dinámica
El framework RADical
…J2EE sin complicaciones
Producido por:
Martín Córdova y Asociados C.A.
www.martincordova.com
martin.cordova@gmail.com
<img src="${def:context}/images/progress.gif">
</span>
${inc:/action/pagecontrols}
</div>
<table width="450px">
${hgrid}
</table>
row.htm
Contiene un marcado ${cols} en el cual se inyectará las distintas columnas a partir de la cantidad
de registro encontrados e impresos en el “col.htm”.
<tr>
${cols}
</tr>
col.htm para imágenes (BLOBs)
Se imprime tantas columnas como registro de imágenes existan en la base de datos. Se hace
llamada a funciones en javascript residente en la acción ”form” que abrirán la imagen en un
popup o mostrar las barras de progresos mientras se cargan las imágenes.
<td valign="top" align="center" style="width:150px;backgroundcolor:#d8d8d8;padding:5px;font-size:8pt;font-family:Arial">
<div style="background-color:white; height:120px; padding-top:5px;">
<!--indicador de progreso de carga del chart-->
<div id="image_${fld:id}_wait" class="alert" style="margintop:5px;color:gray;width:120px;font-weight:normal;font-family:Arial">
<img src="${def:context}/images/progress.gif"> Cargando...
</div>
<img id="image_${fld:id}" style="display:none;width:100px;height:80px"
class="tool"
src="${def:context}/action/demo/blob/getblob?id=${fld:id}"
border="0" onload="displayImage('image_${fld:id}')"
onclick="openImage('${fld:id}','${def:context}${def:actionroot}/getimage?
id=${fld:id}')" title="Ver imagen">
<br>${fld:description}
</div>
Biblioteca técnica
Página 10 de 14
Dinámica
El framework RADical
…J2EE sin complicaciones
Producido por:
Martín Córdova y Asociados C.A.
www.martincordova.com
martin.cordova@gmail.com
</td>
//mostrar imagen y esconder su indicador de progreso de carga
function displayImage(imageID)
{
document.getElementById(imageID + "_wait").style.display='none';
document.getElementById(imageID).style.display='';
}
//invoca un popup para mostrar los documentos
function openImage(id,url)
{
var features =
"height=400,width=700,status=no,toolbar=no,menubar=no,location=no,scrollbars=yes,re
sizable=yes";
var w = window.open(url, id, features);}
Reducción dinámica de imágenes
Al atributo “src” del tag “img” que mostrarála imagen (en el template col.htm) se le puede añadir
un parámetro al URL para que el servidor envíe una copia reducida de la imagen, esto hace mucho
más eficiente al HGrid, ya que imágenes de 102K pueden resultar en 2K, por ejemplo, y es aun
más dramático para fotos JPEG con tamaños originales de 2MB o más, con la reducción pueden
llegar a 45K-50K. El parámetro que debe añadirse se llama “scale” y representa el porcentaje al
cual debe reducirse la imagen en ancho y largo. Ejemplo:
<img src="${def:context}/action/demo/blob/getblob?id=${fld:id}&scale=0.25"…>
Retorna imágenes reducidas a un 25%, esto es recomendable para los Thumbnails o galerías de
imágenes.
De ser posible las imágenes se retornan como JPEG, pero si originalmente estaban en formato
PNG, se retornarán como PNG reducidas, para evitar problemas de corrupción en la
transformación de formato que puede ocurrir con PNGs de muy alta resolución, según hemos
observado en nuestras pruebas. Los GIF son retornados como JPEGs. Las imágenes menores a
20K no son reducidas, no se justifica, además de que puede producir una pérdida de calidad muy
severa en la versión reducida.
Solo se modificó la clase “dinamica.BlobOutputPGSQL”, y esta clase solo intentará reducir la
imagen si:
•
•
•
Se trata en efecto de una imagen.
El parámetro “scale” está presente (debe ser un double entre 0 y 1) en el request.
La imagen pesa más de 20K.
Biblioteca técnica
Página 11 de 14
Dinámica
El framework RADical
…J2EE sin complicaciones
Producido por:
Martín Córdova y Asociados C.A.
www.martincordova.com
martin.cordova@gmail.com
Para lograr la reducción dinámica de la imagen en el servidor, se utilizó el API estándar de manejo
de imágenes de Java, la clase BufferedImage, la clase ImageIO y las clases para transformaciones
de imágenes, principalmente. El pequeño bloque que se añadió a la clase afectada es este:
//scale image if requested
if (blob.length > 20000 && scaleFactor > 0 && info.getString("format").startsWith("image/")) {
BufferedImage bufimg = ImageIO.read(new ByteArrayInputStream(blob));
AffineTransform tx = new AffineTransform();
tx.scale(scaleFactor, scaleFactor);
AffineTransformOp op = new AffineTransformOp(tx,
AffineTransformOp.TYPE_NEAREST_NEIGHBOR);
BufferedImage newImg = op.filter(bufimg, null);
ByteArrayOutputStream bout = new ByteArrayOutputStream();
if (info.getString("format").endsWith("png"))
ImageIO.write(newImg, "png", bout);
else
ImageIO.write(newImg, "jpg", bout);
blob = bout.toByteArray();
}
Cómo reutilizar y adaptar la plantilla
Notas importantes
•
Sugerimos ejecutar estos pasos con Eclipse, simplifica mucho todas las tareas que tendrá
que ejecutar.
•
Es conveniente que antes de reutilizar la plantilla, la haya corrido contra la base de datos
de demo. Así tendrá una comprensión cabal desde la óptica del usuario de lo que hace la
plantilla.
•
Recuerde que la plantilla tiene un propósito específico, pueden ser necesarias algunas
modificaciones para lograr un efecto particular.
Procedimiento paso a paso
1. Crear un directorio debajo de “/WEB-INF/action” o debajo de una subcarpeta dentro de
esta ubicación. Escoja un nombre apropiado para su modulo, que también sirva como
nombre para el paquete de clases Java que requerirá mas adelante.
Biblioteca técnica
Página 12 de 14
Dinámica
El framework RADical
…J2EE sin complicaciones
Producido por:
Martín Córdova y Asociados C.A.
www.martincordova.com
martin.cordova@gmail.com
2. Copiar todo el contenido de “/hgrid” a su nueva carpeta. El contenido solamente, no copie
la carpeta “hgrid”.
3. Cambiar la acción “search”, modificar el query.sql para que se adapte a la tabla de archivo
(imagenes) que se usará. Tener en cuenta la condición para solo retorne data donde el
content_type sea de tipo “image”.
select
id,
filename,
content_type,
(image_size / 1024) as image_size,
description
from demo.imagebank
where
upper (content_type) like upper('%image%')
order by id
4. Copiar la acción “getblob” de la plantilla “PL009” para manejo de BLOBs y pegarla dentro
del directorio en el que se está trabajando. Esta acción contiene un “config.xml” el cual
deberá ser modificado para el caso que se use una base de datos distinta de Postgres SQL.
<?xml version='1.0' encoding='ISO-8859-1'?>
<config>
<summary>
Muestra un documento
</summary>
<log>false</log>
<transaction>
<classname>dinamica.GetBlob</classname>
<validator>true</validator>
<transaction>false</transaction>
<jdbc-log>false</jdbc-log>
</transaction>
<output>
<!--for databases other than PostgreSQL use dinamica.BlobOutput-->
<classname>dinamica.BlobOutputPGSQL</classname>
</output>
<!--custom element for THIS Action only-->
<!-set to true if you want to force a "Save as" dialog
when the browser downloads the BLOB - your query-info.sql
template MUST contain a "filename" column.
Biblioteca técnica
Página 13 de 14
Dinámica
El framework RADical
…J2EE sin complicaciones
Producido por:
Martín Córdova y Asociados C.A.
www.martincordova.com
martin.cordova@gmail.com
-->
<attach>false</attach>
</config>
4.1
Modificar el “query-blob.sql” para que se adapte a la tabla que se usará.
select
image_data
from demo.imagebank
where id = ${fld:id}
4.2
Modificar el “query-info.sql” para que se adapte a la tabla que se usará.
select
content_type,
filename
from demo.imagebank
where id = ${fld:id}
5. Cambiar la acción “hgrid”, modifique “col.htm” para que apunte a la acción “getblob” que
generará la imagen almacenada en la base de datos.
6. Cambiar la acción “getimage”, modificar “template.htm” para que apunte a la acción
“getblob” que generará la imagen.
Recuerde que para probar su nuevo modulo debe navegar a la acción de entrada del mecanismo,
en este caso “/form”. La ruta en el browser dependerá de cómo haya nombrado su carpeta raíz
(en vez de “hgrid”) y donde la ubicó dentro de “/WEB-INF/action/….”.
Biblioteca técnica
Página 14 de 14
Descargar