xesthproyecto
TRANSCRIPT
Facultad de Informatica de la Universidad de A CorunaDepartamento de Tecnologıas de la Informacion y las Comunicaciones
PROYECTO DE FIN DE CARRERA
INGENIERIA TECNICA INFORMATICA DE GESTION
Diseno e Implementacion de una Aplicacion Web Java EEcon Arquitectura MVC Destinada a Gestionar las
Actividades de un Hotel
Alumno: Sergio Padın Varela
Director: Carlos Alberto Pan Bermudez
Fecha: 29 de septiembre de 2009
A mis padres, mi hermano, mis abuelos y a toda mi familia, por su apoyo y ayuda
incondicional. A todos mis amigos por los buenos momentos que me han regalado. Y a
mi novia por todo el carino, apoyo y animo que me ha dado en todo momento. A todos
ellos, muchısimas gracias.
Sergio Padın Varela
3
5
Dr. Carlos Alberto Pan Bermudez
Profesor de la Faculdad de Informatica de la Coruna
Departamento de Tecnologıas de la Informacion y las Comunicaciones
Universidad de A Coruna
CERTIFICA: Que la memoria titulada “Diseno e Implementacion de una Aplicacion
Web Java EE con Arquitectura MVC Destinada a Gestionar las Actividades de un Hotel”
ha sido realizada por Sergio Padın Varela bajo mi direccion y constituye su Proyecto
de Fin de Carrera de Ingenierıa Tecnica Informatica de Gestion.
En A Coruna, a 25 de septiembre de 2009
Dr. Carlos Alberto Pan Bermudez
Director del proyecto
7
Resumen:
El proyecto realizado consiste en desarrollar una Aplicacion Web para la gestion de
las reservas de un hotel o similar. Tambien hay que desarrollar todo lo necesario para la
realizacion de reservas, incluyendo entre otros la gestion de clientes y usuarios de la web,
las habitaciones, y los pagos de las mismas.
Ademas tambien se desarrolla un complejo sistema de ofertas, donde se permite crear
ofertas que puedan ser incompatibles unas con otras y basadas en reglas de aplicacion,
altamente configurables para especificar el contexto al cual se le puede aplicar dicha oferta.
Estas luego son utilizadas dinamicamente a la hora de realizar la factura que tiene que
abonar el cliente, en donde se calcula el conjunto de ofertas compatibles entre sı que mayor
descuento proporcionan sobre la factura.
La Aplicacion distingue tres roles principales: el usuario/cliente (de ahora en adelante el
cliente), el recepcionista y el administrador. Cada uno puede realizar una serie operaciones
sobre la aplicacion.
El cliente puede realizar reservas, consultar las ya realizadas y pagarlas o cancelarlas,
ver disponibilidad de habitaciones, y todas las operaciones relacionadas con altas, bajas o
actualizaciones de su perfil web.
Por otro lado el recepcionista puede gestionar los clientes, dandolos de alta, de baja,
actualizar sus perfiles o realizar reservas a su nombre. Para todo ello el recepcionista puede
buscar a los clientes por uno o mas parametros. Tambien tiene la posibilidad de cobrar
una reserva a un cliente o cancelarla, entre otras cosas.
El administrador es el usuario de la aplicacion que mas privilegios tiene. Este puede
anadir habitaciones, modificar precios y mantener todo el sistema de ofertas. Creando
nuevas ofertas, modificandolas, publicandolas o dandolas de baja. Este apartado es muy
delicado debido a las relaciones de incompatibilidad entre ofertas y a las reglas que estas
utilizan para saber si se pueden aplicar en determinados contextos.
9
Lista de palabras clave:
Aplicacion Web, Java, J2EE, MVC, Struts, Apache Tomcat, MySQL, HTML, XML,
CSS, JSP, JSPX, JSTL, Tiles, JDBC, Data Access Object (DAO), Value Object (VO),
Hotel, Reserva, Facturacion, Ofertas, Reglas, Incompatibilidades.
Agradecimientos1
A D. Carlos Alberto Pan Bermudez (Profesor de la Facultad de Informatica, Universidad
de A Coruna), por la orientacion durante la realizacion del proyecto, ası como su ayuda a la
hora de resolver problemas puntuales durante el diseno e implementacion de la aplicacion.
A Dna. Marıa Luisa Carpente Rodrıguez (Profesor de la Facultad de Informatica, Uni-
versidad de A Coruna), por su ayuda a la hora de resolver de forma practica el grafo de
incompatibilidades entre las ofertas.
1En orden alfabetico
11
Indice general
Introduccion XIII
1. Herramientas y tecnologıas utilizadas 1
1.1. Herramientas y tecnologıas para el Diseno . . . . . . . . . . . . . . . . . . . 1
1.2. Herramientas y tecnologıas para la Implementacion . . . . . . . . . . . . . . 2
1.3. Herramientas y tecnologıas para la Documentacion . . . . . . . . . . . . . . 10
2. Estado actual de las tecnologıas utilizadas 13
3. Estudio de viabilidad 17
4. Introduccion al desarrollo realizado 21
4.1. El Proceso Unificado . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
4.2. El Proceso Unificado en este Proyecto . . . . . . . . . . . . . . . . . . . . . 24
5. Requisitos del Sistema 29
5.1. Introduccion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
5.2. Actores . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
5.3. Casos de Uso . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
i
Indice general ii
5.3.1. Gestion de Usuarios Web . . . . . . . . . . . . . . . . . . . . . . . . 34
5.3.2. Gestion de Reservas Web . . . . . . . . . . . . . . . . . . . . . . . . 40
5.3.3. Gestion de Clientes . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
5.3.4. Gestion de Reservas . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
5.3.5. Gestion de Habitaciones . . . . . . . . . . . . . . . . . . . . . . . . . 60
5.3.6. Gestion de Ofertas . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68
5.4. Modelo de Casos de Uso . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78
5.4.1. Gestion de Usuarios Web . . . . . . . . . . . . . . . . . . . . . . . . 78
5.4.2. Gestion de Reservas Web . . . . . . . . . . . . . . . . . . . . . . . . 79
5.4.3. Gestion de Clientes . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80
5.4.4. Gestion de Reservas . . . . . . . . . . . . . . . . . . . . . . . . . . . 81
5.4.5. Gestion de Habitaciones . . . . . . . . . . . . . . . . . . . . . . . . . 82
5.4.6. Gestion de Ofertas . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83
6. Diseno de la aplicacion 85
6.1. Arquitectura General . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85
6.2. Capa de la Vista . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87
6.2.1. Hojas de Estilo - CSS . . . . . . . . . . . . . . . . . . . . . . . . . . 88
6.2.2. Paginas JSP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88
6.2.3. ActionForms . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91
6.2.4. Internacionalizacion . . . . . . . . . . . . . . . . . . . . . . . . . . . 91
6.2.5. ApplicationObjects . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93
6.3. Capa del Controlador . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93
Indice general iii
6.3.1. Patron Front Controller . . . . . . . . . . . . . . . . . . . . . . . . . 94
6.3.2. Patron Chain of Responsability . . . . . . . . . . . . . . . . . . . . . 96
6.3.3. Acciones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98
6.3.4. Clases de Utilidad y Soporte a Acciones . . . . . . . . . . . . . . . . 99
6.4. Arquitectura del Modelo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102
6.4.1. Persistencia de los Datos . . . . . . . . . . . . . . . . . . . . . . . . . 104
6.4.2. Patrones Utilizados en el Modelo . . . . . . . . . . . . . . . . . . . . 111
6.4.3. Capa de Acceso a la Base de Datos . . . . . . . . . . . . . . . . . . . 117
6.4.4. Descripcion de los Subsistemas . . . . . . . . . . . . . . . . . . . . . 131
6.4.5. Sistema de Soporte - Modelo de Ofertas . . . . . . . . . . . . . . . . 166
7. Implementacion 183
7.1. Detalles Especıficos de la Implementacion . . . . . . . . . . . . . . . . . . . 183
7.2. Implementacion de las Base de Datos . . . . . . . . . . . . . . . . . . . . . . 185
7.2.1. Implementacion de la Base de Datos General . . . . . . . . . . . . . 185
7.2.2. Implementacion de la Base de Datos de Ofertas . . . . . . . . . . . . 190
7.3. Implementaciones del Sistema de Ofertas . . . . . . . . . . . . . . . . . . . 192
7.4. Software Necesario para Desplegar la Aplicacion . . . . . . . . . . . . . . . 204
7.4.1. Instalacion y Configuracion del Software Necesario . . . . . . . . . . 204
7.5. Organizacion de los Directorios del Proyecto . . . . . . . . . . . . . . . . . . 208
7.6. Instrucciones de Compilacion y Despliegue . . . . . . . . . . . . . . . . . . . 209
8. Pruebas 211
Indice general iv
9. Planificacion y Evaluacion de Costes 213
10.Conclusiones y Futuras Lıneas de Trabajo 217
A. Manuales para la Utilizacion de la Aplicacion 221
A.1. Manual Comun a Todos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 221
A.2. Manual Especıfico para el Usuario . . . . . . . . . . . . . . . . . . . . . . . 225
A.3. Manual Especıfico para el Recepcionista . . . . . . . . . . . . . . . . . . . . 231
A.4. Manual Especıfico para el Administrador . . . . . . . . . . . . . . . . . . . 239
B. Licencia del Proyecto - GPLv3 251
B.1. General Public License (Version 3) . . . . . . . . . . . . . . . . . . . . . . . 251
Indice de figuras
4.1. Grafico del Proceso Unificado . . . . . . . . . . . . . . . . . . . . . . . . . . 22
5.1. CU: Gestion de Usuarios Web . . . . . . . . . . . . . . . . . . . . . . . . . . 78
5.2. CU: Gestion de Reservas Web . . . . . . . . . . . . . . . . . . . . . . . . . . 79
5.3. CU: Gestion de Clientes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80
5.4. CU: Gestion de Reservas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81
5.5. CU: Gestion de Habitaciones . . . . . . . . . . . . . . . . . . . . . . . . . . 82
5.6. CU: Gestion de Ofertas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83
6.1. MVC - Arquitectura General Del Sistema . . . . . . . . . . . . . . . . . . . 86
6.2. Capa Vista . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87
6.3. Plantilla Ventana . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89
6.4. Resultado Final . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90
6.5. Patron Front Controller General . . . . . . . . . . . . . . . . . . . . . . . . 95
6.6. Paquetes - Distribucion de Acciones . . . . . . . . . . . . . . . . . . . . . . 99
6.7. Diagrama Aplicacion de Front Controller . . . . . . . . . . . . . . . . . . . 100
6.8. Diagrama Entidad Relacion - General . . . . . . . . . . . . . . . . . . . . . 107
v
Indice de figuras vi
6.9. Modelo Relacional - General . . . . . . . . . . . . . . . . . . . . . . . . . . . 108
6.10. Diagrama Entidad Relacion - Ofertas . . . . . . . . . . . . . . . . . . . . . . 110
6.11. Modelo Relacional - Ofertas . . . . . . . . . . . . . . . . . . . . . . . . . . . 111
6.12. Diagrama de Value Object . . . . . . . . . . . . . . . . . . . . . . . . . . . . 112
6.13. Diagrama de Data Access Object . . . . . . . . . . . . . . . . . . . . . . . . 113
6.14. Diagrama de Data Access Object Utilizado . . . . . . . . . . . . . . . . . . 114
6.15. Diagrama de Session Facade y Business Delegate . . . . . . . . . . . . . . . 116
6.16. Diagrama del Procesador de Acciones . . . . . . . . . . . . . . . . . . . . . 117
6.17. Estructura de los paquetes DAO y VO . . . . . . . . . . . . . . . . . . . . . 118
6.18. Diagrama General de los DAO . . . . . . . . . . . . . . . . . . . . . . . . . 118
6.19. Diagrama del Paquete ’persona’ . . . . . . . . . . . . . . . . . . . . . . . . . 119
6.20. Diagrama del Paquete ’tipohabitacion’ . . . . . . . . . . . . . . . . . . . . . 120
6.21. Diagrama del Paquete ’habitacion’ . . . . . . . . . . . . . . . . . . . . . . . 121
6.22. Diagrama del Paquete ’esdetipo’ . . . . . . . . . . . . . . . . . . . . . . . . 122
6.23. Diagrama del Paquete ’incidencia’ . . . . . . . . . . . . . . . . . . . . . . . 123
6.24. Diagrama del Paquete ’lineadereserva’ . . . . . . . . . . . . . . . . . . . . . 124
6.25. Diagrama del Paquete ’reserva’ . . . . . . . . . . . . . . . . . . . . . . . . . 125
6.26. Diagrama del Paquete ’factura’ . . . . . . . . . . . . . . . . . . . . . . . . . 126
6.27. Diagrama del Paquete ’tipooferta’ . . . . . . . . . . . . . . . . . . . . . . . 127
6.28. Diagrama del Paquete ’oferta’ . . . . . . . . . . . . . . . . . . . . . . . . . . 128
6.29. Diagrama del Paquete ’aplicablea’ . . . . . . . . . . . . . . . . . . . . . . . 129
6.30. Diagrama del Paquete ’incompatiblecon’ . . . . . . . . . . . . . . . . . . . . 130
Indice de figuras vii
6.31. Diagrama Simple de Gestion de Usuarios . . . . . . . . . . . . . . . . . . . 132
6.32. Actions y Exceptions de Gestion de Usuarios . . . . . . . . . . . . . . . . . 132
6.33. Diagrama Simple de Gestion de Clientes . . . . . . . . . . . . . . . . . . . . 135
6.34. Actions y Exceptions de Gestion de Clientes . . . . . . . . . . . . . . . . . . 136
6.35. Diagrama Simple de Gestion de Reservas . . . . . . . . . . . . . . . . . . . 139
6.36. Actions y Exceptions de Gestion de Reservas . . . . . . . . . . . . . . . . . 140
6.37. Diagrama Simple de Gestion de Habitaciones . . . . . . . . . . . . . . . . . 145
6.38. Actions de Gestion de Habitaciones . . . . . . . . . . . . . . . . . . . . . . . 146
6.39. Diagrama Simple de Gestion de Tipos de Ofertas . . . . . . . . . . . . . . . 151
6.40. Actions de Gestion de Tipos de Ofertas . . . . . . . . . . . . . . . . . . . . 152
6.41. Diagrama Simple de Gestion de Ofertas . . . . . . . . . . . . . . . . . . . . 156
6.42. Actions de Gestion de Ofertas . . . . . . . . . . . . . . . . . . . . . . . . . . 157
6.43. Diagrama de la Interfaz Ofertable . . . . . . . . . . . . . . . . . . . . . . . . 160
6.44. Diagrama Simple de Gestion de Facturas . . . . . . . . . . . . . . . . . . . . 162
6.45. Actions y Exceptions de Gestion de Facturas . . . . . . . . . . . . . . . . . 163
6.46. Diagrama del Sistema de Reglas . . . . . . . . . . . . . . . . . . . . . . . . 173
6.47. Diagrama de clase BestSetOfOffers . . . . . . . . . . . . . . . . . . . . . . . 176
6.48. Diagrama de las Clases Calculadoras . . . . . . . . . . . . . . . . . . . . . . 178
6.49. Diagrama Simple del Sistema de Ofertas . . . . . . . . . . . . . . . . . . . . 181
6.50. Diagrama Secuencia de la Accion de Calcular . . . . . . . . . . . . . . . . . 182
9.1. Planificacion - Diagrama de Gantt . . . . . . . . . . . . . . . . . . . . . . . 215
10.1. Gestion de Reservas de Otra Aplicacion . . . . . . . . . . . . . . . . . . . . 218
Indice de figuras viii
A.1. Pagina Principal del Portal . . . . . . . . . . . . . . . . . . . . . . . . . . . 222
A.2. Pagina Registro de Nuevo Usuario . . . . . . . . . . . . . . . . . . . . . . . 222
A.3. Pagina Autentificacion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 223
A.4. Pagina Principal del Usuario . . . . . . . . . . . . . . . . . . . . . . . . . . 225
A.5. Pagina de Aviso al Darse de Baja . . . . . . . . . . . . . . . . . . . . . . . . 226
A.6. Pagina para Realizar una Nueva Reserva . . . . . . . . . . . . . . . . . . . . 227
A.7. Pagina para Listar las Reservas . . . . . . . . . . . . . . . . . . . . . . . . . 228
A.8. Pagina para Modificar una Reserva . . . . . . . . . . . . . . . . . . . . . . . 229
A.9. Pagina para Mostrar el Borrador de una Factura . . . . . . . . . . . . . . . 229
A.10.Pagina para Mostrar una Factura Pagada . . . . . . . . . . . . . . . . . . . 230
A.11.Pagina Principal del Recepcionista . . . . . . . . . . . . . . . . . . . . . . . 231
A.12.Pagina para Listar las Habitaciones para el Recpecionista . . . . . . . . . . 232
A.13.Pagina para Mostrar los Datos de un Tipo de Habitacion . . . . . . . . . . 233
A.14.Pagina para Dar de Alta un Nuevo Cliente . . . . . . . . . . . . . . . . . . 234
A.15.Pagina para Buscar Clientes . . . . . . . . . . . . . . . . . . . . . . . . . . . 235
A.16.Pagina para Listar los Clientes Buscados . . . . . . . . . . . . . . . . . . . . 235
A.17.Pagina Principal del Recepcionista Despues de Seleccionar Cliente . . . . . 236
A.18.Pagina Principal del Administrador . . . . . . . . . . . . . . . . . . . . . . . 239
A.19.Pagina para Crear una Nueva Oferta . . . . . . . . . . . . . . . . . . . . . . 240
A.20.Pagina para Crear una Nueva Oferta (Rellenada) . . . . . . . . . . . . . . . 241
A.21.Pagina para Crear un Nuevo Tipo de Oferta . . . . . . . . . . . . . . . . . . 243
A.22.Pagina para Listar las Ofertas . . . . . . . . . . . . . . . . . . . . . . . . . . 244
Indice de figuras ix
A.23.Pagina para Realizar Operaciones con las Ofertas . . . . . . . . . . . . . . . 244
A.24.Pagina para Realizar Operaciones con los Tipos de Ofertas . . . . . . . . . 245
A.25.Pagina para Dar de Alta una Habitacion . . . . . . . . . . . . . . . . . . . . 246
A.26.Pagina para Crear un Nuevo Tipo de Habitacion . . . . . . . . . . . . . . . 246
A.27.Pagina para Listar las Habitaciones para el Administrador . . . . . . . . . . 247
A.28.Pagina para Consultar/Modificar los Datos de una Habitacion . . . . . . . 248
A.29.Pagina para Consultar/Modificar los Datos de un Tipo de Habitacion . . . 248
A.30.Pagina para Listar las Incidencias de una Habitacion . . . . . . . . . . . . . 249
A.31.Pagina para Registrar una Incidencia de una Habitacion . . . . . . . . . . . 250
Indice de cuadros
3.1. Tabla de costes para estudio de viabilidad . . . . . . . . . . . . . . . . . . . 18
9.1. Planificacion - Tabla de Tareas . . . . . . . . . . . . . . . . . . . . . . . . . 214
xi
Introduccion
Determinacion de la situacion actual
En la actualidad el turismo es una fuente indiscutible de ingresos para muchas zonas, e
Internet llega casi a todos los rincones del mundo, por eso es una de las mejores formas de
dar a conocer negocios de todo tipo. Es especialmente util a la hora de ofrecer servicios
de alojamiento, y ocio entre otros.
Cada dıa mas personas planean sus vacaciones a traves de Internet, por lo que no solo
es bueno dar a conocer los servicios que se prestan, sino tambien dar la oportunidad de
poder contratar esos servicios este donde este el cliente.
Hoy en dıa muchas pequenas empresas hoteleras aun siguen registrando sus reservas
manualmente en un libro para tal efecto. Estas se producen normalmente por telefono,
no ofreciendo practicamente ninguna garantıa de que la reserva vaya a ser pagada, los
responsables del establecimiento dieron su palabra al cliente que llamo y esa estancia
puede que quede sin ocupar, con las posibles perdidas que ello pueda conllevar. Ademas
normalmente no tienen un sitio web que puedan usar para promocionarse, lo que implica
que solo se pueden dar a conocer a traves de anuncios o similares y esto supone un gasto
adicional para la empresa.
Las grandes firmas de hoteles y multinacionales no tienen todos esos problemas. La
mayorıa permite que se reserven habitaciones a traves de su sitio web y pide que se abone
el pago de dicha reserva, ası se aseguran que esta se va llevar a cabo. Las que no permiten
xiii
xiv
hacer el pago en el momento de la realizacion de la reserva tampoco pierden demasiado,
ya que la perdida de una estancia es compensada por la multitud que se hacen efectivas
debido a sus volumenes de negocio. Estas empresas tampoco se tienen que preocupar
demasiado por la publicidad, ya que pueden permitirse hacer campanas publicitarias por
todo el mundo, y todas tienen sus sitios web actualizados.
Alcance y objetivos
La forma tradicional de gestionar un hotel, es tediosa y a veces incluso difıcil de llevar a
cabo si el volumen de trabajo del hotel es elevado o si hay muchas habitaciones y servicios
de los cuales hay que mantener actualizados sus datos.
Este proyecto surge para ayudar a simplificar y facilitar las tareas propias de la gestion
de un hotel, comenzando por desarrollar un sistema a traves del cual se puedan realizar
reservas y generar facturas, ası como gestionar las habitaciones, etc. Para esto se desarrolla
una Aplicacion Web, que permitira hacer reservas on-line del mismo modo que tambien
se podra gestionar el hotel en su totalidad, facil y comodamente.
Se pretende entre otras cosas que este proyecto sea facilmente ampliable, de forma que,
a medida que vayan surgiendo necesidades distintas dentro de la gestion de un hotel, se
pueda dar una solucion facil, rapida y lo mas elegante posible. Ademas se desarrolla de
forma que se pueda integrar de forma comoda la gestion del hotel y la gestion del sitio
web, ya que actualmente en el ambito de los hoteles hay la necesidad de darlos a conocer
a un mayor publico para ampliar el mercado.
Para comenzar se definen los usuarios que van a interactuar con la aplicacion. El Cliente,
el Recepcionista y el Administrador seran los usuarios principales, pero no los unicos, ya
que la aplicacion necesitara tambien tener como actor de soporte alguna entidad financiera
contra la cual se realizaran los pagos de las reservas.
xv
Cualquier usuario que entre en el portal del hotel puede consultar nuevas noticia acerca
del hotel, la ofertas que actualmente ofrece el establecimiento y diversos datos referentes
al hotel: ubicacion, fotografıas, etc.
El usuario tendra la posibilidad de crearse una cuenta en el portal web del hotel, con la
cual podra realizar distintas acciones. El usuario que este registrado podra modificar sus
datos personales en cualquier momento o darse de baja cuando lo desee. Tambien tendra la
posibilidad de realizar tantas reservas como quiera y luego podra pasar a administrarlas,
pudiendo ası cancelar o modificar las reservas efectuadas, o comprobar la factura para ver
cuanto tendrıa que pagar. Esta factura se calcula de forma dinamica aplicando el conjunto
de ofertas que descuenten la mayor cantidad de dinero a la factura. Una vez vista la fatura
podra pagarla en ese preciso momento, a partir del cual la reserva quedara hecha.
A partir del momento en el que un usuario registrado paga su primera reserva, ya se
puede considerar como cliente del hotel.
Por otro lado el recepcionista del hotel puede realizar tambien reservas para un cliente.
En primer lugar se le da la opcion de actualizar sus datos personales. Tambien puede
buscar a un cliente en la base de datos por varios criterios, nombre, apellidos, etc. Si el
cliente no esta registrado, se le da la oportunidad de darlo de alta en el sistema, y si lo
esta se puede tambien modificar su perfil. A continuacion se le permite realizar la reserva
que el cliente le pueda pedir. Y cuando el cliente pague la reserva el empleado de recepcion
del hotel podra marcar la factura como pagada en la aplicacion.
Asimismo, puede consultar las reservas de un cliente, las habitaciones, precios y otras
consultas generales acerca del hotel.
El administrador de la aplicacion y del hotel tiene como actividades principales en
el sistema gestionar las distintas partes del mismo. Puede crear habitaciones, consultar
y modificar sus datos, tambien tiene la posibilidad de hacer lo mismo con los tipos de
habitaciones que son los que en realidad definen los precios y condiciones que tienen las
mismas.
xvi
Otra de las operaciones que puede realizar el administrador es la creacion y publicacion
de ofertas. Cuando el administrador crea una oferta, ademas de cubrir de que fecha a
que fecha la oferta sera aplicable, tambien debe especificar la regla que se debe cumplir
con respecto al contexto en el cual se hara efectiva la oferta, de esta forma se podra definir
mas concretamente los parametros que se deben de cumplir para que la oferta se pueda
aplicar. Mediante el uso de reglas se podra definir, por ejemplo, que una oferta solo se
pueda aplicar a los clientes de un determinado paıs que hayan nacido antes de una fecha
determinada y que paguen la reserva antes de un dıa fijado.
Estas reglas podran definirse a traves del lenguaje natural, siguiendo simplemente unas
condiciones en la escritura de las mismas, como que las diferentes partes en las que se divide
una regla esten separadas utilizando unos caracteres especiales. Por ejemplo, una posible
regla para decir que solo se puede aplicar a personas de Espana que nacieran antes del 20 de
Octubre de 1980 serıa la siguiente: “PersonFrom:Espana&&PersonBornBefore:20,10,1980”
El sistema de reglas desarrollado es altamente configurable de forma que se pueden
anadir nuevas reglas al sistema sin tener que alterar nada de lo que ya esta hecho. Ası de
este modo se podrıan definir en caso necesario, condiciones mas elaboradas, como por
ejemplo, que solo se pudiese aplicar a aquellas personas que desde la apertura del hotel
hayan gastado en el mas de una cantidad de dinero.
La internacionalizacion de la aplicacion es algo fundamental en este caso ya que al
tratarse de un hotel es imprescindible especificarlo todo en varios idiomas y ası llegar
mejor a clientes extranjeros. La aplicacion web tendra traducciones a Espanol, Gallego e
Ingles, y sera muy sencillo anadir nuevas traducciones en un futuro, de igual forma tambien
estaran internacionalizadas las fechas y los numeros, pero se dejan sin internacionalizar
los precios ya que todas las transacciones se haran y se calcularan en Euros.
xvii
Estructura de la memoria
Esta memoria se ha estructurado en 10 capıtulos en los cuales se explican los diferentes
temas a tener en cuenta en la realizacion de un proyecto software.
Capıtulo 1. En este capıtulo se detallan de forma breve todas las tecnologıas empleadas
en el desarrollo y documentacion del proyecto, desde las herramientas utilizadas para
realizar el codigo fuente de la aplicacion, hasta las tecnologıas empleadas para que esta
funcionase correctamente en el momento del despliege final de la misma.
Capıtulo 2. En este apartado se explica el estado de las tecnologıas utilizadas en la
actualidad, ası como la diferencia con otras tecnologıas disponibles en el mercado, y el
porque se utilizaron unas y no otras. Para esta elecion estuvo muy presente la idea de que
la aplicacion final deberıa poder licenciarse como software libre por lo que las licencias de
algunas tecnologıas impidieron su uso.
Capıtulo 3. Se estudia en este capıtulo la viabilidad del desarrollo de la aplicacion que
se realizara. En este estudio se tiene en cuenta desde el tiempo estimado que se empleara en
su desarrollo como el coste este conllevara, ademas de otras cuestiones como la posible
comercializacion del producto una vez terminado.
Capıtulo 4. En este capıtulo se indica la metodologıa que se sigue en el desarrollo del
proyecto. En este caso se detallan las caracterısticas del Proceso Unificado y sus diferentes
fases en el ciclo de desarrollo de la aplicacion.
Ademas se explica detalladamente lo que se hizo en cada una de estas fases en el proyecto,
indicando exactamente en que momento, iteracion, de la fase del Proceso Unificado se
realizo.
xviii
Capıtulo 5. Se detallan en este capıtulo todos los requisitos que regiran el desarrollo
del proyecto. En un primer lugar se analizaran textualmente y de forma general las fun-
cionalidades que debera contemplar la aplicacion, que luego seran detalladas exactamente
en un modelo de casos de uso.
Este modelo de casos de uso se explicara dividiendolo en subconjuntos de casos de uso
relacionados, y dentro de cada subconjunto se detallara cada uno de los casos de uso por
separado y se mostrara un diagrama de casos de uso para ver como se relacionan estos
con los actores que interactuaran con la aplicacion.
Capıtulo 6. Este capıtulo junto con el anterior son los dos capıtulos fundamentales en
el desarrollo del proyecto, ya que en este se detalla todo el diseno del sistema final.
Se explican en este apartado las diferentes capas en las que se divide el sistema, basi-
camente se describe la arquitectura Modelo-Vista-Controlador utilizada. Despues de una
introduccion al diseno realizado se detalla el funcionamiento y el diseno de cada una de
las capas por separado.
En la capa modelo es donde se realiza especial incapie ya que es donde estara situa-
da toda la logica de negocio del sistema, donde realmente se implementaran los casos de
uso especificados en el modelo de casos de uso. Para desglosar esta capa, se realiza una
separacion en subsistemas, se puede identificar claramente cada uno de ellos con un sub-
conjunto de casos de uso y a continuacion se explica el diseno utilizado en estos subsistemas
acompanandolos en todo momento de los diagramas UML correspondientes.
Para terminar, pero ni mucho menos importante, se explica en detalle el sistema de
soporte de las ofertas realizado para resolver, de forma aislada del resto del modelo, las
cuestiones referente al comportamiento de las ofertas. Para detallar este comportamiento
se comienza con una explicacion textual de como deben operar e interacturar entre ellas y a
continuacion se hace un analisis mas formal apoyandose en un grafo de incompatibilidades
y su resolucion, realizado expresamente para solventar las cuestiones mas complejas del
xix
sistema. Por otro lado se explica tambien el funcionamiento del sistema de reglas y el
lenguaje utilizado para definirlas, siendo las reglas las que rigen la aplicabilidad de las
ofertas dependiendo del contexto.
Capıtulo 7. En este apartado se describe como se ha realizado la implementacion de
la aplicacion, ası como el software utilizado para su despliegue y configuracion. Ademas
tambien se expondran problemas surgidos durante la implementacion del proyecto y sus
soluciones.
Capıtulo 8. Este capıtulo de la memoria describe las diferentes pruebas realizadas para
probar el correcto funcionamiento de la aplicacion. Entre las pruebas hechas destacan las
pruebas de unidad, aunque no menos importantes son las pruebas de funcionalidad para
chequear que la aplicacion cumpliese con todos los requisitos de funcionalidad requeridos
al inicio del proyecto.
Capıtulo 9. En este capıtulo se establece la planificacion de tiempo y costes para la
realizacion del proyecto, ilustrado todo con un diagrama de Gantt.
Capıtulo 10. Este es el capıtulo donde se comentan las impresiones acerca del proyecto,
ası como las conclusiones sobre los conocimientos adquiridos y futuras posibles modifica-
ciones sobre este proyecto.
Capıtulo 1
Herramientas y tecnologıas
utilizadas
Para la realizacion de este proyecto se utilizaron distintas herramientas y tecnologıas,
desde el diseno y la implementacion, hasta la documentacion del sistema.
1.1. Herramientas y tecnologıas para el Diseno
ArgoUML Es una aplicacion para realizar diagramas UML escrita en Java y publicada
bajo la Licencia BSD open source. Dado que es una aplicacion Java, esta disponible en
cualquier plataforma soportada por Java. Aunque la interfaz grafica no es lo mejor del
mercado, la potencia para realizar diagramas y exportarlo a la mayorıa de los formatos
que se puedan querer, hace de esta aplicacion una herramienta de gran ayuda a la hora de
realizar los diagramas para desarrollar una aplicacion.
Ademas esta aplicacion permite realizar ingenierıa directa de diagramas UML a codigo,
pero no solo a codigo Java, sino tambien a otros lenguajes como C# o PHP. Tambien
permite la realizacion de ingenierıa inversa, generando un modelo a partir de codigo fuente.
Esto es muy util a la hora de documentar un proyecto, ya que de esta forma se asegura
1
1.2. Herramientas y tecnologıas para la Implementacion 2
de que no se olvida de nada, especialmente cuando se crea un modelo de clases detallado,
donde muy a menudo se puede olvidar de algun metodo, atributo, etc.
DIA Es una aplicacion grafica de proposito general para la creacion de diagramas, desa-
rrollada como parte del proyecto GNOME. Esta concebido de forma modular, con dife-
rentes paquetes de formas para diferentes necesidades.
Dia esta disenado como un sustituto de la aplicacion comercial Visio de Microsoft. Se
puede utilizar para dibujar diferentes tipos de diagramas. Actualmente se incluyen diagra-
mas entidad-relacion, diagramas UML, diagramas de flujo, diagramas de redes, diagramas
de circuitos electricos, etc. Nuevas formas pueden ser facilmente agregadas, dibujandolas
con un subconjunto de SVG e incluyendolas en un archivo XML.
El formato para leer y almacenar graficos es XML (comprimido con gzip, para ahorrar
espacio). Pero lo interesante, al igual que con ArgoUML es que puede producir salida en
multiples formatos como: EPS, SVG, PNG, etc. Y al igual que ArgoUML, Dia, gracias al
paquete ‘dia2code‘, puede generar el esqueleto del codigo a escribir a partir de un diagrama
UML.
1.2. Herramientas y tecnologıas para la Implementacion
Java EE Java Platform, Enterprise Edition, tambien conocida como J2EE es un con-
junto de especificaciones Java definidas para la construccion de aplicaciones empresariales.
Estas aplicaciones empresariales estan estructuradas en diferentes capas, donde cada una
de ellas se comporta como un componente software totalmente independiente y que puede
interactuar con otro componente. Una de las separaciones en capas que se puede ver mas
frecuentemente es la de modelo, vista y controlador.
El modelo es el que define la logica de negocio de la aplicacion, es totalmente indepen-
diente de la vista y del controlador. En el residen los objetos de la aplicacion incluyendo
sus datos y comportamiento.
1.2. Herramientas y tecnologıas para la Implementacion 3
Por otro lado la vista es la encargada de la representacion de los datos en una interfaz
de usuario para interactuar con este. Esta capa tambien es independiente de las demas
aunque necesita conocer al modelo que es donde tiene que recoger los datos a representar.
Por su parte el controlador es el encargado de conectar el modelo y la vista. Este recoge
los eventos producidos por el usuario sobre la capa vista e invoca a las acciones pertinentes
de la capa del modelo.
JDBC Java Database Connectivity. Es un API que permite la ejecucion de operaciones
sobre bases de datos desde Java. Con este API se define una interfaz que permite interac-
tuar con gran variedad de bases de datos relacionales. Este API forma parte de la edicion
estandar de java (J2SE) y tambien de la edicion empresarial (J2EE).
Los drivers JDBC son implementaciones particulares del API de JDBC para una base
de datos relacional particular, y facilitan mucho el acceso a las bases de datos. En el caso
de este proyecto se utiliza un driver JDBC para MySQL.
JUnit Es un ‘framework‘, conjunto de clases, que permite probar el funcionamiento de
clases Java de manera controlada. Probando el funcionamiento de cada uno de los metodos
de la clase para ver que se comporta como se espera. Es decir, en funcion de ciertos valores
de entrada se evaluan y luego se comprueba que la respuesta es la esperada, si la clase
cumple con la especificacion, entonces JUnit devolvera que el metodo de la clase paso exi-
tosamente la prueba, en caso de que el valor esperado sea diferente al que devolvio el
metodo durante la ejecucion, JUnit devolvera un fallo en el metodo correspondiente.
A traves de JUnit tambien se puede controlar que despues de hacer cambios en la
implementacion de una clase, se sigan cumpliendo las especificaciones.
El propio framework incluye formas de ver los resultados que pueden ser en modo texto
o grafico. Y en la actualidad las herramientas de desarrollo como NetBeans y Eclipse
cuentan con plugins que permiten que la generacion de las plantillas necesarias para la
creacion de las pruebas de una clase Java se realice de manera automatica, facilitando al
1.2. Herramientas y tecnologıas para la Implementacion 4
programador enfocarse en la prueba y el resultado esperado, y dejando a la herramienta
la creacion de las clases que permiten coordinar las pruebas.
JSP Java Server Pages, es una tecnologıa Java que permite generar contenido dinamico
para web, en forma de documentos HTML, XML o de otro tipo. Estos documentos deben
de estar contenidos en un servidor web que soporte esta tecnologıa, y se compilan a clases
java la primera vez que se accede a cada pagina.
Las JSP’s permiten la utilizacion de codigo Java mediante scripts. Ademas, es posible
utilizar algunas acciones JSP predefinidas mediante etiquetas. Estas etiquetas pueden
ser enriquecidas mediante la utilizacion de librerıas de etiquetas externas, como las que
proporciona el framework struts, e incluso se pueden construır etiquetas personalizadas.
JSTL JavaServer Pages Standard Tag Library, es un componente de Java EE. Extiende
las JavaServer Pages (JSP) proporcionando librerıas de etiquetas con utilidades amplia-
mente utilizadas en el desarrollo de paginas web dinamicas.
Las diferentes librerıas de JSTL permiten realizar tareas comunes en el desarrollo de
la mayorıa de las aplicaciones web dinamicas, estas tareas son: iteradores para recorrer
colecciones de elementos y poder mostrarlos, etiquetas condicionales por si hay que escoger
entre varias opciones, y unas de las mas utilizadas, las etiquetas de internacionalizacion,
que facilitan en gran medida el proceso de cambiar facilmente el idioma de la aplicacion
ası como el formateo de datos para los diferentes paıses.
HTML HyperText Markup Language, es el lenguaje de marcado mas utilizado para
la construccion de paginas web. Es usado para describir la estructura y el contenido en
forma de texto, ası como para complementar el texto con objetos tales como imagenes,
tablas, etc. Este es el lenguaje de marcado que son capaces de interpretar los navegadores
web. La sintaxis de este lenguaje de marcado consiste en escribir ‘etiquetas‘ que estaran
rodeadas por corchetes angulares, ‘<etiqueta>‘. HTML tambien puede describir, hasta
1.2. Herramientas y tecnologıas para la Implementacion 5
un cierto punto, la apariencia de un documento, y puede incluir un script que puede
afectar el comportamiento de navegadores web y otros procesadores de HTML. Aunque
normalmente, y lo mas correcto es separar la apariencia y el comportamiento en diferentes
ficheros.
XML EXtensible Markup Language, es un metalenguaje extensible de etiquetas desa-
rrollado por el World Wide Web Consortium (W3C). Es una simplificacion y adaptacion
del SGML y permite definir la gramatica de lenguajes especıficos. Por lo tanto XML no es
realmente un lenguaje en particular, sino una manera de definir lenguajes para diferentes
necesidades. Algunos de estos lenguajes que usan XML para su definicion son XHTML,
SVG, MathML.
XML no ha nacido solo para su aplicacion en Internet, sino que se propone como un
estandar para el intercambio de informacion estructurada entre diferentes plataformas. Se
puede usar en bases de datos, editores de texto, hojas de calculo y casi cualquier cosa
imaginable.
XML es una tecnologıa sencilla que tiene a su alrededor otras que la complementan
y la hacen mucho mas grande y con unas posibilidades mucho mayores. Tiene un papel
muy importante en la actualidad ya que permite la compatibilidad entre sistemas para
compartir la informacion de una manera segura, fiable y facil.
CSS Cascade Style Sheet, como su nombre indica son hojas de estilo, se utilizan para
definir la apariencia de una pagina web. En el documento HTML simplemente hay que
indicar en cada etiqueta un identificador que servira para luego establecer su apariencia a
partir del CSS.
CSS es una herramienta muy potente, dado que permite hacer cambios radicales en la
apariencia de una pagina sin tener que modificar en absoluto el codigo fuente. Permite
realizar casi cualquier cosa imaginable, desde cambiar tamanos, fuentes o colores, hasta la
posicion y el comportamientdo de los distintos elementos de una pagina.
1.2. Herramientas y tecnologıas para la Implementacion 6
Apache Struts Apache Struts es un framework gratuito de codigo abierto para crear
aplicaciones web en Java de forma sencilla y rapida.
Las aplicaciones web difieren de las paginas web convencionales en que las aplicaciones
web pueden crear una respuesta dinamica. Muchos sitios web ofrecen solo las paginas
estaticas. Una aplicacion web puede interactuar con bases de datos o motores de la logica
de negocio para personalizar una respuesta.
En las aplicaciones basadas en JavaServer Pages, a veces se mezclan el codigo de acceso
a base de datos con codigo de diseno de la misma, y el codigo de control de flujo. En
la practica, nos encontramos con que a menos que estas preocupaciones estan separadas,
aplicaciones grandes son muy difıciles de mantener.
Una forma de separar las distintas partes de una aplicacion de software es utilizar una
arquitectura Modelo-Vista-Controlador (MVC). El modelo representa la empresa o de base
de datos de codigo, la vista representa el codigo de diseno de la pagina, y el Contralor
representa el codigo de la navegacion. La plataforma Struts esta disenada para ayudar a
los desarrolladores a crear aplicaciones web que utilizan una arquitectura MVC.
MySQL 5.0 Es un sistema de gestion de base de datos relacional, multihilo y multi-
usuario con mas de seis millones de instalaciones. Este sistema de gestion es uno de los mas
utilizados, porque, a parte de tener una licencia GPL, libre y gratuita, es facil de utilizar
en proyectos pequenos y actualmente es compatible con las tecnologıas mas importantes
del mercado, las cuales proporcionan APIs para conectarse y realizar consultas contra la
base de datos.
MySQL AB, desde enero de 2008 una subsidiaria de Sun Microsystems y esta a su vez
de Oracle Corporation desde abril de 2009, desarrolla MySQL como software libre en un
esquema de licenciamiento dual.
Esto ultimo consiste en que por un lado se ofrece bajo la GNU GPL para cualquier
uso compatible con esta licencia, pero para aquellas empresas que quieran incorporarlo en
1.2. Herramientas y tecnologıas para la Implementacion 7
productos privativos deben comprar a la empresa una licencia especıfica que les permita
este uso. Esta desarrollado en su mayor parte en ANSI C.
Al contrario de proyectos como Apache, donde el software es desarrollado por una co-
munidad publica y el copyright del codigo esta en poder del autor individual, MySQL es
propietario y esta patrocinado por una empresa privada, que posee el copyright de la ma-
yor parte del codigo. Esto es lo que posibilita el esquema de licenciamiento anteriormente
mencionado. Ademas de la venta de licencias privativas, la companıa ofrece soporte y ser-
vicios. Para sus operaciones contratan trabajadores alrededor del mundo que colaboran
vıa Internet.
Apache Tomcat Apache Tomcat es una servidor web de codigo abierto, que sirve como
contenedor de paginas web para las tecnologıas Java Servlet y JavaServer Pages.
Apache Tomcat esta desarrollado en un entorno abierto y participativo por la companıa
Apache y publicado bajo la licencia Apache Software. Esta en continuo desarrollo y mante-
nimiento, y aunque hay diferentes productos no gratuitos que ofrecen mas funcionalidades,
para una aplicacion sencilla, es suficiente para ejecutarla.
IDE Eclipse Es un entorno de desarrollo integrado de codigo abierto multiplataforma
para desarrollar lo que el llama ‘Aplicaciones de Cliente Enriquecido‘, opuesto a las apli-
caciones ‘Cliente-liviano‘ basadas en navegadores. Esta plataforma, tıpicamente ha sido
usada para desarrollar entornos de desarrollo integrados (del ingles IDE), como el IDE de
Java llamado Java Development Toolkit (JDT) y el compilador (ECJ) que se entrega como
parte de Eclipse (y que son usados tambien para desarrollar el mismo Eclipse). Sin embar-
go, tambien se puede usar para otros tipos de aplicaciones cliente, y para otros lenguajes
de programacion. Ademas es un entorno que posibilita la utilizacion de plugins por lo que
se pueden anadir los plugins que se necesiten y ampliar de esa forma las funcionalidades
que se estimen oportunas.
1.2. Herramientas y tecnologıas para la Implementacion 8
Eclipse es tambien una comunidad de usuarios, extendiendo constantemente las areas
de aplicacion cubiertas. Un ejemplo es el recientemente creado Eclipse Modeling Project,
cubriendo casi todas las areas de la Ingenierıa dirigida por el modelo.
Eclipse fue desarrollado originalmente por IBM como el sucesor de su familia de he-
rramientas para VisualAge. Eclipse sigue siendo desarrollado por la fundacion Eclipse,
una organizacion independiente sin animo de lucro que fomenta una comunidad de codigo
abierto y un conjunto de productos complementarios, capacidades y servicios.
PhpMyAdmin Es una herramienta de software libre escrito en PHP hecho con la in-
tencion de manejar la administracion de MySQL en la World Wide Web. PhpMyAdmin
es compatible con una amplia gama de operaciones con MySQL. Las operaciones mas
frecuentes son el apoyo de la interfaz de usuario (gestion de bases de datos, tablas, cam-
pos, relaciones, ındices, usuarios, permisos, etc) mientras que el usuario todavıa tiene la
capacidad de ejecutar directamente cualquier sentencia SQL.
Configurar PhpMyAdmin es muy sencillo y facilita mucho la tarea de administrar las
distintas bases de datos que necesita una aplicacion. Ası como la de realizar las diferentes
consultas que se puedan querer hacer.
Mozilla Firefox Es un navegador de Internet libre y de codigo abierto descendiente de
Mozilla Application Suite, desarrollado por la Corporacion Mozilla, la Fundacion Mozilla
y un gran numero de voluntarios externos.
Firefox es un navegador multiplataforma y esta disponible en varias versiones de Mi-
crosoft Windows, Mac OS X, GNU/Linux y algunos sistemas Unix. Su codigo fuente es
software libre, publicado bajo una triple licencia GPL/LGPL/MPL.
Actualmente cuenta con un alto porcentaje del mercado de navegadores web, haciendo
ası firme competencia al navegador Internet Explorer de Microsoft. Y cada ano este na-
vegador gana nuevos adeptos, gracias, entre otras cosas, al licenciamiento como software
1.2. Herramientas y tecnologıas para la Implementacion 9
libre y a que cuenta con un gran numero de personas que consiguen sacar parches para
errores puntuales en un tiempo record gracias al eficaz sistema de reporte de errores.
Para visualizar paginas web, Firefox usa el motor de renderizado Gecko, que implementa
la mayorıa de los estandares web actuales ademas de otras funciones, algunas de las cuales
estan destinadas a anticipar probables adiciones a los estandares web.
Incluye navegacion por pestanas, corrector ortografico, busqueda progresiva, marcadores
dinamicos, un administrador de descargas y un sistema de busqueda integrado que utiliza
el motor de busqueda que desee el usuario. Ademas se pueden anadir funciones a traves
de complementos desarrolladas por terceros, muy util a la hora de comprobar aplicaciones
web o de realizar el diseno de la interfaz de usuario de estas.
Apache Maven 2 Maven 2 es una herramienta para la gestion de proyectos software que
proporciona soluciones a tareas comunes a todos los proyectos desde la compilacion inicial
hasta la distribucion e instalacion en los sistemas finales. Maven genera una estructura de
directorios y ficheros que sirve de estructura base. Esta estructura de directorios es estandar
en todos los proyectos lo que permite a los desarrolladores moverse entre proyectos con
mayor comodidad y familiaridad, algo muy importante a la hora de que otro desarrollador
mantenga una aplicacion, ya que siempre sabra donde puede encontrar las cosas.
Maven utiliza un fichero XML conocido como Project Object Model (POM) para descri-
bir el proyecto de software a construir, sus dependencias de otros modulos y componentes
externo, y el orden de construccion de los elementos. Esta es una caracterıstica importante
de Maven ya que el desarrollador no se tiene que preocupar de tener las dependencias de
su proyecto, simplemente se describen en el fichero POM las que necesitara y Maven ya
se encarga de tenerlas preparadas, siempre y cuando disponga de conexion a Internet, ya
que le hara falta en caso de que tenga que descargar las dependencias que necesita.
1.3. Herramientas y tecnologıas para la Documentacion 10
1.3. Herramientas y tecnologıas para la Documentacion
LATEX Es un lenguaje de marcado para documentos, y un sistema de preparacion de
documentos, formado por un gran conjunto de macros de TEX, escritas inicialmente por
Leslie Lamport (LamportTeX) en 1984, con la intencion de facilitar el uso del lenguaje de
composicion tipografica creado por Donald Knuth. Es muy utilizado para la composicion
de artıculos academicos, tesis y libros tecnicos, dado que la calidad tipografica de los
documentos realizados con LATEX es comparable a la de una editorial cientıfica de primera
lınea. LATEX es software libre bajo licencia libre.
Kile Es una herramienta para trabajar con LATEX en GNU/Linux. Facilita entre otras
cosas las labores de compilacion LATEX y de generacion de documentos. Ademas propor-
ciona caracterısticas algunas tıpicas de los entornos de edicion de texto ‘wysiwyg‘ como
Microsoft Word o OpenOffice Writer. Los comandos basicos para la edicion de un tex-
to LATEX no hay que saberselos, ya que Kile proporciona un entorno que facilita mucho
el aspecto de escribir los comandos, proporcionando en forma de botones aquellos mas
utilidados. A continuacion se senalan algunas cuestiones de configuracion que resulta util
conocer.
Configurar bien la codificacion de la pagina, ya que, salvo que se le indique lo contrario,
Kile utiliza la codificacion que el sistema GNU/Linux tiene activada por defecto. En las
configuraciones modernas la codificacion frecuentemente es utf-8 (unicode). Sin embargo lo
mas habitual en los documentos LATEX que utilizamos es usar latin1, que corresponde con
la codificacion iso 8859-1 o iso 8859-15 si los textos en espanol van a utilizar algun sımbolo
especial. Si al abrir un archivo aparecen caracteres raros esto indica una configuracion de
codificacion de Kile no es la correcta y habra que modificarla.
Planner Aplicacion software libre para realizar planificanion de proyectos, utililzada
para la planificacion del proyecto actual y la evaluacion de costes. Entre sus funcionalidades
1.3. Herramientas y tecnologıas para la Documentacion 11
se puede observar la del calculo del coste asociado a cada una de las tareas, realizacion de
diagramas de Gantt para seguir la realizacion del proyecto.
El unico inconveniente de esta aplicacion es que no exporta a ningun formato de imagen
los diagramas finales.
GIMP Es un editor de imagenes software libre que permite crear y modificar imagenes de
distintos formatos y exportarlas finalmente a practicamente cualquier formato de imagen.
Este editor tiene unas prestaciones parecidas al programa Photoshop de Adobe pero con
las ventajas de que no hay que pagar una licencia por el, es comodo de usar y, auque tiene
una curva de aprendizaje larga, es muy rapido de utilizar una vez que se sabe manejar.
Capıtulo 2
Estado actual de las tecnologıas
utilizadas
Antes de desarrollar cualquier proyecto software lo primero que hay que hacer es iden-
tificar todas las tecnologıas que se utilizaran en el mismo. Para ello un desarrollador se
sirve de su experiencia con las distintas herramientas y de los requisitos que tendra que
cumplir la aplicacion que va a desarrolar, ya que algunas tecnologıas no permitiran que
estos se cumplan.
En un primer lugar para este proyecto se descartaran automaticamente todas aquellas
tecnologıas que impidan licenciar el sistema final como software libre, siendo basicamente
todas aquellas que esten licenciadas bajo una licencia privativa. En ciertas situaciones
sera complicado encontrar aplicaciones, y tecnologıas libres equivalentes a las tecnologıas
privativas mas comunes, ademas de ser una dificultad el encontrar algun software, tambien
influira en el tiempo de desarrollo del proyecto, ya que habra que aprender a manejar las
tecnologıas elegidas.
Cuando se quiere desarrollar una aplicacion web lo primero que hay que identificar es
la plataforma a utilizar, en este caso J2EE, ya se sabıa de antemano porque era uno de
los requisitos del proyecto, pero aparte de J2EE hay otras alternativas como pueden ser la
13
14
plataforma .NET o PHP, cualquiera de ellas se podrıa utilizar. En el caso de J2EE la curva
de aprendizaje es muy larga, entre otras cosas porque se necesita saber utilizar un unico
lenguaje de programacion, pero a parte de eso se necesitan aprender como funcionan las
diferentes tecnologıas que se utilizaran conjuntamente a la hora de desarrollar el proyecto.
En este caso J2EE y PHP tienen multitud de comunidades de usuarios ya sea de los propios
proyectos, Apache, MySQL, como grupos independientes de desarrolladores, mientras que
en proyectos .NET las comunidades de desarrolladores estan controladas y gestionadas
por Microsoft.
Aunque la tecnologıa a utilizar no estuviera previamente determinada, .NET no se podrıa
utilizar debido a que su entorno de desarrollo integrado es propietario y de un coste muy
elevado que harıa inviable el proyecto, frente a los entornos de desarrollo que existen en el
mercado para trabajar con J2EE entre los que destaca Eclipse, considerado por muchos
el mejor entorno de desarrollo integrado libre del mercado. Ademas hay otros aspectos de
J2EE que corren a su favor, como la portabilidad entre diferentes plataformas, gracias en
gran medida a estar todo realizado en Java. Esto proporciona que el proyecto final sea
totalmente independiente de la plataforma, cosa que no sucede con .NET que hasta el
momento solo se puede montar sobre plataformas de Microsoft. Del mismo modo .NET
solo cuenta con servidores comerciales de pago mientras que J2EE funciona tanto sobre
servidores de pago como libres.
Por otra parte dada la naturaleza del proyecto y a que se licenciara como software libre
para que otros desarrolladores puedan agregar nuevas mejoras, este debe ser facilmente
escalable, por eso tambien en este caso de adapta perfectamente J2EE que permite gran es-
calabilidad por si en el futuro se desea integrar esta aplicacion con otras para proporcionar
mas funcionalidades.
J2EE nos es la opcion mas rapida del mercado, ya que en este aspecto otras tecnologıas
como PHP no tienen competidor, pero es lo suficientemente rapido para dar soporte a las
necesidades de la aplicacion final.
15
Se necesita tambien un gestor de bases de datos para el proyecto y para ello habra que
tener en cuenta de igual forma que sea una tecnologıa libre, por lo que quedan descarta-
dos gestores de bases de datos como Oracle. Entre la oferta disponible destacan MySQL
y PostgreSQL, y puestos a tener que elegir, como ambas ofrecen mas o menos las mis-
mas prestaciones, se utilizara MySQL dada la familiaridad que se tiene, a que tiene una
comunidad de usuarios bien organizada y al bajo coste debido a su licencia libre.
Capıtulo 3
Estudio de viabilidad
Obviamente antes de realizar el proyecto que aquı se esta detallando, se estudio si era
viable realizarlo y terminarlo con exito en el tiempo previsto, puesto que, al ser un proyecto
academico para dar fin a la formacion que se ha estado recibiendo, la fecha lımite serıa la
que marcaran las convocatorias para la entrega del proyecto. Si el proyecto no fuese viable
no se podrıa realizar porque no se tendrıa la garantıa de terminarlo.
A parte del tiempo del que se dispone para la realizacion de esta aplicacion, tambien es
un factor decisivo para estudiar la viabilidad del mismo, el coste, que debera ser el mınimo
posible.
Este proyecto no solo valdra para terminar los estudios, sino que se hara de tal forma
que sea facilmente ampliable para que en el futuro se pueda adaptar para una aplicacion
empresarial real con muy poco esfuerzo y haciendo los mınimos cambios posibles. Para
posibilitar la realizacion de futuros cambios, en la realizacion del diseno de la aplicacion ya
se han tenido en cuenta posibles puntos de amplicacion. De esta forma se podrıa adaptar
la aplicacion para venderla, y con muy pocos cambios sacarle mucha rentabilidad a la
aplicacion web.
Por otro lado como la realizacion del proyecto solo se hara por parte de una persona,
este no se hara demasiado extenso para que sea viable realizarlo en 4 o 6 meses.
17
18
Para que cualquier proyecto sea rentable realizarlo hay que tener en cuenta el coste en
cuanto a tiempo de desarrollo y tambien el coste derivado de la utilizacion de las distintas
tecnologıas. Por esa razon para que la realizacion del proyecto saliese rentable, se decide
utilizar solamente software libre y gratuito, gracias a esto tambien cabe la posibilidad de
licenciar la aplicacion final como software libre.
A continuacion se detallan algunas de las tecnologıas y herramientas software conside-
radas y finalmente utilizadas, ası como su coste asociado.
Herramienta Descripcion Cantidad Precio (e)
MySQL Gestor de base de datos relacionalutilizado para almacenar los datosde la aplicacion
1 0.00
IDE Eclipse Entorno de programacion integradoutilizado para realizar la programa-cion de la aplicacion
1 0.00
Apache Tomcat Servidor de Aplicaciones Web utili-zado contener la aplicacion
1 0.00
DIA Editor de diagramas utilizados uti-lizados para realizar los diagramasdel modelo Entidad-Relacion de labase de datos
1 0.00
Argo UML Editor de diagramas UML utili-zados para realizar los diagramasUML del modelo de la aplicacion
1 0.00
PhpMyAdmin Aplicacion utilizada para gestionary monitorizar las bases de datos uti-lizadas
1 0.00
Kile Editor de textos paraLATEXutilizado para realizar to-da la documentacion necesaria parala aplicacion
1 0.00
Cuadro 3.1: Tabla de costes para estudio de viabilidad
Resumiendo, gracias a las licencias libres de todas las herramientas y tecnologıas utili-
zadas, el coste total de todas es de 0.00e, por lo que el coste final sera igual al coste del
tiempo empleado en el desarrollo de la aplicacion. Esto cambiarıa si se utilizasen herra-
19
mientas y tecnologıas de pago, porque solo por el coste de las licencias, el proyecto que se
desea realizar serıa totalmente inviable para realizar como proyecto fin de carrera.
Capıtulo 4
Introduccion al desarrollo
realizado
4.1. El Proceso Unificado
Para realizar este proyecto se utiliza una metodologıa basada en iteraciones, donde en
cada una de ellas se consigue implementar un conjunto de funcionalidades de la aplicacion,
casos de uso, y ası al terminar la utima iteracion se tiene un sofware que implementa todos
los casos de uso.
En cada una de las iteraciones se realizara analisis, diseno, implementacion y pruebas.
Para realizar estas iteraciones se utiliza la metodologıa que define el Proceso Unificado,
(UP, Unified Process). Este proceso de desarrollo, acompanado del leguaje de modelado
UML (Unified Modelling Languaje) son, conjuntamente, la metodologıa que mas se utiliza
actualmente a la hora de desarrollar un nuevo proyecto software.
El Proceso Unificado de desarrollo software es un marco de desarrollo software iterativo
e incremental, el UP se puede extender para ser adaptado a organizaciones o proyectos
expecıficos, de hecho, el refinamiento mas conocido del Proceso Unificado es el Proceso
21
4.1. El Proceso Unificado 22
Unificado de Rational que es un marca registrada de IBM, pero hay otros muchos refina-
mientos: Agile UP, Open UP, etc.
El UP esta compuesto por cuatro fases denominadas Concepcion, Elaboracion, Cons-
truccion y Transicion, donde cada una de estas fases se divide en iteraciones. Cada una
de las iteraciones ofrece como resultado un incremento del producto que anade o mejora
funcionalidades del sistema.
Cada iteracion se divide en disciplinas como las que se definıan en el ciclo de vida
clasico: Analisis de requisitos, Diseno, Implementacion, Pruebas, etc. Pero, aunque todas
las iteraciones incluyen trabajo en casi todas las disciplinas, cada una de ellas se centra
mas en una iteracion u otra. Este enfasis en cada iteracion se puede observar en el grafico
de la figura 4.1.
Figura 4.1: Grafico del Proceso Unificado
El Proceso Unificado se caracteriza, entre otras cosas, por estar dirgido por los casos de
uso, estos se utilizan para capturar los requisitos funcionales y para definir los contenidos
de cada iteracion. Estos contenidos son los recogidos en un cada uno de los conjuntos
4.1. El Proceso Unificado 23
de casos de uso o escenarios, de forma que cada iteracion pase a traves de todas las
disciplinas: diseno, implementacion, etc. Ademas, siguiendo este proceso de desarrollo, hay
que centrarse en los riesgos, es decir, se deben identificar los riesgos crıticos que pueden
afectar al desarrollo del proyecto lo antes posible. Identificando los riesgos en una etapa
temprana luego el desarrollo se debe centrar en resolver estos puntos crıticos en primer
lugar.
A continuacion se detalla lo que tiene lugar en las distintas fases del Proceso Unificado:
Fase de Concepcion
Esta fase es la mas pequena del proyecto, en ella se deben establer el ambito del
proyecto y una justificacion de por que se realiza.
Ademas es en este momento cuando se esbozan los casos de uso y los requisitos
principales por los cuales se dirigiran las cuestiones de diseno del proyecto. Por otro
lado se deben comenzar a buscar las arquitecturas generales que mejor se adapten
al proyecto que se quiere realizar e identificar los riesgos crıticos para el mismo. A
continuacion se debe preparar un plan para el proyecto y una estimacion de los costes
que este conllevara.
Fase de Elaboracion
Es la fase en la cual se capturan la mayorıa de los requisitos del sistema, identificando
tambien los riesgos y estableciendo la arquitectura general del sistema.
Ademas se debe implementar una Base de Arquitectura Ejecutable para demostrar
que el sistema final soportara los aspectos claves de funcionalidad establecidos y
comprobar que tiene un rendimiento, escalabilidad y coste adecuados.
Fase de Construccion
Es la mas larga del proyecto, donde se construye el sistema en base a lo especificado
en la fase de elaboracion. Esta fase se divide en una serie de iteraciones, y en cada
4.2. El Proceso Unificado en este Proyecto 24
una de ellas se implementa un conjunto de las funcionalidades, terminando cada una
con una version completa de la aplicacion final.
Fase de Transicion
Esta es la fase en la que se despliega la aplicacion para el usuario final, y recogiendo
las impersiones de estos para incorporar refinamientos al sistema en sucesivas itera-
ciones, esta fase tambien incluye el entrenamiento en la utilizacion del sistema por
parte de los usuarios.
4.2. El Proceso Unificado en este Proyecto
A continuacion se vera como se aplico el Proceso Unificado en el desarrollo de este
proyecto, para ello se iran indicando las diferentes fases por las que se fue pasando y las
iteraciones que se realizaron en cada una de ellas con una descripcion de lo que se hizo.
Fase de Concepcion
1. Iteracion 1
En esta iteracion se hizo un analisis de las funcionalidades que deberıa con-
templar la aplicacion, estableciendo textualmente los requisitos principales del
sistema.
A partir de este analisis de requisitos se realizo el diseno Entidad Relacion de
la base de datos que necesitara la aplicacion, para luego realizar el modelo rela-
cional. A continuacion se implementa la base de datos en base a lo especificado
en el modelo relacional.
Ademas en este momento se vio que probablemente serıa un riesgo a solventar
que el driver JDBC, que posteriormente se utilizara para conectarse a la base
de datos, funcionase correctamente. Se detecto en este momento un mal funcio-
namiento de la conexion con la base de datos y se resolvio despues de consultar
la documentacion especıfica del manejador JDBC.
4.2. El Proceso Unificado en este Proyecto 25
Fase de Elaboracion
1. Iteracion 1
En esta iteracion se realiza un analisis de requisitos mas exhaustivo, realizando
el modelo de casos de uso. A partir de este analisis de requisitos se refina el
diseno de la base de datos y se implementan los cambios realizados.
Se disena en este momento como sera la capa modelo, los DAO y las Fachadas
que se necesitaran. A partir de este diseno se implementa la capa de acceso a
base de datos (DAO) y alguna de las fachadas, tambien se hacen las pruebas
de unidad correspondientes a estas implementaciones.
Ademas se hacen pruebas para ver como funciona la tecnologıa struts que se
utilizara para implementar la capa controladora de la aplicacion web.
Fase de Construccion
1. Iteracion 1
En esta iteracion se refinan pequenos detalles de los requisitos y se disena la
capa controladora y la vista.
Es ahora cuando se implementa un subconjunto completo de casos de uso, en
este caso el referido a la gestion de usuarios. Se implementa desde las acciones
del modelo, que implementan realmente los casos de uso, hasta la capa vista.
Entre estos casos de uso se encuentran los de autentificar al usuario en la aplica-
cion, darlo de alta, etc, para lo que tambien hay que implementar el mecanismo
para mantener las sesiones.
Para terminar con esta iteracion y conseguir una version funcional del sistema
se prueba que se realicen correctamente los requisitos especificados en los casos
de uso.
Iteracion 2
4.2. El Proceso Unificado en este Proyecto 26
En este momento se refina el diseno de las fachadas que se van a implementar de
forma que se ajuste exactamente a lo que se desea. Ademas se disena la estructura
general del sistema de ofertas con el que se iteractuara a la hora de realizar las
facturas.
En este momento se implementan otros dos subconjuntos completos de casos de uso,
en este caso los referidos a la gestion de reservas y habitaciones. Se implementa
desde las acciones del modelo que implementan realmente los casos de uso hasta la
capa vista. Entre estos casos de uso se encuentran los de realizar una nueva reserva,
consultar las reservas y modificarlas, para ello es necesario implementar una forma
de gestionar la realizacion de las reservas.
Para terminar con esta iteracion y conseguir una version funcional del sistema se
prueba que se realicen correctamente los requisitos especificados en los casos de uso.
Iteracion 3
En este momento se refina el diseno del sistema de las ofertas para que se ajuste
exactamente a los requisitos requeridos por el mismo.
En este momento se implementan otros dos subconjuntos completos de casos de uso,
en este caso los referidos a la gestion de facturas y ofertas. Se implementa desde las
acciones del modelo que implementan realmente los casos de uso hasta la capa vista.
Entre estos casos de uso se encuentran los de ver el borrador de una factura en el
que entra en juego el sistema de ofertas desarrollado, pagar una factura o cancelarla,
etc.
Para terminar con esta iteracion y conseguir una version funcional del sistema se
prueba que se realicen correctamente los requisitos especificados en los casos de uso,
prestando especial atencion al sistema de ofertas, ya que la unica forma de probarlo
es en este momento, debido a la dificultad de realizar pruebas de unidad de cada
uno de los metodos que forman sus clases.
Fase de Transicion
4.2. El Proceso Unificado en este Proyecto 27
Esta fase del Proceso Unificado no es necesaria realizarla para la realizacion del pro-
yecto debido a que en este caso solo valdra para evaluar los conocimientos adquiridos
durantes los estudios realizados. Si este proyecto tuviese que ser adaptado para su
comercializacion, serıa en esta fase cuando se desplegarıa ante el usuario final para
que informase si todo esta como se habıa pedido y cuando se ensenarıa al usuario a
utilizar la aplicacion.
Capıtulo 5
Requisitos del Sistema
5.1. Introduccion
Antes de comenzar cualquier proyecto de desarrollo de software, lo primero que hay que
hacer es un analisis de requisitos del sistema, es decir, hay que conocer las caracterısticas
que debe tener el sistema.
Las caracterısticas de una aplicacion las determinan el cliente que la solicita y el usuario
final que lo va a utilizar. En nuestro caso necesitamos una aplicacion que permita gestionar
las reservas de un hotel y demas partes del mismo, de una forma sencilla. El sistema a
desarrollar esta orientado a las pequenas y medianas empresas hoteleras, por lo que el
coste del producto lo hay que reducir lo maximo posible.
En la actualidad la gran mayorıa de pequenos hoteles o similares realizan sus tareas de
una forma manual, o utilizando numerosos productos software. La gestion de las reservas
se suele hacer por telefono o en persona en el lugar donde se encuentre el establecimiento,
anotando las mismas en un libro de reservas ya sea, en formato papel o digital. Ademas
necesitan un software especial para gestionar el proceso de facturacion del hotel, y no
tienen manera de gestionar de forma automatica y eficaz, todas las ofertas que puedan, o
quieran, tener a disposicion del consumidor.
29
5.1. Introduccion 30
Las grandes firmas hoteleras y las cooperativas de varios hoteles no tienen estos proble-
mas, ya que tienen financiamiento suficiente para contratar el desarrollo de aplicaciones
que se ajusten a sus necesidades.
Lo que se intenta hacer con este proyecto es ofrecer una solucion lo mas generica posible
para todas aquellas pequenas empresas a las cuales un producto como este les facilitarıa
muchısimo las cosas a la hora de gestionar sus modestos negocios, ademas de proporcionar
la opcion de gestionar un sitio web propio que este totalmente integrado, dando, entre
otras cosas, la opcion de hacer reservas y consultas on-line.
Una de las cosas mas importantes es que este sistema se licenciara como software libre
bajo una licencia GPL (General Public License), de modo que todo aquel que lo necesite
pueda acceder a este software de manera totalmente gratuita.
El desarrollo de este producto software esta pensado para que, en caso necesario, sea
facilmente ampliable, configurable y ajustable, para adaptarse a las necesidades del usuario
final. Esta aplicacion contiene las funcionalidades basicas que un establecimiento hotelero
pueda necesitar en su dıa a dıa, pero esta orientado a que en cualquier momento se puedan
realizar cambios de forma sencilla y sin alterar su estructura general.
El funcionamiento basico del sistema final tiene que dar soporte para dar de alta a
nuevos clientes, ası como para la realizacion de reservas por parte de los clientes a traves
de internet y en el establecimiento del hotel por parte del recepcionista, tambien dara la
posibilidad de que el administrador gestione todas las partes mas crıticas del negocio,
como son las habitaciones y sus precios, o la publicacion de nuevas ofertas para que esten
a disposicion de los usuarios.
Cuando un nuevo usuario acceda a la aplicacion a traves de internet se le proporcionara la
oportunidad de darse de alta, o si ya lo esta, de acceder al sistema. Para ello se le pediran
sus datos personales, los cuales seran utilizados posteriormente a la hora de realizar las
facturas a nombre del cliente. Si por el contrario el alta del nuevo cliente la realiza el
recepcionista, se le pediran los mismos datos a excepcion del nombre de usuario que desea
5.1. Introduccion 31
y su contrasena, ya que esos datos se los tendra que pedir explıcitamente el cliente al
recepcionista.
Un cliente, una vez registrado y autentificado en el sistema tendra, la posibilidad de
hacer una reserva para los dıas que desee. Para la realizacion de una reserva simplemente
sera necesario que el cliente este registrado, pero esta reserva no sera una reserva real hasta
que el cliente la pague, para lo cual el administrador del hotel tendra que dar un plazo,
y si el cliente no paga la reserva dentro de ese plazo esta sera cancelada. De este modo
se pueden evitar perdidas derivadas de intentos de sabotaje por parte de algun usuario
malintencionado.
Una vez realizada la misma, se le comunica al cliente el numero de reserva que de-
bera buscar para pagar. A partir de ese momento el cliente puede consultar la reserva
realizada y modificarla si lo desea, o ver la factura y pagarla o cancelarla. La factura que
ve el cliente se genera automaticament; para ello el sistema debera utilizar algun algoritmo
especial que permite aplicar las ofertas pertinentes.
El sistema de ofertas es quiza una de las partes de la aplicacion mas complicada de resol-
ver. Una oferta va a pertenecer a un tipo de ofertas; estos tipos los definira el administrador
(obviamente de cada tipo de oferta solo se podra aplicar una oferta).
Hasta aquı la parte sencilla, este sistema tambien permitira acumular ofertas de forma
que se puedan aplicar varios descuentos de ofertas distintas sobre el importe inicial, y
dejara al administrador especificar mediante reglas altamente configurables, el conjunto
de clientes o aquellas situaciones especıficas en las cuales se podra aplicar una oferta; por
lo tanto, otro problema a solventar sera la definicion de dicho lenguaje de reglas.
Como acabamos de mencionar, de cada tipo de oferta solamente una se podra aplicar,
pero ademas los tipos tendran incompatibilidades entre sı, relaciones mediante las cuales
se definira que ofertas no se pueden aplicar conjuntamente. La aplicacion debe resolver de
forma rapida y eficaz esta problematica, ya que a la hora de calcular la mejor oferta que
5.2. Actores 32
se le puede ofrecer a un cliente sobre una factura, tendra que calcular cual es el conjunto
de ofertas que a este le proporcionara un mayor descuento.
En las siguientes secciones se veran en detalle todas las situaciones que el sistema de-
bera contemplar y resolver, y todos los usuarios que interactuaran con la aplicacion.
Para la definicion de las funcionalidades del sistema se empleara notacion UML (Unified
Modelling Language) especificando los usuarios del sistema y todos los que interactuan
con el (actores), y los comportamientos del mismo ante las peticiones de los actores (casos
de uso).
Las funcionalidades basicas de este producto se definiran en cojuntos de casos de uso, a
traves de los cuales se detallara el funcionamiento de la aplicacion.
5.2. Actores
Como se acaba de mencionar, un actor es alguien o algo que intercambia informacion
con el sistema, bien sea un usuario u otro sistema. Varios usuarios se pueden representar
como un solo actor para el sistema y viceversa, un mismo usuario puede ser representado
por varios actores.
Se pueden distinguir varios tipos de actores, de los cuales los mas importantes son:
Los actores primarios y los de soporte. Los actores primarios son aquellos que utilizan
el sistema para alcanzar sus objetivos y a traves de los cuales se pueden identificar los
objetivos a desarrollar en el sistema. Los actores de soporte son los que proveen un servicio
al sistema, estos actores sirven para identificar interfaces externos a nuestro sistema que
hay que utilizar.
En nuestro sistema podemos encontrar los siguientes actores primarios:
Persona Es toda persona que entra en la aplicacion y no se autentifica o se registra. Este
usuario puede hacer consultas de precios, ofertas y demas, pero no podra realizar
5.3. Casos de Uso 33
ningua reserva. Este tipo de usuario tiene la opcion de autentificarse o de registrarse
en el sistema.
Cliente Es aquel usuario que se ha autentificado, tiene la posibilidad de hacer las mis-
mas operaciones que una Persona, pero ademas tambien puede realizar reservas de
habitaciones, hacer consultas sobre sus reservas y facturas, y pagar o cancelar las
reservas que desee. Entre otras cosas este usuario tambien puede actualizar su perfil
o darse de baja en el sistema.
Recepcionista Es el empleado del hotel que se encarga de la recepcion del mismo, este
usuario es el encargado de recibir a los clientes en el establecimiento y tiene la
posibilidad de dar de alta a un nuevo cliente y realizarle una reserva si es necesario.
Administrador Es el empleado encargado de gestionar y mantener todo el sistema por
lo que tiene unos privilegios que no posee ningun otro usuario.
Como el Cliente va a poder hacer las mismas operaciones que la Persona, esto significa
que entre los dos constituyen una jerarquıa de usuarios.
Pero ademas la aplicacion necesita un indispensable actor de soporte:
Entidad Financiera Es el sistema de pago contra el cual nuestro sistema tiene que
realizar y verificar los pagos de las reservas. Este usuario permite que las reservas se
puedan pagar on-line.
5.3. Casos de Uso
Un caso de uso es una forma de definir el escenario completo de una operacion. Un caso
de uso especifica claramente lo que hace una operacion desde el punto de vista del actor
que la realiza. En el apareceran exclusivamente aquellos detalles que son relevantes para
el actor.
5.3. Casos de Uso 34
En primer lugar se expecificaran los distintos casos de uso siguiendo las especificaciones
que proporciona el proceso de desarrollo unificado, que es el que se esta siguiendo en la
elaboracion de este proyecto. Estas especificaciones indican que el detallado de un caso de
uso debe contener la siguiente informacion: actores, precondiciones, postcondiciones, flujo
basico y flujo alternativo.
Los actores son los usuarios implicados en el caso de uso en cuestion. Las precondiciones
especifican todas las condiciones del sistema que son obligatorias que se cumplan antes de
que comience el caso de uso. Por otro lado, las postcondiciones son aquellas condiciones
en las que, con toda seguridad, quedara el sistema una vez termine la ejecucion del caso
de uso.
Aunque lo mas importante para detallar un caso de uso es indicar cual va a ser su flujo
basico de eventos y cual su flujo alternativo. El flujo basico de eventos indica los eventos
que se han de realizar para que el caso de uso termine exitosamente. El flujo alternativo
es aquel flujo de eventos que se seguira en caso de que algun fallo ocurra durante el flujo
basico del mismo.
Una vez aclarados estos conceptos ya se puede comenzar a detallar cada uno de los casos
de uso de este sistema, y para que se puedan entender mejor van a estar agrupados por
conjuntos donde estan contextualmente relacionados entre sı.
5.3.1. Casos de Uso de Gestion de Usuarios Web
Estos casos de uso son todos aquellos relacionados con la gestion de los Usuarios del
sistema, registro, autentificacion, etc. Se puede ver el diagrama correspondiente en la figura
5.1 de la pagina 78.
1. Autenticarse
Actores Primarios: Cliente, Recepcionista, Administrador.
5.3. Casos de Uso 35
Descripcion: Permite a una persona entrar en el sistema.
Precondiciones: La persona aun no esta autenticada en el sistema.
Postcondiciones: La persona pasa a estar autenticada en el sistema.
Flujo basico:
1 La persona quiere autenticarse en el sistema.
2 El sistema pide a la persona que introduzca su nombre de usuario y su con-
trasena.
3 La persona introduce su nombre de usuario y su contrasena.
4 La persona confirma que desea autenticarse.
5 El sistema autentica a la persona.
Flujo alternativo:
*.1 En cualquier momento la persona tiene la posibilidad de cancelar el proceso.
4.1 La persona no ha introducido el login, la contrasena o ambos.
4.2 El sistema indica que tiene que indicar el nombre de usuario y contrasena.
4.3 Se vuelve al evento 2 del flujo basico.
5.1 El nombre de usuario o contrasena son incorrectos.
5.2 El sistema se lo indica a la persona y le da la opcion de registrarse.
5.3 Se vuelve al paso 2.
2. Salir del sistema
Actores Primarios: Cliente, Recepcionista, Administrador
Descripcion: Permite a un cliente dejar de estar autenticado en el sistema.
Precondiciones: El cliente esta autenticado en el sistema.
5.3. Casos de Uso 36
Postcondiciones: El cliente deja de estar autenticado en el sistema.
Flujo basico:
1 La persona quiere salir del sistema.
2 El sistema pide al cliente que confirme que desea salir del sistema.
3 El cliente confirma que desea salir.
4 El sistema procesa la peticion y el cliente deja de estar autenticado en la
aplicacion.
Flujo alternativo:
*.1 En cualquier momento la persona tiene la posibilidad de cancelar el proceso.
3. Dar de Alta Usuario
Actores Primarios: Persona
Descripcion: Permite a una nueva persona que entra en el portal Web del hotel darse de alta
como usuario del mismo.
Precondiciones: La persona no esta autenticada en el sistema.
Postcondiciones: La persona pasa a estar autenticada en el sistema y se registra como nuevo
usuario de este.
Flujo basico:
1 La persona quiere darse de alta en el sistema.
2 El sistema pide a la persona que introduzca los siguientes datos de los cuales
algunos son obligatorios:
• Nombre (obligatorio)
5.3. Casos de Uso 37
• Apellidos (obligatorio)
• DNI o pasaporte (obligatorio)
• Fecha de Nacimiento (obligatorio)
• Direccion completa (obligatorio)
• Paıs (obligatorio)
• Direccion de e-mail (obligatorio)
• Telefono1 (opcional)
• Telefono2 (opcional)
• Nombre de Usuario (obligatorio)
• Contrasena (obligatorio)
• Confirmacion de contrasena (obligatorio)
3 La persona introduce los datos solicitados.
4 La persona confirma que desea darse de alta.
5 El sistema procesa la informacion del nuevo cliente.
6 La persona pasa a estar dada de alta como cliente.
7 El sistema autentica al cliente en la aplicacion.
8 El cliente esta autenticado en el sistema.
Flujo alternativo:
*.1 En cualquier momento la persona tiene la posibilidad de cancelar el proceso.
4.1.1 La persona no ha introducido todos los datos obligatorios o las contra-
senas no coinciden.
4.1.2 El sistema indica que tiene que introducir los datos obligatorios y se
vuelve al evento 2 del flujo basico.
4.2.1 El nombre de usuario ya existe como nombre de usuario de otro cliente.
4.2.2 Se solicita que cambie el nombre de usuario y se vuelve al paso 2.
4.3.1 El dni indica que esa persona ya esta dada de alta.
5.3. Casos de Uso 38
4.3.2 Se le pide a la persona que compruebe que ha escrito bie su dni y se
vuelve al paso 2.
4. Modificar datos de Usuario
Actores Primarios: Cliente, Recepcionista, Administrador
Descripcion: Permite a un cliente modificar los datos con los que se dio de alta como usuario
del sistema.
Precondiciones: El cliente esta autenticado en el sistema.
Postcondiciones: Los datos del cliente estan actualizados.
Flujo basico:
1 El cliente quiere midificar los datos con los que se dio de alta en el sistema.
2 El sistema muestra los datos actuales del cliente y pide al cliente que actualice
los que desee de los siguientes:
• Nombre (obligatorio)
• Apellidos (obligatorio)
• Fecha de Nacimiento (obligatorio)
• Direccion completa (obligatorio)
• Paıs (obligatorio)
• Direccion de e-mail (obligatorio)
• Telefono1 (opcional)
• Telefono2 (opcional)
• Contrasena (obligatorio)
• Confirmacion de contrasena (obligatorio)
3 El cliente modifica los datos que quiere.
5.3. Casos de Uso 39
4 El cliente confirma que desea actualizar sus datos.
5 El sistema procesa la actualizacion de los datos del cliente.
6 Los datos del cliente pasan a estar actualizados.
Flujo alternativo:
*.1 En cualquier momento la persona tiene la posibilidad de cancelar el proceso.
4.1 La persona no ha introducido todos los datos obligatorios o las contrasenas
no coinciden.
4.2 El sistema indica que tiene que introducir los datos obligatorios y se vuelve
al evento 2 del flujo basico.
5. Consultar datos de Usuario
Actores Primarios: Cliente, Recepcionista, Administrador
Descripcion: Permite a un cliente consultar los datos con los que se dio de alta en el sistema.
Precondiciones: El cliente esta autenticado en el sistema.
Postcondiciones: Ninguna.
Flujo basico:
1 El cliente quiere consultar los datos con los que se dio de alta en el sistema.
2 El sistema muestra al cliente sus datos personales.
6. Dar de baja Usuario
Actores Primarios: Cliente
Descripcion: Permite a un un cliente darse de baja como usuario del sistema.
5.3. Casos de Uso 40
Precondiciones: El cliente esta autenticado en el sistema.
Postcondiciones: El cliente deja de estar autenticado en el sistema y deja de existir como usuario
de la aplicacion.
Flujo basico:
1 La persona quiere darse de baja del sistema.
2 El sistema muestra un aviso al cliente, y pide a este que confirme que desea
darse de baja.
3 El cliente confirma que desea darse de baja.
4 El sistema procesa la baja del cliente.
5 El cliente deja de ser usuario de la aplicacion.
Flujo alternativo:
*.1 En cualquier momento el cliente tiene la posibilidad de cancelar el proceso.
5.3.2. Casos de Uso de Gestion de Reservas Web
Los Casos de Uso que aquı se detallan son todos los relacionados con la gestion de las
reservas en el portal web del hotel por parte de los clientes. Se puede ver el diagrama
correspondiente en la figura 5.2 de la pagina 79.
7. Hacer reserva web
Actores Primarios: Cliente
Descripcion: Permite a un cliente realizar una reserva de una o varias habitaciones para un
dıa determinado.
Precondiciones: El cliente esta autenticado en el sistema.
5.3. Casos de Uso 41
Postcondiciones: La reserva queda realizada a espera de que el cliente la pague.
Flujo basico:
1 El cliente quiere realizar una reserva de habitacion.
2 La aplicacion pide al cliente que indique el tipo de habitacion que desea
reserva, el dıa que llega, el dıa de salida, y la cantidad de habitaciones de
ese tipo que necesita.
3 El cliente especifica todos los datos solicitados.
4 El cliente confirma que desea realizar la reserva de ese tipo de habitacion
para los dıas indicados.
5 El sistema procesa la reserva.
6 La reserva pasa a estar realizada a la espera de ser pagada y se le muestra al
cliente el numero de reserva para que la pueda localizar.
Flujo alternativo:
*.1 En cualquier momento el cliente tiene la posibilidad de cancelar el proceso.
4.1.1 El cliente no ha introducido todos los datos.
4.1.2 El sistema indica que tiene que especificar todos los datos y se vuelve al
evento 2 del flujo basico.
4.2.1 El cliente ha introducido una fecha de llegada o de salida erronea.
4.2.2 El sistema indica que vuelva a introducir las fechas correctamente. y se
vuelve al evento 2.
4.3.1 No hay habitaciones disponibles para los valores especificados, se indica
y se vuelve al paso 2.
4.4.1 El cliente indica que desea realizar la reserva de otro tipo de habitacion.
4.4.2 El sistema procesa la reserva.
4.4.3 Se vuelve al paso 2 para realizar la siguiente reserva.
5.3. Casos de Uso 42
8. Consultar reservas web
Actores Primarios: Cliente
Descripcion: Permite a un cliente consultar las reservas que ha realizado desde que es cliente
del hotel, se podran ver las reservas pagadas, las canceladas y las que estan aun
pendientes de pago.
Precondiciones: El cliente esta autenticado en el sistema.
Postcondiciones: Ninguna.
Flujo basico:
1 El cliente quiere consultar las reservas que ha realizado hasta el momento
2 El sistema muestra al cliente todas sus reservas.
9. Modificar reserva web
Actores Primarios: Cliente
Descripcion: Permite a un cliente modificar una reserva realizada
Precondiciones: El cliente esta autenticado en el sistema, y la reserva no esta pagada ni cance-
lada.
Postcondiciones: La reserva queda modificada a espera de que el cliente la pague.
Flujo basico:
1 El cliente quiere modificar una reserva de habitaciones.
2 El cliente indica que desea anadir una nueva reserva de habitacion.
5.3. Casos de Uso 43
3 La aplicacion pide al cliente que indique el tipo de habitacion que desea
reserva, el dıa que llega, el dıa de salida, y la cantidad de habitaciones de
ese tipo que necesita.
4 El cliente especifica todos los datos solicitados.
5 El cliente confirma que desea realizar la reserva de ese tipo de habitacion
para los dıas indicados.
6 El sistema procesa la reserva.
7 El cliente confirma que quiere guardar los cambios realizados en la reserva
de habitaciones.
8 El sistema guarda la reserva.
Flujo alternativo:
*.1 En cualquier momento el cliente tiene la posibilidad de cancelar el proceso.
2.1 El cliente indica que desea eliminar una reserva de habitacion.
2.2 El sistema pide al usuario que indique cual es la lınea de reserva que desea
eliminar.
2.3 El cliente especifica la lınea de reserva que quiere eliminar.
2.4 El sistema procesa la eliminacion de la lınea de reserva.
2.5 Se pasa al paso 2 del flujo basico.
5.1.1 El cliente no ha introducido todos los datos.
5.1.2 El sistema indica que tiene que especificar todos los datos y se vuelve al
evento 2 del flujo basico.
5.2.1 El cliente ha introducido una fecha de llegada o de salida erronea.
5.2.2 El sistema indica que vuelva a introducir las fechas correctamente. y se
vuelve al evento 2.
5.3.1 No hay habitaciones disponibles para los valores especificados, se indica
y se vuelve al paso 2.
5.3. Casos de Uso 44
7.4.1 El cliente indica que desea seguir modificando la reserva.
7.4.2 El sistema procesa la reserva.
7.4.3 Se vuelve al paso 2 para continuar modificando
10. Consultar factura web
Actores Primarios: Cliente
Descripcion: Permite a un cliente consultar la factura de cualquier reserva que haya realizado
desde que es cliente del hotel, se podran ver las facturas pagadas, las canceladas
y las que estan aun pendientes de pago.
Precondiciones: El cliente esta autenticado en el sistema.
Postcondiciones: Ninguna.
Flujo basico:
1 El cliente quiere consultar una factura de una reserva que ha realizado.
2 El sistema pide al cliente que indique el numero de reserva para la factura
que desea consultar.
3 El cliente indica el numero de reserva deseado.
4 El sistema muestra al cliente la factura de la reserva solitada. En el caso
de que la factura ya este pagada o cancelada muestra el importe que ha
pagado y si la factura esta pendiente de pago muestra el total que debe
pagar indicando aquellos descuentos que se le han proporcionado debido a
las ofertas que se le han podido aplicar.
Flujo alternativo:
*.1 En cualquier momento el cliente tiene la posibilidad de cancelar el proceso.
5.3. Casos de Uso 45
11. Cancelar reserva web
Actores Primarios: Cliente
Descripcion: Permite a un cliente cancelar cualquier reserva que haya realizado y aun no dis-
frutado, si la factura estuviese pagada se le devuelve un porcentaje del importe,
dependiendo de la antelacion con la que la cancele.
Precondiciones: El cliente esta autenticado en el sistema.
Postcondiciones: La reserva queda cancelada.
Flujo basico:
1 El cliente quiere cancelar una reserva que ha realizado.
2 El sistema pide al cliente que indique el numero de reserva que desea cancelar.
3 El cliente indica el numero de reserva deseado.
4 El sistema pide al cliente la confirmacion de que quiere cancelarlas.
5 El cliente lo confirma.
6 El sistema cancela la reserva.
Flujo alternativo:
*.1 En cualquier momento el cliente tiene la posibilidad de cancelar el proceso.
3.1 El cliente indica un numero de reserva que ya habıa sido cancelada o dis-
frutada.
3.2 Se le muestra un error al cliente y se termina el proceso sin que se cancele
ninguna reserva.
12. Pagar factura web
5.3. Casos de Uso 46
Actores Primarios: Cliente
Actores de Soporte: Entidad Financiera
Descripcion: Permite a un cliente pagar la factura de una reserva.
Precondiciones: El cliente esta autenticado en el sistema.
Postcondiciones: La factura de la reserva esta pendiente de pago y no esta cancelada.
Flujo basico:
1 El cliente quiere pagar la factura de una reserva que ha realizado.
2 El sistema pide al cliente que indique el numero de reserva que desea pagar.
3 El cliente indica el numero de reserva deseado.
4 El sistema muestra al cliente la factura de la reserva y le pide la confirmacion
de que quiere pagarla.
5 El cliente lo confirma.
6 El sistema marca la factura como en proceso de pago y envıa los datos del
pago a la entidad financiera.
7 El cliente y la entidad financiera gestionan el pago de la factura.
8 La entidad financiera envıa al sistema la confirmacion de pago de la factura.
9 El sistema comprueba la confirmacion.
10 La factura se marca como pagada.
Flujo alternativo:
(1-5).1 En cualquier momento el cliente tiene la posibilidad de cancelar el
proceso.
3.1 El cliente indica un numero de reserva que ya habıa sido pagado o que ya
esta en proceso de pago.
3.2 Se le muestra un error al cliente y se termina el proceso sin que se pague
la factura de la reserva.
5.3. Casos de Uso 47
8.1 La entidad financiera no envıa la confirmacion de pago de la factura.
8.2 El pago de la factura se interrumpe y la factura deja de estar en proceso
de pago.
5.3.3. Casos de Uso de Gestion de Clientes
Estos casos de uso son todos aquellos relacionados con la gestion de los Clientes,
en la recepcion del hotel, registro de nuevos clientes, consulta y modificacion de sus
datos, etc. Se puede ver el diagrama correspondiente en la figura 5.3 de la pagina 80.
13. Buscar Cliente
Actores Primarios: Recepcionista
Descripcion: Permite al recepcionista buscar a un cliente para trabajar con el.
Precondiciones: El recepcionista esta autenticado en el sistema.
Postcondiciones: El recepcionista sigue siendo el usuario real del sistema, pero el cliente elegido
es el usuario efectivo del mismo.
Flujo basico:
1 El recepcionista quiere buscar a un cliente para trabajar con el.
2 El sistema pide al recepcionista que introduzca los parametros requeridos
para realizar la busqueda del cliente.
3 El recepcionista introduce todos, algunos o ninguno de los parametros reque-
ridos
4 El recepcionista confirma que desea buscar a un cliente que coincida con esos
parametros
5 El sistema muestra todos los clientes que coinciden con los parametros de
busqueda y pide al recepcionista que elija a uno de ellos.
5.3. Casos de Uso 48
6 El recepcionista escoge el cliente que buscaba.
7 El sistema pone al cliente elegido como usuario efectivo del sistema.
Flujo alternativo:
*.1 En cualquier momento la persona tiene la posibilidad de cancelar el proceso.
14. Salir de la cuenta de un cliente
Actores Primarios: Recepcionista
Descripcion: Permite al recepcionista dejar de trabajar con la cuenta de un cliente.
Precondiciones: El recepcionista esta autenticado en el sistema y hay un cliente como usuario
efectivo.
Postcondiciones: El cliente deja de ser el usuario efectivo de la aplicacion.
Flujo basico:
1 El recepcionista quiere salir de la cuenta de un cliente.
2 El sistema pide al recepcionista que confirme que desea salir de la cuenta del
cliente.
3 El recepcionista confirma que desea salir.
4 El sistema procesa la peticion y el cliente deja de ser el usuario efectivo de
la aplicacion.
Flujo alternativo:
*.1 En cualquier momento el recepcionista tiene la posibilidad de cancelar el
proceso.
5.3. Casos de Uso 49
15. Dar de Alta Cliente
Actores Primarios: Recepcionista
Descripcion: Permite al recepcionista dar de alta a un nuevo cliente en el sistema cuando
llega al hotel para realizar una reserva.
Precondiciones: El recepcionista esta autenticado en el sistema.
Postcondiciones: El nuevo cliente pasa a estar registrado en el sistema y es usuario efectivo del
mismo.
Flujo basico:
1 El recepcionista quiere dar de alta al nuevo usuario en el sistema.
2 El sistema pide al recepcionista que introduzca los siguientes datos de los
cuales algunos son obligatorios:
• Nombre (obligatorio)
• Apellidos (obligatorio)
• DNI o pasaporte (obligatorio)
• Fecha de Nacimiento (obligatorio)
• Direccion completa (obligatorio)
• Paıs (obligatorio)
• Direccion de e-mail (obligatorio)
• Telefono1 (opcional)
• Telefono2 (opcional)
3 El recepcionista introduce los datos solicitados.
4 El recepcionista confirma que desea dar de alta al nuevo cliente.
5 El sistema procesa la informacion del nuevo cliente.
6 El nuevo cliente pasa a estar dada de alta como cliente y es usuario efectivo
del sistema en ese momento.
5.3. Casos de Uso 50
Flujo alternativo:
*.1 En cualquier momento el recepcionista tiene la posibilidad de cancelar el
proceso.
4.1.1 El recepcionista no ha introducido todos los datos obligatorios.
4.1.2 El sistema indica que tiene que introducir los datos obligatorios y se
vuelve al evento 2 del flujo basico.
4.2.1 El DNI indica que esa persona ya esta dada de alta.
4.2.2 Se le pide al recepcionista que compruebe que ha escrito bien el DNI y
se vuelve al paso 2.
16. Modificar datos de Cliente
Actores Primarios: Recepcionista
Descripcion: Permite al recepcionista modificar los datos con los que se dio de alta un cliente
del sistema.
Precondiciones: El recepcionista esta autenticado en el sistema y hay un cliente como usuario
efectivo.
Postcondiciones: Los datos del cliente estan actualizados.
Flujo basico:
1 El recepcionista quiere modificar los datos con los que se dio de alta el cliente
que esta como usuario efectivo en el sistema.
2 El sistema muestra los datos actuales del cliente y pide al recepcionista que
actualice los que desee de los siguientes:
• Nombre (obligatorio)
• Apellidos (obligatorio)
5.3. Casos de Uso 51
• Fecha de Nacimiento (obligatorio)
• Direccion completa (obligatorio)
• Paıs (obligatorio)
• Direccion de e-mail (obligatorio)
• Telefono1 (opcional)
• Telefono2 (opcional)
3 El recepcionista modifica los datos que quiere.
4 El recepcionista confirma que desea actualizar los datos del cliente.
5 El sistema procesa la actualizacion de los datos del cliente.
6 Los datos del cliente pasan a estar actualizados.
Flujo alternativo:
*.1 En cualquier momento el recepcionista tiene la posibilidad de cancelar el
proceso.
4.1 El recepcionista no ha introducido todos los datos obligatorios.
4.2 El sistema indica que tiene que introducir los datos obligatorios y se vuelve
al evento 2 del flujo basico.
17. Consultar datos de Cliente
Actores Primarios: Recepcionista
Descripcion: Permite al recepcionista consultar los datos con los que se dio de alta un cliente
en el sistema.
Precondiciones: El recepcionista esta autenticado en el sistema y hay un cliente como usuario
efectivo.
Postcondiciones: Ninguna.
5.3. Casos de Uso 52
Flujo basico:
1 El recepcionista quiere consultar los datos con los que se dio de alta el cliente
que esta como usuario efectivo en el sistema.
2 El sistema muestra al recepcionista los datos personales del cliente.
18. Dar de baja Cliente
Actores Primarios: Cliente
Descripcion: Permite al recepcionista dar de baja a un cliente como usuario del sistema.
Precondiciones: El recepcionista esta autenticado en el sistema y hay un cliente como usuario
efectivo.
Postcondiciones: El cliente deja de ser usuario efectivo del sistema y deja de existir como usuario
de la aplicacion.
Flujo basico:
1 El recepcionista quiere dar de baja del sistema al cliente que esta como
usuario efectivo.
2 El sistema muestra un aviso al recepcionista, y pide a este que avise y confirme
que el cliente desea darse de baja.
3 El recepcionista confirma que desea dar de baja al cliente.
4 El sistema procesa la baja del cliente.
5 El cliente deja de ser usuario de la aplicacion.
Flujo alternativo:
*.1 En cualquier momento el recepcionista tiene la posibilidad de cancelar el
proceso.
5.3. Casos de Uso 53
5.3.4. Casos de Uso de Gestion de Reservas
Los Casos de Uso que aquı se detallan son todos los relacionados con la gestion de
las reservas en el establecimiento del hotel por parte del recepcionista a peticion de
un cliente. Se puede ver el diagrama correspondiente en la figura 5.4 de la pagina
81.
19. Hacer reserva
Actores Primarios: Recepcionista
Descripcion: Permite al recepcionista realizar una reserva de una o varias habitaciones para
un dıa determinado para el cliente que lo solicite
Precondiciones: El recepcionista esta autenticado en el sistema y el cliente esta como usuario
efectivo.
Postcondiciones: La reserva queda realizada a espera de que el cliente la pague.
Flujo basico:
1 El recepcionista quiere realizar una reserva de habitacion para el cliente que
es el usuario efectivo actual de la aplicacion.
2 La aplicacion pide al recepcionista que indique el tipo de habitacion que
desea reservar, el dıa que llega el cliente, el dıa de salida, y la cantidad de
habitaciones de ese tipo que necesita.
3 El recepcionista especifica todos los datos solicitados.
4 El recepcionista confirma que el cliente desea realizar la reserva de ese tipo
de habitacion para los dıas indicados.
5 El sistema procesa la reserva.
5.3. Casos de Uso 54
6 La reserva pasa a estar realizada a la espera de ser pagada y se le mues-
tra al recepcionista el numero de reserva para que la pueda localizar y
transmitırselo al cliente que ha solicitado la reserva.
Flujo alternativo:
*.1 En cualquier momento el recepcionista tiene la posibilidad de cancelar el
proceso.
4.1.1 El recepcionista no ha introducido todos los datos.
4.1.2 El sistema indica que tiene que especificar todos los datos y se vuelve al
evento 2 del flujo basico.
4.2.1 El recepcionista ha introducido una fecha de llegada o de salida erronea.
4.2.2 El sistema indica que vuelva a introducir las fechas correctamente. y se
vuelve al evento 2.
4.3.1 No hay habitaciones disponibles para los valores especificados, se indica
y se vuelve al paso 2.
4.4.1 El recepcionista indica que desea realizar la reserva de otro tipo de ha-
bitacion.
4.4.2 El sistema procesa la reserva.
4.4.3 Se vuelve al paso 2 para realizar la siguiente reserva.
20. Consultar reservas
Actores Primarios: Recepcionista
Descripcion: Permite al recepcionista consultar las reservas que ha realizado un cliente del
hotel, se podran ver las reservas pagadas, las canceladas y las que estan aun
pendientes de pago.
Precondiciones: El recepcionista esta autenticado en el sistema y el cliente esta como usuario
efectivo.
5.3. Casos de Uso 55
Postcondiciones: Ninguna.
Flujo basico:
1 El recepcionista quiere consultar las reservas que ha realizado el cliente hasta
el momento
2 El sistema muestra al recepcionista todas las reservas del cliente.
21. Modificar reserva
Actores Primarios: Recepcionista
Descripcion: Permite al recepcionista modificar una reserva realizada por un cliente.
Precondiciones: El recepcionista esta autenticado en el sistema, el cliente esta como usuario
efectivo, y la reserva no esta pagada ni cancelada.
Postcondiciones: La reserva queda modificada a espera de que el cliente la pague.
Flujo basico:
1 El recepcionista quiere modificar una reserva de habitaciones por peticion
del cliente.
2 El recepcionista indica que desea anadir una nueva reserva de habitacion.
3 La aplicacion pide al recepcionista que indique el tipo de habitacion que
desea reservar, el dıa que llega el cliente, el dıa de salida, y la cantidad de
habitaciones de ese tipo que necesita.
4 El recepcionista especifica todos los datos solicitados.
5 El recepcionista confirma que el cliente desea realizar la reserva de ese tipo
de habitacion para los dıas indicados.
6 El sistema procesa la reserva.
5.3. Casos de Uso 56
7 El recepcionista confirma que quiere guardar los cambios realizados en la
reserva de habitaciones del cliente.
8 El sistema guarda la reserva.
Flujo alternativo:
*.1 En cualquier momento el recepcionista tiene la posibilidad de cancelar el
proceso.
2.1 El recepcionista indica que desea eliminar una reserva de habitacion.
2.2 El sistema pide al recepcionista que indique cual es la lınea de reserva que
desea eliminar.
2.3 El recepcionista especifica la lınea de reserva que quiere eliminar.
2.4 El sistema procesa la eliminacion de la lınea de reserva.
2.5 Se pasa al paso 2 del flujo basico.
5.1.1 El recepcionista no ha introducido todos los datos.
5.1.2 El sistema indica que tiene que especificar todos los datos y se vuelve al
evento 2 del flujo basico.
5.2.1 El recepcionista ha introducido una fecha de llegada o de salida erronea.
5.2.2 El sistema indica que vuelva a introducir las fechas correctamente. y se
vuelve al evento 2.
5.3.1 No hay habitaciones disponibles para los valores especificados, se indica
y se vuelve al paso 2.
7.4.1 El recepcionista indica que desea seguir modificando la reserva.
7.4.2 El sistema procesa la reserva.
7.4.3 Se vuelve al paso 2 para continuar modificando
22. Consultar factura
5.3. Casos de Uso 57
Actores Primarios: Recepcionista
Descripcion: Permite al recepcionista consultar la factura de cualquier reserva que haya
realizado un cliente del hotel, se podran ver las facturas pagadas, las canceladas
y las que estan aun pendientes de pago.
Precondiciones: El recepcionista esta autenticado en el sistema y el cliente esta como usuario
efectivo.
Postcondiciones: Ninguna.
Flujo basico:
1 El recepcionista quiere consultar una factura de una reserva que ha realizado
el cliente.
2 El sistema pide al recepcionista que indique el numero de reserva para la
factura que desea consultar.
3 El recepcionista indica el numero de reserva deseado.
4 El sistema muestra al recepcionista la factura de la reserva solitada. En el
caso de que la factura ya este pagada o cancelada muestra el importe que
ha pagado y si la factura esta pendiente de pago muestra el total que debe
pagar indicando aquellos descuentos que se le han proporcionado debido a
las ofertas que se le han podido aplicar.
Flujo alternativo:
*.1 En cualquier momento el recepcionista tiene la posibilidad de cancelar el
proceso.
23. Cancelar reserva
Actores Primarios: Recepcionista
5.3. Casos de Uso 58
Descripcion: Permite al recepcionista cancelar cualquier reserva que haya realizado un cliente
y aun no disfrutado, si la factura estuviese pagada se le devuelve al cliente un
porcentaje del importe, dependiendo de la antelacion con la que la cancele.
Precondiciones: El recepcionista esta autenticado en el sistema y el cliente esta como usuario
efectivo.
Postcondiciones: La reserva queda cancelada.
Flujo basico:
1 El recepcionista quiere cancelar una reserva que ha realizado el cliente.
2 El sistema pide al recepcionista que indique el numero de reserva que desea
cancelar.
3 El recepcionista indica el numero de reserva deseado.
4 El sistema pide al recepcionista la confirmacion de que el cliente quiere can-
celar las reservas de habitaciones de esa reserva.
5 El cliente se lo confirma y el recepcionista lo confirma al sistema.
6 El sistema cancela la reserva.
Flujo alternativo:
*.1 En cualquier momento el recepcionista tiene la posibilidad de cancelar el
proceso.
3.1 El recepcionista indica un numero de reserva que ya habıa sido cancelada
o disfrutada.
3.2 Se le muestra un error al recepcionista y se termina el proceso sin que se
cancele ninguna reserva.
24. Pagar factura
5.3. Casos de Uso 59
Actores Primarios: Recepcionista
Actores de Soporte: Entidad Financiera
Descripcion: Permite al recepcionista marcar la factura de una reserva como pagada cuando
le paga el cliente.
Precondiciones: El recepcionista esta autenticado en el sistema y el cliente es el usuario efectivo.
Postcondiciones: La factura de la reserva esta pendiente de pago y no esta cancelada.
Flujo basico:
1 El recepcionista quiere pagar la factura de una reserva que ha realizado un
cliente.
2 El sistema pide al recepcionista que indique el numero de reserva que desea
pagar.
3 El recepcionista indica el numero de reserva deseado.
4 El sistema muestra al recepcionista la factura de la reserva y le pide la con-
firmacion de que quiere pagarla.
5 El recepcionista indica al cliente el importe que debe pagar.
6 El cliente paga al recepcionista y el recepcionista confirma el pago.
7 El sistema procesa la confirmacion y marca la factura como pagada.
Flujo alternativo:
(1-5).1 En cualquier momento el recepcionista tiene la posibilidad de cancelar
el proceso.
3.1 El recepcionista indica un numero de reserva que ya habıa sido pagado o
que ya esta en proceso de pago.
3.2 Se le muestra un error al recepcionista y se termina el proceso sin que se
pague la factura de la reserva.
5.3. Casos de Uso 60
6.1 El cliente no le paga al recepcionista.
6.2 El recepcionista cancela el pago de la factura.
5.3.5. Casos de Uso de Gestion de Habitaciones
Los Casos de Uso que aquı se detallan son todos los relacionados con la gestion de las
habitaciones en el establecimiento del hotel por parte del administrador del sistema.
Se puede ver el diagrama correspondiente en la figura 5.5 de la pagina 82.
25. Crear Tipo de Habitacion
Actores Primarios: Administrador
Descripcion: Permite al administrador crear un nuevo tipo de habitacion en el momento
que estime necesario, ya sea por apertura del hotel, reforma, modificacion de
habitaciones, etc. Los tipos de habitaciones son los que definen entre otras cosas
el precio base de una habitacion.
Precondiciones: El administrador esta autenticado en el sistema.
Postcondiciones: El nuevo tipo de habitacion esta creado.
Flujo basico:
1 El administrador quiere crear un nuevo tipo de habitacion.
2 La aplicacion pide al administrador que introduzca los siguentes datos: Des-
cripcion del tipo de habitacion (obligatorio), Numero de personas para
las que esta acondicionada la habitacion (obligatorio) y precio base que
tendra una habitacion de este tipo (obligatorio).
3 El administrador especifica todos los datos solicitados.
4 El administrador confirma que desea crear un tipo de habitacion con los datos
indicados.
5.3. Casos de Uso 61
5 El sistema crea el nuevo tipo de habitacion.
Flujo alternativo:
*.1 En cualquier momento el administrador tiene la posibilidad de cancelar el
proceso.
3.1 El administrador no introduce todos los datos.
3.2 El sistema indica que tiene que especificar todos los datos y se vuelve al
evento 2 del flujo basico.
26. Consultar Tipo de Habitacion
Actores Primarios: Recepcionista, Administrador
Descripcion: Permite al administrador consultar los datos de un tipo de habitacion.
Precondiciones: El administrador esta autenticado en el sistema.
Postcondiciones: Ninguna.
Flujo basico:
1 El administrador quiere consultar los datos de un tipo de habitacion.
2 El sistema pide al administrador que indique el tipo de habitacion que desea
consultar.
3 El administrador especifica el tipo que quiere consultar.
4 El sistema muestra al administrador el tipo de habitacion requerido.
Flujo alternativo:
*.1 En cualquier momento el administrador tiene la posibilidad de cancelar el
proceso.
5.3. Casos de Uso 62
3.1 El administrador no introduce un tipo de habitacion existente.
3.2 El sistema indica que no existe el tipo de habitacion especificado y se vuelve
al evento 2 del flujo basico.
27. Modificar Tipo de Habitacion
Actores Primarios: Administrador
Descripcion: Permite al administrador modificar un tipo de habitacion en el momento que
estime necesario, ya sea por reforma, modificacion de habitaciones, etc.
Precondiciones: El administrador esta autenticado en el sistema.
Postcondiciones: El tipo de habitacion esta actualizado.
Flujo basico:
1 El administrador quiere modificar un tipo de habitacion.
2 El sistema pide al administrador que indique el tipo de habitacion que desea
modificar.
3 El administrador especifica el tipo que quiere actualizar.
4 La aplicacion muestra al administrador los datos del tipo de habitacion y
pide a este que actualice los siguentes datos: Descripcion del tipo de habi-
tacion (obligatorio), Numero de personas para las que esta acondicionada
la habitacion (obligatorio) y precio base que tendra una habitacion de este
tipo.
5 El administrador especifica todos los datos solicitados.
6 El administrador confirma que desea guardar los cambios realizados.
7 El sistema actualiza el tipo de habitacion con los nuevos datos.
Flujo alternativo:
5.3. Casos de Uso 63
*.1 En cualquier momento el administrador tiene la posibilidad de cancelar el
proceso.
3.1 El administrador no introduce un tipo de habitacion existente.
3.2 El sistema indica que no existe el tipo de habitacion especificado y se vuelve
al evento 2 del flujo basico.
5.1 El administrador no introduce todos los datos.
5.2 El sistema indica que tiene que especificar todos los datos y se vuelve al
evento 4 del flujo basico.
28. Crear Habitacion
Actores Primarios: Administrador
Descripcion: Permite al administrador crear una nueva habitacion en el momento que estime
necesario, ya sea por apertura del hotel, reforma, modificacion de habitaciones,
etc. Los tipos de habitaciones son los que definen entre otras cosas el precio
extra de una habitacion, y el tipo de habitacion.
Precondiciones: El administrador esta autenticado en el sistema.
Postcondiciones: La nueva habitacion esta creada.
Flujo basico:
1 El administrador quiere crear una nueva habitacion.
2 La aplicacion pide al administrador que introduzca los siguentes datos: Ti-
po de habitacion (obligatorio), Numero de habitacion (obligatorio), piso
en el que esta la habitacion y precio extra que tendra esta habitacion en
particular.
3 El administrador especifica todos los datos solicitados.
5.3. Casos de Uso 64
4 El administrador confirma que desea crear una habitacion con los datos in-
dicados.
5 El sistema crea la nueva habitacion.
Flujo alternativo:
*.1 En cualquier momento el administrador tiene la posibilidad de cancelar el
proceso.
3.1 El administrador no introduce todos los datos.
3.2 El sistema indica que tiene que especificar todos los datos y se vuelve al
evento 2 del flujo basico.
29. Consultar Habitacion
Actores Primarios: Recepcionista, Administrador
Descripcion: Permite al administrador consultar los datos de una habitacion.
Precondiciones: El administrador esta autenticado en el sistema.
Postcondiciones: Ninguna.
Flujo basico:
1 El administrador quiere consultar los datos de una habitacion.
2 El sistema pide al administrador que indique el numero de la habitacion que
desea consultar.
3 El administrador especifica el numero de habitacion que quiere consultar.
4 El sistema muestra al administrador los datos de la habitacion requerida.
Flujo alternativo:
5.3. Casos de Uso 65
*.1 En cualquier momento el administrador tiene la posibilidad de cancelar el
proceso.
3.1 El administrador no introduce un numero de habitacion existente.
3.2 El sistema indica que no existe la habitacion especificada y se vuelve al
evento 2 del flujo basico.
30. Modificar Habitacion
Actores Primarios: Administrador
Descripcion: Permite al administrador modificar una habitacion en el momento que estime
necesario, ya sea por reforma, etc.
Precondiciones: El administrador esta autenticado en el sistema.
Postcondiciones: La habitacion esta actualizada.
Flujo basico:
1 El administrador quiere modificar los datos de una habitacion.
2 El sistema pide al administrador que indique el numero de la habitacion que
desea modificar.
3 El administrador especifica el numero de la habitacion que quiere actualizar.
4 La aplicacion muestra al administrador los datos de la habitacion y pide
a este que actualice los siguentes datos: Tipo de habitacion (obligatorio),
Numero de la habitacion (obligatorio), piso (obligatorio) y precio extra que
tendra esta habitacion en particular.
5 El administrador especifica todos los datos solicitados.
6 El administrador confirma que desea guardar los cambios realizados.
7 El sistema actualiza la habitacion con los nuevos datos.
5.3. Casos de Uso 66
Flujo alternativo:
*.1 En cualquier momento el administrador tiene la posibilidad de cancelar el
proceso.
3.1 El administrador no introduce un numero de habitacion existente.
3.2 El sistema indica que no existe la habitacion especificada y se vuelve al
evento 2 del flujo basico.
5.1 El administrador no introduce todos los datos.
5.2 El sistema indica que tiene que especificar todos los datos y se vuelve al
evento 4 del flujo basico.
31. Registrar Incidencia de Habitacion
Actores Primarios: Administrador
Descripcion: Permite al administrador registrar alguna incidencia que haya tenido lugar en
una de las habitaciones del hotel.
Precondiciones: El administrador esta autenticado en el sistema.
Postcondiciones: La incidencia queda registrada y asociada a la habitacion pertinente.
Flujo basico:
1 El administrador quiere registrar una nueva incidencia.
2 El sistema pide al administrador que indique el numero de la habitacion a la
cual desea asociar la incidencia.
3 El administrador especifica el numero de la habitacion que requerido.
4 La aplicacion pide al administrador que introduzca los siguentes datos: Tipo
de incidencia (obligatorio): grave, leve, etc, y una descripcion textual de lo
ocurrido.
5 El administrador especifica todos los datos solicitados.
5.3. Casos de Uso 67
6 El administrador confirma que desea registrar la incidencia.
7 El sistema registra la incidencia asociada a la habitacion que procede.
Flujo alternativo:
*.1 En cualquier momento el administrador tiene la posibilidad de cancelar el
proceso.
3.1 El administrador no introduce un numero de habitacion existente.
3.2 El sistema indica que no existe la habitacion especificada y se vuelve al
evento 2 del flujo basico.
5.1 El administrador no introduce todos los datos.
5.2 El sistema indica que tiene que especificar todos los datos y se vuelve al
evento 4 del flujo basico.
32. Consultar Incidencias de Habitacion
Actores Primarios: Administrador
Descripcion: Permite al administrador consultar todas las incidencias que hayan tenido lugar
en una de las habitaciones del hotel.
Precondiciones: El administrador esta autenticado en el sistema.
Postcondiciones: Ninguna.
Flujo basico:
1 El administrador quiere consultar las incidencias de una habitacion.
2 El sistema pide al administrador que indique el numero de la habitacion de
la cual desea consultar las incidencias.
3 El administrador especifica el numero de la habitacion que requerido.
5.3. Casos de Uso 68
4 El sistema muestra al administrador todas las incidencias ocurridas en esa
habitacion.
Flujo alternativo:
*.1 En cualquier momento el administrador tiene la posibilidad de cancelar el
proceso.
3.1 El administrador no introduce un numero de habitacion existente.
3.2 El sistema indica que no existe la habitacion especificada y se vuelve al
evento 2 del flujo basico.
5.3.6. Casos de Uso de Gestion de Ofertas
Los Casos de Uso que aquı se detallan son todos los relacionados con la gestion de
las ofertas en el establecimiento del hotel por parte del administrador del sistema. El
administrador es el engargado de dar de alta nuevas ofertas y tiene la responsabilidad
de especificar correctamente que ofertas son incompatibles con que otras, y las reglas
de aplicacion por las que se regiran, estas reglas definiran el contexto en el cual una
oferta se podra aplicar. Se puede ver el diagrama correspondiente en la figura 5.6 de
la pagina 83.
33. Crear Tipo de Oferta
Actores Primarios: Administrador
Descripcion: Permite al administrador crear un nuevo tipo de oferta en el momento que
estime necesario. Los tipos de oferta son los que definen entre otras cosas a
que se podra aplicar la oferta, reservas de habitaciones, servicios extra, etc, y
con que otros tipos de oferta sera incompatible.
Precondiciones: El administrador esta autenticado en el sistema.
5.3. Casos de Uso 69
Postcondiciones: El nuevo tipo de oferta esta creado.
Flujo basico:
1 El administrador quiere crear un nuevo tipo de oferta.
2 La aplicacion pide al administrador que introduzca los siguentes datos: Nom-
bre para el tipo de oferta (obligatorio), Descripcion del tipo de oferta (obli-
gatorio), A que se podra aplicar este tipo de oferta (obligatorio) y cantidad
mınima (obligatorio), y con que otros tipos de oferta sera incompatible este
nuevo tipo.
3 El administrador especifica todos los datos solicitados.
4 El administrador confirma que desea crear un tipo de oferta con los datos
indicados.
5 El sistema crea el nuevo tipo de oferta.
Flujo alternativo:
*.1 En cualquier momento el administrador tiene la posibilidad de cancelar el
proceso.
3.1 El administrador no introduce todos los datos obligatorios.
3.2 El sistema indica que tiene que especificar todos los datos y se vuelve al
evento 2 del flujo basico.
34. Consultar Tipo de Oferta
Actores Primarios: Administrador
Descripcion: Permite al administrador consultar los datos de un tipo de oferta.
Precondiciones: El administrador esta autenticado en el sistema.
Postcondiciones: Ninguna.
5.3. Casos de Uso 70
Flujo basico:
1 El administrador quiere consultar los datos de un tipo de oferta.
2 El sistema pide al administrador que indique el tipo de oferta que desea
consultar.
3 El administrador especifica el tipo que quiere consultar.
4 El sistema muestra al administrador los datos del tipo de oferta requerido.
Flujo alternativo:
*.1 En cualquier momento el administrador tiene la posibilidad de cancelar el
proceso.
3.1 El administrador no introduce un tipo de oferta existente.
3.2 El sistema indica que no existe el tipo de oferta especificado y se vuelve al
evento 2 del flujo basico.
35. Modificar Tipo de Oferta
Actores Primarios: Administrador
Descripcion: Permite al administrador modificar un tipo de oferta en el momento que estime
necesario.
Precondiciones: El administrador esta autenticado en el sistema.
Postcondiciones: El tipo de oferta esta actualizado.
Flujo basico:
1 El administrador quiere modificar un tipo de oferta.
2 El sistema pide al administrador que indique el tipo de habitacion que desea
modificar.
5.3. Casos de Uso 71
3 El administrador especifica el tipo que quiere actualizar.
4 La aplicacion muestra al administrador los datos del tipo de oferta y pide a
este que actualice los siguentes datos: Nombre para el tipo de oferta (obliga-
torio), Descripcion del tipo de oferta (obligatorio), A que se podra aplicar
este tipo de oferta (obligatorio) y cantidad mınima (obligatorio), y con
que otros tipos de oferta sera incompatible este tipo.
5 El administrador especifica todos los datos solicitados.
6 El administrador confirma que desea guardar los cambios realizados.
7 El sistema actualiza el tipo de oferta con los nuevos datos.
Flujo alternativo:
*.1 En cualquier momento el administrador tiene la posibilidad de cancelar el
proceso.
3.1 El administrador no introduce un tipo de oferta existente.
3.2 El sistema indica que no existe el tipo de oferta especificado y se vuelve al
evento 2 del flujo basico.
5.1 El administrador no introduce todos los datos obligatorios.
5.2 El sistema indica que tiene que especificar todos los datos y se vuelve al
evento 4 del flujo basico.
36. Crear Oferta
Actores Primarios: Administrador
Descripcion: Permite al administrador crear una nueva oferta en el momento que estime
necesario, ya sea por apertura del hotel, eventos especiales, etc. Las Ofertas son
las que definen entre otras cosas a quien se le podra aplicar una oferta gracias
a las reglas que se pueden definir, fechas de aplicacion, etc.
5.3. Casos de Uso 72
Precondiciones: El administrador esta autenticado en el sistema.
Postcondiciones: La nueva oferta esta creada pero como un borrador que luego habra que revisar
y publicar.
Flujo basico:
1 El administrador quiere crear una nueva oferta.
2 La aplicacion pide al administrador que introduzca los siguentes datos: Ti-
po de oferta (obligatorio), Fecha en la que se comenzara y terminara la
aplicacion de la oferta (obligatorio), Descuento que ofrece esta oferta (obi-
gatorio), Descripcion de la oferta (obligatorio) y regla que sera utilizada
por el sistema a la hora de saber si una oferta se puede aplicar en ciertas
condiciones especiales (obligatorio).
3 El administrador especifica todos los datos solicitados.
4 El administrador confirma que desea crear una oferta con los datos indicados.
5 El sistema crea la nueva oferta y se marca como borrador no publicado.
Flujo alternativo:
*.1 En cualquier momento el administrador tiene la posibilidad de cancelar el
proceso.
3.1 El administrador no introduce todos los datos.
3.2 El sistema indica que tiene que especificar todos los datos y se vuelve al
evento 2 del flujo basico.
37. Consultar Oferta
Actores Primarios: Administrador
Descripcion: Permite al administrador consultar los datos de una oferta.
5.3. Casos de Uso 73
Precondiciones: El administrador esta autenticado en el sistema.
Postcondiciones: Ninguna.
Flujo basico:
1 El administrador quiere consultar los datos de una oferta.
2 El sistema pide al administrador que indique el numero de la oferta que desea
consultar.
3 El administrador especifica el numero de oferta que quiere consultar.
4 El sistema muestra al administrador los datos de la oferta requerida.
Flujo alternativo:
*.1 En cualquier momento el administrador tiene la posibilidad de cancelar el
proceso.
3.1 El administrador no introduce un numero de oferta existente.
3.2 El sistema indica que no existe la oferta especificada y se vuelve al evento
2 del flujo basico.
38. Modificar Oferta
Actores Primarios: Administrador
Descripcion: Permite al administrador modificar una oferta en el momento que estime nece-
sario, ya sea por reforma, etc, siempre y cuando esta oferta aun sea un borrador.
Precondiciones: El administrador esta autenticado en el sistema y la oferta aun esta marcada
como borrador y no ha sido publicada.
Postcondiciones: La oferta esta actualizada.
5.3. Casos de Uso 74
Flujo basico:
1 El administrador quiere modificar los datos de una oferta.
2 El sistema pide al administrador que indique el numero de la oferta que desea
modificar.
3 El administrador especifica el numero de la oferta que quiere actualizar.
4 La aplicacion muestra al administrador los datos de la oferta y pide a este que
actualice los siguentes datos: Tipo de oferta (obligatorio), Fecha en la que
se comenzara y terminara la aplicacion de la oferta (obligatorio), Descuento
que ofrece esta oferta (obigatorio), Descripcion de la oferta (obligatorio) y
regla que sera utilizada por el sistema a la hora de saber si una oferta se
puede aplicar en ciertas condiciones especiales (obligatorio).
5 El administrador especifica todos los datos solicitados.
6 El administrador confirma que desea guardar los cambios realizados.
7 El sistema actualiza la oferta con los nuevos datos.
Flujo alternativo:
*.1 En cualquier momento el administrador tiene la posibilidad de cancelar el
proceso.
3.1 El administrador no introduce un numero de oferta existente.
3.2 El sistema indica que no existe la oferta especificada y se vuelve al evento
2 del flujo basico.
5.1 El administrador no introduce todos los datos.
5.2 El sistema indica que tiene que especificar todos los datos y se vuelve al
evento 4 del flujo basico.
39. Eliminar Oferta
5.3. Casos de Uso 75
Actores Primarios: Administrador
Descripcion: Permite al administrador eliminar una oferta que estaba como borrador.
Precondiciones: El administrador esta autenticado en el sistema, la oferta no esta publicada y
esta marcada como borrador.
Postcondiciones: La oferta esta eliminada y deja de existir.
Flujo basico:
1 El administrador quiere eliminar una oferta.
2 El sistema pide al administrador que indique el numero de la oferta que desea
eliminar.
3 El administrador especifica el numero de oferta requerido.
4 La aplicacion pide al administrador la confirmacion de que desea eliminar la
oferta indicada.
5 El administrador confirma que desea eliminar la oferta.
6 El sistema elimina la oferta.
Flujo alternativo:
*.1 En cualquier momento el administrador tiene la posibilidad de cancelar el
proceso.
3.1 El administrador no introduce un numero de oferta existente.
3.2 El sistema indica que no existe la oferta especificada y se vuelve al evento
2 del flujo basico.
40. Publicar Oferta
Actores Primarios: Administrador
5.3. Casos de Uso 76
Descripcion: Permite al administrador publicar una oferta para que la puedan disfrutar los
clientes.
Precondiciones: El administrador esta autenticado en el sistema y la oferta no esta publicada.
Postcondiciones: La oferta queda publicada.
Flujo basico:
1 El administrador quiere publicar una oferta.
2 El sistema pide al administrador que indique el numero de la oferta que desea
publicar.
3 El administrador especifica el numero la oferta requerido.
4 La aplicacion pide al administrador la confirmacion de que desea publicar la
oferta indicada.
5 El administrador confirma que desea publicar la oferta.
6 El sistema publica la oferta.
Flujo alternativo:
*.1 En cualquier momento el administrador tiene la posibilidad de cancelar el
proceso.
3.1 El administrador no introduce un numero de oferta existente.
3.2 El sistema indica que no existe la oferta especificada y se vuelve al evento
2 del flujo basico.
41. Dar de baja Oferta
Actores Primarios: Administrador
5.3. Casos de Uso 77
Descripcion: Permite al administrador dar de baja una oferta. Esto es un mecanismo de
seguridad por si se publico una oferta por error o descuido que pueda afectar
gravemente a la economıa del establecimiento.
Precondiciones: El administrador esta autenticado en el sistema y la oferta esta publicada.
Postcondiciones: La oferta deja de estar publicada.
Flujo basico:
1 El administrador quiere dar de baja una oferta.
2 El sistema pide al administrador que indique el numero de la oferta que desea
dar de baja.
3 El administrador especifica el numero de oferta requerido.
4 El sistema pide al administrador la confirmacion de que desea dar de baja la
oferta indicada.
5 El administrador confirma que desea dar de baja la oferta.
6 El sistema da de baja la oferta y de esta forma deja de estar publicada para
el publico.
Flujo alternativo:
*.1 En cualquier momento el administrador tiene la posibilidad de cancelar el
proceso.
3.1 El administrador no introduce un numero de oferta existente.
3.2 El sistema indica que no existe la oferta especificada y se vuelve al evento
2 del flujo basico.
5.4. Modelo de Casos de Uso 78
5.4. Modelo de Casos de Uso
5.4.1. Gestion de Usuarios Web
Figura 5.1: Diagrama de Casos de Uso de Gestion de Usuarios Web
5.4. Modelo de Casos de Uso 79
5.4.2. Gestion de Reservas Web
Figura 5.2: Diagrama de Casos de Uso de Gestion de Reservas Web
5.4. Modelo de Casos de Uso 80
5.4.3. Gestion de Clientes
Figura 5.3: Diagrama de Casos de Uso de Gestion de Clientes
5.4. Modelo de Casos de Uso 81
5.4.4. Gestion de Reservas
Figura 5.4: Diagrama de Casos de Uso de Gestion de Reservas
5.4. Modelo de Casos de Uso 82
5.4.5. Gestion de Habitaciones
Figura 5.5: Diagrama de Casos de Uso de Gestion de Habitaciones
5.4. Modelo de Casos de Uso 83
5.4.6. Gestion de Ofertas
Figura 5.6: Diagrama de Casos de Uso de Gestion de Ofertas
Capıtulo 6
Diseno de la aplicacion
6.1. Arquitectura General
Para el desarrollo de este proyecto se va a seguir el patron arquitectonico Modelo-Vista-
Controlador cuyo objetivo es desligar el diseno de las interfaces de usuario del resto del
sistema. Hoy en dıa es la tecnica habitual de diseno de interfaces en la programacion
Web con J2EE. Con esta tecnica se consiguen principalmente dos cosas: que el modelo
sea reusable con distintas vistas, lo que es una ventaja si el dıa de manana se quiere
realizar una interfaz grafica local; y gracias a que se desarrolla de esta forma el software,
se puede dividir el trabajo de forma clara dentro de un equipo, segun la especialidad de
cada miembro.
Pero la arquitectura mejora cuando se usan conjuntamente con el patron arquitectonico
Layers. Usando esta arquitectura el software se estructura en capas de forma que un cambio
en una de ellas, o incluso el reemplazo, no produce un cambio en capas superiores.
El Modelo Es una abstraccion que representa a los objetos de la aplicacion que se
esta desarrollando, en esta capa se incluyen tanto los datos (Bases de Datos, Ficheros,
85
6.1. Arquitectura General 86
etc) como las reglas de negocio (el comportamiento que debe tener la aplicacion). No tiene
conocimiento de ninguna de las otra dos partes, vista y controlador.
La Vista El la capa encargada de la representacion visual de los datos del modelo, para
ello necesita acceder al modelo para obtener los datos que tiene que mostrar al usuario
final.
El Controlador El controlador es el encargado de recoger las acciones que el usuario
efectua sobre la vista, para a continuacion invocar las acciones pertinentes del modelo,
normalmente, y ası es en este caso, es el unico que conoce a las otras dos capas, modelo y
vista.
A continuacion (figura 6.1) se muestra un pequeno esquema de como se va a dividir el
sistema que se esta desarrollando con algunos de los subsitemas que se pueden encontrar
en cada una de las capas.
Figura 6.1: Arquitectura General Del Sistema (Modelo-Vista-Controlador)
6.2. Capa de la Vista 87
En las siguientes secciones se explica cada una de estas tres capas en detalle, que contiene,
que objetivos se persiguen, patrones y tecnologıas utilizados.
6.2. Capa de la Vista
La capa vista incluye todos aquellos paquetes y artefactos necesarios para la presentacion
grafica. En esta capa se incluyen las paginas JSP y los objetos que estas necesitan para
una correcta representacion de los datos.
En esta capa se usa la tecnologıa JSP que permite escribir paginas web usando codigo
java, pero, para no incluir codigo java en las paginas web de este proyecto, se usara el API
de JSTL que permite ocultar todo el codigo java mediante etiquetas ya predefinidas. De
esta forma se consigue que en un futuro un disenador grafico pueda disenar la forma que
deben tener las paginas sin tener que saber nada sobre el lenguaje de programacion Java.
Como se puede observar en la figura 6.2, esta capa se divide en dos partes bien diferen-
ciadas, una de ellas es la que contiene las paginas JSP y la otra es donde estan ubicados
los recursos java que estas paginas necesitan para poder mostrar su contenido.
Figura 6.2: Arquitectura de la Capa Vista
6.2. Capa de la Vista 88
6.2.1. Hojas de Estilo - CSS
El estilo de la interfaz web de usuario lo definen unas hojas de estilo creadas para tal
efecto, de esta forma, las paginas JSP que se explicaran a continuacion solo tienen que
definir la estructura general y el contenido, dejando toda la parte de presentacion para la
hoja de estilos.
Los estilos se han definido todos tomando como base un estilo css libre y se ha adaptado
totalmente para que la relacion de tamanos se hiciese de forma relativa y no absoluta, esto
se consigue adaptando todos los tamanos y posiciones, expresandolos de forma porcentual.
Con esto se consigue que, sea cual sea la resolucion del ordenador desde el que se visualice
la aplicacion, esta no tenga unas dimensiones fijas, sino que se adapte a las dimensiones
del navegador.
6.2.2. Paginas JSP
Para la presentacion mediante paginas JSP se usa un sistema de plantillas, ası simple-
mente hay que definir la apariencia global de un grupo de paginas y todas aquellas que
extiendan esa plantilla tendran una apariencia similar. En el caso de este proyecto, se
considero que al haber tres tipos de usuarios bien diferenciados, serıa una buena idea que
hubiese tres plantillas distintas para diferenciar claramente que tipo de usuario esta en la
aplicacion en cada momento.
A su vez dentro de cada plantilla hay dos opciones de presentacion, que se diferencian
usando luego hojas de estilo en cascada (CSS). Por un lado estan las paginas que solo
muestran informacion, y aquellas que ademas de mostra informacion tienen una barra
lateral que permite escoger la operacion que se desea realizar. En el caso que nos ocupa
se usa el sistema de plantillas Tiles de Struts.
Ademas Struts nos proporciona un sistema mediante el cual mostrar y recoger datos de
formularios se realiza de forma mas sencilla. Este sistema lo proporcionan los servlet y los
6.2. Capa de la Vista 89
ActionForms que define el programador y cuyo funcionamiento se detalla en una seccion
posterior.
6.2.2.1. Sistema de Plantillas Tiles de Struts
Gracias a este sistema de plantillas se pueden definir todas las pantallas de una aplicacion
web en un fichero XML. Despues de tener las pantallas definidas, se pueden usar tags
predefinidos para recuperar lo que se necesite: tıtulo, enlaces, etc.
En primer lugar hay que definir una pantalla base por cada conjunto de ventanas. Esta
pantalla base especifica la pagina JSP que contiene la estructura basica de este conjunto
de ventanas y todo aquello que es comun a todas ellas.
Luego para definir cada una de las distintas pantallas, simplemente se extiende de la
pantanlla base deseada y se ponen los valores propios de la ventana que se desea mostrar.
En la figura 6.3 se pueden ver dos plantillas que posteriormente puede derivar en dos
ventanas diferentes dependiento de los valores con los que se extienda la pantalla base.
La estructura basica de cada grupo de pantallas se define en una pagina JSP que se
llama DefaultLayout.jspx y las partes comunes se especificaran en DefaultFooter.jspx y
DefaultTitle.jspx.
Figura 6.3: Plantilla de una ventana
6.2. Capa de la Vista 90
Tıtulo Es la zona donde ira el nombre de la empresa y el tıtulo de la parte de la aplicacion
en la que se esta trabajando.
Cabezera Aquı se mostrara una pequena descripcion de la operacion en curso que se
muestra en la parte de Contenido.
Contenido Aquı se mostrara el resultado de la operacion solicitada por el usuario:
tablas, formularios, imagenes, etc.
Menu En esta zona se posicionaran los enlaces a las distintas operaciones que el usuario
puede realizar.
Pie de pagina Este es el lugar donde se pondra el nombre del desarrollador, licencia
bajo la que esta publicado el software, polıtica de privacidad, etc.
Una vez terminada la aplicacion, el resultado no tiene nada que ver con rectangulos
como se observo en la figura anterior, sino que quedarıa algo como lo que se muestra en
la siguiente imagen.
Figura 6.4: Resultado Final de una ventana
6.2. Capa de la Vista 91
6.2.3. ActionForms
Un ActionForm es simplemente un Bean que contiene las funcionalidades basicas de un
formulario, entrada y recuperacion de los datos de cada campo, y ademas proporciona, si
es necesario, una validacion de los datos a la hora del procesamiento de los mismos.
Definir un ActionForm es muy sencillo, simplemente hay que heredar de la clase Action-
Form que proporciona Struts y luego el Objeto que se esta construyendo debe contener
metodos Get y Set para todos los campos del formulario. Luego para trabajar con este
Objeto hay que especificar en el fichero de configuracion de Struts donde se encuentra el
objeto y a la hora de usarlo en una accion simplemente se tiene que indicar que se va a
utilizar dicho objeto y si se desea que se valide el contenido antes de pasarselo a la accion.
En la pagina JSP cuando dentro de una etiqueta ’<form>’ se desea especificar que un
campo determinado, va a ser un campo del objeto ActionForm que se ha definido para ese
formulario, simplemente se le anade a la etiqueta correspondiente el atributo ’property’
con el valor del nombre exacto del atributo del ActionForm que lo define. A partir de
aquı ya se encarga Struts de manejar el formulario y de pasarle a la accion que lo gestiona,
el ActionForm que corresponda, de forma que en la accion de Struts se puede recuperar
de forma sencilla el valor del formulario, o viceversa, introducir datos previamente en un
formulario antes de que sea mostrado.
6.2.4. Internacionalizacion
Internacionalizar una aplicacion consiste en que esta sea accesible y funcione correcta-
mente sea cual sea el paıs e idioma donde se utiliza el sistema. Localizar una aplicacion no
es simplemente que los textos aparezcan en otro idioma, sino que tambien hay que tener
en cuenta otros detalles como por ejemplo la representacion de numeros, porcentajes o
fechas. Ya que en paıses como Gran Bretana los decimales se representan con un punto
como separador mientras que en Espana se indica con una coma.
6.2. Capa de la Vista 92
En un sistema como el que se esta desarrollando es obligatoria la intenacionalizacion.
En otras aplicaciones es aconsejable, pero en esta no puede faltar ya que al tratarse de
una aplicacion para un hotel, que esta estea internacionalizada permite que el sistema sea
accesible para gente de muchos paıses.
La internacionalizacion de aplicaciones web empresariales con paginas JSP es muy sen-
cilla utilizando las etiquetas que nos proporciona la librerıa JSTL. Lo mas complicado es
integrar la localizacion de JSTL con la que proporciona Struts ya que, entre otras cosas,
utilizan procesos distintos para localizar las traducciones. La librerıa de JSTL proporciona
las etiquetas ’<fmt:xxxxxx/>’ que sirven proporcionan formas sencillas para especificar
mensajes, ya que solo hay que indicar la clave correspondiente del fichero de mensajes,
ademas estas etiquetas proporcionan metodos simples para internacionalizar numeros de-
cimales, porcentajes o las distintas fechas.
Lo primero que hay que hacer es especificar en los distintos ficheros de configuracion
como se llaman los archivos que contienen las traducciones. Las traducciones dentro de
estos ficheros tienen la forma clave=valor. En este caso los ficheros tendran como nom-
bre Messages.properties la traduccion basica por defecto que estara en ingles y Messa-
ges ll CC.properties las demas traducciones donde ’ll’ es el codigo de idioma y ’CC’ el
codigo de paıs que identifican unıvocamente la traduccion. Los codigos de los idiomas
estan definidos en el estandar ISO 639 y los codigos de los paıses en el estandar ISO 3166.
Cuando se inicia la aplicacion esta coge como idioma el mismo que tiene el navegador
del cliente, si no se puede identificar entonces se tomara el idioma del servidor web, y si
tampoco se puede identificar o el idioma aun no esta soportado, entonces se escogera el
idioma por defecto.
Una vez dentro del sistema el usuario, sea cual sea, tiene la posibilidad de elegir el idioma
que desee de entre todos los disponibles.
En el proyecto que se esta realizando, esta internacionalizacion se realizara en tres idio-
mas: Gallego, Castellano e Ingles. Con estos tres idiomas se puede acceder a muchısimos
6.3. Capa del Controlador 93
millones de personas. Aunque sera muy sencillo realizar nuevas traducciones para otros
idiomas, simplemente se crea un nuevo fichero con los codigos de idioma y paıs desea-
dos, y se cambian las traducciones actuales por las correctas para el idioma que se quiera
traducir.
6.2.5. ApplicationObjects
Los ApplicationObjects son objetos de utilidad que utiliza la capa vista para la repre-
sentacion de algunos datos, en el caso de este proyecto se necesitaba por ejemplo de un
objeto que sirviera para mostrar las fechas, algo muy util ya que la utilizacion de fechas
es muy comun entre muchos de los casos de uso que se implementan. Esta clase se llama
DateRanges, se ha aprovechado de la implentacion de un ejemplo que distribuyeron en la
asignatura de IS de quinto curso de Ingenierıa Informatica.
Por otro lado tambien se vio la necesidad de una clase que sirviera de cache para mostrar
los tipos de habitacion que hay en el sistema. Como los tipos de habitacion se utilizan
mucho, serıa muy ineficiente consultarlos en la base de datos cada vez que se quisieran
mostrar. Por eso, esta clase guarda en memoria todos los tipos de habitacion tan pronto
como la clase es cargada en memoria. La poca memoria que se desperdicia se compensa
por la eficiencia que se gana con el ahorro en accesos a la base de datos.
6.3. Capa del Controlador
La capa del controlador es la que contiene aquellos paquetes y artefactos necesarios para
la separacion de la vista y del modelo. Para el diseno de esta capa se utilizan una serie de
patrones arquitectonicos que se muestran a continuacion en las siguientes secciones.
En esta capa es en la que se centra principalmente Struts, proporcionando todas las
implementaciones basicas que se necesitan para el desarrollo de una aplicacion web em-
presarial.
6.3. Capa del Controlador 94
6.3.1. Patron Front Controller
El patron Front Controller consiste en que, cada vez que el servidor recibe una nueva
peticion siempre la procesa el mismo controlador, que lo unico que hace es delegar en otras
clases para que resuelvan la peticion. Para esto struts proporciona la clase ActionServlet
que luego hay que extender para anadirle nuevas funcionalidades personalizadas como
filtros de procesado.
Lo primero que se hace es indicar en el fichero de configuracion del servidor, que todas
las peticiones que terminen en ’.do’ las procese el nuevo Servlet que se ha definido. Para
decirle al servidor que todas estas peticiones vayan al servlet personalizado, simplemente
hay que especificar el patron que siguen (en este caso *.do) y a continuacion especificar el
nombre de la clase que extiende ActionServlet.
En la figura 6.5 podemos ver como se esctructuran las distintas clases que dan forma a
este patron.
6.3. Capa del Controlador 95
javax.servlet.http.HttpServlet
org.apache.struts.action.ActionServlet
#doGet()#doPost()
org.apache.struts.action.Action
+execute()
1 0..*
org.apache.struts.action.ActionForm
+reset()+validate()
<<instantiate>>
<<call>>
Action1 ActionN
ActionForm1 ActionFormN
<<call>>
Figura 6.5: Patron Front Controller General
Ahora vamos a describir como se relacionan las clases que se ven en el diagrama anterior.
Cuando el servidor web recibe una peticion comprueba si la URL solicitada cumple
alguno de los patrones que se especifican en su fichero de configuracion web.xml, si es ası,
entonces crea una instancia del ActionServlet que tiene indicado para manejar esa peticion.
En el caso del proyecto que se esta desarrollando, el ActionServlet que gestionara las
peticiones de URLs terminadas en ’.do’ sera HotelPortalRequestProcessor. En este caso
no se va a extender del ActionServlet de Struts sino que se hace de TilesRequestProcessor,
como ya se ha visto, el plugin Tiles para Struts se encarga de construir las ventanas a partir
de unas plantillas, por eso se deja que primero la peticion pase por el procesador de Tiles.
A continuacion el HotelPortalRequestProcessor tiene que llamar a la accion que se ha
especificado para gestionar la URL en concreto que le ha llegado. Ademas entre otras cosas
6.3. Capa del Controlador 96
a la accion que se va a invocar se le pasara, en caso de que hubiese alguno, el formulario
asociado a esa accion (ActionForm).
Si solo se quisiera la funcionalidad que se acaba de mencionar, no harıa falta crear un
procesador de acciones propio, valdrıa de igual forma el procesador de acciones de Tiles.
Pero como el sistema que se esta desarrollando es algo complejo, se necesita de algo mas.
En primer lugar se va a necesitar mantener las sesiones de los usuarios activas y cuando
un usuario haga una peticion, sera indispensable comprobar que este esta autenticado en
la aplicacion.
Ademas es tambien una buena idea que en este momento de la peticion, cuando aun
no se ha hecho nada importante, se comprobase si el usuario que esta autenticado en
la aplicacion tiene acceso a la accion que intenta llevar a cabo, y si no es ası no se le
permitira realizarla.
Implementar este tipo de controles no es tarea facil, por lo tanto se busca algun tipo de
patron que pueda ayudar a resolver esta cuestion. El patron que se usara sera el llamado
Chain of Responsability (Cadena de Responsabilidad) a traves de una cadena de filtros, por
los cuales pasara la peticion, si en el contexto en el que se esta se cumplen las condiciones
de todos los filtros entonces la peticion seguira adelante.
6.3.2. Patron Chain of Responsability
Este patron, Cadena de Responsabilidad, utiliza la delegacion como proceso basico para
realizar su cometido. En este caso se usa una cadena de filtros por la cual pasa la peticion
inicial. Esta cadena funciona de la siguiente forma.
La peticion entra en el primer filtro, este comprueba si se cumple alguna de las condi-
ciones preestablecidas para las que tiene una respuesta ya predefinida, es decir, que con
la informacion que tiene el filtro ya puede decir que accion se tiene que ejecutar luego. Si
ninguna de las condiciones del filtro se cumple, entonces este delega toda la responsabili-
6.3. Capa del Controlador 97
dad en el siguiente filtro de la cadena, el cual realiza el mismo proceso, y ası hasta que se
termine la cadena de filtros.
En la aplicacion de este proyecto se usan cuatro filtros a traves de los cuales deben pasar
todas las peticiones. Estos filtros son los que se muestran a continuacion, por orden de
aplicacion.
SessionPreProcessingFilter Este filtro lo primero que hace es comprobar si la sesion
del usuario aun esta activa, en caso afirmativo no hace nada. Si la sesion ha terminado
tiene que comprobar si el usuario tiene su nombre y contrasena guardadas en las cookies,
y si es ası reestablecerle la sesion. A diferencia de otros filtros, este filtro no interrumpe la
ejecucion de la cadena, simplemente sirve para que en todas las peticiones se este comple-
temente seguro de que la sesion esta activa.
AuthenticationPreProcessingFilter Este es uno de los filtros mas importantes ya
que es el encargado de verificar si el usuario que esta utilizando la aplicacion esta au-
tenticado o no. En caso de que lo este no hace nada y ejecuta el siguiente filtro de la
cadena, pero si el usuario no esta autenticado, tiene que comprobar si la accion que quiere
realizar requiere de autenticacion, de ser ası este filtro enviarıa al usuario a la pagina de
autenticacion.
AdminOnlyPreProcessingFilter El filtro AdminOnly proporciona una comprobacion
de acceso, al estar despues del filtro que comprueba si el usuario esta autenticado, ya se
sabe que el usuario esta autenticado, por lo que este filtro tiene la mision de chequear si la
accion que se desea realizar es una accion que solo puede realizar el administrador, de ser
ası el filtro debe comprobar que el usuario que solicita la accion es el administrador, una
vez realizada esta comprobacion, si el usuario es el administrador entonces se le permite
realizar la operacion, y si no lo es se le envıa a la pagina principal.
6.3. Capa del Controlador 98
RecepcionistOnlyPreProcessingFilter Este filtro proporciona otra comprobacion de
acceso, al estar despues del filtro que comprueba si el usuario esta autenticado, ya se sabe
que el usuario esta autenticado, por lo que este filtro tiene la mision de chequear si la
accion que se desea realizar es una accion que solo puede realizar el recepcionista, de ser
ası el filtro debe comprobar que el usuario que solicita la accion es el recepcionista, una
vez realizada esta comprobacion, si el usuario es el recepcionista entonces se le permite
realizar la operacion, y si no lo es se le envıa a la pagina principal.
6.3.3. Acciones
Una vez que la peticion ha pasado los filtros y estos han decidido que accion realizar,
entonces el ActionServlet de Struts debe llamar a la accion a la cual corresponda realizar
la operacion solicitada. En el fichero de configuracion de struts, struts-config.xml, es donde
se encuentran definidas las URLs y la accion que se debe ejecutar cuando se solicita dicha
URL.
Ademas de la accion que se tiene que ejecutar, en este fichero tambien se pueden definir
propiedades, para que luego puedan ser utilizadas por ejemplo por los filtros, y redirec-
ciones con nombre, de forma que cuando una accion se ejecute pueda usar esos nombres
para redirigir la accion a una pagina u otra accion. Por otro lado, se indican, de la misma
forma, los ActionForm correspondientes a los formularios que debe manejar y procesar
cada accion.
En este caso, para una mejor comprension del sistema, las acciones se han dividido
en paquetes segun lo que manejan, o para que se utilizan dichas acciones, como se pue-
de observar en la figura 6.6. Por ejemplo, hay paquetes donde estan todas las acciones
relacionadas con las reservas u otro donde estan las que tienen relacion con las ofertas,
etc.
6.3. Capa del Controlador 99
Ademas para facilitar el manejo de diversas operaciones que pueden tomar mas de una
accion para realizarse, se vio la nececidad de crear unas clases de apoyo a las que se le dio
el nombre de XXXManager.
http.controller
actions
offers
reservations
rooms
session
frontcontroller
clients
misc
offers
payment
reservations
rooms
users
Figura 6.6: Paquetes - Distribucion de Acciones de Struts
A continuacion se muestra en la figura 6.7 el diagrama de como se organiza realmente
el patron Front Controller junto con el de Chain of Responsability en el desarrollo final
de este proyecto.
6.3.4. Clases de Utilidad y Soporte a Acciones
Para dar soporte a la estructura del patron Front Controller se definen clases abstractas
que tienen que ser luego extendidas por las acciones y los formularios, pero ademas de poder
agrupar las acciones todas bajo una misma clase padre, esta clase abstracta tambien sirve
para realizar operaciones comunes a todas las acciones, como el procesamiento de algunas
excepciones, etc.
6.3. Capa del Controlador 100
org::apache::struts::tiles::TilesRequestProcessor
org::apache::struts::action::Actionorg::apache::struts::action::ActionForm
http::util::struts::action::DefaultAction
+execute(... : ...) : ActionForward
#doExecute(... : ...)#doOnInternalErrorException(... : ...)
http::util::struts::action::DefaultActionForm
#getLocale(request : HttpServletRequest) : Locale
-serialVersionUID : long
http::controller::frontcontroller::HotelPortalRequestProcessor
<<create>> +HotelPortalRequestProcessor()#processActionPerform(... : ...) : ActionForward
~firstPreProcessingFilter : PreProcessingFilter
1
0..*
<<call>>
http::controller::frontcontroller::PreProcessingFilter
<<create>> +PreProcessingFilter(nextFilter : PreProcessingFilter)+process(... : ...) : ActionForward
#doProcess(... : ...) : ActionForward#doOnInternalErrorException(... : ...) : ActionForward
-nextFilter : PreProcessingFilter
<<create>>
http::controller::frontcontroller::SessionPreProcessingFilter
<<create>> +SessionPreProcessingFilter(... : ...)#doProcess(... : ...) : ActionForward
http::controller::frontcontroller::AuthenticationPreProcessingFilter
<<create>> +AuthenticationPreProcessingFilter(... : ...)#doProcess(... : ...) : ActionForward
http::controller::frontcontroller::AdminOnlyPreProcessingFilter
<<create>> +AdminOnlyPreProcessingFilter(... : ...)#doProcess(... : ...) : ActionForward
http::controller::frontcontroller::ReceptionistOnlyPreProcessingFilter
<<create>> +ReceptionistOnlyPreProcessingFilter(... : ...)#doProcess(... : ...) : ActionForward
http::view::actionforms::FindClientsForm
http::view::actionforms::FindIncidentsForm
http::view::actionforms::FindOffersForm
http::view::actionforms::FindReservationsForm
http::view::actionforms::FindRoomsForm
http::view::actionforms::IncidentForm
http::view::actionforms::LoginForm http::view::actionforms::OfferForm
http::view::actionforms::OfferTypeFormhttp::view::actionforms::RoomForm
http::view::actionforms::RoomReservationForm
http::view::actionforms::RoomTypeForm
http::view::actionforms::UserProfileForm
Todas las acciones que extienden esta clase se encuentran en los paqueteshttp.controller.actions.clients, misc, offers,payment, reservations, rooms y users.
Pero no se incluyen aquí porque son una gran cantidad, además todas estas acciones hacen uso de los actionFormsque se incluyeron en este diagrama
Figura 6.7: Diagrama Aplicacion de Front Controller
Las clases de utilidad que se han definido son: DefaultAction, de la cual derivan luego
todas las acciones, y DefaultFormAction que extienden luego todos los formularios. Estas
clases se pueden ver claramente en el diagrama de la figura 6.7 que se acaba de mostrar.
Para dar soporte a algunas acciones, no basta con los metodos que proporcionan las
fachadas del modelo, sino que hacen falta algunas clases de soporte que ayuden a procesar
algunas operaciones. Esta necesidad se hace visible cuando aparece la necesidad de man-
tener alguna informacion en cache a la espera de algunos otros datos para luego poder
enviar todo junto al metodo correspondiente de la fachada del modelo. Estas clases de
soporte son las siguientes:
6.3. Capa del Controlador 101
SessionManager Esta clase proporciona diferentes metodos que ayudan a gestionar las
sesiones de los clientes, de esta forma si por ejemplo un cliente se autentica en el sistema
o modifica sus datos personales, esta clase mantiene actualizada su sesion y si es necesario
tambien actualiza las cookies de su navegador. Ademas en ocasiones sera util por ejemplo
cuando se trata del recepcionista, el cual tiene que poder realizar acciones en nombre
del cliente que se lo solicita, en estos casos la clase SessionManager mantendra en todo
momento quien es el usuario real del sistema (el recepcionista) y quien es el usuario efectivo
(el cliente).
Esta clase sera en la que se apoyen los filtros de procesamiento a la hora de comprobar
si un usuario esta autenticado, si es el administrador o si es el recepcionista.
ReservationsManager La forma en la que se procesan las reservas hacen obligatorio
el guardar algunos datos a la espera de la confirmacion, de que se desea hacer, que estos
sean persistentes, en cuyo caso hay que pasar todos los datos a la fachada de gestion de
reservas o a la de gestion de reservas web para que estas se encarguen de su procesamiento
final.
Por ejemplo, cuando se realiza una nueva reserva, se le va preguntando al cliente que
introduzca los datos para reservar una habitacion, lo que se llama lınea de reserva en la
aplicacion, y una reserva contiene una o varias de estas lıneas, por lo que se ira preguntando
al cliente de hacer mas lıneas de reserva o si desea guardarlas. Al terminar se le pasan a
la fachada correspondiente todas las lıneas para que cree la nueva reserva. El proceso de
modificacion de una reserva es algo parecido, al cliente se le permite borrar las lıneas de
reserva que quiera y anadir otras nuevas, al terminar el cliente debe elegir si desea guardar
los cambios o no, en caso afirmativo todos los cambios se guardan juntos llamando a la
accion correspondiente de la fachada y ahorrando ası multiples accesos a la base de datos.
OffersManager En el caso de las ofertas, cuando se crea una nueva oferta o se modifica
no hace falta realizarlo en varios pasos, pero sı hay que dar la opcion de que cuando se
6.4. Arquitectura del Modelo 102
desea crear una oferta se pueda crear en ese instante un nuevo tipo de oferta. La creacion
de este nuevo tipo de oferta la hay que mantener en la cache a la espera de la confirmacion
de que se quiere crear la oferta, en caso afirmativo se crearan simultaneamente el nuevo
tipo y la nueva oferta, pasando todos los datos conjuntamente a la fachada del modelo.
RoomsManager Ası como con las ofertas, cuando se crea una nueva habitacion o se
modifican sus datos no hace falta realizarlo en varios pasos, pero sı hay que dar la opcion
de que cuando se desea crear una habitacion se pueda crear en ese instante un nuevo
tipo de habitacion. La creacion de este nuevo tipo la hay que mantener en la cache a
la espera de la confirmacion de que se quiere crear la habitacion, en caso afirmativo se
crearan simultaneamente el nuevo tipo y la nueva habitacion, pasando todos los datos
conjuntamente a la fachada del modelo.
6.4. Arquitectura del Modelo
Como ya se ha mencionado, el modelo es la parte de la aplicacion que implementa la
logica de negocio, es decir, es donde se decide como se llevaran a cabo todos los casos de
uso estudiados con anterioriad, que el sistema debe realizar.
Se comienza construyendo la base de datos, para que esta este construıda correctamente
antes se disena la misma en base a diagramas, donde se incluyen las relaciones que hay
entre las entidades que formaran la base de datos. Luego atendiendo a una serie de reglas
preestablecidas, todas estas entidades y relaciones se pasan a un esquema denominado
modelo relacional, en el cual se pueden ver con claridad las distintas tablas que habra que
crear en la base de datos relacional.
Para desarrollar con mayor facilidad este proyecto, se ha dividido la aplicacion en dife-
rentes subsistemas, cada uno de ellos se encarga de un subconjunto de los casos de uso. Se
pretende que todos estos subsistemas sean lo mas independientes posible unos de otros,
y ademas se implementaran de forma que se pueda cambiar facilmente la base de datos
6.4. Arquitectura del Modelo 103
sobre la que se guarda la informacion, gracias al patron DAO usado para acceder a los
datos.
Para acceder a los distindos subsistemas, estos ofrecen una fachada con los metodos que
ofrecen, lo que permite cambiar la implentacion de dichos metodos cuando se desee sin
alterar las capas superiores de la aplicacion.
La arquitectura de los distintos sistemas es la misma para todos, de forma que en
primer lugar se hara una explicacion de los distintos patrones y arquitecturas usados, y
a continuacion se detallaran los diferentes subsistemas para comprobar como se utilizan
estos patrones.
6.4. Arquitectura del Modelo 104
6.4.1. Persistencia de los Datos
En este apartado se vera como se consigue desarrollar la base de datos en la que se
guardaran todos los datos de la aplicacion, a partir de las especificaciones iniciales.
En realidad este proyecto necesitara dos bases de datos distintas, una para guardar a los
usuarios, las habitaciones, las reservas y las facturas, y otra para guardar todo lo relacio-
nado con las ofertas. Gracias a esta separacion, si se desea modificar el esquema de gestion
de ofertas, solo se modificara una parte del sistema, que es totalmente independiente del
resto de la aplicacion.
A continuacion se detallara el proceso seguido para el diseno de cada una de las bases
de datos.
6.4.1.1. Base de Datos General
En esta base de datos se necesitara guardar a los distintos usuarios del sistema, estos
usuarios se identificaran mediante el DNI o el numero de Pasaporte, y de ellos se alma-
cenaran los siguientes datos: nombre, apellidos, fecha de nacimiento, direccion, paıs, dos
numeros de telefono y la direccion de correo electronico. Ademas se guardaran tambien el
nombre de usuario dentro del sistema y su contrasena cifrada, por otro lado, de un usuario
se tendra que poder saber si ya es cliente del hotel y si ha confirmado su identidad.
Por otro lado tambien se necesitan registrar las habitaciones que hay en el hotel, estas
se identificaran por su numero, y de ellas se mantendran almacenados el piso en el que
se encuentra y el posible precio extra que pueda tener. Cada habitacion sera de un solo
tipo, aunque en el futuro puede que se necesite que pueda ser de varios tipos distintos,
donde cada tipo se identifica por un numero generado y es el que define el precio base
de la habitacion, ademas se deben de almacenar la descripcion del tipo y el numero de
personas para las que se destina.
6.4. Arquitectura del Modelo 105
Como en una habitacion puede que ocurra algun tipo de percance, tambien se debe dar
soporte para registrar las distintas incidencias que puedan tener lugar en cada habitacion,
cada una de ellas se identificara por el numero de habitacion y por un identificador secun-
dario generado dinamicamente, de cada incidencia habra que mantener constancia de la
descripcion de la misma, el tipo (si es grave, leve, etc) y la fecha en la que se registra.
Para terminar, y como el cometido principal de la aplicacion es poder realizar reservas
de habitaciones, hay que dar soporte a esta opcion. Las reservas se identificaran por un
codigo de reserva y podran ser temporales o no, ademas habra que registrar la fecha en
la que se realiza. Luego una reserva podra contener una o varias lıneas de reserva cada
cual con relacion a una habitacion, por lo que estas lıneas se identificaran mediante el
numero de habitacion para la que se destinan y la fecha de llegada que se debe almacenar
en cada una, tambien se guardaran la fecha de salida, el total parcial que cuesta esa
estancia y el descuento ofrecido al aplicar las ofertas correspondientes. El total parcial
se almacena porque ademas de las reservas, las lıneas de reserva tambien estan presentes
en las facturas, por lo que una factura podra estar formada de igual forma por una o
varias lıneas de reserva. La factura se asociara a una persona, que sera quien debe pagarla
y se identificara por un numero de factura generado. En las facturas debe constar si ya
esta pagada, si aun esta como borrador, la fecha en la que se realiza el pago, el total que
forma la factura, el total parcial antes de aplicar las ofertas y las ofertas aplicadas.
El diseno se debe realizar para que si en un futuro se necesita, se pueda anadir por
ejemplo servicios extra, etc, y que estos puedan incluirse en la misma factura.
Despues de definir todo lo que se necesita almacenar, se procede a realizar el modelo
Entidad-Relacion, que es un diagrama mediante el cual se muestran los requisitos expre-
sados en los parrafos anteriores de forma gafica a traves de entidades, que son las ’cosas’
u ’objetos’ en el mundo real que se distinguen de todos los demas objetos, y relaciones,
las encargadas de mostrar como estan ligadas las distintas entidades unas con otras. Cada
entidad tendra una serie de propiedades especıficas que la describen, a estas se les llama
’atributos’ y si se puede diferenciar unıvocamente una instancia de una entidad de otra de
6.4. Arquitectura del Modelo 106
la misma entidad a traves de uno o varios de los atributos, estos forman la denominada
’clave primaria’. En la pagina siguiente en la figura 6.8 se puede ver como queda el diseno
de esta base de datos a traves de un diagrama Entidad-Relacion.
6.4.A
rquitectu
radel
Modelo
107Figura 6.8: Diagrama Entidad Relacion - General
6.4. Arquitectura del Modelo 108
Una vez visto el diseno de la base de datos se procede a realizar el Modelo Relacional
de esta. El modelo relacional es un modelo de datos es una coleccion de herramientas
conceptuales para describir los datos, sus relaciones y restricciones, para esto el modelo
relacional cuenta con: una estructura para almacenar los datos y unas restricciones. La
estructura basica y unica para el almacenamiento de los datos es la ’relacion’. Ası, la base
de datos se representa como una coleccion de relaciones.
El modelo relacional de esta primera base de datos se puede ver representado en la figura
6.9
Figura 6.9: Modelo Relacional - General
6.4. Arquitectura del Modelo 109
Cuando se tiene el modelo relacional ya se pueden diferenciar las tablas que habra que
crear en la base de datos con sus claves primarias identificadas y tambien las claves
foraneas.
Para este proyecto se usara como base de datos MySQL, por defecto el motor de esta
base de datos es MyISAM. Este motor es rapido y eficiente. En un principio se penso en
utilizarlo, pero viendo que para realizar la persistencia de los datos de la aplicacion se
necesitan realizar transacciones, se opto por elegir un motor de base de datos que las
soportara. El motor elegido fue InnoDB que ademas de dar soporte para las transacciones
tambien soporta claves foraneas.
Finalmente y gracias al modelo relacional realizado ya se podra implementar la base de
datos, esta implementacion se muestra en el capıtulo 7 en la seccion 7.2.1.
6.4.1.2. Base de Datos de Ofertas
Esta base de datos se crea con motivo de dar soporte al que sera el sistema que gestione
las ofertas y sus combinaciones. Para que este sistema funcione correcta y eficientemente
es necesario que el diseno de la base de datos sea lo mas flexible posible y que cumpla
todos los requisitos del sistema.
Este sistema debe permitir definir ofertas de distintos tipos ya que de cada tipo, lue-
go, solo se podra aplicar una de ellas. Pero esto no es todo, ademas se podran definir
incompatibilidades entre ofertas, ası luego unicamente se aplicaran aquellas ofertas que
sean todas compatibles entre sı. Y por otro lado habra que indicar a que tipo de ventas
se podra aplicar la oferta (reservas, servicios extra, etc) y tambien se tendra que poder
definir una regla por la cual se restrinja a quien se le puede aplicar la oferta y a quien no.
Las ofertas se identificaran por un numero generado en el momento en la que se crean.
Cada oferta debera mantener los siguientes datos: Descripcion de la oferta, descuento que
se ofrece con esa oferta, la fecha a partir de la cual la oferta se comienza a aplicar y cuando
se termina de hacerlo, indicar si es un borrador y si esta desactivada. Ademas almacenara la
6.4. Arquitectura del Modelo 110
regla que se debe de cumplir para que se pueda aplicar, esta estara escrita en un lenguaje
de reglas que se definira posteriormente. Ademas cada oferta tendra un tipo de oferta,
estos tipos deberan guardar una descripcion y un nombre, y se identificaran mediante un
numero generado automaticamente. Luego estas ofertas podran ser incompatibles entre sı.
Cada oferta a su vez podra ser aplicada a una serie de productos, estas aplicaciones
se resolveran mediante un nombre del tipo de producto al que se aplicaran y la cantidad
mınima necesaria para que se aplique. En la figura 6.10 se puede ver como queda el diseno
de esta base de datos a traves de un diagrama Entidad-Relacion.
Figura 6.10: Diagrama Entidad Relacion - Ofertas
6.4. Arquitectura del Modelo 111
Una vez terminado el diseno de esta segunda base de datos se pasa a realizar el modelo
relacional, que se puede ver en la figura 6.11.
Figura 6.11: Modelo Relacional - Ofertas
A partir del Modelo Relacional de la figura 6.11 y optimizando las tuplas generadas por
este, ya se podran crear las tablas en la base de datos. La implementacion real de esta
base de datos se vera de forma mas detallada en el capıtulo 7 en la seccion 7.2.2.
6.4.2. Patrones Utilizados en el Modelo
6.4.2.1. Value Object (VO)
Este patron se utiliza cuando se necesita representar un conjunto de atributos proce-
dentes de uno o varios objetos del dominio, ademas, normalmente, representa en forma
de objeto del dominio a una entidad completa representada en la base de datos. Por esto
ultimo el patron VO se utiliza conjuntamente con el patron DAO que se explicara en la
siguiente seccion y que es el encargado de acceder a la base de datos y hacer persistentes
los atributos de los VO.
6.4. Arquitectura del Modelo 112
En la figura 6.12 se muestra la estructura basica de este patron.
<<interface>>java.io.Serializable
VO
+metodos get/set()
-atributos : ...
<<realize>>
<<interface>>DAO
<<call>>
Figura 6.12: Diagrama de Value Object
La clase VO de la figura es la que representa el objeto y ofrece metodos de lectura y
escritura para sus atributos. Este objeto debe implementar la interfaz Serializable ya que
esta, aunque simplemente es una interfaz marcadora, luego este objeto se podra transmitir
por red y reconstruir con facilidad gracias a un API que proporciona Java para convertir
automaticamente el estado de una instancia en un vector de bytes y viceversa.
Los objetos VO son utilizados tanto por los DAO para devolver valores persistentes
o recoger valores para actualizar o crear, como para las fachadas del subsistema que lo
necesite. En esta aplicacion se usara la notacion xxxVO para estos objetos
6.4.2.2. Data Access Object (DAO)
El patron DAO es el encargado de abstraer el acceso a los datos. Esta arquitectura
ofrecera al programador una interfaz comun para acceder a la informacion, sin importar
ni como ni donde estan almacenados los datos. Ademas, ası se da la posibilidad de cambiar
la implementacion de acceso a la informacion cuando se desee. Para posibilitar este cambio,
se usa el patron Factory (Factorıa) que consta de una clase encargada de devolver un objeto
del tipo solicitado. Para crear el nuevo objeto esta clase debe de saber el nombre de la clase
del mismo, y para ello se ayuda de una utilidad que es ConfigurationParametersManager,
6.4. Arquitectura del Modelo 113
una clase que a partir de una cadena devuelve el nombre de recurso deseado despues de
leerlo en un fichero de configuracion.
En la siguiente figura (6.13) se muestra como se estructuran las clases que dan forma
a este patron, y donde se incluye tambien el patron VO para que se vea claramente la
relacion de uno con otro.
DAOFactory
-DAOFactory()+getDAO() : DAO
-daoClass : Class
ConfigurationParametersManager
<<call>>
DAO
+create(c : Connection,vo : VO) : VO+exists(c : Connection,id : Integer) : boolean+find(c : Connection,id : Integer) : VO+findBy(c : Connection,id : Integer,start : Integer,count : Integer) : List+update(c : Connection,vo : VO)+remove(c : Connection,id : Integer)
<<instantiate>>
VO
+metodos get/set()
-atributos : ...<<call>>
Figura 6.13: Diagrama de Data Access Object
Pero esta estructura aun se puede mejorar, como en este caso el volumen de datos no
sera pequeno, la informacion se almacenara en una base de datos relacional. Teoricamente
todas las bases de datos relacionales comprenden correctamente el lenguaje de consultas
SQL, pero en la practica esto no es ası, aunque SQL es un estandar cada fabricante tiene
sus pequenas variantes, lo que puede complicar un poco mas el diseno, ya que las sentencias
SQL que se escriban para hacer consultas sobre la base de datos variaran dependiendo de la
base de datos que se utilice. Las sencencias que sufren mayores variaciones entre fabricantes
son sobre todo las de insercion de datos, ya que para las sentencias de consultas simples
se utiliza el mismo SQL en todas las bases de datos.
Con el diseno anterior, si se quisiera cambiar de base de datos tendrıamos que modificar
la clase DAO, aunque solo se tuviese que cambiar la sentencia de insercion. Por este
motivo en el diseno utilizado se opto por separar la interfaz de acceso a los datos DAO
y su implementacion, de forma que se pudiese tener una implementacion abstracta de los
6.4. Arquitectura del Modelo 114
metodos comunes en todas las bases de datos, y redefinir exclusivamente aquellos que fuese
necesario, y en la figura 6.14 se puede ver como se organizan estas nuevas clases.
DAOFactory
-DAOFactory()+getDAO() : DAO
-daoClass : ClassConfigurationParametersManager
<<call>>
<<interface>>DAO
+create(c : Connection,vo : VO) : VO+exists(c : Connection,id : Long) : boolean+find(c : Connection,id : Long) : VO+findBy(c : Connection,id : Long,start : Integer,count : Integer) : List+update(c : Connection,vo : VO)+remove(c : Connection,id : Long)
<<instantiate>>
AbstractDAO
<<realize>>
SpecificDAO
VO
+metodos get/set()
-atributos : ...
Figura 6.14: Diagrama de Data Access Object Utilizado
Como se puede observar, todos los metodos necesitan recibir la conexion, esto se hace
para poder agrupar luego varias operaciones en una transaccion cuando sea necesario. La
clase DAO define una interfaz para insertar, borrar, buscar y actualizar objetos VO. Es-
te es un ejemplo de la aplicacion de otro patron simple, el Adapter (Adaptador), donde
DAOFactory permite obeter una instancia del adaptador que proceda para la aplicacion.
Gracias a este diseno, como ya se ha mencionado, es posible hacer ’plug-n-play’ de adap-
tadores sin tener que recompilar la aplicacion cuando se cambia de base de datos. En el
desarrollo del sistema se usara la notacion xxxDAO, xxx representara el nombre de la
entidad de la base de datos que corresponde al DAO en cuestion.
6.4. Arquitectura del Modelo 115
6.4.2.3. Session Facade y Business Delegate
Estos dos patrones forman una capa del modelo que utiliza los DAOs para acceder a los
datos y ofrece unos metodos a las capas superiores, vista y controlador. Estas arquitecturas
se utilizan fundamentalmente para proporcionar una capa mas sencilla que de soporte para
implementar los casos de uso definidos, ocultando a su vez la tecnologıa utilizada.
El patron Session Facade es una aplicacion del patron Facade (Fachada) gracias al cual el
subsistema desarrollado resulta mas facil de utilizar por parte de capas superiores y reduce
el acoplamiento, de forma que la modificacion del subsistema no afecta a las otras capas
que lo utilicen. En este caso el Session Facade representa control y flujo, no persistencia,
de la cual ya se encargan los DAOs, ademas una Session Facade representa un conjunto de
casos de uso relacionados entre sı, y cada uno de estos conjuntos formaran un subsistema
de la aplicacion. En este caso se desarrollaran los siguientes Session Facades para imple-
mentar todos los subsistemas: ClientesFacade, FacturasWebFacade, HabitacionesFacade,
ReservasWebFacade, UsuariosWebFacade, OfertaFacade y TipoOfertaFacade.
Conjuntamente con el Session Facade se utiliza el patron Business Delegate, este sirve
para ocultar las tecnologıas utilizadas en el modelo, normalemente un objeto Business
Delegate oculta a un Session Facade, pero en este caso seran el mismo, y aunque no
sera necesario dar la opcion de cambiar la tecnologıa usada, por ejemplo utilizar EJB, si
en el futuro se desea hacer este cambio se hara de forma sencilla. Como en el sistema solo
habra un Business Delegate por subsistema se denotara por GeneralXxxFacade.
Para dar soporte a las consultas a la base de datos, hay que recordar que los DAO
necesitaban que se les proveera de una conexion para ejecutar las consultas, se tiene una
clase de utilidad, en este caso SimpleDataSource, que valdra para crear una conexion nueva
a la base de datos y devolverla.
Tambien hay que dar solucion a unos problemas. El primero que se encuentra es que
un Session Facade puede tener mas de 10 operaciones, lo que desembocarıa en una clase
muy grande. Para solucionar este primer contratiempo se hara que cada operacion se
6.4. Arquitectura del Modelo 116
implemente en una clase, se denominaran clases Action, con esto lo que se consigue es que el
Session Facade delegue la implementacion de cada operacion en la Action correspondiente.
La organizacion de las distintas clases de este conjunto de patrones se puede ver en la figura
6.15
<<interface>>XxxFacade
GeneralXxxFacade
+GeneralXxxFacade()
-dataSource : DataSource
<<realize>>
Actions
<<call>>
PlainActionProcessor
<<call>>
SimpleDataSource
+getConnection() : Connection
<<call>>
Figura 6.15: Diagrama de Session Facade y Business Delegate
Como segundo problema esta la transaccionalidad necesaria en muchas de las acciones
aunque otras no lo necesiten. Las acciones transaccionales deberan solicitar una conexion
al inicio de la operacion y cerrarla al terminar. La resolucion de este ultimo problema se
logra utilizando el procesador de acciones, en este caso PlainActionProcessor, lo unico que
hay que conseguir es que teniendo dos metodos, uno para procesar las acciones transac-
cionales y otro para procesar las que no lo son, las acciones transaccionales las procese
automaticamente el metodo que corresponde y lo mismo para las no transaccionales.
El procesador de acciones que se ve en la figura 6.15 necesita que las acciones implemen-
ten una interfaz PlainAction, para desta forma identificarlas y poder llamar a su metodo
execute(). Esta opcion, es la que se aprovecha para diferenciar las acciones transacciona-
les, se crean dos nuevas interfaces que heredan de PlainAction: TransactionalPlainAction
y NonTransactionalPlainAction. Ası las acciones que implementen cualquiera de estas dos
nuevas interfaces estaran implementando tambien la interfaz PlainAction, como bien se
puede ver en la figura 6.16. Las interfaces que se crean se denominan Markers (Marcado-
6.4. Arquitectura del Modelo 117
res) ya que no tienen la firma de ningun metodo y simplemente sirven para diferenciar
unas clases de otras, en este caso las que implementan una transaccion y las que no.
PlainActionProcessor
-PlainActionProcessor()+process(dataSource : DataSource,action : NonTransactionalPlainAction) : Object+process(dataSource : DataSource,action : TransactionalPlainAction) : Object
<<interface>>PlainAction
+execute(c : Connection) : Object
<<call>>
<<interface>>NonTransactionalPlainAction
<<interface>>TransactionalPlainAction
Figura 6.16: Diagrama del Procesador de Acciones
6.4.3. Capa de Acceso a la Base de Datos
Para acceder a la informacion guardada en la base de datos y modificarla si fuera necesa-
rio, Java proporciona un API JDBC para realizarlo. Ademas en este proyecto se utilizara el
patron DAO explicado en la seccion 6.4.2.2. Para simplificar el trabajo, se construira un
objeto DAO por cada entidad y relacion de la base de datos, esto es, un DAO por cada
tabla de la base de datos. Los objetos DAO tendran metodos de creacion de nuevos valores
en la base de datos, eliminacion, modificacion y consulta de datos segun algunos parame-
tros que se proporcionen. Aunque se implementaran todos los metodos que se puedan
necesitar, luego no se usaran todos, pero los objetos DAO ya quedarıan preparados por si
en el futuro se necesitasen realizar otras consultas. Los objetos DAO utilizan los objetos
VO relacionados con ellos, por lo que tambien se creara un objeto VO por cada una de
las tablas que hay en la base de datos. La estructura de estos paquetes se puede observar
en las figuras 6.17 y 6.18
6.4. Arquitectura del Modelo 118
Figura 6.17: Estructura de los paquetes DAO y VO
xxx
DAO
VO
xxxVO
SQLxxxDAOFactory
AbstractSQLxxxDAO
<<interface>>SQLxxxDAO
<<realize>>
<<instantiate>>
MySQLxxxDAO
Figura 6.18: Diagrama General de los DAO
Y a continuacion se muestran los diagramas de todos los DAOs de esta aplicacion,
clasificados segun el paquete en el que se encuentran. La estructura es la misma para
todos, pero los metodos que ofrecen no lo son. Las clases MySQLxxDAO se utilizan para
redefinir el metodo de creacion de datos, ya que si luego se desea cambiar de gestor de base
de datos, las sentencias de consulta en SQL normalmente son iguales en todos los gestores,
pero las de insercion no, sobre todo a la hora de generar las claves. En caso de que esto
suceda, simplemente habrıa que cambiar la clase MySQLxxxDAO por la que corresponda
para el nuevo gestor de base de datos.
6.4. Arquitectura del Modelo 119
6.4.3.1. Paquete ’persona’
<<interface>>SQLPersonaDAO
+addPersona(connection : Connection,personaVO : PersonaVO) : PersonaVO+removePersona(connection : Connection,dniPas : String) : void+existsPersona(connection : Connection,dniPas : String) : boolean+existsPersona(connection : Connection,userName : String,userPassword : String) : boolean+existsUserName(connection : Connection,userName : String) : boolean+findPersona(connection : Connection,dniPas : String) : PersonaVO+findPersona(connection : Connection,userName : String,userPassword : String) : PersonaVO+getAll(connection : Connection,startIndex : int,count : int) : Collection+getByPais(connection : Connection,pais : String,startIndex : int,count : int) : Collection+getByCliente(connection : Connection,cliente : boolean,startIndex : int,count : int) : Collection+getByUsuarioConf(connection : Connection,usuarioConf : boolean,startIndex : int,count : int) : Collection+GetByNameSurnameAndDniPas(connection : Connection,name : String,search1 : boolean,surname : String,search2 : boolean,dniPas : String,search3 : boolean,startIndex : int,count : int) : Collection+updateEMail(connection : Connection,dniPas : String,eMail : String) : void+updateUsuarioConf(connection : Connection,dniPas : String,usuarioConf : boolean) : void+updateNomUsuario(connection : Connection,dniPas : String,newNomUsuario : String) : void+updatePassword(connection : Connection,dniPas : String,newPassword : String) : void+updateNombre(connection : Connection,dniPas : String,newNombre : String) : void+updateApellidos(connection : Connection,dniPas : String,newApellidos : String) : void+updateDirCalle(connection : Connection,dniPas : String,newDirCalle : String) : void+updatePais(connection : Connection,dniPas : String,newPais : String) : void+updateCliente(connection : Connection,dniPas : String,cliente : boolean) : void+updateTelefono1(connection : Connection,dniPas : String,newTelefono : String) : void+updateTelefono2(connection : Connection,dniPas : String,newTelefono : String) : void
AbstractSQLPersonaDAO
+addPersona(connection : Connection,personaVO : PersonaVO) : PersonaVO+removePersona(connection : Connection,dniPas : String) : void+existsPersona(connection : Connection,dniPas : String) : boolean+existsUserName(connection : Connection,userName : String) : boolean+existsPersona(connection : Connection,userName : String,userPassword : String) : boolean+findPersona(connection : Connection,dniPas : String) : PersonaVO+findPersona(connection : Connection,userName : String,userPassword : String) : PersonaVO+getAll(connection : Connection,startIndex : int,count : int) : Collection+getByPais(connection : Connection,pais : String,startIndex : int,count : int) : Collection+getByCliente(connection : Connection,cliente : boolean,startIndex : int,count : int) : Collection+getByUsuarioConf(connection : Connection,usuarioConf : boolean,startIndex : int,count : int) : Collection+GetByNameSurnameAndDniPas(connection : Connection,name : String,search1 : boolean,surname : String,search2 : boolean,dniPas : String,search3 : boolean,startIndex : int,count : int) : Collection+updateEMail(connection : Connection,dniPas : String,eMail : String) : void+updateUsuarioConf(connection : Connection,dniPas : String,usuarioConf : boolean) : void+updateNomUsuario(connection : Connection,dniPas : String,newNomUsuario : String) : void+updatePassword(connection : Connection,dniPas : String,newPassword : String) : void+updateNombre(connection : Connection,dniPas : String,newNombre : String) : void+updateApellidos(connection : Connection,dniPas : String,newApellidos : String) : void+updateDirCalle(connection : Connection,dniPas : String,newDirCalle : String) : void+updatePais(connection : Connection,dniPas : String,newPais : String) : void+updateCliente(connection : Connection,dniPas : String,cliente : boolean) : void+updateTelefono1(connection : Connection,dniPas : String,newTelefono : String) : void+updateTelefono2(connection : Connection,dniPas : String,newTelefono : String) : void
<<realize>>
MySQLPersonaDAO
+addPersona(connection : Connection,personaVO : PersonaVO) : PersonaVO
SQLPersonaDAOFactory
<<create>> -SQLPersonaDAOFactory()-getDAOClass() : Class+getDAO() : SQLPersonaDAO
-DAO_CLASS_NAME_PARAMETER : String-daoClass : Class
hotel::modelo::persona::vo::PersonaVO
-serialVersionUID : long-dniPas : String-eMail : String-usuarioConf : boolean-nomUsuario : String-password : String-nombre : String-apellidos : String-dirCalle : String-pais : String-cliente : boolean-telefono1 : String-telefono2 : String
<<call>>
<<call>>
Figura 6.19: Diagrama del Paquete ’persona’
6.4. Arquitectura del Modelo 120
6.4.3.2. Paquete ’tipohabitacion’
SQLTipoHabitacionDAOFactory
<<create>> -SQLTipoHabitacionDAOFactory()-getDAOClass() : Class+getDAO() : SQLTipoHabitacionDAO
-DAO_CLASS_NAME_PARAMETER : String-daoClass : Class
<<interface>>SQLTipoHabitacionDAO
+addTipoHabitacion(connection : Connection,tipoHabitacionVO : TipoHabitacionVO) : TipoHabitacionVO+removeTipoHabitacion(connection : Connection,idTipo : Long) : void+existsTipoHabitacion(connection : Connection,idTipo : Long) : boolean+findTipoHabitacion(connection : Connection,idTipo : Long) : TipoHabitacionVO+getAll(connection : Connection,startIndex : int,count : int) : Collection+updatePrecioBase(connection : Connection,idTipo : Long,newPrecioBase : double) : void+updateDescripcion(connection : Connection,idTipo : Long,newDescripcion : String) : void+updateNumPersonas(connection : Connection,idTipo : Long,newNumPersonas : Long) : void
AbstractSQLTipoHabitacionDAO
+addTipoHabitacion(connection : Connection,tipoHabitacionVO : TipoHabitacionVO) : TipoHabitacionVO+removeTipoHabitacion(connection : Connection,idTipo : Long) : void+existsTipoHabitacion(connection : Connection,idTipo : Long) : boolean+findTipoHabitacion(connection : Connection,idTipo : Long) : TipoHabitacionVO+getAll(connection : Connection,startIndex : int,count : int) : Collection+updatePrecioBase(connection : Connection,idTipo : Long,newPrecioBase : double) : void+updateDescripcion(connection : Connection,idTipo : Long,newDescripcion : String) : void+updateNumPersonas(connection : Connection,idTipo : Long,newNumPersonas : Long) : void
<<realize>>
MySQLTipoHabitacionDAO
+addTipoHabitacion(connection : Connection,tipoHabitacionVO : TipoHabitacionVO) : TipoHabitacionVO
TipoHabitacionVO
-serialVersionUID : long-idTipo : Long-descripcion : String-numPersonas : Long-precioBase : double
Figura 6.20: Diagrama del Paquete ’tipohabitacion’
6.4. Arquitectura del Modelo 121
6.4.3.3. Paquete ’habitacion’
SQLHabitacionDAOFactory
<<create>> -SQLHabitacionDAOFactory()-getDAOClass() : Class+getDAO() : SQLHabitacionDAO
-DAO_CLASS_NAME_PARAMETER : String-daoClass : Class
<<interface>>SQLHabitacionDAO
+addHabitacion(connection : Connection,habitacionVO : HabitacionVO) : HabitacionVO+removeHabitacion(connection : Connection,numero : Long) : void+existsHabitacion(connection : Connection,numero : Long) : boolean+findHabitacion(connection : Connection,numero : Long) : HabitacionVO+getAll(connection : Connection,startIndex : int,count : int) : Collection+getByPiso(connection : Connection,piso : Long,startIndex : int,count : int) : Collection+updatePrecioExtra(connection : Connection,numero : Long,newPrecioExtra : double) : void+updatePiso(connection : Connection,numero : Long,newPiso : double) : void
AbstractSQLHabitacionDAO
+addHabitacion(connection : Connection,habitacionVO : HabitacionVO) : HabitacionVO+existsHabitacion(connection : Connection,numero : Long) : boolean+findHabitacion(connection : Connection,numero : Long) : HabitacionVO+getAll(connection : Connection,startIndex : int,count : int) : Collection+getByPiso(connection : Connection,piso : Long,startIndex : int,count : int) : Collection+removeHabitacion(connection : Connection,numero : Long) : void+updatePrecioExtra(connection : Connection,numero : Long,newPrecioExtra : double) : void+updatePiso(connection : Connection,numero : Long,newPiso : double) : void
<<realize>>
MySQLHabitacionDAO
+addHabitacion(connection : Connection,habitacionVO : HabitacionVO) : HabitacionVO
HabitacionVO
-serialVersionUID : long-numero : Long-piso : Long-precioExtra : Double
Figura 6.21: Diagrama del Paquete ’habitacion’
6.4. Arquitectura del Modelo 122
6.4.3.4. Paquete ’esdetipo’
SQLEsDeTipoDAOFactory
<<create>> -SQLEsDeTipoDAOFactory()-getDAOClass() : Class+getDAO() : SQLEsDeTipoDAO
-DAO_CLASS_NAME_PARAMETER : String-daoClass : Class
<<interface>>SQLEsDeTipoDAO
+addEsDeTipo(connection : Connection,esDeTipoVO : EsDeTipoVO) : EsDeTipoVO+removeEsDeTipo(connection : Connection,numero : Long,idTipo : Long) : void+removeEsDeTipoByNumber(connection : Connection,numero : Long) : void+existsEsDeTipo(connection : Connection,numero : Long,idTipo : Long) : boolean+getAll(connection : Connection,startIndex : int,count : int) : Collection+getByTipo(connection : Connection,idTipo : Long,startIndex : int,count : int) : Collection+getByHabitacion(connection : Connection,numero : Long,startIndex : int,count : int) : Collection
AbstractSQLEsDeTipoDAO
+addEsDeTipo(connection : Connection,esDeTipoVO : EsDeTipoVO) : EsDeTipoVO+getAll(connection : Connection,startIndex : int,count : int) : Collection+existsEsDeTipo(connection : Connection,numero : Long,idTipo : Long) : boolean+getByHabitacion(connection : Connection,numero : Long,startIndex : int,count : int) : Collection+getByTipo(connection : Connection,idTipo : Long,startIndex : int,count : int) : Collection+removeEsDeTipo(connection : Connection,numero : Long,idTipo : Long) : void+removeEsDeTipoByNumber(connection : Connection,numero : Long) : void
<<realize>>
MySQLEsDeTipoDAO
+addEsDeTipo(connection : Connection,esDeTipoVO : EsDeTipoVO) : EsDeTipoVO
EsDeTipoVO
-serialVersionUID : long-numero : Long-idTipo : Long
Figura 6.22: Diagrama del Paquete ’esdetipo’
6.4. Arquitectura del Modelo 123
6.4.3.5. Paquete ’incidencia’
SQLIncidenciaDAOFactory
<<create>> -SQLIncidenciaDAOFactory()-getDAOClass() : Class+getDAO() : SQLIncidenciaDAO
-DAO_CLASS_NAME_PARAMETER : String-daoClass : Class
<<interface>>SQLIncidenciaDAO
+addIncidencia(connection : Connection,incidenciaVO : IncidenciaVO) : IncidenciaVO+removeIncidencia(connection : Connection,numero : Long,idSecundario : Long) : void+existsIncidencia(connection : Connection,numero : Long,idSecundario : Long) : boolean+findIncidencia(connection : Connection,numero : Long,idSecundario : Long) : IncidenciaVO+getAll(connection : Connection,startIndex : int,count : int) : Collection+getByHabitacion(connection : Connection,numero : Long,startIndex : int,count : int) : Collection+getByTipo(connection : Connection,tipo : String,startIndex : int,count : int) : Collection
AbstractSQLIncidenciaDAO
+addIncidencia(connection : Connection,incidenciaVO : IncidenciaVO) : IncidenciaVO+existsIncidencia(connection : Connection,numero : Long,idSecundario : Long) : boolean+findIncidencia(connection : Connection,numero : Long,idSecundario : Long) : IncidenciaVO+getAll(connection : Connection,startIndex : int,count : int) : Collection+getByHabitacion(connection : Connection,numero : Long,startIndex : int,count : int) : Collection+getByTipo(connection : Connection,tipo : String,startIndex : int,count : int) : Collection+removeIncidencia(connection : Connection,numero : Long,idSecundario : Long) : void
<<realize>>
MySQLIncidenciaDAO
+addIncidencia(connection : Connection,incidenciaVO : IncidenciaVO) : IncidenciaVO
IncidenciaVO
-serialVersionUID : long-numero : Long-idSecundario : Long-tipo : String-descripcion : String-fechaRegistro : Calendar
Figura 6.23: Diagrama del Paquete ’incidencia’
6.4. Arquitectura del Modelo 124
6.4.3.6. Paquete ’lineadereserva’
SQLLineaDeReservaDAOFactory
<<create>> -SQLLineaDeReservaDAOFactory()-getDAOClass() : Class+getDAO() : SQLLineaDeReservaDAO
-DAO_CLASS_NAME_PARAMETER : String-daoClass : Class
<<interface>>SQLLineaDeReservaDAO
+addLineaDeReserva(connection : Connection,lineaDeReservaVO : LineaDeReservaVO) : LineaDeReservaVO+removeLineaDeReserva(connection : Connection,numero : Long,fechaInicio : Calendar) : void+existsReservaForHabitacionForDay(connection : Connection,numero : Long,fecha : Calendar) : boolean+findLineaDeReserva(connection : Connection,codigoReserva : Long,numero : Long,fechaInicio : Calendar) : LineaDeReservaVO+getAll(connection : Connection,startIndex : int,count : int) : Collection+getByCodigoReserva(connection : Connection,codigoReserva : Long,startIndex : int,count : int) : Collection+getByCodigoReservaAndHabitacion(connection : Connection,codigoReserva : Long,numero : Long,startIndex : int,count : int) : Collection+getByCodigoReservaAndPendientes(connection : Connection,codigoReserva : Long,startIndex : int,count : int) : Collection+getByFactura(connection : Connection,numeroFactura : Long,startIndex : int,count : int) : Collection+getByCancelada(connection : Connection,cancelada : boolean,startIndex : int,count : int) : Collection+getByHabitacionAndActual(connection : Connection,numero : Long,startIndex : int,count : int) : Collection+updateReservaCancelada(connection : Connection,codigoReserva : Long,cancelada : boolean) : void+updateLineaReservaCancelada(connection : Connection,numero : Long,fechaInicio : Calendar,cancelada : boolean) : void+updateTotalParcial(connection : Connection,lineaDeReservaVO : LineaDeReservaVO,totalParcial : double) : void+updateDescuento(connection : Connection,lineaDeReservaVO : LineaDeReservaVO,descuento : double) : void
AbstractSQLLineaDeReservaDAO
+addLineaDeReserva(connection : Connection,lineaDeReservaVO : LineaDeReservaVO) : LineaDeReservaVO+removeLineaDeReserva(connection : Connection,numero : Long,fechaInicio : Calendar) : void+existsReservaForHabitacionForDay(connection : Connection,numero : Long,fecha : Calendar) : boolean+findLineaDeReserva(connection : Connection,codigoReserva : Long,numero : Long,fecha : Calendar) : LineaDeReservaVO+getAll(connection : Connection,startIndex : int,count : int) : Collection+getByCancelada(connection : Connection,cancelada : boolean,startIndex : int,count : int) : Collection+getByCodigoReserva(connection : Connection,codigoReserva : Long,startIndex : int,count : int) : Collection+getByCodigoReservaAndPendientes(connection : Connection,codigoReserva : Long,startIndex : int,count : int) : Collection+getByCodigoReservaAndHabitacion(connection : Connection,codigoReserva : Long,numero : Long,startIndex : int,count : int) : Collection+getByFactura(connection : Connection,numeroFactura : Long,startIndex : int,count : int) : Collection+getByHabitacionAndActual(connection : Connection,numero : Long,startIndex : int,count : int) : Collection+updateLineaReservaCancelada(connection : Connection,numero : Long,fechaInicio : Calendar,cancelada : boolean) : void+updateReservaCancelada(connection : Connection,codigoReserva : Long,cancelada : boolean) : void+updateTotalParcial(connection : Connection,lineaDeReservaVO : LineaDeReservaVO,totalParcial : double) : void+updateDescuento(connection : Connection,lineaDeReservaVO : LineaDeReservaVO,descuento : double) : void
<<realize>>
MySQLLineaDeReservaDAO
+addLineaDeReserva(connection : Connection,lineaDeReservaVO : LineaDeReservaVO) : LineaDeReservaVO
LineaDeReservaVO
-serialVersionUID : long-codigoReserva : Long-numero : Long-fechaInicio : Calendar-fechaFin : Calendar-descuento : double-totalParcial : double-numeroFactura : Long-cancelada : boolean
Figura 6.24: Diagrama del Paquete ’lineadereserva’
6.4. Arquitectura del Modelo 125
6.4.3.7. Paquete ’reserva’
SQLReservaDAOFactory
<<create>> -SQLReservaDAOFactory()-getDAOClass() : Class+getDAO() : SQLReservaDAO
-DAO_CLASS_NAME_PARAMETER : String-daoClass : Class
<<interface>>SQLReservaDAO
+addReserva(connection : Connection,reservaVO : ReservaVO) : ReservaVO+removeReserva(connection : Connection,codigo : Long) : void+existsReserva(connection : Connection,codigo : Long) : boolean+findReserva(connection : Connection,codigo : Long) : ReservaVO+getAll(connection : Connection,startIndex : int,count : int) : Collection+getEntreFechas(connection : Connection,fecha1 : Calendar,fecha2 : Calendar,startIndex : int,count : int) : Collection+getByPersona(connection : Connection,dniPas : String,startIndex : int,count : int) : Collection+getByTemporal(connection : Connection,temporal : boolean,startIndex : int,count : int) : Collection+updateTemporal(connection : Connection,codigo : Long,temporal : boolean) : void+updateFechaRealizacion(connection : Connection,codigo : Long,fechaRealizacion : Calendar) : void
AbstractSQLReservaDAO
+addReserva(connection : Connection,reservaVO : ReservaVO) : ReservaVO+removeReserva(connection : Connection,codigo : Long) : void+existsReserva(connection : Connection,codigo : Long) : boolean+findReserva(connection : Connection,codigo : Long) : ReservaVO+getAll(connection : Connection,startIndex : int,count : int) : Collection+getEntreFechas(connection : Connection,fecha1 : Calendar,fecha2 : Calendar,startIndex : int,count : int) : Collection+getByPersona(connection : Connection,dniPas : String,startIndex : int,count : int) : Collection+getByTemporal(connection : Connection,temporal : boolean,startIndex : int,count : int) : Collection+updateTemporal(connection : Connection,codigo : Long,temporal : boolean) : void+updateFechaRealizacion(connection : Connection,codigo : Long,fechaRealizacion : Calendar) : void
<<realize>>
MySQLReservaDAO
+addReserva(connection : Connection,reservaVO : ReservaVO) : ReservaVO
ReservaVO
-serialVersionUID : long-dniPas : String-codigo : Long-fechaRealizacion : Calendar-temporal : boolean
Figura 6.25: Diagrama del Paquete ’reserva’
6.4. Arquitectura del Modelo 126
6.4.3.8. Paquete ’factura’
SQLFacturaDAOFactory
<<create>> -SQLFacturaDAOFactory()-getDAOClass() : Class+getDAO() : SQLFacturaDAO
-DAO_CLASS_NAME_PARAMETER : String-daoClass : Class
<<interface>>SQLFacturaDAO
+addFactura(connection : Connection,facturaVO : FacturaVO) : FacturaVO+removeFactura(connection : Connection,numeroFactura : Long) : void+findFactura(connection : Connection,numeroFactura : Long) : FacturaVO+existsFactura(connection : Connection,numeroFactura : Long) : boolean+getAll(connection : Connection,startIndex : int,count : int) : Collection+getByCliente(connection : Connection,dniPas : String,startIndex : int,count : int) : Collection+getBetweenFechas(connection : Connection,earlierFecha : Calendar,laterFecha : Calendar,startIndex : int,count : int) : Collection+getByPagada(connection : Connection,pagada : boolean,startIndex : int,count : int) : Collection+getByBorrador(connection : Connection,borrador : boolean,startIndex : int,count : int) : Collection+getByClienteAndPagada(connection : Connection,dniPas : String,pagada : boolean,startIndex : int,count : int) : Collection+getByClienteAndBorrador(connection : Connection,dniPas : String,borrador : boolean,startIndex : int,count : int) : Collection+updateTotal(connection : Connection,numeroFactura : Long,newTotal : double) : void+updateTotalDescontado(connection : Connection,numeroFactura : Long,newTotalDescontado : double) : void+updateOfertasAplicadas(connection : Connection,numeroFactura : Long,ofertasAplicadas : String) : void+updateBorrador(connection : Connection,numeroFactura : Long,isBorrador : Boolean) : void+updatePagada(connection : Connection,numeroFactura : Long,isPagada : Boolean) : void+updateFecha(connection : Connection,numeroFactura : Long,fecha : Calendar) : void
AbstractSQLFacturaDAO
+getAll(connection : Connection,startIndex : int,count : int) : Collection
+addFactura(connection : Connection,facturaVO : FacturaVO) : FacturaVO+existsFactura(connection : Connection,numeroFactura : Long) : boolean+findFactura(connection : Connection,numeroFactura : Long) : FacturaVO+getByBorrador(connection : Connection,borrador : boolean,startIndex : int,count : int) : Collection+getByCliente(connection : Connection,dniPas : String,startIndex : int,count : int) : Collection+getByClienteAndBorrador(connection : Connection,dniPas : String,borrador : boolean,startIndex : int,count : int) : Collection+getByClienteAndPagada(connection : Connection,dniPas : String,pagada : boolean,startIndex : int,count : int) : Collection+getBetweenFechas(connection : Connection,earlierFecha : Calendar,laterFecha : Calendar,startIndex : int,count : int) : Collection+getByPagada(connection : Connection,pagada : boolean,startIndex : int,count : int) : Collection+removeFactura(connection : Connection,numeroFactura : Long) : void+updateTotal(connection : Connection,numeroFactura : Long,newTotal : double) : void+updateBorrador(connection : Connection,numeroFactura : Long,isBorrador : Boolean) : void+updatePagada(connection : Connection,numeroFactura : Long,isPagada : Boolean) : void+updateTotalDescontado(connection : Connection,numeroFactura : Long,newTotalDescontado : double) : void+updateOfertasAplicadas(connection : Connection,numeroFactura : Long,ofertasAplicadas : String) : void+updateFecha(connection : Connection,numeroFactura : Long,fecha : Calendar) : void
<<realize>>
MySQLFacturaDAO
+addFactura(connection : Connection,facturaVO : FacturaVO) : FacturaVO
FacturaVO
-serialVersionUID : long-dniPas : String-numeroFactura : Long-fecha : Calendar-totalDescontado : double-total : double-pagada : boolean-borrador : boolean-ofertasAplicadas : String
Figura 6.26: Diagrama del Paquete ’factura’
6.4. Arquitectura del Modelo 127
6.4.3.9. Paquete ’tipooferta’
SQLTipoOfertaDAOFactory
<<create>> -SQLTipoOfertaDAOFactory()-getDAOClass() : Class+getDAO() : SQLTipoOfertaDAO
-DAO_CLASS_NAME_PARAMETER : String-daoClass : Class
<<interface>>SQLTipoOfertaDAO
+addTipoOferta(connection : Connection,tipoOfertaVO : TipoOfertaVO) : TipoOfertaVO+removeTipoOferta(connection : Connection,idTipo : Long) : void+existsTipoOferta(connection : Connection,idTipo : Long) : boolean+findTipoOferta(connection : Connection,idTipo : Long) : TipoOfertaVO+getAll(connection : Connection,startIndex : int,count : int) : Collection+updateDescripcion(connection : Connection,idTipo : Long,newDescripcion : String) : void+updateNombre(connection : Connection,idTipo : Long,newNombre : String) : void
AbstractSQLTipoOfertaDAO
+addTipoOferta(connection : Connection,tipoOfertaVO : TipoOfertaVO) : TipoOfertaVO+removeTipoOferta(connection : Connection,idTipo : Long) : void+existsTipoOferta(connection : Connection,idTipo : Long) : boolean+findTipoOferta(connection : Connection,idTipo : Long) : TipoOfertaVO+getAll(connection : Connection,startIndex : int,count : int) : Collection+updateDescripcion(connection : Connection,idTipo : Long,newDescripcion : String) : void+updateNombre(connection : Connection,idTipo : Long,newNombre : String) : void
<<realize>>
MySQLTipoOfertaDAO
+addTipoOferta(connection : Connection,tipoOfertaVO : TipoOfertaVO) : TipoOfertaVO
TipoOfertaVO
-serialVersionUID : long-idTipo : Long-nombre : String-descripcion : String
Figura 6.27: Diagrama del Paquete ’tipooferta’
6.4. Arquitectura del Modelo 128
6.4.3.10. Paquete ’oferta’
SQLOfertaDAOFactory
<<create>> -SQLOfertaDAOFactory()-getDAOClass() : Class+getDAO() : SQLOfertaDAO
-DAO_CLASS_NAME_PARAMETER : String-daoClass : Class
AbstractSQLOfertaDAO
+addOferta(connection : Connection,ofertaVO : OfertaVO) : OfertaVO+removeOferta(connection : Connection,idOferta : Long) : void+existsOferta(connection : Connection,idOferta : Long) : boolean+findOferta(connection : Connection,idOferta : Long) : OfertaVO+getAll(connection : Connection,startIndex : int,count : int) : Collection+getByIdTipo(connection : Connection,idTipo : Long,startIndex : int,count : int) : Collection+getByBorrador(connection : Connection,borrador : boolean,startIndex : int,count : int) : Collection+getByPublicadaActual(connection : Connection,startIndex : int,count : int) : Collection+getByDesactivada(connection : Connection,desactivada : boolean,startIndex : int,count : int) : Collection+getOfertasEnFecha(connection : Connection,fecha : Calendar,startIndex : int,count : int) : Collection+updateDescuento(connection : Connection,idOferta : Long,newDescuento : double) : void+updateDescripcion(connection : Connection,idOferta : Long,newDescripcion : String) : void+updateFechaInicio(connection : Connection,idOferta : Long,fechaInicio : Calendar) : void+updateFechaFin(connection : Connection,idOferta : Long,fechaFin : Calendar) : void+updateRegla(connection : Connection,idOferta : Long,newRegla : String) : void+updateBorrador(connection : Connection,idOferta : Long,borrador : boolean) : void+updateDesactivada(connection : Connection,idOferta : Long,desactivada : boolean) : void
MySQLOfertaDAO
+addOferta(connection : Connection,ofertaVO : OfertaVO) : OfertaVO
OfertaVO
-serialVersionUID : long-idOferta : Long-descuento : double-descripcion : String-fechaInicio : Calendar-fechaFin : Calendar-reglaACumplir : String-idTipo : Long-borrador : boolean-desactivada : boolean
<<interface>>hotel::modelo::modelooferta::oferta::dao::SQLOfertaDAO
+addOferta(connection : Connection,ofertaVO : OfertaVO) : OfertaVO+removeOferta(connection : Connection,idOferta : Long) : void+existsOferta(connection : Connection,idOferta : Long) : boolean+findOferta(connection : Connection,idOferta : Long) : OfertaVO+getAll(connection : Connection,startIndex : int,count : int) : Collection+getByIdTipo(connection : Connection,idTipo : Long,startIndex : int,count : int) : Collection+getByBorrador(connection : Connection,borrador : boolean,startIndex : int,count : int) : Collection+getByPublicadaActual(connection : Connection,startIndex : int,count : int) : Collection+getByDesactivada(connection : Connection,desactivada : boolean,startIndex : int,count : int) : Collection+getOfertasEnFecha(connection : Connection,fecha : Calendar,startIndex : int,count : int) : Collection+updateDescuento(connection : Connection,idOferta : Long,newDescuento : double) : void+updateDescripcion(connection : Connection,idOferta : Long,newDescripcion : String) : void+updateFechaInicio(connection : Connection,idOferta : Long,fechaInicio : Calendar) : void+updateFechaFin(connection : Connection,idOferta : Long,fechaFin : Calendar) : void+updateRegla(connection : Connection,idOferta : Long,newRegla : String) : void+updateBorrador(connection : Connection,idOferta : Long,borrador : boolean) : void+updateDesactivada(connection : Connection,idOferta : Long,desactivada : boolean) : void
<<realize>>
Figura 6.28: Diagrama del Paquete ’oferta’
6.4. Arquitectura del Modelo 129
6.4.3.11. Paquete ’aplicablea’
SQLAplicableADAOFactory
<<create>> -SQLAplicableADAOFactory()-getDAOClass() : Class+getDAO() : SQLAplicableADAO
-DAO_CLASS_NAME_PARAMETER : String-daoClass : Class
<<interface>>SQLAplicableADAO
+addAplicableA(connection : Connection,aplicableAVO : AplicableAVO) : AplicableAVO+removeAplicableA(connection : Connection,idTipo : Long,nombre : String) : void+existsAplicableA(connection : Connection,idTipo : Long,nombre : String) : boolean+findAplicableA(connection : Connection,idTipo : Long,nombre : String) : AplicableAVO+getAll(connection : Connection,startIndex : int,count : int) : Collection+getByIdTipo(connection : Connection,idTipo : Long,startIndex : int,count : int) : Collection+getByNombre(connection : Connection,nombre : String,startIndex : int,count : int) : Collection+updateCantidadMin(connection : Connection,idTipo : Long,nombre : String,cantidadMin : Long) : void
AbstractSQLAplicableADAO
+addAplicableA(connection : Connection,aplicableAVO : AplicableAVO) : AplicableAVO+removeAplicableA(connection : Connection,idTipo : Long,nombre : String) : void+existsAplicableA(connection : Connection,idTipo : Long,nombre : String) : boolean+findAplicableA(connection : Connection,idTipo : Long,nombre : String) : AplicableAVO+getAll(connection : Connection,startIndex : int,count : int) : Collection+getByIdTipo(connection : Connection,idTipo : Long,startIndex : int,count : int) : Collection+getByNombre(connection : Connection,nombre : String,startIndex : int,count : int) : Collection+updateCantidadMin(connection : Connection,idTipo : Long,nombre : String,cantidadMin : Long) : void
<<realize>>
MySQLAplicableADAO
+addAplicableA(connection : Connection,aplicableAVO : AplicableAVO) : AplicableAVO
AplicableAVO
-serialVersionUID : long-idTipo : Long-nombre : String-cantidadMin : Long
Figura 6.29: Diagrama del Paquete ’aplicablea’
6.4. Arquitectura del Modelo 130
6.4.3.12. Paquete ’incompatiblecon’
SQLIncompatibleConDAOFactory
<<create>> -SQLIncompatibleConDAOFactory()-getDAOClass() : Class+getDAO() : SQLIncompatibleConDAO
-DAO_CLASS_NAME_PARAMETER : String-daoClass : Class
<<interface>>SQLIncompatibleConDAO
+addIncompatibleCon(connection : Connection,incompatibleConVO : IncompatibleConVO) : IncompatibleConVO+removeAIncompatibleConB(connection : Connection,idTipoA : Long,idTipoB : Long) : void+existsAIncompatibleConB(connection : Connection,idTipoA : Long,idTipoB : Long) : boolean+getAll(connection : Connection,startIndex : int,count : int) : Collection+getByIncompatibleConA(connection : Connection,idTipoA : Long,startIndex : int,count : int) : Collection
AbstractSQLIncompatibleConDAO
+addIncompatibleCon(connection : Connection,incompatibleConVO : IncompatibleConVO) : IncompatibleConVO+removeAIncompatibleConB(connection : Connection,idTipoA : Long,idTipoB : Long) : void+existsAIncompatibleConB(connection : Connection,idTipoA : Long,idTipoB : Long) : boolean+getAll(connection : Connection,startIndex : int,count : int) : Collection+getByIncompatibleConA(connection : Connection,idTipoA : Long,startIndex : int,count : int) : Collection
<<realize>>
MySQLIncompatibleConDAO
+addIncompatibleCon(connection : Connection,incompatibleConVO : IncompatibleConVO) : IncompatibleConVO
IncompatibleConVO
-serialVersionUID : long-idTipo : Long-idTipoIncomp : Long
Figura 6.30: Diagrama del Paquete ’incompatiblecon’
6.4. Arquitectura del Modelo 131
6.4.4. Descripcion de los Subsistemas
En los siguientes apartados se detallaran todos los subsistemas que forman la aplicacion.
El primer subsistema que se tratara sera el de gestion de Usuarios y Clientes, encargado
de dar de alta, baja, modificacion de datos, busqueda de clientes, etc. Este subsistema
junto con el de Reservas son los dos que se desarrollan en la primera iteracion de la fase de
construccion durante la implementacion. Un vez desarrollados estos dos sistemas se tiene
una primera version del software que ya se puede utilizar y probar.
En una segunda iteracion se implementa el subsistema de Gestion de Facturas, ya que
esta muy relacionado con la Gestion de Reservas. Sin embargo este sistema utiliza el
Sistema de Ofertas del que se habla en la pagina 166, por lo que, aunque se implementa
mas tarde, ya habra que definir en un principio la interfaz que va a utilizar para ofrecer
servicios a los subsistemas.
En la siguiente iteracion se desarrollara el subsistema de Gestion de Ofertas, que ya que
tambien esta relacionado con el de las Facturas, es una buena idea implementarlo en este
punto.
Por ultimo se desarrollara la Gestion de Habitaciones, que aunque es un sistema que no
es complicado, no se puede dejar atras.
6.4.4.1. Gestion de Usuarios y Clientes
En esta seccion se mostrara como es el desarrollo de los casos de uso Gestion de Usuarios
Web y Gestion de Clientes. Como se ha podido observar en la descripcion de estos casos de
uso, los dos conjuntos de casos son muy parecidos, simplemente cambian algunos apartados
de los casos de uso o se anaden otros nuevos, y los actores que los llevan a cabo. Por
esta similitud a la hora de llevarse a cabo, se juntaron esos dos conjuntos en el mismo
subsistema. Aunque a la hora de implementarlo se han dividido de nuevo, de esta forma
se usa el patron Session Facade en ambos conjuntos de casos de uso.
6.4. Arquitectura del Modelo 132
De aquı en adelante se mostrara como se organizan las clases que forman este subsistema
y luego se aclarara el cometido que tiene cada una de ellas. En las figuras 6.31 y 6.32
se muestra unos diagramas sencillos de la Gestion de Usuarios y en las 6.33 y 6.34 los
diagramas de la Gestion de Clientes.
<<interface>>UsuariosWebFacade
+autenticar(userName : String,userPassword : String) : PersonaVO+altaUsuario(personaVO : PersonaVO) : PersonaVO+bajaUsuario(dniPasPersona : String) : void+modificarDatosUsuario(personaVO : PersonaVO) : PersonaVO+getDatos(dniPasPersona : String) : PersonaVO+getDatos() : PersonaVO
GeneralUsuariosWebFacade
<<create>> +GeneralUsuariosWebFacade()+bajaUsuario(dniPasPersona : String) : void+modificarDatosUsuario(personaVO : PersonaVO) : PersonaVO+altaUsuario(personaVO : PersonaVO) : PersonaVO+getDatos(dniPasPersona : String) : PersonaVO+getDatos() : PersonaVO+autenticar(userName : String,userPassword : String) : PersonaVO
<<realize>>
actions
exceptions
Figura 6.31: Diagrama Simple de Gestion de Usuarios
AltaUsuarioAction
<<create>> +AltaUsuarioAction(personaVO : PersonaVO)+execute(connection : Connection) : Object
AutenticarAction
<<create>> +AutenticarAction(userName : String,userPassword : String)+execute(connection : Connection) : Object
BajaUsuarioAction
<<create>> +BajaUsuarioAction(dniPas : String)+execute(connection : Connection) : Object
GetDatosAction
<<create>> +GetDatosAction(dniPasPersona : String)+execute(connection : Connection) : Object
ModificarDatosUsuarioAction
<<create>> +ModificarDatosUsuarioAction(personaVO : PersonaVO)+execute(connection : Connection) : Object
<<interface>>PlainAction
+execute(connection : Connection) : Object
<<interface>>TransactionalPlainAction
<<interface>>NonTransactionalPlainAction
AuthenticationFailException
PersonAlreadyExistsException
UserNameAlreadyInUseException
Figura 6.32: Actions y Exceptions de Gestion de Usuarios
6.4. Arquitectura del Modelo 133
En estos diagramas se puede observar el uso de los patrones Session Facade y Business
Delegate. La interfaz para acceder a este subsistema es UsuariosWebFacade, implementado
por GeneralUsuariosWebFacade, el cual se implementa en terminos de DAOs. Esta fachada
proporciona a las demas capas que la quieran utilizar una serie de operaciones. Estas
operaciones que ofrece, para evitar caer en una clase enorme, delegan su funcionamiento
en las acciones correspondientes del subpaquete Actions. A continuacion se explicara el
funcionamiento de cada una de las acciones.
Ademas de usar unas acciones para implementar sus metodos, esta fachada tambien
lanza una serie de excepciones personalizadas, CustomException, que a diferencia de las
excepciones normales de Java que se utilizan para describir un caso de error en el sistema,
estas se emplearan para proporcionar informacion a las capas superiores acerca del estado
con el que finalizo la operacion, sin que este estado tenga que ser un estado de error de
la aplicacion. En el caso de UsuariosWebFacade se utilizaran excepciones para informar si
el nombre de usuario esta en uso, si la autenticacion ha sido fallida y si el usuario que se
pretende crear o modificar ya existe en el sistema.
Las acciones en base a las cual se implementan las operaciones de UsuariosWebFacade,
podran clasificarse como transaccionales y no transaccionales dependiendo si es necesario
que la operacion se realice de forma atomica o no, y son las siguientes:
AltaUsuarioAction Esta accion es la encargada de dar de alta un nuevo usuario
en el sistema. Para ello necesita que se le pasen los parametros necesarios para
tal operacion, es decir, los datos del nuevo usuario, estos iran encapsulados
en un objeto PersonaVO, que como ya se ha visto anterioremente, sigue el
patron Value Object (VO) y proporciona metodos para lectura y escritura de
sus atributos.
Lo primero que se debe hacer es comprobar si el nuevo DNI ya existe en la base
de datos, esto lo hacemos gracias a PersonaDAO que nos ofrece metodos para
insertar, modificar, consultar y eliminar datos de la base de datos. Si el DNI
6.4. Arquitectura del Modelo 134
ya existe se lanzara una excepcion indicando este suceso, y si no se continua
comprobando si existe el nombre de usuario, si no existe entonces se procede
a la insercion de los datos del nuevo usuario en la base de datos utilizando
PersonaDAO
BajaUsuarioAction Es la encargada de dar de baja un usuario del sistema. Para
ello es necesario pasarle el DNI del cliente que se desea dar de baja.
Luego se utiliza PersonaDAO para actualizar el atributo ’usuarioConf’ poniendo
un ’false’. En realidad no se eliminan sus datos del sistema, pero a partir de ese
momento deja de ser usuario de este.
ModificarDatosUsuarioAction Se encarga de actualizar los datos personales de
un usuario. Para ello necesita que se le pasen todos los datos de nuevo, como
si el usuario se fuera a dar de alta, mediante un objeto PersonaVO.
Luego se recuperan los datos del usuario que estan almacenados y se comparan
uno a uno con los nuevos, aquellos que no coincidan se actualizan utilizando
PersonaDAO.
GetDatosAction Se encarga de recuperar los datos personales de un usuario. Para
ello necesita que se le pase el DNI del usuario del que se desea la informacion.
A continuacion se recuperan los datos del usuario que estan almacenados.
AutenticarAction Se encarga de comprobar si el usuario existe en el sistema, y de
ser ası devolver un objeto PersonaVO con sus datos personales. Para realizar
esta operacion necesita el nombre de usuario y la contrasena del cliente.
Lo primero que realiza la accion es recuperar los datos de un usuario que tenga
ese nombre de usuario y esa contrasena, si la recuperacion falla o el usuario
esta senalado como ’no confirmado’ entonces se lanza la excepcion Autentica-
tionFailException, que indica que no se pudo autenticar la identidad del cliente.
6.4. Arquitectura del Modelo 135
A continuacion en la figura 6.33 se muestra el esquema de las clases que forman el Session
Facade ’ClientesFacade’ y las acciones en las que sus metodos delegan su funcionamiento.
<<interface>>ClientesFacade
+altaCliente(personaVO : PersonaVO) : PersonaVO+bajaCliente(dniPas : String) : void+modificarDatosCliente(personaVO : PersonaVO) : PersonaVO+buscarClientes(name : String,surname : String,dniPas : String,startIndex : int,count : int) : PersonaCollectionChunkVO+getDatos(dniPasPersona : String) : PersonaVO+getDatos() : PersonaVO
GeneralClientesFacade
<<create>> +GeneralClientesFacade()+modificarDatosCliente(personaVO : PersonaVO) : PersonaVO+altaCliente(personaVO : PersonaVO) : PersonaVO+bajaCliente(dniPas : String) : void+getDatos(dniPasPersona : String) : PersonaVO+getDatos() : PersonaVO+buscarClientes(name : String,surname : String,dniPas : String,startIndex : int,count : int) : PersonaCollectionChunkVO
-serialVersionUID : long-dataSource : DataSource-personaVO : PersonaVO
<<realize>>
actions exceptions vo
Figura 6.33: Diagrama Simple de Gestion de Clientes
6.4. Arquitectura del Modelo 136
AltaClienteAction
<<create>> +AltaClienteAction(personaVO : PersonaVO)+execute(connection : Connection) : Object
BajaClienteAction
<<create>> +BajaClienteAction(dniPas : String)+execute(connection : Connection) : Object
BuscarClientesAction
<<create>> +BuscarClientesAction(name : String,surname : String,dniPas : String,startIndex : int,count : int)+execute(connection : Connection) : Object
GetDatosAction
<<create>> +GetDatosAction(dniPasPersona : String)+execute(connection : Connection) : Object
ModificarDatosClienteAction
<<create>> +ModificarDatosClienteAction(personaVO : PersonaVO)+execute(connection : Connection) : Object
<<interface>>PlainAction
+execute(connection : Connection) : Object
<<interface>>NonTransactionalPlainAction
<<interface>>TransactionalPlainAction
PersonAlreadyExistsException
PersonNotFoundException UserNameAlreadyInUseException
PersonaCollectionChunkVO
<<create>> +PersonaCollectionChunkVO(colPersonas : Collection,index : int,more : Boolean)+getColPersonas() : Collection+getIndex() : int+getHasMore() : Boolean
<<call>>
<<create>>
Figura 6.34: Actions y Exceptions de Gestion de Clientes
En estos diagramas se puede observar de nuevo el uso de los patrones Session Facade
y Business Delegate. La interfaz para acceder a este subsistema es ClientesFacade, im-
plementado por GeneralClientesFacade. Al igual que en el Session Facade anterior, los
metodos de la fachada delegan su funcionamiento en las acciones correspondientes del
subpaquete Actions. A continuacion se explicara el funcionamiento de cada una de las
acciones.
Ademas de usar unas acciones para implementar sus metodos, esta fachada tambien
lanza CustomException para proporcionar informacion a las capas superiores acerca del
estado con el que finalizo la operacion. En este caso se usaran excepciones para informar si
el nombre de usuario del cliente esta en uso, si el cliente que se pretende crear o modificar
ya existe en el sistema, o si un cliente buscado no se ha encontrado.
6.4. Arquitectura del Modelo 137
Las acciones en base a las cual se implementan las operaciones de ClientesFacade, tam-
bien podran clasificarse como transaccionales y no transaccionales dependiendo si es ne-
cesario que la operacion se realice de forma atomica o no, y son las siguientes:
AltaClienteAction Esta accion es la encargada de dar de alta un nuevo cliente
en el sistema. Para ello necesita que se le pasen los parametros necesarios para
tal operacion, es decir, los datos del nuevo cliente, estos iran encapsulados en
un objeto PersonaVO, que como ya se ha visto anterioremente, aunque para el
caso de dar de alta un nuevo cliente no seran obligatorios todos los datos que
lo eran para dar de alta a un usuario.
Lo primero que se debe hacer es comprobar si el nuevo DNI ya existe en la base
de datos utilizando PersonaDAO. Si el DNI ya existe se lanzara una excepcion
indicando este suceso, y sino se continua comprobando si existe el nombre de
usuario, si no existe entonces se procede a la insercion de los datos del nuevo
cliente en la base de datos utilizando de nuevo PersonaDAO
BajaClienteAction Es la encargada de dar de baja un usuario del sistema. Para
ello es necesario pasarle el DNI del cliente que se desea dar de baja.
Primero se comprueba si existe el DNI, sino se lanza una excepcion, y luego
se utiliza PersonaDAO para actualizar el atributo ’usuarioConf’ poniendo un
’false’. En realidad no se eliminan sus datos del sistema, pero a partir de ese
momento deja de ser cliente.
ModificarDatosClienteAction Se encarga de actualizar los datos personales de
un cliente. Para ello necesita que se le pasen todos los datos de nuevo, como si
el cliente se fuera a dar de alta, mediante un objeto PersonaVO.
Luego se recuperan los datos del cliente que estan almacenados y se comparan
uno a uno con los nuevos, aquellos que no coincidan se actualizan utilizando
PersonaDAO.
6.4. Arquitectura del Modelo 138
GetDatosAction Se encarga de recuperar los datos personales de un cliente. Para
ello necesita que se le pase el DNI del cliente del que se desea la informacion.
A continuacion se recuperan los datos del cliente que estan almacenados.
BuscarClientesAction Esta accion es la encargada de recuperar una lista de clien-
tes que concuerden con unos parametros de busqueda, en este caso se podra bus-
car por nombre, apellidos y/o DNI, se podra hacer cualquier combinacion que
se desee.
Para llevar a cabo esta operacion es necesario comprobar cuales son los campos
por los que se quiere buscar, ya que el DAO PersonaDAO necesita que se le
indique mediante valores ’boolean’ aquellos campos para los que tiene que rea-
lizar la consulta. Una vez hecho esto PersonaDAO recupera la lista de clientes
que concuerdan con los criterios.
6.4.4.2. Gestion de Reservas
En esta seccion se mostrara como es el desarrollo de los casos de uso Gestion de Reservas.
Como en los casos anteriores se utiliza el patron Session Facade para implementar este
subsistema.
Entre las operaciones de este sistema cabe destacar que debe permitir comprobar si existe
alguna habitacion libre de un tipo determinado para una serie de dıas. Esta operacion no
implementa ningun caso de uso especıfico pero es necesaria para realizar comprobaciones
a la hora de realizar reservas.
De aquı en adelante se mostrara como se organizan las clases que forman este subsistema
y luego se aclarara el cometido que tiene cada una de ellas. En las figuras 6.35 y 6.36 se
muestra unos diagramas sencillos de la Gestion de Reservas.
6.4. Arquitectura del Modelo 139
<<interface>>ReservasWebFacade
+checkDisponible(reserva : ReservaFromToTipoHabitacionChunkVO) : boolean+checkDisponible(reserva : ReservaFromToTipoHabitacionChunkVO,numeroHabs : Long) : boolean+crearReserva(dniPas : String,reservaTipoHabitacion : Collection) : ReservaCompletaChunkVO+getReservaCompleta(codReserva : Long) : ReservaCompletaChunkVO+modificarDatosReserva(lastReserva : ReservaCompletaChunkVO,newReserva : ReservaCompletaChunkVO) : ReservaCompletaChunkVO+getReservas(dniPas : String,index : int,count : int) : ReservasCollectionChunkVO+checkHabitacionesLibres(From : Calendar,To : Calendar) : Map
GeneralReservasWebFacade
<<create>> +GeneralReservasWebFacade()+checkDisponible(reserva : ReservaFromToTipoHabitacionChunkVO) : boolean+crearReserva(dniPas : String,reservaTipoHabitacion : Collection) : ReservaCompletaChunkVO+getReservaCompleta(codReserva : Long) : ReservaCompletaChunkVO+modificarDatosReserva(lastReserva : ReservaCompletaChunkVO,newReserva : ReservaCompletaChunkVO) : ReservaCompletaChunkVO+checkDisponible(reserva : ReservaFromToTipoHabitacionChunkVO,numeroHabs : Long) : boolean+getReservas(dniPas : String,index : int,count : int) : ReservasCollectionChunkVO+checkHabitacionesLibres(from : Calendar,to : Calendar) : Map
-dataSource : DataSource
<<realize>>
actions
vo
exceptions
LineaDeReservaChunkVO
ReservaChunkVOReservaCompletaChunkVO
ReservaFromToTipoHabitacionChunkVO
ReservasCollectionChunkVO
Figura 6.35: Diagrama Simple de Gestion de Reservas
6.4. Arquitectura del Modelo 140
<<interface>>PlainAction
+execute(connection : Connection) : Object
<<interface>>TransactionalPlainAction
<<interface>>NonTransactionalPlainAction
CrearReservaAction
<<create>> +CrearReservaAction(dniPas : String,reserva : Collection)+execute(connection : Connection) : Object
ModificarReservaAction
<<create>> +ModificarReservaAction(lastReserva : ReservaCompletaChunkVO,newReserva : ReservaCompletaChunkVO)+execute(connection : Connection) : Object
CheckDisponibleAction
<<create>> +CheckDisponibleAction(reserva : ReservaFromToTipoHabitacionChunkVO)+execute(connection : Connection) : Object
CheckDisponibleQuantityAction
<<create>> +CheckDisponibleQuantityAction(reserva : ReservaFromToTipoHabitacionChunkVO,quantity : Long)+execute(connection : Connection) : Object
CheckHabitacionesLibresAction
<<create>> +CheckHabitacionesLibresAction(from : Calendar,to : Calendar)+execute(connection : Connection) : Object
GetReservaCompletaAction
<<create>> +GetReservaCompletaAction(codReserva : Long)+execute(connection : Connection) : Object
GetReservasAction
<<create>> +GetReservasAction(dniPas : String,index : int,count : int)+execute(connection : Connection) : Object
EmptyReservationException
IllegalCheckException
IllegalReservationChangeException
NoReservationFoundException
NoRoomsOfEspecifiedTypeException
SomeDayNotAvailableException
Figura 6.36: Actions y Exceptions de Gestion de Reservas
6.4. Arquitectura del Modelo 141
En estos diagramas se puede ver como se vuelven a usar los patrones Session Facade
y Business Delegate. La interfaz para acceder a este subsistema es ReservasWebFacade,
implementado por GeneralReservasWebFacade. Al igual que en el Session Facade anterior,
los metodos de la fachada delegan su funcionamiento en las acciones correspondientes del
subpaquete Actions. A continuacion se explicara el funcionamiento de cada una de las
acciones.
Ademas de usar unas acciones para implementar sus metodos, esta fachada tambien
lanza CustomException para proporcionar informacion a las capas superiores acerca del
estado con el que finalizo la operacion. En este caso se usaran excepciones para informar
si no hay habitaciones libres de un tipo solicitado, si una reserva que se desea crear o
modificar esta vacıa, si se quiere crear o cambiar una reserva pero alguno de los dıas
esta ya ocupado, si una reserva no se puede cambiar o si no se encuentra una reserva
buscada.
Por otro lado, esta fachada manejara unos objetos especiales, los Custom Value Objects.
Estos objetos estaran localizados en el subpaquete ’vo’ y tendran como cometido ofrecer
a las capas superiores un conjunto de los atributos de un VO ya existente, o varios atri-
butos de diferentes VOs agrupados, con esto lo que se pretente es pasar a la capa superior
unicamente los datos que necesita. Otro caso para lo que se utilizan los Custom Value Ob-
jects es para ’paginar’ los resultados de una lista, por ejemplo, si se quieren recuperar 100
valores de la base de datos, estos se encapsularan en un objeto que ademas contendra otra
informacion como: si hay, o no, mas elementos para hacer una siguiente busqueda.
Las acciones en base a las cuales se implementan las operaciones de ReservasFacade,
tambien podran clasificarse como transaccionales y no transaccionales dependiendo si es
necesario que la operacion se realice de forma atomica o no, y son las siguientes:
CrearReservaAction Esta accion es la encargada de crear una nueva reserva. Para
esto necesita que se le pasen un conjunto de lıneas de reserva y el DNI del cliente
que la desea realizar.
6.4. Arquitectura del Modelo 142
Las lıneas de reserva que se le deben pasar a esta accion tienen que ser lo menos
concretas posibles, es decir, no se indicara la habitacion, ya que estas se asignan
una vez que se comprueben si estan libres. Para pasar estos datos se crea un
nuevo objeto que es ’ReservaFromToTipoHabitacionChunkVO’ que lo unico
que representa es: una fecha de llegada, fecha de salida y tipo de habitacion
al que se destina. Este objeto tambien proporcionara metodos necesarios para
comprobar si una reserva coincide en fechas con otra.
Luego la accion tiene que comprobar si hay habitaciones libres de alguna ha-
bitacion del tipo deseado para los dıas indicados. Si es ası, se escoge alguna
de las habitaciones libres para los dıas que se desean y se guarda la lınea de
reserva. Esto se hace con todas las lıneas de reserva y a continuacion se crean:
una nueva factura calculando todos los totales y una reserva.
Al terminar se devuelve un objeto ’ReservaCompletaChunkVO’ donde se encap-
sulan todas las lıneas de reserva, los datos de la reserva, numero de la factura,
etc.
ModificarReservaAction Esta accion hace lo mismo que ’CrearReservaAction’,
pero antes de comprobar las habitaciones libres divide el conjunto de lıneas de
reserva pasadas en: las que ya existen en la base de datos, las que no existen,
y las que existıan y hay que eliminar. Una vez hechas esas comprobaciones y
sabiendo que se pueden crear las nuevas lıneas de reserva, se procede a eliminar
y crear las lıneas que proceda y a actualizar los totales en la factura.
GetReservaCompletaAction Se encarga de recuperar todos los datos relativos a
una reserva, para ello le hay que pasar el codigo de la reserva. Luego la accion,
utilizando los DAOs pertinentes, recupera las lıneas de reserva, los datos de la
reserva y los datos de la factura. A continuacion lo encapsula todo en un objeto
’ReservaCompletaChunkVO’ y lo devuelve.
6.4. Arquitectura del Modelo 143
GetReservasAction Se encarga de recuperar los datos de las reservas de un cliente.
Para eso se le deben pasar el DNI del cliente, desde donde se desea recuperar
la lista de reservas y cuantas se quiere que se devuelvan.
Con estos datos, la accion consigue de la base de datos las reservas deseadas y
las encapsula en un objeto ’ReservasCollectionChunkVO’ que sera el que se le
pase a la capa superior, este objeto, como ya se ha mencionado antes, es el que
se utiliza para ’paginar’ una lista de resultados.
CheckDisponibleAction Esta accion es la encargada de comprobar si hay habita-
ciones libres para un rango de fechas determinado y para un tipo de habitacion.
Para esto se le debe pasar un objeto ’ReservaFromToTipoHabitacionChunkVO’
que contiene las fechas y el tipo de habitacion que se quiere comprobar.
La accion comprueba si para los dıas indicados existe alguna habitacion que no
este ocupada, de ser ası devuelve un valor de tipo ’boolean’ indicando que hay
al menos una habitacion disponible de ese tipo para esas fechas.
CheckDisponibleQuantityAction Esta accion es la encargada de comprobar si
hay habitaciones libres para un rango de fechas, para un tipo de habitacion y
una cantidad determinada. Para esto se le debe pasar un objeto ’ReservaFrom-
ToTipoHabitacionChunkVO’ que contiene las fechas, el tipo de habitacion que
se quiere comprobar y el numero de habitaciones que se desean.
La accion comprueba si para los dıas indicados existe el numero de habitaciones
indicado que no esten ocupadas, de ser ası devuelve un valor de tipo ’boolean’
indicando que hay al menos ese numero de habitaciones disponibles de ese tipo
para esas fechas.
CheckHabitacionesLibresAction Esta accion es la encargada de comprobar cuantas
habitaciones hay libres para un rango de fechas. Se le pasa una fecha de llegada
y una de salida.
6.4. Arquitectura del Modelo 144
Luego comprueba para todos los tipos de habitaciones cuantas hay libres para
esas fechas y devuelve un conjunto de tipos de habitacion y numero de habita-
ciones libres.
6.4.4.3. Gestion de Habitaciones
En esta seccion se mostrara como es el desarrollo de los casos de uso Gestion de Habita-
ciones. Como en los casos anteriores se utiliza el patron Session Facade para implementar
este subsistema.
De aquı en adelante se mostrara como se organizan las clases que forman este subsistema
y luego se aclarara el cometido que tiene cada una de ellas. En las figuras 6.37 y 6.38 se
muestra unos diagramas sencillos de la Gestion de Habitaciones.
6.4. Arquitectura del Modelo 145
<<interface>>HabitacionesFacade
+getRoom(number : Long) : HabitacionVO+getRoomsOfType(typeId : Long) : Collection+getRoomComplete(number : Long,startIndex : int,count : int) : HabitacionCompletaChunkVO+addRoom(habitacion : HabitacionVO,idTipo : Long) : HabitacionVO+updateRoom(habitacion : HabitacionVO,idTipo : Long) : HabitacionVO+addRoom(habitacion : HabitacionVO,tipoHabitacion : TipoHabitacionVO) : HabitacionCompletaChunkVO+updateRoom(habitacion : HabitacionVO,tipoHabitacion : TipoHabitacionVO) : HabitacionCompletaChunkVO+deleteRoom(number : Long) : void+getRooms(index : int,count : int) : HabitacionesCollectionChunkVO+addRoomType(tipoHabitacion : TipoHabitacionVO) : TipoHabitacionVO+updateRoomType(tipohabitacion : TipoHabitacionVO) : TipoHabitacionVO+getRoomType(typeId : Long) : TipoHabitacionVO+getAllRoomTypes() : Collection+addIncident(incidencia : IncidenciaVO,number : Long) : IncidenciaVO+getIncident(number : Long,idInc : Long) : IncidenciaVO+getAllIncidentsOfRoom(number : Long,index : int,count : int) : IncidenciasCollectionChunkVO
GeneralHabitacionesFacade
<<create>> +GeneralHabitacionesFacade()+addIncident(incidencia : IncidenciaVO,number : Long) : IncidenciaVO+addRoom(habitacion : HabitacionVO,idTipo : Long) : HabitacionVO+updateRoom(habitacion : HabitacionVO,idTipo : Long) : HabitacionVO+addRoom(habitacion : HabitacionVO,tipoHabitacion : TipoHabitacionVO) : HabitacionCompletaChunkVO+updateRoom(habitacion : HabitacionVO,tipoHabitacion : TipoHabitacionVO) : HabitacionCompletaChunkVO+addRoomType(tipoHabitacion : TipoHabitacionVO) : TipoHabitacionVO+updateRoomType(tipoHabitacion : TipoHabitacionVO) : TipoHabitacionVO+deleteRoom(number : Long) : void+getAllIncidentsOfRoom(number : Long,index : int,count : int) : IncidenciasCollectionChunkVO+getAllRoomTypes() : Collection+getRooms(index : int,count : int) : HabitacionesCollectionChunkVO+getIncident(number : Long,idInc : Long) : IncidenciaVO+getRoom(number : Long) : HabitacionVO+getRoomComplete(number : Long,startIndex : int,count : int) : HabitacionCompletaChunkVO+getRoomType(typeId : Long) : TipoHabitacionVO+getRoomsOfType(typeId : Long) : Collection
-dataSource : DataSource
<<realize>>
actions exceptionsvo
HabitacionCompletaChunkVO
HabitacionesCollectionChunkVO
IncidenciasCollectionChunkVO
Figura 6.37: Diagrama Simple de Gestion de Habitaciones
6.4. Arquitectura del Modelo 146
<<interface>>PlainAction
+execute(connection : Connection) : Object
<<interface>>NonTransactionalPlainAction
<<interface>>TransactionalPlainAction
AddIncidentAction
<<create>> +AddIncidentAction(incidencia : IncidenciaVO,number : Long)+execute(connection : Connection) : Object
AddRoomAction
<<create>> +AddRoomAction(habitacion : HabitacionVO,idTipo : Long)+execute(connection : Connection) : Object
AddRoomCompleteAction
<<create>> +AddRoomCompleteAction(habitacion : HabitacionVO,tipoHabitacion : TipoHabitacionVO)+execute(connection : Connection) : Object
AddRoomTypeAction
<<create>> +AddRoomTypeAction(tipoHabitacion : TipoHabitacionVO)+execute(connection : Connection) : Object
DeleteRoomAction
<<create>> +DeleteRoomAction(number : Long)+execute(connection : Connection) : Object
GetAllIncidentsOfRoomAction
<<create>> +GetAllIncidentsOfRoomAction(number : Long,index : int,count : int)+execute(connection : Connection) : Object
GetAllRoomsAction
<<create>> +GetAllRoomsAction(index : int,count : int)+execute(connection : Connection) : Object
GetAllRoomTypesAction
<<create>> +GetAllRoomTypesAction()+execute(connection : Connection) : Object
GetIncidentAction
<<create>> +GetIncidentAction(number : Long,idInc : Long)+execute(connection : Connection) : Object
GetRoomAction
<<create>> +GetRoomAction(number : Long)+execute(connection : Connection) : Object
GetRoomCompleteAction
<<create>> +GetRoomCompleteAction(number : Long,startIndex : int,count : int)+execute(connection : Connection) : Object
GetRoomsOfTypeAction
<<create>> +GetRoomsOfTypeAction(idTipo : Long)+execute(connection : Connection) : Object
GetRoomTypeAction
<<create>> +GetRoomTypeAction(idTipo : Long)+execute(connection : Connection) : Object
UpdateRoomAction
<<create>> +UpdateRoomAction(habitacion : HabitacionVO,idTipo : Long)+execute(connection : Connection) : Object
UpdateRoomCompleteAction
<<create>> +UpdateRoomCompleteAction(habitacion : HabitacionVO,tipoHabitacion : TipoHabitacionVO)+execute(connection : Connection) : Object
UpdateRoomTypeAction
<<create>> +UpdateRoomTypeAction(tipoHabitacion : TipoHabitacionVO)+execute(connection : Connection) : Object
Figura 6.38: Actions de Gestion de Habitaciones
6.4. Arquitectura del Modelo 147
Al igual que en los subsistemas anteriores, en este se vuelven a utilizar los patrones
Session Facade y Business Delegate. La interfaz para acceder a este subsistema es Habita-
cionesFacade, implementado por GeneralHabitacionesFacade. Al igual que en los Session
Facade anteriores, los metodos de la fachada delegan su funcionamiento en las acciones
del subpaquete Actions. A continuacion se explicara el funcionamiento de cada una de las
acciones.
Ademas de usar unas acciones para implementar sus metodos, esta fachada tambien
lanzara CustomException para proporcionar informacion a las capas superiores acerca del
estado con el que finalizo la operacion. En este caso se usaran excepciones para informar
si algo que se desea insertar ya existe o si lo que se quiere recuperar no se encuentra.
Al igual que el caso de la Gestion de Reserva, esta fachada tambien manejara unos
objetos especiales, los Custom Value Objects. Este tipo de objetos, cuyo uso y cometido ya
se ha mencionado en la explicacion del subsistema anterior, se encontraran en el subpaquete
’vo’.
Las acciones en base a las cuales se implementan las operaciones de HabitacionesFacade,
se podran clasificar como transaccionales y no transaccionales como ocurrıan en los demas
subsistemas. Estas acciones se explicaran a continuacion muy brevemente debido a que no
implementan procesos complejos:
AddRoomTypeAction Esta accion se encarga de crear un nuevo tipo de habita-
cion. Para ello se le pasan los datos del nuevo tipo de habitacion y utilizando
los DAOs pertinentes inserta el nuevo tipo en la base de datos.
AddRoomAction Al igual que la accion anterior, se encarga de crear una nueva
habitacion. Para esto necesita que se le pasen los datos de la habitacion y el
tipo de habitacion al que pertenecera.
Primero se comprueba que el tipo de habitacion exista, si existe se guardan los
datos de la nueva habitacion, y sino se lanza una exepcion indicando que el tipo
de habitacion no se ha encontrado.
6.4. Arquitectura del Modelo 148
AddRoomCompleteAction A veces puede que se quiera crear una habitacion y
el tipo de habitacion en el mismo momento. Esta accion da soporte para que
eso se pueda realizar. Como se puede adivinar, en este caso se necesitaran los
datos de la habitacion y del tipo de habitacion.
Primero se intenta crear el tipo de habitacion, si el tipo existe, se lanza una
excepcion para indicarlo, y sino, se procede a insertar los datos de la nueva
habitacion.
AddIncidentAction Si ocurriese algun percance en una de las habitaciones habrıa
que registrarlo, esta accion permite guardar un incidente y relacionarlo con una
habitacion. Para realizarlo se le deben pasar los datos del incidente y el numero
de habitacion en la que ha ocurrido.
Luego utilizando los DAOs necesarios inserta el nuevo incidente en la base de
datos.
UpdateRoomTypeAction Se encarga de actualizar los datos de un tipo de habi-
tacion. Se le deben indicar los nuevos datos.
Primero se recuperan los datos almacenados, luego se comparan con los datos
antiguos y solo se actualizan los que difieran.
UpdateRoomAction Se encarga de actualizar los datos de una habitacion. Se le
deben indicar los nuevos datos y el nuevo tipo de habitacion.
Primero se recuperan los datos almacenados, luego se comprueba si se debe
actualizar el tipo de habitacion, y a continuacion se comparan los nuevos datos
con los antiguos y solo se actualizan los que difieran.
UpdateRoomAction Se encarga de actualizar los datos de una habitacion y de
crear un nuevo tipo de habitacion para esta. Se le deben indicar los nuevos
datos de la habitacion y los del tipo de habitacion.
6.4. Arquitectura del Modelo 149
Primero se recuperan los datos almacenados, luego se crea el nuevo tipo de
habitacion, y a continuacion se comparan los nuevos datos con los antiguos y
solo se actualizan los distintos.
DeleteRoomAction Esta accion es la encargada de eliminar una habitacion de la
base de datos. Simplemente le hay que pasar el numero de la habitacion que se
quiere borrar. Si la habitacion no existe se lanza una excepcion indicandolo, y
sino se utiliza el DAO pertinente para eliminarla.
GetAllIncidentsOfRoomAction Con esta accion se permite recuperar una lista
de los incidentes de una habitacion. Para ello hay que pasarle el numero de
habitacion de la cual se desean los incidentes, desde donde se quiere que se
recuperen y la cantidad.
A continuacion la accion recupera los datos a traves de los DAOs y los encapsula
en un Custom Value Object, de esta forma, como ya se ha visto con las reservas,
se consigue una paginacion de los resultados.
GetIncidentAction Esta accion es la encargada recuperar los datos de un inci-
dente. Para ello se le debe pasar la habitacion donde tuvo lugar y el numero de
incidente. Con estos datos lo recupera y lo devuelve.
GetAllRoomTypesAction Con esta accion se permite recuperar una lista de los
tipos de habitacion.
La accion simplemente recupera todos los tipos de habitacion y los devuelve a
traves de un objeto Collection. Esta vez no necesitan ser paginados porque se
estiman pocos y se puede permitir enviarlos todos juntos.
GetRoomTypeAction Esta accion se encarga de recuperar los datos de un tipo
de habitacion. Para ello hay que pasarle el identificador del tipo de habitacion
del que se quieren los datos. La accion recupera los datos mediante los DAOs
pertinentes y los devuelve.
6.4. Arquitectura del Modelo 150
GetAllRoomsAction Con esta accion se permite recuperar una lista de las ha-
bitaciones. Para esto la accion necesita que se le pase desde donde necesita la
lista y la cantidad de habitaciones que se desean ver.
La accion simplemente recupera todos las habitaciones y las devuelve a traves
de un objeto HabitacionesCollectionChunkVO, para que luego pueda realizarse
una paginacion del resultado.
GetRoomAction Esta accion se encarga de recuperar los datos de una habitacion.
Para ello hay que pasarle el numero de la habitacion de la que se quieren
los datos. La accion recupera los datos mediante los DAOs pertinentes y los
devuelve.
GetRoomCompleteAction Esta accion se encarga de recuperar los datos de una
habitacion, las incidencias y los datos del tipo de habitacion. Para ello hay que
pasarle el numero de la habitacion de la que se quieren los datos.
La accion recupera los toda la informacion requerida mediante los DAOs que
correspondan y lo devuelve todo encapsulado en un Costum Value Object.
GetRoomsOfTypeAction Esta accion se encarga de recuperar todas las habita-
ciones que pertenecen a un tipo de habitacion. Para ello se le pasa el identifi-
cador del tipo de habitacion.
La accion recupera todas las habitaciones del tipo de habitacion indicado y las
devuelve todas juntas utilizando un objeto Collection.
6.4.4.4. Gestion de Ofertas
En esta seccion se mostrara como es el desarrollo de los casos de uso Gestion de Ofertas.
Como en los subsistemas anteriores se utilizan los patrones Session Facade y Business
Delegate para desarrollarlo
De aquı en adelante se mostrara como se organizan las clases que forman este subsistema
y luego se aclarara el cometido que tiene cada una de ellas. El subsistema se divide en dos
6.4. Arquitectura del Modelo 151
fachadas, una en la que se manejan los tipos de oferta, y otra en la cual se gestionan las
ofertas. En las figuras 6.39 y 6.40 se observa como se organizan las clases de la Session
Facade que gestiona los tipos de oferta, y en las figuras 6.41 y 6.42 se muestra unos
diagramas sencillos de la Gestion de Ofertas.
<<interface>>TipoOfertaFacade
+crearTipoOferta(tipoOfertaVO : TipoOfertaVO) : TipoOfertaVO+crearIncompatibleCon(incompatibleConVO : IncompatibleConVO) : IncompatibleConVO+existsIncompatibleCon(incompatibleConVO : IncompatibleConVO) : Boolean+borrarIncompatibleCon(incompatibleConVO : IncompatibleConVO) : void+crearTipoOferta(tipoOfertaVO : TipoOfertaVO,colAplicableAVO : Collection,colIncompatibleConVO : Collection) : TipoOfertaVO+borrarTipoOferta(idTipoOferta : Long) : void+cambiarTipoOferta(tipoOfertaVO : TipoOfertaVO) : TipoOfertaVO+cambiarTipoOferta(tipoOfertaVO : TipoOfertaVO,colAplicableAVO : Collection,colIncompatibleConVO : Collection) : TipoOfertaVO+recuperarTipoOferta(idTipoOferta : Long) : TipoOfertaVO+recuperarTipoOfertas(startIndex : int,count : int) : Collection+recuperarIncompatibleConA(idTipo : Long,startIndex : int,count : int) : Collection+recuperarAplicableA(idTipo : Long,startIndex : int,count : int) : Collection
GeneralTipoOfertaFacade
<<create>> +GeneralTipoOfertaFacade()+borrarTipoOferta(idTipoOferta : Long) : void+cambiarTipoOferta(tipoOfertaVO : TipoOfertaVO) : TipoOfertaVO+crearTipoOferta(tipoOfertaVO : TipoOfertaVO) : TipoOfertaVO+crearTipoOferta(tipoOfertaVO : TipoOfertaVO,colAplicableAVO : Collection,colIncompatibleConVO : Collection) : TipoOfertaVO+recuperarTipoOferta(idTipoOferta : Long) : TipoOfertaVO+recuperarTipoOfertas(startIndex : int,count : int) : Collection+cambiarTipoOferta(tipoOfertaVO : TipoOfertaVO,colAplicableAVO : Collection,colIncompatibleConVO : Collection) : TipoOfertaVO+crearIncompatibleCon(incompatibleConVO : IncompatibleConVO) : IncompatibleConVO+borrarIncompatibleCon(incompatibleConVO : IncompatibleConVO) : void+existsIncompatibleCon(incompatibleConVO : IncompatibleConVO) : Boolean+recuperarIncompatibleConA(idTipo : Long,startIndex : int,count : int) : Collection+recuperarAplicableA(idTipo : Long,startIndex : int,count : int) : Collection
-dataSource : DataSource
<<realize>>
actions
Figura 6.39: Diagrama Simple de Gestion de Tipos de Ofertas
6.4. Arquitectura del Modelo 152
<<interface>>PlainAction
+execute(connection : Connection) : Object
<<interface>>NonTransactionalPlainAction
<<interface>>TransactionalPlainAction
BorrarIncompatibleConAction
<<create>> +BorrarIncompatibleConAction(incompatibleConVO : IncompatibleConVO)+execute(connection : Connection) : Object
BorrarTipoOfertaAction
<<create>> +BorrarTipoOfertaAction(idTipoOferta : Long)+execute(connection : Connection) : Object
CambiarTipoOfertaAction
<<create>> +CambiarTipoOfertaAction(tipoOfertaVO : TipoOfertaVO)+execute(connection : Connection) : Object
CambiarTipoOfertaCompletaAction
<<create>> +CambiarTipoOfertaCompletaAction(tipoOfertaVO : TipoOfertaVO,colAplicableAVO : Collection,colIncompatibleConVO : Collection)-isPetitionCongruent() : boolean+execute(connection : Connection) : Object
CrearIncompatibleConAction
<<create>> +CrearIncompatibleConAction(incompatibleConVO : IncompatibleConVO)+execute(connection : Connection) : Object
CrearTipoOfertaAction
<<create>> +CrearTipoOfertaAction(tipoOfertaVO : TipoOfertaVO)+execute(connection : Connection) : Object
CrearTipoOfertaCompletaAction
<<create>> +CrearTipoOfertaCompletaAction(tipoOfertaVO : TipoOfertaVO,colAplicableAVO : Collection,colIncompatibleConVO : Collection)-isPetitionCongruent() : boolean+execute(connection : Connection) : Object
ExistsIncompatibleConAction
<<create>> +ExistsIncompatibleConAction(incompatibleConVO : IncompatibleConVO)+execute(connection : Connection) : Object
RecuperarAplicableAAction
<<create>> +RecuperarAplicableAAction(idTipo : Long,startIndex : int,count : int)+execute(connection : Connection) : Object
RecuperarIncompatibleConAAction
<<create>> +RecuperarIncompatibleConAAction(idTipo : Long,startIndex : int,count : int)+execute(connection : Connection) : Object
RecuperarTipoOfertaAction
<<create>> +RecuperarTipoOfertaAction(idTipoOferta : Long)+execute(connection : Connection) : Object
RecuperarTipoOfertasAction
<<create>> +RecuperarTipoOfertasAction(startIndex : int,count : int)+execute(connection : Connection) : Object
Figura 6.40: Actions de Gestion de Tipos de Ofertas
6.4. Arquitectura del Modelo 153
Este Session Facade es el encargado de manejar la creacion, recuperacion y consulta
de los tipos de oferta. La interfaz de esta fachada es TipoOfertaFacade y el Business
Delegate que la implemente es GeneralTipoOfertaFacade. Al igual que en los Session
Facade anteriores, los metodos de la fachada delegan su funcionamiento en las acciones
del subpaquete Actions que se explicaran a continuacion.
Las acciones en base a las cual se implementan las operaciones de TipoOfertasFacade,
se podran clasificar como transaccionales y no transaccionales. Ademas, a diferencia de
otros Session Facade, estas acciones son algo mas complejas, debido a que hay que tener
especial cuidado con que la base de datos de ofertas no quede en un estado inconsistente.
En los siguientes puntos se aclara el funcionamiento de cada una de las acciones de esta
fachada:
CrearTipoOfertaAction Esta accion se encarga de crear un nuevo tipo de oferta.
Para ello se le pasan los datos del nuevo tipo de oferta y utilizando los DAOs
pertinentes, primero comprueba que el tipo de oferta no existe y luego inserta
el nuevo tipo en la base de datos.
CrearIncompatibleConAction Esta accion sera la encargada de crear una in-
compatibilidad entre dos tipos de oferta. Para ello se le pasa un objeto que
contiene los identificadores de los dos tipos que son incompatibles. La incompa-
tibilidad es recıproca, es decir, si A es incompatible con B entonces B tambien
es incompatible con A.
A continuacion se comprueba que la incompatibilidad no existe, en ese caso se
inserta la nueva utilizando IncompatibleConDAO, sino simplemente no se hace
nada.
CrearTipoOfertaCompletaAction A veces puede que se quiera crear un tipo de
oferta, sus incompatibilidades y a que sera aplicable, en el mismo momento.
Esta accion da soporte para que eso se pueda realizar. Como se puede adivinar,
en este caso se necesitaran los datos del tipo de oferta, pero ademas tambien
6.4. Arquitectura del Modelo 154
se necesitara un conjunto de todas las incompatibilidades que se deseen crear,
y otro que contenga todos aquellos productos a los que se podra aplicar el tipo
de oferta.
Primero se comprueba que todos los datos recibidos sean congruentes, por ejem-
plo, que el identificador del tipo de oferta que se quiere crear sea uno de cada
una de las parejas de identificadores del conjunto de incompatibilidades.
Una vez realizadas las comprobaciones pertinentes, se chequea si el tipo de
oferta ya existe, si es ası, se anaden las incompatibilidades y los productos a
los que se aplicara (siempre y cuando no esten ya en la base de datos), sino se
crea el nuevo tipo y todas sus relaciones.
CambiarTipoOfertaAction Esta accion permite modificar los datos de un tipo
de oferta. Para eso le hay que pasar los nuevos datos del tipo de oferta.
La accion, comprueba que el tipo de oferta exista, de ser ası recupera la infor-
macion antigua, la compara con los nuevos datos y actualiza aquellos que se
han cambiado.
CambiarTipoOfertaCompletaAction Al igual que CambiarTipoOfertaAction,
permite cambiar los datos de un tipo de oferta, pero en este caso tambien se
permitira cambiar las incompatibilidades y los productos a los que es aplicable
el tipo de oferta.
Del mismo modo que CrearTipoOfertaCompletaAction, esta accion recibe los
mismos parametros y comprueba que la peticion sea congruente, luego recupera
los todos datos antiguos y actualiza aquellos que han sido modificados. En el
caso de las incompatibilidades, se crean aquellas que no existan, y si alguna de
las existente ya no es necesaria, entonces se elimina.
BorrarIncompatibleConAction Es la accion encargada de eliminar una incom-
patibilidad entre tipos de oferta. Para ello se le pasa un objeto VO que contiene
los identificadores de los tipos incompatibles que se desean borrar.
6.4. Arquitectura del Modelo 155
La accion busca la incompatibilidad en ambos sentidos, A con B y B con A, y
si las encuentra las elimina.
BorrarTipoOfertaAction Se encarga de borrar un tipo de oferta. Para realizar
esta operacion la accion simplemente necesita el identificador del tipo de oferta,
lo busca en la base de datos y todas sus incompatibilidades. Una vez que ha
recuperado todos los datos entonces los elimina.
ExistsIncompatibleConAction Esta accion es la encargada de chequear si existe
una incompatibilidad entre dos tipos de oferta. Para hacer esta comprobacion
necesita que se le pase un objeto VO con los dos identificadores que se desean
buscar. Devuelve el resultado a traves de un objeto ’boolean’.
RecuperarAplicableAAction Se encarga de recuperar todos los productos a los
cuales se puede aplicar un tipo de oferta. Para ello le hay que proporcionar el
identificador del tipo de oferta.
La accion busca los datos solicitados y devuelve un objeto ’Collection’ con la
informacion requerida.
RecuperarIncompatibleConAAction Se encarga de recuperar todos los tipos
de oferta que son incompatibles con el tipo que se indica. Para ello le hay que
proporcionar el identificador del tipo de oferta.
La accion busca los tipos de oferta que son incompatibles con el indicado y
devuelve un objeto ’Collection’ con la informacion requerida.
RecuperarTipoOfertaAction Con esta accion se permite recuperar los datos de
un tipo de oferta. Para ello se le especifica el identificador del tipo.
La accion simplemente recupera los datos del tipo de oferta solicitado y los
devuelve a mediante un objeto TipoOfertaVO.
RecuperarTipoOfertasAction Esta accion se encarga de recuperar todos los ti-
pos de oferta, desde una posicion determinada y la cantidad que se solicite.
6.4. Arquitectura del Modelo 156
Para ello se le indica la posicion desde la que se desea comenzar a recuperar y
la cantidad de tipos que se quieren.
La accion recupera todos los tipos requeridos y los devuelve en un objeto ’Co-
lleciton’.
<<interface>>OfertaFacade
+crearOferta(ofertaVO : OfertaVO) : OfertaVO+crearOferta(ofertaVO : OfertaVO,tipoOfertaVO : TipoOfertaVO,colAplicableAVO : Map,colIncompatibleConVO : Collection) : OfertaVO+borrarOferta(idOferta : Long) : void+cambiarOferta(ofertaVO : OfertaVO) : OfertaVO+cambiarOferta(ofertaVO : OfertaVO,tipoOfertaVO : TipoOfertaVO,colAplicableAVO : Collection,colIncompatibleConVO : Collection) : OfertaVO+recuperarOferta(idOferta : Long) : OfertaVO+getOfertaCompleta(idOferta : Long) : OfertaCompletaChunkVO+publicarOferta(idOferta : Long,publicar : Boolean) : void+recuperarOfertasPorTipo(idOferta : Long,startIndex : int,count : int) : Collection+recuperarOfertasActuales(startIndex : int,count : int) : Collection+recuperarOfertasBorradores(startIndex : int,count : int) : Collection+recuperarOfertasPublicadas(startIndex : int,count : int) : Collection+recuperarOfertas(startIndex : int,count : int) : OfertasCollectionChunkVO+CalcularDescuento(dniPasPersona : String,ofertables : Collection) : Collection
GeneralOfertaFacade
<<create>> +GeneralOfertaFacade()+CalcularDescuento(dniPasPersona : String,ofertables : Collection) : Collection+borrarOferta(idOferta : Long) : void+cambiarOferta(ofertaVO : OfertaVO) : OfertaVO+crearOferta(ofertaVO : OfertaVO) : OfertaVO+crearOferta(ofertaVO : OfertaVO,tipoOfertaVO : TipoOfertaVO,colAplicableAVO : Map,colIncompatibleConVO : Collection) : OfertaVO+recuperarOferta(idOferta : Long) : OfertaVO+getOfertaCompleta(idOferta : Long) : OfertaCompletaChunkVO+publicarOferta(idOferta : Long,publicar : Boolean) : void+recuperarOfertas(startIndex : int,count : int) : OfertasCollectionChunkVO+recuperarOfertasActuales(startIndex : int,count : int) : Collection+recuperarOfertasBorradores(startIndex : int,count : int) : Collection+recuperarOfertasPorTipo(idTipo : Long,startIndex : int,count : int) : Collection+recuperarOfertasPublicadas(startIndex : int,count : int) : Collection+cambiarOferta(ofertaVO : OfertaVO,tipoOfertaVO : TipoOfertaVO,colAplicableAVO : Collection,colIncompatibleConVO : Collection) : OfertaVO
-dataSource : DataSource
<<realize>>
actions vo
<<interface>>OfertaCompletaChunkVO GeneralOfertaCompletaChunkVO
<<realize>>
OfertasCollectionChunkVO
Figura 6.41: Diagrama Simple de Gestion de Ofertas
6.4. Arquitectura del Modelo 157
<<interface>>PlainAction
+execute(connection : Connection) : Object
<<interface>>NonTransactionalPlainAction
<<interface>>TransactionalPlainAction
CrearOfertaAction
<<create>> +CrearOfertaAction(ofertaVO : OfertaVO)+execute(connection : Connection) : Object
CrearOfertaCompletaAction
<<create>> +CrearOfertaCompletaAction(ofertaVO : OfertaVO,tipoOfertaVO : TipoOfertaVO,colAplicableAVO : Map,colIncompatibleConVO : Collection)-isPetitionCongruent() : boolean-createNecesaryCollections(id : Long) : void+execute(connection : Connection) : Object
CambiarOfertaAction
<<create>> +CambiarOfertaAction(ofertaVO : OfertaVO)+execute(connection : Connection) : Object
BorrarOfertaAction
<<create>> +BorrarOfertaAction(idOferta : Long)+execute(connection : Connection) : Object
PublicarOfertaAction
<<create>> +PublicarOfertaAction(idOferta : Long,publicar : Boolean)+execute(connection : Connection) : Object
CalcularDescuentoAction
<<create>> +CalcularDescuentoAction(dniPasPersona : String,ofertableCollection : Collection)+execute(connection : Connection) : Object
RecuperarOfertaAction
<<create>> +RecuperarOfertaAction(idOferta : Long)+execute(connection : Connection) : Object
RecuperarOfertasAction
<<create>> +RecuperarOfertasAction(startIndex : int,count : int)+execute(connection : Connection) : Object
RecuperarOfertasActualesAction
<<create>> +RecuperarOfertasActualesAction(startIndex : int,count : int)+execute(connection : Connection) : Object
RecuperarOfertasBorradoresAction
<<create>> +RecuperarOfertasBorradoresAction(startIndex : int,count : int)+execute(connection : Connection) : Object
RecuperarOfertasPorTipoAction
<<create>> +RecuperarOfertasPorTipoAction(idTipo : Long,startIndex : int,count : int)+execute(connection : Connection) : Object
RecuperarOfertasPublicadasAction
<<create>> +RecuperarOfertasPublicadasAction(startIndex : int,count : int)+execute(connection : Connection) : Object
Figura 6.42: Actions de Gestion de Ofertas
6.4. Arquitectura del Modelo 158
La interfaz de este Session Facade es OfertasFacade, implementado por el Business
Delegate GeneralOfertasFacade. Al igual que en los Session Facade anteriores, los metodos
de la fachada delegan su funcionamiento en las acciones del subpaquete Actions que se
explicaran a continuacion.
Para implementar algunas de las acciones de esta fachada hubo que realizar un siste-
ma aparte que se puede ver a grandes rasgos en la figura 6.49 de la seccion 6.4.5. Este
sistema sera el encargado de realizar las operaciones relativas al calculo de descuentos
proporcionados por las ofertas que actualmente estan en vigor. En la seccion 6.4.5 se ex-
plicara en detalle el funcionamiento de este sistema, sus principales tareas, y como estan
implementadas.
Esta fachada tambien manejara unos objetos especiales, los Custom Value Objects. Este
tipo de objetos, cuyo uso y cometido ya se ha mencionado en la explicacion de subsistemas
anteriores, se encontraran en el subpaquete ’vo’. Cabe destacar el OfertaCompletaChunk-
VO ya que no es un Value Object puro, a este VO es una interfaz implementada por
GeneralOfertaCompletaChunkVO a la cual no hace falta pasarle todos los atributos al
constructor, sino que a partir de los datos de una oferta (OfertaVO) se encarga de acceder
a la base de datos mediante los DAO y recuperar las incompatibilidades y demas datos
que se encapsulan. Luego proporciona metodos de lectura y escritura como cualquier Value
Object.
Las acciones en base a las cual se implementan las operaciones de HabitacionesFacade,
se podran clasificar como transaccionales y no transaccionales como ocurrıa en los demas
subsistemas. Estas acciones son las que se comentan a continuacion:
CrearOfertaAction Esta accion se encarga de crear una nueva oferta. Para ello se
le pasan los datos de la nueva oferta y utilizando los DAOs pertinentes inserta
su informacion en la base de datos.
CrearOfertaCompletaAction Al igual que la accion anterior, se encarga de crear
una nueva oferta, pero en algunas ocasiones sera necesario crear la oferta y el
6.4. Arquitectura del Modelo 159
tipo de oferta en el mismo momento, incluyendo las incompatibilidades del tipo
de oferta y los productos a los que se puede aplicar. Para esto necesita que se
le pasen los datos de la oferta, la informacion del nuevo tipo de oferta, los tipos
con los cuales este es incompatible y los productos a los cuales se podra aplicar.
Primero se comprueba que los datos sean congruentes, del mismo modo que se
hacıa en CrearTipoOfertaCompletaAction. Luego se insertan todos los datos
nuevos en la base de datos, en el caso de que algun dato ya exista simplemente
se actualiza su informacion.
CambiarOfertaAction Esta accion es la encargada de modificar los datos de una
oferta. Para ellos se le pasan los nuevos datos de la oferta.
A continuacion se buscan los datos antiguos de la oferta y se comparan con la
nueva informacion proporcionada, en los casos en que no coincidan se actualizan
en la base de datos.
BorrarOfertaAction Se encarga de borrar una oferta. Le hay que proporcionar el
identificador de la oferta que se quiere eliminar y mediante los DAO correspon-
dientes se elimina de la base de datos
PublicarOfertaAction Se encarga de publicar o dar de baja una oferta. El me-
canismo de dar de baja se proporciona por si en algun momento se publica
una oferta que va en contra de los intereses del negocio. A esta accion hay que
pasarle el identificador de la oferta y un objeto de tipo ’boolean’ indicando si
se desea publicar o no la oferta.
A traves de los DAO necesarios esta accion actualiza esta informacion en la
base de datos.
CalcularDescuentoAction Es la encargada de, a partir de un conjunto de pro-
ductos, calcular el mejor descuento que puedan proporcionar las ofertas que se
puedan aplicar a esos productos.
6.4. Arquitectura del Modelo 160
Para dar soporte a esta accion y al proceso que debe realizar se define una
interfaz que deben implementar todos aquellos productos a los que se les pueda
hacer algun tipo de descuento. Esta interfaz es la interfaz Ofertable, se puede
ver en la figura 6.43 y otra que a partir de un conjunto de objetos Ofertable los
divide en subconjuntos segun el tipo de producto que definan, esta es la interfaz
OfertableCollectionChunkVO tambien presente en la figura 6.43
<<interface>>Ofertable
+getTipo() : String+getSubTipo() : String+getDescuento() : double+setDescuento(descuento : double) : void+getImporte() : double+getWrapped() : Object+getQuantity() : double+getDayBegin() : int+getMonthBegin() : int+getYearBegin() : int+getDayEnd() : int+getMonthEnd() : int+getYearEnd() : int+getDateBegin() : Calendar+getDateEnd() : Calendar
<<interface>>OfertableCollectionChunkVO
+getDescuento() : double+setDescuento(descuento : double) : void+getTipoOfertable() : String+getCantidad() : double+extractOfertableCollection() : Collection+acumulateDiscount(discount : Double) : void
GeneralOfertableCollectionChunkVO
<<create>> +GeneralOfertableCollectionChunkVO(c : Collection,muestra : Ofertable)+getDescuento() : double+getTipoOfertable() : String+setDescuento(descuento : double) : void+getCantidad() : double+extractOfertableCollection() : Collection+acumulateDiscount(discount : Double) : void
-collectionDeT : Collection-tipoOfertable : String-descuento : double-cantidad : double
<<realize>>
0..* 1
Figura 6.43: Diagrama de la Interfaz Ofertable
Esta accion necesita recibir el DNI o Pasaporte del cliente para el que se destina
el calculo del descuento, y un conjunto de objetos Ofertable que definan todos
los objetos sobre los cuales se haran los calculos para el descuento.
Una vez se tienen todos estos datos, se delega la operacion en el metodo ’Cal-
cularMejorPara’ del calculador de ofertas definido en el sistema de ofertas. El
funcionamiento de este sistema se muestra en detalle en la seccion 6.4.5
RecuperarOfertaAction Se encarga de recuperar los datos de una oferta. Se le
debe pasar el identificador de la oferta.
A continuacion la accion recupera los datos de la oferta solicitada y los devuelve,
en caso de que la oferta que se pida no exista se lanza una excepcion.
6.4. Arquitectura del Modelo 161
RecuperarOfertasAction Esta accion es la encargada de recuperar una lista de
todas las ofertas. Para llevar a cabo esta accion, necesita que le pasen desde
donde se quiere recuperar y la cantidad de ofertas que se desean.
Luego la accion, a traves de los DAO correspondientes, recoge las ofertas solici-
tadas y las devuelve encapsuladas en un Custom Value Object preparado para
realizar paginacion.
RecuperarOfertasActualesAction Con esta accion se permite recuperar una lis-
ta de las ofertas que se aplican actualmente. Para ello necesita que se le pase
desde donde se quieren recuperar las ofertas y la cantidad.
A continuacion la accion recupera los datos a traves de los DAOs y los encapsula
en un Custom Value Object, de esta forma, como ya se ha visto, se consigue
una paginacion de los resultados.
RecuperarOfertasBorradoresAction Esta accion permite recuperar una lista
de las ofertas que aun estan como borradores. Para ello necesita que se le pase
desde donde se quieren recuperar las ofertas y la cantidad.
A continuacion la accion recupera los datos a traves de los DAOs y los encapsula
en un Custom Value Object, para conseguir una paginacion de los resultados.
RecuperarOfertasPublicadasAction Permite recuperar una lista de las ofertas
que aun estan actualmente publicadas. Para ello necesita que se le pase desde
donde se quieren recuperar las ofertas y la cantidad.
A continuacion la accion recupera los datos a traves de los DAOs y los encapsula
en un Custom Value Object, para conseguir una paginacion de los resultados.
RecuperarOfertasPorTipoAction Esta accion se encarga de recuperar todas las
ofertas de un mismo tipo de oferta. Para realizarlo necesita que se le pase desde
donde se quieren recuperar las ofertas y la cantidad.
Luego se recuperan los datos de las ofertas del tipo solicitado y se devuelven
encapsuladas en un Custom Value Object, para que puedan ser paginados.
6.4. Arquitectura del Modelo 162
6.4.4.5. Gestion de Facturas
En esta seccion se mostrara como es el desarrollo de los casos de uso de Gestion de
Facturas. Como en los casos anteriores se utiliza el patron Session Facade y Business
Delegate para implementar este subsistema.
Entre las operaciones de este sistema cabe destacar que debe permitir consultar un
borrador de una factura antes de pagarla; pagar una factura en dos pasos, uno para
marcar la factura como en proceso de pago y otro para marcarla como pagada; tambien
ofrecera una operacion para cancelar una reserva, calculando el recargo de tal operacion
si la factura ya estaba pagada.
De aquı en adelante se mostrara como se organizan las clases que forman este subsistema
y luego se aclarara el cometido que tiene cada una de ellas. En las figuras 6.44 y 6.45 se
muestra unos diagramas sencillos de la Gestion de Facturas.
<<interface>>FacturasFacade
+calculateBillDraft(idBill : Long) : FacturaVO+getBillsBetweenDates(fechaInicio : Calendar,fechaFin : Calendar,startIndex : int,count : int) : Collection+getBill(idFactura : Long,startIndex : int,count : int) : FacturaCompletaChunkVO+payBill(codFactura : Long) : void+paymentConfirmation(codFactura : Long) : void+setBillAsPayed(codFactura : Long) : void+getImporteADevolverCancelacion(codReserva : Long) : void+cancelarReserva(codReserva : Long) : double
GeneralFacturasFacade
<<create>> +GeneralFacturasFacade()+calculateBillDraft(idBill : Long) : FacturaVO+getBill(idFactura : Long,indexProd : int,count : int) : FacturaCompletaChunkVO+getBillsBetweenDates(fechaInicio : Calendar,fechaFin : Calendar,startIndex : int,count : int) : Collection+payBill(codBill : Long) : void+paymentConfirmation(codBill : Long) : void+setBillAsPayed(codBill : Long) : void+getImporteADevolverCancelacion(codReserva : Long) : void+cancelarReserva(codReserva : Long) : double
-dataSource : DataSource
<<realize>>
actions exceptionsvo
FacturaCompletaChunkVO
Figura 6.44: Diagrama Simple de Gestion de Facturas
6.4. Arquitectura del Modelo 163
<<interface>>NonTransactionalPlainAction
<<interface>>PlainAction
+execute(connection : Connection) : Object
<<interface>>TransactionalPlainAction
CalcularBorradorFacturaAction
<<create>> +CalcularBorradorFacturaAction(idFactura : Long)+execute(connection : Connection) : Object
CancelarReservaAction
<<create>> +CancelarReservaAction(codReserva : Long)+execute(connection : Connection) : Object-calculaDevolucionDe(c : Connection,linea : LineaDeReservaVO) : double
GetFacturaAction
<<create>> +GetFacturaAction(idFactura : Long,startIndex : int,count : int)+execute(connection : Connection) : Object
GetFacturasEntreFechasAction
<<create>> +GetFacturasEntreFechasAction(fechaInicio : Calendar,fechaFin : Calendar,startIndex : int,count : int)+execute(connection : Connection) : Object
GetImporteADevolverCancelacionAction
<<create>> +GetImporteADevolverCancelacionAction(codReserva : Long)+execute(connection : Connection) : Object-calculaDevolucionDe(c : Connection,linea : LineaDeReservaVO) : double
PayBillAction
<<create>> +PayBillAction(codBill : Long)+execute(connection : Connection) : Object
PaymentConfirmationAction
<<create>> +PaymentConfirmationAction(codBill : Long)+execute(connection : Connection) : Object
SetBillAsPayedAction
<<create>> +SetBillAsPayedAction(codBill : Long)+execute(connection : Connection) : Object
Figura 6.45: Actions y Exceptions de Gestion de Facturas
En estos diagramas se puede ver como se vuelven a usar los patrones Session Facade
y Business Delegate. La interfaz para acceder a este subsistema es FacturasFacade, im-
plementado por GeneralFacturasFacade. Al igual que en el Session Facade anterior, los
metodos de la fachada delegan su funcionamiento en las acciones correspondientes del
subpaquete Actions. A continuacion se explicara el funcionamiento de cada una de las
acciones.
Ademas de usar unas acciones para implementar sus metodos, esta fachada tambien
lanza CustomException para proporcionar informacion a las capas superiores acerca del
estado con el que finalizo la operacion. En este caso se usaran excepciones para informar
si se ha podido realizar correctamente el pago de una factura y si se ha podido cancelar
una reserva.
6.4. Arquitectura del Modelo 164
Por otro lado, esta fachada manejara un objeto especiale, un Custom Value Object.
Estes objeto estara localizado en el subpaquete ’vo’ y tendran como cometido ofrecer a las
capas superiores un conjunto de los atributos de varios VO ya existentes. En este caso se
usara para encapsular una factura y todas sus lıneas de reserva.
Las acciones en base a las cuales se implementan las operaciones de FacturasFacade,
tambien podran clasificarse como transaccionales y no transaccionales dependiendo si es
necesario que la operacion se realice de forma atomica o no, y son las siguientes:
CalcularBorradorFacturaAction Esta accion es la encargada de calcular el im-
porte final que se debe pagar en una factura, teniendo en cuenta los descuentos
que puedan proporcionar las ofertas. Para esto necesita que se le pase el iden-
tificador de la factura que se desea procesar.
A continuacion la accion recupera todas las lıneas de reserva, y ayudandose de
las operaciones que proporciona el objeto OfertableCollectionChunkVO divide
el conjunto de lıneas recuperadas en varios segun el tipo de producto reservado
en cada lınea.
Luego utilizando el CalculadorDeOferta del Sistema de Ofertas (se comen-
tara en detalle en la seccion 6.4.5) calcula las mejores ofertas que se podran
aplicar al conjunto de lıneas de reserva. Luego aplica las ofertas y devuelve un
objeto con los datos de la factura actualizados.
CancelarReservaAction Esta accion permite cancelar una reserva. Para ello se le
debe pasar el codigo de la reserva que se quiere cancelar.
Luego se recuperan todas las lıneas de reserva de la reserva que se quiere can-
celar y se marcan como canceladas. A continuacion se actualizan los totales de
la factura en caso necesario y se termina.
PayBillAction Se encarga de marcar una factura como en proceso de pago. Para
ello necesita que se le pase el identificador de la factura que se va a pagar.
6.4. Arquitectura del Modelo 165
A continuacion se marca la factura como que ya no es un borrador, si la factura
ya estaba pagada, en proceso de pago o cancelada, se lanza una excepcion
indicandolo.
PaymentConfirmationAction Se encarga de marcar una factura como pagada
definitivamente, es el segundo de los dos pasos necesarios para realizar el pago
on-line. Para ello, la accion, necesita que le pasen el identificador de la factura.
Luego se actualizan los datos de la factura indicando que ya esta pagada.
SetBillAsPayedAction Esta accion es la encargada marcar una factura como pa-
gada directamente, este proceso de pago de un solo paso es necesario para
cuando el pago se realiza directamente en el establecimiento. Se necesita el
identificador de la factura para realizar la operacion.
La accion actualiza la informacion de la factura y marcandola como pagada y
que ya no es borrador.
GetImporteADevolverCancelacionAction Esta accion es la encargada de cal-
cular el importe que hay que devolver en caso de que se cancele una reserva ya
pagada. Necesita que se le indique el identificador de la reserva que se quiere
cancelar.
Luego la accion recupera todas las lıneas de reserva de esa reserva y segun los
dıas que resten para que la reserva se haga efectiva se devuelve un porcentaje
del importe u otro. Para finalizar se actualizan los datos de las lıneas de reserva
y la factura.
GetFacturaAction Esta accion es la encargada de recuperar los datos de una
factura. Para ello necesita el identificador de la factura que se desea.
A continuacion se recuperan los datos de la factura y las lıneas de reserva que
la componen y se devuelven encapsulados en un Custom Value Object.
GetFacturasEntreFechasAction Esta accion es la encargada de recuperar los
datos de todas las facturas pagadas entre dos fechas. Para ello necesitan: la
6.4. Arquitectura del Modelo 166
fecha mas temprana y la mas tardıa entre las cuales se desean recupera las
facturas.
A continuacion se recuperan los datos de las facturas mediante los DAO y
devuelven a traves de un objeto Collection.
6.4.5. Sistema de Soporte - Modelo de Ofertas
6.4.5.1. Requisitos del Sistema de Ofertas
El sistema de Ofertas es un sistema de soporte, totalmente independiente del resto de
la aplicacion. Este modelo proporcionara una serie de funcionalidades, todas ellas relacio-
nadas con las ofertas.
En el caso del software que se esta desarrollando, se pide que las ofertas cumplan unos
requisitos que no son triviales de implementar, por esa razon se concluyo que la mejor
solucion serıa desarrollar un sistema que funcionara de manera independiente. De esta
forma, si en el futuro se desea cambiar el comportamiento de las ofertas en el negocio para
el que se destina la aplicacion, unicamente habrıa que modificar este sistema. Antes de
detallar como se diseno el sistema, se explicara brevemente los requisitos que este tiene
que cumplir, y como se deben organizar las diferentes ofertas unas con otras.
Todas las ofertas estaran asociadas a un tipo de oferta, este tipo es el primero que se
va a definir. Cada tipo de oferta especifica entre otras cosas a que tipo de productos del
negocio esta destinado y cual es la cantidad mınima necesaria de esos productos para
que una oferta de este tipo se pueda aplicar. Ademas, como las ofertas deben poder ser
acumulables, hay que definir unas incompatibilidades de unos tipos de oferta con otros,
de esta forma solo se podran aplicar conjuntamente aquellas ofertas que sean de tipos
compatibles todos entre sı, este es uno de los problemas a los que habra que hacer frente
en el diseno de este sistema.
6.4. Arquitectura del Modelo 167
Por otro lado, todas las ofertas de un mismo tipo seran incompatibles por definicion, y
cada oferta tiene que poder definir una regla, mediante la cual, en un contexto determinado
(cliente, reserva, fecha, etc) se pueda decidir automaticamente si la oferta se puede aplicar
en una factura o no. La definicion del lenguaje de reglas necesario para dar solucion a esta
necesidad es el segundo de los problemas que debe resolverse con este sistema.
Solucion al Problema de las Incompatibilidades
Como todas las ofertas de un mismo tipo son incompatibles, para elegir la mejor de
todas simplemente se eligira la que proporcione un mayor descuento de entre las que
se puedan aplicar.
Y para luego conseguir encontrar el conjunto de ofertas compatibles que produzcan
el mayor descuento hay que combinar la mejor oferta de cada tipo, con todas las
demas de los otros tipos, siempre y cuando los tipos de oferta no sean incompatibles.
Para resolver la incompatibilidad entre los distintos tipos, se ideo constuir un grafo
de incompatibilidades donde los nodos representan los tipos y los arcos indican que
dos tipos son incompatibles.
Para poner un ejemplo de como se resuelve este problema mediante un grafo, se
tomaran 5 tipos de oferta, A, B, C, D y E. El tipo de oferta E sera incompatible con
el A, el B y el C; y el tipo B con el C. Ası se muestra en el siguiente grafo.
A B C
D E
Grafo ’g’ - Ejemplo de Incompatibilidades
6.4. Arquitectura del Modelo 168
Una vez observado el grafo en el que se expresan las incompatibilidades hay que darle
solucion, y conseguir deducir todos aquellos conjuntos de ofertas que son compatibles
entre sı.
Como un estudio puramente matematico llevarıa mucho tiempo, se buscara una
forma practica de resolverlo. Para ello se intentara buscar una serie de pasos con los
cuales se puedan ir obteniendo aproximaciones de la solucion que se busca.
Una primera aproximacion podrıa ser, dado que se tiene un grafo de incompatibili-
dades, crear el grafo de compatibilidades correspondiente. Pero esto tendrıa un serio
coste computacional si aumentasen las ofertas (nodos) del grafo. Teniendo esto en
cuenta, y utilizando algo de notacion matematica, se puede calcular una matriz de
adyacencia del grafo de incompatibilidades identificando la presencia de una relacion
de incompatibilidad mediante un ’1’ y la ausencia de la misma con un ’0’, de esta
forma se puede ver muy facilmente y de manera compacta con que otras ofertas
es compatible una dada, simplemente identificando los ’0’ de una fila de la matriz.
Los nombres que se daran a las filas y columnas de la matriz de adyacencia seran:
’A’, ’B’, ’C’, ’D’ y ’E’; en orden de izquierda a derecha y de arriba abajo. Dando
como resultado, como matriz de adyacencia asociada al grafo del ejemplo anterior,
la siguiente:
Ady(g) =
0 0 0 0 1
0 0 1 0 1
0 1 0 0 1
0 0 0 0 0
1 1 1 0 0
De la matriz Ady(g) se puede sacar facilmente el grafo de compatibilidades, ya que
en ese caso las relaciones de compatibilidad serıan las representadas por los ’0’. Con
esta simple matriz ya se puede saber que ofertas son compatibles y con cuales, pero
aun falta algo, se ve claramente con el siguiente ejemplo: con los datos de la matriz se
6.4. Arquitectura del Modelo 169
llega a la conclusion de que ’A’ es compatible con ’A’, ’B’, ’C’ y ’D’, pero lo que no se
puede saber directamente es que todas ellas, los ’0’ de la fila, sean compatibles entre
sı, en este caso ’B’ y ’C’ no son compatibles y no se podrıan aplicar conjuntamente.
¿Como solucionarlo?, lo que se necesita es calcular conjuntos de ofertas que sı sean
compatibles entre sı, y se sabe que la fila ’N’ es compatible con los ’0’ de su fila, por lo
tanto se puede realizar una ’criba’. Cambiando los ’0’ por ’1’, es decir, con la matriz
complementaria a Ady(g), se pueden realizar ’AND’ logicos de cada una de las filas
con las filas de cada uno de sus componentes con los que es compatible, o como se
vera a continuacion, utilizando conjuntos y haciendo intersecciones de los conjuntos
compatibles, dando como resultado un conjunto de ofertas todas compatibles entre
sı.
Se puede observar mucho mas facilmente resolviendo el ejemplo con el que se esta tra-
bajando. Primero se realiza el calculo de Ady(g), la matriz complementaria a Ady(g).
Ady(g) =
1 1 1 1 0
1 1 0 1 0
1 0 1 1 0
1 1 1 1 1
0 0 0 1 1
A partir de la informacion de esta matriz, se comienza identificando el conjunto de
ofertas que son compatibles con ’A’, las que lo son con ’B’, etc. Estos conjuntos se
identificaran como C(A), C(B), C(C), C(D) y C(E), y a los conjuntos resultantes de
ofertas compatibles entre sı se les llamara R(A), R(B), R(C), R(D) y R(E). En el
ejemplo con el que se esta trabajando se tienen los siquientes conjuntos:
C(A) = {A,B,C,D}
C(B) = {A,B,D}
C(C) = {A,C,D}
6.4. Arquitectura del Modelo 170
C(D) = {A,B,C,D,E}
C(E) = {D,E}
Y para calcular los conjuntos de ofertas que son compatibles entre si, se hace la
interseccion de cada uno de los conjuntos con los conjuntos de las ofertas con las que
es compatible. A continuacion se muestran estas intersecciones y los resultados:
R(A) = C(A) ∩ C(B) ∩ C(C) ∩ C(D) = {A,D}
R(B) = C(A) ∩ C(B) ∩ C(D) = {A,B,D}
R(C) = C(A) ∩ C(C) ∩ C(D) = {A,C,D}
R(D) = C(A) ∩ C(B) ∩ C(C) ∩ C(D) ∩ C(E) = {D}
R(D) = C(D) ∩ C(E) = {D,E}
Las ofertas de estos cinco conjuntos que se acaban de calcular, son compatibles entre
sı, por lo que se podrıa aplicar sus descuentos conjuntamente en una factura. Una vez
resuelto este problema, el sistema debera escoger el conjunto que ofrece un mayor
descuento sobre el importe de la factura, esta operacion se realiza calculando el
descuento que ofrece cada uno de los conjuntos y escogiendo el que ofrezca el mayor
de todos.
Solucion al Problema de las Reglas para las Ofertas
Como ya se ha mencionado, el sistema debe proporcionar la mayor flexibilidad po-
sible para que las ofertas definan su ambito de aplicacion. Para realizarlo se debe
implementar un sistema mediante el cual cada oferta pueda chequear cuando lo
necesite si se puede, o no, aplicar en un contexto determinado.
Para comenzar hara falta guardar la regla junto con los datos de la oferta en la base
de datos, esta se almacenara de forma textual.
6.4. Arquitectura del Modelo 171
Una regla sera una cadena de caracteres, entre los cuales se intercalaran caracteres
especiales para indicar las diferentes partes y funcionalidades que tendran las demas
subcadenas. Esto es lo primero que hay que hacer, definir una sintaxis que se utili-
zara en la construccion de las distintas reglas. Ademas, para que una regla se pueda
adaptar facilmente a la situacion en la que se va a aplicar, se tienen que proporcio-
nar suficientes formas de moldear como se quiera el contexto necesario para que se
aplique una oferta, y dar la posibilidad de, en el momento que se necesite, poder
ampliar este sistema para proporcionar otras formas de medicion distintas. En otras
palabras, con una regla se tendran que poder definir cosas como: la fecha a partir de
la cual habrıa que hacer una reserva para que se aplique la oferta, la edad mınima
del cliente, la edad maxima, el paıs de origen, etc. Y poder proporcionar en el futuro
formas de definir otros aspectos contra los cuales se pueda cotejar la aplicacion de
una oferta.
Para dar cabida a definir todos estos aspectos y posibilitar la definicion de mas,
se ve necesario que una regla se divida en partes bien diferenciadas donde cada
parte definira una unica situacion y para que una regla se cumpla, se deben cumplir
todas las partes. Cada una de las partes tendra un identificador (nombre) y unos
parametros que necesitara para chequearse, por ejemplo, a la parte de regla que debe
comprobar la edad de un cliente se le tiene que proporcionar por ejemplo una fecha
de nacimiento para que la tome como referencia.
Los caracteres que se utilizaran para separar las diferentes partes de la regla seran
’&&’. Luego hara falta diferenciar el identificador de cada parte de sus parametros,
para eso se utilizara ’:’ y dentro de la zona de los argumentos hay que diferenciar
cada uno de ellos, para lo que se hara uso del caracter ’,’. Un ejemplo de como que-
darıa una regla es el siguiente:
PersonBornBefore:30,8,1987&&PersonFrom:Espana
6.4. Arquitectura del Modelo 172
El ejemplo de regla anterior permitirıa que la oferta se aplicase si el cliente al que
va destinada nacio antes del 30 de Agosto de 1987 y solo si tiene su domicilio en
Espana. Podrıa suceder tambien que hubiese una parte de la regla sin argumentos o
que la regla no tubiese ninguna parte.
6.4.5.2. Diseno e Implementacion del Sistema de Ofertas
A diferencia de como se han explicado los subsistemas anteriores, en este caso se comen-
zara describiendo las funcionalidades que ofrecen las clases mas importantes del sistema.
Se recorrera este modelo dividiendolo en subconjuntos de clases que proporcionen funcio-
nalidades necesarias para el resto de la aplicacion.
En primer lugar se describiran las clases necesarias para dar soporte al sistema de
las reglas para las ofertas y como se relacionan entre sı. La mejor forma de ver como
interactuan diferentes clases es a traves de un diagrama, ası lo podremos observar en la
figura 6.46.
6.4. Arquitectura del Modelo 173
RulePartFactory
+getValidRuleParts() : Collection+getRulePart(key : String,args : String[]) : RulePart+getRulePart(key : String) : RulePart+existsRulePart(key : String) : boolean
-availableRuleParts : Collection-availableRulePartsFile : String
Rule
<<create>> +Rule(s : String)-getKey(s : String) : String-getArgs(s : String) : String[]+isOfferApplicable(of : OfertaVO,colDeCol : Collection,dniPas : String) : boolean+isRuleCorrectlyFormed(s : String) : boolean
-ruleParts : Collection
<<interface>>RulePart
+setArgs(args : String[]) : void+isRulePartApplicableTo(of : OfertaVO,colDeCol : Collection,dniPas : String) : boolean+isCorrect(args : String[]) : boolean
<<call>>
0..*
1
PersonBornAfter
<<create>> +PersonBornAfter()+setArgs(args : String[]) : void+isRulePartApplicableTo(of : OfertaVO,colDeCol : Collection,dniPas : String) : boolean+isCorrect(args : String[]) : boolean
-day : Integer-month : Integer-year : Integer
AlwaysTrue
<<create>> +AlwaysTrue()+setArgs(args : String[]) : void+isRulePartApplicableTo(of : OfertaVO,colDeCol : Collection,dniPas : String) : boolean+isCorrect(args : String[]) : boolean
PersonBornBefore
<<create>> +PersonBornBefore()+setArgs(args : String[]) : void+isRulePartApplicableTo(of : OfertaVO,colDeCol : Collection,dniPas : String) : boolean+isCorrect(args : String[]) : boolean
-day : Integer-month : Integer-year : Integer
PersonFrom
<<create>> +PersonFrom()+setArgs(args : String[]) : void+isRulePartApplicableTo(of : OfertaVO,colDeCol : Collection,dniPas : String) : boolean+isCorrect(args : String[]) : boolean
-country : String
ReservationDoneBefore
<<create>> +ReservationDoneBefore()+setArgs(args : String[]) : void+isRulePartApplicableTo(of : OfertaVO,colDeCol : Collection,dniPas : String) : boolean+isCorrect(args : String[]) : boolean
-day : Integer-month : Integer-year : Integer
Figura 6.46: Diagrama del Sistema de Reglas
6.4. Arquitectura del Modelo 174
La clase regla es la encargada de crear dinamicamente una regla y ofrece metodos de
comprobacion para saber si su aplicacion a un conjunto de productos ofertables, una
persona, etc, resulto exitosa o no, y de chequeo para saber si la cadena y todas sus partes
estan bien formadas. En realidad la regla no realiza estas comprobaciones, sino que delega
su funcionamiento en las distintas partes de regla que la componen. El unico cometido de
esta clase es chequear la cadena que forma la regla, dividirla e identificar sus componentes
para crear los objetos RuleParts oportunos ayudandose de la clase RulePartFactory, la
cual se encarga de, a partir de un nombre identificativo crear un objeto RulePart. Para
saber que tipo de objeto implementa cada uno de los RuleParts solicitados, hace uso de la
clase de utilidad ConfigurationParametersManager. En el capıtulo 7, en el apartado 7.3.0.1
se podra observar como se realizo la implementacion de los metodos mas importantes de
esta clase.
Actualmente se proporcionan definidos en el sistema cinco tipos distintos de objetos
RulePart, pero anadir nuevas partes para las reglas serıa tan sencillo como crear un nuevo
objeto que implemente la interfaz RulePart y especificar su nombre y nombre de clase en
un fichero para que este localizable; a partir de ese momento ya se puede utilizar en la
aplicacion sin ningun problema.
Los tipos definidos son los siguientes:
AlwaysTrue Esta parte de regla no necesita de ningun parametro, cuando se utiliza
es para indicar que siempre es verdad, no tiene mucha utilidad a no ser que el
administrador a la hora de crear una oferta quiera estar seguro de que se aplique
siempre, en ese caso utilizarıa esta parte de regla.
PersonBornAfter En este caso, esta parte de regla necesita tres argumentos para
indicarle una fecha (dıa, mes y ano). En un primer lugar se comprueba que
la fecha este correctamente formada, y cuando se pide que se compruebe si se
cumple, lo que hace esta parte de regla es chequear si el cliente del contexto
6.4. Arquitectura del Modelo 175
actual tiene como fecha de nacimiento una posterior a la indicada mediante los
parametros.
PersonBornBefore Esta parte de regla necesita tres argumentos igual que la an-
terior para indicarle una fecha (dıa, mes y ano). Realiza las mismas comproba-
ciones que PersonBornAfter pero esta vez chequea que el cliente naciera antes
de la fecha indicada. Esta es la clase escogida como ejemplo para ilustrar como
se debe crear un nuevo objeto RulePart.
PersonFrom En este caso se necesita un unico argumento para indicar el nombre
de un paıs. Primero se comprueba que se le pasa este argumento y luego debe
chequear que el cliente contra el que se debe validar la regla sea del paıs indicado.
ReservationDoneBefore Esta parte de regla se encarga de comprobar que la re-
serva se haga antes de una fecha, para ello necesita tres parametros para indicar
la fecha lımite que se desea establecer, luego se comprueba que la fecha sea co-
rrecta y que la reserva se este haciendo en realidad antes del dıa especificado.
Para dar implementacion a una nueva parte de regla lo unico que hay que hacer es
definir el comportamiento necesario de los metodos indicados en la interfaz RulePart.
En el capıtulo 7 en la seccion 7.3.0.3 se muestra la implementacion de la parte de regla
’PersonBornBefore’, cualquier otra implementacion de otra parte de regla que se quisiese
realizar serıa analoga a esa.
Una vez creada la nueva parte de regla hay que anadir una nueva entrada en el fichero de
configuracion ConfigurationParameters.properties para indicar donde se puede localizar la
nueva clase.
Ademas de las reglas, el sistema de ofertas necesitaba calcular el mejor conjunto de
ofertas compatibles que se podıan aplicar a los productos de una factura. En la seccion
anterior se desarrollo un algoritmo practico para dar solucion a este problema, este algo-
ritmo lo implementa una clase particular en el sistema, esta es, BestSetOfOffers, la cual, a
6.4. Arquitectura del Modelo 176
partir de los nodos del grafo (las ofertas) y los descuentos que estas proporcionan sobre la
coleccion de productos ofertables, calcula cual es el mejor conjunto de ofertas compatibles
entre sı.
En primer lugar rellena una matriz cuyas filas y columnas son los identificadores de las
ofertas y borra aquellos elementos en donde fila y columna son incompatibles. Esta es la
primera criba que debe pasar la matriz, pero no la unica, porque, como ya se ha visto,
dentro de los elementos de una fila puede haber algunos que sean incompatibles entre sı,
por eso se realiza una segunda criba para eliminar aquellos que dentro de una misma fila
son incompatibles.
Una vez terminado este proceso, los elementos restantes dentro de cada una de las filas
de la matriz son todos compatibles, por lo que ahora solo resta comprobar cuanto es el
descuento que se puede acumular con cada una de las filas (que son las que forman los
conjuntos de ofertas compatibles) y aquel conjunto que proporcione el mayor importe a
descontar sera el buscado.
BestSetOfOffers
<<create>> +BestSetOfOffers(nodes : Map)+getBestSetOfOffersIds() : ArrayList+getBestDiscount() : Double-getAllIncompatibleWith() : void
-nodes : Map-relations : Collection-bestSetOfOffersIds : ArrayList-bestDiscount : Double
Figura 6.47: Diagrama de clase BestSetOfOffers
6.4. Arquitectura del Modelo 177
Para las expecativas que habıa sobre esta solucion, decir que, finalmente, es lo suficiente-
mente rapida y eficaz para satisfacerlas. Aun ası, si lo que se quiere es rapidez a la hora de
realizar calculos, se debe intentar que el calculo del conjunto de mejores ofertas se haga el
mınimo numero de veces posible. Como esta operacion solo serıa estrictamente necesaria
a la hora de realizar el pago de una factura, es en el momento de comprobar una factura
antes de pagarla cuando se ha utilizado esta funcionalidad en la aplicacion final.
Una vez visto el funcionamiento de las clases necesarias para dar soporte al sistema de
reglas y para calcular el mejor conjunto de ofertas, se mostrara la clase que funciona como
interfaz para las capas superiores, abstrayendo todo el funcionamiento que se ha explicado.
Esta clase es ‘CalculadorImpl‘ que implementa la interfaz ‘Calculador‘. La clase Calcula-
dorImpl es la encargada de realizar el calculo del mejor conjunto de ofertas aplicables a un
conjunto de productos ‘Ofertable‘, haciendo uso de ‘BestSetOfOffers‘ para dicho calculo.
En un nivel superior se encuentra la clase ‘GeneralCalculadorDeOferta‘ que es el encar-
gado de pasar a CalculadorImpl los datos necesarios para que este devuelva el resultado
deseado, para filtrar los datos que se pasan a CalculadorImpl, GeneralCalculadorDeOferta
hace uso de todo el sistema de reglas para comprobar que todas las ofertas que se van a
pasar se puedan aplicar. Utilizando estas dos clases se consigue separar la decision de si
una oferta se puede aplicar o no, del calculo del mejor conjunto de ofertas. Se utiliza para
esto el proceso denominado ‘delegacion‘ a traves del cual, GeneralCalculadorDeOferta rea-
liza las operaciones que le corresponden y delega en CalculadorImpl el calculo del mejor
conjunto de ofertas. De este modo, el dıa de manana se podrıa cambiar, si se quisiese, la
implementacion de ‘Calculador‘ para que sea mas eficiente.
A continuacion se muestran los metodos que ofrecen estas dos clases en la figura 6.48
6.4. Arquitectura del Modelo 178
<<interface>>CalculadorDeOferta
+CalcularMejorPara(c : Connection,colOfertable : Collection,dniPasPersona : String) : Collection+setCalculador(c : Calculador) : void+getAppliedOffers() : Collection
GeneralCalculadorDeOferta
-split(colOfertable : Collection) : void+setCalculador(c : Calculador) : void-canBeApplied(of : OfertaVO,colDeCol : Collection,dniPas : String) : boolean+CalcularMejorPara(c : Connection,colOfertable : Collection,dniPasPersona : String) : Collection+getAppliedOffers() : Collection
-colDeCol : Collection-calculador : Calculador-colOfApplied : Collection
<<interface>>Calculador
+calculaMejorOferta(colProductos : Collection,colOfertasPosibles : Collection) : Collection+getAppliedOffers() : Collection
1
1
CalculadorImpl
+calculaMejorOferta(colProductos : Collection,colOfertasPosibles : Collection) : Collection-getBestOffer(colOf : Collection) : OfertaVO-getAmountDiscounted(colProductos : Collection,offer : OfertaVO) : Double-acumularOfertaEnOfertableCollection(colProductos : Collection,offer : OfertaVO) : void-calcAmount(col : Collection,discountTemp : Double) : Double+getAppliedOffers() : Collection
-myProxyMap : Map-myBestSetOfOffersTypes : Collection-myFinalOfertableCol : Collection
Figura 6.48: Diagrama de las Clases Calculadoras
6.4. Arquitectura del Modelo 179
De la clase GeneralCalculadorDeOferta se podrıa destacar el metodo ‘calcularMejorPara‘
encargado de calcular el mejor descuento para un conjunto de objetos ‘Ofertable‘. El
primer paso a realizar es dividir el conjunto de objetos Ofertable inicial en un conjunto
de conjuntos divididos segun el tipo de Ofertable, a continuacion se recuperan todas las
ofertas y ayudandose del sistema de reglas, se escogen simplemente aquellas que segun su
regla se puedan aplicar. Una vez que se tienen estos datos, se delega el resto del calculo
en el metodo ‘calculaMejorOferta‘ del objeto ‘Calculador‘.
Otro metodo importante es ‘calculaMejorOferta‘ de la clase CalculadorImpl, encargado
de, utilizando BestSetOfOffers, calcular el mejor descuento para el conjunto de conjuntos
de objetos Ofertable recibido a partir de las ofertas que le pasan. En primer lugar divide
las ofertas por tipos y escoge la que proporciona el mayor descuento de cada tipo, ya que
de cada tipo solo se podra aplicar una oferta. A continuacion se calcula el descuento que
proporciona cada una de las ofertas elegidas, y se le pasa esta informacion a BestSetOfOf-
fers para que calcule el conjunto de ofertas compatibles que ofrezca un mayor descuento,
para luego calcular el total que proporcionan de descuento sobre el conjunto de Ofertables.
En el capıtulo 7 en la seccion 7.3.0.2 se muestra la implementacion final de estos dos
metodos.
Una vez visto el funcionamiento de todas las clases de este sistema de soporte por se-
parado, se muestra como se relacionan entre sı todas ellas de forma compleja, de forma
que si el dıa de manana hubiese que cambiar algun componente, el proceso fuese practi-
camente de “Enchufar y Listo”. Se muestra a continuacion un diagrama de clases de esta
organizacion en la figura 6.49 donde se puede observar de forma simplificada la relacion
entre las clases.
Del mismo modo, tambien se puede observar como unas clases delegan parte de su
funcionamiento en otras, a traves del diagrama de secuencia de alto nivel que se muestra
en la figura 6.50. En ella se ve claramente el proceso de delegacion, gracias al cual, una de
las clases no se tiene que preocupar de realizar toda la operacion, sino que se realiza una
6.4. Arquitectura del Modelo 180
parte y deja que otra clase se encargue de uno de los trozos. Se podrıa tambien considerar
esto como una aplicacion de “Divide y Venceras”, done en cada metodo solo se trata una
parte de la funcionalidad a implementar, simplificando en gran medida la codificacion de
los metodos de las diferentes clases debido a que las operaciones que se realizan en cada
uno de ellos son mucho mas sencillas que si se realizara todo junto.
6.4.A
rquitectu
radel
Modelo
181
<<interface>>CalculadorDeOferta
+CalcularMejorPara(c : Connection,colOfertable : Collection,dniPasPersona : String) : Collection+setCalculador(c : Calculador) : void+getAppliedOffers() : Collection
GeneralCalculadorDeOferta
-split(colOfertable : Collection) : void+setCalculador(c : Calculador) : void-canBeApplied(of : OfertaVO,colDeCol : Collection,dniPas : String) : boolean+CalcularMejorPara(c : Connection,colOfertable : Collection,dniPasPersona : String) : Collection+getAppliedOffers() : Collection+newOperation()
<<interface>>Calculador
+calculaMejorOferta(colProductos : Collection,colOfertasPosibles : Collection) : Collection+getAppliedOffers() : Collection
1
1<<call>>
CalculadorImpl
+calculaMejorOferta(colProductos : Collection,colOfertasPosibles : Collection) : Collection-getBestOffer(colOf : Collection) : OfertaVO-getAmountDiscounted(colProductos : Collection,offer : OfertaVO) : Double-acumularOfertaEnOfertableCollection(colProductos : Collection,offer : OfertaVO) : void-calcAmount(col : Collection,discountTemp : Double) : Double+getAppliedOffers() : Collection
BestSetOfOffers
<<create>> +BestSetOfOffers(nodes : Map)+getBestSetOfOffersIds() : ArrayList+getBestDiscount() : Double-getAllIncompatibleWith() : void
<<call>>
RulePartFactory
+getValidRuleParts() : Collection+getRulePart(key : String,args : String[]) : RulePart+getRulePart(key : String) : RulePart+existsRulePart(key : String) : boolean
Rule
<<create>> +Rule(s : String)-getKey(s : String) : String-getArgs(s : String) : String[]+isOfferApplicable(of : OfertaVO,colDeCol : Collection,dniPas : String) : boolean+isRuleCorrectlyFormed(s : String) : boolean
<<create>>
<<call>>
<<call>>
<<interface>>RulePart
+setArgs(args : String[]) : void+isRulePartApplicableTo(of : OfertaVO,colDeCol : Collection,dniPas : String) : boolean+isCorrect(args : String[]) : boolean
0..*
1<<instantiate>>
Figura 6.49: Diagrama Simple del Sistema de Ofertas
6.4.
Arq
uitec
tura
del
Model
o18
2
Figura 6.50: Diagrama Secuencia de la Accion de Calcular
Capıtulo 7
Implementacion
7.1. Detalles Especıficos de la Implementacion
A continuacion seran especificados ciertos problemas que surgieron y detalles que se
tuvieron en cuenta a la hora de implementar el sistema.
El primer y principal problema surgido en la implementacion fue utilizando el maneja-
dor JDBC para MySQL en su version mas reciente, debido a que a la hora de conectarse
con la base de datos lanzaba excepciones el driver diciendo que era imposible realizar la
conexion, despues de contactar con comunidades de usuarios de MySQL y no encontrar
solucion, habiendo tambien otros desarrolladores con el mismo problema, se decide inten-
tar solventar el problema analizando en profundidad la traza de la exepcion. Esta idea fue
la acertada, ya que a traves de este analisis se concluye que el error era provocado por la
codificacion de caracteres utilizada por defecto por la conexion. A partir de esta informa-
cion y documentandose sobre las opciones que se pueden pasar al driver de MySQL en el
momento del establecimiento de conexion se consiguio resolver el problema, publicandolo
en las comunidades de MySQL1 y recibiendo agradecimientos de los usuarios que tenıan
ese mismo problemas.
1La comunidad en la que se publico la solucion de este problema fue en: http://forums.mysql.com/exactamente en el siguiente hilo: http://forums.mysql.com/read.php?39,259743,259939#msg-259939
183
7.1. Detalles Especıficos de la Implementacion 184
Para la escritura del codigo fuente de la aplicacion se siguieron las normas que se es-
tablecen en las Convenciones de Codigo Java (Java Code Conventions). De este modo
sera mucho mas facil de entender el codigo fuente de la aplicacion para futuros desarrolla-
dores que realicen el mantenimiento de esta.
Lo primero que se hizo fue decidir que objetos se utilizarıan para manejar las fechas
y los conjuntos de objetos del mismo tipo. Para el manejo de fechas se empleo la clase
Calendar, ya que ofrece grandes ventajas a la hora de consultar una fecha y porque ya
esta practicamente integrada en las tecnologıas utilizadas. Por otro lado para gestionar
conjuntos de elementos se utilizo el objeto Collection, ya que este permite realizar bucles
utilizando un objeto Iterator, lo que hace algo mas comodo el trabajo del programador.
Ademas de la eleccion de los objetos pertinentes para realizar la implementacion, tam-
bien se introdujeron unas clases xxxManager en la capa controlador de la aplicacion, estas
clases tienen dos funciones fundamentales, la primera, realizar de cache, para evitar rea-
lizar multiples veces la misma consulta al modelo, y la segunda, sirve para amortiguar el
acceso al modelo en cuanto al numero de operaciones invocadas se refiere. Un ejemplo de
esto es la clase ReservationsManager que permite anadir nuevas lıneas de reserva a una
reserva o incluso modificarla eliminando lıneas, sin realizar esta operacion directamente
contra el modelo, sino que realiza los cambios internamente en su cache y luego en el mo-
mento de guardar hace los cambios todos juntos. Esto tambien posibilita que si el usuario
desea cancelar un proceso de modificacion, por ejemplo, los cambios que haya realizado
no haya que deshacerlos invocando a operaciones del modelo.
Para la implementacion del cambio de idioma de la interfaz web se consideraron dos
opciones, la opcion logica, serıa que en cualquier momento el usuario pudiese cambiar el
idioma de la aplicacion y que inmediatamente le cambiase el idioma de donde esta actual-
mente este usuario, pero esta no se pudo adoptar. Esta opcion no se pudo implementar,
debido a que la unica forma de que se cargara el nuevo idioma serıa cargar de nuevo la
pagina y si el usuario se encuentra en algun paso de un formulario se le enviarıa automati-
camente una peticion identica a la ultima operacion que realizo. A raız de este compor-
7.2. Implementacion de las Base de Datos 185
tamiento no desado se decidio que, siempre que el usuario decidiese cambiar de idioma la
aplicacion, fuese redireccionado a la pagina principal. De esta forma se consiguen evitar
comportamientos erroneos o inconsistentes
7.2. Implementacion de la Base de Datos
Aunque realmente las dos bases de datos que se utilizaran se podrıa separar en dos bases
de datos distintas, por motivos de simplicidad se considero que las tablas se creasen en
la misma base de datos. La base de datos se creo en localhost con el nombre bd hotel. A
continuacion se mostraran el proceso de creacion de las diferentes tablas y la insercion de
los dos usuarios por defecto del sistema ’admin’ y ’receptionist’, a traves de unas consultas
SQL.
7.2.1. Implementacion de la Base de Datos General
A partir del diseno explicado en la seccion 6.4.1.1 se puede sacar de forma sencilla la
implementacion.
Con las consultas SQL que se muestran a continuacion se crean las tablas de la base
de datos General, y para cada tabla tambien se crean los ındices necesarios. Estos ındices
valdran para realizar consultas mas rapidas en esas tablas, por lo que se centraran en
aquellos atributos por los que luego se haran busquedas mas a menudo.
-- --------------------
-- CREATING TABLES
-- --------------------
CREATE TABLE Persona (
Dni_Pas Varchar(50) NOT NULL ,
E_mail Varchar(255) NOT NULL ,
Usuario_Conf Bit NOT NULL ,
7.2. Implementacion de las Base de Datos 186
Nom_Usuario Varchar(255) NOT NULL ,
Password Varchar(255) NOT NULL ,
Nombre Varchar(255) NOT NULL ,
Apellidos Varchar(255) NOT NULL ,
Dir_Calle Varchar(255),
Pais Varchar(255),
Cliente Bit NOT NULL ,
Telefono1 Varchar(100),
Telefono2 Varchar(100),
Fecha_Nac TimeStamp NOT NULL DEFAULT CURRENT_TIMESTAMP ,
CONSTRAINT pk_Persona PRIMARY KEY (Dni_Pas)) Type= INNODB;
CREATE UNIQUE INDEX indice_Nom_Usuario
ON Persona(Nom_Usuario);
CREATE INDEX indice_Nombre
ON Persona(Nombre);
CREATE INDEX indice_Apellidos
ON Persona(Apellidos);
CREATE INDEX indice_Fecha_Nac
ON Persona(Fecha_Nac);
CREATE TABLE Factura (
Dni_Pas Varchar(50) NOT NULL ,
Numero_Factura BigInt NOT NULL AUTO_INCREMENT ,
Fecha TimeStamp NOT NULL DEFAULT CURRENT_TIMESTAMP ,
Total_Descontado Double NOT NULL ,
Total Double NOT NULL ,
Pagada Bit NOT NULL ,
Borrador Bit NOT NULL ,
7.2. Implementacion de las Base de Datos 187
Ofertas_Aplicadas Varchar(255) NOT NULL ,
CONSTRAINT pk_Factura PRIMARY KEY (Numero_Factura),
CONSTRAINT fk_Dni_Pas_Factura FOREIGN KEY (Dni_Pas)
REFERENCES Persona(Dni_Pas)) Type= INNODB;
CREATE INDEX Indice_Dni_Pas_Factura
ON Factura(Dni_Pas);
CREATE INDEX Indice_Fecha_Factura
ON Factura(Fecha);
CREATE TABLE Reserva (
Dni_Pas Varchar(50) NOT NULL ,
Codigo BigInt NOT NULL AUTO_INCREMENT ,
Fecha_Realizacion TimeStamp NOT NULL DEFAULT
CURRENT_TIMESTAMP ,
Temporal Bit NOT NULL ,
CONSTRAINT pk_Reserva PRIMARY KEY (Codigo),
CONSTRAINT fk_Dni_Pas_Reserva FOREIGN KEY (Dni_Pas)
REFERENCES Persona(Dni_Pas)) Type= INNODB;
CREATE INDEX Indice_Dni_Pas_Reserva
ON Reserva(Dni_Pas);
CREATE INDEX Indice_Fecha_Reserva
ON Reserva(Fecha_Realizacion);
CREATE TABLE Habitacion (
Numero MediumInt NOT NULL ,
Piso SmallInt NOT NULL ,
Precio_Extra Double NOT NULL DEFAULT 0,
7.2. Implementacion de las Base de Datos 188
CONSTRAINT pk_Habitacion PRIMARY KEY (Numero)) Type= INNODB
;
CREATE TABLE Lineas_de_Reserva (
Codigo_Reserva BigInt NOT NULL ,
Numero MediumInt NOT NULL ,
Fecha_Inicio TimeStamp NOT NULL DEFAULT CURRENT_TIMESTAMP ,
Fecha_Fin TimeStamp NOT NULL ,
Descuento Double NOT NULL ,
Total_Parcial Double NOT NULL ,
Numero_Factura BigInt NOT NULL ,
Cancelada Bit NOT NULL ,
CONSTRAINT pk_Lineas_de_Reserva PRIMARY KEY (Codigo_Reserva
, Numero, Fecha_Inicio),
CONSTRAINT fk_Numero_Lineas_de_Reserva FOREIGN KEY (Numero)
REFERENCES Habitacion (Numero),
CONSTRAINT fk_Codigo_Reserva_Lineas_de_Reserva FOREIGN KEY
(Codigo_Reserva) REFERENCES Reserva(Codigo),
CONSTRAINT fk_Numero_Factura_Lineas_de_Reserva FOREIGN KEY
(Numero_Factura) REFERENCES Factura( Numero_Factura))
Type= INNODB;
CREATE INDEX Indice_Codigo_Reserva_Lineas_de_Reserva
ON Lineas_de_Reserva(Codigo_Reserva);
CREATE INDEX Indice_Numero_Factura_Lineas_de_Reserva
ON Lineas_de_Reserva(Numero_Factura);
CREATE TABLE Tipo_Habitacion (
Id_Tipo MediumInt NOT NULL AUTO_INCREMENT ,
Descripcion Text ,
Num_Personas SmallInt ,
7.2. Implementacion de las Base de Datos 189
Precio_Base Double NOT NULL ,
CONSTRAINT pk_Tipo_Habitacion PRIMARY KEY (Id_Tipo)) Type=
INNODB;
CREATE TABLE Es_de_tipo (
Numero MediumInt NOT NULL ,
Id_Tipo MediumInt NOT NULL ,
CONSTRAINT pk_Es_de_tipo PRIMARY KEY (Numero, Id_Tipo),
CONSTRAINT fk_Numero_Habitacion FOREIGN KEY (Numero)
REFERENCES Habitacion(Numero),
CONSTRAINT fk_Id_Tipo_Tipo_Habitacion FOREIGN KEY (Id_Tipo)
REFERENCES Tipo_Habitacion(Id_Tipo)) Type= INNODB;
CREATE INDEX Indice_Id_Tipo_Es_de_tipo
ON Es_de_tipo(Id_Tipo);
CREATE INDEX Indice_Numero_Es_de_tipo
ON Es_de_tipo(Numero);
CREATE TABLE Incidencia (
Numero MediumInt NOT NULL ,
Id_Secundario MediumInt NOT NULL ,
Tipo Varchar(255),
Descripcion Text ,
Fecha_Registro TimeStamp NOT NULL DEFAULT CURRENT_TIMESTAMP
,
CONSTRAINT pk_Incidencia PRIMARY KEY (Numero, Id_Secundario
),
CONSTRAINT fk_Numero_Habitacion_Incidencia FOREIGN KEY (
Numero) REFERENCES Habitacion(Numero)) Type= INNODB;
CREATE INDEX Indice_Numero_Incidencia
7.2. Implementacion de las Base de Datos 190
ON Incidencia(Numero);
-- --------------------
-- Insert Admin
-- --------------------
INSERT INTO Persona (Dni_Pas , E_mail, Usuario_Conf , Nom_Usuario ,
Password , Nombre, Apellidos , Dir_Calle , Pais , Cliente , Telefono1
, Telefono2)
VALUES (’0’, ’’, 1,’admin’, ’admin’, ’’, ’’, ’’, ’’, 0, ’’,
’’);
-- --------------------
-- Insert Receptionist
-- --------------------
INSERT INTO Persona (Dni_Pas , E_mail, Usuario_Conf , Nom_Usuario ,
Password , Nombre, Apellidos , Dir_Calle , Pais , Cliente , Telefono1
, Telefono2)
VALUES (’1’, ’’, 1, ’receptionist’, ’receptionist’, ’’, ’’,
’’, ’’, 0, ’’, ’’);
7.2.2. Implementacion de la Base de Datos de Ofertas
Despues de realizar el diseno que se ha detallado en la seccion 6.4.1.2 ya se pueden crear
directamente las consultas SQL para construir esta base de datos, y ademas, como en el
caso de la base de datos General, crear los ındices necesarios para optimizar las futuras
busquedas. Las consultas que finalmente hay que ejecutar para tales objetivos son las
siguientes:
-- --------------------
7.2. Implementacion de las Base de Datos 191
-- Base de datos Oferta:
-- --------------------
CREATE TABLE Tipo_Oferta (
Id_Tipo MediumInt NOT NULL AUTO_INCREMENT ,
Nombre Varchar(255),
Descripcion Text ,
CONSTRAINT pk_Tipo_Oferta PRIMARY KEY (Id_Tipo)) Type=
INNODB;
CREATE INDEX Indice_Nombre_Tipo_Oferta
ON Tipo_Oferta(Nombre);
CREATE TABLE Oferta (
Id_Oferta MediumInt NOT NULL AUTO_INCREMENT ,
Descuento Double NOT NULL ,
Descripcion Text ,
Fecha_Inicio TimeStamp NOT NULL DEFAULT CURRENT_TIMESTAMP ,
Fecha_Fin TimeStamp NOT NULL ,
Regla_a_cumplir Text ,
Id_Tipo MediumInt NOT NULL ,
Borrador Bit NOT NULL ,
Desactivada Bit NOT NULL ,
CONSTRAINT pk_Oferta PRIMARY KEY (Id_Oferta),
CONSTRAINT fk_Id_Tipo_Tipo_Oferta FOREIGN KEY (Id_Tipo)
REFERENCES Tipo_Oferta(Id_Tipo)) Type= INNODB;
CREATE INDEX Indice_Id_Tipo_Oferta
ON Oferta(Id_Tipo);
CREATE TABLE Aplicable_A (
Id_Tipo MediumInt NOT NULL ,
Nombre Varchar(255) NOT NULL ,
7.3. Implementaciones del Sistema de Ofertas 192
Cantidad_Min MediumInt NOT NULL DEFAULT 1,
CONSTRAINT pk_Aplicable_A PRIMARY KEY (Id_Tipo , Nombre))
Type= INNODB;
CREATE INDEX Indice_Id_Tipo_Aplicable_A
ON Aplicable_A(Id_Tipo);
CREATE TABLE Incompatible_Con (
Id_Tipo MediumInt NOT NULL ,
Id_Tipo_Incomp MediumInt NOT NULL ,
CONSTRAINT pk_Incompatible_Con PRIMARY KEY (Id_Tipo ,
Id_Tipo_Incomp),
CONSTRAINT fk_Id_Tipo_Incompatible_Con FOREIGN KEY (Id_Tipo
) REFERENCES Tipo_Oferta(Id_Tipo),
CONSTRAINT fk_Id_Tipo_Incomp_Incompatible_Con FOREIGN KEY (
Id_Tipo_Incomp) REFERENCES Tipo_Oferta(Id_Tipo)) Type=
INNODB;
CREATE INDEX Indice_Id_Tipo_Incompatible_Con
ON Incompatible_Con(Id_Tipo);
CREATE INDEX Indice_Id_Tipo_Incomp_Incompatible_Con
ON Incompatible_Con(Id_Tipo_Incomp);
7.3. Implementaciones del Sistema de Ofertas
7.3.0.1. Implementacion de Factorıa de Partes de Regla
En esta seccion se muestra como se realizo finalmente la implementacion de la clase
RulePartFactory, que se encarga de crear las partes de regla despues de que la clase Regla
la haya parseado.
7.3. Implementaciones del Sistema de Ofertas 193
1 package hotel.modelo.modelooferta.calculadordeoferta.regla;
2
3 import java.io.BufferedReader;
4 import java.io.FileNotFoundException;
5 import java.io.IOException;
6 import java.io.InputStream;
7 import java.io.InputStreamReader;
8 import java.util.ArrayList;
9 import java.util.Collection;
10 import java.util.Iterator;
11
12 import hotel.util.configuration.ConfigurationParametersManager ;
13 import hotel.util.exceptions.model.
MissingConfigurationParameterException ;
14
15 @SuppressWarnings("unchecked")
16 public class RulePartFactory {
17
18
19 private static Collection <String > availableRuleParts = null;
20 private final static String availableRulePartsFile = "
RulePartFactory/file";
21
22 static {
23
24 availableRuleParts = new ArrayList <String >();
25 String temp = null;
26 try {
27 Class myClass = RulePartFactory.class;
28 ClassLoader classLoader =
29 myClass.getClassLoader();
7.3. Implementaciones del Sistema de Ofertas 194
30 InputStream inputStream = classLoader.
getResourceAsStream(
31 ConfigurationParametersManager .getParameter(
availableRulePartsFile));
32 InputStreamReader in = new InputStreamReader(
inputStream);
33 BufferedReader fileBuffer = new BufferedReader(in);
34
35 while ((temp = fileBuffer.readLine())!=null) {
36 if (!temp.equals("")) {
37 availableRuleParts.add(temp);
38 }
39 }
40 } catch (FileNotFoundException e) {
41 System.out.println("ValidValuesFile Not Found");
42 } catch (IOException e) {
43 System.out.println("Unabled to read ValidValuesFile");
44 } catch ( MissingConfigurationParameterException e) {
45 System.out.println("Configuration parameter Not Found")
;
46 }
47 }
48
49 public Collection <String > getValidRuleParts() {
50
51 return availableRuleParts;
52 }
53
54 public static RulePart getRulePart(String key , String [] args) {
55
56 if (existsRulePart(key)){
57 try {
7.3. Implementaciones del Sistema de Ofertas 195
58 Class concreteClass = null;
59 String className =
ConfigurationParametersManager .
getParameter(
60 "RulePartFactory/" + key);
61 concreteClass = Class.forName(className);
62 RulePart r = (RulePart) concreteClass.
newInstance();
63 r.setArgs(args);
64 return r;
65 } catch (MissingConfigurationParameterException e)
{
66 return null;
67 } catch (ClassNotFoundException e) {
68 return null;
69 } catch (IllegalArgumentException e) {
70 return null;
71 } catch (SecurityException e) {
72 return null;
73 } catch (InstantiationException e) {
74 return null;
75 } catch (IllegalAccessException e) {
76 return null;
77 }
78 }
79 else return null;
80 }
81
82 public static RulePart getRulePart(String key) {
83 /*
84 * Igual al metodo anterior , solo que este crear un
85 * nuevo RulePart sin argumentos
7.3. Implementaciones del Sistema de Ofertas 196
86 */
87 }
88
89 public static boolean existsRulePart(String key) {
90 Iterator <String> iter = availableRuleParts.iterator();
91 String aux = "";
92 boolean cent = false;
93 while (iter.hasNext()) {
94 aux = iter.next();
95 if (aux.compareTo(key)==0) {
96 cent = true;
97 }
98 }
99 return cent;
100 }
101 }
7.3.0.2. Implementacion de Calculador
Los pasos que realiza el metodo ’calcularMejorPara’ del objeto Calculador, se pueden
observar claramente con el trozo de codigo fuente que los realiza:
1 public Collection <Ofertable > CalcularMejorPara(Connection c,
2 Collection <Ofertable > colOfertable , String
dniPasPersona)
3 throws InternalErrorException {
4
5 //Aqui dividimos la coleccion de Ofertables inicial en
OfertableCollections segun su tipo
6
7 split(colOfertable);
8
7.3. Implementaciones del Sistema de Ofertas 197
9 SQLOfertaDAO OF = SQLOfertaDAOFactory.getDAO ();
10
11 //Recuperamos TODA la lista de ofertas posibles
12
13 Collection <OfertaVO > colOferta = new ArrayList <OfertaVO >();
14 Collection <OfertaVO > temp;
15 int i = 1;
16 while ((temp = OF. getByDesactivada(c, false , i, 21)).
size()==21){
17 temp.remove (20);
18 colOferta.addAll(temp);
19 i=i+20;
20 }
21 if (temp.size() <21) {
22 colOferta.addAll(temp);
23 }
24 //Fin recuperacion lista
25
26 //Ahora nos quedamos solo con las que son aplicables segun
nuestra regla
27
28 ArrayList <OfertaVO > ofAplicables = new ArrayList <OfertaVO
>();
29 ArrayList <OfertaVO > alOferta = new ArrayList <OfertaVO >();
30 alOferta.addAll(colOferta);
31 Iterator <OfertaVO > iterOf = alOferta.iterator();
32 OfertaVO myOfAux = null;
33 while (iterOf.hasNext()) {
34 myOfAux = iterOf.next();
35 if (canBeApplied(myOfAux , colDeCol , dniPasPersona)) {
36 ofAplicables.add(myOfAux);
37 }
7.3. Implementaciones del Sistema de Ofertas 198
38 }
39 //Ya solo nos quedan las que podemos aplicar segun nuetra
regla
40
41 //Y ahora llamamos a nuestro calculador preferido para que
nos calcule
42
43 Collection <Ofertable > col =
44 this.calculador.calculaMejorOferta(colDeCol ,
ofAplicables);
45 this.colOfApplied = this.calculador. getAppliedOffers();
46 return col;
47 }
En el siguiente trozo de codigo se puede ver como es el funcionamiento basico del metodo
’calculaMejorOferta’ de la clase CalculadorImpl, ya que para realizar ciertas operaciones
delega su funcionamiento en otro metodo auxiliar:
1 public Collection <Ofertable > calculaMejorOferta(
2 Collection <OfertableCollectionChunkVO > colProductos ,
3 Collection <OfertaVO > colOfertasPosibles)
4 throws InternalErrorException {
5
6 // Primero hay que dividir las ofertas por tipos , ya que de
cada tipo solo se va a poder aplicar una y solo una
oferta.
7
8 Map <Long , ArrayList <OfertaVO >> byTipo =
9 new HashMap <Long , ArrayList <OfertaVO >>();
10 Iterator <OfertaVO > iter = colOfertasPosibles.iterator();
11 OfertaVO ofAux = null;
12 while (iter.hasNext()) {
7.3. Implementaciones del Sistema de Ofertas 199
13 ofAux = iter.next();
14 if (byTipo.containsKey(ofAux.getIdTipo())) {
15 byTipo.get(ofAux.getIdTipo()).add(ofAux);
16 }
17 else {
18 ArrayList <OfertaVO > a = new ArrayList <OfertaVO >();
19 a.add(ofAux);
20 byTipo.put(ofAux.getIdTipo(), a);
21 }
22 }
23
24 Map <Long , Double > offerTypeVsDiscount = new HashMap <Long ,
Double >();
25
26 //Recorro todos los tipos de ofertas , calculo el maximo
descuento que se puede hacer sobre los ofertables que me
pasan y anhado estos valores al mapa , para que luego mi
optimizador (BestSetOfOffers) me devuelva las que se
pueden apicar para que produzcan el mayor descuento.
27
28 Collection <Long > tipos = byTipo.keySet ();
29 Iterator <Long > tiposIter = tipos.iterator();
30 Long longAux = null;
31 OfertaVO bestAux = null;
32 while (tiposIter.hasNext()) {
33 longAux = tiposIter.next();
34 bestAux = this.getBestOffer(byTipo.get(longAux));
35 this.myProxyMap.put(longAux , bestAux);
36 }
37
38 tipos = this.myProxyMap.keySet ();
39 tiposIter = tipos.iterator();
7.3. Implementaciones del Sistema de Ofertas 200
40 while (tiposIter.hasNext()) {
41 longAux = tiposIter.next();
42 offerTypeVsDiscount.put(longAux , this.
getAmountDiscounted(colProductos ,
43 this.myProxyMap.get(longAux)));
44
45 }
46
47
48 try {
49 BestSetOfOffers bestOffers = new BestSetOfOffers(
offerTypeVsDiscount);
50 this. myBestSetOfOffersTypes = bestOffers.
getBestSetOfOffersIds();
51 Iterator <Long > iterBest = this.myBestSetOfOffersTypes.
iterator();
52
53 while (iterBest.hasNext()) {
54 this. acumularOfertaEnOfertableCollection (
colProductos ,
55 this.myProxyMap.get(iterBest.next()));
56 }
57
58 //Ahora anhado todos los ofertables
59
60 Iterator <OfertableCollectionChunkVO > iterOfertableCol =
61 colProductos.iterator();
62 while (iterOfertableCol.hasNext()) {
63 this. myFinalOfertableCol.addAll(
64 iterOfertableCol.next().
extractOfertableCollection ());
65 }
7.3. Implementaciones del Sistema de Ofertas 201
66
67 } catch ( InternalErrorException e) {
68 throw e;
69 } catch (SQLException e) {
70 throw new InternalErrorException("SQL Exception: in
SimpleCalculator");
71 }
72
73 return this. myFinalOfertableCol;
74 }
7.3.0.3. Implementacion de una Parte de Regla
No hay mejor forma de ver como se implementarıa una nueva parte de regla es con
un ejemplo, ası que a continuacion se muestra la implementacion de la parte de regla
PersonBornBefore, la forma de crear una nueva es analoga a esta.
1 package hotel.modelo.modelooferta.calculadordeoferta.regla.partes;
2
3 import java.util.Calendar;
4 import java.util.Collection;
5 import javax.sql.DataSource;
6 import hotel.modelo.modelooferta. calculadordeoferta.regla.RulePart;
7 import hotel.modelo.modelooferta.oferta.vo.OfertaVO;
8 import hotel.modelo.modelooferta.util.ofertablecollection.
OfertableCollectionChunkVO;
9 import hotel.modelo.persona.dao.SQLPersonaDAO;
10 import hotel.modelo.persona.dao.SQLPersonaDAOFactory;
11 import hotel.util.sql.GeneralDataSource;
12
13 public class PersonBornBefore implements RulePart {
7.3. Implementaciones del Sistema de Ofertas 202
14
15 private Integer day ;
16 private Integer month;
17 private Integer year;
18
19 public PersonBornBefore () {}
20
21 public void setArgs (String [] args) {
22 day = new Integer(args[0]);
23 month= new Integer(args[1]);
24 year = new Integer(args[2]);
25 }
26
27 public boolean isRulePartApplicableTo(OfertaVO of,
28 Collection <OfertableCollectionChunkVO > colDeCol , String
dniPas) {
29 try {
30 System.out.println("entro");
31 SQLPersonaDAO persDAO = SQLPersonaDAOFactory.getDAO ();
32 DataSource ds = new GeneralDataSource();
33 Calendar fechaNacimiento = persDAO.findPersona(ds.
getConnection(),
34 dniPas).getFechaNac();
35 Calendar c = Calendar.getInstance();
36 c.clear();
37 c.set(year , month -1, day);
38 c.setLenient(false);
39 c.getTime();
40 System.out.println(c.toString());
41 System.out.println( fechaNacimiento.toString());
42 return c.compareTo( fechaNacimiento) >=0;
43 } catch (Exception e) {
7.3. Implementaciones del Sistema de Ofertas 203
44 return false;
45 }
46 }
47
48 public boolean isCorrect(String [] args) {
49 if (args.length ==3) {
50 if (args [0]!= null&&(args[0]. compareTo("")!=0)
51 &&args[1]!= null&&(args[1]. compareTo("")!=0)
52 &&args[2]!= null&&(args[2]. compareTo("")!=0)) {
53 try {
54 Integer day = new Integer(args [0]);
55 Integer month= new Integer(args [1]);
56 Integer year = new Integer(args [2]);
57 Calendar c = Calendar.getInstance();
58 c.clear();
59 c.set(year , month -1, day);
60 c.setLenient(false);
61 c.getTime();
62 return true;
63 }
64 catch (Exception e) {
65 return false;
66 }
67 }
68 else return false;
69 }
70 else if (args.length <3) {
71 return false;
72 }
73 else {
74 for (int i=3;i<args.length;i++) {
75 if ((args[i]!=null)&&(args[i]. compareTo("")!=0)) {
7.4. Software Necesario para Desplegar la Aplicacion 204
76 return false;
77 }
78 }
79 }
80 return true;
81 }
82 }
7.4. Software Necesario para Desplegar la Aplicacion
Para que la aplicacion funcione correctamente se necesita tener instalado el siguiente
software.
Maquina virtual Java SE 6.0
Es necesario tener intalada la maquina virtual de Java SE 6.0 o posterior ya que fue
esta la utilizada en la compilacion de la aplicacion.
Servidor de Aplicaciones Web Apache Tomcat 6.0.20
Es necesario tener intalado un servidor de aplicaciones web, en este caso se utilizara el
servidor Apache Tomcat 6.0.20 o superior.
Gestor de Bases de Datos MySQL 5.0
Se necesita tener instalado el gestor de base de datos MySQL en su version 5.0 o
superior, para almacenar las bases de datos necesarias para el funcionamiento del
sistema desarrollado.
7.4.1. Instalacion y Configuracion del Software Necesario
Junto con la aplicacion se provee ademas del sofware que esta necesita para funcionar, a
continuacion se explica brevemente como intalarlo y configurarlo. El desarrollo e instala-
7.4. Software Necesario para Desplegar la Aplicacion 205
cion de esta aplicacion se realizo en un entorno Linux, concretamente en una distribucion
’Ubuntu 8.10’, por lo que se realizara la explicacion para este sistema operativo.
Para instalar el software se creara un directorio llamado ’software’ dentro de la carpeta
personal del usuario.
Maquina virtual Java SE 6.0
1. Desempaquetar el archivador ’jdk1.6.0 16.tar.gz’.
2. Copiar la carpeta ’jdk1.6.0 16’ resultante en el directorio /usr/lib/jvm/
3. Exportar las variables de entorno JAVA HOME y JRE HOME, y las anadimos
al PATH, anadiendo las siguientes lıneas al final del fichero de configuracion del
interprete de comandos, en este caso sera en ’$HOME/.bashrc’:
1 JAVA_HOME =/ usr/lib/jvm /jdk1 .6.0 _16 /jre/
2 export JAVA_HOME
3 PATH= $JAVA_HOME /bin :$PATH
4
5 JRE_HOME =/usr/lib/jvm/jdk1 .6.0 _16/jre /
6 export JRE_HOME
7 PATH= $JRE_HOME /bin:$PATH
Servidor de Aplicaciones Web Apache Tomcat 6.0.20
1. Desempaquetar el archivador ’apache-tomcat-6.0.20.tar.gz’.
2. Copiar la carpeta ’apache-tomcat-6.0.20’ resultante en el directorio $HOME/-
software/
3. Exportar la variable de entorno CATALINA HOME, y la anadimos al PATH,
anadiendo la siguiente lınea al final del fichero de configuracion del interprete
de comandos, en este caso sera en ’$HOME/.bashrc’:
1 CATALINA_HOME=$HOME /software /apache -tomcat -6.0.20/
2 export CATALINA_HOME
3 PATH= $CATALINA_HOME/bin:$PATH
7.4. Software Necesario para Desplegar la Aplicacion 206
4. Una vez instalado se procede a su configuracion anadiendo la siguiente lınea en
su fichero de configuracion ($HOME/software/apache-tomcat-6.0.20/conf/tomcat-
users.xml)
1 <user name=" tomcat " password =" tomcat " roles ="tomcat ,manager "/>
5. Para arrancar y apagar el servidor se utilizan los scripts ’startup.sh’ y ’shut-
down.sh’ contenidos en el directorio $HOME/software/apache-tomcat-6.0.20/bin/
Gestor de Bases de Datos MySQL 5.0
1. Desempaquetar el archivador ’mysql-5.0.67-linux-i686-glibc23.tar.gz’.
2. Copiar la carpeta ’mysql-5.0.67-linux-i686-glibc23’ resultante en el directorio
$HOME/software/
3. Se crea el directorio donde MySQL debera almacenar las bases de datos, por
ejemplo, $HOME/.MyDATA .
4. Se crea un fichero de configuracion para MySQL en $HOME/.my.cnf con el
siguiente contenido (en este caso es mejor substituir $HOME por la ruta del
directorio personal):
1 [mysqld ]
2 datadir =$HOME /. MyDATA
5. Hay que colocarse dentro del directorio $HOME/software/mysql-5.0.67-linux-
i686-glibc23/ y ejecutar el siguiente comando para crear las bases de datos
’mysql’ y ’test’:
1 scripts / mysql_install_db
6. Exportar la variable de entorno MYSQL HOME, y la anadimos al PATH,
anadiendo la siguiente lınea al final del fichero de configuracion del interprete
de comandos, en este caso sera en ’$HOME/.bashrc’:
7.4. Software Necesario para Desplegar la Aplicacion 207
1 MYSQL_HOME =$HOME/ software /mysql -5.0.67 - linux -i686 -glibc23
2 export MYSQL_HOME
3 PATH= $MYSQL_HOME /bin:$PATH
7. Una vez exportadas las variables de entorno hay que proceder al arranque del
gestor ejecutando el siguiente comando:
1 mysqld
8. Despues de arrancar el servidor de MySQL hay que crear la base de datos que
va a utilizar la aplicacion y darle permisos a esta, para crear la base de datos
se utilizara el comando:
1 mysqladmin -u root create bd_hotel
A continuacion se entra en la consola de MySQL para crear un nuevo y usuario
y darle permisos. Para entrar en la consola hay que ejecutar:
1 mysql -u root
Y para crear el usuario y sus permisos, desde la consola de MySQL se teclea lo
siguiente y se ejecuta (para salir se utiliza el comando ’quit’):
1 GRANT ALL PRIVILEGES ON bd_hotel .*
2 TO hotelapp@localhost IDENTIFIED BY ’hotelapp ’,
3 [email protected] IDENTIFIED BY ’hotelapp ’;
9. Para parar el servidor de MySQL se ejecuta lo siguiente:
1 mysqladmin -u root shutdown
Herramienta Maven para Gestion de Proyectos
Esta herramienta no es necesario instalarla para que la aplicacion funcione, pero es
de gran utilidad para futuras modificaciones o desarrollos.
7.5. Organizacion de los Directorios del Proyecto 208
1. Desempaquetar el archivador ’apache-maven-2.2.1.tar.gz’.
2. Copiar la carpeta ’apache-maven-2.2.1’ resultante en el directorio $HOME/-
software/
3. Exportar la variable de entorno MAVEN HOME, y la anadimos al PATH,
anadiendo la siguiente lınea al final del fichero de configuracion del interprete
de comandos, en este caso sera en ’$HOME/.bashrc’:
1 MAVEN_HOME =$HOME/software /apache -maven -2.2.1
2 export MAVEN_HOME
3 PATH=$MAVEN_HOME /bin :$PATH
4. Una vez exportado el PATH ya se puede utilizar el comando ’mvn’ para arran-
carlo.
7.5. Organizacion de los Directorios del Proyecto
Para la realizacion de este proyecto se ha mantenido la estructura fundamental generada
por la herramienta Maven 2 para proyectos web. Dentro de esta estructura se organizan
todos los elementos necesarios para el funcionamiento de la aplicacacion, de la siguiente
forma:
En /j2ee-hotel-app/src/main/java/es/udc/j2eehotelapp/hotel se encuentran las clases
del modelo de la aplicacion, los DAO, las fachadas, y el modelo del sistema de ofertas.
En /j2ee-hotel-app/src/main/java/es/udc/j2eehotelapp/http es donde se pueden en-
contrar las clases que implementan las acciones del controlador de Struts, ası como los
ActionForms utilizados para manejar los formularios, las clases que forman el controlador
y la cadena de filtros.
En /j2ee-hotel-app/src/main/resources/es/udc/j2eehotelapp/http/view/messages se en-
cuentran los ficheros de las traducciones utilizadas para la internacionalizacion.
7.6. Instrucciones de Compilacion y Despliegue 209
En /j2ee-hotel-app/src/main/resources estan los ficheros utilizados para la configura-
cion de la aplicacion y para configurar las reglas del sistema de ofertas.
En /j2ee-hotel-app/src/main/webapp se encuentra, divididos en subdirectorios segun el
usuario que vaya a hacer uso de ellas, las paginas JSP utilizadas para mostrar la IU de la
aplicacion.
En /j2ee-hotel-app/src/main/webapp/WEB-INF es donde estan los diferentes ficheros
de configuracion del servidor (web.xml), de Struts (plain-struts-config.xml) y de Tiles
(tiles-defs.xml).
7.6. Instrucciones de Compilacion y Despliegue
Estos pasos se explicaran desde dos puntos de vista, tener instalado Maven 2 o no tenerlo
instalado. Este proyecto se ha desarrollado para que en caso de no tener intalado Maven,
se pueda compilar y desplegar sin problemas, se asume que sı se tiene instalado el IDE
Eclipse.
Para ambos casos, una de las primeras cosas que hay que realizar es ejecutar el gestor
de bases de datos MySQL. Para ello se utilizara el comando ’mysqld’.
A continuacion, en caso de no tener instalado Maven se procede a crear las tablas
manualmente utilizando las consultas SQL definidas en el fichero ’CreacionTablas.sql’ o,
utilizando Maven ejecuntando el siguiente comando: ’mvn sql:execute’
Una vez se tiene preparada la base de datos es procede a arrancar el servidor Apache
Tomcat ejecutando el scrip contenido en la carpeta ’bin’ de su instalacion, ’startup.sh’
En la distribucion de este proyecto se entregan dos versiones, una para el desarrollo
con Maven y otra para el desarrollo sin el. Si se esta utilizando Maven, el proyecto se en-
cuentra en ’j2ee-hotel-app’, hay que entrar dentro de esta carpeta y ejecutar los siguientes
comandos para compilar y generar el ’.war’ utilizado para desplegar la aplicacion:
7.6. Instrucciones de Compilacion y Despliegue 210
’mvn clean’ para eliminar cualquier compilacion anterior.
’mvn package’ para compilar y generar el .war para desplegar.
En caso de no utilizar Maven, se usaran los proyectos contenidos en ’hotel’ y ’hotel-app’.
Ambos son dos proyectos de Eclipse, por lo que se pueden importar directamente en este
entorno de desarrollo. En el proyecto hotel-app se encuentra el modelo y el controlador
de la aplicacion y es compilado automaticamente por eclipse. Por otro lado se encuentra
el proyecto ’hotel’ donde estan las paginas JSP, la configuracion de struts, etc. Para que
este segundo proyecto funcione correctamente se debe crear una librerıa .jar del primer
proyecto y copiarla en la raiz de este. Una vez realizado esto hay que proceder a generar
el fichero .war, para lo que se utilizara la herramienta ’jar’, se posiciona justo fuera de
’hotel’ y se ejectuta ’jar cvfm hotel.war hotel’.
Cuando se haya generado el paquete .war se copia en el directorio webapps de la ins-
talacion de Apache Tomcat y para ejecutarlo simplemente se abre el navegador web y se
especifica la siguiente URL: http://localhost:8080/nombrePaquete.
Capıtulo 8
Pruebas
Para probar que todo funciona correctamente se han ido realizando diversos tipos de
pruebas a lo largo del desarrollo del proyecto. Entre estas pruebas destacan las de Unidad,
para las cuales se utilizo el framework JUnit, estas pruebas se realizar para probar que
ante una entrada determinada en un metodo, este siempre devuelve lo esperado.
Se realizaron pruebas de unidad de todos los objetos DAO de sus metodos mas im-
portantes para comprobar que todo el intercambio de informacion con la base de datos
se realizaba correctamente, posteriormente, a medida que se fueron desarrollando las dis-
tintas fachadas del modelo se realizaban pruebas de unidad de los metodos que serıan
utilizados mas frecuentemente y aquellos que realizasen operaciones mas complejas y ver,
de esta forma, que todo funcionase conforme a lo esperado.
Una vez realizadas todas las pruebas de unidad del modelo y viendo que todas tenıan
un resultado positivo, se desarrolla el resto del proceso hasta la interfaz grafica, una vez
hecho esto se hacen diversas pruebas para comprobar que todo funciona conforme a las
especificaciones establecidas por el usuario.
Dos de los casos mas complejos que hubo que probar fueron, la realizacion de reservas,
y que el sistema de ofertas calculase correctamente el descuento para una factura. En
el primer caso se cubrieron todos los pasos posibles de realizacion de reservas: en varios
211
212
pasos, de una sola lınea de reserva, y se comprobaron los posibles casos de error como que
no hubiese habitaciones suficientes.
En el caso de las ofertas, la funcionalidad crıtica que habıa que probar era que calculase
correctamente el conjunto de ofertas compatibles que ofreciera el mayor descuento. Para
ello previamente se establecieron todas las posibles relaciones de incompatibilidad entre
5 ofertas, se realizaron los calculos pertinentes a mano, y se comprobo que el resutado
calculado por el sistema de ofertas era el esperado en todos los casos de prueba.
Capıtulo 9
Planificacion y Evaluacion de
Costes
En este capıtulo se muestra la planificacion del proyecto teniendo en cuenta las fases
de la metodologıa descrita por el Proceso Unificado. Estas fases se han detallado en el
apartado 4.2. Y se puede observar de forma grafica como se preceden unas a otras en el
grafico de Gantt de la figura 9.1. Ademas tambien se puede ver con claridad como hay
en ciertas ocasiones en las cuales se pueden estar realizando dos tareas simultanemente,
estableciendose de esa forma una relacion comienzo-comienzo entre ellas.
Ademas de indicar la planificacion de las diferentes tareas que forma el desarrollo del
proyecto, tambien se hace una evaluacion de los costes de realizacion de dichas tareas.
Para cada tarea se necesita uno o varios empleados, y para la realizacion de este proyecto
se cuenta con un analista y un progamador. El sueldo del analista se ha fijado en 20e/hora
y el del programador en 30e/hora, en estos sueldos se incluye el coste de seguridad social,
el uso de equipos e instalaciones, etc. Y se ha establecido que la jornada laboral sea de
8:00 a 13:00 cada dıa (5 horas/dıa), 5 dıas a la semana.
A continuacion, en la tabla 9.1 se muestra la planificacion de las diferentes tareas y el
coste asociado a cada una de ellas.
213
214
Id Tarea Nombre Inicio Fin Duracion Coste (e) Asignada a
1 Concepcion Abr 14 Abr 20 5d 600 e1.1 + Iteracion 1 (I) Abr 14 Abr 20 5d 600 e1.1.1 ++ Modelado de Negicio (I1) Abr 14 Abr 14 1d 100 e Analista1.1.2 ++ Analisis de Requisitos (I1) Abr 15 Abr 15 1d 100 e Analista1.1.3 ++ Diseno (I1) Abr 16 Abr 16 1d 100 e Analista1.1.4 ++ Implementacion/Pruebas (I1) Abr 17 Abr 20 2d 300 e Programador2 Elaboracion Abr 21 May 1 9d 1100 e2.1 + Iteracion 1 (E) Abr 21 May 1 9d 1100 e2.1.1 ++ Analisis de Requisitos (E1) Abr 21 Abr 22 2d 200 e Analista2.1.2 ++ Diseno (E1) Abr 23 Abr 27 3d 300 e Analista2.1.3 ++ Implementacion/Pruebas (E1) Abr 28 May 1 4d 600 e Programador3 Construccion May 4 Jul 24 60d 10410 e3.1 + Iteracion 1 (C) May 4 May 22 14d 4h 2280 e3.1.1 ++ Analisis de Requisitos (C1) May 4 May 4 4h 80 e Analista3.1.2 ++ Diseno (C1) May 4 May 8 4d 400 e Analista3.1.3 ++ Implementacion/Pruebas (C1) May 6 May 22 12d 1800 e Programador3.2 + Iteracion 2 (C) May 22 Jun 19 20d 1h 3800 e3.2.1 ++ Analisis de Requisitos (Sistema Ofertas) (C2) May 22 May 25 1d 100 e Analista3.2.2 ++ Diseno (Sistema Ofertas) (C2) May 25 May 28 3d 300 e Analista3.2.3 ++ Diseno (C2) May 22 May 28 4d 400 e Analista3.2.4 ++ Implementacion/Pruebas (C2) May 25 Jun 19 20d 3000 e Programador3.3 + Iteracion 3 (C) Jun 22 Jul 24 25d 4330 e3.3.1 ++ Analisis de Requisitos (Sistema Reglas) (C3) Jun 22 Jun 22 4h 80 e Analista3.3.2 ++ Diseno (Sistema Reglas) (C3) Jun 22 Jun 24 2d 200 e Analista3.3.3 ++ Diseno (C3) Jun 22 Jun 24 3d 300 e Analista3.3.4 ++ Implementacion/Pruebas (C3) Jun 22 Jul 24 25d 3750 e Programador4 Transicion Jul 27 Jul 31 5d 725 e4.1 + Iteracion 1 (T) Jul 27 Jul 31 5d 725 e4.1.1 ++ Despliegue (T1) Jul 27 Jul 27 1d 150 e Programador4.1.2 ++ Documentacion de Usuario (T1) Jul 27 Jul 31 5d 575 e Analista, Programador
Total PROYECTO Abr 14 Jul 31 79d 12835 e Analista, Programador
Cuadro 9.1: Planificacion - Tabla de Tareas
215Figura 9.1: Planificacion - Diagrama de Gantt
Capıtulo 10
Conclusiones y Futuras Lıneas de
Trabajo
Al termino del desarrollo de este proyecto se puede decir que se han cumplido todos los
objetivos que habıa que alcanzar con su realizacion.
Uno de los objetivos principales era el aprendizaje de la plataforma J2EE para el desa-
rrollo de aplicaciones web, ası como del resto de tecnologıas especificadas en el capıtulo 1,
alcanzando ası los conocimientos esperados.
Ademas del objetivo didactico, este proyecto cumple con las especificaciones y los re-
quisitos para los cuales estaba orientado. Aunque algunos de estos requisitos tenıan cierta
complejidad, se consiguio de igual forma llevarlos a cabo.
Entre los requisitos que deberıa cumplir destacan los siguientes:
La gestion de usuarios de la aplicacion funciona correctamente y conforme a lo
esperado, alta de nuevos usuarios, baja de usuario, modificacion de sus datos, etc.
Ademas para el recepcionista del hotel se le proporcionan funcionalidades para dar
de alta a nuevos clientes, modificar sus datos, o realizar una busqueda de un cliente
217
218
por varios campos a la vez, de esta forma el recepcionista podra seleccionar al cliente
que desee y trabajar con el.
La gestion de reservas, que era una de las partes algo complejas de la aplicacion, se
consiguio realizar con exito, en esta parte destaca que la seleccion de ofertas la hace
la aplicacion automaticamente despues de haber realizado la reserva, mientras que
en otros productos del mercado esto debe realizarlo el cliente a la hora de reservar
una estancia. Vease la figura 10.1.
Figura 10.1: Gestion de Reservas de Otra Aplicacion
A raız de estos funcionamientos poco correctos de las aplicaciones comerciales actua-
les, se decidio implementar un sistema de ofertas que se aplique automaticamente
cuando se realiza la reserva. Este fue el sistema, con diferencia, mas complejo de
toda la aplicacion, ya que hubo que definir un lenguaje de reglas para las ofertas y
un sistema de resolucion de incompatibilidades.
Ademas de estos subsistemas, se desarrollaron con exito los de gestion de habitacio-
nes, facturas y ofertas.
219
En futuras ampliaciones de este proyecto, se podrıa implementar un sistema de pago que
soporte el pago de una reserva a traves de diferentes medios, PayPal, tarjeta de credito,
etc.
Otra posible ampliacion serıa la realizacion de un gestor de contenido para el portal
del Hotel. Este gestor de contenido deberıa posibilidar la publicacion de noticias y su
internacionalizacion, y una gestion de las fotografıas de la galerıa.
Apendice A
Manuales para la Utilizacion de la
Aplicacion
Esta aplicacion es muy facil de utilizar e intuitiva, pero hay algunos aspectos, como las
operaciones que debe realizar el usuario que no lo son tanto y deben ser explicadas. Por
esta razon se crean estos manuales de usuario.
A.1. Manual Comun a Todos
Cuando se entra la aplicacion y aun no se ha autenticado, simplemente se ve la pagina
principal que contiene noticias y las ofertas disponibles actualmente, pero ademas de eso
el usuario que no esta autenticado solo podrıa acceder al contenido estatico del portal,
como puede ser la galerıa de imagenes.
La pagina principal, como se puede ver en la figura A.1 ofrece diversas operaciones,
aparte de navegar por el contenido estatico permite registrarse como nuevo usuario y
autentificarse si ya se esta registrado.
221
A.1. Manual Comun a Todos 222
Figura A.1: Pagina Principal del Portal
Si el usuario decide darse de alta debe hacer clic en donde pone ’Registrarse’ y esto lo
llevara al formulario de registro que se muestra en la figura A.2 que debe cubrir con sus
datos personales.
Figura A.2: Pagina Registro de Nuevo Usuario
A.1. Manual Comun a Todos 223
Si por otro lado el usuario ya esta registrado y desea entrar en la aplicacion, debera pin-
char sobre ’Autentificacion’ y esto lo llevara a la pagina de autentificacion que se muestra
en la figura A.3 donde ingresara su nombre de usuario en la aplicacion y su contrasena.
Figura A.3: Pagina Autentificacion
Una vez introducidos los datos, se le da a entrar y esto lleva al usuario a su pagina
principal, que variara dependiendo de su rol dentro del sistema, en este caso habra tres
tipos de usuarios distintos: Usuario/Cliente, Recepcionista y Administrador. Se mostraran
sus paginas principales en sus respectivos manuales de usuario.
A.2. Manual Especıfico para el Usuario 225
A.2. Manual Especıfico para el Usuario
Una vez autentificado en el sistema, se le presenta al usuario su pagina principal, como
se muestra en la figura A.4, donde podra elegir diversas acciones como: cambiar sus datos,
hacer nuevas reservas, consultar reservas, etc.
Figura A.4: Pagina Principal del Usuario
Aquı en la pagina principal se le muestran al usuario las distintas operaciones que puede
realizar en un panel lateral izquierdo, ordenadas por categorıas. Estas categorıas son:
’Personal’ y ’Reservas’.
’Personal’ contiene las siguientes operaciones: ’Actualizar info. registro’, ’Salir’ y ’Darse
de baja’. Y la categorıa de ’Reservas’ tiene: ’Nueva Reserva’ y ’Ver Reservas’.
A continuacion se explican cada una de las operaciones por separado:
Actualizar info. registro
Esta operacion presenta un formulario como el de la figura A.2 en el cual el usuario
podra cambiar la informacion de su perfil cuando desee. Ademas si quiere tambien
A.2. Manual Especıfico para el Usuario 226
podra cambiar su contrasena escribiendo simplemente una nueva, dejando ese campo
en blanco si no lo quiere hacer.
Salir
Esta operacion realiza la simple accion de salir de la cuenta, por lo que el usuario
deja de estar autentificado, si desea volver a entrar debera autentificarse de nuevo.
Darse de Baja
Esta operacion permite al usuario darse de baja en el sistema, pero antes de hacerlo
se le muestra una pagina de aviso como la de la figura A.5 en la que se le pregunta
si desea de verdad darse de baja, si responde afirmativamente, deja de estar dado de
alta en el sistema.
Figura A.5: Pagina de Aviso al Darse de Baja
Nueva Reserva
Esta operacion permite al usuario crear una nueva reserva para los dıas que desee.
El usuario podra anadir en una misma reserva, estancias para diferentes dıas y tipos
de habitacion, para realizar dicha operacion se le muestra un formulario como el de
la figura A.6.
A.2. Manual Especıfico para el Usuario 227
Figura A.6: Pagina para Realizar una Nueva Reserva
El usuario debe cumplimentar todos los campos, en primer lugar tiene que elegir el
tipo de habitacion que desea reservar, luego debe especificar la fecha de entrada y
de salida y por ultimo tiene que indicar el numero de habitaciones de ese tipo que
desea. Para anadir a la reserva la nueva estancia debera darle a ’Anadir’ o ’Anadir
y Finalizar’ si le da al boton de Anadir luego podra seguir creando nuevas estancias
para la reserva actual, y cuando lo desee le dara a ’Finalizar’ esto creara una nueva
reserva y comunicara al usuario el numero de esta para que la pueda consultar en
sus reservas mediante la operacion de ’Ver Reservas’.
Si en algun momento el usuario cumplimenta de forma erronea algun campo o no
hay habitaciones disponibles para cubrir su solicitud se le comunicara para que, si
lo desea pueda cambiar las preferencias de su estancia.
Ver Reservas
Esta operacion permite al usuario todas las reservas que haya realizado hasta el
momento, ya esten pagadas, canceladas o que ya se hayan disfrutado. Se mostraran
en forma de lista como se puede observar en la figura A.7 y si tuviese mas de diez
reservas se paginarıa el resultado. Ademas en cada una de las reservas se permite al
A.2. Manual Especıfico para el Usuario 228
usuario realizar una serie de operaciones: ’Ver Factura’, ’Cancelar’ o consultar los
datos de la reserva y, si aun no se ha pagado ni disfrutado, modificarla.
Figura A.7: Pagina para Listar las Reservas
Si se desean consultar las estancias reservadas y/o modificarlas si es posible, basta
con hacer clic en ’Cod. Reserva n’ y entrar ası en un formulario a traves del cual
consultar y modificar su reserva.
El formulario para modificar una reserva se muestra en la figura A.8 y permite ir
eliminando y creando nuevas reservas de estancias y guardar los cambios realizados
o cancelar el proceso cuando se estime oportuno. El formulario para anadir nuevas
estancias es el mismo que el que se utilizaba en crear nueva reserva, pero con menos
botones ya que ahora solo seran necesarios ’Anadir’ y ’Cancelar’.
Ademas de modificar una reserva, en la lista tambien se ofrece la posibilidad de
cancelarla si aun no se ha disfrutado. Simplemente haciendo clic en ’Cancelar’ la
reserva queda cancelada y en la columna de total aparecera el recargo que se le
cobro al cliente por esta cancelacion si previamente la reserva habıa sido pagada.
A.2. Manual Especıfico para el Usuario 229
Figura A.8: Pagina para Modificar una Reserva
Por otro lado se puede observar la factura de una reserva haciendo clic en ’Factura’.
Si la factura ya se habıa pagado esta aparecera marcada como pagada, y si no lo
habıa sido se mostrara la opcion de pagar. Esto se muestra en la figura A.9.
Figura A.9: Pagina para Mostrar el Borrador de una Factura
A.2. Manual Especıfico para el Usuario 230
En el apartado de ’Descuento’ se muestra el descuento conjunto que proporcionan
todas aquellas ofertas que sean compatibles y se puedan aplicar en cada una de las
lıneas de la factura. Este calculo lo hace automaticamente el sistema. Si el importe
convence al cliente, este solo tendra que proceder al pago de la factura a traves del
boton ’Pagar’ y cuando el pago este realizado la factura se muestra como pagada
como en la figura A.10.
Figura A.10: Pagina para Mostrar una Factura Pagada
A.3. Manual Especıfico para el Recepcionista 231
A.3. Manual Especıfico para el Recepcionista
Una vez autentificado en el sistema, se le presenta al recepcionista su pagina principal,
como se muestra en la figura A.11, donde podra elegir diversas acciones como: cambiar
sus datos, dar de alta un cliente, buscar un cliente, hacer nuevas reservas para un cliente,
consultar reservas de un cliente, ver habitaciones, etc.
Figura A.11: Pagina Principal del Recepcionista
Aquı en la pagina principal se le muestran al recepcionista las distintas operaciones que
puede realizar en un panel lateral izquierdo, ordenadas por categorıas. Estas categorıas
son: ’Clientes’, ’Habitaciones’ y ’Personal’.
’Personal’ contiene las siguientes operaciones: ’Actualizar info. registro’ y ’Salir’. Estas
operaciones son las mismas que se le ofrecen a un usuario normal, consultar las operaciones
’Actualizar info. registro’ y ’Salir’ en las paginas 225 y 226. En la categorıa ’Habitaciones’
se muestra la operacion ’Ver habitaciones’ y en ’Clientes’ se muestran ’Nuevo Cliente’ y
’Buscar Cliente’.
A.3. Manual Especıfico para el Recepcionista 232
A continuacion se explican cada una de las operaciones por separado:
Ver Habitaciones
Esta operacion permite al recepcionista ver las habitaciones del hotel para luego
consultar los datos de cada una en particular. Para esto se le muestra al recepcionista
una lista de habitaciones como la de la figura A.12
Figura A.12: Pagina para Listar las Habitaciones para el Recpecionista
Para consultar los datos especıficos de un tipo de habitacion simplemente basta
con presionar el enlace sobre el tipo de habitacion y se mostraran los datos en un
formulario como el que se muestra en la figura A.13
A.3. Manual Especıfico para el Recepcionista 233
Figura A.13: Pagina para Mostrar los Datos de un Tipo de Habitacion
Nuevo Cliente
Esta operacion permite al recepcionista dar de alta a un nuevo cliente, para ello
se le muestra un formulario como el de la figura A.14 donde el recepcionista debe
cumplimentar los datos personales del nuevo cliente.
Una vez cumplimentados los datos ya puede trabajar con el cliente dado de alta de
la misma forma que si lo buscase y le diese a seleccionar cliente como se explicara en
la siguiente operacion ’Buscar Cliente’
A.3. Manual Especıfico para el Recepcionista 234
Figura A.14: Pagina para Dar de Alta un Nuevo Cliente
Buscar Cliente
Esta operacion permite al recepcionista buscar a un cliente especificando parte o la
totalidad de su nombre, apellidos y/o DNI. Para realizarlo se le presenta un formula-
rio como el que se muestra en la figura A.15 en el cual introduce los parametros por
los que se desea buscar y se presiona el boton de ’Buscar’. Luego se muestra una lista
de los clientes que concuerdan con los parametros de busqueda como la de la figura
A.16 en donde proporciona la posibilidad de seleccionar el cliente que se desee para
trabajar con el, es decir, para poder realizarle reservas, consultarlas, etc. Una vez
seleccionado el cliente deseado se vuelve a la pagina principal del recepcionista, pero
en este caso se muestran opciones a mayores como se puede observar en la figura
A.17.
A.3. Manual Especıfico para el Recepcionista 235
Figura A.15: Pagina para Buscar Clientes
Figura A.16: Pagina para Listar los Clientes Buscados
A.3. Manual Especıfico para el Recepcionista 236
Figura A.17: Pagina Principal del Recepcionista Despues de Seleccionar Cliente
Como se puede observar ahora aumentan las categorıas y las operaciones que se
pueden realizar, puesto que ahora se pueden hacer cosas en nombre del cliente que
se ha seleccionado.
La nueva categorıa que aparece es ’Reservas’ en la cual aparecen las opciones de
’Nueva Reserva’ y ’Ver Reservas’. Ademas en la categorıa ’Clientes’ aparecen nuevas
operaciones como son: ’Ver/Actualizar Perfil del Cliente’, ’Cerrar Cuenta del Cliente’
o ’Dar de Baja Cliente’.
Nueva Reserva
Esta operacion permite al recepcionista realizar una reserva a peticion de un cliente,
el proceso que se sigue es el mismo explicado en la pagina 226 en la operacion ’Nueva
Reserva’.
Ver Reservas
A.3. Manual Especıfico para el Recepcionista 237
Esta operacion permite al recepcionista ver las reservas hechas por un cliente para,
en caso necesario, localizar y pagar o cancelar una reserva concreta a peticion de
un cliente. Estos procesos son exactamente iguales a los explicados para un usuario
normal en la operacion ’Ver Reservas’ en la pagina 227.
Ver/Actualizar Perfil del Cliente
Esta operacion permite al recepcionista ver la informacion del perfil de un cliente
y editarla si fuese necesario como si se tratase del propio cliente solo que no se
le permite, por ejemplo, cambiar la contrasena. Para ello se le presenta el mismo
formulario que el mostrado para realizar la operacion de ’Nuevo Cliente’ que se
puede ver en la pagina 233
Cerrar Cuenta del Cliente
Esta operacion permite al recepcionista cerrar la cuenta del cliente con el que esta tra-
bajando, pasando a su pagina principal como se mostraba en la figura A.11 de la
pagina 231. Si desea volver a trabajar con ese u otro cliente debera volver a buscarlo
y seleccionarlo.
Dar de Baja Cliente
Esta operacion permite al recepcionista dar de baja a un cliente del sistema a peticion
de este, tan pronto como lo haga se le mostrara un mensaje de aviso como el de la
figura A.5 de la pagina 226, indicando al recepcionista que debe alertar al cliente y
persuadirlo para que no se de de baja. Si el recepcionista confirma de todas formas
que desea realizar la operacion el cliente deja de estar dado de alta en el sistema y
por lo tanto se vuelve a la pagina principal del recepcionista de la figura A.11 de la
pagina 231.
A.4. Manual Especıfico para el Administrador 239
A.4. Manual Especıfico para el Administrador
Una vez autentificado en el sistema, se le presenta al administrdor su pagina principal,
como se muestra en la figura A.18, donde podra elegir diversas acciones como: cambiar
sus datos, crear y administrar las ofertas, dar de alta habitaciones y modificar su precio.
Figura A.18: Pagina Principal del Administrador
Aquı en la pagina principal se le muestran al administrador las distintas operaciones que
puede realizar en un panel lateral izquierdo, ordenadas por categorıas. Estas categorıas
son: ’Personal’, ’Ofertas’ y ’Habitaciones’.
’Personal’ contiene las siguientes operaciones: ’Actualizar info. registro’ y ’Salir’. Las
operaciones de esta categorıa son las mismas que se le proporcionan a un usuario normal,
por lo que se pueden ver en la pagina 225. En la categorıa de ’Ofertas’ se tienen operaciones
que permiten ’Crear Ofertas’ y ’Ver Ofertas’. En la tercera categorıa, ’Habitaciones’, se
le proporcionan las siguientes opciones: ’Nueva Habitacion’, ’Ver Habitaciones’ y ’Anadir
Incidencia’.
A.4. Manual Especıfico para el Administrador 240
A continuacion se explican cada una de las operaciones por separado:
Crear Ofertas
Esta operacion presenta un formulario como el de la figura A.19 en el cual el ad-
ministrador debe introducir los datos necesarios para dar de alta una nueva oferta,
como se puede observar en la figura A.20.
Figura A.19: Pagina para Crear una Nueva Oferta
A.4. Manual Especıfico para el Administrador 241
Figura A.20: Pagina para Crear una Nueva Oferta (Rellenada)
En primer lugar se debe elegir el tipo de oferta al que se desea que pertenezca la
oferta de entre los que se proporcionan. Si lo que se quiere es crear un nuevo tipo
de oferta simplemente habra que anadirlo pinchando sobre el enlace ’Nuevo Tipo de
Oferta’ como se explicara mas adelante.
Luego se cubriran las fechas de inicio de aplicacion y de fin, el descuento que se
quiere que proporcione la oferta y la regla que tiene que definir cuando se pue-
de aplicar la oferta. Para definir la regla se utiliza la nomenclatura ’NombreRe-
gla1:Argumento1 &&NombreRegla2:Argumento1,[...],ArgumentoN &&[...] &&Nom-
breReglaN:Argumento1,Argumento2’ pero sin ningun tipo de espacios. A continua-
cion se detallan los Nombre de Regla disponibles y sus argumentos necesarios:
• PersonBornBefore:(Dıa),(Mes),(Ano) Esta regla sirve para definir que se
le aplique la oferta a las personas que hayan nacido antes de la fecha indi-
cada.
◦ (Dıa): Numero entero especificando el dıa.
◦ (Mes): Numero entero especificando el mes.
A.4. Manual Especıfico para el Administrador 242
◦ (Ano): Numero entero especificando el ano.
• PersonBornAfter:(Dıa),(Mes),(Ano) Esta regla sirve para definir que se
le aplique la oferta a las personas que hayan nacido despues de la fecha
indicada.
◦ (Dıa): Numero entero especificando el dıa.
◦ (Mes): Numero entero especificando el mes.
◦ (Ano): Numero entero especificando el ano.
• PersonFrom:(Paıs) Esta regla sirve para definir que se le aplique la oferta a
las personas de cierto Paıs
◦ (Paıs): Nombre del paıs.
• ReservationDoneBefore:(Dıa),(Mes),(Ano) Esta regla sirve para definir
que se le aplique la oferta a los clientes que realicen la reserva (que la
paguen) antes de la fecha indicada.
◦ (Dıa): Numero entero especificando el dıa.
◦ (Mes): Numero entero especificando el mes.
◦ (Ano): Numero entero especificando el ano.
• true Esta regla sirve para definir que se le aplique la oferta a todas las personas.
Como ya se ha mencionado, si el administrador lo desea puede dar de alta un nue-
vo tipo de oferta, teniendo en cuenta que debe definir diferentes aspectos, como
por ejemplo las incompatibilidades, y aquellos conjuntos de productos a los que es
aplicable el tipo de oferta creado. Para realizar esta operacion se le muestra al ad-
ministrador un formulario como el de la figura A.21 y al darle a ’Crear’ el nuevo
tipo aparece disponible para ser seleccionado en el formulario que se acaba de ver
para crear una oferta y sera creado de verdad cuando se cree la nueva oferta que lo
utilice.
En este formulario se deben cumplimentar: el nombre del nuevo tipo de oferta y una
descripcion de este. Ademas se mostraran una lista de posibles productos a los que
A.4. Manual Especıfico para el Administrador 243
Figura A.21: Pagina para Crear un Nuevo Tipo de Oferta
podra ser aplicable la oferta de los cuales se eligiran los que se deseen, indicando a
su vez la cantidad mınima que se debe ordenar para que se aplique la oferta. Por
otro lado apareceran tambien todos los tipos de oferta que haya hasta el momento
dados de alta en el sistema, y se deben marcar aquellos con los que se desea que el
nuevo tipo sea incompatible, es decir, aquellos tipos de oferta con los cuales no se
pueda aplicar conjuntamente una oferta del nuevo tipo que se esta creando.
Ver Ofertas
Esta operacion permite al administrador ver las ofertas que existen actualmente en el
sistema, la publicadas, las que no lo estan y los borradores. Las ofertas se mostraran
en una lista como la que se muestra en la figura A.22 y desde la cual se podra acceder
para ver los datos de una oferta en particular o un tipo de oferta.
Si se desean realizar operaciones con una oferta en particular basta con hacer clic
encima de su identificador y esto mostrara un formulario como el de la figura A.23
indicando las operaciones que podemos realizar con ella. Si la reserva aun esta mar-
cada como borrador se podran modificar sus datos, borrarla o publicarla, pero si ya
no es borrador solo se podra publicar en caso de que aun no lo este y ’despublicar’
A.4. Manual Especıfico para el Administrador 244
Figura A.22: Pagina para Listar las Ofertas
si ya habıa sido publicada. Se le ofrece este mecanismo al administrador por si por
error publica una oferta que no deberıa.
Figura A.23: Pagina para Realizar Operaciones con las Ofertas
A.4. Manual Especıfico para el Administrador 245
Ademas de proporcionar la opcion de consultar los datos de una oferta y modificarlos
tambien se le permite al administrador consultar y modificar los datos de un tipo de
oferta a traves del formulario que se muestra en la figura A.24. Para ello simplemente
debe hacer clic en el nombre del tipo de oferta que aparece en la lista de ofertas en
la columna correspondiente.
Figura A.24: Pagina para Realizar Operaciones con los Tipos de Ofertas
Nueva Habitacion
Esta operacion permite al administrador dar de alta una nueva habitacion en el
sistema. Esto lo debe hacer tan pronto como desee que el sistema se pueda utilizar,
ya que si no hay habitaciones no se pueden hacer reservas. Para dar de alta una
habitacion se muestra al administrador un formulario como el de la figura A.25 donde
debera especificar el numero que tendra la habitacion, el piso en el que estara la
habitacion y el precio extra que puede tener esta a mayores del precio que establezca
el tipo de habitacion.
A.4. Manual Especıfico para el Administrador 246
Figura A.25: Pagina para Dar de Alta una Habitacion
El tipo al que pertenecera, lo puede elegir de la lista, pero si no esta el deseado
debera crear uno que se ajuste a lo que necesia haciendo clic en ’Nuevo Tipo de
Habitacion’. Esta operacion de nuevo tipo, le permite al administrador crear un
nuevo tipo de habitacion a traves de un formulario como el que se muestra en la
figura A.26 donde debe especificar una breve descripcion, el numero de personas al
que esta destinado y el precio base que costara.
Figura A.26: Pagina para Crear un Nuevo Tipo de Habitacion
A.4. Manual Especıfico para el Administrador 247
Ver Habitaciones
Esta operacion permite al administrador ver las habitaciones que estan dadas de alta
actualmente en el sistema. Las habitaciones se mostraran en una lista como la que
se muestra en la figura A.27 y desde la cual se podra acceder para ver los datos de
una oferta en particular o un tipo de oferta.
Figura A.27: Pagina para Listar las Habitaciones para el Administrador
Para consultar los datos especıficos de una habitacion el administrador tiene que
hacer clic en ’Habitacion numero n’ y esto le mostrara un formulario como el de la
figura A.28 mediante el cual podra consultar los datos de la habitacion deseada o
modificarlos si lo desea.
A.4. Manual Especıfico para el Administrador 248
Figura A.28: Pagina para Consultar/Modificar los Datos de una Habitacion
Ademas se proporciona la opcion de consultar yo modificar los datos de un tipo
de habitacon a traves del formulario que se muestra en la figura A.29. Para ello
simplemente debe hacer clic en el nombre del tipo de habitacion que aparece en la
lista de habitaciones en la columna correspondiente.
Figura A.29: Pagina para Consultar/Modificar los Datos de un Tipo de Habitacion
A.4. Manual Especıfico para el Administrador 249
Por otro lado en cada lınea de la lista se proporciona un enlace para que el ad-
ministrador pueda ver las incidencias de esa habitacion simplemente pinchando en
el. Al realizarlo se le muestra una lista con todas las incidencias registradas en esa
habitacion como se puede observar en la figura A.30.
Figura A.30: Pagina para Listar las Incidencias de una Habitacion
Anadir Incidencia
Esta operacion permite al administrador registrar una incidencia ocurrida en una
habitacion. Para realizar este cometido se le presenta un formulario como el de la
figura A.31 donde el administrador debe cubrir lo siguiente: elegir la habitacion
a la que esta relacionada la incidencia, definir el tipo de gravedad de la incidencia
(meramente informativo, a definir por el administrador), y una descripcion completa
de lo ocurrido.
A.4. Manual Especıfico para el Administrador 250
Figura A.31: Pagina para Registrar una Incidencia de una Habitacion
Apendice B
Licencia del Proyecto - GPLv31
A continuacion se muestra el contenido de esta licencia, aunque por motivos de validez
legal se provee en ingles, se puede consultar una version traducida en el siguiente enlace:
http://www.viti.es/gnu/licenses/gpl.html
B.1. General Public License (Version 3)
Version 3, 29 June 2007
Copyright c© 2007 Free Software Foundation, Inc. http://fsf.org/
Everyone is permitted to copy and distribute verbatim copies of this
license document, but changing it is not allowed.
The GNU General Public License is a free, copyleft license for software and other kinds
of works.
The licenses for most software and other practical works are designed to take away your
freedom to share and change the works. By contrast, the GNU General Public License is
intended to guarantee your freedom to share and change all versions of a program–to make
sure it remains free software for all its users. We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to any other work
released this way by its authors. You can apply it to your programs, too.
When we speak of free software, we are referring to freedom, not price. Our General
Public Licenses are designed to make sure that you have the freedom to distribute copies
1General Public License version 3
251
B.1. General Public License (Version 3) 252
of free software (and charge for them if you wish), that you receive source code or can get
it if you want it, that you can change the software or use pieces of it in new free programs,
and that you know you can do these things.
To protect your rights, we need to prevent others from denying you these rights or asking
you to surrender the rights. Therefore, you have certain responsibilities if you distribute
copies of the software, or if you modify it: responsibilities to respect the freedom of others.
For example, if you distribute copies of such a program, whether gratis or for a fee, you
must pass on to the recipients the same freedoms that you received. You must make sure
that they, too, receive or can get the source code. And you must show them these terms
so they know their rights.
Developers that use the GNU GPL protect your rights with two steps: (1) assert copy-
right on the software, and (2) offer you this License giving you legal permission to copy,
distribute and/or modify it.
For the developers’ and authors’ protection, the GPL clearly explains that there is no
warranty for this free software. For both users’ and authors’ sake, the GPL requires that
modified versions be marked as changed, so that their problems will not be attributed
erroneously to authors of previous versions.
Some devices are designed to deny users access to install or run modified versions of the
software inside them, although the manufacturer can do so. This is fundamentally incom-
patible with the aim of protecting users’ freedom to change the software. The systematic
pattern of such abuse occurs in the area of products for individuals to use, which is pre-
cisely where it is most unacceptable. Therefore, we have designed this version of the GPL
to prohibit the practice for those products. If such problems arise substantially in other
domains, we stand ready to extend this provision to those domains in future versions of
the GPL, as needed to protect the freedom of users.
Finally, every program is threatened constantly by software patents. States should not
allow patents to restrict development and use of software on general-purpose computers,
but in those that do, we wish to avoid the special danger that patents applied to a free
program could make it effectively proprietary. To prevent this, the GPL assures that
patents cannot be used to render the program non-free.
The precise terms and conditions for copying, distribution and modification follow.
Terms and Conditions
0. Definitions.
“This License” refers to version 3 of the GNU General Public License.
B.1. General Public License (Version 3) 253
“Copyright” also means copyright-like laws that apply to other kinds of works, such
as semiconductor masks.
“The Program” refers to any copyrightable work licensed under this License. Each
licensee is addressed as “you”. “Licensees” and “recipients” may be individuals or
organizations.
To “modify” a work means to copy from or adapt all or part of the work in a
fashion requiring copyright permission, other than the making of an exact copy. The
resulting work is called a “modified version” of the earlier work or a work “based
on” the earlier work.
A “covered work” means either the unmodified Program or a work based on the
Program.
To “propagate” a work means to do anything with it that, without permission, would
make you directly or secondarily liable for infringement under applicable copyright
law, except executing it on a computer or modifying a private copy. Propagation
includes copying, distribution (with or without modification), making available to
the public, and in some countries other activities as well.
To “convey” a work means any kind of propagation that enables other parties to
make or receive copies. Mere interaction with a user through a computer network,
with no transfer of a copy, is not conveying.
An interactive user interface displays “Appropriate Legal Notices” to the extent
that it includes a convenient and prominently visible feature that (1) displays an
appropriate copyright notice, and (2) tells the user that there is no warranty for the
work (except to the extent that warranties are provided), that licensees may convey
the work under this License, and how to view a copy of this License. If the interface
presents a list of user commands or options, such as a menu, a prominent item in
the list meets this criterion.
1. Source Code.
The “source code” for a work means the preferred form of the work for making
modifications to it. “Object code” means any non-source form of a work.
A “Standard Interface” means an interface that either is an official standard defined
by a recognized standards body, or, in the case of interfaces specified for a particular
programming language, one that is widely used among developers working in that
language.
The “System Libraries” of an executable work include anything, other than the work
as a whole, that (a) is included in the normal form of packaging a Major Component,
B.1. General Public License (Version 3) 254
but which is not part of that Major Component, and (b) serves only to enable use
of the work with that Major Component, or to implement a Standard Interface for
which an implementation is available to the public in source code form. A “Major
Component”, in this context, means a major essential component (kernel, window
system, and so on) of the specific operating system (if any) on which the executable
work runs, or a compiler used to produce the work, or an object code interpreter
used to run it.
The “Corresponding Source” for a work in object code form means all the source
code needed to generate, install, and (for an executable work) run the object code
and to modify the work, including scripts to control those activities. However, it
does not include the work’s System Libraries, or general-purpose tools or generally
available free programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source includes interface
definition files associated with source files for the work, and the source code for shared
libraries and dynamically linked subprograms that the work is specifically designed
to require, such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users can regenerate au-
tomatically from other parts of the Corresponding Source.
The Corresponding Source for a work in source code form is that same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of copyright on the
Program, and are irrevocable provided the stated conditions are met. This License
explicitly affirms your unlimited permission to run the unmodified Program. The
output from running a covered work is covered by this License only if the output,
given its content, constitutes a covered work. This License acknowledges your rights
of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not convey, without
conditions so long as your license otherwise remains in force. You may convey covered
works to others for the sole purpose of having them make modifications exclusively
for you, or provide you with facilities for running those works, provided that you
comply with the terms of this License in conveying all material for which you do not
control copyright. Those thus making or running the covered works for you must
do so exclusively on your behalf, under your direction and control, on terms that
prohibit them from making any copies of your copyrighted material outside their
relationship with you.
B.1. General Public License (Version 3) 255
Conveying under any other circumstances is permitted solely under the conditions
stated below. Sublicensing is not allowed; section 10 makes it unnecessary.
3. Protecting Users’ Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological measure under any
applicable law fulfilling obligations under article 11 of the WIPO copyright treaty
adopted on 20 December 1996, or similar laws prohibiting or restricting circumven-
tion of such measures.
When you convey a covered work, you waive any legal power to forbid circumvention
of technological measures to the extent such circumvention is effected by exercising
rights under this License with respect to the covered work, and you disclaim any
intention to limit operation or modification of the work as a means of enforcing,
against the work’s users, your or third parties’ legal rights to forbid circumvention
of technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program’s source code as you receive it,
in any medium, provided that you conspicuously and appropriately publish on each
copy an appropriate copyright notice; keep intact all notices stating that this License
and any non-permissive terms added in accord with section 7 apply to the code; keep
intact all notices of the absence of any warranty; and give all recipients a copy of
this License along with the Program.
You may charge any price or no price for each copy that you convey, and you may
offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to produce it
from the Program, in the form of source code under the terms of section 4, provided
that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified it, and giving
a relevant date.
b) The work must carry prominent notices stating that it is released under this
License and any conditions added under section 7. This requirement modifies
the requirement in section 4 to “keep intact all notices”.
c) You must license the entire work, as a whole, under this License to anyone who
comes into possession of a copy. This License will therefore apply, along with
any applicable section 7 additional terms, to the whole of the work, and all its
B.1. General Public License (Version 3) 256
parts, regardless of how they are packaged. This License gives no permission to
license the work in any other way, but it does not invalidate such permission if
you have separately received it.
d) If the work has interactive user interfaces, each must display Appropriate Legal
Notices; however, if the Program has interactive interfaces that do not display
Appropriate Legal Notices, your work need not make them do so.
A compilation of a covered work with other separate and independent works, which
are not by their nature extensions of the covered work, and which are not combined
with it such as to form a larger program, in or on a volume of a storage or distribution
medium, is called an “aggregate” if the compilation and its resulting copyright are
not used to limit the access or legal rights of the compilation’s users beyond what
the individual works permit. Inclusion of a covered work in an aggregate does not
cause this License to apply to the other parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms of sections 4
and 5, provided that you also convey the machine-readable Corresponding Source
under the terms of this License, in one of these ways:
a) Convey the object code in, or embodied in, a physical product (including a
physical distribution medium), accompanied by the Corresponding Source fixed
on a durable physical medium customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product (including a
physical distribution medium), accompanied by a written offer, valid for at least
three years and valid for as long as you offer spare parts or customer support
for that product model, to give anyone who possesses the object code either
(1) a copy of the Corresponding Source for all the software in the product that
is covered by this License, on a durable physical medium customarily used for
software interchange, for a price no more than your reasonable cost of physically
performing this conveying of source, or (2) access to copy the Corresponding
Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the written offer to
provide the Corresponding Source. This alternative is allowed only occasionally
and noncommercially, and only if you received the object code with such an
offer, in accord with subsection 6b.
d) Convey the object code by offering access from a designated place (gratis or
for a charge), and offer equivalent access to the Corresponding Source in the
B.1. General Public License (Version 3) 257
same way through the same place at no further charge. You need not require
recipients to copy the Corresponding Source along with the object code. If the
place to copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party) that supports
equivalent copying facilities, provided you maintain clear directions next to the
object code saying where to find the Corresponding Source. Regardless of what
server hosts the Corresponding Source, you remain obligated to ensure that it
is available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided you inform
other peers where the object code and Corresponding Source of the work are
being offered to the general public at no charge under subsection 6d.
A separable portion of the object code, whose source code is excluded from the
Corresponding Source as a System Library, need not be included in conveying the
object code work.
A “User Product” is either (1) a “consumer product”, which means any tangible
personal property which is normally used for personal, family, or household purposes,
or (2) anything designed or sold for incorporation into a dwelling. In determining
whether a product is a consumer product, doubtful cases shall be resolved in favor
of coverage. For a particular product received by a particular user, “normally used”
refers to a typical or common use of that class of product, regardless of the status of
the particular user or of the way in which the particular user actually uses, or expects
or is expected to use, the product. A product is a consumer product regardless of
whether the product has substantial commercial, industrial or non-consumer uses,
unless such uses represent the only significant mode of use of the product.
“Installation Information” for a User Product means any methods, procedures, aut-
horization keys, or other information required to install and execute modified versions
of a covered work in that User Product from a modified version of its Corresponding
Source. The information must suffice to ensure that the continued functioning of
the modified object code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or specifically for
use in, a User Product, and the conveying occurs as part of a transaction in which
the right of possession and use of the User Product is transferred to the recipient in
perpetuity or for a fixed term (regardless of how the transaction is characterized),
the Corresponding Source conveyed under this section must be accompanied by the
Installation Information. But this requirement does not apply if neither you nor any
B.1. General Public License (Version 3) 258
third party retains the ability to install modified object code on the User Product
(for example, the work has been installed in ROM).
The requirement to provide Installation Information does not include a requirement
to continue to provide support service, warranty, or updates for a work that has been
modified or installed by the recipient, or for the User Product in which it has been
modified or installed. Access to a network may be denied when the modification
itself materially and adversely affects the operation of the network or violates the
rules and protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided, in accord
with this section must be in a format that is publicly documented (and with an
implementation available to the public in source code form), and must require no
special password or key for unpacking, reading or copying.
7. Additional Terms.
“Additional permissions” are terms that supplement the terms of this License by
making exceptions from one or more of its conditions. Additional permissions that
are applicable to the entire Program shall be treated as though they were included
in this License, to the extent that they are valid under applicable law. If additional
permissions apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by this License
without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option remove any
additional permissions from that copy, or from any part of it. (Additional permissions
may be written to require their own removal in certain cases when you modify the
work.) You may place additional permissions on material, added by you to a covered
work, for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you add to a covered
work, you may (if authorized by the copyright holders of that material) supplement
the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the terms of sections
15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or author attribu-
tions in that material or in the Appropriate Legal Notices displayed by works
containing it; or
c) Prohibiting misrepresentation of the origin of that material, or requiring that
modified versions of such material be marked in reasonable ways as different
from the original version; or
B.1. General Public License (Version 3) 259
d) Limiting the use for publicity purposes of names of licensors or authors of the
material; or
e) Declining to grant rights under trademark law for use of some trade names,
trademarks, or service marks; or
f ) Requiring indemnification of licensors and authors of that material by anyo-
ne who conveys the material (or modified versions of it) with contractual as-
sumptions of liability to the recipient, for any liability that these contractual
assumptions directly impose on those licensors and authors.
All other non-permissive additional terms are considered “further restrictions” within
the meaning of section 10. If the Program as you received it, or any part of it,
contains a notice stating that it is governed by this License along with a term that
is a further restriction, you may remove that term. If a license document contains a
further restriction but permits relicensing or conveying under this License, you may
add to a covered work material governed by the terms of that license document,
provided that the further restriction does not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you must place, in
the relevant source files, a statement of the additional terms that apply to those files,
or a notice indicating where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the form of a
separately written license, or stated as exceptions; the above requirements apply
either way.
8. Termination.
You may not propagate or modify a covered work except as expressly provided
under this License. Any attempt otherwise to propagate or modify it is void, and
will automatically terminate your rights under this License (including any patent
licenses granted under the third paragraph of section 11).
However, if you cease all violation of this License, then your license from a particular
copyright holder is reinstated (a) provisionally, unless and until the copyright holder
explicitly and finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means prior to 60 days
after the cessation.
Moreover, your license from a particular copyright holder is reinstated permanently
if the copyright holder notifies you of the violation by some reasonable means, this
is the first time you have received notice of violation of this License (for any work)
from that copyright holder, and you cure the violation prior to 30 days after your
receipt of the notice.
B.1. General Public License (Version 3) 260
Termination of your rights under this section does not terminate the licenses of
parties who have received copies or rights from you under this License. If your rights
have been terminated and not permanently reinstated, you do not qualify to receive
new licenses for the same material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or run a copy of the
Program. Ancillary propagation of a covered work occurring solely as a consequence
of using peer-to-peer transmission to receive a copy likewise does not require accep-
tance. However, nothing other than this License grants you permission to propagate
or modify any covered work. These actions infringe copyright if you do not accept
this License. Therefore, by modifying or propagating a covered work, you indicate
your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically receives a license
from the original licensors, to run, modify and propagate that work, subject to this
License. You are not responsible for enforcing compliance by third parties with this
License.
An “entity transaction” is a transaction transferring control of an organization, or
substantially all assets of one, or subdividing an organization, or merging organiza-
tions. If propagation of a covered work results from an entity transaction, each party
to that transaction who receives a copy of the work also receives whatever licenses
to the work the party’s predecessor in interest had or could give under the previous
paragraph, plus a right to possession of the Corresponding Source of the work from
the predecessor in interest, if the predecessor has it or can get it with reasonable
efforts.
You may not impose any further restrictions on the exercise of the rights granted or
affirmed under this License. For example, you may not impose a license fee, royalty,
or other charge for exercise of rights granted under this License, and you may not
initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for sale, or importing
the Program or any portion of it.
11. Patents.
A “contributor” is a copyright holder who authorizes use under this License of the
Program or a work on which the Program is based. The work thus licensed is called
the contributor’s “contributor version”.
B.1. General Public License (Version 3) 261
A contributor’s “essential patent claims” are all patent claims owned or controlled
by the contributor, whether already acquired or hereafter acquired, that would be
infringed by some manner, permitted by this License, of making, using, or selling
its contributor version, but do not include claims that would be infringed only as
a consequence of further modification of the contributor version. For purposes of
this definition, “control” includes the right to grant patent sublicenses in a manner
consistent with the requirements of this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free patent license
under the contributor’s essential patent claims, to make, use, sell, offer for sale,
import and otherwise run, modify and propagate the contents of its contributor
version.
In the following three paragraphs, a “patent license” is any express agreement or
commitment, however denominated, not to enforce a patent (such as an express
permission to practice a patent or covenant not to sue for patent infringement).
To “grant” such a patent license to a party means to make such an agreement or
commitment not to enforce a patent against the party.
If you convey a covered work, knowingly relying on a patent license, and the Co-
rresponding Source of the work is not available for anyone to copy, free of charge
and under the terms of this License, through a publicly available network server or
other readily accessible means, then you must either (1) cause the Corresponding
Source to be so available, or (2) arrange to deprive yourself of the benefit of the pa-
tent license for this particular work, or (3) arrange, in a manner consistent with the
requirements of this License, to extend the patent license to downstream recipients.
“Knowingly relying” means you have actual knowledge that, but for the patent li-
cense, your conveying the covered work in a country, or your recipient’s use of the
covered work in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or arrangement, you convey,
or propagate by procuring conveyance of, a covered work, and grant a patent license
to some of the parties receiving the covered work authorizing them to use, propagate,
modify or convey a specific copy of the covered work, then the patent license you
grant is automatically extended to all recipients of the covered work and works based
on it.
A patent license is “discriminatory” if it does not include within the scope of its
coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or
more of the rights that are specifically granted under this License. You may not
convey a covered work if you are a party to an arrangement with a third party that
B.1. General Public License (Version 3) 262
is in the business of distributing software, under which you make payment to the
third party based on the extent of your activity of conveying the work, and under
which the third party grants, to any of the parties who would receive the covered
work from you, a discriminatory patent license (a) in connection with copies of the
covered work conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that contain the covered
work, unless you entered into that arrangement, or that patent license was granted,
prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting any implied
license or other defenses to infringement that may otherwise be available to you
under applicable patent law.
12. No Surrender of Others’ Freedom.
If conditions are imposed on you (whether by court order, agreement or otherwi-
se) that contradict the conditions of this License, they do not excuse you from the
conditions of this License. If you cannot convey a covered work so as to satisfy simul-
taneously your obligations under this License and any other pertinent obligations,
then as a consequence you may not convey it at all. For example, if you agree to
terms that obligate you to collect a royalty for further conveying from those to whom
you convey the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Use with the GNU Affero General Public License.
Notwithstanding any other provision of this License, you have permission to link or
combine any covered work with a work licensed under version 3 of the GNU Affero
General Public License into a single combined work, and to convey the resulting work.
The terms of this License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License, section 13,
concerning interaction through a network will apply to the combination as such.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of the GNU
General Public License from time to time. Such new versions will be similar in spirit
to the present version, but may differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Program specifies that a
certain numbered version of the GNU General Public License “or any later version”
applies to it, you have the option of following the terms and conditions either of that
numbered version or of any later version published by the Free Software Foundation.
B.1. General Public License (Version 3) 263
If the Program does not specify a version number of the GNU General Public License,
you may choose any version ever published by the Free Software Foundation.
If the Program specifies that a proxy can decide which future versions of the GNU
General Public License can be used, that proxy’s public statement of acceptance of
a version permanently authorizes you to choose that version for the Program.
Later license versions may give you additional or different permissions. However, no
additional obligations are imposed on any author or copyright holder as a result of
your choosing to follow a later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PER-
MITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN
WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVI-
DE THE PROGRAM “AS IS” WITHOUT WARRANTY OF ANY KIND, EITHER
EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IM-
PLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PAR-
TICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PER-
FORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM
PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SER-
VICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO
IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY
WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABO-
VE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL,
SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF
THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT
LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE
OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF
THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBI-
LITY OF SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided above cannot be
given local legal effect according to their terms, reviewing courts shall apply local law
that most closely approximates an absolute waiver of all civil liability in connection
B.1. General Public License (Version 3) 264
with the Program, unless a warranty or assumption of liability accompanies a copy
of the Program in return for a fee.
End of Terms and Conditions
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest possible use to
the public, the best way to achieve this is to make it free software which everyone
can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest to attach them to
the start of each source file to most effectively state the exclusion of warranty; and
each file should have at least the “copyright” line and a pointer to where the full
notice is found.
<one line to give the program’s name and a brief idea of what it does.>
Copyright (C) <textyear> <name of author>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short notice like this
when it starts in an interactive mode:
<program> Copyright (C) <year> <name of author>
This program comes with ABSOLUTELY NO WARRANTY; for details type ‘show w’.
This is free software, and you are welcome to redistribute it
under certain conditions; type ‘show c’ for details.
B.1. General Public License (Version 3) 265
The hypothetical commands show w and show c should show the appropriate parts
of the General Public License. Of course, your program’s commands might be diffe-
rent; for a GUI interface, you would use an “about box”.
You should also get your employer (if you work as a programmer) or school, if any, to
sign a “copyright disclaimer” for the program, if necessary. For more information on
this, and how to apply and follow the GNU GPL, see http://www.gnu.org/licenses/.
The GNU General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may consider it
more useful to permit linking proprietary applications with the library. If this is what
you want to do, use the GNU Lesser General Public License instead of this License.
But first, please read http://www.gnu.org/philosophy/why-not-lgpl.html.
Bibliografıa
[1] The Apache Software Foundation. Apache tomcat. Website, 1999.
http://tomcat.apache.org/.
[2] The Apache Software Foundation. Maven. Website, 2002.
http://maven.apache.org/.
[3] The Eclipse Foundation. Eclipse. Website, 2009. http://www.eclipse.org/.
[4] Craig Larman. UML y Patrones. ISBN 84-205-3438-2. Prentice Hall.
[5] Sun Microsystems. Java 2 platform, enterprise edition (j2ee). Website, 1994.
http://java.sun.com/j2ee/overview.html.
[6] Kenneth H. Rosen. Matematica discreta y sus aplicaciones. ISBN 84-481-4073-7.
McGraw Hill, 2005.
[7] Deepak Alur; John Crupi y Dan Malks. Core J2EE Patterns. ISBN 0-13-064884-1.
Prentice Hall.
[8] Ted Husted; Cedric Dumoulin; George Franciscus y David Winterfeldt. Struts In
Action. ISBN 1-930110-50-2. MANNING.
[9] Ivar Jacobson; Grady Booch y James Rumbaugh. El Proceso Unificado De Desarrollo
De Software. ISBN 84-7829-036-2. Addison Wesley, 1999.
267
Bibliografıa 268
[10] Bernardo Cascales Salinas; Pascual Lucas Saorın; Jose Manuel Mira Ros; Antonio
Jose Pallares Ruiz y Salvador Sanchez-Pedreno Gillen. El libro de LATEX. ISBN
84-205-3779-9. Prentice Hall.
[11] MySQL y Sun Microsystems. Mysql. Website, 1995. http://www.mysql.com/.
[12] Christopher Schmitt; Mark Trammel; Ethan Marcotte; Dunstan Orchard y Todd Do-
miney. CSS: Hojas de estilo en cascada para el diseno Web. ISBN 84-415-1954-4.
ANAYA, 2005.