# HBean
## Introducción

El desarrollo de aplicaciones web con formularios presenta algunas problemáticas comunes:
* Una arquitectura tradicional basada en Servlets y páginas JSPs requiere un número de clases y páginas JSPs proporcional al número de formularios. Cuando el número de formularios es elevado también lo es la cantidad de código a desarrollar y mantener.
* Se necesita utilizar una gran variedad de elementos html que además deben mantener una coherencia de funcionalidad y estilo en todos los formularios. Mantener la coherencia requiere un esfuerzo notable y difícil de comprobar, la técnica de copiar y pegar acentúa más este problema, cualquier error o cambio se propaga por todos los formularios.
* Se produce un fuerte acoplamiento entre el objeto que contiene los datos y el código que visualiza el formulario. Cambiar el tamaño de un 'input' del formulario requiere que el programador modifique el código para cada una de las jsps o servlets dónde se muestra el formulario. En el caso de utilizar servlets además es necesario volver a compilar y reiniciar el servidor de aplicaciones, con los inconvenientes que conlleva.
* Incrustar y programar el código javascript de validación de cada componente HTML del formulario es costoso, difícil de depurar y adolece de estar continuamente en prueba y error. Se requiere ejecutar código javascript por ejemplo para validar que el usuario ha entrado un número positivo, o comprobar que el número de caracteres entrados para el NIF del formulario es 9.
* Todos los formularios deben implementar algún tipo de estrategia para mostrar los textos en diferentes idiomas, no tener un control centralizado sino diversificado por múltiples páginas dificulta la implementación.
* La recogida de datos del formulario requiere una programación pesada y repetitiva para establecer cada atributo del objeto con el valor del formulario relacionado.
* «Proyecto HBean Opensource». Código abierto.
Los HBeans (acrónimo de HTML Beans) son beans orientados a crear y gestionar formularios y sus objetos relacionados de manera homogénea, sus características básicas:
* Generación automática de formularios HTML.
* Generación automática de código de validación Javascript.
* Gestión automática de recogida y establecimiento de valores del formulario.
* Sustitución de etiquetas.
* Lenguaje declarativo en XML.
* Bajo acoplamiento entre contenido y vista.
* Promueve la división de tareas.
* Son extensibles. Permite crear nuevos elementos HTML y funciones Javascript.
* Los prototipos pueden cambiar "en caliente" sin tener que volver a compilar ni reiniciar el servidor.
El siguiente diagrama muestra los componentes con los que se construye un HBean:
El bean es el bean de negocio que se gestiona en el formulario. Contiene todos los getXXX y setXXX para cada atributo del objeto.
El prototipo define mediante xml las propiedades de cada atributo del bean en el formulario, si es editable o no, tamaño, descripción, editor, etc.
El descriptor es un objeto que implementa la interfaz HBeanDescriptor y tiene asociado el bean de negocio. Podemos tener cualquier número de prototipos y descriptores apuntando a un mismo bean de negocio.
El descriptor también permite especificar en tiempo de ejecución algunas propiedades en lugar de obtenerlas del prototipo. Por ejemplo, el siguiente método define el valor de la propiedad enabled:
Estos métodos deben seguir la nomenclatura: hbeanXXXAtributoXXX, el mismo método para el atributo Horas se definiría como hbeanIsHorasEnabled.

## Guía

A continuación se describen los diferentes actores que conforman el uso y aplicación de los HBeans.
* Prototipos
* Descriptor
* HBean
* Editores
* Validación JavaScript
* Etiquetas y Variables

## Prototipos

Para obtener un hbean se pide al contenedor un hbean según un prototipo y descriptor.
Dónde Tarea.hbean es el nombre del prototipo. El contenedor se configura previamente con un objeto PrototypeLoader que se encarga de buscar y acceder al prototipo. Podemos utilizar el cargador de prototipos por defecto que nos permite especificar un directorio dónde buscar los prototipos.
Este cargador por defecto resuelve los nombres de los prototipos siguiendo la misma lógica que la definición de paquetes Java, el prototipo intranet.Tarea hace referencia al fichero WEB-INF/repository/intranet/Tarea.hbean (la extensión .hbean se debe omitir).
El contenedor instancia un nuevo HBean clonando el prototipo y añadiendo las propiedades definidas en el descriptor.
Los prototipos se crean bajo demanda y se guardan en el contenedor junto con información sobre el descriptor. Después de que el prototipo ha sido creado si modificamos el prototipo solo tenemos que vaciar la caché del contenedor para que los cambios tengan efecto, podemos hacerlo por código o directamente desde el navegador:
O desde el navegador
http://localhost:8080/.../miContexto/manager?action=reset Para borrar los prototipos guardados.
http://localhost:8080/.../miContexto/manager?action=list Para listar los prototipos instalados.

## Descriptor

El descriptor tiene asociado un único bean de negocio.
Aunque puede existir de forma separada, la forma más fácil es definir los métodos del descriptor en la misma clase del Bean. En los ejemplos la clase Tarea se define como:
El método hbeanGetPrimaryKey debe identificar al hbean de forma única dentro del formulario, normalmente coincidirá con el identificador del objeto en base de datos pero no tiene porque ser así, es suficiente que dentro del formulario no exista ningún otro objeto de su misma clase con su misma clave.
Puesto que el ejemplo no trabaja con bases de datos se ha añadido el método hbeanSetPrimaryKey de forma que se pueda establecer desde la JSP.
Además de implementar los métodos de la interfaz HBeanDescriptor un descriptor puede implementar métodos de propiedades no definidas en el prototipo, por ejemplo el método
equivale a la entrada <value-set> del XML del prototipo. Si no lo definimos en el prototipo entonces el contenedor mira si existe el método hbeanGetXXXValues para ese atributo. Estos métodos deben seguir la nomenclatura: hbeanXXXPPP dónde XXX es "Get" o "Is" más el nombre del atributo, y PPP es el nombre de la propiedad.
La correspondencia entre los métodos del descriptor y el XML del prototipo son:
| Método Descriptor | XML Prototipo |
| boolean hbeanIsNombreEnabled | <attribute name='Nombre' ... enabled='yes'> |
| boolean hbeanGetHorasValues | <value-set>.. <value name='0'>0<value> .. <value-set> |
| boolean hbeanGetHorasJavascripts | <js-validation>.. <js-function> .. <js-validation> |

## HBean

Un hbean se obtiene del contenedor a partir de un descriptor y un prototipo:
Una vez obtenido el hbean podemos acceder a sus atributos y generar el html del formulario, o modificar cualquiera de sus propiedades.
Para guardar los datos que el usuario pueda introducir en el formulario html creamos un objeto Setter:
También podemos especificar más de un atributo especificando un iterador. Un iterador se define en el prototipo mediante los tags.
Utilizando el nombre del iterador (en este caso lista):

## Editores

Los editores corresponden con los componentes HTML que permiten una interacción con el usuario: listas, casillas de verifación, botones de radio, etc ... En cada atributo del prototipo se define el editor a utilizar, si no se especifica el contenedor buscará un editor que se ajuste al tipo de valor utilizado por el método "get" del bean para ese atributo.
Atributo horas en Bean:
XML prototipo:
puesto que IntegerEditor es el editor por defecto para atributos que retornan enteros no haría falta establecerlo, tendríamos el mismo resultado con:
Los editores disponibles en la versión 1.0 son
| Clase | Tipo | Descripción |
| com.it.hbean.editor.BooleanEditor | boolean, Boolean | *Editor por defecto si no especifica |
| com.it.hbean.editor.DateEditor | java.util.Date | *Editor por defecto si no especifica |
| com.it.hbean.editor.FileEditor | String | Editor por subir ficheros |
| com.it.hbean.editor.FloatEditor | float, Float | *Editor por defecto si no especifica |
| com.it.hbean.editor.ImageEditor | String | Editor por subir ficheros de imagen |
| com.it.hbean.editor.IntegerEditor | int, Integer | *Editor por defecto si no especifica |
| com.it.hbean.editor.IntegerSelectEditor | int, Integer | Selector listas |
| com.it.hbean.editor.StringCheckboxEditor | String | Editor de opciones múltiples (casillas de verificación) |
| com.it.hbean.editor.StringEditor | String | *Editor por defecto si no especifica |
| com.it.hbean.editor.StringRadioEditor | String | Editor de opciones múltiples (botones de radio) |
| com.it.hbean.editor.StringSelectEditor | String | Editor de opciones múltiples (tipo selector) |
| com.it.hbean.editor.TextAreaEditor | String | Editor zona de texto libre |
| Nuevos editores | | |
| com.it.hbean.editor.BankCCCEditor | int, int, int, int | Editor de cuenta bancaria CCC (20 dígitos) |
| com.it.hbean.editor.NifEditor | int, String | Editor de Identificación fiscal (NIF) |

## Validación JavaScript

El código de validación puede generarse automáticamente mediante el objeto JavascriptCoder.
El código javascript se genera a partir de las definiciones de validación definidas en el prototipo:
Dónde js-name es el nombre de la función de javascript y las entradas js-param son cada uno de los argumentos que se pasan a la función. Cómo primer argumento se añade automáticamente el id del componente HTML en el formulario.
Podemos utilizar alguna de las funciones de javascript disponibles en el fichero hbean.js:
* checkNoEmpty(name, errorMsg)
* checkPassword(name, errorMsg)
* checkFloat(name, decimalChar, groupingChar, errorMsg)
* checkInteger(name, errorMsg)
* checkPositiveFloat(name, decimalChar, groupingChar, errorMsg)
* checkBetween(name, minimus, maximus, errorMsg)
* checkInteger(name, errorMsg)
* checkPositive(name, errorMsg)
* checkDate(name, errorMsg)
* checkLengthMandatory(name, len, errorMsg)
* checkLength(name, len, errorMsg)
* checkLetraNIF(name, errorMsg)
* checkEmail(name, errorMsg)

## Etiquetas y Variables

Las etiquetas sirven para insertar texto en tiempo de ejecución, esto puede ser útil para mostrar texto según el usuario actual, el idioma seleccionado o cualquier otra condición. Una etiqueta se define añadiéndola entre los caracteres #{ y } . El ejemplo MultiIdioma.jsp utiliza etiquetas para mostar texto en diferentes idiomas y variables para cambiar la foto de la mascota seleccionada con el texto adecuado.
El prototipo Persona.hbean utiliza una etiqueta para el nombre que será sustituida por "Nombre", "Nom" o "Name" según el idioma seleccionado:
Para resolver la etiqueta se utiliza un objeto que implemente la interfaz com.it.hbean.LabelResolver establecido en el objeto com.it.hbean.Configuration del contenedor. El contenedor busca entre el texto las etiquetas y las sustituye llamando al método de la interfaz LabelResolver.
Internamente es el objeto com.it.hbean.Compiler quién sustituye las etiquetas. Podemos llamar directamente a sus métodos para sustituir cualquier otro texto que queramos incluir.
En el ejemplo se utiliza el objeto com.it.hbean.test.Diccionario como LabelResolver y se establece a la configuración en la jsp index.jsp. El objeto Diccionario accede a tres ficheros de propiedades: data.es, data.ct y data.en según el idioma sea castellano, catalán o inglés.
De la misma forma que utilizamos etiquetas para sustituir texto en tiempo de ejecución utilizamos variables para referenciar valores de atributos que se desconocen hasta el momento de ejecución. Una variable se define añadiéndola entre los caracteres ${ y }. Las variables que podemos utilizar están definidas como constantes en el mismo objeto com.it.hbean.HBeanAttribute.
El ejemplo MultiIdioma.jsp utiliza las variables ${Nombre.Id} y ${Mascota.Id} que referencian el elemento html del atributo nombre y los botones de radio del atributo mascota. Cuando la selección de mascota cambia se muestra la foto de la mascota y el texto "La mascota de [Nombre]"

## Arquitectura

En el diagrama adjunto podemos apreciar la arquitectura del sistema de HBeans.