Article
· Fév 12 10m de lecture

La nouvelle validation du serveur FHIR basée sur les profils

La nouveauté de la version 2023.3 (d'InterSystems IRIS for Health) est une fonctionnalité permettant d'effectuer une validation basée sur le profil FHIR.

 (*)

Dans cet article, je vais fournir un aperçu de base de cette fonctionnalité.

Si FHIR est important pour vous, vous devriez absolument essayer cette nouvelle fonctionnalité, alors poursuivez votre lecture.

 

Contexte

Le standard FHIR définit une opération appelée $validate. Cette opération est destinée à fournir une API pour valider les ressources.

Pour en savoir plus sur la validation FHIR en général, vous pouvez consulter cette documentation FHIR.

Vous pouvez également voir ma session du Sommet mondial 2023 - "Performing Advanced FHIR Validation", où dans la première partie je fournis des informations sur différents types de validations.

Une partie de cette validation consiste à valider par rapport à des profils spécifiques. Vous pouvez voir ici à propos des profils.

Pour illustrer, à titre d'exemple simple, la définition de base FHIR pour la ressource Patient, définit la cardinalité de l'identifiant comme '0..*', ce qui signifie qu'un patient peut ne pas avoir d'identifiant (zéro) et être toujours valide. Mais le profil de patient principal des États-Unis définit une cardinalité de '1..*', ce qui signifie que l'absence d'identifiant pour un patient ne serait pas valide.

D'autres exemples, à la suite de l'exemple du profil USA de patient principal ci-dessus, utiliseraient des extensions, telles que la race ou le sexe de naissance.

Si vous souhaitez en savoir plus sur le profilage FHIR, vous pouvez consulter une session de notre Global Summit 2022 présenté par @Patrick Jamieson : "Using FHIR Shorthand", où Patrick explique l'utilisation de FSH (FHIR Shorthand), mais commence par aborder le sujet général du profilage.

Dans les versions précédentes, notre serveur FHIR ne supportait pas ce type de validation - validation basée sur le profil, mais à partir de la dernière version (2023.3), cette fonctionnalité est prise en charge.

Utilisation

Notre documentation comprend une section sur la façon d'appeler $validate pour une validation basée sur un profil.

Il existe deux manières fondamentales d’appeler l’opération $validate.

Profil dans l'URL de la requête

La première consiste à envoyer un POST avec la ressource dans le corps de la demande et le profil comme paramètre d'URL.

Par exemple, dans Postman :

Ou en utilisant curl (notez l'encodage des barres obliques dans la valeur du paramètre d'URL du profil ; Postman s'en charge pour vous) :

 curl --location 'http://fhirserver/endpoint/Patient/$validate?profile=http%3A%2F%2Fhl7.org%2Ffhir%2Fus%2Fcore%2FStructureDefinition%2Fus-core-patient' --header 'Content-Type: application/fhir+json' --header 'Accept: application/fhir+json' --header 'Authorization: Basic U3VwZXJVc2VyOnN5cw==' --data "@data.json"

Alors que data.json mentionné ci-dessus inclut ce patient principal américain valide, par exemple :

{
  "resourceType" : "Patient",
  "id" : "example",
  "meta" : {
    "profile" : ["http://hl7.org/fhir/us/core/StructureDefinition/us-core-patient|7.0.0-ballot"]
  },
  "text" : {
    "status" : "generated",
    "div" : "<div xmlns=\"http://www.w3.org/1999/xhtml\"><p style=\"border: 1px #661aff solid; background-color: #e6e6ff; padding: 10px;\"></div>"
  },
  "extension" : [{
    "extension" : [{
      "url" : "ombCategory",
      "valueCoding" : {
        "system" : "urn:oid:2.16.840.1.113883.6.238",
        "code" : "2106-3",
        "display" : "White"
      }
    },
    {
      "url" : "ombCategory",
      "valueCoding" : {
        "system" : "urn:oid:2.16.840.1.113883.6.238",
        "code" : "1002-5",
        "display" : "American Indian or Alaska Native"
      }
    },
    {
      "url" : "ombCategory",
      "valueCoding" : {
        "system" : "urn:oid:2.16.840.1.113883.6.238",
        "code" : "2028-9",
        "display" : "Asian"
      }
    },
    {
      "url" : "detailed",
      "valueCoding" : {
        "system" : "urn:oid:2.16.840.1.113883.6.238",
        "code" : "1586-7",
        "display" : "Shoshone"
      }
    },
    {
      "url" : "detailed",
      "valueCoding" : {
        "system" : "urn:oid:2.16.840.1.113883.6.238",
        "code" : "2036-2",
        "display" : "Filipino"
      }
    },
    {
      "url" : "text",
      "valueString" : "Mixed"
    }],
    "url" : "http://hl7.org/fhir/us/core/StructureDefinition/us-core-race"
  },
  {
    "extension" : [{
      "url" : "ombCategory",
      "valueCoding" : {
        "system" : "urn:oid:2.16.840.1.113883.6.238",
        "code" : "2135-2",
        "display" : "Hispanic or Latino"
      }
    },
    {
      "url" : "detailed",
      "valueCoding" : {
        "system" : "urn:oid:2.16.840.1.113883.6.238",
        "code" : "2184-0",
        "display" : "Dominican"
      }
    },
    {
      "url" : "detailed",
      "valueCoding" : {
        "system" : "urn:oid:2.16.840.1.113883.6.238",
        "code" : "2148-5",
        "display" : "Mexican"
      }
    },
    {
      "url" : "text",
      "valueString" : "Hispanic or Latino"
    }],
    "url" : "http://hl7.org/fhir/us/core/StructureDefinition/us-core-ethnicity"
  },
  {
    "url" : "http://hl7.org/fhir/us/core/StructureDefinition/us-core-birthsex",
    "valueCode" : "F"
  }
  ],
  "identifier" : [{
    "use" : "usual",
    "type" : {
      "coding" : [{
        "system" : "http://terminology.hl7.org/CodeSystem/v2-0203",
        "code" : "MR",
        "display" : "Medical Record Number"
      }],
      "text" : "Medical Record Number"
    },
    "system" : "http://hospital.smarthealthit.org",
    "value" : "1032702"
  }],
  "active" : true,
  "name" : [{
    "use" : "old",
    "family" : "Shaw",
    "given" : ["Amy",
    "V."],
    "period" : {
      "start" : "2016-12-06",
      "end" : "2020-07-22"
    }
  },
  {
    "family" : "Baxter",
    "given" : ["Amy",
    "V."],
    "suffix" : ["PharmD"],
    "period" : {
      "start" : "2020-07-22"
    }
  }],
  "telecom" : [{
    "system" : "phone",
    "value" : "555-555-5555",
    "use" : "home"
  },
  {
    "system" : "email",
    "value" : "amy.shaw@example.com"
  }],
  "gender" : "female",
  "birthDate" : "1987-02-20",
  "address" : [{
    "use" : "old",
    "line" : ["49 MEADOW ST"],
    "city" : "MOUNDS",
    "state" : "OK",
    "postalCode" : "74047",
    "country" : "US",
    "period" : {
      "start" : "2016-12-06",
      "end" : "2020-07-22"
    }
  },
  {
    "line" : ["183 MOUNTAIN VIEW ST"],
    "city" : "MOUNDS",
    "state" : "OK",
    "postalCode" : "74048",
    "country" : "US",
    "period" : {
      "start" : "2020-07-22"
    }
  }]
}

La réponse de cette opération est une ressource OperationOutcome.

Si la ressource est valide (comme ci-dessus), vous vous attendez à obtenir ce type de réponse :

{
    "resourceType": "OperationOutcome",
    "issue": [
        {
            "severity": "information",
            "code": "informational",
            "details": {
                "text": "All OK"
            }
        }
    ]
}

Mais si par exemple j'omets les identifiants de la ressource ci-dessus, j'obtiendrai cette réponse OperationOutcome :

{
    "resourceType": "OperationOutcome",
    "issue": [
        {
            "severity": "error",
            "code": "invariant",
            "details": {
                "text": "generated-us-core-patient-1: Constraint violation: identifier.count() >= 1 and identifier.all(system.exists() and value.exists())"
            },
            "diagnostics": "Caused by: [[expression: identifier.count() >= 1, result: false, location: Patient]]",
            "expression": [
                "Patient"
            ]
        }
    ]
}

Profil dans le corps de la requête

L'autre façon d'envoyer les données à $validate consiste à envoyer un POST avec la ressource à l'intérieur d'un tableau de Paramètres, avec le profil et autres options.

Dans Postman, cela ressemblera dès lors à ceci :

Avec curl:

curl --location 'http://fhirserver/endpoint/Patient/$validate' --header 'Content-Type: application/fhir+json' --header 'Accept: application/fhir+json' --header 'Authorization: Basic U3VwZXJVc2VyOnN5cw==' --data "@data.json"

Notez que l'URL n'inclut pas de profil, mais le contenu du corps (ou data.json dans l'exemple ci-dessus) ressemble désormais à ceci :

{
    "resourceType": "Parameters",
    "parameter": [
        {
            "name": "mode",
            "valueString": "profile"
        },
        {
            "name": "profile",
            "valueUri": "http://hl7.org/fhir/us/core/StructureDefinition/us-core-patient"
        },
        {
            "name": "resource",
            "resource": {
                "resourceType": "Patient"
                
               
            }
        }
    ]
}

J'ai exclu la ressource patient réelle, car elle est la même que dans les exemples précédents.

Mais ce qui est différent ici, c'est l'élément de paramètre mode et celui de profile, et la ressource est incluse dans son propre élément de paramètre simplement nommé « resource ».

Cf. les documents référencés ci-dessus pour plus d'options de mode, y compris l'endroit où un identifiant peut être inclus dans l'URL (pour valider par exemple sa mise à jour ou sa suppression).

Pour votre commodité, j'ai créé un simple package Open Exchange qui comprend une collection Postman avec des exemples de demandes comme ci-dessus.

Par code

Notez qu'au lieu d'appeler l'opération $validate via l'API REST standard, en interne, si le cas d'utilisation est approprié, vous pouvez également appeler une méthode de classe.

De la même manière que la méthode qui existait déjà HS.FHIRServer.Util.ResourceValidator:ValidateResource() (mentionné également ici dans la documentation) il existe maintenant aussi une nouvelle méthode ValidateAgainstProfile() que vous pouvez utiliser.

 

Portée

Il est important de noter qu'actuellement (v2023.3), ce type de validation (validation basée sur le profil) se produit uniquement dans le cadre de l'opération $validate, mais pas lorsque vous créez ou mettez à jour des ressources. Là, une simple validation "de base" se produit. Donc, si vous le souhaitez, vous pouvez exécuter vos ressources via la validation basée sur le profil le plus "avancée" avant de les enregistrer via POST ou PUT.

D'autres options pourraient être disponibles dans les versions futures.

Notes de configuration

En général, la bonne nouvelle est que le serveur FHIR se chargera de la majeure partie de la configuration du validateur de profil pour vous.

Ce dont vous devez vous assurer, c'est que vous disposez d'un JDK Java 11 pris en charge. (actuellement c'est celui d'Oracle ou d'OpenJDK).

Vous pouvez trouver plus de détails dans la documentation de la Configuration du serveur de validation de profil.

Fondamentalement, ce qui se passe en coulisses, c'est que nous nous assurons qu'un serveur de langage externe (Java) est en cours d'exécution, afin d'exécuter le JAR du validateur (situé dans le dossier d'installation, sous dev/fhir/java ; d'ailleurs, si vous jetez un coup d'œil dans le dossier des journaux et vous voyez des avertissements, tels que :

CodeSystem-account-status.json : Expected: JsonArray but found: OBJECT for element: identifier

ne vous inquiétez pas, c'est très bien. Le validateur charge de nombreux profils par défaut et certains d'entre eux comportent des erreurs de formatage).

Ainsi, si vous regardez votre liste de serveurs de langues externes, vous devriez voir que vous avez quelque chose comme ceci :

Notez que lorsque le validateur doit valider un profil, pour la première fois, il doit le charger. Ainsi, pour améliorer les performances, vous pouvez appeler la méthode HS.FHIRServer.Installer:InitalizeProfileValidator() :

do ##class(HS.FHIRServer.Installer).InitializeProfileValidator()

Ceci est également mentionné dans la documentation référencée ci-dessus pour la configuration du validateur.

En effet, vous pouvez inclure cet appel dans la routine de démarrage de votre instance IRIS %ZSTART.

Et ceci est également mentionné dans la référence de classe associée :

Il est recommandé d'appeler cette méthode après un redémarrage de l'instance ou du serveur de langage externe afin de ne pas subir de pertes de performances liées au chargement des profils lors de l'opération de validation.

 

À venir...

Dans les versions à venir, nous prévoyons de fournir plus de fonctionnalités dans et autour du validateur.

Mais, par exemple, même aujourd'hui, si vous souhaitez effectuer une validation externe basée sur le serveur de Terminologies (comme pour les codes LOINC), vous pouvez utiliser une approche différente, expliquée et démontrée dans ma session de Global Summit que j''ai mentionnée ci-dessus, sur la base de l'exemple de mon collègue @Dmitry Zasypkin (disponible sur Open Exchange). 

Remerciements spéciaux

Merci à @Kimberly Dunn qui a été une source d'informations inestimable lors de l'examen de cette nouvelle fonctionnalité et de la préparation de cet article

(*) Merci au créateur d'images alimenté par DALL-E 3 de Microsoft Bing qui a créé l'image ci-dessus pour moi.

Discussion (0)1
Connectez-vous ou inscrivez-vous pour continuer