Índice de contenido -...
TRANSCRIPT
Gestión de Análisis Clínicos: Cornalvo
Índice de contenidoCapítulo1 : Introducción.......................................................................................................................5
Subcapítulo1.1: Objetivo................................................................................................................. 6Subcapítulo1.2: Proyecto Cornalvo: Módulos básicos.................................................................... 7Subcapítulo1.3: IHE.........................................................................................................................8Subcapítulo1.4: IHE en Europa..................................................................................................... 11
Capítulo2 : Guía implementación IHE-HL7...................................................................................... 13Subcapítulo 2.1: Visión general..................................................................................................... 15Subcapítulo 2.2: Sistema de Información de Laboratorio (SIL)....................................................16
Capítulo3 : Material y método............................................................................................................16Subcapítulo 3.1: Orden externa con el espécimen identificado.....................................................17Subcapítulo 3.2: Órdenes externas con espécimenes sin identificar o recogidos por el laboratorio........................................................................................................................................................ 18Subcapítulo 3.3: Ordenes con espécimenes identificados por terceras partes o recogidos por el laboratorio......................................................................................................................................18Subcapítulo 3.4: Perfil IHE del Flujo de Trabajo Programado de Laboratorio (LSWF)...............20Subcapítulo 3.5: Actores................................................................................................................ 21Subcapítulo 3.6: Transacciones......................................................................................................23
Capítulo 4 : Estados de una prueba.................................................................................................... 24Capítulo 5 : Transacción LAB-3.........................................................................................................25
Subcapítulo 5.1: Mensaje OUL^R22.............................................................................................25Subcapítulo 5.2: Mensaje OUL^R24.............................................................................................26Subcapítulo 5.3: Mensaje ACK..................................................................................................... 27
Capítulo 6 : Segmentos.......................................................................................................................28Subcapítulo 6.1: Segmento MSH...................................................................................................29
MSH-1 Separador de campos................................................................................................... 30MSH-2 Caracteres de codificación........................................................................................... 30MSH-3 Aplicación emisora.......................................................................................................30MSH-4 Centro emisor...............................................................................................................31MSH-5 Aplicación receptora.................................................................................................... 32MSH-6 Centro receptor.............................................................................................................32MSH-7 Fecha/hora del mensaje................................................................................................ 32MSH-9 Tipo de mensaje........................................................................................................... 32MSH-10 Identificador de control del mensaje.......................................................................... 33MSH-11 Identificador de procesamiento.................................................................................. 33MSH-12 Identificador de versión............................................................................................. 34
Subcapítulo 6.2: Segmento MSA...................................................................................................34MSA-1 Código de acuse de recibo........................................................................................... 35MSA-2 Identificador de control del mensaje ........................................................................... 36
Subcapítulo 6.3: Segmento ERR................................................................................................... 36ERR-3 Código de error HL7..................................................................................................... 36ERR-4 Severidad.......................................................................................................................37
Subcapítulo 6.4: Segmento PID.....................................................................................................38PID-3 Lista de ID de Paciente...................................................................................................40
1
Gestión de Análisis Clínicos: Cornalvo
PID-5 Nombre de Paciente....................................................................................................... 40PID-7 Fecha/Hora de Nacimiento.............................................................................................41PID-8 Sexo Administrativo.......................................................................................................41PID-11 Dirección del paciente.................................................................................................. 42PID-13 Número de Teléfono – Domicilio.................................................................................42PID-26 Ciudadanía....................................................................................................................42
Subcapítulo 6.5: Segmento OBR................................................................................................... 43OBR-1 Identificador de conjunto .............................................................................................46OBR-2 Número de orden del peticionario................................................................................ 46OBR-3 Número de orden del “order filler”.............................................................................. 46OBR-4 Identificador universal del servicio.............................................................................. 46OBR-10 Identificador del que recoge el espécimen................................................................. 46OBR-11 Código de Acción del espécimen................................................................................47OBR-16 Proveedor de la orden................................................................................................. 48OBR-24 Identificador de la sección de diagnóstico..................................................................48OBR-25 Estado del resultado....................................................................................................50OBR-28 Copias del resultado a.................................................................................................51
Subcapítulo 6.5: Segmento OBX...................................................................................................53OBX-1 Número de secuencia................................................................................................... 54OBX-2 Tipo de valor.................................................................................................................54OBX-3 Identificador de la observación.................................................................................... 56OBX-4 Subidentificador de la observación.............................................................................. 56OBX-5 Valores.......................................................................................................................... 56OBX-6 Unidades.......................................................................................................................56OBX-7 Rangos de valores normales......................................................................................... 56OBX-8 Señal de anormalidad................................................................................................... 57OBX-11 Estado del resultado de la observación.......................................................................58OBX-13 Chequeo de accesos de usuarios.................................................................................59OBX-14 Fecha y hora de observación...................................................................................... 59OBX-15 Identificación de quién produce el resultado..............................................................59OBX-16 Responsable de la observación (Verificador técnico).................................................59OBX-17 Método de la observación.......................................................................................... 59
Subcapítulo 6.6: Segmento NTE................................................................................................... 60NTE-1 Identificador de conjunto.............................................................................................. 60NTE-2 Origen del comentario...................................................................................................60NTE-3 Comentario....................................................................................................................61NTE-4 Tipo de comentario....................................................................................................... 61
Capítulo7 : Detalles de la implementación.........................................................................................62Subcapítulo7.1: Transporte JMS....................................................................................................62Subcapítulo7.2: Transporte TCP/IP (socket)................................................................................. 63
Capítulo 8 : Open Adaptor..................................................................................................................64Subcapítulo 8.1: introducción........................................................................................................ 64Subcapítulo 8.2: Adaptadores Openadaptor...................................................................................66Subcapítulo 8.3:Configuración de los componentes......................................................................67
Componente JMSSource...........................................................................................................67Componente JMSSink...............................................................................................................69Componentes Pipe.....................................................................................................................72HospitalPipe.............................................................................................................................. 72
2
Gestión de Análisis Clínicos: Cornalvo
GenericPipe............................................................................................................................... 74Implementación de un GenericPipe.......................................................................................... 78
AuditPipe..............................................................................................................................83FilterPipe...................................................................................................................................84El componente Controller......................................................................................................... 85El componente Logging............................................................................................................ 86Configuración para un adaptador: Roche..................................................................................88Caso de uso: procesar mensaje..................................................................................................89Configurando componentes...................................................................................................... 92Script de inicio/parada.............................................................................................................. 97
Capítulo 9 : Arquitectura.................................................................................................................... 98Subcapítulo 9.1: El receptor y el acumulador de resultados..........................................................99Subcapítulo 9.2: Consulta de los datos almacenados a través de un navegador Web..................100
Capítulo 10 : Situación actual y líneas futuras................................................................................. 110Anexo 1 : Ejemplos de códigos del acumulador del resultados....................................................... 112
Anexo 1.1: Código del ORT........................................................................................................ 112Anexo 1.2: Código del mensaje OUL_R24................................................................................. 120Anexo 1.3: Configuración de Hibernate...................................................................................... 137
Anexo 2 : Ejemplos de códigos de struts..........................................................................................144 Anexo 2.1: Código del Action buscar pacientes......................................................................... 144Anexo 2.2: Código del Form buscar pacientes............................................................................ 148Anexo 2.3: Configuración del pool de conexiones......................................................................152
Índice de ilustracionesIlustración 1: Proyecto Cornalvo : 1ª FASE......................................................................................... 7Ilustración 2: Esquema general de arquitectura basada en IHE......................................................... 16Ilustración 3: Caso de uso 1................................................................................................................17Ilustración 4: Caso de uso 2................................................................................................................18Ilustración 5: Caso de uso 3................................................................................................................19Ilustración 6: Relación de actores y las transacciones entre ellos...................................................... 20Ilustración 7: OpenAdaptor Framework.............................................................................................66Ilustración 8: Componente Palette......................................................................................................66Ilustración 9: Componentes JMS........................................................................................................67Ilustración 10: JMSSource................................................................................................................. 67Ilustración 11: JMSSink..................................................................................................................... 69Ilustración 12: HospitalPipe............................................................................................................... 72Ilustración 13: Property Tools............................................................................................................ 73Ilustración 14: GenericPipe................................................................................................................ 74Ilustración 15: Configuración de un Adaptador................................................................................. 88Ilustración 16: Arquitectura del Sistema............................................................................................ 98Ilustración 17: Validación del usuario a través de LDAP.................................................................102Ilustración 18: Búsqueda de un paciente.......................................................................................... 103Ilustración 19: Listado de pacientes................................................................................................. 104Ilustración 20: Listado de analíticas................................................................................................. 105Ilustración 21: Listado de pruebas del laboratorio........................................................................... 106Ilustración 22: Evolutivo de una prueba...........................................................................................107Ilustración 23: Comparativa de evolutivos.......................................................................................108
3
Gestión de Análisis Clínicos: Cornalvo
Ilustración 24: Informe de Laboratorio............................................................................................ 109Ilustración 25: Distribución de áreas del S.E.S................................................................................ 110
Índice de tablasTabla 1: Estados por los que pasa la orden desde el momento que es procesada por el Order Filler hasta que finalmente se completa o cancela la orden......................................................................... 24Tabla 2: Mensaje OUL^R22...............................................................................................................26Tabla 3: Mensaje OUL^R24...............................................................................................................26Tabla 4: Mensaje ACK....................................................................................................................... 27Tabla 5: Tabla HL7 de Atributos - MSH – Cabecera de mensaje......................................................29Tabla 6: Tabla HL7 0103 – Identificador de procesamiento.............................................................. 33Tabla 7: Tabla HL7 de Atributos - MSA – Confirmación de Mensaj.................................................34Tabla 8: Tabla HL7 0008 - Código de confirmación........................................................................35Tabla 9: Tabla HL7 de Atributos de error - ERR...............................................................................36Tabla 10: Tabla HL7 0516 – Severidad del error............................................................................... 37Tabla 11: Segmento PID.....................................................................................................................39Tabla 12: Tabla definida por el usuario 0001 – Sexo Administrativo................................................ 41Tabla 13: Tabla HL7 de Atributos – OBR – Petición de Observación............................................... 45Tabla 14: Tabla HL7 0065 – Códigos de acción del espécimen.........................................................47Tabla 15: Tabla HL7 0074 – Identificadores de Sección de Servicio Diagnóstico............................ 49Tabla 16: Tabla HL7 0123 – Estado de Resultado............................................................................. 51Tabla 17: Tabla HL7 de atributos – OBX – Observación/Resultad...................................................53Tabla 18: Tabla HL7 0125 – Tipo de valor........................................................................................55Tabla 19: Tabla definida por el usuario 0078 – Indicadores de anormalidad.....................................57Tabla 20: Tabla HL7 0085 – Interpretación de los códigos resultado de observación....................... 58Tabla 21: Segmento NTE................................................................................................................... 60Tabla 22: Tabla HL7 0105 – Origen del comentario.......................................................................... 60Tabla 23: Tabla definida por el usuario 0364 – Tipo de comentario.................................................. 61
4
Gestión de Análisis Clínicos: Cornalvo
Capítulo1 : IntroducciónLa iniciativa I.H.E., acrónimo inglés de Integrating the Healthcare Enterprise
(Integración de la Empresa/Organización de salud) nace como esfuerzo común de
la R.S.N.A. y la H.I.M.S.S. (Healthcare Information and Managment Systems
Society), a la que se unió posteriormente el A.C.C. (American Collage of
Cardiology). Dicho proyecto tiene la intención de dar respuesta a las dificultades
que tienen los diferentes sistemas de información clínico-asistenciales para
comunicarse entre sí, aún cuando estos sean conformes a estándares de la
categoría de DICOM y HL7. Nace en 1998 y, al igual que ocurriera con el estándar
DICOM, se han realizado varias “Demostraciones” en los congresos de la RSNA,
así como en los congresos de la HIMSS y la ACC.
Con la llegada del nuevo milenio nos encontramos en la era de la información en lo que
respecta a los cuidados de salud. Mejorar la atención de salud tanto de una forma
cuantitativa como cualitativa dependerá de la mejora en la gestión de la información
digital dentro y entre las instituciones de salud.
Actualmente en un sistema de salud cualquiera, existen docenas de sistemas de
información que realizan cada una funciones específicas. Pueden existir por ejemplo, un
sistema de facturación, un sistema de gestión de pacientes (ADT) y un numeroso grupo
de sistemas departamentales (como por ejemplo sistemas de información radiológica,
PACS, sistemas de información de laboratorio, sistemas de información de anatomía
patológica, etc). Para optimizar la eficiencia de estos sistemas, necesitan comunicarse
de tal forma que los usuarios finales tengan la información que necesitan para tomar
decisiones cuando y donde lo necesiten. Históricamente, tanto en nuestro modelo
sanitario como en los de cualquier otro país, la implantación de sistemas de información
se ha realizado de tal suerte que han conducido a la constitución de verdaderas “islas”
de información, sin interfases con otros sistemas. Afortunadamente, la llegada de
estándares de sistemas de información tales como Health Level 7 y DICOM han creado
mecanismos para compartir datos y optimizar los flujos de información [1]
5
Gestión de Análisis Clínicos: Cornalvo
Subcapítulo1.1: Objetivo
El proyecto Cornalvo puede establecerse en nuestro nivel como paradigma de
la voluntad de interoperabilidad entre sistemas que antiguamente se encontraban
aislados y sin posibilidad alguna de interaccionar. Este proyecto, desarrollado
integramente en el SES, pero con la decidida participación de las empresas, tiene lugar
en el dominio de Laboratorio. Es un proyecto que naciendo desde la modestia, pretende
implementar la mayor parte de actores y transacciones que están descritas en los
Technical Framework de Laboratorio, y cuyo alcance se extiende por todos los sistemas
departamentales de Laboratorio del SES.
El proyecto Cornalvo surge de la necesidad de construir la Historia de Salud única del
Sistema Sanitario Público de Extremadura, proyecto JARA, en la que es un requisito
indispensable contar con los resultados analíticos de las pacientes. No obstante esta
necesidad se ve seriamente limitada desde el punto de vista tecnológico por la
presencia de múltiples sistemas de información tecnológicamente independientes y en
los que se implementaba con diferentes criterios la identificación de nuestros pacientes
y con diferentes códigos sus resultados analíticos. Esto en la práctica hace que fuera
imposible compartir ningún dato sobre los resultados analíticos. Por ello se puso en
marcha un grupo, constituido por personal técnico y responsables del Área de
laboratorio (analistas, hematólogos, etc) para que utilizando el marco tecnológico de
IHE fuéramos capaces de hacer interoperables dichos sistemas sin menoscabo de la
satisfacción de los profesionales que trabajan en los laboratorios. Las conclusiones de
dicho grupo fueron las siguientes:
• Asumir la necesidad de identificar a sus pacientes de la misma forma que se
postula en el Plan de Sistemas del SES, es decir, con el CIP de la Comunidad.
• Asumir la necesidad de establecer un sistema de identificación de los analitos
realizados en cada laboratorio, utilizando para ello la terminología LOINC.
6
Gestión de Análisis Clínicos: Cornalvo
Subcapítulo1.2: Proyecto Cornalvo: Módulos básicos
Asumir que los esquemas de intercambio de información se adecuarían al perfil
I del Technical Framework de Laboratorio, construyendo “ex novo” una
aplicación que soportará el actor con la función de “Order Result Tracker”, y
utilizando los sistemas de información de laboratorio como “Order Filler”.
7
Ilustración 1: Proyecto Cornalvo : 1ª FASE
Gestión de Análisis Clínicos: Cornalvo
Subcapítulo1.3: IHE
Hoy por hoy, todas las partes que intervenimos en el proceso sanitario (tanto asistencial,
gestor o planificador) “sufrimos” de unos sistemas de información computacionales que
no comparten la información eficazmente. Es un objetivo teórico el que en un futuro
todos ellos compartan información de una forma eficaz y transparente. Como hemos
visto se hace necesario para ello el uso de lenguajes comunes o estándares de
comunicación medica, para que dichos sistemas sean interoperables. Pero dichos
estándares no garantizan la integración sin problemas, encontrándose los usuarios y
fabricantes habitualmente con serias dificultades para integrar los diferentes sistemas
de información.
La iniciativa IHE trata pues de establecer que estándares son recomendables utilizar en
una circunstancias específicas, construyendo lo que se llaman los “Technical
Frameworks”. Estos marcos de trabajo son un grupo detallado de documentos que guían
a los desarrolladores de sistemas de información y los integradores para poder
implementar las capacidades que se definen en la iniciativa.
8
Gestión de Análisis Clínicos: Cornalvo
La iniciativa IHE aún los esfuerzos de los usuarios y los desarrolladores de sistemas de
información y modalidades de adquisición para avanzar la integración de datos. Hace
uso de estándares establecidos para crear un marco de trabajo de transacciones entre
sistemas. Bajo la iniciativa IHE, los profesionales médicos y la industria sanitaria llegan
a un consenso de un modelo de integración que crezca anualmente, añadiendo
progresivamente más y más transacciones entre un grupo mayor de sistemas.
Los IHE Technical Framework documentan este modelo de integración. Se publican de
forman anual y se pueden revisar en la siguiente dirección: www.ihe.net. La iniciativa
se marcó un periodo para llevar a cabo el diseño de dichos Technical
Framework, pero debido al “éxito” obtenido, y la ampliación actual en los escenarios y
dominios (Radiología, Medicina Nuclear, IT, Laboratorio, Cardiología) y futura (Farmacia,
Anatomía Patológica, etc) alguno de ellos liderados desde IHE España.
Existe otro documento “Guía para los compradores”, cuya intención es la de ofrecer
información a los gestores de IT, gestores de hospital y de empresas de salud en la forma
de influir con la filosofía de IHE a la hora de adquirir sistemas de información y
modalidades diagnósticas. Describe las características de integración disponibles por IHE
con énfasis en como trata los retos reales con los que se enfrentan los profesionales
cada día.
Los perfiles de integración ofrecen un lenguaje común para los profesionales sanitarios y
los vendedores de cómo comunicar conformidad IHE. Ellos proveen una forma adecuada
para ambas partes para referir las funcionalidades detalladas en los IHE Technical
Framework. Permite a ambos ser más específicos que simplemente pidiendo o
prometiendo una conformidad en general a IHE, sin tener que especificar todos los
detalles que conciernen a los actores y transacciones de IHE. De entre la terminología
utilizada en los Perfiles de Integración conviene destacar:
9
Gestión de Análisis Clínicos: Cornalvo
• Actor: Son sistemas de información o componentes de un sistema de
información que producen, gestionan y actúan sobre la información asociada a
actividades operativas de la empresa de salud. Cada uno de los actores reciben
un nombre específico que los identifica de forma no ambigua.
• Transacción: Son interacciones entre actores que se transfieren la información
requerida a través de la utilización de mensajes basados en estándares.
Los perfiles de integración IHE no son estados de conformidad a un estándar, ni tan
siquiera es un cuerpo de certificación. Los usuarios deben continuar solicitando a los
vendedores que provean un estado de conformidad a estándares relevantes, tales como
DICOM, HL7, LDAP, etc. De hecho la conformidad a un estándar es un prerrequisito para
que las compañías adopten los perfiles de integración IHE. Con la adopción de los
perfiles de integración IHE, sin embargo, los vendedores dan un paso más asegurando la
conformidad a estándares, implementando los estándares de acuerdo al Technical
Framework (Marco Tecnico) de IHE. El proyecto de implementar estándares se prueba
en demostraciones públicas (Conect-a-thon), con resultados que se hacen públicos por
una técnico independiente, de tal forma que a los usuarios y gestores se nos
proporciona una certificación externa del cumplimiento de los requisitos del sistema de
información a adquirir , aunque obviamente la integración exitosa de los sistemas
requiere planes de proyecto que minimicen rupturas, que tenga estrategias de
recuperación de fallos, que cumpla expectativas mutuas, requerimientos de usuarios,
etc. Las soluciones de integración basadas en estándares son más flexibles, duraderas y
menos caras de mantener que los métodos propietarios.
10
Gestión de Análisis Clínicos: Cornalvo
Subcapítulo1.4: IHE en Europa
Los mercados europeo e internacional demandan globalmente soluciones competitivas
para integrar los sistemas de información en la sanidad (cuidados médicos e imagen
medica). La Iniciativa IHE ha provisto de dicha plataforma en EEUU para desarrollar
dichas demandas. El mercado europeo de los Sistemas de Información está fragmentado.
Prevalecen las soluciones para cada mercado nacional particular. Esto puede situar a los
fabricantes europeos de soluciones de Sistemas de Información Sanitaria en desventaja
en el mercado global. La iniciativa IHE en Europa dotará a los fabricantes europeos de
Sistemas de Información Sanitaria, incluyendo las de imagen medica, de una plataforma
para desarrollar y comprobar soluciones de interoperabilidad.
En un esfuerzo común la COCIR y la EAR, han tomado la iniciativa de promover el
concepto de IHE-Europa. El concepto de IHE-E se presentó en el congreso de la ECR ,
y encontró interés y apoyo entre los usuarios y fabricantes.
11
Gestión de Análisis Clínicos: Cornalvo
Un grupo IHE-Europa requiere una aproximación coordinada y focalizada, para asegurar
que todas las actividades siguen los mismos principios. Mientras la COCIR y la EAR están
interesados en establecer un Framework europeo para la integración de las aplicaciones
de Sistemas de Información Sanitaria, en Francia, la SFR y la GMSIH han comenzado una
plataforma de integración, incluyendo una demostración en presentaciones de mercado
para promover el concepto.
La cooperación entre las iniciativas europeas y nacionales será crucial para el exito del
proceso. Todos los actores tienen por tanto que estar de acuerdo en la siguiente
estructura organizativa:
El comité europeo IHE (EIC) será el responsable de la selección de los perfiles IHE que
serán parte de las actividades de integración europeas. Mantendrán la relación con los
comités IHE de Estrategia/Planificación/Técnico de los EEUU e influirán en la evolución
del IHE Technical Framework para asegurar la continuidad y consistencia en Europa.
Pertenecen a este grupo empresas y organizaciones profesionales de nivel nacional
europeo.
El EIC será responsable del Connectathon (un test anual de integración) y supervisará la
adhesión de los participantes al Technical Framework. Esto incluye el desarrollo o
reutilización de las herramientas de test necesaria y de la ayuda de verificaciones.
La participación en el Connectathon será abierta a todos los participantes interesados,
independientemente de si intentan participar en una demostración IHE nacional o
europea.
En cada país se formará un “National IHE Committee” (NIC), que será responsable de la
demostración de los resultados de integración en su país y la selección del campo de
esta demostración basados en la definición del EIC. Dicho comite nacional será tambien
responsable de atraer a empresas nacionales relevantes a dicho proceso. El NIC
cooperará con el EIC en albergar el Connectathon.
Actualmente participan en IHE Europa los NIC de Francia, Alemania, Reino Unido e
Italia, España, Países Bajos, Noruega y Dinamarca [1].
12
Gestión de Análisis Clínicos: Cornalvo
Capítulo2 : Guía implementación IHE-HL7
La integración entre las distintas aplicaciones informáticas de los Servicios de Salud esta
definida en IHE a varios niveles:
• Definición de perfiles en cada ámbito.
• Definición de los actores (aplicaciones en el caso de laboratorio) que intervienen en cada
parcela sanitaria.
• Definición de las transacciones entre los distintos actores y el orden en que estas se producen,
indicando casuísticas concretas
Y finalmente, utilizando el estándar HL7, especifica los mensajes utilizados en cada
transacción, su estructura y contenido, definiendo en este último punto, los datos que debemos
obligatoriamente enviar, los datos que pueden ser enviados y como deben ser enviados.
• El Servicio Extremeño de Salud (en adelante SES) ha decidido adoptar IHE y HL7 para la
conexión lógica de sus Sistemas de Información con la finalidad de disponer de una
información de sus pacientes bien identificada y por lo tanto fiable, integrada, disponible y
accesible de acuerdo con la ley y unas necesidades previamente definidas.
• El objetivo final del SES es mejorar la atención a los pacientes, simplificando la parte de
trabajo administrativa del personal sanitario y proporcionándoles toda la información
necesaria disponible referente a ese paciente.
• Dentro de este marco de trabajo se encuentra Cornalvo, Proyecto sobre el que trata este
documento. El objeto del mismo es establecer un marco general para la comunicación de los
resultados clínicos de laboratorio entre los sistemas de información de laboratorio origen de
los datos (SIL) hasta el sistema de registro y seguimiento de dichos resultados (ORT), y este
marco está englobado en:
• El perfil LSWF (Flujo de Trabajo Programado de Laboratorio).
• Las aplicaciones que intervienen en la parcela a la que se refiere este documento son :
ORT - Acumulador de resultados
OF -Aplicación del laboratorio en concreto que realiza y valida las pruebas
13
Gestión de Análisis Clínicos: Cornalvo
• La transacción concreta a la que se hace referencia en este documento es la LAB-3
• Los mensajes son el OUL^R22 y OUL^R24, cuyo contenido se especifica en este
documento.
• Hemos de tener en cuenta también que los OF de los de los distintos laboratorios deben ser
capaces de recibir los mensajes ADT referentes al alta ,actualización y fusión de los datos
demográficos del paciente de las transacciones RAD-11y RAD-122.
• Además en un futuro próximo se abordarán dentro de mismo perfil las transacciones LAB-1
y LAB-2 de gestión de peticiones, en estas transacciones intervendrán las aplicaciones JARA
(Historia Clínica Única) y el OF.
1 La transacción RAD-1 se denomina “Patient Registration”, o “Registro de Paciente”. Es la utilizada para facilitar el registro o la admisión de un nuevo paciente comunicándolo a todos los sistemas de información.
2 La transacción RAD-12 se denomina “Patient Update”, o “Actualización de Paciente”. Es la transacción utilizada en la actualización de los datos demográficos de los pacientes en los sistemas de información.
14
Gestión de Análisis Clínicos: Cornalvo
Subcapítulo 2.1: Visión general
En el contexto de los sistemas de información del servicio extremeño de salud, se presenta a
continuación una visión general de los sistemas de información que actualmente están
desarrollándose y la correspondencia de los actores antes enunciados con los sistemas reales.
En primer lugar, la información demográfica de los pacientes se suministrará desde el sistema
de información poblacional de la consejería de Extremadura (“CIVITAS”). Es el origen y
responsable de la información demográfica del paciente. La información demográfica se
comunicará en una primera fase a JARA desde CIVITAS. Este sistema es responsable de parte de
las funciones del ADT.
En segundo lugar, el sistema de información del proyecto JARA reunirá las funciones de
estación clínica responsables de mantener la historia clínica del paciente y hacer el seguimiento del
servicio asistencial. Por ello, tanto el sistema de información CORNALVO como los SIL recibirán
información demográfica de pacientes desde JARA. Este sistema realiza las funciones de ADT en
colaboración con CIVITAS para todos los sistemas dependientes del SES. JARA es un sistema
centralizado que constituye el núcleo de los sistemas de información sanitarios.
El proyecto CORNALVO asumirá la gestión de peticiones que relacionará JARA con el OF de
los laboratorios.
Por último, los SIL son los sistemas de información, situados en cada servicio o departamento
de laboratorio clínico, responsables de realizar las pruebas solicitadas y devolver los resultados a su
peticionario. Desempeña las funciones de los actores OF y AM en conjunto y tal como se ha
definido la arquitectura del sistema en el SES. Debido a la multitud de servicios de laboratorio
diferentes y a la variedad de proveedores que dan servicio a dichos laboratorios, representa el
conjunto de sistemas de información más numeroso y heterogéneo. Existe al menos un SIL
diferente para cada laboratorio.
A continuación se muestra un esquema de lo dicho anteriormente:
15
Gestión de Análisis Clínicos: Cornalvo
Subcapítulo 2.2: Sistema de Información de Laboratorio (SIL)
Constituyen los Sistemas de Información departamentales que dan servicio a cada uno de los
departamentos de laboratorio clínico existentes en la red asistencial del SES. En el momento actual
hay un gran número de sistemas de información independientes sin ningún tipo de integración entre
ellos y con un alto grado de heterogeneidad en los sistemas de información y en los modos y pautas
de trabajo (codificación de resultados, órdenes, servicios, facultativos, etc.).
Capítulo3 : Material y métodoIHE define tres casos de uso que principalmente se diferencian entre si en función de que actor
identifica el espécimen. Los resumimos e ilustramos a continuación.
16
Ilustración 2: Esquema general de arquitectura basada en IHE
SILSIL
JARA
CORNALVO SIL
CIVITAS
ADT
Gestión Peticiones
Resultados
Inf. Demográfica
Inf. Demográfica
Inf. Demográfica
OP y ORT
OF y AM
Gestión de Análisis Clínicos: Cornalvo
Subcapítulo 3.1: Orden externa con el espécimen identificado
El medico con la aplicación de Order Placer hace una petición de pruebas y determina que
espécimenes son requeridos para llevar a cabo los test ( tipo de contenedores,tiempo, estado del
paciente,etc.) mediante unas normas previamente establecidas con los laboratorios.
El “Order Placer” proporciona la identificación del espécimen, que podría contener un
espécimen ID(único para toda la vida del espécimen), el “Placer Order ID” , CIP del paciente y
puede identificar la batería de relativas a estos espécimenes.
El centro de extracciones realiza la extracción, identifica el espécimen con la etiqueta que le
corresponde y lo envía al laboratorio(“Order Filler”) a cuyo sistema el “Order Placer” ha dirigido
la orden.
El OF rechaza o acepta la orden introduciendo modificaciones a la misma si fuera necesario, de
todo esto será informado el “Order Placer”.
Si un espécimen resulta dañado o perdido el “Order Filler” se lo comunica al “Order Placer” y
le solicita otros.
El “Order Filler” le da las ordenes oportunas al Gestor de Automatización quien le devolverá
los resultados.
Finalmente el OF enviará los resultados validados clínicamente al “Order Result Tracker”.
17
Ilustración 3: Caso de uso 1
Gestión de Análisis Clínicos: Cornalvo
Subcapítulo 3.2: Órdenes externas con espécimenes sin identificar o recogidos por
el laboratorio.
El “Order Placer” no identifica el espécimen. Puede ocurrir que:
La unidad de extracción etiqueta el espécimen con una información mínima que contendrá el
CIP del paciente y la identificación del “Order Placer”. Posteriormente el espécimen será
identificado de nuevo por el laboratorio.
También contempla el caso en el que el laboratorio se encargue tanto de la extracción como de
la identificación del espécimen.
La unidad de extracción se encarga de la obtención del espécimen y lo identifica con etiquetas
creadas por el “Order Filler”.
Subcapítulo 3.3: Ordenes con espécimenes identificados por terceras partes o
recogidos por el laboratorio.
Recoge dos subcasos de uso:
18
Ilustración 4: Caso de uso 2
Gestión de Análisis Clínicos: Cornalvo
El laboratorio recibe la orden en papel por la imposibilidad por parte del medico peticionario de
acceder a la aplicación Order Placer.
Durante el procesado de la order u ordenes, desde el laboratorio se deciden añadir nuevas
pruebas, que se realizará sobre alguno de los espécimenes existentes.
En ambos casos el laboratorio introducirá la orden en la aplicación “Order Filler” enviando en
“Filler Order Number” al “Order Placer” y le será comunicado al medico que la dará de alta en la
aplicación “Order Placer”, enviando el “Placer Order Number” al “Order Filler” .
19
Ilustración 5: Caso de uso 3
Gestión de Análisis Clínicos: Cornalvo
Subcapítulo 3.4: Perfil IHE del Flujo de Trabajo Programado de Laboratorio (LSWF)
A continuación se muestra un gráfico a modo de esquema con los actores que intervienen en el
LSWF y las transacciones que ocurren entre ellos. Se denota al sistema de información del
laboratorio como la unión de los roles de “Order Filler” y “Automation Manager”, mientras que el
resto de sistemas de la organización asumen los papeles de “Admission, Discharge and Transfer”,
“Order Placer” y “Order Result Tracker”. En la primera fase del proyecto la comunicación entre el
sistema de información de la organización (SES) y el SIL se limita a las transacciones RAD-1,
RAD-12 y LAB-3. Implementando estas transacciones se asegura la recepción de los resultados en
el “Order Result Tracker”, pero no se tiene la gestión de las peticiones de pruebas de las que se
ocupan las transacciones LAB-1 y LAB-2. La gestión de las peticiones de pruebas se pospone para
una segunda fase del desarrollo del proyecto.
20
Ilustración 6: Relación de actores y las transacciones entre ellos
Gestión de Análisis Clínicos: Cornalvo
Subcapítulo 3.5: Actores
Desde el punto de vista de la organización, los actores que intervienen en la gestión de las
pruebas clínicas de laboratorio se dividen en dos grandes grupos:
1. Peticionarios de pruebas. Estos son los centros de salud y consultorios de atención primaria,
junto con los departamentos hospitalarios de atención especializada desde los que se prescriben
la realización de pruebas clínicas de laboratorio sobre una muestras obtenidas de los pacientes
dentro del proceso asistencial de salud. La prueba la ordena el centro y es prescrita por el
facultativo que trata al paciente.
2. Servicios de laboratorios clínicos, internos o externos a la organización. En lineas generales, y
simplificando mucho, reciben las peticiones de las pruebas y las muestras, realizan los procesos
analíticos correspondientes y obtienen un resultado que devuelven al facultativo que prescribe la
prueba. Dependiendo del flujo de trabajo de cada organización los laboratorios pueden
encargarse o no de la extracción de la muestra de los pacientes. Incluido en el proceso de la
obtención de los resultados se encuentran dos controles de calidad: la validación técnica del
análisis y la validación clínica de la prueba. Lo habitual es devolver los resultados de las pruebas
después de que han sido validados clínicamente y no antes, aunque esto depende de las normas
de trabajo de la organización y también de la situación en la que se produce la petición como
también de la prueba solicitada (pe., una petición de urgencia).
Desde el punto de vista de sistemas de información, la propuesta IHE define y diferencia
claramente varios roles independientes que pueden asumir las unidades organizativas y los sistemas
de información que dependen de ellas:
1. “Order Placer” (OP). Es el sistema que permite la solicitud de una prueba clínica y su
seguimiento. Es el sistema de información utilizado directamente por el personal facultativo de
la organización de salud.
2. “Order Filler” (OF). Es el sistema de información responsable de la realización de las pruebas
clínicas de laboratorio y su gestión dentro del servicio de laboratorio. Acepta las peticiones de
pruebas del “Order Placer”, manteniéndolo al tanto del estado en el que se encuentran las
pruebas y también envía los resultados de las pruebas al “Order Result Tracker”. Este sistema lo
utilizan los especialistas y técnicos del servicio de laboratorio para realizar su labor.
21
Gestión de Análisis Clínicos: Cornalvo
3. “Order Result Tracker” (ORT). Es el sistema encargado de reunir la información de los
resultados de las pruebas analíticas de los laboratorios, actuando como un repositorio central de
resultados de pruebas. Se alimenta con la información que le envía el “Order Filler”. Permite
mantener un historial de pruebas clínicas por pacientes y debe ser accesible al personal
facultativo de la organización.
4. “Automation Manager” (AM). Es el sistema que controla todo el equipamiento de análisis
clínico automatizado (autoanalizadores, aliquotadores, etc.). Actúa bajo la supervisión y las
órdenes del Order Filler coordinando las tareas analíticas de los instrumentos de laboratorio.
5. “Admission Discharge and Transfer” (ADT). Sistema encargado de la gestión de la
información demográfica, la admisión, el alta y el traslado de los pacientes. Sigue la situación
del paciente dentro de la organización y es el responsable de informar al resto de sistemas de
dicha situación.
22
Gestión de Análisis Clínicos: Cornalvo
Subcapítulo 3.6: Transacciones
Las transacciones introducidas por el perfil LSWF son las siguientes:
• LAB-1. Gestión de la orden del peticionario (“Order Placer”). Esta transacción contiene todos
los mensajes necesarios entre el “Order Placer” y el “Order Filler” para la gestión del ciclo de
vida de la orden. Su objetivo principal es mantener una visión consistente de la orden
(contenido y estado) entre los dos actores.
• LAB-2. Gestión de la Orden del “Order Filler”. Esta transacción contiene todos los mensajes
necesarios entre el “Order Filler” y el “Order Placer” para la notificación de una nueva orden en
el “Order Filler”, así como la creación de la orden en el “Order Placer” que lo refleja. Su
cometido principal es asegurar que cada orden del “Order Filler” está representada por una
orden del “Order Placer”, y que ambas tendrán un número de orden del “Order Filler” y un
número de orden del “Order Placer”.
• LAB-3. Gestión de resultados de la orden. Esta transacción lleva los cambios de los resultados
de las observaciones y el estado de las órdenes desde el “Order Filler” hasta el “Order Result
Tracker”. Pe. correcciones, cancelaciones.
• LAB-4. Gestión de las órdenes de trabajo. Esta transacción contiene todos los mensajes
necesarios entre el “Order Filler” y el Gestor de Automatización para la ejecución de una orden
de trabajo conteniendo un subconjunto de test de la orden del “Order Filler”. La meta principal
de esta transacción es distribuir el trabajo al Gestor de Automatización, y mantener a este actor
informado de todas las actualizaciones del paciente y la orden. Esta transacción se basará en un
mecanismo “push”, el mecanismo de consulta nunca se utilizará en esta transacción.
• LAB-5. Gestión del resultado de los test. Esta transacción lleva los test técnicamente validados
desde el gestor de automatización hacia el “Order Filler”.
Además de estas cinco nuevas transacciones, el perfil LSWF adopta dos transacciones de la
parte de radiología: RAD-1 y RAD-12.
• RAD-1. Registro de paciente. El Sistema ADT registra y/o admite a un paciente, enviando la
información a otros sistemas de información.
• RAD-12. Actualización de Paciente. El sistema ADT informa al “Order Placer” y al “Order
Filler” de nueva información para un paciente particular. El “Order Filler” puede a su vez
informar al Gestor de Automatización.
23
Gestión de Análisis Clínicos: Cornalvo
Capítulo 4 : Estados de una pruebaEn la versión 2.5 del estándar HL7 un cambio en el estado de una observación se identifica por
una combinación del campo del evento en el segmento MSH, el campo ORC-5 (Estado de la orden
del “Order Filler”), el OBR-25 (Estado del resultado de la Orden) y el campo OBX-11 (Estado del
resultado de la observación). El campo OBX-11 contiene el estado de un test individual, el campo
OBR-25 el estado de la petición completa. No puede haber incosistencia en estos estados.
Debido a que en la primera fase del proyecto solamente se atiende a resultados ya terminados y
verificados clínicamente, en la práctica se utilizan las tres últimas combinaciones de valores que
reflejan los últimos estados de las peticiones de pruebas (destacados en negrita y subrayados). Es
decir, que los mensajes solamente contendrán resultados terminados y verificados, correcciones a
los resultados finales o bien cancelaciones de órdenes.
El ORT debe admitir todas las combinaciones de los campos anteriores que muestra la tabla
siguiente.
Orden
Tabla 0038
(ORC-5)
Petición
Tabla 0123
(OBR-25)
Resultado
Tabla 0085
(OBX-11)
Descripción
O O Orden recibida; El espécimen aun no se recibió. Solamente descripción detallada de
la orden (OBX no tiene resultado).
Este valor solo puede usarse en los mensajes de respuesta de los eventos ORL. No
debe usarse en los mensajes OML.
SC S No hay resultados disponibles; procedimiento programado, pero no hecho. El
espécimen pudo no haber llegado al laboratorio. No hay OBX.
IP I I En proceso; El espécimen está disponible en el laboratorio; los resultados están
pendientes; el procedimiento está incompleto.
D Borra el registro OBX.
A R R (Algunos) resultados introducidos – aun no verificados
A P P (Algunos) resultados preliminares verificados; técnicamente validados en LAB-5,
clínicamente validados en LAB-3. Los resultados finales aun no se obtuvieron.
CM F F Resultados terminados y verificados. Solo pueden ser cambiados por resultados correctos
(CM) C C Reemplaza un resultado final por una corrección.
CA X X El resultado del test no puede ser obtenido para esta Orden/Batería , por lo tanto, Orden cancelada
Tabla 1: Estados por los que pasa la orden desde el momento que es procesada por el Order Filler hasta que finalmente se completa o cancela la orden.
24
Gestión de Análisis Clínicos: Cornalvo
Capítulo 5 : Transacción LAB-3Partiendo de la base establecida en el perfil IHE LSWF, se definen dos perfiles de mensajes
para utilizar en la transmisión de los resultados clínicos de laboratorio. Estos mensajes se
corresponden a los utilizados en la transacción LAB-3 del perfil LSWF.
• Mensaje OUL^R22
• Mensaje OUL^R24
Esta implementación se basa en los segmentos definidos en el perfil IHE LSWF, pero en esta
primera fase no se utilizan los segmentos PVI y TQ1, y se ignoran si aparecen en algún mensaje.
En ambos mensajes el orden en el cual aparecen los segmentos OBX define el orden para la
presentación de los resultados para una batería o espécimen dado. En cuanto a esto, el “Order
Filler” debe transmitir todos los resultados disponibles para la batería o el espécimen en modo de
recapitulación, fuesen transmitidos o no.
Como IHE no contempla la posibilidad explícita de utilizar segmentos NTE para introducir
anotaciones o comentarios a las observaciones asociadas a un espécimen, se adopta la convención
de representar un comentario como el último valor de la observación si éste es de tipo texto y si hay
más de un segmento de observación (OBX) para un test.
Aunque no está contemplado en la propuesta IHE, el ORT admite comentarios también sobre
las propias peticiones de pruebas (OBR/ORC) utilizando uno o más segmentos NTE para tal efecto.
Si se proporcionan los segmentos NTE a continuación de los segmentos OBR/ORC, se registrarán
en el repositorio como comentarios a las órdenes de prueba.
Subcapítulo 5.1: Mensaje OUL^R22
La estructura del mensaje OUL^R22 debe utilizarse para todas las órdenes para las cuales cada
batería solicitada requiere un único espécimen.
25
Gestión de Análisis Clínicos: Cornalvo
OUL^R22^OUL_R22 Mensaje orientado al espécimen Uso Card. SubcapítuloMSH Cabecera del mensaje R [1..1] 2 [ --- Comienzo de PACIENTE [1..1] PID Identificación de paciente R [1..1] 3 [PV1] Visita del paciente X [0..0] 3 ] --- fin de PACIENTE { --- comienzo de ESPECIMEN R [1..*] SPM Información de espécimen R [1..1] 7 [{ OBX }] Resultado de observación (para espécimen) O [0..*] 7 { --- Comienzo de la ORDEN R [1..1] OBR Orden de Observación R [1..1] 7 [ORC] Orden Común R [1..1] 4 [{TQ1}] Tiempo/Cantidad RE [0..1] 4 [{NTE}] Notas y comentarios O [0..*] 2 [{ --- comienzo de RESULTADO O [0..*] OBX Resultado de Observación R [1..1] 7 [{NTE}] Notas y comentarios C [0..*] 2 }] --- fin de RESULTADO } --- fin de ORDEN } --- fin de ESPECIMEN
Tabla 2: Mensaje OUL^R22
Subcapítulo 5.2: Mensaje OUL^R24
La estructura de mensaje OUL^R24 debe utilizarse cuando una batería solicitada requiere
múltiples espécimenes (pe. test de tolerancia a la glucosa, etc.)
OUL^R24^OUL_R24 Mensaje Orientado a la Observación Uso Card. SubcapítuloMSH Cabecera de mensaje R [1..1] 2 [ --- comienzo de PACIENTE [1..1] PID Indentificación de paciente R [1..1] 3 [PV1] Visita paciente X [0..0] 3 ] --- fin de PACIENTE { --- comienzo de ORDEN R [1..*] OBR Orden de observación R [1..1] 7 [ORC] Orden común R [1..1] 4 [{TQ1}] Tiempo / cantidad Secuencia de la orden X [0..0] 4 [{NTE}] Notas y comentarios O [0..*] 2 [{ --- comienzo de ESPECIMEN O [0..*] SPM Información del espécimen R [1..1] 7 [{OBX}] Resultado de observación O [0..*] 7 }] --- fin de ESPECIMEN [{ --- comienzo de RESULTADO R [1..*] OBX resultado de observación R [1..1] 7 [{NTE}] Notas y comentarios C [0..*] 2 }] --- fin de RESULTADO } --- fin de ORDEN
Tabla 3: Mensaje OUL^R24
26
Gestión de Análisis Clínicos: Cornalvo
Subcapítulo 5.3: Mensaje ACK
El mensaje ACK se debe utilizar para responder a los mensajes OUL^R22 y OUL^R24,
indicando el resultado del procesamiento del mensaje.
ACK^R22^ACK/ACK^R24^ACK Descripción Uso Card.MSH Cabecera de mensaje R [1..1]MSA Respuesta R [1..1][{ERR}] Error C [0..1]
Tabla 4: Mensaje ACK
27
Gestión de Análisis Clínicos: Cornalvo
Capítulo 6 : SegmentosA continuación se detallan las especificaciones de la información requerida para los segmentos
utilizados en ambos mensajes ORL^R22 y ORL^R24.
Solamente se hace una descripción detallada de aquellos atributos que se utilizan en esta
implementación, obviando los que no se utilizan (ver documentación de IHE y estándar HL7 para
más información).
A continuación se explica la leyenda de las tablas empleadas en la descripción de los segmentos
y los atributos de los segmentos:
Tablas de atributos:
• Columna Sec. (Secuencia): Es un número que indica la posición del atributos en el segmento. El
primer atributo del segmento tiene posición 1.
• Columna Long. (Longitud): Es un número que indica la longitud máxima del atributo.
• Columna Tipo: Es un identificador del tipo de datos HL7 asignado al atributo. Los tipos de datos
utilizados en HL7 se describen en el apéndice A del capítulo 2 del estándard.
• Columna Card. (Cardinalidad): Es un intervalo que muestra el número de ocurrencias mínimo y
el máximo permitidos para el atributo. Si el primer valor es mayor que 0 se denota la
obligatoriedad del atributo. Por lo general, se utilizan los siguientes valores:
• [0..0] cuando no se utilice el campo,
• [1..1] cuando sea obligatoria una única ocurrencia del atributo,
• [0..1] cuando el atributo pueda tener opcionalmente 0 o 1 ocurrencias,
• [0..*] cuando el atributo es opcional y puede tener cualquier número de ocurrencias y
• [1..*] cuando el atributo es obligatorio y puede tener cualquier número de ocurrencias.
• La columna Tabla: Es un número que hace referencia a la tabla que figura en el estándar HL7.
Las tablas pueden ser de dos tipos: HL7, cuyos valores son normativos, y usuario, que pueden
definirse según la implementación del sitio.
• La columna Ítem HL7: Es un número referencia del atributo en la documentación del estándar
HL7.
• La columna Nombre Elemento: Es una frase que da nombre al atributo.
Tablas de Valores HL7:
• Columna Valor: Contiene el valor definido para el atributo. Puede ser de cualquier tipo definido
en el estándar. Suele ser un número o una cadena de caracteres ASCII.
28
Gestión de Análisis Clínicos: Cornalvo
• Columna Descripción: Es un enunciado describiendo el significado del valor para el atributo.
• Columna Comentarios: Contiene un párrafo con anotaciones de interés en la implementación
para dicho valor.
Subcapítulo 6.1: Segmento MSH
Este segmento define el propósito, el origen, el destino y algunos aspectos específicos a la
sintaxis de un mensaje.
Sec. Long. Tipo Uso Card. Tabla Ítem HL7 Nombre elemento1 1 ST R [1..1] 00001 Separador de campos2 4 ST R [1..1] 00002 Caracteres de codificación3 227 HD R [1..1] 0361 00003 Aplicación emisora4 227 HD R [1..1] 0362 00004 Centro emisor5 227 HD R [1..1] 0361 00005 Aplicación receptora6 227 HD R [1..1] 0362 00006 Centro receptor7 26 TS R [1..1] 00007 Fecha/Hora del mensaje8 40 ST X [0..0] 00008 Seguridad9 15 MSG R [1..1] 00009 Tipo de mensaje10 20 ST R [1..1] 00010 Identificador de Control de Mensaje11 3 PT R [1..1] 00011 Identificador de Procesamiento12 60 VID R [1..1] 00012 Identificador de versión13 15 NM X [0..0] 00013 Número de secuencia14 180 ST X [0..0] 00014 Puntero de continuación15 2 ID X [0..0] 0155 00015 Tipo de confirmación de Transporte16 2 ID X [0..0] 0155 00016 Tipo de confirmación de Aplicación17 3 ID RE [0..1] 0399 00017 Código de país18 16 ID X [0..1] 0211 00692 Conjunto de caracteres19 250 CE X [0..1] 00693 Lenguaje principal del mensaje20 20 ID X [0..0] 0356 01317 Esquema de manejo de conjunto alternativo de caracteres21 427 EI X [0..1] 01598 Identificador del perfil del mensaje
Tabla 5: Tabla HL7 de Atributos - MSH – Cabecera de mensaje
29
Gestión de Análisis Clínicos: Cornalvo
MSH-1 SEPARADOR DE CAMPOS
El marco de trabajo técnico de Laboratorio IHE requiere que las aplicaciones soporten el valor
recomendado por HL7 que es | (ASCII 124).
MSH-2 CARACTERES DE CODIFICACIÓN
Este campo contiene los cuatro caracteres en el orden siguiente: el separador de componentes,
el separador de repeticiones, el carácter de escape y el separador de subcomponentes. El marco de
trabajo técnico de laboratorio requiere que las aplicaciones soporten los valores recomendados por
HL7 ^~\& (ASCII 94, 126, 92, y 38, respectivamente).
MSH-3 APLICACIÓN EMISORA
Componentes: <Namespace ID (IS)> ^ <Universal ID (ST)> ^ <Universal ID Type (ID)>
El marco de trabajo técnico IHE de laboratorio requiere que este campo se rellene con:
Primer componente (requerido): Identificador del espacio de nombres. El nombre de la
aplicación emisora.
El segundo y tercer componente son opcionales en el marco de trabajo técnico IHE y no se
utilizan en este caso.
Tabla definida por el Usuario 0361 –Aplicaciones3
Valor Descripción Comentario
ORTCORNALVO Repositorio de resultados clínicos de laboratorio.
3 Se propone como ejemplo el valor asignado por el SES a la aplicación “Order Result Tracker” del proyecto CORNALVO. Cada empresa proveedora de un SIL propondrá en acuerdo con el SES el identificador que empleará para su aplicación.
30
Gestión de Análisis Clínicos: Cornalvo
MSH-4 CENTRO EMISOR
Componentes: <Namespace ID (IS)> ^ <Universal ID (ST)> ^ <Universal ID Type (ID)>
El marco técnico IHE de laboratorio requiere que este campo se rellene con:
Primer componente (requerido): Identificador del espacio de nombres. El nombre de la entidad
de organización responsable de la aplicación emisora.
El segundo y tercer componente es opcional en el marco de trabajo técnico IHE y no se utiliza
en este caso.
La codificación de las entidades se define localmente por el sitio en la tabla de usuario 0362.
Tabla definida por el usuario 0362 – Instalaciones4
Valor Descripción Commentario
4 Se propone como ejemplo el valor asignado por el SES a los servicios centrales para el proyecto CORNALVO. También se incluyen los valores provisionales de la codificación de todos los centros.
31
Gestión de Análisis Clínicos: Cornalvo
MSH-5 APLICACIÓN RECEPTORA
Componentes: <Namespace ID (IS)> ^ <Universal ID (ST)> ^ <Universal ID Type (ID)>
El marco técnico IHE de laboratorio requiere que este campo se rellene con:
Primer componente (requerido): Identificador del espacio de nombres. El nombre de la
aplicación receptora.
El segundo y tercer componente son opcionales en el marco de trabajo técnico IHE y no se
utilizan en este caso.
La codificación de las aplicaciones se define localmente por el sitio en la tabla de usuario 0361.
MSH-6 CENTRO RECEPTOR
Componentes: <Namespace ID (IS)> ^ <Universal ID (ST)> ^ <Universal ID Type (ID)>
El marco técnico IHE de laboratorio requiere que este campo se rellene con:
Primer componente (requerido): Identificador del espacio de nombres. El nombre de la entidad
de organización responsable de la aplicación emisora.
El segundo y tercer componente es opcional en el marco de trabajo técnico IHE y no se utiliza
en este caso.
La codificación de las entidades se define localmente por el sitio en la tabla de usuario 0362.
MSH-7 FECHA/HORA DEL MENSAJE
Componentes: <Time (DTM)> ^ <DEPRECATED-Degree of Precision (ID)>
Este campo contiene la fecha y la hora en el que el sistema emisor creó el mensaje. El formato
completo para el valor del primer componente es YYYY[MM[DD[HH[MM[SS[.S[S[S[S]]]]]]]]]
[+/-ZZZZ]. En este caso se requiere la parte YYYYMMDDHHMMSS. El resto es opcional.
El segundo componente no se utiliza.
MSH-9 TIPO DE MENSAJE
Componentes: <Message Code (ID)> ^ <Trigger Event (ID)> ^ <Message Structure (ID)>
Este campo contiene el tipo de mensaje, el evento disparador y la identificación de la estructura
para el mensaje. Los tres componentes son obligatorios.
En este caso, se utilizan los valores siguientes para los tipos de mensajes utilizados en esta
integración:
• Mensaje OUL^R22: OUL^R22^OUL_R22, mensaje de respuesta : ACK^R22^ACK.
• Mensaje OUL^R24: OUL^R24^OUL_R24, mensaje de respuesta : ACK^R24^ACK.
32
Gestión de Análisis Clínicos: Cornalvo
• Mensaje ADT^A04: ADT^A04^ADT_A01, mensaje de respuesta : ACK^A04^ACK.
• Mensaje ADT^A08: ADT^A08^ADT_A01, mensaje de respuesta : ACK^A08^ACK.
• Mensaje ADT^A40: ADT^A40^ADT_A39, mensaje de respuesta : ACK^A40^ACK.
MSH-10 IDENTIFICADOR DE CONTROL DEL MENSAJE
• Este campo contiene un número u otro identificador que identifica unívocamente el mensaje. El
sistema emisor debe asignar un identificador único a cada mensaje. El sistema receptor
devolverá este identificador de vuelta en el segmento de confirmación del mensaje (MSA). La
combinación de este identificador y el nombre de la aplicación emisora (MSH-3) debe ser única
para todo el sistema de la organización (en este caso, el SES).
• La única restricción es la generación de identificadores únicos, sean numéricos o no. En el
apéndice C de la guía de implementación HL7 se describe el protocolo para la utilización de
números en secuencia.
MSH-11 IDENTIFICADOR DE PROCESAMIENTO
• Componentes: <Processing ID (ID)> ^ <Processing Mode (ID)>.
• Este campo se usa para decidir si se procesa el mensaje como se define en las reglas de
procesado del nivel de aplicación HL7. En su uso normal solamente se utiliza el primer
componente, cuyos valores posibles se muestran en la tabla HL7 0103. Para operaciones
especiales, como cargas iniciales de datos, restauraciones de copias de seguridad, etc. puede
utilizarse el segundo componente.
• La implementación actual del ORT solo utiliza el primer componente y supone siempre el modo
de operación por defecto para el segundo.
Valor Descripción Comentario
D Depuración Utilizado para probar las aplicaciones
P Producción Utilizado en el entorno habitual de producción
T Formación Utilizado en entornos de formación de aplicaciones
Tabla 6: Tabla HL7 0103 – Identificador de procesamiento
33
Gestión de Análisis Clínicos: Cornalvo
• El valor que debe utilizarse para la operación normal de los sistemas será “P”. Durante cualquier
prueba de integración deberá de utilizarse el valor “D”. Para el caso de que hubiese un entorno
de formación de las aplicaciones, los mensajes transmitidos deberán emplear el valor “T” en este
campo. El ORT solamente procesará los mensajes que estén asignados a su entorno operativo.
MSH-12 IDENTIFICADOR DE VERSIÓN
• Componentes: <Version ID (ID)> ^ <Internationalisation Code (CE)> ^ <International Version
ID (CE)>.
• Este campo se empareja por el sistema receptor con su propia versión para estar seguro que el
mensaje será interpretado correctamente.
• El marco de trabajo técnico de IHE para Laboratorio exige que el primer componente del campo
se rellene con el valor 2.5 (correspondiente a la versión 2.5 del estándar HL7). El resto de
componentes son opcionales y no se utilizan en este caso.
Subcapítulo 6.2: Segmento MSA
• El segmento MSA contiene la información enviada acerca de la confirmación de otro mensaje.
e
Sec. Long. Tipo Uso Card. Tabla Item HL7 Nombre elemento1 2 ID R [1..1] 0008 00018 Código de acuse de recibo2 20 ST R [1..1] 00010 Identificador de control del mensaje3 80 ST X [0..0] 00020 Texto de mensaje 4 15 NM X [0..0] 00021 Número de secuencia esperado5 X [0..0] 00022 Tipo de reconocimiento6 250 CE X [0..0] 0357 00023 Condición de error
Tabla 7: Tabla HL7 de Atributos - MSA – Confirmación de Mensaj
34
Gestión de Análisis Clínicos: Cornalvo
MSA-1 CÓDIGO DE ACUSE DE RECIBO
• El código de acuse de recibo es un valor codificado que puede adoptar los valores mostrados en
la tabla HL7 0008. Los valores esperados en este caso se limitan al modo original de transmisión
de mensajes HL7:AA, AE y AR.
Valor Descripción Comentario
AA Modo original: Aceptación de aplicación
AE Modo original: Error de aplicación
AR Modo original: Rechazo
CA Modo mejorado: Acuse de recibo de aceptación: Aceptación de confirmación
CE Modo mejorado: Acuse de recibo de aceptación: Error de confirmación
CR Modo mejorado: Acuse de recibo de aceptación: Rechazo de confirmación
Tabla 8: Tabla HL7 0008 - Código de confirmación
35
Gestión de Análisis Clínicos: Cornalvo
MSA-2 IDENTIFICADOR DE CONTROL DEL MENSAJE
• El identificador de control del mensaje identifica el mensaje al que da respuesta el ACK y
coincide con el valor del campo MSH-10 del mensaje original.
Subcapítulo 6.3: Segmento ERR
El ORT solamente considera los errores estándares HL7 codificados en el campo ERR-3.
Cualquier otro campo se considera informativo y no se procesa.
Sec. Long. Tipo Uso Card. Tabla Ítem HL7 Nombre elemento1 493 ELD X [0..0] 00024 Código de error y localización2 18 ERL X [0..0] 01812 Localización del error3 705 CWE R [1..1] 0357 01813 Código de error HL74 2 ID R [1..1] 0516 01814 Severidad5 705 CWE X [0..0] 0533 01815 Código de error de aplicación6 80 ST X [0..0] 01816 Parámetro de error de aplicación7 2048 TX X [0..0] 01817 Información de diagnóstico8 250 TX X [0..0] 01818 Mensaje de usuario9 20 IS X [0..0] 0517 01819 Indicador de informar a persona10 705 CWE X [0..0] 0518 01820 Tipo de anulación11 705 CWE X [0..0] 0519 01821 Código de razón de anulación12 652 XTN X [0..0] 01822 Punto de contacto del “Help Des
Tabla 9: Tabla HL7 de Atributos de error - ERR
ERR-3 CÓDIGO DE ERROR HL7
• Componentes: <Identifier (ST)> ^ <Text (ST)> ^ <Name of Coding System (ID)> ^ <Alternate
Identifier (ST)> ^ <Alternate Text (ST)> ^ <Name of Alternate Coding System (ID)> ^ <Coding
System Version ID (ST)> ^ <Alternate Coding System Version ID (ST)> ^ <Original Text
(ST)>.
• En este campo se indica el código de error HL7. Los códigos admitidos se corresponden con la
tabla HL7 0357. Es obligatorio incluir los dos primeros componentes del campo, el código de
error y el texto descriptivo.
36
Gestión de Análisis Clínicos: Cornalvo
ERR-4 SEVERIDAD
• Identifica la severidad de un error de aplicación. El conocimiento que algo es un error, un aviso
o información es intrínseco a como la aplicación maneja el contenido. La tabla HL7 0516
contiene los valores válidos. Si ERR-3 tiene un valor de 0, el valor de ERR-4 debe ser “I”.
Código Descripción Comentario
W Advertencia Transacción con éxito, pero puede haber cuestiones que considerar
I Información Transacción con éxito pero incluye información. Ej. Imform. paciente
E Error Transacción sin éxito
Tabla 10: Tabla HL7 0516 – Severidad del error
37
Gestión de Análisis Clínicos: Cornalvo
Subcapítulo 6.4: Segmento PID
• El segmento PID se utiliza por todas las aplicaciones como la principal manera de comunicar
información de identificación de paciente. Este segmento contiene información de identificación
e información demográfica del paciente que, en la mayor parte de los casos, no suele cambiar
frecuentemente.
• El contenido exacto del segmento PID se debe ajustar a la guía de implementación de HL7
Spain publicada recientemente.
38
Gestión de Análisis Clínicos: Cornalvo
Sec. Long. Tipo Uso Card. Tabla Ítem HL7 Nombre elemento1 4 SI X [0..0] 00104 ID de Conjunto - PID2 20 CX X [0..0] 00105 ID Paciente3 250 CX R [1..8] 00106 Lista de ID de Paciente4 20 CX X [0..0] 00107 ID Alternativo de Paciente - PID5 250 XPN R [1..1] 00108 Nombre de Paciente6 250 XPN RE [0..1] 00109 Nombre de soltera de la madre7 26 TS RE [0..1] 00110 Fecha/Hora de Nacimiento8 1 IS R [1..1] 0001 00111 Sexo Administrativo9 250 XPN X [0..0] 00112 Alias del Paciente10 250 CE X [0..0] 0005 00113 Raza11 250 XAD RE [0..*] 00114 Dirección del Paciente12 4 IS X [0..0] 0289 00115 Código de Condado (Provincia)13 250 XTN RE [0..*] 00116 Número de Teléfono - Domicilio14 250 XTN X [0..0] 00117 Número de Teléfono - Negocio15 250 CE X [0..0] 0296 00118 Lenguaje Principal16 250 CE X [0..0] 0002 00119 Estado Marital17 250 CE X [0..0] 0006 00120 Religión18 250 CX X [0..0] 00121 Número de Cuenta del Paciente19 16 ST X [0..0] 00122 Número de la Seguridad Social - Paciente20 25 DLN X [0..0] 00123 Número del Permiso de Conducir - Paciente21 250 CX X [0..0] 00124 Identificador de la Madre22 250 CE X [0..0] 0189 00125 Grupo Étnico23 250 SE RE [0..1] 00126 Lugar de Nacimiento24 1 ID X [0..0] 0136 00127 Indicador de Parto Múltiple25 2 NM X [0..0] 00128 Orden de Nacimiento26 250 CE RE [0..1] 0171 00129 Ciudadanía27 250 CE X [0..0] 0172 00130 Estado de Veterano Militar28 250 CE X [0..1] 0212 00739 Nacionalidad29 26 TS X [0..0] 00740 Fecha y Hora de Defunción de Paciente30 1 ID X [0..0] 0136 00741 Indicador de Defunción de Paciente31 1 ID X [0..0] 0136 01535 Indicador de Identidad Desconocida32 20 IS X [0..0] 0445 01536 Indicador de Fiabilidad de Identificación33 26 TS X [0..0] 01537 Fecha/Hora de última actualización34 241 HD X [0..0] 01538 Últimas instalaciones de actualización35 250 CE X [0..0] 0446 01539 Código de especie36 250 CE X [0..0] 0447 01540 Código de raza37 80 ST X [0..0] 01541 Esguince38 250 CE X [0..0] 0429 01542 Código de la clase de producción39 250 CWE X [0..0] 0171 01840 Ciudadanía Tribal
Tabla 11: Segmento PID
39
Gestión de Análisis Clínicos: Cornalvo
PID-3 LISTA DE ID DE PACIENTE
• Componentes: <ID Number (ST)> ^ <Check Digit (ST)> ^ <Check Digit Scheme (ID)> ^
<Assigning Authority (HD)> ^ <Identifier Type Code (ID)> ^ <Assigning Facility (HD)> ^
<Effective Date (DT)> ^ <Expiration Date (DT)> ^ <Assigning Jurisdiction (CWE)> ^
<Assigning Agency or Department (CWE)>.
• Este campo puede contener múltiples ocurrencias de identificadores de pacientes para reflejar
todos los identificadores posibles, como por ejemplo, los identificadores normalizados en la guía
de implementación de Datos de identificación de paciente de HL7 Spain.
• En este campo se envía el identificador único de paciente (Código de Identificación de Paciente,
CIP) .
• En esta primera fase, y para el caso de los resultados, no se considerarán aquellos mensajes que
no tengan un identificador CIP en este campo.
PID-5 NOMBRE DE PACIENTE
• Componentes: <Family Name (FN)> ^ <Given Name (ST)> ^ <Second and Further Given
Names or Initials Thereof (ST)> ^ <Suffix (e.g., JR or III) (ST)> ^ <Prefix (e.g., DR) (ST)> ^
<Degree (e.g., MD) (IS)> ^ <Name Type Code (ID)> ^ <Name Representation Code (ID)> ^
<Name Context (CE)> ^ <Name Validity Range (DR)> ^ <Name Assembly Order (ID)> ^
<Effective Date (TS)> ^ <Expiration Date (TS)> ^ <Professional Suffix (ST)>
• Vendrá el primer apellido del paciente en el primer componente del campo (PID-5-1-1) y el
segundo apellido en el segundo componente (PID-5-2-1).
40
Gestión de Análisis Clínicos: Cornalvo
PID-7 FECHA/HORA DE NACIMIENTO
• Componentes: <Time (DTM)> ^ <Degree of Precision (ID)>.
• Contendrá la fecha de nacimiento siguiendo el formato YYYYMMDDHHMMSS en el primer
componente (PID-7-1-1).
PID-8 SEXO ADMINISTRATIVO
• Se indicará el Sexo del paciente según los valores establecidos por la tabla de Usuario 0001. Se
utilizan los valores propuestos por HL7 para la tabla.
Valor Descripción Comentario
F Femenino
M Masculino
O Otro
U Desconocido
A Ambiguo
N No aplicable
Tabla 12: Tabla definida por el usuario 0001 – Sexo Administrativo
41
Gestión de Análisis Clínicos: Cornalvo
PID-11 DIRECCIÓN DEL PACIENTE
• En este atributo se envía la dirección habitual del paciente, según se describe en la guía de
implementación de HL7 Spain, datos de identificación de paciente. Este campo puede tener más
de un valor, aunque el ORT solamente considerará el primero como domicilio habitual.
PID-13 NÚMERO DE TELÉFONO – DOMICILIO
• En este atributo se envía el número de teléfono del domicilio, tal y como se describe en la guía
de implementación de HL7 Spain, datos de identificación de paciente. Aunque este campo puede
tener más de un valor, se considerará el primer valor como el teléfono de contacto.
PID-26 CIUDADANÍA
• En este campo se envía el País de procedencia del paciente. Los valores posibles se determinan
en la tabla de usuario 0171. La referencia para los valores es la norma ISO-3166, con
representación alfanumérica de tres caracteres.
42
Gestión de Análisis Clínicos: Cornalvo
Subcapítulo 6.5: Segmento OBR
El segmento OBR sirve como cabecera para la información clínica. Identifica el conjunto de
observaciones representado por las observaciones atómicas que le siguen. Incluye la información
de la orden cuando se aplica. Contiene muchos de los atributos que se aplican habitualmente a
todas las observaciones.
NOTA: En esta primera fase de la implementación solamente se permite una batería de test por
orden/petición de pruebas del SIL. Es decir, que para cada batería debe haber un OBR-3 único.
43
Gestión de Análisis Clínicos: Cornalvo
Sec. Long. Tipo Uso Card. Tabla Ítem HL7 Nombre elemento1 4 SI X [0..0] 00237 Identificador de conjunto - OBR2 22 EI RE [0..1] 00216 Número de orden del peticionario3 22 EI R [1..1] 00217 Número de orden del “order filler”4 250 CE R [1..1] 00238 Identificador universal del servicio5 2 ID X [0..0] 00239 Prioridad OBR6 26 TS X [0..0] 00240 Fecha/Hora de la petición7 26 TS X [0..0] 00241 Fecha/Hora de la observación8 26 TS X [0..0] 00242 Fecha/Hora del fin de la observación9 20 CQ X [0..0] 00243 Volumen de la colección10 250 XCN RE [0..1] 00244 Identificador del que recoge el espécimen11 1 ID RE [0..1] 0065 00245 Código de Acción del espécimen12 250 CE X [0..0] 00246 Código de peligro13 300 ST X [0..0] 00247 Información clínica relevante14 26 TS X [0..0] 00248 Fecha/Hora de recepción del espécimen15 300 SPS X [0..0] 00249 Origen del espécimen16 250 XCN RE [0..1] 00226 Proveedor de la orden17 250 XTN X [0..0] 00250 Número de teléfono de devolución de llamada de la
orden18 60 ST X [0..0] 00251 Placer Field 119 60 ST X [0..0] 00252 Placer Field 220 60 ST X [0..0] 00253 Filler Field 121 60 ST X [0..0] 00254 Filler Field 222 26 TS X [0..0] 00255 Results Rpt/Status Chng - Date/Time23 40 MOC X [0..0] 00256 Charge to Practice24 10 ID R [1..1] 0074 00257 Identificador de la sección de diagnóstico25 1 ID R [1..1] 0123 00258 Estado del resultado26 400 PRL X [0..0] 00259 Parent Result27 200 TQ X [0..0] 00221 Quantity/Timing28 250 XCN RE [0..*] 00260 Result Copies To29 200 EIP X [0..0] 00261 Parent 30 20 ID X [0..0] 0124 00262 Transportation Mode31 250 CE X [0..0] 00263 Reason for Study32 200 NDL C [0..1] 00264 Principal Result Interpreter33 200 NDL X [0..0] 00265 Assistant Result Interpreter34 200 NDL X [0..0] 00266 Technician35 200 NDL X [0..0] 00267 Transcriptionist36 26 TS X [0..0] 00268 Scheduled Date/Time37 4 NM X [0..0] 01028 Number of Sample Containers *38 250 CE X [0..0] 01029 Transport Logistics of Collected Sample39 250 CE X [0..0] 01030 Collector's Comment *40 250 CE X [0..0] 01031 Transport Arrangement Responsibility41 30 ID X [0..0] 0224 01032 Transport Arranged42 1 ID X [0..0] 0225 01033 Escort Required43 250 CE X [0..0] 01034 Planned Patient Transport Comment44 250 CE X [0..0] 0088 00393 Procedure Code45 250 CE X [0..0] 0340 01316 Procedure Code Modifier46 250 CE X [0..0] 0411 01474 Placer Supplemental Service Information47 250 CE X [0..0] 0411 01475 Filler Supplemental Service Information48 250 CWE X [0..0] 0476 01646 Medically Necessary Duplicate Procedure Reason.49 2 IS X [0..0] 0507 01647 Result Handling
44
Gestión de Análisis Clínicos: Cornalvo
Tabla 13: Tabla HL7 de Atributos – OBR – Petición de Observación
45
Gestión de Análisis Clínicos: Cornalvo
OBR-1 IDENTIFICADOR DE CONJUNTO
Identifica la orden dentro del mensaje transmitido. El contenido se establece como un valor
numérico único para cada segmento OBR del mensaje, estableciendo una secuencia que comienza
con el valor 1. En resumen, el primer segmento OBR debe llevar un valor 1 en este campo, el
segundo segmento OBR un valor 2, etc.
OBR-2 NÚMERO DE ORDEN DEL PETICIONARIO
Componentes: <Entity Identifier (ST)> ^ <Namespace ID (IS)> ^ <Universal ID (ST)> ^
<Universal ID Type (ID)>.
Este campo se requiere si su valor es conocido al emisor. Este identificador debe ser único para
el peticionario. El tipo de datos (EI) tiene cuatro componentes, pero solamente es obligatorio enviar
el primer componente.
OBR-3 NÚMERO DE ORDEN DEL “ ORDER FILLER ”
Componentes: <Entity Identifier (ST)> ^ <Namespace ID (IS)> ^ <Universal ID (ST)> ^
<Universal ID Type (ID)>.
Este campo es obligatorio y permite al ORT enlazar todos los test/resultados de una petición
juntos. También permite identificar la orden al nivel del “Order Filler”, por lo que debe ser un
identificador único para el “Order Filler” que envía el resultado. De los cuatro componentes de su
tipo de datos, solamente es obligado rellenar el primer componente.
OBR-4 IDENTIFICADOR UNIVERSAL DEL SERVICIO
Componentes: <Identifier (ST)> ^ <Text (ST)> ^ <Name of Coding System (ID)> ^ <Alternate
Identifier (ST)> ^ <Alternate Text (ST)> ^ <Name of Alternate Coding System (ID)>.
Este campo es el identificador de la batería de pruebas. Es obligatorio. Debe enviarse algún
valor para los tres primeros componentes de su tipo: Identificador, Texto y Nombre del Sistema de
Codificación. El resto de componentes son opcionales y en este caso no se utilizan.
La codificación propuesta es la codificación LOINC, de tal manera que el campo quedaría
reflejado como : <cod. LOINC batería>^<Descripción Batería>^LN.
OBR-10 IDENTIFICADOR DEL QUE RECOGE EL ESPÉCIMEN
46
Gestión de Análisis Clínicos: Cornalvo
Componentes: <ID Number (ST)> ^ <Family Name (FN)> ^ <Given Name (ST)> ^ <Second
and Further Given Names or Initials Thereof (ST)> ^ <Suffix (e.g., JR or III) (ST)> ^ <Prefix (e.g.,
DR) (ST)> ^ <DEPRECATED-Degree (e.g., MD) (IS)> ^ <Source Table (IS)> ^ <Assigning
Authority (HD)> ^ <Name Type Code (ID)> ^ <Identifier Check Digit (ST)> ^ <Check Digit
Scheme (ID)> ^ <Identifier Type Code (ID)> ^ <Assigning Facility (HD)> ^ <Name
Representation Code (ID)> ^ <Name Context (CE)> ^ <DEPRECATED-Name Validity Range
(DR)> ^ <Name Assembly Order (ID)> ^ <Effective Date (TS)> ^ <Expiration Date (TS)> ^
<Professional Suffix (ST)> ^ <Assigning Jurisdiction (CWE)> ^ <Assigning Agency or
Department (CWE)>.
Este campo identifica la persona, departamento o centro que recoge la muestra. Se envía si la
información está disponible, en caso contrario el campo se envía vacío. Solamente los tres primeros
componentes son obligatorios en caso de enviarse el dato.
OBR-11 CÓDIGO DE ACCIÓN DEL ESPÉCIMEN
Este campo es obligatorio cuando ocurren los siguientes eventos:
• La petición se introduce a nivel del “Order Filler” (SIL). El valor del código de acción es A.
• La batería o el test ha sido añadido por el “Order Filler” (SIL) para la confirmación de un
diagnóstico (test reflexivo). Su valor ha de ser G.
En cualquier otro caso el campo de Código de Acción carece de significado y no es obligatorio
su envío.
Código Descripción Comentario
A Añadir test solicitados al espécimen existente
G Orden generada; orden reflexiva
L El laboratorio tiene que extraer el espécimen del paciente
O El espécimen se obtuvo por otro servicio diferente al laboratorio
P Espécimen pendiente; Orden enviada antes de su llegada
R Orden revisada
S Programar los tests especificados debajo
Tabla 14: Tabla HL7 0065 – Códigos de acción del espécimen
47
Gestión de Análisis Clínicos: Cornalvo
OBR-16 PROVEEDOR DE LA ORDEN
Componentes: <ID Number (ST)> ^ <Family Name (FN)> ^ <Given Name (ST)> ^ <Second
and Further Given Names or Initials Thereof (ST)> ^ <Suffix (e.g., JR or III) (ST)> ^ <Prefix (e.g.,
DR) (ST)> ^ <DEPRECATED-Degree (e.g., MD) (IS)> ^ <Source Table (IS)> ^ <Assigning
Authority (HD)> ^ <Name Type Code (ID)> ^ <Identifier Check Digit (ST)> ^ <Check Digit
Scheme (ID)> ^ <Identifier Type Code (ID)> ^ <Assigning Facility (HD)> ^ <Name
Representation Code (ID)> ^ <Name Context (CE)> ^ <DEPRECATED-Name Validity Range
(DR)> ^ <Name Assembly Order (ID)> ^ <Effective Date (TS)> ^ <Expiration Date (TS)> ^
<Professional Suffix (ST)> ^ <Assigning Jurisdiction (CWE)> ^ <Assigning Agency or
Department (CWE)>.
Este campo identifica a quien ordenó el test. Es obligatorio si forma parte de la orden enviada
por el “Order Placer”. En esta primera fase esta información no está disponible.
OBR-24 IDENTIFICADOR DE LA SECCIÓN DE DIAGNÓSTICO
Este campo es la sección del servicio de diagnóstico donde se realizó la observación. HL7
permite guardar la identificación de un servicio externo de laboratorio si la observación proviene
de fuera de la organización. Este campo es obligatorio. En el caso de que el ORT reciba parte de los
resultados de una orden completa en diferentes momentos, el ORT puede utilizar este campo para
presentar todas las baterías/test con el mismo identificador de sección de diagnósticos juntos. La
tabla HL7 recoge los valores posibles para este campo5.
5 En la primera fase de implantación se utilizarán solamente los correspondientes a hematología (HM) y bioquímica (CH).
48
Gestión de Análisis Clínicos: Cornalvo
Valor Descripción Comentario
AU Audiología
BG Gases en sangre
BLB Banco de sangre
CUS Ultrasonido Cardíaco
CTH Cateterización Cardíaca
CT Escáner CAT
CH Química
CP Citopatología
EC Electrocardíaco (pe., EKG, EEC, Holter)
EN Electroneuro (EEG, EMG,EP,PSG)
HM Hematología
ICU Monitorización UCI al lado de la cama
IMM Inmunología
LAB Laboratorio
MB Microbiología
MCB Micobacteriología
MYC Micología
NMS Escáner de Medicina Nuclear
NMR Resonancia Magnético Nuclear
NRS Medidas del Servicio de Enfermería
OUS Ultrasonido OB
OT Terapia Ocupacional
OTH Otro
OSL Laboratorio Externo
PHR Farmacia
PT Terapia Física
PHY Medico (Hx. Dx, nota de admisión, etc.)
PF Función Pulmonar
RAD Radiología
RX Radiografía
RUS Ultrasonido Radiología
RC Cuidado Respiratorio (terapia)
RT Terapia con Radiación
SR Serología
SP Patología Cirugía
TX Toxicología
VUS Ultrasonido Vascular
VR Virología
XRC Cineradiógrafo
Tabla 15: Tabla HL7 0074 – Identificadores de Sección de Servicio Diagnóstico
49
Gestión de Análisis Clínicos: Cornalvo
OBR-25 ESTADO DEL RESULTADO
Este campo es obligatorio y debe rellenarse de acuerdo a la tabla HL7 0123 descrita en el
capítulo 4 del estándar. Dependiendo del evento disparador del mensaje OUL los valores posibles
son:
• Valor I. Utilizado para indicar la recepción del espécimen en el laboratorio. En caso de que una
batería o test requiera más de un espécimen este es el estado que debe usarse cuando todo los
espécimenes requeridos se hayan recibido. un segmento OBR con este estado I puede seguirse
por segmentos OBX que contienen resultados de observaciones tomadas en un tiempo de
recogida de espécimen (pe. volumen del espécimen recogido).
• Valor R. Indica que algunos resultados están disponibles y validados técnicamente pero aun no
validados clínicamente.
• Valor P. Indica que algunos de los resultados, pero no todos, están disponibles y han sido
clínicamente validados. La identidad del Experto Clínico debe ser indicada en este caso en el
campo OBR-32.
• Valor F. Indica que todos los resultados están disponibles y han sido validados clínicamente. La
identidad del Experto Clínico debe ser indicada en este caso en el campo OBR-32.
• Valor C. Indica que al menos un resultado contenido en uno de los segmentos OBX que lo
siguen ha sido modificado después de que los resultados hayan sido transmitidos con el estado
F. Este valor C nunca debe utilizarse antes de que los resultados hayan sido transmitidos con el
estado F. Puesto que un resultado corregido se supone clínicamente validado, la identidad del
Experto Clínico debe indicarse en el campo OBX-32 cuando el valor del estado del resultado es
C.
• Valor X, para indicar que una batería/test ha sido borrado. Este borrado pudo haber sido, bien
recibido desde el “Order Placer” para un espécimen ya recibido y aceptado por el “Order Filler”,
o bien decidido por el laboratorio. Este valor X no debe utilizarse si ya han sido transmitidos
algunos resultados para este test.
• Valor S, aunque el uso de este valor es principalmente en respuesta a un mensaje de consulta
(“Query”), puede utilizarse en mensajes OUL para test que hayan sido añadidos a la petición
original por el “Order Filler” (SIL). En este caso, el valor del campo OBR-11 (Código de
Acción) debe ser A o G.
50
Gestión de Análisis Clínicos: Cornalvo
Valor Descripción Comentario
O Orden recibida; espécimen aun no recibido
I No hay resultados disponibles; espécimen recibido, procedimiento incompleto
S No hay resultados disponibles; procedimiento programado, pero no realizado
A Algunos, pero no todos, de los resultados disponibles
P Preliminar: Un resultado temprano verificado está disponible, el resultado final aun no
obtenido
C Corrección a los resultados Para correcciones
R Resultados almacenados; aun no verificados
F Resultados finales; resultados almacenados y verificados. Solamente pueden cambiarse con
un resultado corregido.
Utilizado normalmente
X No hay resultados disponibles; Orden cancelada.
Y No hay orden en el registro para este test (utilizado solamente en consultas)
Z No hay registro de este paciente (utilizado solamente en consultas)
Tabla 16: Tabla HL7 0123 – Estado de Resultado
OBR-28 COPIAS DEL RESULTADO A
• Componentes: <ID Number (ST)> ^ <Family Name (FN)> ^ <Given Name (ST)> ^ <Second
and Further Given Names or Initials Thereof (ST)> ^ <Suffix (e.g., JR or III) (ST)> ^ <Prefix
(e.g., DR) (ST)> ^ <DEPRECATED-Degree (e.g., MD) (IS)> ^ <Source Table (IS)> ^ <Assign-
ing Authority (HD)> ^ <Name Type Code (ID)> ^ <Identifier Check Digit (ST)> ^ <Check Digit
Scheme (ID)> ^ <Identifier Type Code (ID)> ^ <Assigning Facility (HD)> ^ <Name Represent-
ation Code (ID)> ^ <Name Context (CE)> ^ <DEPRECATED-Name Validity Range (DR)> ^
<Name Assembly Order (ID)> ^ <Effective Date (TS)> ^ <Expiration Date (TS)> ^ <Profes-
sional Suffix (ST)> ^ <Assigning Jurisdiction (CWE)> ^ <Assigning Agency or Department
(CWE)>.
• Este campo puede utilizarse para indicar la lista de los destinatarios que recibirán una copia
impresa del informe de resultados, lo cual puede ser información muy útil para los usuarios que
tienen acceso a estos resultados. Es un campo que admite repeticiones y cuyos primeros tres
componentes son obligatorios.
51
Gestión de Análisis Clínicos: Cornalvo
• El primer componente del atributo se codifica como el Número CIAS del facultativo mientras
no comience a funcionar la integración con JARA y sus sistema de información de recursos
humanos, momento en el cual la identificación pasará a ser mediante la “posición” definida en el
proyecto JARA.
• OBR-32 Intérprete principal del resultado
• Componentes: <Name (CNN)> ^ <Start Date/time (TS)> ^ <End Date/time (TS)> ^ <Point of
Care (IS)> ^ <Room (IS)> ^ <Bed (IS)> ^ <Facility (HD)> ^ <Location Status (IS)> ^ <Patient
Location Type (IS)> ^ <Building (IS)> ^ <Floor (IS)>.
• Este campo es obligatorio cuando el valor del campo de estado de los resultados (OBR-25) es P,
F o C. El campo identifica quien ha validado el resultado, dónde y cuando se realizó la
validación. Describe completamente el paso de validación clínica. Si este campo se rellena con
la información de la validación clínica, son obligatorios los dos primeros componentes, es decir,
el nombre del responsable de la validación y la fecha y hora de la validación en el componente
de fecha y hora de comienzo. El resto de campos son opcionales y no se van a considerar en el
ORT. En el componente del nombre, son obligados los tres primeros subcomponentes al igual
que en otros atributos similares.
• La identificación de la persona que valida se hará empleando el número CIAS en esta primera
fase. En una fase posterior cuando entre en funcionamiento JARA en atención especializada y se
haya integrado la petición de las pruebas se pasará a utilizar la posición del experto definida en
el proyecto JARA.
• En resumen, la forma del campo será:
<Num. CIAS>&<Apellidos>&<Nombre>^AAAAMMDDHHMMSS.
52
Gestión de Análisis Clínicos: Cornalvo
Subcapítulo 6.5: Segmento OBX
El segmento OBX se utiliza para enviar la información de una observación simple o un
fragmento de una observación. Representa la unidad más pequeña e indivisible de un informe.
o
Sec. Long. Tipo Uso Card. Tabla Ítem HL7 Descripción1 4 SI R [1..1] 00569 Numero de secuencia2 2 ID C [0..1] 0125 00570 Tipo de valor3 250 CE R [1..1] 00571 Identificador de la observación 4 20 ST C [0..1] 00572 Subidentificador de la Observación5 999996 varia C [0..1] 00573 Valores6 250 CE C [0..1] 00574 Unidades7 60 ST RE [0..1] 00575 Rangos de valores normales8 5 IS RE [0..1] 0078 00576 Señal de anormalidad9 5 NM X [0..0] 00577 Probabilidad10 2 ID X [0..0] 0080 00578 Naturaleza del test anormal11 1 ID R [1..1] 0085 00579 Estado del resultado de la Observación 12 26 TS X [0..0] 00580 Dato efectivo del rango de referencia13 20 ST C [0..1] 00581 Chequeo de accesos de Usuarios14 26 TS RE [0..1] 00582 Fecha y hora de la Observación15 250 CE RE [0..1] 00583 Identificación de quien produce el resultado16 250 XCN RE [0..1] 00584 Responsable de la Observación17 250 CE C [0..1] 00936 Método de la Observación18 22 EI X [0..0] 01479 Identificador del Equipo19 26 TS X [0..0] 01480 Fecha y hora del Analisis
Tabla 17: Tabla HL7 de atributos – OBX – Observación/Resultad
6 La longitud del campo de observación es variable, dependiendo de su tipo. Ver tipo de valor OBX-2.
53
Gestión de Análisis Clínicos: Cornalvo
OBX-1 NÚMERO DE SECUENCIA
Este campo contiene un número de secuencia para la observación.
OBX-2 TIPO DE VALOR
Este campo debe de tener valor si OBX-5 (Valor de la observación) tiene un valor. El campo
del tipo de valor debe rellenarse de acuerdo a la tabla HL7 0125. Por ejemplo, si el resultado es
“>300” debe de utilizarse el tipo de valor “SN” en lugar del tipo de valor “ST” (cadena de
caracteres). Se prefiere el tipo de valor “TM” al “NM”.
En la práctica, para la mayoría de las observaciones se utilizarán los valores SN-Número
Estructurado, ST- Cadena de caracteres y NM – Numérico.
54
Gestión de Análisis Clínicos: Cornalvo
Valor Descripción Comentario
AD Dirección
CE Entrada Codificada
CF Elemento Codificado con Valores Formateados
CK Identificador Compuesto con Dígito de Control
CN Identificador Compuesto y Nombre
CP Precio Compuesto
CX Identificador Compuesto Extendido con Dígito de
Control
DT Fecha
ED Datos Encapsulados
FT Texto Formateado (Visualización)
MO Moneda
NM Numérico
PN Nombre de Persona
RP Puntero de referencia
SN Numérico estructurado
ST Datos de cadena de caracteres
TM Tiempo
TN Número de teléfono
TS Marca de tiempo (Fecha y Hora)
TX Datos de Texto (Visualización)
XAD Dirección extendida
XCN Nombre Extendido Compuesto y Número para
Personas
XON Nombre Extendido Compuesto y Número para
Organizaciones
XPN Nombre de Persona Extendido
XTN Número de Telecomunicaciones Extendido
Tabla 18: Tabla HL7 0125 – Tipo de valor
55
Gestión de Análisis Clínicos: Cornalvo
OBX-3 IDENTIFICADOR DE LA OBSERVACIÓN
Componentes: <Identifier (ST)> ^ <Text (ST)> ^ <Name of Coding System (ID)> ^
<Alternate Identifier (ST)> ^ <Alternate Text (ST)> ^ <Name of Alternate Coding System (ID)>
Código LOINC del test. Contenido: <Código LOINC>^<Nombre corto LOINC>^LN.
Se utilizan obligatoriamente los tres primeros componentes del campo para detallar el código
LOINC del test. El tercer campo está codificado según la tabla HL7 0396 y el valor que debe
rellenarse es LN, que se corresponde con la codificación LOINC.
OBX-4 SUBIDENTIFICADOR DE LA OBSERVACIÓN
Este campo se utiliza si es necesario agrupar varios segmentos OBX con el mismo
identificador de observación bajo el mismo OBR.
OBX-5 VALORES
Contiene los valores del test y será requerido a no ser que el campo OBX-11 (restado del
resultado) tenga los valores D,I ó X.
OBX-6 UNIDADES
Componentes: <Identifier (ST)> ^ <Text (ST)> ^ <Name of Coding System (ID)> ^
<Alternate Identifier (ST)> ^ <Alternate Text (ST)> ^ <Name of Alternate Coding System (ID)>
Unidades en las que se dan los valores. Este campo es obligatorio si el campo de tipo de valor
(OBX-2) está asignado como “NM” o “SN”.
Este campo está pendiente de acuerdo entre los responsables de laboratorio para escoger el
conjunto de unidades de medida normalizados en el SES.
OBX-7 RANGOS DE VALORES NORMALES
Rango de valores normales para el paciente.
Este campo debe ser valorado como se describe en HL7 V2.5 para todas las observaciones para
las cuales sea relevante. El rango de referencia que figura en este campo se supone que es relativo a
la edad y sexo del paciente u otros parámetros tales como el número de semanas de embarazo
cuando sea aplicable, lo que hace al campo OBX-10 (naturaleza de test anormal) innecesario.
Para valores numéricos se ha de valorar en el formato:
a) límite inferior – límite superior (cuando ambos límOBX-17 Método de la
observaciónites están definidos)
b) > límite inferior
56
Gestión de Análisis Clínicos: Cornalvo
c) < límite superior
en el caso de valores alfabéticos el valor normal puede informarse en esta localización.
OBX-8 SEÑAL DE ANORMALIDAD
Este campo se requiere cuando es aplicable. En el marco técnico IHE de laboratorio solo
admite un valor. Entre los posibles valores listados para este campo en la tabla HL7 0078, deben
admitirse los valores subrayados.
Valor Descripción Comentario
L Por debajo de lo normal
H Por encima de lo norma
LL Por debajo de los límites inferiores de pánico
HH Por encima de los límites superiores de pánico
< Por debajo de los valores inferiores absolutos. Fuera de escala instrumental
> Por encima de los valores superiores absolutos. fuera de escala instrumental
N Normal (aplicado a resultados no numéricos)
A Anormal (aplicado a resultados no numéricos)
AA Muy anormal (aplicado a valores no numéricos, análogo a límites de pánico para unidades numéricas)
nulo Rango no definido, o rangos normales.
U Cambio significativo hacia arriba
D Cambio significativo hacia abajo
B Mejor – uso cuando la dirección no es relevante
W Peor – uso cuando la dirección no es relevante
S Susceptible. Indicado solamente para susceptibilidades de microbiología.
R Resistente. Indicado para susceptibilidades de microbiología.
I Intermedio. Indicado solamente para susceptibilidades de microbiología.
MS Moderadamente susceptible. Indicado solamente para susceptibilidades de
microbiología.
VS Muy susceptible. Indicado solamente para susceptibilidades de microbiología.
Tabla 19: Tabla definida por el usuario 0078 – Indicadores de anormalidad
57
Gestión de Análisis Clínicos: Cornalvo
OBX-11 ESTADO DEL RESULTADO DE LA OBSERVACIÓN
Se indicará la fase en la que se encuentra el test enviado. Los valores que puede tomar este
campo se especifican en la tabla HL7-0085, de los cuales se utilizarán en esta primera fase el valor
F (resultado final), C (corrección) y X (no se puede obtener).
Valor Descripción Comentario
C El registro es una corrección y debe sustituir un resultado final
D Borra el registro OBX
F Resultados finales; solamente pueden cambiarse con un resultado corregido
I Espécimen en laboratorio; resultados pendientes
N No preguntado; utilizado para documentar afirmativamente que la observación identificada en el
OBX no fue .... cuando el identificador universal de servicio OBR-4 implica que pueder ser .... Not
asked; used to affirmatively document that the observation identified in the OBX was not sought
when the universal service ID in OBR-4 implies that it would be sought.
O Solamente descripción detallada (no resultado)
P Resultados preliminares
R Resultados introducidos, no verificados
S Resultados Parciales
X Los resultados no pueden obtenerse para esta observación
U Results status change to final without retransmitting results already sent as ‘preliminary.’ E.g.,
radiology changes status from preliminary to final
W Envió el original como incorrecto. Pe., transmitido para un paciente incorrecto
Tabla 20: Tabla HL7 0085 – Interpretación de los códigos resultado de observación
58
Gestión de Análisis Clínicos: Cornalvo
OBX-13 CHEQUEO DE ACCESOS DE USUARIOS
El “Order Filler” mandaría en este campo el valor 'P' si quiere informar al ORT de una
restricción en el acceso de algunos resultados para permitirlo solo a unos usuarios con privilegios
suficientes.
OBX-14 FECHA Y HORA DE OBSERVACIÓN
Fecha y hora de obtención del resultado del Test. Su formato será YYYMMDDHHMMSS.
Debe de rellenarse cuando el campo OBX-5 (valor) no está vacío. En casos muy excepcionales
puede ser desconocido para el “Order Filler”. Si el campo se envía vacío el ORT no indicará error.
OBX-15 IDENTIFICACIÓN DE QUIÉN PRODUCE EL RESULTADO
Componentes: <Identifier (ST)> ^ <Text (ST)> ^ <Name of Coding System (ID)> ^ <Alternate
Identifier (ST)> ^ <Alternate Text (ST)> ^ <Name of Alternate Coding System (ID)>.
Este campo será requerido siempre que el resultado venga de un laboratorio externo a la
Organización, es decir, desde un laboratorio que no pertenezca al SES.
OBX-16 RESPONSABLE DE LA OBSERVACIÓN (VERIFICADOR TÉCNICO)
Componentes: <ID Number (ST)> ^ <Family Name (FN)> ^ <Given Name (ST)> ^
<Second and Further Given Names or Initials Thereof (ST)> ^ <Suffix (e.g., JR or III) (ST)> ^
<Prefix (e.g., DR) (ST)> ^ <DEPRECATED-Degree (e.g., MD) (IS)> ^ <Source Table (IS)> ^
<Assigning Authority (HD)> ^ <Name Type Code (ID)> ^ <Identifier Check Digit (ST)> ^ <Check
Digit Scheme (ID)> ^ <Identifier Type Code (ID)> ^ <Assigning Facility (HD)> ^ <Name
Representation Code (ID)> ^ <Name Context (CE)> ^ <DEPRECATED-Name Validity Range
(DR)> ^ <Name Assembly Order (ID)> ^ <Effective Date (TS)> ^ <Expiration Date (TS)> ^
<Professional Suffix (ST)> ^ <Assigning Jurisdiction (CWE)> ^ <Assigning Agency or
Department (CWE)>.
Los tres primeros componentes son obligatorios. Este campo identifica al responsable del
cambio de estado de la Observación. La codificación de la persona emplea el número CIAS en el
momento actual.
OBX-17 MÉTODO DE LA OBSERVACIÓN
59
Gestión de Análisis Clínicos: Cornalvo
Este campo es innecesario debido a la utilización de la codificación LOINC para el campo
OBX-3 (Identificador de la observación). Solamente ha de utilizarse cuando no se pueda deducir el
método a partir del valor de este campo. En la práctica, no habrá ningún caso.
Subcapítulo 6.6: Segmento NTE
El segmento NTE Se usa habitualmente para enviar notas y comentarios.
Sec. Long. Tipo Uso Card. Tabla Ítem HL7 Descripción1 4 SI R [1..1] 00096 Identificador de conjunto - NTE2 8 ID RE [0..1] 105 00097 Origen del comentario3 65536 FT RE [0..1] 00098 Comentario4 250 CE RE [0..1] 0364 01318 tipo de comentario
Tabla 21: Segmento NTE
NTE-1 IDENTIFICADOR DE CONJUNTO
Este campo puede utilizarse cuando se incluyen múltiples segmentos NTE. Contiene un número
que comienza en 1 para el primer segmento y se incrementa en una unidad en el siguiente
segmento. En el marco técnico IHE de laboratorio este campo es obligatorio.
NTE-2 ORIGEN DEL COMENTARIO
Requerido pero puede ir vacío. El marco técnico IHE de Laboratorio utiliza una variación de la
tabla HL7 0105 que incluye un valor para el gestor de automatización.
Valor Descripción Comentario
L Departamento auxiliar (Order Filler, laboratorio)
P Peticionario (Order Placer)
A Gestor de automatización
O Otro sistema
Tabla 22: Tabla HL7 0105 – Origen del comentario
60
Gestión de Análisis Clínicos: Cornalvo
NTE-3 COMENTARIO
Requerido pero puede ir vacío. Este campo contiene el texto del comentario. Este texto puede ir
formateado. Para borrar un comentario existente, el campo debe contener una cadena vacía con
dobles comillas: “” (valor nulo).
Texto de comentario de idéntico tipo y fuente debe ser incluido en la misma ocurrencia de un
segmento NTE, y no dividirse sobre múltiples segmentos.
NTE-4 TIPO DE COMENTARIO
Requerido si se conoce. El marco técnico IHE de Laboratorio rellena este campo con los
siguientes valores:
Valor Descripción Comentario
I Anotación interna, no debe enviarse fuera del
laboratorio.
Utilizado entre el Gestor de Automatización y el Order Filler. No
debe ser enviado al ORT.
C Comentario dirigido al equipo médico Debe ser enviado al ORT o el Order Placer, pero no se debe
mostrar al paciente.
P Comentario dirigido al equipo médico, puede
mostrarse al paciente
Debe enviarse al ORT o al Order Placer y puede aparecer en el
informe de resultados dirigido al paciente
Tabla 23: Tabla definida por el usuario 0364 – Tipo de comentario
61
Gestión de Análisis Clínicos: Cornalvo
Capítulo7 : Detalles de la implementaciónLa comunicación de mensajes se establece con el modo original de respuesta, que significa que
el emisor espera que la aplicación receptora del mensaje devuelva un mensaje de respuesta (ACK)
después de procesar cada mensaje que recibe. El mensaje de respuesta informa del éxito o el
fracaso del procesamiento del mensaje. Mientras la aplicación emisora no reciba el mensaje de
confirmación, se entiende que es el responsable de la comunicación de dicho mensaje y no debe
descartarlo, intentando nuevas transmisiones del mensaje si fuese necesario.
Si hubiese algún error en la recepción o el procesamiento del mensaje, la aplicación receptora
enviará en el mensaje de respuesta un mensaje de error apropiado.
La implementación de este sistema está basada en [2] [3]:
1. Para todas las cuestiones que no estén explícitas en este documento ni se encuentren definidas en
los dos documentos anteriores, se tomará como referencia el estándar HL7 en su versión 2.5 para
la comunicación entre los SIL y el ORT, y en su versión 2.3.1 para la comunicación de
información demográfica de pacientes entre el sistema ADT y los sistemas SIL/ORT [4].
Subcapítulo7.1: Transporte JMS
El transporte JMS es un sistema de transporte de mensajes con entrega asegurada basado en una
especificación J2EE [5]. Es un sistema de comunicación basado en colas e implementado en JAVA.
En un sistema de comunicación basado en JMS el mensaje HL7 se encapsula en un mensaje JMS,
como mensaje de texto, dirigido a una cola de entrada de mensajes. Los mensajes de respuesta se
depositan en una cola de salida después de procesarse el mensaje.
La arquitectura final de la implementación define dos colas en el servidor de aplicaciones de
CORNALVO:
62
Gestión de Análisis Clínicos: Cornalvo
1. Cola de recepción de mensajes OUL^R22/OUL^R24. En esta cola los SIL depositarán los
mensajes con los resultados de las pruebas.
2. Cola de emisión de ACK (mensajes de respuesta). En esta cola el servidor de CORNALVO
deposita cada mensaje de respuesta producido al procesar un mensaje de la cola de entrada.
Cada SIL tiene una cola de ACK asignada desde la que puede obtener los mensajes de respuesta
a sus mensajes.
Aunque el sistema de transporte es por naturaleza asíncrono, realizar una implementación
síncrona del protocolo es bastante sencillo.
Subcapítulo7.2: Transporte TCP/IP (socket)
3. La Comunicación con este tipo de transporte, al contrario que en el caso anterior, no
proporciona un método asegurado de la entrega de los mensajes. De esta manera, el emisor debe
implementar los mecanismos adecuados para asegurarse que no se pierde ningún mensaje por un
problema en la comunicación. HL7 establece en su protocolo de comunicación que la
responsabilidad de la comunicación de un mensaje recae sobre el emisor. Esto quiere decir que
el emisor del mensaje no debe descartar ningún mensaje hasta que no tiene confirmación
mediante un mensaje de respuesta de su procesamiento por el receptor. Si hubiese algún
problema con las comunicaciones de los mensajes el emisor debe volver a enviar el mensaje
original. La conexión se establece mediante una conexión TCP/IP empleando sockets. En este
caso las aplicaciones deberán usar en la conexión una implementación del Protocolo Mínimo de
la Capa Más baja (MLLP) definido en el apéndice C del la guía de implementación HL77. En
resumen, la comunicación entre dos sistemas se producirá con una conexión por transacción,
esperando un mensaje de confirmación (ACK o respuesta a consulta) en la misma conexión en
dirección contraria (receptor-emisor). En la transmisión del mensaje se utilizará un protocolo
simple orientado a carácter en la forma8
<SB>dddd<EB><CR>, siendo
4. <SB> = carácter de comienzo de bloque (1 byte), ASCII VT (0x0B),
7 Sección C.4 de la guía de implementación, págs. 22-24.8 Convenciones de notación:
1. Los caracteres ASCII simples se encierran en comillas simples.2. Los caracteres especiales o caracteres ASCII no imprimibles se encierran entre <>. Los caracteres especiales son los caracteres LLP de comienzo de bloque y finalización de bloque. Los caracteres ASCII no imprimibles pueden escribirse con su abreviatura, pe., ESC para el carácter de Escape. También pueden escribirse como sus valores hexadecimales en la forma 0xXX dónde X es un dígito hexadecimal. Por ejemplo en el Estándar ASCII, <ESC> es <0x1B>.
63
Gestión de Análisis Clínicos: Cornalvo
5. dddd = datos, contenido completo del mensaje HL7 y codificado según el estándar en ER7 o
XML,
6. <EB> = carácter de fin de bloque (1 byte), carácter ASCII FS (0x1C),
7. <CR> = retorno de carro (1 byte), carácter ASCII (0x0D).
Capítulo 8 : Open Adaptor
Subcapítulo 8.1: introducción
64
Gestión de Análisis Clínicos: Cornalvo
En la arquitectura software del repositorio de análisis clínicos vemos que el motor de
integración se apoya en Openadaptor para extraer los mensajes HL7 que se encuentran
encapsulados en los mensajes JMS[6].
Los mensajes JMS son depositados en colas de OpenJMS[7]. Existe una cola para cada
laboratorio, además de otra cola para el ACK de cada laboratorio. En el caso de algunos
laboratorios se dispone además de otras 2 ó 3 colas para diferentes puntos de emisión de mensajería
HL7. Por otra parte, disponemos también de una cola de monitorización para cada laboratorio.
Estas colas de monitorización se utilizan exlusivamente por nuestro Order Result Tracker (ORT)
para comprobar si el sistema de mensajería está funcionando correctamente.
El proceso de captación de mensajes HL7 a partir de los mensajes JMS depositados en las colas
Openjms, es realizado por Openadaptor por medio de lo que se llaman adaptadores. Un adaptador
es un programa que, obedeciendo a una serie de parámetros de configuración, es capaz de
conectarse a colas de Openjms para recibir los mensajes JMS allí depositados y extraer de dichos
mensajes los datos de nuestro interés particular.
Para cada laboratorio tendremos un adaptador independiente que procese mensajes JMS
exlusivamente de la cola de entrada de ese laboratorio, depositando los mensajes de ACK en la cola
de ACK del mismo laboratorio.
Cada adaptador integra, además, un mecanismo de hospitalización [8]para aquellos mensajes
que, por alguna razón, no hayan podido ser procesados correctamente. Estos mensajes
hospitalizados pueden en un futuro volver a ser procesados observando la circunstancia que los
hizo fallar en su momento.
Openadaptor utiliza la librería java log4j para la generación de ficheros de registro. Existirá un
fichero de registro en formato htm para el seguimiento del procesamiento de mensajes por parte de
cada uno de los adaptadores de cada laboratorio. Por otra parte, también habrá dos ficheros de texto
para cada laboratorio, uno para los mensajes entrantes y otro para los mensajes de ACK de salida
de un mismo laboratorio.
65
Gestión de Análisis Clínicos: Cornalvo
Subcapítulo 8.2: Adaptadores Openadaptor
Un adaptador es una instancia de la clase org.openadaptor.adaptor.RunAdaptor con ciertos
parámetros de configuración que hacen única una instancia de otra. Estos parámetros son
configurables desde fichero.
Para la elaboración de los ficheros de configuración se ha utilizado la herramienta AFEditor
que viene con la distribución de Openadaptor.
Esta herramienta permite realizar ficheros de configuración de una manera intuitiva, al tiempo
que facilita la configuración de cada uno de los componentes utilizados en el adaptador. Sin
embargo, esta herramienta tiene un par de puntos malos que se discutirán en profundidad más
adelante.
Lo primero que hay que definir es la fuente de datos. Para ello, desplegamos la carpeta “All
Sources” y buscamos en la palette el componente fuente que necesitamos, en este caso un
componente JMSSource. Más tarde lo configuraremos en profundidad.
66
Ilustración 7: OpenAdaptor Framework
Ilustración 8: Componente Palette
Gestión de Análisis Clínicos: Cornalvo
Este componente va a leer mensajes JMS de una cola Openjms y va a extraer los datos de
interés depositándolos en lo que se llaman DataObjects. Un DataObject es un tipo de datos
manejable por Openadaptor. Estos DataObjetcts son los que se irán moviendo a través de todos los
componentes del adaptador.
Los DataObjects extraídos en el JMSSource son después llevados hasta un componente de
filtración de Openadaptor llamado Pipe. Un Pipe es el encargado de tratar la información contenida
en el DataObject y permite establecer reglas para dirigir los DataObjects a uno u otro destino.
Por último, una vez que los DataObjects han sido tratados en los Pipes, llega el momento de
enviarlos a un componente destino denominado Sink. Para depositar los mensajes de respuesta de
ACK de los laboratorios en su cola JMS respectiva, necesitaremos un componente llamado
JMSSink.
Esta es la configuración básica:
● Componente JMSSource conectado a
● Componente Pipe conectado a
● Componente JMSSink
Subcapítulo 8.3:Configuración de los componentes
COMPONENTE JMSSOURCE
67
Ilustración 9: Componentes JMS
Ilustración 10: JMSSource
Gestión de Análisis Clínicos: Cornalvo
Este componente se conecta a una cola Openjms para leer mensajes JMS. Al pulsar sobre este
componente en la herramienta AFEditor podemos configurar los siguientes parámetros:
✔ Name: es el nombre del componente. Por defecto Openadaptor le da el nombre de “C”
seguido de un número que hace referencia al número de componentes que se hayan creado.
✔ Number: es el orden de inicialización para el componente. No es un parámetro muy
importante ya que este orden no afecta al funcionamiento del adaptador.
✔ Queue++: nombre de la n-ésima cola que se vaya a configurar. Un componente JMSSource
se puede conectar a la vez a múltiples colas de escucha. A cada una de estas colas se las
identifica por el nombre que se ponga aquí.
✔ Queue1: nombre de la cola 1. Si se hubiesen definido más colas según el parámetro Queue+
+, tendríamos también Queue2, Queue3, etc. A continuación, se detallan los parámetros
imprescindibles para una cola en particular (el resto de parámetros toma los valores por
defecto):
○ Queue1: nombre de la n-ésima cola.
○ Factory: nombre de la factoría usada para establecer la conexión con la cola JMS.
Utilizaremos JmsQueueConnectionFactory
○ Subject: nombre de la cola a la que nos conectaremos. Esta cola debe existir en el
servidor jndi.
○ ConnectionCheckTimeOut: máximo tiempo de espera entre mensajes antes de chequear
el estado de conexión. Le fijamos un valor de 10.000 milisegundos.
68
Gestión de Análisis Clínicos: Cornalvo
○ JndiFactory: factoría jndi donde se conectará para buscar las colas JMS. Utilizaremos
org.exolab.jms.jndi.InitialContextFactory
○ JndiProvider: url para el proveedor jndi. Las colas se encuentran en
tcp://IP_SERVIDOR:3035, donde IP_SERVIDOR es la ip del servidor que hospeda el
servicio jndi (p. ej. 10.15.168.50)
✔ Topic++: nombre del n-ésimo tema que se vaya a configurar. Este tipo de configuración no
es usado por el ORT.
✔ ContinueOnException: continua con el proceso si en uno de los componentes salta una
excepción. Lo ponemos a true
✔ DOStringReader: clase utilizada para transformar el mensaje JMS en un DataObject.
Utilizaremos la clase org.openadaptor.dosstrings.VerbatimStreamReader
✔ ExitOnError: declara si el adaptador intentará hospitalizar un mensaje fallido (valor a true)
o si terminará el proceso con ese adaptador (valor a false). Fijaremos el valor a true
✔ TextEncoding: formato de codificación de los mensajes. Utilizaremos el formato “ISO-
8859-1”
✔ AttName: es el nombre del atributo que contiene el mensaje HL7. Establecemos el valor a
payload
✔ BufferSize: es el tamaño máximo que contendrá el buffer de lectura del mensaje JMS. Este
valor por defecto es de 4096 KB, pero le fijaremos un valor de 12288 KB
COMPONENTE JMSSINK
69
Ilustración 11: JMSSink
Gestión de Análisis Clínicos: Cornalvo
Este componente se conecta a una cola Openjms para escribir mensajes JMS. Al pulsar
sobre este componente en la herramienta AFEditor podemos configurar los siguientes
parámetros:
✔ Name: es el nombre del componente. Por defecto Openadaptor le da el nombre de “C”
seguido de un número que hace referencia al número de componentes que se hayan creado.
✔ Number: es el orden de inicialización para el componente. No es un parámetro muy
importante ya que este orden no afecta al funcionamiento del adaptador.
✔ Queue++: nombre de la n-ésima cola que se vaya a configurar. Un componente JMSSource
se puede conectar a la vez a múltiples colas de escritura. A cada una de estas colas se las
identifica por el nombre que se ponga aquí.
✔ Queue1: nombre de la cola 1. Si se hubiesen definido más colas según el parámetro Queue+
+, tendríamos también Queue2, Queue3, etc. A continuación, se detallan los parámetros
imprescindibles para una cola en particular (el resto de parámetros toma los valores por
defecto):
70
Gestión de Análisis Clínicos: Cornalvo
○ Queue1: nombre de la n-ésima cola.
○ Factory: nombre de la factoría usada para establecer la conexión con la cola JMS.
Utilizaremos JmsQueueConnectionFactory
○ Subject: nombre de la cola a la que nos conectaremos. Esta cola debe existir en el
servidor jndi.
○ ConnectionCheckTimeOut: máximo tiempo de espera entre mensajes antes de chequear
el estado de conexión. Le fijamos un valor de 10.000 milisegundos.
○ JndiFactory: factoría jndi donde se conectará para buscar las colas JMS. Utilizaremos
org.exolab.jms.jndi.InitialContextFactory
○ JndiProvider: url para el proveedor jndi. Las colas se encuentran en
tcp://IP_SERVIDOR:3035, donde IP_SERVIDOR es la ip del servidor que hospeda el
servicio jndi (p. ej. 10.15.168.50)
✔ Topic++: nombre del n-ésimo tema que se vaya a configurar. Este tipo de configuración no
es usado por el ORT.
✔ ContinueOnException: continua con el proceso si en uno de los componentes salta una
excepción. Lo ponemos a true
71
Gestión de Análisis Clínicos: Cornalvo
✔ DOStringWriter: clase utilizada para transformar el DataObject en un mensaje JMS.
Utilizaremos la clase org.openadaptor.dosstrings.VerbatimStringWriter
✔ ExitOnError: declara si el adaptador intentará hospitalizar un mensaje fallido (valor a true)
o si terminará el proceso con ese adaptador (valor a false). Fijaremos el valor a true
✔ TextEncoding: formato de codificación de los mensajes. Utilizaremos el formato “ISO-
8859-1”
COMPONENTES PIPE
Estos componentes conforman el corazón del procesamiento de los adaptadores. Hay
diferentes tipos de Pipes de acuerdo al cometido de cada uno de ellos. Veremos cómo
configurar un hospital para el ingreso en el mismo de los mensajes que no hayan podido ser
procesados correctamente. También veremos cómo definir nuestros propios Pipes, punto
trascendental para permitir a nuestra aplicación ORT interactuar con los DataObjects
definidos por Openadaptor. Por último, veremos cómo configurar el adaptador para dirigir
los DataObjects a una cola destino u otra dependiendo de la información que contengan.
Esto lo conseguiremos por medio de AuditPipes o filtros de auditoría, que nos permitirán
declarar qué tipos de parámetros serán filtrados en los FilterPipes.
HOSPITALPIPE
72
Ilustración 12: HospitalPipe
Gestión de Análisis Clínicos: Cornalvo
En el adaptador de cada laboratorio tenemos un HospitalPipe. Si en el procesamiento de
algún mensaje salta una excepción IbafException de tipo Hospital, el procesamiento de ese
adaptador terminaría a no ser que utilizasemos este componente, que capturaría la
excepción y procedería a ingresar el mensaje en el hospital. Para la implementación del
hospital se pueden seguir varias alternativas; nosotros hemos optado por una base de datos.
La configuración de nuestro HospitalPipe es la siguiente:
✔ Name: es el nombre del componente. Le ponemos el nombre Chospital
✔ Number: es el orden de inicialización del componente.
✔ DefaultApplication: permite al hospital decir de qué adaptador viene el mensaje rechazado.
Fijamos el valor Cornalvo
✔ DefaultSubject: nombre por defecto si el mensaje no tiene una fuente asociada. Fijamos el
valor debug
✔ HospitalName: nombre del hospital al que enviar los mensajes que se hospitalizarán.
Fijamos el valor CornalvoHospital
✔ CornalvoHospital.ClassName: nombre de la clase que implementa al hospital. Utilizaremos
org.openadaptor.adaptor.jdbc.oracle.HospitalOracleImpl
73
Ilustración 13: Property Tools
Gestión de Análisis Clínicos: Cornalvo
Ahora pinchamos en la pestaña Adaptor y volvemos a definir la propiedad
CornalvoHospital.ClassName con el valor
org.openadaptor.adaptor.jdbc.oracle.HospitalOracleImpl con el botón de añadir propiedad de las
“Property Tools”. También aprovechamos ahora para establecer el nombre de nuestro adaptador,
por lo que fijamos el parámetro Name a Cadena_adaptor
Le damos a salvar adaptador y le ponemos un nombre. Una vez hecho esto nos salimos de la
herramienta AFEditor y editamos a mano el fichero de configuración que acabamos de salvar para
establecer las propiedades de conexión a nuestra base de datos. Este es un punto importante ya que
la herramienta AFEeditor tiene una serie de “bugs” como éste. Una vez tenemos el fichero abierto
con cualquier editor de textos, añadiremos las siguientes propiedades:
● Cadena_adaptor.CornalvoHospital.ClassName =
org.openadaptor.adaptor.jdbc.oracle.HospitalOracleImpl
● Cadena_adaptor.CornalvoHospital.Database = Hospital
● Cadena_adaptor.CornalvoHospital.JdbcDriver = oracle.jdbc.driver.OracleDriver
● Cadena_adaptor.CornalvoHospital.JdbcUrl = jdbc:oracle:thin:@10.15.168.50:1521:RTDB
● Cadena_adaptor.CornalvoHospital.UserName = hospital
● Cadena_adaptor.CornalvoHospital.Password = h
Ahora hay que hacer una copia de seguridad del fichero de configuración, ya que si se vuelve a
abrir el fichero con la herramienta AFEditor y se salva el progreso, la herramienta borrará estas
propiedades. Quizás sea conveniente definir el componente del hospital en último lugar para
prevenir este error de la herramienta AFEditor.
GENERICPIPE
74
Ilustración 14: GenericPipe
Gestión de Análisis Clínicos: Cornalvo
Utilizamos Pipes genéricos para implementar funcionalidades específicas de nuestra aplicación.
En el ORT necesitamos implementar dos GenericPipes: HL7CarrierPipe y ORTPipe.
HL7CarrierPipe será el encargado de codificar los distintos atributos HL7 del segmento
MSH que forman parte del mensaje que viene en el atributo JMS payload. Estos atributos
HL7 son, por ejemplo, el SendingFacility, SendingApplication, ReceivingFacility,
ReceivingApplication, etc. Para definir los parámetros de configuración del HL7CarrierPipe,
pinchamos en el componente GeneriPipe y fijamos los siguientes valores:
✔ Name: nombre del componente, por ejemplo, HL7CarrierPipe
✔ ClassName: nombre de la clase que implementa este GenericPipe. Esta clase debe
encontrarse en el classpath de Openadaptor para que funcione correctamente. Esta es nuestra
implementación: com.comparex.sil.integracion.openadaptor.HL7CarrierPipe
75
Gestión de Análisis Clínicos: Cornalvo
ORTPipe enlaza con el motor de la aplicación que procesa los mensajes HL7 y genera el ACK
correspondiente de cada mensaje de entrada. A continuación explicamos los parámetros de
configuración de este componente:
✔ Name: nombre del componente, por ejemplo, ORTPipe
✔ ClassName: nombre de la clase que implmenta este GenericPipe. Esta clase debe
encontrarse en el classpath de Openadaptor para que funcione correctamente. Esta es
nuestra implementación: com.comparex.sil.integracion.openadaptor.ORTPipe
Una sóla instancia de la clase ORTPipe puede gestionar diversas aplicaciones tales como el
registro de los mensajes, una aplicación para la gestión de los mensajes tipo OULR22, otra para los
de tipo OULR24, otra para los mensajes tipo ADTA04, otra para los mensajes tipo ADTA08 y otra
para los mensajes tipo ADTA40. Para cada una de estas aplicaciones hay que especificar en el
fichero de configuración cuál será su clase, cuál será el fichero de hibernate que utilizará y
cualquier otra propiedad que tenga cada aplicación. Para el ORTPipe serán necesarios los
siguientes parámetros adicionales, añadidos por medio del botón “Add Property” de las “Property
Tools”:
✔ RegistroMensaje.FicheroHibernate = hibernate.cfg.xml
✔ RegistroMensaje.clase = com.comparex.sil.ort.HL7MessageLogApplication
✔ RegistroMensaje.nombre = RegistroMensaje
✔ RegistroRespuesta.FicheroHibernate = hibernate.cfg.xml
✔ RegistroRespuesta.clase = com.comparex.sil.ort.log.HL7AckLogApplication
✔ RegistroRespuesta.nombre = RegistroRespuesta
76
Gestión de Análisis Clínicos: Cornalvo
✔ aplicacion1.FicheroHibernate = hibernate.cfg.xml
✔ aplicacion1.cambiable = true
✔ aplicacion1.clase = com.comparex.sil.ort.adt.ADTA04Application
✔ aplicacion1.estricto = true
✔ aplicacion1.nombre = ADTA04Application
✔ aplicacion2.FicheroHibernate = hibernate.cfg.xml
✔ aplicacion2.cambiable = true
✔ aplicacion2.clase = com.comparex.sil.ort.adt.ADTA08Application
✔ aplicacion2.estricto = true
✔ aplicacion2.nombre = ADTA08Application
✔ aplicacion3.FicheroHibernate = hibernate.cfg.xml
✔ aplicacion3.cambiable = true
✔ aplicacion3.clase = com.comparex.sil.ort.adt.ADTA40Application
✔ aplicacion3.estricto = true
✔ aplicacion3.nombre = ADTA40Application
✔ aplicacion4.FicheroHibernate = hibernate.cfg.xml
✔ aplicacion4.cambiable = true
✔ aplicacion4.clase = com.comparex.sil.ort.adt.OULR22Application
✔ aplicacion4.estricto = true
✔ aplicacion4.nombre = OULR22Application
✔ aplicacion5.FicheroHibernate = hibernate.cfg.xml
✔ aplicacion5.cambiable = true
✔ aplicacion5.clase = com.comparex.sil.ort.adt.OULR24Application
✔ aplicacion5.estricto = true
✔ aplicacion5.nombre = OULR24Application
77
Gestión de Análisis Clínicos: Cornalvo
IMPLEMENTACIÓN DE UN GENERICPIPE
Para implementar un GenericPipe, tal como HL7CarrierPipe u ORTPipe, hay que extender la
clase AbstractSimplePipe de Openadaptor e implementar los siguientes métodos:
● protected DataObject[] transformDataObjects(DataObject[] inDobs) throws
PipelineException;
● public void init(String name, Properties properties, String propsPrefix, Controller
controller) throws IbafException;
78
Gestión de Análisis Clínicos: Cornalvo
Ejemplo de implementación de GenericPipe: HL7CarrierPipe
/** * inicializa el HL7CarrierPipe con el valor del atributo que encapsula el * mensaje HL7 */ public void init(String name, Properties properties, String propsPrefix, Controller controller) throws IbafException { super.init(name, properties, propsPrefix, controller);
if (propsPrefix!="") propsPrefix += "."; // Añade el . separador si hay prefijo if (properties.containsKey(propsPrefix + HL7NombreAtributo)) { HL7Capsula = properties.getProperty(propsPrefix + HL7NombreAtributo); } else { logger.warn("No existe la propiedad " + propsPrefix + HL7NombreAtributo); } logger.info("Obteniendo el mensaje HL7 del atributo " + HL7Capsula); this.Message = new SDOType("Message");
try { this.Message.addAttribute("FieldSeparator", new SDOType("String")); this.Message.addAttribute("EncodingCharacters", new SDOType("String")); this.Message.addAttribute("SendingApplication", new SDOType("String")); this.Message.addAttribute("SendingFacility", new SDOType("String")); this.Message.addAttribute("ReceivingApplication", new SDOType("String")); this.Message.addAttribute("ReceivingFacility", new SDOType("String")); this.Message.addAttribute("DateTimeOfMessage", new SDOType("String")); this.Message.addAttribute("Security", new SDOType("String")); this.Message.addAttribute("MessageCode", new SDOType("String")); this.Message.addAttribute("MessageEvent", new SDOType("String")); this.Message.addAttribute("MessageStructure", new SDOType("String")); this.Message.addAttribute("MessageControlID", new SDOType("String")); this.Message.addAttribute("ProcessingID", new SDOType("String")); this.Message.addAttribute("VersionID", new SDOType("String")); this.Message.addAttribute("SequenceNumber", new SDOType("String")); this.Message.addAttribute("ContinuationPointer", new SDOType("String")); this.Message.addAttribute("AcceptAcknowledgmentType", new SDOType("String")); this.Message.addAttribute("ApplicationAcknowledgmentType", new SDOType("String")); this.Message.addAttribute("CountryCode", new SDOType("String")); this.Message.addAttribute("CharacterSet", new SDOType("String")); this.Message.addAttribute("PrincipalLanguageOfMessage", new SDOType("String")); this.Message.addAttribute("AlternateCharacterSetHandlingScheme", new SDOType("String")); this.Message.addAttribute("MessageProfileIdentifier", new SDOType("String")); this.Message.addAttribute(HL7Capsula, new SDOType("String")); } catch (Exception e) { e.printStackTrace(); } }
79
Gestión de Análisis Clínicos: Cornalvo
/** * Transforma el DataObject añadiendo a cada DO del array los atributos de * la cabecera del mensaje HL7 encapsulado */ protected DataObject[] transformDataObjects(DataObject[] inDobs) throws PipelineException { DataObject[] outDobs = new DataObject[1]; int numDO = inDobs.length; int i = 0; DataObject outDO = null;
while (i < numDO) { try { // Rellena el DO con los atributos del MSH del mensaje HL7 if (inDobs[i] != null) { String mensajeHL7 = (String) inDobs[i].getAttributeValue(HL7Capsula); GenericParser analizador = new GenericParser(); Message mensajeAnalizado = analizador.parse(mensajeHL7); outDO = new SimpleDataObject(Message); outDO.setAttributeValue(HL7Capsula, inDobs[i].getAttributeValue(HL7Capsula)); logger.debug(HL7Capsula + " = " + outDO.getAttributeValue(HL7Capsula));
if (! mensajeAnalizado.getVersion().equalsIgnoreCase("2.5")) { //throw new HL7Exception("Versión HL7 no soportada"); logger.warn("No viene la versión del mensaje"); }
MSH mensajeMSH = (MSH) mensajeAnalizado.get("MSH");
if (mensajeMSH != null) { outDO.setAttributeValue("FieldSeparator", mensajeMSH.getFieldSeparator().getValue()); logger.debug("FieldSeparator = " + mensajeMSH.getFieldSeparator().getValue()); outDO.setAttributeValue("EncodingCharacters", mensajeMSH.getEncodingCharacters().getValue());
logger.debug("EncodingCharacters = " + mensajeMSH.getEncodingCharacters().getValue());
outDO.setAttributeValue("SendingApplication", mensajeMSH.getSendingApplication().getComponent(0).toString());
logger.debug("SendingApplication = " + mensajeMSH.getSendingApplication().getComponent(0).toString());
outDO.setAttributeValue("SendingFacility", mensajeMSH.getSendingFacility().getComponent(0).toString());
logger.debug("SendingFacility = " + mensajeMSH.getSendingFacility().getComponent(0).toString());
outDO.setAttributeValue("ReceivingApplication", mensajeMSH.getReceivingApplication().getComponent(0).toString());
logger.debug("ReceivingApplication = " + mensajeMSH.getReceivingApplication().getComponent(0).toString());
outDO.setAttributeValue("ReceivingFacility", mensajeMSH.getReceivingFacility().getComponent(0).toString());
logger.debug("ReceivingFacility = " + mensajeMSH.getReceivingFacility().getComponent(0).toString());
outDO.setAttributeValue("DateTimeOfMessage", mensajeMSH.getDateTimeOfMessage().getTime().toString());
80
Gestión de Análisis Clínicos: Cornalvo
logger.debug("DateTimeOfMessage = " + mensajeMSH.getDateTimeOfMessage().getTime().toString());
outDO.setAttributeValue("Security", mensajeMSH.getSecurity().getValue()); logger.debug("Security = " + mensajeMSH.getSecurity().getValue()); outDO.setAttributeValue("MessageCode", mensajeMSH.getMessageType().getMessageCode().getValue());
logger.debug("MessageCode = " + mensajeMSH.getMessageType().getMessageCode().getValue());
outDO.setAttributeValue("MessageEvent", mensajeMSH.getMessageType().getComponent(1).toString());
logger.debug("MessageEvent = " + mensajeMSH.getMessageType().getComponent(1).toString());
outDO.setAttributeValue("MessageStructure", mensajeMSH.getMessageType().getMessageStructure().getValue());
logger.debug("MessageStructure = " + mensajeMSH.getMessageType().getMessageStructure().getValue());
outDO.setAttributeValue("MessageControlID", mensajeMSH.getMessageControlID().getValue());
logger.debug("MessageControlID = " + mensajeMSH.getMessageControlID().getValue()); outDO.setAttributeValue("SequenceNumber", mensajeMSH.getSequenceNumber().getValue());
outDO.setAttributeValue("ProcessingID", mensajeMSH.getProcessingID().getProcessingID().getValue());
logger.debug("ProcessingID = " + mensajeMSH.getProcessingID().getProcessingID().getValue());
outDO.setAttributeValue("VersionID", mensajeMSH.getVersionID().getVersionID().getVersion());
logger.debug("VersionID = " + mensajeMSH.getVersionID().getVersionID().getVersion()); outDO.setAttributeValue("SequenceNumber", mensajeMSH.getSequenceNumber().getValue());
logger.debug("SecuenceNumber = " + mensajeMSH.getSequenceNumber().getValue()); outDO.setAttributeValue("ContinuationPointer", mensajeMSH.getContinuationPointer().getValue());
logger.debug("ContinuationPointer = " + mensajeMSH.getContinuationPointer().getValue());
outDO.setAttributeValue("AcceptAcknowledgmentType", mensajeMSH.getAcceptAcknowledgmentType().getValue());
logger.debug("AcceptAcknowledgmentType = " + mensajeMSH.getAcceptAcknowledgmentType().getValue());
outDO.setAttributeValue("ApplicationAcknowledgmentType", mensajeMSH.getApplicationAcknowledgmentType().getValue());
logger.debug("ApplicationAcknowledgmentType = " + mensajeMSH.getApplicationAcknowledgmentType().getValue());
outDO.setAttributeValue("CountryCode", mensajeMSH.getCountryCode().getValue()); logger.debug("CountryCode = " + mensajeMSH.getCountryCode().getValue());
81
Gestión de Análisis Clínicos: Cornalvo
if (mensajeMSH.getCharacterSet().length == 0) { outDO.setAttributeValue("CharacterSet", null); logger.debug("CharacterSet = " + null); } else { outDO.setAttributeValue("CharacterSet", mensajeMSH.getCharacterSet()[0].getValue()); logger.debug("CharacterSet = " + mensajeMSH.getCharacterSet()[0].getValue()); }
outDO.setAttributeValue("PrincipalLanguageOfMessage", mensajeMSH.getPrincipalLanguageOfMessage().getIdentifier().getValue());
logger.debug("PrincipalLanguageOfMessage = " + mensajeMSH.getPrincipalLanguageOfMessage().getIdentifier().getValue());
outDO.setAttributeValue("AlternateCharacterSetHandlingScheme", mensajeMSH.getAlternateCharacterSetHandlingScheme().getValue());
logger.debug("AlternateCharacterSetHandlingScheme = " + mensajeMSH.getAlternateCharacterSetHandlingScheme().getValue());
if (mensajeMSH.getMessageProfileIdentifier().length == 0) { outDO.setAttributeValue("MessageProfileIdentifier", null); logger.debug("MessageProfileIdentifier = " + null); } else { outDO.setAttributeValue("MessageProfileIdentifier", mensajeMSH.getMessageProfileIdentifier()[0].toString());
logger.debug("MessageProfileIdentifier = " + mensajeMSH.getMessageProfileIdentifier()[0].toString()); } } } } catch (InvalidParameterException e) { logger.error("Error en HL7CarrierPipe: "+e.getMessage()+"\n"); e.printStackTrace(); throw new PipelineException(e.getLocalizedMessage(),PipelineException._FATAL);
} catch (EncodingNotSupportedException e) { logger.error("Error en HL7CarrierPipe: "+e.getMessage()+"\n"); e.printStackTrace(); throw new PipelineException("Codificación no soportada: " + e.getLocalizedMessage(),PipelineException._HOSPITAL);
} catch (HL7Exception e) { logger.error("Error en HL7CarrierPipe: "+e.getMessage()+"\n"); e.printStackTrace(); throw new PipelineException("Problema con mensaje HL7: " + e.getLocalizedMessage(),PipelineException._HOSPITAL);
} catch (Exception e) { logger.error("Error en HL7CarrierPipe: "+e.getMessage()+"\n"); e.printStackTrace(); throw new PipelineException(e.getLocalizedMessage(), PipelineException._HOSPITAL); }
finally { outDobs[i] = outDO; outDO = null; i++; } }
return outDobs; }
82
Gestión de Análisis Clínicos: Cornalvo
AuditPipe
Es un componente de auditoría, que establece los parámetros que se utilizarán en posteriores
componentes, como en el FilterPipe. En el caso de la aplicación ORT, se establecen los siguientes
parámetros tras señalar el componente AuditPipe de la herramienta AFEditor:
✔ Name: nombre que le queramos poner al componente, por ejemplo, Auditor
✔ IgnoreUnknownTypes: lanza una excepción si el auditor se encuentra una propiedad que no
esté configurada. Para evitar esta posibilidad, la fijamos a false
✔ LogFileName: nombre del fichero de registro que se creará para el auditor, por ejemplo,
Auditor.log
Ahora hay que declarar qué parámetros serán utilizados en posteriores componentes. Estos
parámetros se definen de acuerdo al tipo de datos que el componente anterior utilizó para componer
el DataObject. Como se verá más adelante en el ejemplo de configuración final, hace referencia al
componente “HL7CarrierPipe.Message”. Entonces, para declarar los parámetros escribiremos la
siguiente notación (valores de ejemplo):
✔ Message.Type = Message
✔ Message.AttName1 = payload
✔ Message.AttName2 = ReceivingFacility
✔ Message.AttName3 = ReceivingApplication
✔ Message.AttName...
83
Gestión de Análisis Clínicos: Cornalvo
FILTERPIPE
Este es el componente que se utiliza para dirigir los mensajes a una u otra cola, dependiendo de
la información contenida en el mensaje. Hay que recordar que el mensaje viene encapsulado en el
atributo payload (o nombre que hayamos fijado en el campo AttName) de un mensaje JMS.
Los FilterPipes se colocan a continuación del AuditPipe. En la aplicación ORT lo normal es
colocar un FilterPipe para filtrar por el campo MSH-5 (ReceivingApplication) y, de esta manera,
distinguir a qué laboratorio enviar el ACK de vuelta. Sin embargo, otros laboratorios disponen de
otros centros emisores de mensajes, aunque formen parte del mismo laboratorio, por lo que para
estos centros es necesario colocar otro FilterPipe para filtrar de acuerdo al MSH-6
(ReceivingFacility). Este nuevo FilterPipe se debe colocar a continuación del anterior.
En última instancia, se puede colocar otro FilterPipe tras el AuditPipe esta vez para filtrar los
mensajes que no concuerden con ninguno de los anteriores filtros, hospitalizando estos mensajes,
por ejemplo. Para hospitalizar un mensaje es necesario hacer saltar un IbafException de tipo
Hospital.
A continuación, señalamos un FilterPipe en la herramienta AFEditor y fijamos los siguientes
parámetros de configuración:
✔ Filter++ = pass
Nada más fijar este valor se generarán automáticamente nuevos campos en el componente con
el nombre “Filter1”.
✔ Filter1.AttName1 = ReceivingApplication
✔ Filter1.Value = ROCHE-OMEGA-2000
84
Gestión de Análisis Clínicos: Cornalvo
EL COMPONENTE CONTROLLER
En Openadaptor, el controlador es el que gestiona el transporte de todos los DataObjects entre
uno y otro componente. En nuestra aplicación, el componente Controller se configura con los
siguientes parámetros:
✔ Name: nombre del controlador. Lo dejamos por defecto en Controller
✔ RemoteControl.ClassName: nombre de la clase que implementa la funcionalidad de un
control remoto, en este caso vía http. Utilizaremos la clase HttpRemoteControl
✔ RemoteControl.ControlPassword: contraseña para control remoto. Le ponemos
AdminCornalvo
✔ RemoteControl.HttpPort: puerto para conectarse vía http. Dependiendo del adaptador que
estemos usando, este valor será:
○ para Abbott: 9001
○ para Bayer: 9002
○ para Izasa: 9003
○ para Dade Behring: 9004
○ para Horus: 9005
○ para Roche: 9006
○ para JARA: 9007
85
Gestión de Análisis Clínicos: Cornalvo
EL COMPONENTE LOGGING
Se trata de un componente que permite fijar el ámbito de los mensajes de registro de las
aplicaciones. Puede ser tipo “INFO” que muestra casi todos los mensajes, incluyendo los de
carácter informativo, los de avisos y los de error, “WARN” que muestra únicamente mensajes de
avisos y de error, “ERROR” que muestra únicamente los mensajes de error, “DEBUG” que muestra
únicamente mensajes de depuración y “ALL” que muestra todos los tipos de mensajes.
Normalmente utiliza la salida stdout estándar para mostrar los mensajes de registro. En la
aplicación ORT utilizamos una configuración particular basada en log4j. De esta manera, en el
fichero de configuración de cada adaptador definimos la siguiente propiedad:
✔ log4j.configuration = file:confLogLAB.properties, donde LAB es un laboratorio.
Con esto conseguimos hacer que el sistema de registro de mensajes se realice por medio de la
configuración de log4j particular para cada laboratorio. Algunos de los parámetros de
configuración del fichero log4j que utilizamos son los siguientes:
# Esta propiedad define el alcance de los ficheros de registro
⁃ log4j.rootCategory=INFO, logLAB
86
Gestión de Análisis Clínicos: Cornalvo
# Utilizaremos un fichero htm para la generación de los registros
⁃ log4j.appender.logLAB=org.apache.log4j.RollingFileAppender
⁃ log4j.appender.logLAB.file=ORT_LAB.htm
⁃ log4j.appender.logLAB.layout=org.apache.log4j.HTMLLayout
⁃ log4j.appender.logLAB.append=true
⁃ log4j.appender.logLAB.layout.title=Log de mensajes de Cornalvo: LAB
⁃ log4j.appender.logLAB.MaxFileSize=8192KB
# Esta propiedad define el número de ficheros de respaldo que se crearán
⁃ log4j.appender.logLAB.MaxBackupIndex=40
# Configuración para el log de Hibernate que también utiliza log4j
⁃ log4j.logger.org.hibernate.SQL=warn
⁃ log4j.logger.org.hibernate.type=warn
⁃ log4j.logger.org.hibernate.tool.hbm2ddl=warn
⁃ log4j.logger.org.hibernate.pretty=warn
⁃ log4j.logger.org.hibernate.cache=warn
⁃ log4j.logger.org.hibernate.transaction=warn
⁃ log4j.logger.org.hibernate.jdbc=warn
⁃ log4j.logger.org.hibernate.hql.ast.AST=warn
⁃ log4j.logger.org.hibernate.secure=warn
⁃ log4j.logger.org.hibernate=warn
# Configuración para el resto de clases de Openadaptor
⁃ log4j.logger.org.openadaptor.adaptor.RunAdaptor=warn
⁃ log4j.logger.org.openadaptor.util.SuperProperties=warn
⁃ log4j.logger.org.openadaptor.util.log4j.Log4jConfig=warn
⁃ log4j.logger.org.openadaptor.util.SuperPropertiesUtils=warn
⁃ log4j.logger.org.openadaptor.adaptor=warn
⁃ log4j.logger.org.openadaptor.adaptor.AbstractSimplePipe=info
⁃ org.openadaptor.dostrings.XMLStreamReader=warn
87
Gestión de Análisis Clínicos: Cornalvo
CONFIGURACIÓN PARA UN ADAPTADOR: ROCHE
En esta configuración del adaptador, Roche dispone de dos centros emisores: el hospital de
Mérida y el de Virgen del Puerto. Por otra parte, en este adaptador se ha conservado la cola antigua
de recepción de mensajes de Roche. El fichero de configuración para el adaptador de Roche, se
llama “ORT_ROCHE.properties”.
Como se ve en el gráfico, hay 4 tipos de componentes: los rojos denotan componentes de
control, los verdes son componentes fuente (sources), los amarillos son componentes destino
(sinks) y los azules son componentes tubería (pipes).
88
Ilustración 15: Configuración de un Adaptador
Gestión de Análisis Clínicos: Cornalvo
CASO DE USO: PROCESAR MENSAJE
El caso de uso normal para el adaptador ORT_ROCHE es el siguiente:
1. Llega un mensaje a una de las colas fuente del componente OUL_Roche
1.1.Crea el DataObject con el atributo “payload” que contiene el mensaje HL7
1.2.Adjunta en el DataObject otras propiedades JMS que tuviera el mensaje
1.3.Envía el DataObject al componente EntrantesRoche
1.4.Envía el DataObject al componente CHospital
2. EntrantesRoche
2.1.Añade el contenido del atributo “payload” al final del fichero “EntrantesRoche.hl7”
3. Chospital
3.1.Envía el DataObject al componente ORTPipe
4. ORTPipe
4.1.Procesa el mensaje HL7 contenido en el atributo “payload”
4.2.Envía el ACK generado por el ORTPipe al componente CarrierPipe
5. CarrierPipe
5.1.Añade al DataObject los atributos definidos en la clase HL7CarrierPipe que se
corresponden con todos los campos de un segmento MSH de HL7
5.2.Envía el DataObject al componente Auditor_Roche
6. Auditor_Roche
6.1.Declara los atributos que utilizarán los componentes conectados a éste
6.2.Envía el DataObject al componente MSH5
6.3.Envía el DataObject al componente Monitorizacion
7. Monitorizacion
7.1.Comprueba si el campo MSH-5 (receiving application) del mensaje HL7 se corresponde
con la palabra “MONITORIZACION”
7.1.1.Envía el DataObject al componente Monitor_Roche
7.1.2.FIN
8. Monitor_Roche
8.1.Escribe un mensaje JMS en la cola ACK_MONITORIZACION_ROCHE con el
contenido del DataObject
8.2.FIN
9. MSH5
89
Gestión de Análisis Clínicos: Cornalvo
9.1.Comprueba si el campo MSH-5 (receiving application) del mensaje HL7 se corresponde
con la palabra “ROCHE-OMEGA-2000”
9.1.1.Envía el DataObject al componente MSH6_MERIDA
9.1.2.Envía el DataObject al componente MSH6_VP
9.1.3.Envía el DataObject al componente MSH6_Viejo
10. MSH6_MERIDA
10.1.Comprueba si el MSH-6 (receiving facility) del mensaje HL7 se corresponde con la
expresión regular “[0256.U.73,256.U.73]”. Esta expresión deja pasar sólo aquellos
mensajes cuyo MSH-6 sea el mismo que alguno de los valores contenidos entre los
corchetes
10.1.1.Envía el DataObject al componente ACK_MERIDA
10.1.2.Envía el DataObject al componente LOG_ROCHE
11. ACK_MERIDA
11.1.Escribe un mensaje JMS en la cola ACK_ROCHE_MERIDA con el contenido del
DataObject
11.2.FIN
12. MSH6_VP
12.1.Comprueba si el MSH-6 (receiving facility) del mensaje HL7 se corresponde con la
expresión regular “[0566.U.73,566.U.73]”. Esta expresión deja pasar sólo aquellos
mensajes cuyo MSH-6 sea el mismo que alguno de los valores contenidos entre los
corchetes
12.2.Envía el DataObject al componente ACK_VP
12.3.Envía el DataObject al componente LOG_ROCHE
13. ACK_VP
13.1.Escribe un mensaje JMS en la cola ACK_ROCHE_VP con el contenido del
DataObject
13.2.FIN
14. MSH6_Viejo
14.1.Comprueba si el MSH-6 (receiving facility) del mensaje HL7 se corresponde con la
expresión regular “![0566.U.73,566.U.73,0256.U.73,256.U.73]”. Esta expresión deja
pasar sólo aquellos mensajes cuyo MSH-6 sea distinto que cualesquiera de los valores
contenidos entre los corchetes
90
Gestión de Análisis Clínicos: Cornalvo
14.2.Envía el DataObject al componente ACK_ROCHE
14.3.Envía el DataObject al componente LOG_ROCHE
15. ACK_ROCHE
15.1.Escribe un mensaje JMS en la cola ACK_ROCHE con el contenido del DataObject
15.2.FIN
16. LOG_ROCHE
16.1.Añade el contenido del atributo “payload” (que ahora contiene el ACK generado por el
ORTPipe), al final del fichero “ACK_ROCHE.ack”
16.2.FIN
91
Gestión de Análisis Clínicos: Cornalvo
CONFIGURANDO COMPONENTES
El adaptador se llama Cadena_adaptor
✔ OUL_ROCHE
○ Queue1 = Roche_Merida
○ Queue1.Factory = JmsQueueConnectionFactory
○ Queue1.Subject = OUL_ROCHE_MERIDA
■ JndiFactory = org.exolab.jms.jndi.InitialContextFactory
■ JndiProvider = tcp://10.15.168.50:3035
■ ServiceLevel = GUARANTEED
■ Transacted = true
■ UseCallback = false
○ Queue2 = Roche_VP
○ Queue2.Factory = JmsQueueConnectionFactory
○ Queue2.Subject = OUL_ROCHE_VP
■ JndiFactory = org.exolab.jms.jndi.InitialContextFactory
■ JndiProvider = tcp://10.15.168.50:3035
■ ServiceLevel = GUARANTEED
■ Transacted = true
■ UseCallback = false
○ Queue3 = Roche_Viejo
○ Queue3.Factory = JmsQueueConnectionFactory
○ Queue3.Subject = OUL_ROCHE
■ JndiFactory = org.exolab.jms.jndi.InitialContextFactory
■ JndiProvider = tcp://10.15.168.50:3035
■ ServiceLevel = GUARANTEED
■ Transacted = true
■ UseCallback = false
○ ContinueOnException = true
○ DOStringReader = org.openadaptor.dostrings.VerbatimStreamReader
○ ExitOnError = false
○ IgnoreHeaderLines = 0
○ TextEncoding = ISO-8859-1
92
Gestión de Análisis Clínicos: Cornalvo
○ TransporterManagerClassName = JMSAdaptorListenerManager
○ AttName = payload
○ BufferSize = 12288
✔ Entrantes_Roche
○ CreateOutputFile = true
○ DOStringWriter = org.openadaptor.dostrings.VerbatimStringWriter
○ MoveExistingOutputFile = false
○ OutputFileName = Entrantes_Roche.hl7
○ RecordDelimiter = \r\n
○ WriteMode = Append
○ AttName = payload
○ RolloverPeriod = 1D
✔ CHospital
○ DefaultApplication = Cornalvo
○ DefaultSubject = debug
○ CornalvoHospital.ClassName =
org.openadaptor.adaptor.jdbc.oracle.HospitalOracleImpl
○ HospitalName = CornalvoHospital
○ Nota: editar fichero de configuración para añadir el resto de propiedades del hospital
que la herramienta AFEditor elimina
○ Cadena_adaptor.CornalvoHospital.ClassName =
org.openadaptor.adaptor.jdbc.oracle.HospitalOracleImpl
○ Cadena_adaptor.CornalvoHospital.Database = Hospital
○ Cadena_adaptor.CornalvoHospital.JdbcDriver = oracle.jdbc.driver.OracleDriver
○ Cadena_adaptor.CornalvoHospital.JdbcUrl =
jdbc:oracle:thin:@10.15.168.50:1521:RTDB
○ Cadena_adaptor.CornalvoHospital.Password = h
○ Cadena_adaptor.CornalvoHospital.UserName = hospital
✔ ORTPipe
93
Gestión de Análisis Clínicos: Cornalvo
○ ClassName = com.comparex.sil.integracion.openadaptor.ORTPipe
○ RegistroMensaje.FicheroHibernate = hibernate.cfg.xml
○ RegistroMensaje.clase = com.comparex.sil.ort.log.HL7MessageLogApplication
○ RegistroMensaje.nombre = RegistroMensaje
○ RegistroRespuesta.FicheroHibernate = hibernate.cfg.xml
○ RegistroRespuesta.clase = com.comparex.sil.ort.log.HL7AckLogApplication
○ RegistroRespuesta.nombre = RegistroRespuesta
○ aplicacion1.FicheroHibernate = hibernate.cfg.xml
○ aplicacion1.cambiable = true
○ aplicacion1.clase = com.comparex.sil.ort.adt.ADTA04Application
○ aplicacion1.estricto = true
○ aplicacion1.nombre = ADTA04Application
○ aplicacion2.FicheroHibernate = hibernate.cfg.xml
○ aplicacion2.cambiable = true
○ aplicacion2.clase = com.comparex.sil.ort.adt.ADTA08Application
○ aplicacion2.estricto = true
○ aplicacion2.nombre = ADTA08Application
○ aplicacion3.FicheroHibernate = hibernate.cfg.xml
○ aplicacion3.cambiable = true
○ aplicacion3.clase = com.comparex.sil.ort.adt.ADTA40Application
○ aplicacion3.estricto = true
○ aplicacion3.nombre = ADTA40Application
○ aplicacion4.FicheroHibernate = hibernate.cfg.xml
○ aplicacion4.cambiable = true
○ aplicacion4.clase = com.comparex.sil.ort.adt.OULR22Application
○ aplicacion4.estricto = true
○ aplicacion4.nombre = OULR22Application
○ aplicacion5.FicheroHibernate = hibernate.cfg.xml
○ aplicacion5.cambiable = true
○ aplicacion5.clase = com.comparex.sil.ort.adt.OULR24Application
○ aplicacion5.estricto = true
○ aplicacion5.nombre = OULR24Application
94
Gestión de Análisis Clínicos: Cornalvo
✔ CarrierPipe
○ ClassName = com.comparex.sil.integracion.openadaptor.HL7CarrierPipe
✔ Auditor_Roche
○ IgnoreUnknownTypes = true
○ LogFileName = AuditorRoche.log
○ Type = Message
○ Message.AttName1 = payload
○ Message.AttName2 = ReceivingApplication
○ Message.AttName3 = ReceivingFacility
✔ MSH5
○ Filter1 = pass
○ Filter1.AttName1 = ReceivingApplication
○ Filter1.Value1 = ROCHE-OMEGA-2000
✔ MSH6_MERIDA
○ Filter1 = pass
○ Filter1.AttName1 = ReceivingFacility
○ Filter1.Value1 = [0256.U.73,256.U.73]
✔ ACK_MERIDA
○ Queue1 = Ack_MERIDA
○ Queue1.Factory = JmsQueueConnectionFactory
○ Queue1.Subject = ACK_ROCHE_MERIDA
■ JndiFactory = org.exolab.jms.jndi.InitialContextFactory
■ JndiProvider = tcp://10.15.168.50:3035
■ ServiceLevel = GUARANTEED
■ TimeToLive = 0
■ Transacted = true
95
Gestión de Análisis Clínicos: Cornalvo
○ RecordDelimiter = \n
○ ContinueOnException = false
○ DOSTRINGWRITER = org.openadaptor.dostrings.VerbatimStringWriter
○ AttName = payload
El resto de componentes se definen de forma análoga.
96
Gestión de Análisis Clínicos: Cornalvo
SCRIPT DE INICIO/PARADA
El script para iniciar y detener las aplicaciones ORT, así como el openjms, se llama cornalvo.sh
Uso para iniciar:
#> cornalvo.sh iniciar {todo openjms IZASA ABBOTT ROCHE HORUS DADE BAYER
JARA}
Uso para parar:
#> cornalvo.sh parar {orts openjms IZASA ABBOTT ROCHE HORUS DADE BAYER
JARA}
● “iniciar todo” inicia primero el openjms realizando una espera de 3 minutos para que al
servidor de openjms le de tiempo de levantarse. Después va iniciando cada uno de los
adaptadores ORT.
● “iniciar openjms” arranca el servidor openjms. En este caso no hace una espera de 3
minutos.
● “iniciar {LABORATORIO}” inicia un único adaptador ORT.
● “parar orts” para todos los adaptadores ORT pero deja funcionando el servidor de openjms.
● “parar openjms” para el servidor openjms.
● “parar {LABORATORIO}” para un único adaptador ORT.
En el script hay que configurar la variable JAVA_HOME y la variable OPENJMS_HOME.
Cada adaptador ORT se inicia por separado mediante su propio script
run_ORT_LABORATORIO.sh que necesita además el fichero de configuración del propio
laboratorio, ORT_LABORATORIO.properties
Por último, en cada script run_ORT_LABORATORIO.sh hay que definir la variable
JAVA_HOME y la variable OPENADAPTOR_HOME. Este script hace una llamada a un fichero
de configuración de classpath exclusivo para openadaptor llamado set_classpathProduccion.profile
que es el que carga todas las librerías que openadaptor necesita para funcionar.
97
Gestión de Análisis Clínicos: Cornalvo
Capítulo 9 : Arquitectura
La Aplicación se divide en dos partes bien diferenciadas:
•El receptor y acumulador de resultados.
•Consultas de datos almacenados en un navegador WEB.
98
Ilustración 16: Arquitectura del Sistema
Gestión de Análisis Clínicos: Cornalvo
Subcapítulo 9.1: El receptor y el acumulador de resultados
La recepción de mensajes se realiza a través de de mensajes JMS que son acumulados en el
servidor OpenJMS. Los mensajes van siendo retirados por el Gestor de Colas. Cada mensaje es
desglosado mediante las componentes de negocio y se almacena la información que contiene en la
base de datos.
El acumulador de resultados , ORT, se basa en una aplicación JAVA, en concreto, HAPI. Es una
aplicación que procesa mensajes HL7 y los parsea [9].
Está muy bien documentada en Internet por lo que sólo nos centramos en la generación del
ORT y del mensaje OULR24Application que es realmente lo que es propio de Cornalvo . Ver
Anexo 1.
La conexión con la Base de datos se realiza mediante Hibernate [8].
Hibernate es una herramienta de Mapeo objeto-relacional para la plataforma Java (y
disponible también para .Net con el nombre de NHibernate) que facilita el mapeo de atributos entre
una base de datos relacional tradicional y el modelo de objetos de una aplicación, mediante
archivos declarativos (XML) que permiten establecer estas relaciones. Ver Anexo 1.
Hibernate es software libre, distribuido bajo los términos de la licencia GNU LGPL.
99
Gestión de Análisis Clínicos: Cornalvo
Subcapítulo 9.2: Consulta de los datos almacenados a través de un navegador
Web.
Se añade una nueva capa al clásico diseño en tres capas para implementar el patrón MVC
utilizando Struts. Struts es una herramienta de soporte para el desarrollo de aplicaciones Web bajo
el patrón MVC bajo la plataforma J2EE (Java 2, Enterprise Edition). Struts se desarrollaba como
parte del proyecto Jakarta de la Apache Software Foundation, pero actualmente es un proyecto
independiente conocido como Apache Struts [10].
Struts permite reducir el tiempo de desarrollo. Su carácter de "software libre" y su
compatibilidad con todas las plataformas en que Java Entreprise esté disponible, lo convierte en
una herramienta altamente disponible.
Cada funcionalidad estará representada por una acción. Cuando en la vista se solicite una
acción, el controlador redigirá la petición al action correspondiente que realizará la consulta
solicitada y redirecciona el resultado a la vista asociada.
El software base de desarrollo ha sido eclipse 2.1 con los siguientes plugin:
● Sysdeo Tomcat: Arracando el plugin desde el Tomcat se puede reiniciar, depurar...
● Solar Eclipse: Editor de JSP y XML
● Tomcat como servidor de aplicaciones JSP
JavaServer Pages (JSP) es una tecnología Java que permite generar contenido dinámico para
web, en forma de documentos HTML, XML o de otro tipo [11].
Esta tecnología es un desarrollo de la compañía Sun Microsystems. La Especificación JSP 1.2
fue la primera que se liberó y en la actualidad está disponible la Especificación JSP 2.1.
Las JSP's permiten la utilización de código Java mediante scripts. Además, es posible utilizar
algunas acciones JSP predefinidas mediante etiquetas. Estas etiquetas pueden ser enriquecidas
mediante la utilización de Librerías de Etiquetas (TagLibs o Tag Libraries) externas e incluso
personalizadas. Ver ejemplos ilustrativos en el Anexo 2.
En la capa de acceso a datos tenemos un conjunto de tres clases que proporcionan las utilidades
necesarias:
● DataService : Proporciona utilidades para el acceso a la base de datos.
● DBConnetion: Facilita la conexión a la base de datos. La utiliza internamente DataService.
● Data: Clase que representa a los datos. Cuanto solicitamos datos a DataService, nos facilita
un objeto Data que los contiene.
100
Gestión de Análisis Clínicos: Cornalvo
La conexión a la base de datos se realiza mediante un pool de conexiones. Las base de datos es
Oracle. Ver Anexo 2.3.
A continuación se exponen algunos ejemplos de la visualización de resultados:
101
Gestión de Análisis Clínicos: Cornalvo
102
Ilustración 17: Validación del usuario a través de LDAP
Gestión de Análisis Clínicos: Cornalvo
103
Ilustración 18: Búsqueda de un paciente
Gestión de Análisis Clínicos: Cornalvo
104
Ilustración 19: Listado de pacientes
Gestión de Análisis Clínicos: Cornalvo
105
Ilustración 20: Listado de analíticas
Gestión de Análisis Clínicos: Cornalvo
106
Ilustración 21: Listado de pruebas del laboratorio
Gestión de Análisis Clínicos: Cornalvo
✔ Para las gráficas se ha usado JFreeChart[12] ,una biblioteca de clases Java libre para la
generación de gráficos (GNU LGPL). Incluye: gráficos circulares, gráficas de barras,
gráficos de líneas, gráficos de dispersión, gráficos de series de tiempo, gráficos candlestick,
y más. Uso en aplicaciones, servlets, JSP o applets. Exportar a PNG, JPEG, PDF, HTML y
SVG mapas de imagen. Código fuente completo se incluye, con sujeción a la GNU LGPL.
107
Ilustración 22: Evolutivo de una prueba
Gestión de Análisis Clínicos: Cornalvo
108
Ilustración 23: Comparativa de evolutivos
Gestión de Análisis Clínicos: Cornalvo
Para generar el informe se ha usado Jasper Report [13], una librería para la generación de
informes. Está escrita en java y es libre. El funcionamiento consiste en escribir un xml donde se
recogen las particularidades del informe. Este xml lo tratan las clases del Jasper para obtener una
salida. Esta salida puede ser un PDF, XML, HTML, CSV, XLS, RTF, TXT. Otra ventaja de utilizar
Jasper Report es que se integra perfectamente con el JFreeChart que es una librería libre para la
generación de todo tipo de graficas.
Para generar el xml lo recomendable es bajarse la herramienta iReport que es un editor gráfico
que está implementado en java y se integra perfectamente con el Jasper Report [14].
109
Ilustración 24: Informe de Laboratorio
Gestión de Análisis Clínicos: Cornalvo
Capítulo 10 : Situación actual y líneas futurasActualmente Cornalvo está implantado en cinco de las ocho áreas en las que está divida la
sanidad extremeña. En concreto, el área de Mérida, de Badajoz ,Cáceres, Don Bento y Llerena.
Las otras dos áreas restantes entrarán próximamente en funcionamiento.
En esta primera fase del proyecto como se comentó en la introducción sólo se ha abordado la
transacción LAB-3, queda pendiente, aunque ya se está comenzando a trabajar en ello el resto de
transacciones y actores. Se mantienen reuniones semanales con todos los clínicos de Extremadura
así como contactos con los distintos proveedores comerciales.
En cuanto a requerimientos técnicos se está trabajando también en el transporte JMS, que va ser
sustituido por Web Services, más enfocado hacia la Web e Internet.
Bibliografía1: RevistaeSalud.com, IHE, Integrando la Empresa de Salud2: Notas de implementación de IHE 3: Guía de implementación HL7 Spain4: Estándar HL7 v2.55: java.sun.com/jms (último acceso abril 2010)
110
Ilustración 25: Distribución de áreas del S.E.S
Gestión de Análisis Clínicos: Cornalvo
6: www.openadaptor.org (último acceso marzo 2010)7: http://openjms.sourceforge.net (último acceso mayo 2010)8: www.hibernate.org (último acceso mayo 2010)9: http://hl7api.sourceforge.net (último acceso mayo 2010)10: struts.apache.org (último acceso abril 2010)11: http://java.sun.com/products/jsp (último acceso junio 2010)12: www.jfree.org/jfreechart (último acceso noviembre 2009)13: jasperreports.sourceforge.net (último acceso diciembre 2009)14: http://jasperforge.org/plugins/project/project_home.php?group_id=83 (último acceso enero 2010)
111
Gestión de Análisis Clínicos: Cornalvo
Anexo 1 : Ejemplos de códigos del acumulador del resultados
Anexo 1.1: Código del ORT}/**
* Inicializa una aplicación capaz de procesar un mensaje HL7 * @param applicationConfiguration configuración de la aplicación * @param prefijo * @return aplicación inicializada y configurada * @throws InstantiationException * @throws IllegalAccessException * @throws ClassNotFoundException * @throws IbafException */ private Application cargarAplicacion(SuperProperties
112
Gestión de Análisis Clínicos: Cornalvo
applicationConfiguration) throws InstantiationException, IllegalAccessException, ClassNotFoundException, IbafException { Enumeration claves = applicationConfiguration.keys(); int numClaves = 0; Object[] parametros; ArrayList parametrosAux = new ArrayList(); Properties p = new Properties(); String nombreClase = ""; String nombreAplicacion = ""; Constructor[] constructoresAplicacion = null;
while(claves.hasMoreElements()){ String clave = (String) claves.nextElement(); numClaves++; parametrosAux.add(clave); } parametros = new Object[2];//parametrosAux.size()]; for (int i=0;i<parametrosAux.size();i++){ String clave = (String) parametrosAux.get(i);
if(clave.equalsIgnoreCase("nombre")){ nombreAplicacion = applicationConfiguration.getProperty(clave); parametros[0] = nombreAplicacion; } else if(clave.equalsIgnoreCase("clase")){// p.setProperty(clave, applicationConfiguration.getProperty(clave)); nombreClase = applicationConfiguration.getProperty(clave); } else{
p.setProperty(clave, applicationConfiguration.getProperty(clave)); } } parametros[1] = p; boolean coincidenciaParametros = false; int j = 0;
if (nombreClase != "") { constructoresAplicacion = Class.forName(nombreClase).getConstructors();
while ((!coincidenciaParametros) && (j < constructoresAplicacion.length)){
if (parametros.length == constructoresAplicacion[j].getParameterTypes().length)
coincidenciaParametros = true; else j++; }
} Application aplicacion = null;
if(coincidenciaParametros){
try {aplicacion = (Application)
constructoresAplicacion[j].newInstance(parametros);} catch (IllegalArgumentException e) {
113
Gestión de Análisis Clínicos: Cornalvo
e.printStackTrace();} catch (InstantiationException e) {
e.printStackTrace();} catch (IllegalAccessException e) {
e.printStackTrace();} catch (InvocationTargetException e) {
e.printStackTrace();}
logger.debug("Aplicación " + nombreAplicacion + " cargada e inicializada");
return aplicacion;
} else{ logger.error("Aplicación " + nombreAplicacion + " no cargada"); return null; }
}
/** * Procesa un mensaje delegando en cada una de las aplicaciones configuradas * Utiliza también dos clases preconfiguradas para registrar los mensajes * de entrada y de salida * @param mensaje mensaje HL7 a procesar * @return mensaje de respuesta (ACK) si procede * @throws ApplicationException * @throws HL7Exception */ private Message procesa(Message mensaje) throws ApplicationException, HL7Exception {
Message ack=null;
/* * Proceso del mensaje de entrada NOTA: Aunque manda procesar el mensaje por todas las aplicaciones que puedan hacerlo, solamente devuelve como resultado el mensaje de respuesta de la última aplicación que lo ha procesado */ if (aplicaciones!=null) { if (!aplicaciones.isEmpty()) { Enumeration iterador = aplicaciones.elements(); while (iterador.hasMoreElements()) { Application siguiente = (Application)iterador.nextElement(); if (siguiente.canProcess(mensaje)) { ack = siguiente.processMessage(mensaje); if (ack==null) logger.warn("procesa(Message) : La aplicación " + siguiente.getClass().getName() + "no ha devuelto ACK."); } else logger.warn("procesa(Message) : La aplicación " + siguiente.getClass().getName() + "no puede procesar el mensaje. canProcess(mensaje)=false."); }
114
Gestión de Análisis Clínicos: Cornalvo
} else { logger.warn("procesa(Message): No se configuraron aplicaciones para procesar el mensaje HL7"); } } else { logger.warn("procesa(Message): No se configuraron aplicaciones para procesar el mensaje HL7"); }
return ack; }
/** * Procesa un mensaje HL7 rechazando cualquier mensaje HL7 que no sea para
el * entorno de producción * @param mensajeHL7 * @return */private ACK procesaMensaje(Message mensajeHL7) throws
ApplicationException, HL7Exception {String procID = getProcID(mensajeHL7);ACK ack = null;if ("P".equalsIgnoreCase(procID))
ack = (ACK) procesa(mensajeHL7);else {
logger.warn("procesa(String): El mensaje no es para un entorno de producción (MSH-11=" + procID + "). Se devuelve un ACK de rechazo.");
ack = hacerRespuesta(mensajeHL7);}
return ack;}/**
* Registra un mensaje HL7 con la aplicación de registro de mensajes HL7 * @param mensajeHL7 */ private void registraMensaje(Message mensajeHL7) { try {
if (registroMensaje!=null) { if (registroMensaje.canProcess(mensajeHL7)) { logger.debug("procesa(String): Registrando el mensaje
HL7."); registroMensaje.processMessage(mensajeHL7); } else logger.error("procesa(String) : No se puede registrar el
mensaje. canProcess(mensaje)=false."); } else logger.warn("procesa(String) : No hay aplicación de registro
para registrar el mensaje."); } catch (Exception e) { logger.warn("ORTPipe.procesa(string): No se pudo registrar el mensaje de entrada", e); } }
115
Gestión de Análisis Clínicos: Cornalvo
/** * Registra un mensaje de respuesta con la aplicación de registro de ACK * @param ack */ private void registraACK(Message ack) { try {
if (registroRespuesta!=null) { if (registroRespuesta.canProcess(ack)) { logger.debug("procesa(String): Registrando el mensaje de
respuesta (ACK)."); registroRespuesta.processMessage(ack); } else logger.error("procesa(String) : No se puede registrar el
ACK. canProcess(ACK)=false."); } else logger.warn("procesa(String) : No hay aplicación de registro
para registrar la respuesta (ACK)."); } catch (Exception e) { logger.warn("registraACK(Message): No se pudo registrar la respuesta.", e); } }
/** * Obtiene una codificación HL7 válida a partir del mensaje * @param mensaje * @return Codificación válida */private String getCodificacion(String mensaje) {
String codificacion = analizador.getEncoding(mensaje);
if (codificacion == null) {codificacion = DEFAULT_ENCODING;logger.warn("ORTPipe.procesa(String):No se reconoce una
codificación válida para el mensaje. Utilizando la codificación por defecto (" + codificacion + ").");
}
return codificacion;
}/**
* Construye un mensaje de respuesta ACK (rechazo) a partir de un mensaje HL7 * @param mensaje * @return */ private ACK hacerRespuesta(Message mensaje) {
ACK ack = null;try {
MSH msh = (MSH)mensaje.get("MSH");ack = hacerRespuesta(msh);
} catch (HL7Exception e) {ack = null;
116
Gestión de Análisis Clínicos: Cornalvo
logger.error("hacerRespuesta(Message): No se puede crear el mensaje de respuesta (ACK).", e);
}return ack;
}
/** * Construye un mensaje de respuesta ACK (rechazo) a partir de un mensaje HL7 * @param mensaje * @return */ private ACK hacerRespuesta(String mensaje) {
ACK ack = null;try {
MSH msh = (MSH)analizador.getCriticalResponseData(mensaje);ack = hacerRespuesta(msh);
} catch (HL7Exception e) {ack = null;logger.error("hacerRespuesta(String): No se puede crear el
mensaje de respuesta (ACK). " + e.getLocalizedMessage(), e);}return ack==null?dummyACK():ack;
}
private ACK dummyACK() { ACK ack = new ACK(); try {
ack.getMSH().getSendingApplication().getNamespaceID().setValue("CORNALVO");
ack.getMSH().getSendingFacility().getNamespaceID().setValue("CORNALVO");ack.getMSH().getVersionID().getVersionID().setValue("2.5");
ack.getMSH().getDateTimeOfMessage().getTime().setValue(DateFormat.getInstance().format(new Date()));
ack.getMSA().getAcknowledgmentCode().setValue("AR");} catch (DataTypeException e) {
logger.error("dummyACK(): Error inesperado al crear un ACK vacío. " + e.getLocalizedMessage(), e);
}return ack;
}/**
* Construye un mensaje de respuesta ACK (rechazo) a partir de un segmento MSH * @param mensaje * @return */ private ACK hacerRespuesta(MSH msh) {
ACK ack = null; try {
msh.getVersionID().getVersionID().setValue("2.5");
117
Gestión de Análisis Clínicos: Cornalvo
ack = (ACK) ORTDefaultApplication.makeACK((Segment)msh);MSH mshAck = ack.getMSH();
mshAck.getSendingApplication().getNamespaceID().setValue(aplicacionORT==null?"CORNALVO":aplicacionORT);
String sendingApplication = msh==null?null:msh.getSendingApplication()==null?null:msh.getSendingApplication().getNamespaceID()==null?null:msh.getSendingApplication().getNamespaceID().getValue();
mshAck.getReceivingApplication().getNamespaceID().setValue(sendingApplication);mshAck.getSendingFacility().getNamespaceID().setValue("CORNALVO");String sendingFacility = msh==null?
null:msh.getSendingFacility()==null?null:msh.getSendingFacility().getNamespaceID()==null?null:msh.getSendingFacility().getNamespaceID().getValue();
mshAck.getReceivingFacility().getNamespaceID().setValue(sendingFacility);String triggerEvent = msh==null?null:msh.getMessageType()==null?
null:msh.getMessageType().getTriggerEvent()==null?null:msh.getMessageType().getTriggerEvent().getValue();
mshAck.getMessageType().getTriggerEvent().setValue(triggerEvent);ack.getMSA().getAcknowledgmentCode().setValue("AR");
} catch (IOException e) {ack = null;logger.error("hacerRespuesta(MSH): No se puede crear el
mensaje de respuesta (ACK).", e);} catch (DataTypeException e) {
ack = null;logger.error("hacerRespuesta(MSH): No se puede crear el
mensaje de respuesta (ACK).", e);} catch (HL7Exception e) {
ack = null;logger.error("hacerRespuesta(MSH): No se puede crear el
mensaje de respuesta (ACK).", e);}
return ack;
}
/** * Obtiene el identificador de procesamiento de un mensaje HL7 * @param mensaje * @return */ private String getProcID(Message mensaje) { String procID = null; try {
MSH msh = (MSH) mensaje.get("MSH");procID = msh==null?null:
msh.getProcessingID()==null?null:msh.getProcessingID().getProcessingID()==null?
null:
msh.getProcessingID().getProcessingID().getValue();} catch (HL7Exception e) {
118
Gestión de Análisis Clínicos: Cornalvo
procID = null;logger.error("getProcID(Message): No se puede obtener el
identificador de procesamiento del mensaje HL7.", e);}return procID;
}
/** * Anota un error en el campo de error del segmento ERR de un * mensaje de respuesta (ACK) * @param ack * @param error * @return * @throws HL7Exception */ private ACK anotaError(ACK ack, String error) throws HL7Exception { if ((ack==null) || ack.isEmpty()) throw new HL7Exception("anotaError(ACK, String): El ACK está vacío"); else {
ack.getMSA().getAcknowledgmentCode().setValue("AE"); ack.getERR().getHL7ErrorCode().getIdentifier().setValue("207");
ack.getERR().getHL7ErrorCode().getText().setValue(ORTDefaultApplication.getHl7ErrorText(207));
ack.getERR().getApplicationErrorCode().getText().setValue(error); } return ack; }}
119
Gestión de Análisis Clínicos: Cornalvo
Anexo 1.2: Código del mensaje OUL_R24
package com.comparex.sil.ort.oul;
import ca.uhn.hl7v2.app.ApplicationException;import ca.uhn.hl7v2.model.v25.message.OUL_R24;import ca.uhn.hl7v2.HL7Exception;
import com.comparex.sil.modelo.maestras.CodigoLoinc;import com.comparex.sil.modelo.maestras.hl7.DiagnosticServSectId;import com.comparex.sil.modelo.maestras.hl7.ResultStatus;import com.comparex.sil.modelo.maestras.hl7.SpecimenActionCode;import com.comparex.sil.modelo.metadatos.EntityIdentifierPair;import com.comparex.sil.modelo.metadatos.ExtendedCompositeId;import com.comparex.sil.modelo.metadatos.HierarchicDesignator;import com.comparex.sil.modelo.personas.Interlocutor;import com.comparex.sil.modelo.personas.Paciente;import com.comparex.sil.modelo.personas.UnidadFuncional;import com.comparex.sil.modelo.pruebas.*;
import ca.uhn.hl7v2.model.v25.datatype.CE;import ca.uhn.hl7v2.model.v25.datatype.TS;import ca.uhn.hl7v2.model.v25.group.OUL_R24_CONTAINER;import ca.uhn.hl7v2.model.v25.group.OUL_R24_ORDER;import ca.uhn.hl7v2.model.v25.group.OUL_R24_RESULT;import ca.uhn.hl7v2.model.v25.group.OUL_R24_SPECIMEN;import ca.uhn.hl7v2.model.v25.group.OUL_R24_TIMING_QTY;import ca.uhn.hl7v2.model.v25.segment.OBR;import ca.uhn.hl7v2.model.v25.segment.OBX;import ca.uhn.hl7v2.model.v25.segment.NTE;import ca.uhn.hl7v2.model.v25.segment.MSH;import ca.uhn.hl7v2.model.v25.segment.SPM;
import com.comparex.sil.modelo.ModeloException;import com.comparex.sil.ort.ORTDefaultApplication;import com.comparex.sil.ort.OrtException;
import java.io.IOException;import java.text.ParseException;import java.util.Properties;
import org.hibernate.Transaction;import org.openadaptor.adaptor.Configurable;import ca.uhn.hl7v2.model.DataTypeException;import ca.uhn.hl7v2.model.Message;import ca.uhn.hl7v2.model.Structure;
public class OULR24Application extends ORTDefaultApplication implementsConfigurable {
// private Hashtable configuracion = null;// private Session sesion = null;
/** * Constructor vacío */public OULR24Application() {
120
Gestión de Análisis Clínicos: Cornalvo
}
/** * Constructor * * @param name * @param config */public OULR24Application(String name, Properties config) {
super(name, config);}
/* * (non-Javadoc) * * @see
ca.uhn.hl7v2.app.Application#processMessage(ca.uhn.hl7v2.model.Message) */public Message processMessage(Message mensaje) throws ApplicationException
{
log.debug("Comienzo de procesamiento de mensaje OUL^R24");
// Extraemos los datos del mensajeMessage ack = null;OUL_R24 oul_r24 = (OUL_R24) mensaje;
// es importante crear una transacción, para controlar si todo sale algo
// bien o malTransaction tx = getSesion().beginTransaction();
try {ack = makeACK(oul_r24.getMSH());OrtException incorrecto = esCorrectoMSH(oul_r24.getMSH());
if (incorrecto != null)throw new ApplicationException(
incorrecto.getLocalizedMessage(), incorrecto);
log.info("PROCESANDO MENSAJE OUL_R24 ["+
oul_r24.getMSH().getMessageControlID().getValue() + "]");
if (!ACTIVO.equalsIgnoreCase(configuracion.getProperty(propiedadCambiable))) {
log.warn(this.name
+ ": no se permite alterar la base de datos. Propiedad "
+ propiedadCambiable + " = "+
configuracion.getProperty(propiedadCambiable));return ack;
}
121
Gestión de Análisis Clínicos: Cornalvo
// Unidad Funcional que envia el mensajeHierarchicDesignator unidadEmisora =
toHierarchicDesignator(oul_r24.getMSH()==null?null:oul_r24.getMSH().getSendingFacility());
String nsid = unidadEmisora.getNamespaceId()==null?null:unidadEmisora.getNamespaceId().getCodigo();
UnidadFuncional unidadFuncionalEmisora = nsid == null ? null : factoriaUnidadFuncional(nsid);
if (unidadEmisora != null)getSesion().saveOrUpdate(unidadFuncionalEmisora);
// Obtenemos el pacientePaciente paciente;if (ACTIVO.equalsIgnoreCase(configuracion
.getProperty(propiedadCambiablePaciente))) { // Actualiza
// la BDpaciente =
factoriaPaciente(oul_r24.getPATIENT().getPID());log.debug("processMessage(): Se guarda el paciente ["
+ paciente.getCip().getIdNumber() + "]");if (paciente.borrado())
paciente.activar();getSesion().saveOrUpdate(paciente);
} else { // No actualiza la BDExtendedCompositeId cip = (ExtendedCompositeId) getPIDs(
oul_r24.getPATIENT().getPID().getPatientIdentifierList()).get(
"JHN");paciente = getPaciente(cip);if (paciente == null || paciente.borrado())
throw new OrtException("processMessage(): No se puede dar de
alta a un paciente en la BD, configurado para no alterar la BD de pacientes");}
// Procesamos los datos de las órdenes y sus resultados
int numOrdenes;numOrdenes = oul_r24.getORDERReps();
for (int i = 0; i < numOrdenes; i++) {// gestionamos cada una de las órdenesOUL_R24_ORDER grupoOrden = oul_r24.getORDER(i);EntityIdentifierPair idOrden = toEntityIdentifierPair(
grupoOrden.getOBR().getPlacerOrderNumber(), grupoOrden
.getOBR().getFillerOrderNumber());
if (actualizaOrden(idOrden, toDate(oul_r24.getMSH().getDateTimeOfMessage()))) {
Orden orden = factoriaOrden(grupoOrden.getOBR(), grupoOrden.getORC(), unidadEmisora);
if (orden.getUnidadProveedora() == null) {// La unidad proveedora se toma del msh-3
orden.setUnidadProveedora(unidadFuncionalEmisora);}
122
Gestión de Análisis Clínicos: Cornalvo
if (orden.getFechaEfectiva() == null) { // Si no tenemos la
// fecha efectiva,// tomamos la de la// transacciónTS fechaTransaccion = (grupoOrden.getORC())
.getDateTimeOfTransaction();orden.setFechaEfectiva(fechaTransaccion ==
null ? null: toDate(fechaTransaccion));
}
if (!paciente.equals(orden.getSujeto())) {log.warn("¡Atención! La orden [" +
(orden.getOrderNum()==null?"":orden.getOrderNum().toString()) + "] se ha reasignado al paciente [" + (paciente.getCip()==null?"":paciente.getCip().getIdNumber()) + "]");
}
orden.setSujeto(paciente);
orden.setUltimaActualizacion(toDate(oul_r24.getMSH().getDateTimeOfMessage()));
getSesion().saveOrUpdate(orden);
// Se obtiene la Batería/Test de la ordenCE codLoinc =
grupoOrden.getOBR().getUniversalServiceIdentifier();Object cl = getCodigoLoinc(codLoinc);if (cl==null) {
if (ACTIVO.equalsIgnoreCase(configuracion.getProperty(propiedadLoincOmitir))) {
log.warn("El identificador de servicio de la bateria no es un codigo (LOINC) admitido. Se omite la batería");
continue;}else
throw new ApplicationException("processMessage():Identificador de servicio incorrecto.");
}BateriaTest bateriaTest = orden
.getBateriaTest(cl == null?null: (CodigoLoinc) cl);
// Bateria de la ordenif (bateriaTest == null) {
OBR obr = grupoOrden.getOBR();bateriaTest = factoriaBateriaTest(obr,
unidadEmisora);if (bateriaTest!=null) {
bateriaTest.setOrden(orden);orden.addBateriaTest(bateriaTest);
}} else {
OBR obr = grupoOrden.getOBR();bateriaTest.setBateriaPadre(null);bateriaTest
.setCodigoAccion(obr.getSpecimenActionCode()
.getValue() == null ?
123
Gestión de Análisis Clínicos: Cornalvo
null:
(SpecimenActionCode) getSesion().get(
SpecimenActionCode.class,
obr.getSpecimenActionCode()
.getValue()));bateriaTest
.setEstado(obr.getResultStatus().getValue() == null ? null
: (ResultStatus) getSesion().get(
ResultStatus.class,
obr.getResultStatus()
.getValue()));bateriaTest
.setRecolectorEspecimen(factoriaInterlocutor(((obr
.getCollectorIdentifier() != null) && (obr
.getCollectorIdentifier().length == 0)) ? null
: obr.getCollectorIdentifier()[0], unidadEmisora));
bateriaTest.setSeccionDiagnostico(obr
.getDiagnosticServSectID().getValue() == null ? null
: (DiagnosticServSectId) getSesion()
.get(
DiagnosticServSectId.class,
obr
.getDiagnosticServSectID()
.getValue()));bateriaTest
.setSecuencia(obr.getSetIDOBR().getValue() == null ? 0
: (new Integer(obr.getSetIDOBR()
.getValue())).intValue());
bateriaTest.setValidacionClinica(factoriaInt
erlocutor(obr.getPrincipalResultInterpreter().getNameOfPerson(), unidadEmisora));
}getSesion().saveOrUpdate(bateriaTest);
// Se procesa el espécimen de la Batería/Test
124
Gestión de Análisis Clínicos: Cornalvo
OUL_R24_SPECIMEN oulR24Specimen = grupoOrden.getSPECIMEN();
SPM spm = oulR24Specimen.getSPM();Especimen especimen = null;if ((spm != null) && !spm.isEmpty()) {
especimen = factoriaEspecimen(spm);if (especimen == null)
throw new OrtException("No se puede obtener un
especimen a partir del segmento SPM");
String placerIdSpecimen = especimen.getIdEspecimen() == null ? null
: especimen.getIdEspecimen().getPlacerAssignedIde
ntifier() == null ? null:
especimen.getIdEspecimen().getPlace
rAssignedIdentifier().getEntit
yIdentifier();String fillerIdSpecimen =
especimen.getIdEspecimen() == null ? null: especimen.getIdEspecimen()
.getFillerAssignedIdentifier() == null ? null
: especimen.getIdEspecimen()
.getFillerAssignedIdentifier()
.getEntityIdentifier();
String cipPaciente = paciente == null ? null : paciente
.getCip() == null ? null : paciente.getCip()
.getIdNumber();log.debug(getClass().toString()
+ ".processMessage(): Asociando especimen ["
+ placerIdSpecimen + ":" + fillerIdSpecimen
+ "] al paciente [" + cipPaciente + "]");
especimen.setPaciente(paciente);especimen.addBateriaTest(bateriaTest);bateriaTest.addEspecimen(especimen);getSesion().saveOrUpdate(especimen);
// Procesa las observaciones del especimenint numResultados =
oulR24Specimen.getOBXReps();for (int j = 0; j < numResultados; j++) {
OBX obx = oulR24Specimen.getOBX(j);if ((obx != null) && !obx.isEmpty()) {
// Se asocia la observación al test existente
125
Gestión de Análisis Clínicos: Cornalvo
ObservacionBateriaTest observacion = bateriaTest
.getObservacion(obx.getObser
vationSubID().getValue
());if (observacion == null) {
observacion = new ObservacionBateriaTest(
factoriaObservacion(obx, unidadEmisora));
observacion.setBateriaTest(bateriaTest);
bateriaTest.addObservacion(observacion);} else {
fillObservacion(observacion, obx, unidadEmisora);}
getSesion().saveOrUpdate(observacion);
// Se procesan los comentarios de las
// observaciones del especimenOUL_R24_CONTAINER container =
oulR24Specimen.getCONTAINER();
String[] nombresSegmentos = container
.getNames();boolean nteSi = false;for (int k = 0; (k <
nombresSegmentos.length)&& !nteSi; k++) {
nteSi = "NTE".equals(nombresSegmentos[k]);
}if (nteSi) {
Structure[] ntes = (Structure[]) container
.getAll("NTE");int numNTEs = ntes.length;for (int k = 0; k <
numNTEs; k++) {NTE nte = (NTE)
ntes[k];ComentarioObservacion
comentario = null;if (!nte.isEmpty()) {
int sec = 0;String
secuencia = nte.ge
tSetIDNTE().getValue();if (secuencia !
= null)sec = new
126
Gestión de Análisis Clínicos: Cornalvo
Integer(secuencia)
.intValue();comentario =
observacion.ge
tComentario(sec);
if (comentario == null) {
comentario = new ComentarioObservacion(
getComentario(nte));
comentario
.setObservacion(observacion);
observacion
.addComentario(comentario);} else {
fillComentario(comentario, nte);}getSesion()
.saveOrUpdate(comentario);
}}
}}
}}
// Se procesan los resultados de la orden
// Se procesan las observaciones de TIMING_QUANTITY
// por fallo en análisis sintáctico de HL7API al no aparecer
// SPMprocesaObxQTY(grupoOrden, orden, especimen,
bateriaTest, unidadEmisora);
// Se procesan las observaciones de los resultados
procesaObxResultado(grupoOrden, orden, especimen, bateriaTest, unidadEmisora);
}}
// Nos aseguramos que se actualizan las asociaciones del paciente
// con órdenes y especímenesgetSesion().saveOrUpdate(paciente);
// como todo ha ido bien, hacemos el commit de la transacción
127
Gestión de Análisis Clínicos: Cornalvo
tx.commit();log.info("FIN PROCESO MENSAJE OUL_R24 ["
+ (oul_r24==null?null:oul_r24.getMSH()==null?null:oul_r24.getMSH().getMessageControlID()==null?null:oul_r24.getMSH().getMessageControlID().getValue()) + "] "
+ "] CORRECTO");
} catch (ParseException e) {// algo ha ido mal, hacemos el rollbacktx.rollback();log.error("ProcessMessage(Message): ParseException. " +
e.getLocalizedMessage());log.error("ERROR PROCESO MENSAJE [" +
(oul_r24.getMSH().getMessageControlID().getValue()) + "] ");
fillDetails(ack, "ParseException : " + e.getLocalizedMessage());
} catch (IOException e) {tx.rollback();log.error("ProcessMessage(Message): IOException." +
e.getLocalizedMessage());log.error("ERROR PROCESO MENSAJE [" + (oul_r24==null?
null:oul_r24.getMSH()==null?null:oul_r24.getMSH().getMessageControlID()==null?null:oul_r24.getMSH().getMessageControlID().getValue()) + "] ");
fillDetails(ack, "IOException : " + e.getLocalizedMessage());
} catch (OrtException e) {// algo ha ido mal, hacemos el rollbacktx.rollback();log.error("ProcessMessage(Message): OrtException. " +
e.getLocalizedMessage());log.error("ERROR PROCESO MENSAJE [" + (oul_r24==null?
null:oul_r24.getMSH()==null?null:oul_r24.getMSH().getMessageControlID()==null?null:oul_r24.getMSH().getMessageControlID().getValue()) + "] ");
fillDetails(ack, "OrtException : " + e.getMensaje());} catch (DataTypeException e) {
// algo ha ido mal, hacemos el rollbacktx.rollback();log.error("ProcessMessage(Message): OrtException. " +
e.getLocalizedMessage());log.error("ERROR PROCESO MENSAJE [" + (oul_r24==null?
null:oul_r24.getMSH()==null?null:oul_r24.getMSH().getMessageControlID()==null?null:oul_r24.getMSH().getMessageControlID().getValue()) + "] ");
fillDetails(ack, "DataTypeException : " + e.getLocalizedMessage());
} catch (HL7Exception e) {// algo ha ido mal, hacemos el rollbacktx.rollback();log.error("ProcessMessage(Message): DataTypeException. " +
e.getLocalizedMessage());log.error("ERROR PROCESO MENSAJE [" + (oul_r24==null?
null:oul_r24.getMSH()==null?null:oul_r24.getMSH().getMessageControlID()==null?null:oul_r24.getMSH().getMessageControlID().getValue()) + "] ");
fillDetails(ack, "HL7Exception : " + e.getLocalizedMessage());} catch (ModeloException e) {
128
Gestión de Análisis Clínicos: Cornalvo
// algo ha ido mal, hacemos el rollbacktx.rollback();log.error("ProcessMessage(Message): ModeloException. " +
e.getLocalizedMessage());log.error("ERROR PROCESO MENSAJE [" + (oul_r24==null?
null:oul_r24.getMSH()==null?null:oul_r24.getMSH().getMessageControlID()==null?null:oul_r24.getMSH().getMessageControlID().getValue()) + "] ");
fillDetails(ack, "ModeloException : " + e.getMensaje());} catch (Exception e) {
// algo ha ido mal, hacemos el rollbacktx.rollback();log.error("ProcessMessage(Message): Exception. " +
e.getLocalizedMessage());log.error("ERROR PROCESO MENSAJE [" + (oul_r24==null?
null:oul_r24.getMSH()==null?null:oul_r24.getMSH().getMessageControlID()==null?null:oul_r24.getMSH().getMessageControlID().getValue()) + "] ");
fillDetails(ack, "Exception : " + e.getLocalizedMessage());}
finally {closeSesion();log.debug("Fin de procesamiento de mensaje OUL^R24");
}
return ack;
}
/** * @param obx * @param bateriaTest */private void procesaObxResultado(OUL_R24_ORDER grupoOrden, Orden orden,
Especimen especimen, BateriaTest bateriaTest, HierarchicDesignator unidadAlternativa)
throws ParseException, OrtException, HL7Exception {
OUL_R24_RESULT resultado = grupoOrden.getRESULT();OBX obx = resultado.getOBX();
if (!obx.isEmpty()) {if (bateriaTest.getIdUniversalServicio().getLoincNum().equals(
obx.getObservationIdentifier().getIdentifier().getValue())) {// Se asocia la observación al test existenteObservacionBateriaTest observacion = bateriaTest
.getObservacion(obx.getObservationSubID().getValue());
if (observacion == null) {observacion = new ObservacionBateriaTest(
factoriaObservacion(obx, unidadAlternativa));
observacion.setBateriaTest(bateriaTest);bateriaTest.addObservacion(observacion);
} else {fillObservacion(observacion, obx,
unidadAlternativa);
129
Gestión de Análisis Clínicos: Cornalvo
}getSesion().saveOrUpdate(observacion);
// Se procesan los comentarios del resultadoint numNTEs = resultado.getNTEReps();for (int k = 0; k < numNTEs; k++) {
NTE nte = resultado.getNTE(k);ComentarioObservacion comentario = null;if (!nte.isEmpty()) {
int sec = 0;String secuencia =
nte.getSetIDNTE().getValue();if (secuencia != null)
sec = new Integer(secuencia).intValue();
comentario = observacion.getComentario(sec);
if (comentario == null) {comentario = new
ComentarioObservacion(getComentario(nte));
comentario.setObservacion(observacion);observacion.addComentario(comentario);
} else {fillComentario(comentario, nte);
}getSesion().saveOrUpdate(comentario);
}}
} else {// Se crea un nuevo test asociado a la batería y se
asocia la// observación al testCodigoLoinc codigo = obx.getObservationIdentifier()
.getIdentifier().getValue() == null ? null:
getCodigoLoinc(obx.getObservationIdentifier().getIdentifier().getValue());
BateriaTest test = orden.getBateriaTest(codigo);if (test == null) {
test = factoriaBateriaTest(grupoOrden.getOBR(), unidadAlternativa);
test.setOrden(orden);orden.addBateriaTest(bateriaTest);test.getEspecimenes().add(especimen);especimen.addBateriaTest(bateriaTest);
} else {// Se actualiza el test existenteOBR obr = grupoOrden.getOBR();test.setBateriaPadre(bateriaTest);test
.setCodigoAccion(obr.getSpecimenActionCode()
.getValue() == null ? null: (SpecimenActionCode)
getSesion().get(
130
Gestión de Análisis Clínicos: Cornalvo
SpecimenActionCode.class,
obr.getSpecimenActionCode().ge
tValue()));test
.setEstado(obr.getResultStatus().getValue() == null ? null
: (ResultStatus) getSesion().get(
ResultStatus.class,
obr.getResultStatus().getValue()));if (obr.getCollectorIdentifier().length == 0)
test.setRecolectorEspecimen(null);else
test.setRecolectorEspecimen(factoriaInterlocutor(obr.getCollectorIdentifier(0),
unidadAlternativa));
test.setSeccionDiagnostico(obr.getDiagnosticServSectID().getValue() == null ? null: (DiagnosticServSectId)
getSesion().get(DiagnosticServSectId.class,
obr.getDiagnosticServSectID().getValue()));test.setSecuencia(obr.getSetIDOBR().getValue() ==
null ? 0: (new
Integer(obr.getSetIDOBR().getValue())).intValue());
test.setValidacionClinica(factoriaInterloc
utor(obr.getPrincipalResultInterpre
ter().getNameOfPerson(),
unidadAlternativa));}getSesion().saveOrUpdate(bateriaTest);
// Se asocia la observación al test existenteObservacionBateriaTest observacion =
test.getObservacion(obx.getObservationSubID().getValue());
if (observacion == null) {observacion = new ObservacionBateriaTest(
factoriaObservacion(obx, unidadAlternativa));
observacion.setBateriaTest(test);} else {
fillObservacion(observacion, obx, unidadAlternativa);
}getSesion().saveOrUpdate(observacion);
131
Gestión de Análisis Clínicos: Cornalvo
// Se procesan los comentarios del resultadoint numNTEs = resultado.getNTEReps();for (int k = 0; k < numNTEs; k++) {
NTE nte = resultado.getNTE(k);ComentarioObservacion comentario = null;if (!nte.isEmpty()) {
int sec = 0;String secuencia =
nte.getSetIDNTE().getValue(); // NTE-1:// Secuenciaif (secuencia != null)
sec = new Integer(secuencia).intValue();
comentario = observacion.getComentario(sec);if (comentario == null) {
comentario = new ComentarioObservacion(
getComentario(nte));
comentario.setObservacion(observacion);observacion.addComentario(comentario);
} else {fillComentario(comentario, nte);
}getSesion().saveOrUpdate(comentario);
}}
}}
}
void procesaObxQTY(OUL_R24_ORDER grupoOrden, Orden orden,Especimen especimen, BateriaTest bateriaTest,
HierarchicDesignator unidadAlternativa)throws DataTypeException, OrtException, ParseException,HL7Exception {
OUL_R24_TIMING_QTY timing_Qty = grupoOrden.getTIMING_QTY();String[] segmentNames = timing_Qty.getNames();// OBX[] obxs = (OBX[])timing_Qty.getAll("OBX");// NTE[] ntes = (NTE[])timing_Qty.getAll("NTE");int cOBXs = 0, cNTEs = 0;OBX obx = null;ObservacionBateriaTest observacion = null;for (int i = 0; i < segmentNames.length; i++) {
if ("OBX".equals(segmentNames[i])) {obx = (OBX) timing_Qty.get("OBX", cOBXs++);if (!obx.isEmpty()) {
String codigoLoincBateria = bateriaTest == null ? null
: bateriaTest.getIdUniversalServicio() == null ? null
: bateriaTest.getIdUniversalServicio()
.getLoincNum();String codigoLoincObservacion = obx == null ? null
: obx.getObservationIdentifier() == null ? null
132
Gestión de Análisis Clínicos: Cornalvo
: obx.getObservationIdentifier()
.getIdentifier() == null ? null : obx
.getObservationIdentifier()
.getIdentifier().getValue();
if (codigoLoincBateria.equals(codigoLoincObservacion)) {
// Se asocia la observación al test existente
observacion = bateriaTest.getObservacion(obx.getObservationSubID().getValue()
);if (observacion == null) {
observacion = new ObservacionBateriaTest(
factoriaObservacion(obx, unidadAlternativa));
observacion.setBateriaTest(bateriaTest);
bateriaTest.addObservacion(observacion);} else {
fillObservacion(observacion, obx, unidadAlternativa);
}getSesion().saveOrUpdate(observacion);
} else {// Se crea un nuevo test asociado a la
batería y se// asocia la observación al testCodigoLoinc codigo =
obx.getObservationIdentifier().getIdentifier().getValue() ==
null ? null:
getCodigoLoinc(obx.getObservationIdentifier().getIdentifier().getV
alue());BateriaTest test =
orden.getBateriaTest(codigo);if (test == null) {
test = factoriaBateriaTest(grupoOrden.getOBR(), unidadAlternativa);
test.setOrden(orden);orden.addBateriaTest(bateriaTest);if (especimen != null) {
test.getEspecimenes().add(especimen);
especimen.addBateriaTest(bateriaTest);}
} else {// Se actualiza el test existenteOBR obr = grupoOrden.getOBR();test.setBateriaPadre(bateriaTest);
133
Gestión de Análisis Clínicos: Cornalvo
test.setCodigoAccion(obr.getSpecimenActionCode().getValue() == null ? null: (SpecimenActionCode)
getSesion().get(
SpecimenActionCode.class,
obr.getSpecimenActionCode().ge
tValue()));test
.setEstado(obr.getResultStatus().getValue() == null ? null
: (ResultStatus) getSesion().get(
ResultStatus.class,
obr.getResultStatus()
.getValue()));if
(obr.getCollectorIdentifier().length == 0)
test.setRecolectorEspecimen(null);else
test.setRecolectorEspecimen(factoriaInterlocutor(obr.getColle
ctorIdentifier(0), unidadAlternativa));test.setSeccionDiagnostico(obr
.getDiagnosticServSectID()
.getValue() == null ? null
: (DiagnosticServSectId) getSesion()
.get(
DiagnosticServSectId.class,
obr
.getDiagnosticServSectID()
.getValue()));
test.setSecuencia(obr.getSetIDOBR().getValue() == null ? 0: (new
Integer(obr.getSetIDOBR().ge
tValue())).intValue());Interlocutor validadorClinico =
factoriaInterlocutor(obr.getPrincipalResultInterpreter().getNameOfPerson(), unidadAlternativa);
test.setValidacionClinica(validadorClinico);}
134
Gestión de Análisis Clínicos: Cornalvo
getSesion().saveOrUpdate(bateriaTest);
// Se asocia la observación al test existente
observacion = test.getObservacion(obx.getObservationSubID().getValue()
);if (observacion == null) {
observacion = new ObservacionBateriaTest(
factoriaObservacion(obx, unidadAlternativa));
observacion.setBateriaTest(test);} else {
fillObservacion(observacion, obx, unidadAlternativa);
}getSesion().saveOrUpdate(observacion);
}} else if ("NTE".equals(segmentNames[i])) {
NTE nte = (NTE) timing_Qty.get("NTE", cNTEs++);ComentarioObservacion comentario = null;if (!nte.isEmpty()) {
int sec = 0;String secuencia =
nte.getSetIDNTE().getValue(); // NTE-1:// Secuenciaif (secuencia != null)
sec = new Integer(secuencia).intValue();
comentario = observacion.getComentario(sec);
if (comentario == null) {comentario = new
ComentarioObservacion(getComentario(nte));
comentario.setObservacion(observacion);observacion.addComentario(comentario);
} else {fillComentario(comentario, nte);
}getSesion().saveOrUpdate(comentario);
}}
}}
}
/* * (non-Javadoc) * * @see
ca.uhn.hl7v2.app.DefaultApplication#canProcess(ca.uhn.hl7v2.model.Message) */public boolean canProcess(Message in) {
if (in == null)
135
Gestión de Análisis Clínicos: Cornalvo
return false;
boolean canDoIt = false;try {
MSH msh = (MSH) in.get("MSH");canDoIt = (esCorrectoMSH(msh) == null)
&& msh.getMessageType().getMessageCode().getValue()
.equalsIgnoreCase("OUL")&&
msh.getMessageType().getTriggerEvent().getValue().equalsIgnoreCase("R24");
} catch (HL7Exception e) {log.error(e.getMessage());
}return canDoIt;
}
}
136
Gestión de Análisis Clínicos: Cornalvo
Anexo 1.3: Configuración de Hibernate
<?xml version='1.0' encoding='utf-8'?><!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration><session-factory>
<property name="cache.provider_class">org.hibernate.cache.TreeCacheProvider
</property><property name="hibernate.cache.use_minimal_puts">false</property><!--use_minimal_puts->true--><!-- <property
name="connection.datasource">java:/comp/env/jdbc/PoolServlet</property> --><!--<property
name="connection.datasource">java:/comp/env/jdbc/cornalvo</property>--><property
name="hibernate.connection.driver_class">oracle.jdbc.driver.OracleDriver</property>
<property name="hibernate.connection.url">jdbc:oracle:thin:@cornalvo_db.ses.rts:1521:cornalvo</property><!-- <property name="hibernate.connection.url">jdbc:oracle:thin:@localhost:1521:RTDB</property> --><!-- <property name="hibernate.connection.url">jdbc:oracle:thin:@10.15.168.50:1521:RTDB</property> -->
<property name="hibernate.connection.username">c2</property><property name="hibernate.connection.password">c2</property>
<!-- <property name="hibernate.connection.username">cornalvo</property><property name="hibernate.connection.password">cornalvo</property>
--><property name="hibernate.connection.pool_size">10</property><!--<property name="show_sql">true</property>--><property
name="dialect">org.hibernate.dialect.OracleDialect</property><property name="hibernate.dbcp.maxWait">300</property><property name="hibernate.dbcp.maxIdle">10</property><property name="hibernate.dbcp.maxActive">100</property> <!--<property name="hibernate.hbm2ddl.auto">update</property> -->
<!-- Mapping files -->
<!--Tablas Maestras-->
<mapping resource="com/comparex/sil/modelo/maestras/ClaseLoinc.hbm.xml"/>
<mapping resource="com/comparex/sil/modelo/maestras/CodigoLoinc.hbm.xml"/>
<mapping resource="com/comparex/sil/modelo/maestras/GrupoLoinc.hbm.xml"/>
<mapping resource="com/comparex/sil/modelo/maestras/SistemaLoinc.hbm.xml"/>
<mapping
137
Gestión de Análisis Clínicos: Cornalvo
resource="com/comparex/sil/modelo/maestras/TablaHL7.hbm.xml"/>
<mapping resource="com/comparex/sil/modelo/maestras/hl7/AcknowledgmentCode.hbm.xml"/>
<mapping resource="com/comparex/sil/modelo/maestras/hl7/CodingSystem.hbm.xml"/>
<mapping resource="com/comparex/sil/modelo/maestras/hl7/NamespaceId.hbm.xml"/>
<mapping resource="com/comparex/sil/modelo/maestras/hl7/Aplicacion.hbm.xml"/>
<mapping resource="com/comparex/sil/modelo/maestras/hl7/Centro.hbm.xml"/>
<mapping resource="com/comparex/sil/modelo/maestras/hl7/UniversalIdType.hbm.xml"/>
<mapping resource="com/comparex/sil/modelo/maestras/hl7/MessageCode.hbm.xml"/>
<mapping resource="com/comparex/sil/modelo/maestras/hl7/TriggerEvent.hbm.xml"/>
<mapping resource="com/comparex/sil/modelo/maestras/hl7/MessageStructure.hbm.xml"/>
<mapping resource="com/comparex/sil/modelo/maestras/hl7/Severity.hbm.xml"/>
<mapping resource="com/comparex/sil/modelo/maestras/hl7/SpecimenActionCode.hbm.xml"/>
<mapping resource="com/comparex/sil/modelo/maestras/hl7/ResultStatus.hbm.xml"/>
<mapping resource="com/comparex/sil/modelo/maestras/hl7/AbnormalFlag.hbm.xml"/>
<mapping resource="com/comparex/sil/modelo/maestras/hl7/AdministrativeSex.hbm.xml"/>
<mapping resource="com/comparex/sil/modelo/maestras/hl7/CommentType.hbm.xml"/>
<mapping resource="com/comparex/sil/modelo/maestras/hl7/DiagnosticServSectId.hbm.xml"/>
<mapping resource="com/comparex/sil/modelo/maestras/hl7/CheckDigitScheme.hbm.xml"/>
<mapping resource="com/comparex/sil/modelo/maestras/hl7/IdentifierType.hbm.xml"/>
<mapping resource="com/comparex/sil/modelo/maestras/hl7/OrganizationalNameType.hbm.xml"/>
<mapping resource="com/comparex/sil/modelo/maestras/hl7/NameRepresentation.hbm.xml"/>
<mapping resource="com/comparex/sil/modelo/maestras/hl7/AssigningAuthorityCode.hbm.xml"/>
<mapping resource="com/comparex/sil/modelo/maestras/hl7/ObservationResultStatus.hbm.xml"/>
<mapping resource="com/comparex/sil/modelo/maestras/hl7/OrderStatus.hbm.xml"/>
<mapping resource="com/comparex/sil/modelo/maestras/hl7/SourceOfComment.hbm.xml"/>
<mapping resource="com/comparex/sil/modelo/maestras/hl7/SpecimenAvailability.hbm.xml"/>
<mapping resource="com/comparex/sil/modelo/maestras/hl7/ValueType.hbm.xml"/>
<mapping
138
Gestión de Análisis Clínicos: Cornalvo
resource="com/comparex/sil/modelo/maestras/hl7/VersionHl7.hbm.xml"/>
<!-- Tablas Pruebas -->
<mapping resource="com/comparex/sil/modelo/pruebas/BateriaTest.hbm.xml"/>
<mapping resource="com/comparex/sil/modelo/pruebas/Comentario.hbm.xml"/>
<mapping resource="com/comparex/sil/modelo/pruebas/Especimen.hbm.xml"/>
<mapping resource="com/comparex/sil/modelo/pruebas/Observacion.hbm.xml"/>
<mapping resource="com/comparex/sil/modelo/pruebas/Orden.hbm.xml"/>
<!--Tablas Pacientes -->
<mapping resource="com/comparex/sil/modelo/personas/Persona.hbm.xml"/>
<mapping resource="com/comparex/sil/modelo/personas/Responsabilidad.hbm.xml"/>
<mapping resource="com/comparex/sil/modelo/personas/Visita.hbm.xml"/>
<mapping resource="com/comparex/sil/modelo/personas/UnidadFuncional.hbm.xml"/>
<!-- Tablas Registro Mensajes -->
<mapping resource="com/comparex/sil/modelo/log/Mensaje.hbm.xml"/>
<!--************************************--><!--************************************--><!--************************************--><!-- Configurando la Caché de 2º Nivel --><!--************************************--><!--************************************--><!--************************************--><!--Tablas Maestras--><class-cache
class="com.comparex.sil.modelo.maestras.ClaseLoinc" usage="transactional"/>
<class-cache class="com.comparex.sil.modelo.maestras.CodigoLoinc" usage="transactional"/>
<class-cache class="com.comparex.sil.modelo.maestras.GrupoLoinc" usage="transactional"/><collection-cache
collection="com.comparex.sil.modelo.maestras.GrupoLoinc.codigosLoinc"
usage="transactional"/><class-cache
class="com.comparex.sil.modelo.maestras.TablaHL7" usage="transactional"/>
<!--<class-cache class="com.comparex.sil.modelo.maestras.ValorHL7" usage="transactional"/>
139
Gestión de Análisis Clínicos: Cornalvo
-->
<class-cache class="com.comparex.sil.modelo.maestras.hl7.AcknowledgmentCode" usage="transactional"/>
<class-cache class="com.comparex.sil.modelo.maestras.hl7.CodingSystem" usage="transactional"/>
<class-cache class="com.comparex.sil.modelo.maestras.hl7.NamespaceId"
usage="transactional"/><class-cache
class="com.comparex.sil.modelo.maestras.hl7.Aplicacion" usage="transactional" /><class-cache
class="com.comparex.sil.modelo.maestras.hl7.Centro" usage="transactional"/><class-cache
class="com.comparex.sil.modelo.maestras.hl7.UniversalIdType" usage="transactional"/>
<class-cache class="com.comparex.sil.modelo.maestras.hl7.MessageCode" usage="transactional"/>
<class-cache class="com.comparex.sil.modelo.maestras.hl7.TriggerEvent" usage="transactional"/>
<class-cache class="com.comparex.sil.modelo.maestras.hl7.MessageStructure" usage="transactional"/>
<class-cache class="com.comparex.sil.modelo.maestras.hl7.Severity" usage="transactional"/>
<class-cache class="com.comparex.sil.modelo.maestras.hl7.SpecimenActionCode" usage="transactional"/>
<class-cache class="com.comparex.sil.modelo.maestras.hl7.ResultStatus" usage="transactional"/>
<class-cache class="com.comparex.sil.modelo.maestras.hl7.AbnormalFlag" usage="transactional"/>
<class-cache class="com.comparex.sil.modelo.maestras.hl7.AdministrativeSex" usage="transactional"/>
<class-cache class="com.comparex.sil.modelo.maestras.hl7.CommentType" usage="transactional" />
<class-cache class="com.comparex.sil.modelo.maestras.hl7.DiagnosticServSectId" usage="transactional"/>
<class-cache class="com.comparex.sil.modelo.maestras.hl7.ObservationResultStatus" usage="transactional"/>
<class-cache class="com.comparex.sil.modelo.maestras.hl7.OrderStatus" usage="transactional" />
<class-cache class="com.comparex.sil.modelo.maestras.hl7.SourceOfComment" usage="transactional" />
<class-cache
140
Gestión de Análisis Clínicos: Cornalvo
class="com.comparex.sil.modelo.maestras.hl7.SpecimenAvailability" usage="transactional" />
<class-cache class="com.comparex.sil.modelo.maestras.hl7.ValueType" usage="transactional" />
<class-cache class="com.comparex.sil.modelo.maestras.hl7.VersionHl7" usage="transactional" />
<!-- Tablas Pruebas --><class-cache
class="com.comparex.sil.modelo.pruebas.BateriaTest" usage="transactional"/><collection-cache
collection="com.comparex.sil.modelo.pruebas.BateriaTest.especimenes"
usage="transactional"/><collection-cache
collection="com.comparex.sil.modelo.pruebas.BateriaTest.observaciones"
usage="transactional"/>
<class-cache class="com.comparex.sil.modelo.pruebas.Comentario" usage="transactional"/>
<!-- <class-cache
class="com.comparex.sil.modelo.pruebas.ComentarioObservacion" usage="transactional"/>
--><!--<class-cache
class="com.comparex.sil.modelo.pruebas.ComentarioBateriaTest" usage="transactional"/>
<class-cache class="com.comparex.sil.modelo.pruebas.ComentarioBateriaTest" usage="transactional"/>
-->
<class-cache class="com.comparex.sil.modelo.pruebas.Especimen" usage="transactional"/>
<collection-cache
collection="com.comparex.sil.modelo.pruebas.Especimen.bateriasTests" usage="transactional"/>
<collection-cache
collection="com.comparex.sil.modelo.pruebas.Especimen.observaciones" usage="transactional"/>
<class-cache
141
Gestión de Análisis Clínicos: Cornalvo
class="com.comparex.sil.modelo.pruebas.Observacion" usage="transactional"/>
<collection-cache
collection="com.comparex.sil.modelo.pruebas.Observacion.comentarios"usage="transactional"/>
<!--<class-cache
class="com.comparex.sil.modelo.pruebas.ObservacionBateriaTest"usage="transactional"/>
<class-cache class="com.comparex.sil.modelo.pruebas.ObservacionEspecimen"
usage="transactional"/>-->
<class-cache class="com.comparex.sil.modelo.pruebas.Orden" usage="transactional"/><collection-cache
collection="com.comparex.sil.modelo.pruebas.Orden.baterias"usage="transactional"/>
<!--Tablas Pacientes --><class-cache
class="com.comparex.sil.modelo.personas.Persona" usage="transactional"/>
<!--<class-cache
class="com.comparex.sil.modelo.personas.Paciente" usage="transactional"/>
-->
<collection-cache collection="com.comparex.sil.modelo.personas.Paciente.ordenes"
usage="transactional"/><collection-cache
collection="com.comparex.sil.modelo.personas.Paciente.especimenes" usage="transactional"/>
<!--<class-cache
class="com.comparex.sil.modelo.personas.Interlocutor" usage="transactional"/>
--><collection-cache
collection="com.comparex.sil.modelo.personas.Interlocutor.puestos"usage="transactional"/>
<collection-cache
142
Gestión de Análisis Clínicos: Cornalvo
collection="com.comparex.sil.modelo.personas.Interlocutor.ordenesRegistradas"usage="transactional"/>
<collection-cache
collection="com.comparex.sil.modelo.personas.Interlocutor.ordenesPrescritas"usage="transactional"/>
<collection-cache
collection="com.comparex.sil.modelo.personas.Interlocutor.ordenesValidadas"usage="transactional"/>
<collection-cache
collection="com.comparex.sil.modelo.personas.Interlocutor.bateriasValidadas"usage="transactional"/>
<collection-cache
collection="com.comparex.sil.modelo.personas.Interlocutor.observacionesValidadas"
usage="transactional"/>
<class-cache class="com.comparex.sil.modelo.personas.Responsabilidad" usage="transactional"/>
<collection-cache
collection="com.comparex.sil.modelo.personas.Responsabilidad.interlocutores" usage="transactional"/>
<class-cache class="com.comparex.sil.modelo.personas.UnidadFuncional" usage="transactional"/>
<class-cache class="com.comparex.sil.modelo.personas.Visita" usage="transactional"/><collection-cache
collection="com.comparex.sil.modelo.personas.Visita.responsabilidades"
usage="transactional"/>
<!-- Tablas Mensajeria --><class-cache
class="com.comparex.sil.modelo.log.Mensaje" usage="transactional"/><!--<class-cache
class="com.comparex.sil.modelo.log.MensajeOULR22"usage="transactional"/>
--><collection-cache
collection="com.comparex.sil.modelo.log.MensajeOULR22.especimenes" usage="transactional"/>
<!--
143
Gestión de Análisis Clínicos: Cornalvo
<class-cacheclass="com.comparex.sil.modelo.log.MensajeOULR24"usage="transactional"/>
--><collection-cache
collection="com.comparex.sil.modelo.log.MensajeOULR24.ordenes" usage="transactional"/>
<!--<class-cache
class="com.comparex.sil.modelo.log.MensajeACK"usage="transactional"/>
-->
</session-factory>
</hibernate-configuration>
Anexo 2 : Ejemplos de códigos de struts
Anexo 2.1: Código del Action buscar pacientes
package com.comparex.sil.struts.action;
import java.util.ArrayList;import java.util.List;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import javax.servlet.http.HttpSession;
import com.comparex.sil.log.AccesoWeb;import com.comparex.sil.log.RegistroAcceso;
import org.apache.log4j.Logger;import org.apache.struts.action.ActionForm;import org.apache.struts.action.ActionForward;import org.apache.struts.action.ActionMapping;import org.hibernate.*;
import com.comparex.sil.struts.form.BuscarPacientesForm;import com.comparex.sil.consulta.ConsultaFactory;import com.comparex.sil.consulta.PacienteBuscarVista;
public class BuscarPacientesAction extends org.apache.struts.action.Action {
private static Logger log = Logger.getLogger("AppLogger");
public ActionForward execute(ActionMapping mapping, ActionForm form,HttpServletRequest request, HttpServletResponse response)throws Exception {
String CIP;String nombre;String apellido1;String apellido2;
144
Gestión de Análisis Clínicos: Cornalvo
String analiticas;int idArea;long comienzo, fin;comienzo = System.currentTimeMillis();HttpSession httpsesion = request.getSession();Session session = null;String result;try {
// SessionFactory sessionFactory = (SessionFactory) httpsesion// .getServletContext().getAttribute("HibernateFactory");//// Session session = sessionFactory.openSession();session = ((SessionFactory) httpsesion.getServletContext()
.getAttribute("HibernateFactoryModelo")).openSession();
BuscarPacientesForm BPform = (BuscarPacientesForm) form;CIP = BPform.getCIP();nombre = BPform.getNombre();apellido1 = BPform.getApellido1();apellido2 = BPform.getApellido2();analiticas = BPform.getAnaliticas();idArea = BPform.getIdArea();
// Pasamos todas las variables a mayúsculas para que ORACLE nos
// devuelta TODOS los resultados// nombre = nombre.toUpperCase();// apellido1 = apellido1.toUpperCase();// apellido2 = apellido2.toUpperCase();// sexo = sexo.toUpperCase();
// creamos el paciente con los datos que estamos buscandoPacienteBuscarVista pbv = new PacienteBuscarVista();pbv.setApellido1(apellido1);pbv.setApellido2(apellido2);pbv.setNombre(nombre);pbv.setIdentificador(CIP);httpsesion.setAttribute("pacienteBuscar", pbv);httpsesion.setAttribute("inicio", "false");
List pacientes;
ConsultaFactory consultaFactory = new ConsultaFactory();consultaFactory.setHibernateSession(session);// pacientes = consultaFactory.consultaPacientes(CIP, nombre,// apellido1, apellido2, analiticas, idArea);
pacientes = consultaFactory.consultaPacientes(CIP, nombre,apellido1, apellido2, analiticas, idArea);
httpsesion.setAttribute("TotalQuery", System.getProperty("TotalQuery"));
httpsesion.setAttribute("pacientes", pacientes);fin = System.currentTimeMillis();ArrayList areas = consultaFactory.dameAreas();
httpsesion.setAttribute("areas", areas);
145
Gestión de Análisis Clínicos: Cornalvo
// RegistroAcceso registro = RegistroAcceso.getRegistroAcceso(log,// (Session) httpsesion.getServletContext()// .getAttribute("HibernateFactoryRegistro"));
SessionFactory sessionFRegistro = (SessionFactory) httpsesion.getServletContext().getAttribute("HibernateFactoryRegistro");
RegistroAcceso registro = new RegistroAcceso();registro.setLog(log);registro.setFactoriaSesiones(sessionFRegistro);
AccesoWeb acceso = registro.nuevoAcceso((String) httpsesion.getAttribute("usuario"), request.getRequestURL().toString(), null, fin - comienzo, true);
acceso.setOrigen(request.getRemoteHost() + "["+ request.getRemoteAddr() + "]");
acceso.setServidor(request.getServerName());registro.registrar(acceso);
// EscribirLog.escribirLog(log, "BuscarPacientes",// request.getRemoteAddr(),// request.getRemoteHost(),// (String)httpsesion.getAttribute("nombre_completo"),// true, fin - comienzo);
// session.flush();//liberamos recursos de sesionresult = "pacientes";
} catch (Exception e) {result = "error";fin = System.currentTimeMillis();// Hecho por JUANLU para controlar erroesif(httpsesion != null) {
httpsesion.setAttribute("TotalQuery", null);httpsesion.setAttribute("pacientes", null);httpsesion.setAttribute("areas", null);
}
e.printStackTrace();// RegistroAcceso registro = RegistroAcceso.getRegistroAcceso(log,// (Session) httpsesion.getServletContext()// .getAttribute("HibernateFactoryRegistro"));
SessionFactory sessionFRegistro = (SessionFactory) httpsesion.getServletContext().getAttribute("HibernateFactoryRegistro");
RegistroAcceso registro = new RegistroAcceso();registro.setLog(log);registro.setFactoriaSesiones(sessionFRegistro);
AccesoWeb acceso = registro.nuevoAcceso((String) httpsesion.getAttribute("usuario"), request.getRequestURL().toString(), null, fin - comienzo, false);
acceso.setOrigen(request.getRemoteHost() + "["+ request.getRemoteAddr() + "]");
acceso.setServidor(request.getServerName());registro.registrar(acceso);// EscribirLog.escribirLog(log, "BuscarPacientes",// request.getRemoteAddr(),
146
Gestión de Análisis Clínicos: Cornalvo
// request.getRemoteHost(),// (String)httpsesion.getAttribute("nombre_completo"),// true, fin - comienzo);
}finally {
if (session!=null)try {
session.close();} catch (Exception e) {
e.printStackTrace();}
}
return (mapping.findForward(result));}
147
Gestión de Análisis Clínicos: Cornalvo
Anexo 2.2: Código del Form buscar pacientes
package com.comparex.sil.struts.form;
import javax.servlet.http.HttpServletRequest;
import org.apache.struts.action.ActionErrors;import org.apache.struts.action.ActionMapping;import org.apache.struts.action.ActionMessage;
public class BuscarPacientesForm extends org.apache.struts.action.ActionForm {
/** * */private static final long serialVersionUID = 1L;private String CIP;private String nombre;private String apellido1;private String apellido2;private String fechaNacimiento;private String sexo;private String analiticas;private int idArea;private int idCentro;private String fechaInicio;private String fechaFin;
public BuscarPacientesForm () { }
public void reset(ActionMapping actionMapping, HttpServletRequest request) { this.CIP = "";
this.nombre = "";this.apellido1 = "";this.apellido2 = "";this.sexo = "";this.fechaNacimiento = "";
}
public ActionErrors validate(ActionMapping actionMapping, HttpServletRequest request) { ActionErrors errors = new ActionErrors(); if (
((this.CIP == null) ||(this.CIP.length() < 1)
) &&(
(this.nombre == null) ||(this.nombre.length() < 1)
) &&(
(this.apellido1 == null) ||(this.apellido1.length() < 1)
) &&(
148
Gestión de Análisis Clínicos: Cornalvo
(this.apellido2 == null) ||(this.apellido2.length() < 1)
)) {errors.add("paciente", new
ActionMessage("com.comparex.sil.patientFilterForm.error.vacio"));
}return errors;
}
/** * @return Returns the apellido1. */public String getApellido1() {
return apellido1;}
/** * @param apellido1 The apellido1 to set. */public void setApellido1(String apellido1) {
this.apellido1 = apellido1;}
/** * @return Returns the apellido2. */public String getApellido2() {
return apellido2;}
/** * @param apellido2 The apellido2 to set. */public void setApellido2(String apellido2) {
this.apellido2 = apellido2;}
/** * @return Returns the cIP. */public String getCIP() {
return CIP;}
/** * @param cip The cIP to set. */public void setCIP(String cip) {
CIP = cip;}
/** * @return Returns the fechaNacimiento. */public String getFechaNacimiento() {
return fechaNacimiento;}
149
Gestión de Análisis Clínicos: Cornalvo
/** * @param fechaNacimiento The fechaNacimiento to set. */public void setFechaNacimiento(String fechaNacimiento) {
this.fechaNacimiento = fechaNacimiento;}
/** * @return Returns the nombre. */public String getNombre() {
return nombre;}
/** * @param nombre The nombre to set. */public void setNombre(String nombre) {
this.nombre = nombre;}
/** * @return Returns the sexo. */public String getSexo() {
return sexo;}
/** * @param sexo The sexo to set. */public void setSexo(String sexo) {
this.sexo = sexo;}
/** * @return Returns the analiticas. */public String getAnaliticas() {
return analiticas;}
/** * @param analiticas The analiticas to set. */public void setAnaliticas(String analiticas) {
this.analiticas = analiticas;}
/** * @return Returns the idArea. */public int getIdArea() {
return idArea;}
150
Gestión de Análisis Clínicos: Cornalvo
/** * @param idArea The idArea to set. */public void setIdArea(int idArea) {
this.idArea = idArea;}
/** * @return el idCentro */public int getIdCentro() {
return idCentro;}
/** * @param idCentro el idCentro a establecer */public void setIdCentro(int idCentro) {
this.idCentro = idCentro;}
/** * @return el fechaFin */public String getFechaFin() {
return fechaFin;}
/** * @param fechaFin el fechaFin a establecer */public void setFechaFin(String fechaFin) {
this.fechaFin = fechaFin;}
/** * @return el fechaInicio */public String getFechaInicio() {
return fechaInicio;}
/** * @param fechaInicio el fechaInicio a establecer */public void setFechaInicio(String fechaInicio) {
this.fechaInicio = fechaInicio;}
151
Gestión de Análisis Clínicos: Cornalvo
Anexo 2.3: Configuración del pool de conexiones
<c3p0-config>
<default-config><!-- <property name="com.mchange.v2.c3p0.management.ManagementCoordinator">com.mchange.v2.c3p0.management.NullManagementCoordinator</property> --><!-- <property name="automaticTestTable">con_test</property> --> <property name="checkoutTimeout">30000</property> <!-- Espera 30 segs a conexion --> <property name="idleConnectionTestPeriod">30</property> <!-- Cada 30 segs chequea las conexiones ociosas --> <property name="initialPoolSize">10</property> <!-- Conexiones establecidas en el inicio --> <property name="maxIdleTime">30</property> <!-- 30 ssegundos que una conexion puede estar sin usarse antes de ser descartada --> <property name="maxPoolSize">100</property> <!-- Maximo numero de conexiones en el pool --> <property name="minPoolSize">10</property> <!-- El minimo numero de conexiones mantenidas--> <property name="maxStatements">0</property> <property name="maxStatementsPerConnection">5</property>
<!-- Con las dos anteriores se habilita el caché de sentencias sin lÃmite global, solo 5 por conexion--> <user-overrides user="test-user">
<property name="maxPoolSize">10</property> <property name="minPoolSize">1</property> <property name="maxStatements">0</property>
</user-overrides> </default-config>
</c3p0-config>
152
Gestión de Análisis Clínicos: Cornalvo
Índice de ilustracionesIlustración 1: Proyecto Cornalvo : 1ª FASE......................................................................................... 7Ilustración 2: Esquema general de arquitectura basada en IHE......................................................... 15Ilustración 3: Caso de uso 1................................................................................................................16Ilustración 4: Caso de uso 2................................................................................................................17Ilustración 5: Caso de uso 3................................................................................................................18Ilustración 6: Relación de actores y las transacciones entre ellos...................................................... 19Ilustración 7: OpenAdaptor Framework.............................................................................................66Ilustración 8: Componente Palette......................................................................................................66Ilustración 9: Componentes JMS........................................................................................................67Ilustración 10: JMSSource................................................................................................................. 67Ilustración 11: JMSSink..................................................................................................................... 69Ilustración 12: HospitalPipe............................................................................................................... 72Ilustración 13: Property Tools............................................................................................................ 73Ilustración 14: GenericPipe................................................................................................................ 74Ilustración 15: Configuración de un Adaptador................................................................................. 88Ilustración 16: Arquitectura del Sistema............................................................................................ 98Ilustración 17: Validación del usuario a través de LDAP.................................................................102Ilustración 18: Búsqueda de un paciente.......................................................................................... 103Ilustración 19: Listado de pacientes................................................................................................. 104Ilustración 20: Listado de analíticas................................................................................................. 105Ilustración 21: Listado de pruebas del laboratorio........................................................................... 106Ilustración 22: Evolutivo de una prueba...........................................................................................107Ilustración 23: Comparativa de evolutivos.......................................................................................108Ilustración 24: Informe de Laboratorio............................................................................................ 109Ilustración 25: Distribución de áreas del S.E.S................................................................................ 110
Índice de tablasTabla 1: Estados por los que pasa la orden desde el momento que es procesada por el Order Filler hasta que finalmente se completa o cancela la orden......................................................................... 23Tabla 2: Mensaje OUL^R22...............................................................................................................25Tabla 3: Mensaje OUL^R24...............................................................................................................25Tabla 4: Mensaje ACK....................................................................................................................... 26Tabla 5: Tabla HL7 de Atributos - MSH – Cabecera de mensaje......................................................28Tabla 6: Tabla HL7 0103 – Identificador de procesamiento.............................................................. 32Tabla 7: Tabla HL7 de Atributos - MSA – Confirmación de Mensaj.................................................33Tabla 8: Tabla HL7 0008 - Código de confirmación........................................................................34Tabla 9: Tabla HL7 de Atributos de error - ERR...............................................................................35Tabla 10: Tabla HL7 0516 – Severidad del error............................................................................... 36
153
Gestión de Análisis Clínicos: Cornalvo
Tabla 11: Segmento PID.....................................................................................................................38Tabla 12: Tabla definida por el usuario 0001 – Sexo Administrativo................................................ 40Tabla 13: Tabla HL7 de Atributos – OBR – Petición de Observación............................................... 44Tabla 14: Tabla HL7 0065 – Códigos de acción del espécimen.........................................................46Tabla 15: Tabla HL7 0074 – Identificadores de Sección de Servicio Diagnóstico............................ 48Tabla 16: Tabla HL7 0123 – Estado de Resultado............................................................................. 50Tabla 17: Tabla HL7 de atributos – OBX – Observación/Resultad...................................................52Tabla 18: Tabla HL7 0125 – Tipo de valor........................................................................................54Tabla 19: Tabla definida por el usuario 0078 – Indicadores de anormalidad.....................................56Tabla 20: Tabla HL7 0085 – Interpretación de los códigos resultado de observación....................... 57Tabla 21: Segmento NTE................................................................................................................... 59Tabla 22: Tabla HL7 0105 – Origen del comentario.......................................................................... 59Tabla 23: Tabla definida por el usuario 0364 – Tipo de comentario.................................................. 60
154