scieee AI-readable full text Open interactive document viewer

Servicio web para el acceso a información sanitaria de pacientes renales

Pedrera Jiménez, Miguel

Abstract

La e-Salud alude a la práctica de cuidados sanitarios apoyada en tecnologías de la información y las comunicaciones, introduciendo dichas tecnologías en la vida de los pacientes, y haciendo que participen de forma activa en el cuidado de su salud. Con un número cada vez mayor de sistemas de e-Salud trabajando conjuntamente, se hace necesario que interoperen e intercambien información con el fin de mejorar la atención a los pacientes, reducir costes y hacer sostenibles los complejos sistemas sanitarios. Hacer que sistemas independientes interoperen no es una tarea sencilla pues dichos sistemas pueden trabajar internamente de maneras muy distintas. Por ello se hace necesario que, de cara a comunicarse con otros sistemas, se utilice un lenguaje común que todos entiendan. Ese lenguaje común puede ser convenido entre cada par de sistemas (protocolo propietario) o adoptado desde un estándar de interoperabilidad en salud. Este trabajo tiene por objeto, el diseño y desarrollo de un servicio web, siguiendo la especificación Fast Healthcare Interoperability Resources (FHIR) de la organización Health Level 7 (HL7), para el acceso a información sanitaria almacenada en la base de datos de un sistema de e-Salud para monitorización remota de pacientes renales. Aunque el dominio de aplicación del servicio es la patología renal, los resultados son extensibles a cualquier otro sistema que gestione información de pacientes crónicos. Previo al diseño del servicio web, se ha llevado a cabo un profundo estudio del estándar, así como de su estado actual y los principales sistemas que lo utilizan o planean utilizar, con el objetivo de enmarcar nuestro trabajo en el contexto actual.

Full text

i Equation Chapter 1 Section 1 Proyecto Fin de Grado Grado en Ingeniería de Tecnologías de Telecomunicación Servicio web para el acceso a información sanitaria de pacientes renales Dep. Ingeniería de Sistemas y Automática Escuela Técnica Superior de Ingeniería Universidad de Sevilla Autor: Miguel Pedrera Jiménez Tutor: Laura M. Roa Romero Sevilla, 2016 iii Trabajo Fin de Grado Grado en Ingeniería de las Tecnologías de Telecomunicación Servicio web para el acceso a información sanitaria de pacientes renales Autor: Miguel Pedrera Jiménez Tutor: Laura M. Roa Romero Catedrática de Universidad Dep. de Ingeniería de Sistemas y Automática Escuela Técnica Superior de Ingeniería Universidad de Sevilla Sevilla, 2016 v Trabajo Fin de Grado: Servicio web para el acceso a información sanitaria de pacientes renales Autor: Miguel Pedrera Jiménez Tutor: Laura M. Roa Romero El tribunal nombrado para juzgar el Proyecto arriba indicado, compuesto por los siguientes miembros: Presidente: Vocales: Secretario: Acuerdan otorgarle la calificación de: Sevilla, 2016 El Secretario del Tribunal vii A Loli y Adrián, siempre seréis parte de mí. ix Agradecimientos Con este trabajo se cierra una etapa de mi vida, y no me gustaría hacerlo sin acordarme y dar las gracias a todas esas personas que me han acompañado a lo largo de este duro camino, convirtiéndolo en un agradable paseo. En primer lugar, a mis padres, Carmen y Miguel, y a mi hermana Marta, por darme todo lo que han tenido y más. Por ser un ejemplo en el que fijarme cada día, sin el cuál no estaría ahora mismo escribiendo estas líneas. A mi familia, los que están y los que no, a mis abuelos, mis tíos, mis primos… porque no hay nada más importante que la familia, y cuando algún miembro ya no está, todo cambia para siempre. A mis amigos de siempre, Pablo, Jose, Natalia, Lorena, Jorge y Víctor; por demostrarme cada día que la amistad no tiene fecha de caducidad. A los festivaleros, Sito, Fati, Curro, Marta y Trini; porque la música se vuelve especialmente valiosa cuando te hace descubrir personas como ellos. A todas las personas que he conocido durante mi etapa en la escuela, en especial a Soriano, Fran, Richy, Marchal, Dani, Jairo, Bole, Ana, Franxi, Ale y Caye, porque estos años sin ellos no habrían sido lo mismo. A mis ex-compañeros de Everis, en especial a Jorge y Miguel, por enseñarme que de unas prácticas no sólo te llevas conocimientos, sino también grandes amigos. A los profesores, por todo lo que me han enseñado, en particular a Laura María Roa, por confiar en mí para este proyecto, y a Jorge Calvillo, por la inestimable atención y ayuda prestada durante la realización del mismo. A todos, muchas gracias. Miguel Pedrera Jiménez Sevilla, 2016 xvii Índice de Tablas Tabla 3-1. Objeto Paciente 26 Tabla 3-2. Objeto Personal sanitario 27 Tabla 3-3. Objeto Organización 28 Tabla 3-4. Objeto Cita 29 Tabla 3-5. Objeto Actividad Toma de medicación 30 Tabla 3-6. Objeto Registro Toma de medicación 31 Tabla 3-7. Objeto Actividad Medida de variable 31 Tabla 3-8. Objeto Registro Medida de variable 32 Tabla 3-9. Objeto Actividad Toma de imagen 33 Tabla 3-10. Objeto Registro Toma de imagen 34 Tabla 3-11. Objeto Incidencia 34 Tabla 3-12. Objeto Plan de cuidados 35 Tabla 3-13. Objeto Periodo de seguimiento 35 Tabla 3-14. Lista de recursos FHIR 37 Tabla 3-15. Recurso Patient 38 Tabla 3-16. Recurso Practitioner 38 Tabla 3-17. Recurso Organization 39 Tabla 3-18. Recurso Appointment 39 Tabla 3-19. Recurso Encounter 40 Tabla 3-20. Recurso Location 41 Tabla 3-21. Recurso MedicationOrder 41 Tabla 3-22. Recurso MedicationStatement 42 Tabla 3-23. Recurso ProcedureRequest 43 Tabla 3-24. Recurso Observation 44 Tabla 3-25. Recurso DetectedIssue 45 Tabla 3-26. Recurso CarePlan 46 Tabla 3-27. Recurso EpisodeOfCare 47 Tabla 3-28. Recurso Condition 47 Tabla 3-29. Método para el recurso Patient (I) 48 Tabla 3-30. Método para el recurso Patient (II) 49 Tabla 3-31. Método para el recurso Practitioner 49 Tabla 3-32. Método para el recurso Appointment (I) 50 Tabla 3-33. Método para el recurso Appointment (II) 50 Tabla 3-34. Método para el recurso Appointment (III) 50 Tabla 3-35. Método para el recurso Appointment (IV) 51 Tabla 3-36. Método para el recurso Encounter (I) 51 Tabla 3-37. Método para el recurso Encounter (II) 51 Tabla 3-38. Método para el recurso Encounter (III) 52 Tabla 3-39. Método para el recurso Encounter (IV) 52 Tabla 3-40. Método para el recurso MedicationOrder (I) 53 Tabla 3-41. Método para el recurso MedicationOrder (II) 53 Tabla 3-42. Método para el recurso MedicationStatement (I) 54 Tabla 3-43. Método para el recurso MedicationStatement (II) 54 Tabla 3-44. Método para el recurso ProcedureRequest (I) 54 Tabla 3-45. Método para el recurso ProcedureRequest (II) 55 Tabla 3-46. Método para el recurso Observation (I) 55 Tabla 3-47. Método para el recurso Observation (II) 56 Tabla 3-48. Método para el recurso DetectedIssue (I) 56 Tabla 3-49. Método para el recurso DetectedIssue (II) 56 Tabla 3-50. Método para el recurso CarePlan 57 Tabla 3-51 Método para el recurso EpisodeOfCare 57 xix Índice de Figuras Figura 1-1. Funcionalidad del servicio web 2 Figura 1-2. Metodología incremental 3 Figura 2-1. Estructura del Recurso FHIR 9 Figura 2-2. Tipos de datos en FHIR 10 Figura 3-1. Diagrama de flujo de la selección de artículos 16 Figura 3-2. Distribución temporal de los artículos sobre FHIR 16 Figura 3-3. Clasificación en función del área médica donde se aplica FHIR 17 Figura 3-4. Clasificación según el tipo de sistema donde se aplica FHIR 18 Figura 3-5. Funcionalidad del Paciente/Cuidador en e-Nefro 20 Figura 3-6. Funcionalidad del Profesional en e-Nefro 21 Figura 3-7. Modelo de datos de e-Nefro: Información personal de usuario 23 Figura 3-8. Modelo de datos de e-Nefro: Organización del profesional 23 Figura 3-9. Modelo de datos de e-Nefro: Cargo y especialidad del profesional 24 Figura 3-10. Modelo de datos de e-Nefro: Actividades 24 Figura 3-11. Modelo de datos de e-Nefro: Registros 25 Figura 3-12. Modelo de datos de e-Nefro: Relación profesional-paciente 25 Figura 3-13. Modelo de datos de e-Nefro: Relación cuidador-paciente 26 Figura 3-14. Relaciones entre objetos de información 36 Figura 3-15. Referencias en el recurso Practitioner 39 Figura 3-16. Referencias en el recurso Appointment 40 Figura 3-17. Referencias en el recurso Encounter 41 Figura 3-18. Referencias en el recurso MedicationOrder 42 Figura 3-19. Referencias en el recurso MedicationStatement 43 Figura 3-20. Referencias en el recurso ProcedureRequest 44 Figura 3-21. Referencias en el recurso Observation 45 Figura 3-22. Referencias en el recurso DetectedIssue 45 Figura 3-23. Referencias en el recurso CarePlan 46 Figura 3-24. Referencias en el recurso EpisodeOfCare 47 Figura 3-25. Sintaxis GET/POST de la operación Search 48 Figura 3-26. Diagrama de secuencia de la funcionalidad del servicio web 58 Figura 3-27. Diagrama de paquetes de la estructura del servicio web 59 Figura 3-28- Paquete servlet 60 Figura 3-29. Paquete narrative 61 Figura 3-30. Paquete bean 62 Figura 3-31. Paquete SQL 63 Figura 3-32. Paquete model 64 Figura 3-33. Paquete provider 65 Figura 3-34. Paquete config 67 Figura 3-35. Módulo de validación: Página principal 68 Figura 3-36. Módulo de validación: Página de recurso 68 Figura 3-37. Módulo de validación: Página de resultado 69 Figura 3-38. Petición/respuesta consulta de un paciente 70 Figura 3-39. Elemento narrativo de recurso Patient 71 Figura 3-40. Petición/Respuesta consulta de un paciente inexistete. 72 Figura 3-41. Petición/Respuesta consulta de pacientes a cargo de un profesional 72 Figura 3-42. Petición/Respuesta consulta de un profesional 73 Figura 3-43. Elemento narrativo de recurso Practitioner 75 Figura 3-44. Petición/Respuesta consulta de un profesional inexistente 75 Figura 3-45. Petición/Respuesta consulta de las citas de un profesional 76 Figura 3-46. Petición/Respuesta consulta de los encuentros de un profesional 78 Figura 3-47. Petición/Respuesta acceso a método no implementado 80 Figura 3-48. Cliente FHIR Android: Interfaz 81 Figura 3-49. Cliente FHIR Android: Muestra de los pacientes obtenidos 82 Figura 3-50. Cliente FHIR Android: Notificación de no infomación 83 xxi Notación FHIR CDA Fast Health Interoperability Resources Clinical Document Architecture HL7 ERC TSR TX HD DP DSTU URI API CASE UML POM URI Health Level Seven Enfermedad Renal Crónica Tratamiento Sustitutivo Renal Trasplante Renal Hemodiálisis Diálisis Peritoneal Draft Standard for Trial Use Uniform Resource Identifier Application Programming Interface Computer Aided Software Engineering Unified Modeling Language Project Object Model Uniform Resource Identifier 1 1 INTRODUCCIÓN n este primer capítulo, se exponen los motivos y objetivos de este trabajo, y cómo se ha llevado a cabo dicha tarea, explicando y justificando la metodología de trabajo escogida y desglosando el plan de trabajo que se ha diseñado y llevado a cabo. 1.1. Motivación y Objetivos La e-Salud alude a la práctica de cuidados sanitarios apoyada en tecnologías de la información y las comunicaciones, introduciendo dichas tecnologías en la vida de los pacientes, y haciendo que participen de forma activa en el cuidado de su salud. Se busca hacer de la atención sanitaria un proceso cada vez más eficiente. Con un gran número de sistemas de e-Salud trabajando conjuntamente, el intercambio de información entre ellos es un pilar fundamental en los procesos de atención a los pacientes, gestión y generación de conocimiento clínico, reducción de costes y sostenibilidad del sistema sanitario. No obstante, con frecuencia se desarrollan sistemas de información sanitarios que no contemplan ese intercambio de información con otros, lo que se traduce en una asistencia fragmentada y lo que se han venido a llamar las islas de información. El interés de este proyecto surge de la necesidad de hacer accesible la información almacenada en la base de datos de un sistema de e-Salud para el tratamiento de pacientes renales crónicos (sistema e-Nefro) a otros sistemas. Entre la información almacenada en dicha base de datos se puede encontrar: tratamientos seguidos por los pacientes, citas concertadas, registros e incidencias de las actividades que han realizado en el tratamiento de su enfermedad. Si se dejara esta información aislada en el ámbito de e-Nefro, estaríamos perdiendo parte del potencial del sistema, y estaríamos lejos de lograr una implementación eficiente para el tratamiento de la enfermedad renal crónica. Se busca, por tanto, una integración de e-Nefro con el resto de sistemas para así hacer posible que toda la información que genera el sistema pueda ser extraída y utilizada por otros. Para ello se diseñará y desarrollará un servicio web siguiendo la reciente especificación FHIR de HL7 para el intercambio de información sanitaria. En la Figura 1-1 se muestra el esquema que pretendemos alcanzar, donde nuestro servicio web hará de intermediario entre la base de datos de e-Nefro y el resto de clientes FHIR externos. E “El conocimiento es poder. El conocimiento compartido es poder multiplicado.” Robert Noyce 2 Figura 1-1. Funcionalidad del servicio web Frente a otros estándares, y como se describe en el apartado 2.3.1, se ha escogido FHIR porque está llamado a ser una de las especificaciones de referencia para el intercambio de información en la próxima generación de la e-Salud pues busca reducir de forma importante los tiempos y, por consiguiente, los costes de los proyectos de integración, al ser diseñado para ser fácil de aprender, desarrollar e implementar, a la vez que combina las características más interesantes de los estándares actualmente en uso. En definitiva, podemos resumir los objetivos del proyecto en los siguientes puntos:  Estudio del estándar HL7 FHIR y su aplicación en sistemas de e-Salud para el tratamiento de enfermedades crónicas.  Diseño e implementación de un servicio web que permita el acceso a la información de la base de datos de e-Nefro a cualquier otro sistema que adopte el estándar anteriormente mencionado.  Extracción de conclusiones y valoración de la utilización del estándar para sistemas de este tipo. 3 1.2. Metodología de trabajo Para la realización del trabajo se va a llevar a cabo una metodología iterativa y creciente, más conocida como metodología incremental. Esta metodología es muy empleada en el desarrollo ágil de software donde los requisitos y soluciones evolucionan con el tiempo según la necesidad del proyecto. Figura 1-2. Metodología incremental Esta metodología de trabajo difiere del tradicional desarrollo en cascada, en el que llevaríamos a cabo las tareas en el orden lógico de realización. De este modo, una vez estudiado el problema médico y técnico a resolver, se realizarán las tareas de diseño, implementación y pruebas, de manera incremental. Con esto se pretende, por un lado, obtener beneficio de lo aprendido a lo largo de cada iteración y aplicarlo en el siguiente, es decir, retroalimentación, y, por otro lado, detectar, gracias a las comprobaciones y pruebas a cada bloque, los errores lo antes posible, y poder solucionarlos con la menor repercusión posible en el trabajo realizado hasta el momento. 1.3. Plan de trabajo Un proyecto de este tipo conlleva una serie de tareas para su comprensión y realización: 1. Estudio y comprensión de la enfermedad renal crónica, así como de sus principales tratamientos domiciliarios: prediálisis, diálisis peritoneal y tratamiento conservador. 2. Estudio y comprensión del problema técnico a resolver con nuestro sistema: la necesidad de interoperabilidad entre aplicaciones sanitarias, y cómo se logra. 3. Estudio y comprensión del estándar de comunicación en salud FHIR y su API, y la aplicación de éste en un sistema de e-Salud para pacientes crónicos. 4. Identificación de los objetos de información existentes en la aplicación, tras el estudio de la aplicación e-Nefro y su base de datos. Las tareas que vienen a continuación, seguirán una metodología iterativa y creciente, llevándose a cabo en bloque para cada objeto de información identificado en el punto anterior. 5. Modelado de los objetos de información, identificando sus atributos y relacionándolos con la base de datos de la aplicación. 6. Establecer la correspondencia entre los objetos de información definidos y los recursos ofrecidos por FHIR y sus campos. 10 Figura 2-2. Tipos de datos en FHIR Algunos atributos, que siguen la nomenclatura atributo[x], pueden ser implementados con diferentes tipos datos, en función de lo que necesitemos de ellos (Figura 2-3). Figura 2-3. Tipo de dato atributo[x] Un tipo de dato especial es el llamado Reference (Figura 2-4) [15], que nos proporciona un mecanismo muy útil a la hora de estructurar la información. Con él, es posible contener recursos dentro de otros. Esto nos permite combinar recursos y poder plasmar la información sanitaria en toda su complejidad. Por ejemplo, podríamos tener un recurso de tipo Practitioner, y en su campo ManagingOrganization referenciar un recurso de tipo Organization, con toda la información relativa a la organización a la que pertenece el profesional. Existen dos tipos de referencias:  Internas, referencias a recursos empaquetados dentro del recurso principal.  Externas, referencias a recursos almacenados externamente a través de su URI. 11 Figura 2-4. Diagrama de referencia a recursos El campo reference contiene la dirección del recurso contenido, pudiendo ser una URL o un identificador, mientras que el campo display sirve para identificar a lo que se está haciendo referencia, sin entrar en detalle. En nuestro servicio utilizaremos el primer tipo de referencia. En la Figura 2-5 se muestra un ejemplo. Figura 2-5. Ejemplo de referencia a recursos Tal como especifica el estándar, existen algunas limitaciones en los recursos contenidos: no deben tener extensiones, recursos contenidos ni elemento narrativo. Como hemos dicho anteriormente, los recursos son representaciones de conceptos básicos del mundo sanitario y administrativo. A veces, es necesario utilizar FHIR en contextos locales o sistemas tan específicos, que estos recursos definidos se nos quedan cortos a la hora de representar nuestra información. Ante este problema, FHIR nos da la solución en forma de Extensiones [16]. Una extensión no es más que añadir nuevos campos de información a un recurso ya definido. Todas las extensiones requieren la publicación de una definición formal, mediante un recurso tipo StructureDefinition (Figura 2-6). Siempre que se intercambian los recursos que contienen las extensiones, las definiciones de las extensiones estarán a disposición de todas las partes que comparten los recursos. Figura 2-6. Diagrama de extensión de recursos 12 Cada extensión contiene un URI, en el campo url, que hace referencia a la fuente de la definición, mientras que el campo value contiene la información como tal. El campo value puede ser cualquiera de los tipos de datos vistos anteriormente, incluido el tipo Reference. En la Figura 2-7 se puede ver un ejemplo de recurso Patient extendido. Figura 2-7. Ejemplo de extensión de recursos Por último, hay que hablar de los elementos narrativos [17], cuya finalidad es facilitar la legibilidad humana del contenido. Para ello se utiliza un fragmento XHTML, generando el resumen de los datos, en forma no estructurada (Figura 2-8). Figura 2-8. Diagrama de elemento narrativo El contenido del elemento div es el fragmento de XHTML que únicamente contendrá elementos básicos de HTML Esto es para asegurar que el contenido del elemento narrativo está íntegramente dentro del recurso y que no hay contenido activo. Dicho contenido introduciría problemas de seguridad y por tanto se prohíbe su uso. 13 Podemos ver un ejemplo de elemento narrativo en la Figura 2-9. Figura 2-9. Ejemplo de elemento narrativo En la Figura 2-10, se puede ver el resultado práctico del elemento narrativo de un recurso que contiene la información de un profesional médico. Figura 2-10. Resultado de elemento narrativo En el apartado correspondiente a la implementación del servicio web, se verá cómo se generan estos elementos, y de qué forma pueden los clientes utilizarlos. 2.3.1.2. Mensajes y Documentos Aunque, debido al tipo de servicio web que se va a diseñar, no se han utilizado Mensajes y Documentos, es conveniente explicarlos brevemente para ver el potencial de FHIR. Los recursos pueden agruparse en forma de mensajes, al igual que se hacía en las versiones 2 y 3 de HL7. En la mensajería FHIR, cuando ocurre un evento que desencadena la necesidad de un intercambio de información, se genera y envía un mensaje desde una aplicación de origen a una aplicación de destino, de forma similar a los mensajes y eventos disparadores en HL7 V3. Así mismo, también se pueden utilizar para construir documentos clínicos. Los documentos FHIR, al igual que en CDA, tienen una serie de características (persistencia, custodia, potencial de autenticación, contexto, integridad y legibilidad humana), que los convierten en una representación de la realidad de un evento clínico. 14 2.4. Material y método Para concluir el estado del arte, se hablará de las principales herramientas que se han utilizado para las tareas de diseño e implementación del servicio web.  MagicDraw [18]. Esta herramienta CASE (Computer Aided Software Engineering), compatible con el estándar UML, ha sido utilizada en las tareas de modelado necesarias para el diseño del servicio web, esto es, modelado de los objetos de información y las relaciones existentes entre ellos, y de la funcionalidad y estructura del servicio web.  Eclipse Mars [19]. Para el desarrollo del servicio web, se ha utilizado esta plataforma de desarrollo en la plataforma Java, junto a los plugins de Spring [20] e Hibernate [21], muy utilizados en el desarrollo de aplicaciones de este tipo.  Apache Maven [22]. Maven es una herramienta CASE de gestión de proyectos de software y comprensión, basada en el concepto de un Proyect Object Model (POM). Se ha utilizado Maven para describir el proyecto software a construir, sus dependencias de otros módulos y componentes externos, y el orden de construcción de los elementos. Su principal característica es que está listo para usar en red. El motor incluido en su núcleo puede dinámicamente descargar plugins de un repositorio que provee acceso a muchas versiones de diferentes proyectos Open Source en Java, de Apache y otras organizaciones y desarrolladores.  Apache Tomcat 8.0 [23]. Se utiliza este contenedor web con soporte de servlets y JSPs, para el despliegue de nuestro servicio web, a través de Eclipse.  PostgreSQL [24]. Sistema de gestión de bases de datos relacional orientado a objetos y de código libre. La base de datos de e-Nefro está implementada bajo este sistema, por lo que se ha utilizado tanto en la fase de diseño, para realizar consultas y estudiar la base de datos, como en la fase de implementación, para extraer y manejar la información, incorporando la librería correspondiente en Eclipse.  Android Studio [25]. Herramienta principal para el desarrollo de aplicaciones Android. Este IDE desarrollado por la misma compañía propietaria del sistema operativo Android, lo que aporta numerosas ventajas adicionales a la hora de escribir aplicaciones para su plataforma. En nuestro caso se ha utilizado para la implementación de un cliente Android FHIR que utilice nuestro servicio web.  HAPI FHIR [26]. Para la implementación de la especificación HL7 FHIR en nuestro servicio web, se utiliza esta API de código abierto, completamente compatible con aplicaciones Java. Entre los distintos usos que se proponen para la librería, es especialmente interesante para nuestro proyecto el de emplearla en una aplicación que permita a aplicaciones externas acceder a nuestra información (Figura 2-11). Figura 2-11. Funcionalidad HAPI FHIR 15 3 RESULTADOS n este tercer capítulo, se muestran los resultados obtenidos en la realización del trabajo. En primer lugar, se ha realizado una revisión literaria sobre la situación actual de FHIR, centrada en determinar las principales áreas y sistemas donde se está utilizando dicha especificación. Tras ello, se han realizado las tareas que abarcan el diseño del servicio web: identificación y modelado de objetos de información de e-Nefro, identificación y modelado de los recursos FHIR a intercambiar y diseño de los métodos de acceso a la información. Por último, se ha llevado a cabo la implementación del servicio web, utilizando para ello una API de código abierto de FHIR en Java: HAPI FHIR. 3.1. Revisión literaria sobre la especificación HL7 FHIR Previo al diseño del servicio, se ha realizado un estudio de la situación actual del estándar a través de una profunda revisión literaria. Con este análisis, se busca conocer en qué áreas médicas se está aplicando el estándar, así como cuáles son los principales sistemas que están planteando su implementación, para poder enmarcar nuestro servicio en el panorama actual. A continuación, se expone la metodología de búsqueda utilizada para recopilar la información, los resultados obtenidos del estudio y su discusión, y las principales conclusiones que podemos extraer de ello. 3.1.1. Metodología de búsqueda Para la elaboración de esta revisión bibliográfica, se han realizado búsquedas de artículos relevantes, atendiendo al número citaciones en otros artículos, en lengua inglesa utilizando las bases de datos de Scopus, ScienceDirect y Google Scholar, desde el año 2013, fecha de publicación de FHIR, hasta abril de 2016 (documentos en prensa incluidos). El conjunto de artículos se obtuvo recogiendo aquellos que incluían "FHIR" o “Fast Health Interoperability Resource” en el título, resumen o como palabras clave, dando ambas búsquedas prácticamente el mismo resultado. Se excluyeron de dicha lista artículos de opinión y documentos no catalogados como artículos. La Figura 3-1 muestra el proceso de selección para el conjunto de artículos, en la que, tras agrupar todos los artículos de las diferentes bases de datos, y excluir duplicados, se hizo una revisión del resumen y, posteriormente, del contenido, para excluir aquellos artículos en los que FHIR no era el objeto del trabajo, o no se presentaba ninguna implementación que fuera a utilizarlo. E “Los científicos estudian el mundo tal como es; los ingenieros crean el mundo que nunca ha sido.” Theodore von Kármán 16 Figura 3-1. Diagrama de flujo de la selección de artículos 3.1.2. Resultados La búsqueda en las bases de datos mencionadas dio un total de 45 artículos donde se mencionaba la especificación FHIR. Tras combinar los resultados y eliminar los duplicados, nos quedamos con 35 artículos, de los cuáles tras hacer una revisión del resumen y contenido, sólo 21 de ellos cumplían los requisitos del proceso de selección. Como se puede ver en la Figura 3-2, a partir del conjunto de artículos seleccionado, se extrajeron datos como su fecha de publicación, interesante para estudiar la tendencia que seguirán, y la importancia de FHIR, en el futuro. Figura 3-2. Distribución temporal de los artículos sobre FHIR 17 Podemos observar que el número de artículos publicados sobre FHIR va en aumento. Tras la publicación del artículo de presentación en 2013, en 2014 no se publicaron artículos donde la jugase un papel relevante. Ya en 2015, con la especificación más asentada, nos encontramos con un total de 17 artículos publicados sobre dicha especificación, y sólo en los cuatro primeros meses de 2016 se publicaron otros tres artículos. Los artículos seleccionados también han sido clasificados en función de en qué área de la medicina se va a aplicar el sistema de e-Salud para el que se propone el uso de FHIR (Figura 3-3). Hay que mencionar que 5 de los 21 artículos seleccionados no tratan sobre un sistema donde aplicarlo, sino sobre aspectos teórico-técnicos de la especificación como tal, por lo que no han sido incluidos en la siguiente clasificación, que se realiza sobre los 16 artículos restantes. El 41% (6) de los artículos tratan sobre la utilización de FHIR en sistemas de información sanitaria general, con el propósito de que se integre en el conjunto de sistemas e intercambie información con éstos. El 23% (4) proponen utilizar FHIR en sistemas para la monitorización de pacientes crónicos, donde se registrarán sus variables que serán accesibles por otros sistemas, aunque no especifican a qué tipo de pacientes concretos irán dirigidos. Profundizando algo más en este tipo de sistemas, el 6% de los artículos habla de aplicar FHIR en un sistema de lo que se conoce como Healthy Ageing [27], mientras que otro 6% (1) va dirigidos a pacientes de Diabetes mellitus gestacional [28]. Por último, un 25% (4) trata sobre sistemas de ayuda a la decisión clínica y de generación de conocimiento, mediante análisis de datos genómicos y la aplicación de reglas de decisión. Figura 3-3. Clasificación en función del área médica donde se aplica FHIR Otra clasificación interesante a la hora de analizar la tendencia de los sistemas que utilizan FHIR, es la de en qué tipo de sistemas se plantea su uso (Figura 3-4). En este aspecto, encontramos:  3 artículos son meramente informativos sobre FHIR. Entre ellos se encuentra el artículo de presentación [29], y 2 artículos que tratan sobre la colaboración médico-paciente [30] y la toma de decisiones clínicas [31], y el aporte de la especificación a estas tareas.  4 artículos realizan un estudio teórico de FHIR, los recursos que ofrece, tipos de datos [32-34] y la capacidad para utilizarlo con un sistema basado en arquetipos. [35]  4 artículos [36-39] plantean el uso de FHIR en el envío y captación de registros en sistemas de monitorización para pacientes crónicos y hogares asistidos, entre ellos el sistema CyPhyS+ [39], para para personas de edad avanzada, rama conocida como healthy ageing [27]. 18  4 artículos [40-43] que aplican FHIR en sistemas de ayuda a la decisión clínica y de generación de conocimiento, mediante análisis de datos genómicos y la aplicación reglas de decisión.  3 artículos [44-46] sobre el uso de FHIR en aplicaciones móviles, lo que se conoce como m-Salud [47], una de las principales tendencias de la e-Salud.  2 artículos [48-49] plantean el uso de FHIR en sistemas EHR, para integrarlos con el resto de sistemas. Concretamente, se plantea su uso en OpenMRS [50].  Un artículo [51] sobre el uso de FHIR en un sistema de validación de documentos clínicos. Figura 3-4. Clasificación según el tipo de sistema donde se aplica FHIR 3.1.3. Discusión En la introducción se estableció el objetivo de la revisión: estudiar la situación actual de la especificación FHIR, y valorar su uso frente a otras propuestas. Se seleccionaron un total de 21 artículos donde FHIR jugaba un papel relevante. Viendo la evolución de los artículos desde el año 2013 hasta la actualidad (Figura 3-2) podemos ver una tendencia claramente creciente en el número de artículos publicados. En 2013, año en el que se lanzó la especificación, tenemos el artículo [29] en el que fue presentado por HL7 y en el que se describen sus principales características. Durante 2014 no hubo artículos relevantes, pues FHIR estaba recién lanzado, y en una fase muy baja de desarrollo, por lo que se necesitaba tiempo para estudiarlo en profundidad y ver cómo evolucionaba. Ya durante 2015 y los cuatro primeros meses de 2016, con la especificación más asentada, encontramos 17 y 4 artículos, respectivamente, donde se trata su uso en diferentes sistemas de actual relevancia. Esta evolución nos hace pensar que, en los próximos años, con FHIR más maduro y estudiado, el número de sistemas que lo utilizarán aumentará considerablemente. Analizando la Figura 3-3, donde se han clasificado los sistemas que se integrarán con FHIR, en función el área de la medicina a la que pertenecen, podemos observar que su uso no se limita a un área concreta, sino que vemos implementaciones en tres grandes áreas: sistemas de información clínica general, donde se registran las historias clínicas de los pacientes, sistemas para pacientes crónicos y en sistemas para la toma de decisiones médicas. Esto es posible debido a que FHIR no nos limita su uso a un área concreta, sino que ofrece una serie de recursos básicos que son empleados en todas las áreas médicas, tales como Paciente o Procedimiento, a la vez que permite la extensión de éstos para adecuarlos a un contexto específico. He aquí una de las características que hacen tan interesante a FHIR, su flexibilidad. 19 A nivel técnico, FHIR se considera [44] una especificación emergente que aprovecha elementos positivos de sus antepasados HL7 v2 y v3, y CDA, abordando sus limitaciones. Estos estándares han jugado un papel importante en garantizar la interoperabilidad de la asistencia sanitaria, pero que debido a las nuevas tendencias en e-Salud, como las aplicaciones móviles, o los sistemas de EHR, se hacen demasiado complejos para una integración del sistema rápida y poco costosa. Por un lado, FHIR se basa en el estilo arquitectónico REST, siendo [38] adecuado para dispositivos ligeros y con poca capacidad de procesado, como los terminales móviles. También [38] hay que temer en cuenta que son dispositivos portátiles, donde la batería es un factor fundamental a tener en cuenta, y utilizar una tecnología que la ahorre al máximo es una gran ventaja. Aquí vemos una de los principales campos donde FHIR puede ser especialmente interesante, los sistemas de m-Salud. Atendiendo a la clasificación por el tipo de sistema donde se plantea utilizar FHIR (Figura 3-4), podemos observar que las aplicaciones móviles juegan un papel importante en la tendencia del estándar, así como los sistemas de monitorización, que también cuentan con elementos de batería. La interoperabilidad es esencial para hacer frente a las limitaciones causadas por la aplicación ad hoc de los sistemas de información e historia clínica. FHIR [48] es particularmente relevante en este tipo de sistemas, una de las bases de la atención médica moderna. Otro de los puntos que hace la especificación tan interesante, es que su diseño se ha hecho pensando en crear un estándar de interoperabilidad lo más sencillo posible de implementar, reduciendo los costes de los proyectos de integración. Es por ello particularmente relevante para OpenMRS [50], un sistema de registros médicos de código abierto ampliamente utilizado en todas las economías emergentes. Debido a la naturaleza del proyecto, es especialmente interesante el principio de ahorro de costes bajo los que la especificación ha sido diseñada. FHIR tiene el potencial de permitir a OpenMRS alejarse de una API propia para la integración con otros sistemas y definir los planes a largo plazo para la transición hacia una API basada en FHIR que reduce en gran medida la curva de aprendizaje para los desarrolladores y reducir costes [48] [49]. Otra de las líneas de investigación abierta, es la combinación de FHIR con arquetipos. El uso de arquetipos aportaría una serie de ventajas como ser capaz de verificar si un recurso es válido dentro del modelo de referencia, aunque aún hay cuestiones a resolver cuando se trata de arquetipos, sobre todo debido a la separación entre la definición narrativa y la definición formal de los recursos [35]. Actualmente, se está trabajando en el estudio de FHIR, con el objetivo de hacer que funcione junto a otros estándares y mecanismos de interoperabilidad. Esto es relativamente sencillo de conseguir con las especificaciones previas de HL7, HL7 V2 y V3 y CDA [52], pues FHIR se ha diseñado con esa idea. Conseguir esta integración con otros estándares, como por ejemplo Arden Syntax [41], requiere un esfuerzo mayor. En comparación con estas especificaciones HL7 previas, FHIR ha implementado sus características más interesantes como la generación de mensajes y documentos clínicos, además de reducir la complejidad. Es especialmente interesante, como ya se ha comentado, [38] en sistemas con batería, donde es preferible el uso de la arquitectura REST que implementa FHIR, frente a SOAP, implementada, por ejemplo, por HL7 V2, uno de los estándares actualmente más asentados. Así mismo [38], se ha demostrado que hay una disminución significativa en el tráfico de datos cuando se basa en una arquitectura REST en combinación con HL7 FHIR. Otra ventaja es que el recurso FHIR proporciona un nivel de auto descriptivo, en comparación con el enfoque HL7v2 y v3, siendo mucho más intuitivo de manejar, ahorrando tiempo de aprendizaje a los desarrolladores. Desde este punto de vista, resulta interesante dar el paso a FHIR, un estándar más flexible, ligero, eficiente y fácil de implementar, siempre teniendo en cuenta los costes asociados a adaptar los sistemas actuales a este nuevo estándar. 3.1.4. Conclusiones FHIR está llamado a ser una de las especificaciones de referencia para el intercambio de información en la próxima generación de la e-Salud. Cada vez cobra más peso en los artículos sobre sistemas de e-Salud actuales, en detraimiento de otras especificaciones como HL7 V2 y V3, y CDA. Debido a cómo se ha concebido su diseño, hace que sea fácil y poco costoso de implementar, y al utilizar tecnología REST, es especialmente interesante en aparatos portátiles y con poca capacidad de procesamiento, 26 Del mismo modo, la tabla e_rel_espepaci (Figura 3-13) relaciona paciente y cuidador. Figura 3-13. Modelo de datos de e-Nefro: Relación cuidador-paciente Con esto, ya tenemos identificada la información existente en la base de datos. En los siguientes apartados, procederemos al modelado de los objetos de información definidos. 3.2.2.2. Objeto Paciente En la Tabla 3-1 se muestra el objeto que contiene la información referente a un usuario de tipo paciente. Se identifican y describen sus atributos y dónde está almacenada cada elemento de información en la base de datos. También se añade la representación del objeto modelado. Tabla 3-1. Objeto Paciente Atributo Relación con BD Descripción Objeto modelado idPaciente pers_id Identificador del objeto estado usua_estadousuario Estado del usuario en la aplicación numHist pers_numhist Número de historia clínica del paciente nombre pers_name Nombre del paciente primerApellido pers_firstsurname Primer apellido del paciente segundoApellido pers_secondsurname Segundo apellido del paciente tipoDocumento tpid_codigo Tipo de documento que identifica al paciente 27 Atributo Relación con BD Descripción Objeto modelado documento pers_document Documento de identificación del paciente sexo pers_sexo Sexo del paciente fechaNacimiento pers_birthtime Fecha de nacimiento del paciente telefono pers_telefono Teléfono del paciente telecom pers_telcom Correo electrónico del paciente direccion pers_address Dirección del paciente 3.2.2.3. Objeto Personal sanitario Objeto que contiene la información almacenada en base de datos sobre un usuario del tipo Profesional o Cuidador. Se emplea una única clase para ambos tipos de usuarios, ya que la información a extraer es la misma, y posteriormente veremos que FHIR tiene un único recurso definido tanto para profesionales sanitarios, como para cuidadores particulares, por lo que es más eficiente utilizar una misma clase. Tabla 3-2. Objeto Personal sanitario Atributo Relación con BD Descripción Objeto modelado idSanitario pers_id Identificador del objeto idOrganizacion orga_id Identificador de la organización del sanitario estado usua_estadousuario Estado del usuario en la aplicación tipo usua_tipo Tipo de personal sanitario nombre pers_name Nombre del sanitario primerApellido pers_firstsurname Primer apellido del sanitario segundoApellido pers_secondsurname Segundo apellido del sanitario tipoDocumento tpid_codigo Tipo de documento que identifica al sanitario documento pers_document Documento de identificación del sanitario sexo pers_sexo Sexo del profesional fechaNacimiento pers_birthtime Fecha de nacimiento del profesional 28 Atributo Relación con BD Descripción Objeto modelado telefono pers_telefono Teléfono del profesional telecom pers_telcom Correo electrónico del profesional cargo staf_cargo Cargo que desempeña el profesional cargoEspecialidad staf_nombre Especialidad médica del profesional 3.2.2.4. Objeto Organización Objeto que contiene la información de base de datos de una organización implicada en la asistencia sanitaria del paciente. Tabla 3-3. Objeto Organización Atributo Relación con BD Descripción Objeto modelado idOrganizacion orga_id Identificador del objeto nombre orga_name Nombre de la organización direccion orga_address Dirección de la organización telefono orga_telefono Teléfono de la organización telecom orga_telecom Correo electrónico de la organización 3.2.2.5. Objeto Cita Objeto que contiene la información de base de datos relativa a la cita de un paciente con un profesional sanitario, lo que genera dicho encuentro. 29 Tabla 3-4. Objeto Cita Atributo Relación con BD Descripción Objeto modelado idCita appo_id Identificador del objeto idPlan appo_id_plan Identificador del plan al que pertenece la actividad idPaciente plan_pacienteusuario Identificador del paciente implicado en la cita idProfesional appo_id_citadocon Identificador del profesional implicado en la cita localizacion acti_location Lugar de la cita fechaInicio acti_startdate Fecha de inicio de la cita causa acti_problemaa Razón por la que la cita tiene lugar descripcion acti_descripcion Descripción de la cita obserMed appo_observacionpriv Observaciones médicas realizadas durante la cita obserEnf appo_observacionenfe Observaciones de enfermería realizadas durante la cita comenPac cric_comentarios Comentarios para el paciente 3.2.2.6. Objeto Actividad Toma de medicamento Objeto que contiene la información de una actividad de tipo medicación de un paciente. 30 Tabla 3-5. Objeto Actividad Toma de medicación Atributo Relación con BD Descripción Objeto modelado idMedAct mact_id Identificador el objeto idPlan mact_id_plan Identificador del plan al que pertenece la actividad idPaciente plan_pacienteusuario Id del paciente implicado en la toma de medicación idPrescriptor acti_creador Id del profesional que prescribe el medicamento medicamento reso_codigo Medicamento a tomar dosis mact_amount Dosis a tomar unidadMedida mact_unitmeasure Unidad de medida de la dosis frecuencia acti_frequency Frecuencia de la toma dias acti_dias Días que tiene que tomar el medicamento cadaDias acti_cadaxdias Cada cuántos días tiene que tomar el medicamento cadaHoras acti_cadaxhoras Cada cuántas horas tiene que tomar el medicamento relComida acti_relcomidas Relación de la toma con las comidas fechaInicio acti_startdate Fecha de inicio del tratamiento fechaFin acti_enddate Fecha de fin del tratamiento causa acti_problemaa Causa de la toma del medicamento descripcion acti_description Descripción de la actividad a realizar 31 3.2.2.7. Objeto Registro Toma de medicamento Objeto que contiene la información de un registro de tipo medicación de un paciente. Tabla 3-6. Objeto Registro Toma de medicación Atributo Relación con BD Descripción Objeto modelado idMedReg macr_id Identificador del objeto idMedAct mact_id Identificador de la actividad de la que se genera el registro fechaToma crir_date Fecha de creación del registro comentario crir_comentarios Comentarios sobre el registro 3.2.2.8. Objeto Actividad Medida de variable Objeto que contiene la información de una actividad de tipo medida de variable fisiológica de un paciente. Tabla 3-7. Objeto Actividad Medida de variable Atributo Relación con BD Descripción Objeto modelado idVarAct phya_id Identificador el objeto idPlan phya_id_plan Identificador del plan al que pertenece la actividad idPaciente plan_pacienteusuario Id del paciente implicado en la actividad idPrescriptor acti_creador Id del profesional que prescribe la actividad variableMedida phys_codigo Variable fisiológica medida frecuencia acti_frequency Frecuencia de la actividad dias acti_dias Días que tiene que realizar la actividad cadaDias acti_cadaxdias Cada cuántos días tiene que realizar la actividad cadaHoras acti_cadaxhoras Cada cuántas horas tiene que realizar la actividad 32 Atributo Relación con BD Descripción Objeto modelado relComida acti_relcomidas Relación de la actividad con las comidas fechaInicio acti_startdate Fecha de inicio de realización de la actividad fechaFin acti_enddate Fecha de fin de realización de la actividad causa acti_problemaa Causa de tener que realizar la actividad descripcion acti_description Descripción de la actividad 3.2.2.9. Objeto Registro Medida de variable Objeto que contiene la información de un registro de tipo medida de variable fisiológica realizada por un paciente. Tabla 3-8. Objeto Registro Medida de variable 3.2.2.10. Objeto Actividad Toma de imagen Objeto que contiene la información de una actividad de tipo toma de imagen de un paciente. Atributo Relación con BD Descripción Objeto modelado idVarReg phyr_id Identificador del objeto idVarAct phya_id Identificador de la actividad de la que se genera el registro medida phyr_medida Valor de la medida fecha crir_date Fecha de creación del registro comentario crir_comentario Comentarios sobre el registro 33 Tabla 3-9. Objeto Actividad Toma de imagen Atributo Relación con BD Descripción Objeto modelado idImgAct take_id Identificador el objeto idPlan take_id_plan Identificador del plan al que pertenece la actividad idPaciente plan_pacienteusuario Identificador del paciente implicado en la actividad idPrescriptor acti_creador Id del profesional que prescribe la actividad causa acti_problemaa Causa de tener que realizar la actividad dias acti_dias Días que tiene que realizar la actividad cadaDias acti_cadaxdias Cada cuántos días tiene que realizar la actividad cadaHoras acti_cadaxhoras Cada cuántas horas tiene que realizar la actividad fechaInicio acti_startdate Fecha de inicio de realización de la actividad fechaFin acti_enddate Fecha de fin de realización de la actividad frecuencia acti_frequency Frecuencia de la actividad descripcion acti_description Descripción de la actividad 3.2.2.11. Objeto Registro Toma de imagen Objeto que contiene la información de un registro de tipo toma de imagen realizada por un paciente. 34 Tabla 3-10. Objeto Registro Toma de imagen Atributo Relación con BD Descripción Objeto modelado idImgReg takr_id Identificador del objeto idImgAct take_id Identificador de la actividad de la que se genera el registro fecha docu_fechainsercion Fecha de creación del registro ruta docu_ruta Ruta de la imagen tomada descripcion takr_picture Descripción de la imagen tomada comentario crir_comentarios Comentarios sobre el registro 3.2.2.12. Objeto Incidencia Objeto que contiene la información de una incidencia registrada por un paciente. Tabla 3-11. Objeto Incidencia Atributo Relación con BD Descripción Objeto modelado idIncidencia heal_id Identificador del objeto idPaciente clin_pacienteusuario Identificador del paciente que registra la incidencia fecha crir_date Fecha de registro de la incidencia descripcion tinc_descripcion Descripción de la incidencia recomendacion tinc_recomendacio Recomendación a la incidencia comentarios crir_comentario Comentarios sobre la incidencia 35 3.2.2.13. Objeto Plan de cuidados Objeto que contiene la información del plan de cuidados seguido por un paciente. Tabla 3-12. Objeto Plan de cuidados Atributo Relación con BD Descripción Objeto modelado idPlan plan_id Identificador del objeto idPaciente plan_pacienteusuario Identificador del paciente que sigue el plan de cuidados descripcion plan_description Descripción de plan de cuidados razon plan_reason Razón de existencia del plan de cuidados tiempoDefinido plan_definitiontime Tiempo definido para el plan de cuidados estado plan_active Estado del plan de cuidados 3.2.2.14. Objeto Periodo de seguimiento Objeto que contiene la información del periodo de seguimiento de un paciente. Tabla 3-13. Objeto Periodo de seguimiento Atributo Relación con BD Descripción Objeto modelado idPeriodo peri_id Identificador del objeto idPaciente peri_id_usuario Identificador del paciente en seguimiento fechaInicio peri_startdate Fecha de inicio del periodo de seguimiento fechaFin peri_enddate Fecha de fin del periodo de seguimiento problema peri_problema Problema que origina el periodo de seguimiento resumen peri_resumen Descripción del periodo de seguimiento 42 Atributo Tipo de Dato Cardinalidad Descripcion dateWritten dateTime 0..1 Fecha de comienzo del tratamiento. dateEnded dateTime 0..1 Fecha de fin del tratamiento. note string 0..1 Información sobre la prescripción. Así mismo, en este recurso van contenidos un recurso Patient, paciente que ha de tomar el medicamento, y un recurso Practitioner, profesional que lo prescribe, en los campos patient y prescriber respectivamente (Figura 3-18). Figura 3-18. Referencias en el recurso MedicationOrder 3.3.2.8. Recurso MedicationStatement Este recurso es utilizado para los registros generados por la toma de medicamentos de un paciente. Contiene información como el medicamento tomado, la fecha de la toma o comentarios sobre ésta. En nuestro caso, contiene la información relativa al objeto Registro Toma de medicamento, no siendo necesario extender el recurso. Tabla 3-22. Recurso MedicationStatement Atributo Tipo de Dato Cardinalidad Descripcion status Reference(Patient) 1..1 Estado en el que se encuentra el tratamiento. patient Reference(Patient) 1..1 Paciente al que se le prescribe el medicamento. medication CodeableConcept 1..1 Medicamento a tomar. effectiveTime dateTime 1..1 Fecha de la toma del medicamento. note string 0..1 Información sobre la toma. Así mismo, contiene un recurso Patient, siendo éste el paciente implicado en la toma de medicamento, referenciado a través del campo patient (Figura 3-19). 43 Figura 3-19. Referencias en el recurso MedicationStatement 3.3.2.9. Recurso ProcedureRequest Este recurso se utiliza para la solicitud de realización de alguna actividad que se lleva a cabo con o en un paciente como parte de su plan de cuidados. En nuestro caso, contiene la información de los objetos Actividad Medida de variable y Actividad Toma de imagen, siendo necesario extender un campo frecuency, que contiene la frecuencia con la que esta actividad debe ser realizada. Tabla 3-23. Recurso ProcedureRequest Atributo Tipo de Dato Cardinalidad Descripcion subject Reference(Patient) 0..1 Paciente sobre el que se realiza la actividad. orderer Reference(Practitioner) 0..1 Profesional que manda la actividad. code CodeableConcept 1..1 Tipo de observación reason CodeableConcept 0..1 Causa de tener que realizar la actividad. scheduledPeriod Period 0..1 Durante cuánto tiempo se tiene que realizar la actividad. notes string 0..1 Descripción de la actividad. frequency string 1..1 Frecuencia con la que hay que realizar la actividad. Así mismo, contiene un recurso Patient, paciente sobre el que se realiza la actividad, y un recurso Practitioner, el profesional que la prescribió, en los campos subject y orderer (Figura 3-20). 44 Figura 3-20. Referencias en el recurso ProcedureRequest 3.3.2.10. Recurso Observation Dentro de este recurso se engloban todos los resultados obtenidos de las actividades realizadas con o sobre el paciente. Entre ellos, encontramos medidas de signos vitales, datos de laboratorio o imágenes médicas. En nuestro caso, contiene la información de los objetos Registro Medida de variable y Registro Toma de imagen, no siendo necesario extenderlo. Tabla 3-24. Recurso Observation Atributo Tipo de Dato Cardinalidad Descripcion status code 1..1 Estado de la actividad subject Reference(Patient) 0..1 Paciente que realiza la actividad. code CodeableConcept 1..1 Tipo de observación effective dateTime 0..1 Momento en el que se realiza la actividad. value string Attachment 1..* Valor de la medida. Imagen adjunta. comments string 0..1 Comentarios sobre la realización de actividad. Aunque se utiliza el mismo recurso para ambos objetos de información, en el caso de la medida de variable, el campo value será de tipo string, conteniendo el valor de la medida, mientras que, en la toma de imagen, será del tipo Attachment, conteniendo la ruta de la imagen tomada. Así mismo, contiene un recurso Patient, siendo el paciente sobre el que se realizó la actividad y del que se ha generado el registro, referenciado a través del campo subject (Figura 3-21). 45 Figura 3-21. Referencias en el recurso Observation 3.3.2.11. Recurso DetectedIssue Se emplea para indicar un problema o evento anómalo al margen de las actividades que realiza el paciente (por ejemplo, dolores abdominales, náuseas o fiebre). En nuestro caso, contiene la información de un objeto Incidencia, siendo necesario extender un campo comments, para los comentarios realizados en el registro de la incidencia. Tabla 3-25. Recurso DetectedIssue Atributos Tipo de Dato Cardinalidad Descripcion patient Reference(Patient) 0..1 Paciente que registra la incidencia. date dateTime 0..1 Fecha de registro de la incidencia. detail string 0..1 Descripción de la incidencia. mitigation BackboneElement 0..* Momento en el que se realiza la actividad. comments string 0..1 Comentarios sobre la incidencia. Contiene un recurso Patient, el paciente que registra la incidencia, referenciado a través del campo patient (Figura 3-22). Figura 3-22. Referencias en el recurso DetectedIssue 46 3.3.2.12. Recurso CarePlan Este recurso contiene la información del plan de cuidados que sigue un paciente, donde se enmarcan las actividades que debe realizar para el cuidado de su salud. En nuestro caso, contiene la información del objeto Plan de cuidados, no siendo necesario extender el recurso. Tabla 3-26. Recurso CarePlan Atributos Tipo de Dato Cardinalidad Descripcion subject Reference(Patient) 0..1 Paciente que registra la incidencia. description string 0..1 Descripción del plan de cuidados. status string 1..1 Estado del plan de cuidados. period Period 0..1 Duración del plan de cuidados. addresses Reference(Condition) 0..* Problemas que trata el plan de cuidados. Contiene un recurso Patient, el paciente que registra la incidencia, y un recurso Condition, problema que trata de cubrir el plan de cuidados, referenciados en los campos subject y addresses, respectivamente (Figura 3-23). Figura 3-23. Referencias en el recurso CarePlan 3.3.2.13. Recurso EpisodeOfCare Contiene información acerca de la asociación de un paciente con un proveedor de atención médica durante un período de tiempo en el que pueden producirse actividades y encuentros médicos. En nuestro caso, contiene la información del objeto Periodo de seguimiento, siendo necesario extender un campo reasonEnded, que indica por qué finalizó dicho periodo de seguimiento. 47 Tabla 3-27. Recurso EpisodeOfCare EpisodeOfCare Tipo de Dato Cardinalidad Descripcion status code 1..1 Estado del periodo de seguimiento. patient Reference(Patient) 0..1 Paciente que registra la incidencia. period Period 0..1 Descripción del plan de cuidados. condition Reference(Condition) 0..* Problemas de salud por el que existe este periodo de seguimiento. reasonEnded string 0..1 Causa del fin del periodo de seguimiento. Contiene un recurso Patient, el paciente que registra la incidencia, y un recurso Condition, problema que trata de cubrir el plan de cuidados, referenciados en los campos subject y condition, respectivamente (Figura 3-24). Figura 3-24. Referencias en el recurso EpisodeOfCare 3.3.2.14. Recurso Condition Se utiliza para enfermedades o problemas médicos que padece un paciente y que originan que tenga que seguir un determinado tratamiento o actividades para el cuidado de su salud. En nuestro caso, contiene parte de la información de los objetos Plan de cuidados y Periodo de seguimiento, concretamente, la enfermedad que causa que el paciente forme parte de ellos, no siendo necesario extender el recurso. Tabla 3-28. Recurso Condition Condition Tipo de Dato Cardinalidad Descripcion patient Reference(Patient) 1..1 Paciente que sufre el problema code CodeableConcept 1..1 Problema de salud. 3.4. Definición de los métodos de acceso a la información Una vez identificados y modelados los recursos que se van a ofrecer al resto de sistemas, hay que definir los métodos de los que podrán hacer uso los clientes para acceder a ellos. 48 3.4.1. Forma de acceso a la información Como se ha comentado, FHIR se basa en el intercambio de recursos que contienen la información solicitada. Debido a este enfoque de construir la especificación en torno a estos elementos básicos, es necesario definir los métodos de acceso a la información para cada recurso de manera independiente. De este modo, el cliente, formalmente, estará solicitando únicamente un tipo de recurso concreto utilizando los métodos definidos, recursos contenidos aparte. Los métodos definidos son operaciones Search, interacción definida por la propia especificación para que los clientes puedan acceder a recursos siguiendo algún criterio de búsqueda. Esta interacción puede llevarse a cabo con métodos GET o POST indistintamente [53] (Figura 3-25). Figura 3-25. Sintaxis GET/POST de la operación Search Cuando un cliente solicita un determinado recurso, lo que recibe es un recurso de tipo Bundle [54], que contendrá los recursos que el cliente había solicitado, y con el que podrá trabajar para extraer dicha información. 3.4.2. Lista de métodos de acceso a los recursos FHIR En este apartado, se mostrará la lista completa de los métodos con los que contarán los clientes para acceder a la información, clasificados según el tipo de recurso suministrado, a través de una serie de tablas que contendrán el nombre del método, una breve descripción, los parámetros de entrada necesarios para la consulta, la repuesta esperada y los posibles errores. 3.4.2.1. Métodos para el recurso Patient Contamos con dos métodos para acceder a la información modelada en el recurso Patient, el primero para solicitar un paciente concreto, y el segundo para solicitar todos los pacientes a cargo de un profesional. Tabla 3-29. Método para el recurso Patient (I) Nombre del método findPatientByNUH Descripción Devuelve el paciente identificado por el número de historia pasado como parámetro. Parámetros de entrada NUH (String, obligatorio): Número de historia del paciente. Respuesta data (XML Object, obligatorio): Contenedor con los recursos solicitados. Posibles errores Límite de tiempo excedido. Error en el servidor. 49 Tabla 3-30. Método para el recurso Patient (II) Nombre del método findPatientByPractitioner Descripción Devuelve los pacientes a cargo del profesional identificado por el DNI pasado como parámetro. Parámetros de entrada DNI (String, obligatorio): Documento Nacional de Identidad del profesional. Respuesta data (XML Object, obligatorio): Contenedor con los recursos solicitados. Posibles errores Límite de tiempo excedido. Error en el servidor. 3.4.2.2. Métodos para el recurso Practitioner Contamos con un método para acceder a la información modelada en el recurso Practitioner, con el que se obtiene la información del profesional solicitado. Tabla 3-31. Método para el recurso Practitioner Nombre del método findPractitionerByID Descripción Devuelve el profesional identificado con el Documento Nacional de Identidad pasado como parámetro. Parámetros de entrada DNI (String, obligatorio): Documento Nacional de Identidad del profesional. Respuesta data (XML Object, obligatorio): Contenedor con los recursos solicitados. Posibles errores Límite de tiempo excedido. Error en el servidor. 3.4.2.3. Métodos para el recurso Appointment Contamos con cuatro métodos para acceder a la información modelada en el recurso Appointment. Con el primero, se obtienen todas las citas futuras del paciente, mientras que, con el segundo, obtenemos aquellas comprendidos entre las dos fechas pasadas como parámetros. De manera análoga, tendremos otros dos métodos para obtener las citas que tiene concertadas un profesional. 50 Tabla 3-32. Método para el recurso Appointment (I) Nombre del método findAppointmentByPatient Descripción Devuelve todas las citas futuras del paciente. Parámetros de entrada NUH (String, obligatorio): Número de historia del paciente. Respuesta data (XML Object, obligatorio): Contenedor con los recursos solicitados. Posibles errores Límite de tiempo excedido. Error en el servidor. Tabla 3-33. Método para el recurso Appointment (II) Nombre del método findAppoinmentByPatDate Descripción Devuelve las citas del paciente comprendidas entre las dos fechas pasadas como parámetros. Parámetros de entrada NUH (String, obligatorio): Número de historia del paciente. Desde (Date, obligatorio): Fecha desde la que iniciar la búsqueda. Hasta (Date, obligatorio): Fecha hasta la que parar la búsqueda. Respuesta data (XML Object, obligatorio): Contenedor con los recursos solicitados. Posibles errores Límite de tiempo excedido. Error en el servidor. Tabla 3-34. Método para el recurso Appointment (III) Nombre del método findAppointmentByPractitioner Descripción Devuelve todas las citas futuras del profesional. Parámetros de entrada DNI (String, obligatorio): Documento Nacional de Identidad del profesional. Respuesta data (XML Object, obligatorio): Contenedor con los recursos solicitados. Posibles errores Límite de tiempo excedido. Error en el servidor. 51 Tabla 3-35. Método para el recurso Appointment (IV) Nombre del método findAppointmentByPracDate Descripción Devuelve las citas del profesional, comprendidas entre las dos fechas pasadas como parámetros. Parámetros de entrada DNI (String, obligatorio): Documento Nacional de Identidad del profesional. Desde (Date, obligatorio): Fecha desde la que iniciar la búsqueda. Hasta (Date, obligatorio): Fecha hasta la que parar la búsqueda. Respuesta data (XML Object, obligatorio): Contenedor con los recursos solicitados. Posibles errores Límite de tiempo excedido. Error en el servidor. 3.4.2.4. Métodos para el recurso Encounter Contamos con cuatro métodos para acceder a la información modelada en el recurso Encounter. Con el primero, se obtienen todos los encuentros que ha realizado el paciente, mientras que, con el segundo, obtenemos aquellos comprendidos entre las dos fechas pasadas como parámetros. De manera análoga, tendremos otros dos métodos para obtener los encuentros en los que ha participado un profesional. Tabla 3-36. Método para el recurso Encounter (I) Nombre del método findEncounterByPatient Descripción Devuelve todas las citas del paciente. Parámetros de entrada NUH (String, obligatorio): Número de historia del paciente. Respuesta data (XML Object, obligatorio): Contenedor con los recursos solicitados. Posibles errores Límite de tiempo excedido. Error en el servidor. Tabla 3-37. Método para el recurso Encounter (II) Nombre del método findEncounterByPatDate Descripción Devuelve las citas del paciente comprendidas entre las dos fechas pasadas como parámetros. Parámetros de entrada NUH (String, obligatorio): Número de historia del paciente. 58 3.5. Implementación del servicio web Para cerrar el capítulo, se describirá la implementación del servicio web, partiendo por su diseño, a nivel de funcionalidad y estructura, e integrando los elementos que se han diseñado en los apartados anteriores. Tras esto, se pasará a ver los aspectos más importantes de su desarrollo. Por último, se detallarán y expondrán las pruebas realizadas sobre la implementación. 3.5.1. Diseño del servicio web Aunque la Figura 1-1 representaba la funcionalidad del servicio web, es interesante completarla con los elementos que se han ido diseñando en los apartados anteriores (objetos propios, recursos FHIR y métodos de acceso), para ver qué papel juegan en ésta. Para ello, se ha creado un diagrama de secuencia, que podemos ver en la Figura 3-26. Figura 3-26. Diagrama de secuencia de la funcionalidad del servicio web Los clientes solicitan la información almacenada en la base de datos mediante los métodos de acceso a recursos, utilizando uno u otro en función de qué información requieran. Cuando el servicio web recibe la petición, realiza la pertinente consulta a la base de datos de e-Nefro, almacenando la información que recibe en el objeto propio que corresponda. Por último, se crea el recurso FHIR que se suministrará al cliente, utilizando para ello la información almacenada en el objeto propio. El servicio web se ha diseñado buscando una arquitectura modular y adaptable, a fin de que sea cómodo trabajar con él, así como ser reutilizado para otros sistemas, añadiendo nuevos módulos si fuera necesario. Por ello, se han agrupado los distintos archivos que forman el proyecto en paquetes funcionales, y organizando estos en función del tipo de recurso. En la Figura 3-27 se muestra la estructura del servicio web mediante un diagrama de paquetes. 59 Figura 3-27. Diagrama de paquetes de la estructura del servicio web  Paquete bean: contiene las clases de los objetos de información de e-Nefro.  Paquete config: contiene la clase de configuración de la web de prueba que suministra la propia API, que se verá en un apartado posterior.  Paquete model: contiene las clases donde se definen los recursos extendidos de nuestro sistema.  Paquete narrative: contiene los archivos necesarios para generar los elementos narrativos de los recursos.  Paquete provider: contiene las clases proveedoras de recursos, donde se crean y suministran a los clientes.  Paquete servlet: contiene la clase en la que se define el servicio web, y se establecen sus proveedores de recursos y parámetros.  Paquete SQL: contiene las clases para la conexión y consulta a la base de datos de e-Nefro.  Paquete util: contiene clases para la creación de recursos que no se suministran al cliente directamente, sino que van contenidos en otros que sí. Todos estos elementos trabajan conjuntamente en la recepción de la petición de información, la obtención de la información solicitada, y la formación y suministro del recurso correspondiente, como se verá en el siguiente apartado. 3.5.2. Desarrollo del servicio web Una vez visto cómo funciona y cómo se estructura el servicio web, podemos pasar a ver cómo se han desarrollado los principales elementos que lo componen, y de qué forma trabajan conjuntamente para ofrecer la información al cliente. En esta primera implementación, se ha incluido todo lo relativo a los recursos Patient, Practitioner, Appointment, Encounter y Organization, en los que se hace uso de todo lo previamente explicado sobre los recursos FHIR: extensiones, recursos contenidos y elementos narrativos. 60 Para poder trabajar con la especificación HL7 FHIR, es necesario incluir en el pom.xml las dependencias de las librerías HAPI FHIR: <!-- This dependency includes the core HAPI-FHIR classes --> <dependency> <groupId>ca.uhn.hapi.fhir</groupId> <artifactId>hapi-fhir-base</artifactId> <version>1.5-SNAPSHOT</version> </dependency> <!-- At least one "structures" JAR must also be included --> <dependency> <groupId>ca.uhn.hapi.fhir</groupId> <artifactId>hapi-fhir-structures-dstu2</artifactId> <version>1.5-SNAPSHOT</version> </dependency> <!-- This dependency is used for the "FHIR Tester" web app overlay --> <dependency> <groupId>ca.uhn.hapi.fhir</groupId> <artifactId>hapi-fhir-testpage-overlay</artifactId> <version>1.5-SNAPSHOT</version> <type>war</type> <scope>provided</scope> </dependency> <dependency> <groupId>ca.uhn.hapi.fhir</groupId> <artifactId>hapi-fhir-testpage-overlay</artifactId> <version>1.5-SNAPSHOT</version> <classifier>classes</classifier> <scope>provided</scope> </dependency> El resto de elementos se explicarán agrupados por el paquete funcional en el que están contenidos. 3.5.2.1. Paquete servlet Contiene la clase ExampleRestfulServlet de donde se define el servicio web (Figura 3-28). Figura 3-28- Paquete servlet En primer lugar, en el constructor, se establece la versión de FHIR que se implementa, siendo la actual versión oficial, DSTU 2: /** * Constructor */ public ExampleRestfulServlet() { super(FhirContext.forDstu2()); // Support DSTU2 } A continuación se definen qué proveedores de recursos se van a implementar en el servicio. En esta primera implementación tendremos cuatro, para los recursos Patient, Practitioner, Appointment y Encounter: /* * Three resource providers are defined. Each one handles a specific * type of resource. */ List<IResourceProvider> providers = new ArrayList<IResourceProvider>(); providers.add(new PatientResourceProvider()); providers.add(new PractitionerResourceProvider()); providers.add(new AppointmentResourceProvider()); providers.add(new EncounterResourceProvider()); setResourceProviders(providers); 61 También se declaran los generadores de elementos narrativos que implementará nuestro servicio. En nuestro caso, se implementan el generador narrativo propio que provee la API, en la que únicamente se genera para el recurso Patient, y un generador propio, en el que hemos definido el elemento narrativo del recurso Practitioner: /* * Use a narrative generator. This is a completely optional step, * but can be useful as it causes HAPI to generate narratives for * resources which don't otherwise have one. */ //Generador narrativo por defecto INarrativeGenerator narrativeGen = new DefaultThymeleafNarrativeGenerator(); getFhirContext().setNarrativeGenerator(narrativeGen); //Generador narrativo propio String propFile = "file:C:/Users/migpedjim/Desktop/hapi-fhir-master/restful-server- example/src/main/java/enefro/interop/narrative/narratives.properties"; CustomThymeleafNarrativeGenerator myNarrativeGen = new CustomThymeleafNarrativeGenerator(propFile); getFhirContext().setNarrativeGenerator(myNarrativeGen); Por último, se establecen una serie de parámetros para que sean más cómodas de leer las respuestas del servidor: /* * This server interceptor causes the server to return nicely * formatter and coloured responses instead of plain JSON/XML if * the request is coming from a browser window. It is optional, * but can be nice for testing. */ registerInterceptor(new ResponseHighlighterInterceptor()); /* * Tells the server to return pretty-printed responses by default */ setDefaultPrettyPrint(true); 3.5.2.2. Paquete narrative Este paquete contiene los archivos necesarios para la implementación del generador narrativo propio (Figura 3-29). Figura 3-29. Paquete narrative En narrative.properties se establecen las propiedades del generador. Concretamente, para qué recursos va a generar su elemento narrativo, y dónde se encuentran estos: #Recurso Practitioner practitioner.class=ca.uhn.fhir.model.dstu2.resource.Practitioner practitioner.narrative=file:C:/Users/migpedjim/Desktop/hapi-fhir-master/restful-server- example/src/main/java/enefro/interop/narrative/Practitioner.html En Practitioner.html se define el elemento narrativo que se va a generar. En primer lugar, se implementa la hoja de estilos narrative.css, donde se define el estilo: <head> <link rel="stylesheet" type="text/css" href="narrative.css"/> </head> 62 Por último, se definen los elementos que lo componen, indicando qué atributos del recurso contiene y su estructura HTML: <div> <th:block th:if="${not resource.name.empty}"> <div class="hapiHeaderText" th:narrative="${resource.name}"/> </th:block> <table class="hapiPropertyTable"> <tbody> <tr th:if="${not resource.identifier.empty}"> <td>Identifier</td> <td th:narrative="${resource.identifier[0]}"></td> </tr> <tr th:if="${not resource.telecom.empty}"> <td>Teléfono</td> <td th:narrative="${resource.telecom[0].valueElement}"></td> </tr> <tr th:if="${not resource.telecom.empty}"> <td>Email</td> <td th:narrative="${resource.telecom[1].valueElement}"></td> </tr> <tr th:if="${not resource.practitionerRole.empty}"> <td>Cargo</td> <td th:narrative="${resource.practitionerRole[0].role}"></td> </tr> <tr th:if="${not resource.practitionerRole.empty}"> <td>Especialidad</td> <td th:narrative="${resource.practitionerRole[0].specialty[0]}"></td> </tr> <tr th:if="${not resource.practitionerRole.empty}"> <td>Organización</td> <td th:narrative="${resource.practitionerRole[0].managingOrganization.resource.nameElement}"></td> </tr> </tbody> </table> </div> 3.5.2.3. Paquete bean Este paquete contiene las clases de los objetos propios definidos en el sistema e-Nefro, a los que se mapea la información extraída de la base de datos (Figura 3-30). Figura 3-30. Paquete bean Esta clase contiene los atributos definidos para el objeto al que representa. Por ejemplo, en el caso de la clase AppointmentBean: private int idCita; private int idPlan; private int idPaciente; private int idProfesional; private String localizacion; private Date fechaInicio; private String causa; private String descripcion; private String obserMed; private String obserEnf; private String comenPac; 63 Y una serie de métodos para obtener dicha información: //Metodo para obtener el id de la cita public int getIdCita() { return idCita; } //Metodo para obtener el id interno del paciene implicado public int getIdPaciente() { return idPaciente; } 3.5.2.4. Paquete SQL Este paquete contiene las clases con los métodos necesarios para realizar las consultas a la base de datos de e- Nefro (Figura 3-31). Figura 3-31. Paquete SQL En primer lugar, se establece el manejador de la base de datos, en este caso implementada con tecnología postgreSQL: //Manejador de la base de datos Class.forName("org.postgresql.Driver"); Antes de realizar la consulta, es necesario conectarse a la base de datos, pasando para ello un usuario con los permisos necesarios, su contraseña y la URL del servidor de base de datos: //Parametros y conexión a la bbdd String usuario = "enefro_owner"; String password = "enefro_owner"; String url = "jdbc:postgresql://gibserv.us.es:4502/enefro"; Connection conexion = DriverManager.getConnection(url, usuario, password); Una vez conectados, definimos la consulta y la ejecutamos. Esta sería una consulta para obtener la información de las citas y encuentros de un profesional, dentro de la clase AppointmentSQL.java: //Consulta a base de datos String sql = "SELECT * FROM " + "((((e_appointmentactivity left join e_appointmentregistry on appo_id=appr_appointmentacti) " + "INNER JOIN e_activity ON appo_base_acti = acti_id) INNER JOIN e_plan ON appo_id_plan=plan_id) " + "LEFT JOIN e_clinicalregistry ON appr_base_crir=crir_id) WHERE appo_citadocon = (SELECT usua_id " + "FROM e_usuario INNER JOIN e_person ON usua_persona=pers_id WHERE pers_document = '"+idPrac+"')"; Statement st = conexion.createStatement(); ResultSet rs = st.executeQuery(sql); Y pasamos a recorrer el resultado mapeando la información de cada elemento obtenido en el objeto propio correspondiente. Estos objetos se irán agrupando en una lista que será devuelta por el método: 64 //Recoremos el resultado de la consulta while (rs.next()) { AppointmentBean appointment = new AppointmentBean(); appointment = new AppointmentBean(); appointment.setIdPlan(rs.getInt("appo_id_plan")); appointment.setIdPaciente(rs.getInt("plan_pacienteusuario")); appointment.setIdProfesional(rs.getInt("appo_citadocon")); appointment.setLocalizacion(rs.getString("acti_location")); appointment.setFechaInicio(rs.getTimestamp("acti_startdate")); appointment.setCausa(rs.getString("acti_problemaa")); appointment.setDescripcion(rs.getString("acti_description")); appointment.setObserMed(rs.getString("appo_observacionpriv")); appointment.setObserEnf(rs.getString("appo_observacionenfe")); appointment.setComenPac(rs.getString("crir_comentarios")); listAppointments.add(appointment); } rs.close(); st.close(); conexion.close(); } catch (Exception e){ e.printStackTrace(); } return listAppointments; } 3.5.2.5. Paquete model Este paquete contiene las clases donde se definen los recursos extendidos (Figura 3-32). Figura 3-32. Paquete model En nuestro caso, hemos extendido el recurso Encounter, mediante la clase MyEncounter, para que contenga la información relativa a las observaciones médicas, observaciones de enfermería y comentarios para el paciente realizados durante el mismo. Esta clase es necesario extenderla con el recurso al que está extendiendo, para que cuando se utilice posteriormente, además de los recursos extendidos, contenga los propios: @ResourceDef(name = "Encounter") public class MyEncounter extends Encounter { … } A continuación, se van definiendo y creando las extensiones, indicando el nombre, su descripción y algunos parámetros: url (dirección que nos devuelve el recurso StructureDefinition con la información de la estructura de la extensión), isModifier (si el atributo modifica el significado del recurso que lo contiene) y definedLocally (si la extensión está definida localmente): /** * This is a basic extension, with a DataType value (in this case, StringDt) */ //Atributo extendido Observaciones medicas @Child(name = "obsMedico") @Description(shortDefinition = "Contiene las observaciones hechas por el profesional médico") @Extension(url = "localhost:8080/extensión/encounter/obsmed", isModifier = false, definedLocally = true) private StringDt myObsMedico; Y para poder trabajar con estos atributos extendidos del recurso, es necesario crear los métodos Get y Set correspondientes: 65 //Obtenemos las observaciones medicas del encuentro public StringDt getObsMedico() { return myObsMedico; } //Establecemos las observaciones medicas del encuentro public void setObsMedico(StringDt obsMedico) { this.myObsMedico = obsMedico; } 3.5.2.6. Paquete provider Este paquete contiene los proveedores de recursos, es decir, las clases en las que se forman y suministran los recursos al cliente (Figura 3.33). Figura 3-33. Paquete provider Estas clases tienen una gran importancia en el servicio web, y son de especial complejidad, pues hacen uso de todos los elementos explicados en la estructura del servicio. Para explicar su funcionamiento, se va a ver el proveedor EncounteResourceProvider, que hace uso de recursos contenidos y extensiones. Esta clase implementa la interfaz IResourceProvier, necesaria en todos los proveedores de recursos. Además, es necesario definir qué tipo de recurso suministra, en nuestro caso MyEncounter, que extiende el recurso Encounter definido por FHIR: public class EncounterResourceProvider implements IResourceProvider{ @Override public Class<? extends IBaseResource> getResourceType() { return MyEncounter.class; } Tras esto, se definen los métodos de acceso al recurso, indicando qué tipo de operación es, a través de un sistema de etiquetas que implementa la API, en nuestro caso Search. Este método en particular devuelve todos los encuentros en los que ha participado un profesional en una lista de recursos MyEncounter, pasándole como parámetro el DNI del profesional: @Search() Public List<MyEncounter> findEncounterByPractitioner(@RequiredParam(name=Encounter.SP_PRACTITIONER) StringParam idPractitioner){ … return listaEncounter; } Se va a describir cómo funcionan nuestros proveedores de recursos con este método como ejemplo. En primer lugar, se recupera la información de la base de datos, mediante el método correspondiente de la clase AppointmentSQL, y se mapea a una lista de AppointmentBean, que recorreremos con un iterador: //Recuperamos los encuentros de base de datos LinkedList<AppointmentBean> listaAppointmentsBean = AppointmentSQL.getAppointmentsByPractitioner(idPractitioner.getValue()); Iterator<AppointmentBean> it = listaAppointmentsBean.iterator(); 66 Es necesario crear la lista de recursos MyEncounter que se suministrará al cliente, en la que iremos incluyendo los recursos formados: //Creamos la lista de recursos MyEncounter List<MyEncounter> listaEncounter = new ArrayList<MyEncounter>(); Dentro de un bucle While, vamos recorriendo la lista de objetos AppointmentBean y formando los recursos con su información: //Recorremos la lista de PacientesBean para ir formando los recursos FHIR while (it.hasNext()) { AppointmentBean AppointmentActual = (AppointmentBean) it.next(); MyEncounter encounter = new MyEncounter(); … } Dentro del bucle, se van añadiendo los atributos del recurso con la información correspondiente. Por ejemplo, para añadir el Id del recurso, campo obligatorio: //Identificador del recurso encounter.setId(Long.toString(AppointmentActual.getIdCita())); Para añadir un recurso contenido, como, por ejemplo, el paciente que participa en el encuentro, utilizamos la clase PatientUtil, con la que podemos obtener un recurso Patient pasándole el identificador interno almacenado en el campo idPaciente del objeto Encuentro. Aunque todo el mecanismo de formación del recurso Patient (consulta a base de datos y mapeo al recurso FHIR) se podría hacer sin utilizar esta clase externa, es más eficiente la creación de estas clases útiles y utilizarlas directamente en todos los recursos donde se necesite. Una vez obtenido el recurso, se referencia a través del atributo patient del recurso Encounter: //Creamos un recurso Patient y lo incluimos Patient patient = PatientUtil.findPatientById(AppointmentActual.getIdPaciente()); if(patient!=null){ encounter.getPatient().setResource(patient); } Los atributos extendidos se añaden del mismo modo que los propios, ya que hemos definido el recurso extendido MyAppointment que los implementa: //Observaciones medicas StringDt ObsMedico = new StringDt(); ObsMedico.setValueAsString(AppointmentActual.getObserMed()); encounter.setObsMedico(ObsMedico); //Observaciones de enfermeria StringDt ObsEnf = new StringDt(); ObsEnf.setValueAsString(AppointmentActual.getObserEnf()); encounter.setObsEnferm(ObsEnf); //Comentarios para el paciente StringDt ComPac = new StringDt(); ComPac.setValueAsString(AppointmentActual.getComenPac()); encounter.setComPaciente(ComPac); Una vez formada la lista de recursos Encounter, tendríamos toda la información solicitada por el cliente. 67 3.5.3. Validación del servicio web Una vez visto cómo ha sido desarrollado el servicio web, se van a mostrar las pruebas de funcionamiento más relevantes realizadas sobre él. Se han realizado dos bloques de pruebas, el primero desde el módulo web que suministra la propia API para el testeo del servicio, y el segundo desde un cliente FHIR Android que se ha implementado específicamente para ello. Aunque se van a hacer uso de estos clientes para que sean más entendibles los resultados obtenidos, también es posible realizar peticiones directamente al servidor desde la dirección base http://localhost:8080/restfulserver-example/fhir, establecida en el archivo web.xml: <servlet-mapping> <servlet-name>fhirServlet</servlet-name> <url-pattern>/fhir/*</url-pattern> </servlet-mapping> 3.5.3.1. Módulo web de testeo La API implementa un módulo web de testeo, con el que es posible hacer uso, de manera sencilla, de los proveedores de recursos que soporta nuestro servicio web. Se configura desde la clase FhirTesterConfig dentro del paquete config (Figura 3-34). Figura 3-34. Paquete config Indicando qué servidor se va a testear con el módulo: TesterConfig retVal = new TesterConfig(); retVal .addServer() .withId("home") .withFhirVersion(FhirVersionEnum.DSTU2) .withBaseUrl("${serverBase}/fhir") .withName("Local Tester") Se accede a ella a través de la dirección http://localhost:8080/restful-server-example/tester/, tal como se establece en el archivo web.xml: <servlet-mapping> <servlet-name>spring</servlet-name> <url-pattern>/tester/*</url-pattern> </servlet-mapping> El módulo provee de una interfaz agradable para realizar las pruebas sobre nuestro servicio. En la página principal encontramos (Figura 3-35): 1. Información sobre nuestro servicio web: nombre, versión que implementa y dirección base. 2. Las opciones del servicio, donde se puede establecer si queremos la respuesta como XML o JSON (Encoding) o si queremos que salgan de manera agradable visualmente (pretty). 3. La lista de recursos que provee nuestro servicio, desde la que seleccionar el proveedor que queremos probar. 74 <td>MEDICO</td> </tr> <tr> <td>Especialidad</td> <td>Especialista Nefrología</td> </tr> <tr> <td>Organización</td> <td>Hospital de prueba</td> </tr> </tbody> </table> </div> </text> <contained> <Organization xmlns="http://hl7.org/fhir"> <id value="1"/> <name value="Hospital de prueba"/> <telecom> <system value="phone"/> <value value="656895262"/> </telecom> <telecom> <system value="email"/> <value value="[email protected]"/> </telecom> <address> <line value="41092"/> </address> </Organization> </contained> <identifier> <type> <text value="3"/> </type> <value value="57722647F"/> </identifier> <active value="true"/> <name> <family value="Núñez García"/> <given value="Alberto"/> </name> <telecom> <system value="phone"/> <value value="698454545"/> </telecom> <telecom> <system value="email"/> <value value="[email protected]"/> </telecom> <gender value="male"/> <birthDate value="1971-04-09"/> <practitionerRole> <managingOrganization> <reference value="#1"/> </managingOrganization> <role> <text value="MEDICO"/> </role> <specialty> <text value="Especialista Nefrología"/> </specialty> </practitionerRole> </Practitioner> </resource> </entry> </Bundle> En la Figura 3-43 vemos el elemento narrativo que se genera junto a este recurso. 75 Figura 3-43. Elemento narrativo de recurso Practitioner  Acceso a la información de un profesional inexistente Se provee un recurso Practitioner cuyo DNI coincide con el que se le pasa como parámetro, en ese caso inexistente en la base de datos. La petición se realiza mediante un GET, en el que viaja el parámetro de búsqueda que identifica al paciente, que para la prueba se ha establecido como ‘ProfesionalInexistente’. Responde con un HTTP 200 OK, indicando que no ha habido errores durante el proceso (Figura 3-44). Figura 3-44. Petición/Respuesta consulta de un profesional inexistente El bundle no contiene ninguna entrada, pues no existe ningún profesional con ese DNI: <Bundle xmlns="http://hl7.org/fhir"> <id value="bc0844b2-b286-46e9-9471-6948462f04b3"/> <meta> <lastUpdated value="2016-06-28T15:07:08.218+02:00"/> </meta> <type value="searchset"/> <total value="0"/> <link> <relation value="self"/> <url value="http://localhost:8080/restful-server- example/fhir/Practitioner?identifier=ProfesionalInexistente"/> </link> </Bundle> 76  Acceso a la información de todas las citas del profesional con DNI 57722647F Se proveen los recursos Appointment de las citas del profesional cuyo DNI coincide con el que se le pasa como parámetro, en este caso 57722647F. La petición se realiza mediante un GET, en el que viaja el parámetro de búsqueda que identifica al profesional. Responde con un HTTP 200 OK, indicando que no ha habido errores durante el proceso (Figura 3-45). Figura 3-45. Petición/Respuesta consulta de las citas de un profesional El bundle contiene catorce entradas, correspondientes a las citas del profesional. Por extensión, sólo se incluye una de ellas. <Bundle xmlns="http://hl7.org/fhir"> <id value="5a07e44f-454a-4bf3-a102-56c8925aaa69"/> <meta> <lastUpdated value="2016-06-26T18:22:56.635+02:00"/> </meta> <type value="searchset"/> <total value="14"/> <link> <relation value="self"/> <url value="http://localhost:8080/restful-server-example/fhir/Appointment?practitioner=57722647F"/> </link> <entry> <fullUrl value="http://localhost:8080/restful-server-example/fhir/Appointment/1"/> <resource> <Appointment xmlns="http://hl7.org/fhir"> <id value="1"/> <contained> <Patient xmlns="http://hl7.org/fhir"> <id value="1"/> <identifier> <type> <coding> <system value="http://hl7.org/fhir/v2/0203"/> <code value="MR"/> </coding> </type> <value value="625218621"/> </identifier> <identifier> <type> <text value="3"/> </type> <value value="87743365K"/> </identifier> <active value="true"/> <name> <family value="Paz Martínez"/> <given value="Lucía"/> </name> <telecom> <system value="phone"/> <value value="698336655"/> </telecom> 77 <telecom> <system value="email"/> <value value="[email protected]"/> </telecom> <gender value="female"/> <birthDate value="1973-04-25"/> <address> <line value="Calle Álava 34"/> </address> </Patient> </contained> <contained> <Practitioner xmlns="http://hl7.org/fhir"> <id value="2"/> <identifier> <type> <text value="3"/> </type> <value value="57722647F"/> </identifier> <active value="true"/> <name> <family value="Núñez García"/> <given value="Alberto"/> </name> <telecom> <system value="phone"/> <value value="698454545"/> </telecom> <telecom> <system value="email"/> <value value="[email protected]"/> </telecom> <gender value="male"/> <birthDate value="1971-04-09"/> <practitionerRole> <role> <text value="MEDICO"/> </role> <specialty> <text value="Especialista Nefrología"/> </specialty> </practitionerRole> </Practitioner> </contained> <contained> <Location xmlns="http://hl7.org/fhir"> <id value="3"/> <name value="Sala 4"/> </Location> </contained> <reason> <text value="DIALISIS"/> </reason> <description value="Cita semanal"/> <start value="2016-04-27"/> <participant> <type> <text value="Paciente"/> </type> <actor> <reference value="#1"/> </actor> </participant> <participant> <type> <text value="Profesional sanitario"/> </type> <actor> <reference value="#2"/> </actor> </participant> <participant> <type> <text value="Localización"/> </type> <actor> <reference value="#3"/> </actor> </participant> </Appointment> </resource> </entry> 78  Acceso a la información de todos los encuentros del profesional con DNI 57722647F Se provee los recursos Encounter de los encuentros del profesional cuyo DNI coincide con el que se le pasa como parámetro, en este caso 57722647F. La petición se realiza mediante un GET, en el que viaja el parámetro de búsqueda que identifica al profesional. Responde con un HTTP 200 OK, indicando que no ha habido errores durante el proceso (Figura 3-46). Figura 3-46. Petición/Respuesta consulta de los encuentros de un profesional El bundle contiene catorce entradas, correspondientes a los encuentros del profesional. Por extensión, sólo se incluye uno de ellos. <Bundle xmlns="http://hl7.org/fhir"> <id value="10e978e6-7fd1-4c2f-b522-5f999320c9e8"/> <meta> <lastUpdated value="2016-06-26T18:26:35.650+02:00"/> </meta> <type value="searchset"/> <total value="14"/> <link> <relation value="self"/> <url value="http://localhost:8080/restful-server-example/fhir/Encounter?practitioner=57722647F"/> </link> <entry> <fullUrl value="http://localhost:8080/restful-server-example/fhir/Encounter/4"/> <resource> <Encounter xmlns="http://hl7.org/fhir"> <id value="4"/> <contained> <Patient xmlns="http://hl7.org/fhir"> <id value="1"/> <identifier> <type> <coding> <system value="http://hl7.org/fhir/v2/0203"/> <code value="MR"/> </coding> </type> </identifier> <identifier> <type> <text value="3"/> </type> <value value="42266532F"/> </identifier> <active value="true"/> <name> <family value="Alvarez Castro"/> <given value="Juan"/> </name> <telecom> <system value="phone"/> <value value="625698695"/> </telecom> <telecom> 79 <system value="email"/> <value value="ju[email protected]"/> </telecom> <gender value="male"/> <birthDate value="1985-05-08"/> <address> <line value="Avenida Colonizadores 23"/> </address> </Patient> </contained> <contained> <Practitioner xmlns="http://hl7.org/fhir"> <id value="2"/> <identifier> <type> <text value="3"/> </type> <value value="57722647F"/> </identifier> <active value="true"/> <name> <family value="Núñez García"/> <given value="Alberto"/> </name> <telecom> <system value="phone"/> <value value="698454545"/> </telecom> <telecom> <system value="email"/> <value value="al[email protected]"/> </telecom> <gender value="male"/> <birthDate value="1971-04-09"/> <practitionerRole> <role> <text value="MEDICO"/> </role> <specialty> <text value="Especialista Nefrología"/> </specialty> </practitionerRole> </Practitioner> </contained> <contained> <Appointment xmlns="http://hl7.org/fhir"> <id value="3"/> <reason> <text value="DIALISIS"/> </reason> <description value="Cita ordinaria de seguimiento"/> <start value="2016-05-18"/> </Appointment> </contained> <contained> <Location xmlns="http://hl7.org/fhir"> <id value="4"/> <name value="Sala 4"/> </Location> </contained> <extension url="ObsMed"> <valueString value="El paciente hace un uso escaso del sistema. Recordarle que las actividades de su plan de cuidados puede consultarlas en el mismo."/> </extension> <patient> <reference value="#1"/> </patient> <participant> <type> <text value="Profesional sanitario"/> </type> <individual> <reference value="#2"/> </individual> </participant> <appointment> <reference value="#3"/> </appointment> <location> <location> <reference value="#4"/> </location> </location> </Encounter> </resource> </entry> 80  Acceso a método no implementado Se accede a un método no implementado en ningún proveedor de recursos. Concretamente, a un método para el recurso Patient al que le estamos pasando como parámetro el identificador del paciente y del profesional a la vez. La petición se realiza mediante un GET, en el que viajan ambos parámetros. Responde con un HTTP 400 Petición Incorrecta, indicando esa petición no está implementada (Figura 3-47). Figura 3-47. Petición/Respuesta acceso a método no implementado En el contenido del mensaje se representa la causa del error, indicando que el servidor no conoce cómo manejar una petición GET con esos parámetros: <OperationOutcome xmlns="http://hl7.org/fhir"> <text> <status value="generated"/> <div xmlns="http://www.w3.org/1999/xhtml"> <h1>Operation Outcome</h1> <table border="0"> <tr> <td style="font-weight: bold;">error</td> <td>[]</td> <td> <pre>Invalid request: The FHIR endpoint on this server does not know how to handle GET operation[Patient] with parameters [[careprovider, identifier]]</pre> </td> </tr> </table> </div> </text> <issue> <severity value="error"/> <code value="processing"/> <diagnostics value="Invalid request: The FHIR endpoint on this server does not know how to handle GET operation[Patient] with parameters [[careprovider, identifier]]"/> </issue> </OperationOutcome> 3.5.3.3. Cliente FHIR Android Por último, se ha desarrollado un cliente FHIR Android para validar el servicio web desde un sistema externo real. Se escoge este tipo de sistema, por la creciente importancia de las aplicaciones móviles en salud, y en particular sobre este sistema operativo. La funcionalidad de la aplicación es muy sencilla, pues el objetivo de esta es únicamente la validación del servicio. Concretamente, se introduce el DNI de un profesional y, pulsando el botón ‘BUSCAR’, devuelve la información de los pacientes a su cargo (Figura 3-48). 81 Figura 3-48. Cliente FHIR Android: Interfaz Para trabajar con la especificación HL7 FHIR, es necesario añadir al Grandle la dependencia de la librería HAPI FHIR para Android. dependencies { compile (group: 'ca.uhn.hapi.fhir', name: 'hapi-fhir-android', version: '1.5-SNAPSHOT', classifier: 'dstu2') { exclude module: 'javax.servlet-api' exclude module: 'hapi-fhir-base' } En primer lugar, re realiza la conexión al servidor web, pasando para ello como parámetro su dirección base. Tras ello, realizamos la consulta pertinente contra este: try { FhirContext fc = FhirContext.forDstu2(); //Skip retrieval of conformance statement... fc.getRestfulClientFactory().setServerValidationMode(ServerValidationModeEnum.NEVER); IGenericClient gc = fc.newRestfulGenericClient("http://10.0.2.2:8080/restful-server-example/fhir"); //$NON-NLS-1$ return gc.search().forResource(Patient.class) .where(new StringClientParam("careprovider").matches().value(profesional)) .execute(); } catch (Throwable e) { Log.e("Err", "Err, handle this better", e); } En el caso de que el bundle suministrado no contenga entradas, se muestra un mensaje indicándolo: if(o.isEmpty()){ Toast.makeText(getApplicationContext(), "Profesional incorrecto o sin pacientes", Toast.LENGTH_SHORT).show(); } else { List<Patient> list = o != null ? o.getResources(Patient.class) : Collections.<Patient>emptyList(); mAdapter.setData(list); } 82 Una vez recibido el bundle, se recorren sus recursos y se muestra su contenido en la aplicación, utilizando para ello su elemento narrativo: Patient patient = data.get(position); StringBuilder b = new StringBuilder("NUH/DNI: "); for (IdentifierDt i : patient.getIdentifier()) { if (i.isEmpty()) { continue; } b.append(" ").append(i.getValue()); } holder.header.setText(b.toString().trim()); holder.content.setText(Html.fromHtml(patient.getText().getDiv().getValueAsString())); 3.5.3.4. Pruebas desde el cliente FHIR Android  Acceso a la información de los pacientes a cargo del profesional con DNI 57722647F Se proveen los recursos Patient de los pacientes que están a cargo del profesional cuyo DNI coincide con el que se le pasa como parámetro, en ese caso inexistente en este caso 57722647F (Figura 3-49). Figura 3-49. Cliente FHIR Android: Muestra de los pacientes obtenidos 83  Acceso a la información de los pacientes a cargo de un profesional inexistente Se proveen los recursos Patient de los pacientes que están a cargo del profesional cuyo DNI se le pasa como parámetro, en este caso inexistente en la base de datos (Figura 3-50). Figura 3-50. Cliente FHIR Android: Notificación de no infomación