Current Build

Переводит команда Health Samurai . Приглашаем поучаствовать в русификации стандарта FHIR: GitHub , Email.

FHIR Infrastructure Work GroupMaturity Level: N/ABallot Status: Informative

Чтобы пользоваться расширениями ресурсов (extensions), необходимо выполнить следующие три шага:

  1. Дать определение расширению
  2. Зарегистрировать его
  3. Использовать расширение как часть некоторой сущности

Ниже приводится описание данного процесса.

Базовый ресурс "пациент" не содержит информации, касающейся согласия пациента на передачу его персональной информации и/или действующей политики, по которой пациент соглашается на регистрацию его данных. Общественные веб-провайдеры сервисов персональных медицинских записей (PHR) могут быть обязаны следить за изменениями конкретной политики, в соответствии с которой пользователь сервиса встeпил во взаимоотношения с поставщиком PHR-услуг, и информировать пользователя об изменении политики с помощью FHIR API. При желании, поставщик PHR-услуг может расширить базовые ресурсы о пациенте для представления в них (и передачи) соглашения об участии пациента (participation agreement). Обратите внимание на существование и иных решений данной проблемы, более предпочтительных, но для демонстрации процесса расширения достаточно и этого примера. The basic patient resource contains no information relating to patient consent, and/or the policy under which the patient consents to their registration details. A social web provider of personal healthcare record (PHR) services might be obliged to keep track of the particular policy under which a patient has created their relationship with the PHR provider, and share this with their participants via their FHIR API. If they wish, they can extend the patient resource to represent the patient's participation agreement. Note that other approaches to this problem are possible and preferred, but this example suffices to demonstrate the extension process.

В рамках этого примера мы предположим, что пациент согласился с условиями участия в рамках своей регистрации, и что как поставщик должен изменить свою политику, они просят пациентов дать согласие на новые детали участия. Каждое соглашение на участие имеет URI, который его идентифицирует, и ресурс patient будет передавать этот URI для каждого соглашения с политикой, на которое согласился пациент.

Для каждого расширения первое, что необходимо сделать, это заполнить дефинициальные свойства расширения:

Code"participation-agreement"
ContextThis extension is used in the patient resource
Short DefnAgreed agreement/policy
DefinitionA URI that identifies a participation agreement/policy to which the patient has agreed
CommentURI is a literal reference to agreement text (html)
Cardinality1..* (patient cannot participate without at least one agreement)
Typeuri
Invariantsno Invariants
is ModifierNo (The participation agreements do not affect that interpretation of the elements of the patient, though they will likely influence how the system interacts with the patient)
Binding(No binding - not a coded value)

Из этой таблицы мы можем построить формальное определение расширения. В данном случае оно будет выглядеть так:

<StructureDefinition xmlns="http://hl7.org/fhir">
  <url value="http://example.org/fhir/StructureDefinition/participation-agreement"/>
  <name value="Example Extension Definition"/>
  <!-- snip other metadata -->
  <kind value="complex-type"/>
  <context>
    <type value="fhirpath"/>
    <expression value="Patient"/>
  </context>
  <type value="Extension"/>
  <baseDefinition value="http://hl7.org.fhir/StructureDefinition/Extension"/>
  <derivation value="constraint"/>

  <differential>
    <element>
      <path value="Extension"/>
      <short value="Agreed agreement/policy"/>
      <definition value="A URI that identifies a participation agreement/policy
        to which the patient has agreed"/>
      <comment value="URI is a literal reference to agreement text (html).
        Systems SHALL conform to the policies as indicated.
        For further information, see the partnership agreement..."/>
      <mustSupport value="true"/>
      <isModifier value="false"/>
    </element>
    <element>
      <path value="Extension.url"/>
      <fixedUri value="http://example.org/fhir/StructureDefinition/participation-agreement"/>
    </element>
    <element>
      <path value="Extension.valueUri"/>
      <short value="The URI value"/>
      <min value="1"/>
      <max value="*"/>
      <type>
         <code value="uri"/>
      </type>
      <mustSupport value="true"/>
    </element>
  </differential>
</StructureDefinition>

Следует отметить, что в большинстве случаев реальные профили будут создаваться с помощью каких-то инструментов. Этот пример был составлен вручную для примера. Note that usually one would build the actual profile using a tool. This example was built by hand for this example.

Это значит, что приведенный выше профиль, определяющий расширение, размещен где-то в веб-сети. Предпочтительно, чтобы он был размещен в точке взаимодействия FHIR Profile, а лучшим местоположением для всех расширений будет реестр профилей HL7 . This means the profile shown above that defines the extension is placed on the web somewhere. By preference, it will be hosted at a FHIR Profile endpoint, and the best location of all is the HL7 Profile registry .

Для этого примера мы предположим, что он был загружен на собственный веб-сайт PHR-провайдера по адресу http://example.org/phr/documents/fhir/extensions.

Для использования расширения в экземпляре, расширение помещается в корень ресурса. Обратите внимание, что URL расширения ссылается на адрес регистрации с идентификатором расширения в качестве фрагмента идентификации.

<Patient xmlns="http://hl7.org/fhir">
  <extension url="http://example.org/phr/documents/fhir/extensions/participation-agreement" >
    <valueUri value="http://example.org/phr/documents/patient/general/v1"/>
  </extension>
  <!-- ... -->
</Patient>

Определение расширения выше просто определяет расширение "participation-agreement" и говорит, что оно используется в ресурсе patient. Однако профиль выше не говорит, что сервер действительно использует его. Чтобы PHR-провайдеру указать, что все ресурсы Patient будут использовать этот ресурс, применяется StructureDefinition ресурса patient: The extension definition above simply defines the extension "participation-agreement", and says that it is used with patient. But the profile above doesn't say that the server actually uses it. For the PHR provider to indicate that all Patient resources will use this resource, a StructureDefinition on the patient resource is used:

<StructureDefinition xmlns="http://hl7.org/fhir">
  <id value="patient-profile"/>
  <!-- snip other metadata, narrative -->
  <differential>

    <!-- first, the patient root element
      - can be copy/paste from the base patient profile -->
    <element>
      <path value="Patient"/>
      <!-- snip definition -->
    </element>

    <!-- now, the general definition for extensions
      - can be copied/pasted from the base patient profile,
      with changes for slicing  -->
    <element>
      <path value="Patient.extension"/>
      <!-- we're going to slice the extension element, and
        one of the extensions is one we have defined -->
      <slicing>
        <!-- extension is always sliced on url -->
        <discriminator>
          <type value="value"/>
          <path value="url"/>
        </discriminator>
        <!-- we don't care what the order of any extensions is -->
        <ordered value="false"/>
        <!-- Other extensions are allowed in addition to this one -->
        <rules value="open"/>
      </slicing>
      <!-- snip definition -->
    </element>

    <!-- now, the slice that contains our extension -->
    <element>
      <path value="Patient.extension"/>
      <sliceName value="base-extension"/>
      <!-- clone information from the extension definition.
        duplicative, but this duplication makes it simpler overall -->
      <short value="Agreed agreement/policy"/>
      <definition value="A URI that identifies a participation agreement/policy
      to which the patient has agreed"/>
      <!--  min has to be 1, since the extension itself has min = 1 -->
      <min value="1"/>
      <max value="*"/>
      <type>
        <!-- obviously it has to be an extension -->
        <code value="Extension"/>
        <!-- and here is the link to the extension definition:
          this extension has to conform to the rules laid down in its definition -->
        <profile value="http://example.org/phr/documents/fhir/extensions#participation-agreement"/>
      </type>
      <isModifier value="false"/>
    </element>

  <!-- snip the rest of the profile -->

  </differential>
</StructureDefinition>

Примечание - этот шаг является необязательным.

ISO 21090 (Healthcare Data Types) определяет концепт "name part qualifier", который содержит дополнительную информацию о том, как конкретная часть имени должна использоваться или интерпретироваться. На практике, это поле используется редко, за исключением определенных культурных контекстов, где использование квалификаторов определенных частей - это вопрос практики. Следуя FHIR design policy, подобное поле не включено в общее определение основного типа данных name, вместо этого оно добавлено в качестве расширения.

На практике, для случаев как эти, в ISO 21090 HL7 предоставляет общие расширения, которые определены по адресу [адрес пока не определен].

Для каждого расширения первое, что необходимо сделать, это заполнить дефинициальные свойства расширения:

Code"name-qualifier"
ContextThis extension can be used anywhere a HumanName.part appears
Short Defn(one of the codes) LS | AC | NB | PR | HON | BR | AD | SP | MID | CL | IN
DefinitionA set of codes each of which specifies a certain subcategory of the name part in addition to the main name part type
CommentUsed to indicate additional information about the name part and how it should be used
Cardinality0..* (this is always optional, but more than one can be used if required)
Typecode
InvariantsN/A
Is ModifierNo (Qualifiers do not change the fact that the part is a given or family name)
RIM MappingENXP.qualifier
v2 MappingN/A
BindingBound to a subset of the codes specified for EntityNamePartQualifierR2 in ISO 21090

Не все коды EntityNamePartQualifierR2 обязательны в этом контексте, поскольку prefix и suffix явно являются частью типов имени. Вместо того, чтобы просто ссылаться на OID для EntityNamePartQualifierR2 (2.16.840.1.113883.5.1122), в данном случае мы перечисляем доступные коды и устанавливаем тип расширения в code. Тип "code" разрешен только если сам профиль задает эти коды, которые могут использоваться. Ниже приводится таблица этих кодов (см. полные определения по ссылке EntityNamePartQualifierR2 reference for the full definitions):

LSLegal status For organizations, a suffix...
ACAcademicIndicates that a prefix like "D...
NBNobilityIn Europe and Asia, there are s...
PRProfessionalPrimarily in the British Im...
HONHonorificAn honorific such as 'The Rig...
BRBirthA name that a person was given at ...
ADAcquiredA name part a person acquired. ...
SPSpouseThe name assumed from the partner...
MIDMiddle NameIndicates that the name par...
CLCall meCall me is used to indicate which...
INInitialIndicates that a name part is ju...

Всё это затем отображается формально в профиле. Таким профилям не обязательно включать утверждения об ограничениях ресурсов; вместо этого они включают только объявления расширений и связанные с ними привязки. В этом случае определение выглядит так: This is all then represented formally in a profile. Such profiles do not need to include resource constraint statements; instead, they include just extension declarations and their associated bindings. In this case, the definition looks like this:

<StructureDefinition xmlns="http://hl7.org/fhir">
  <url value="http://hl7.org/fhir/StructureDefinition/iso21090-EN-qualifier"/>
  <name value="Iso21090NameQualifier"/>
  <title value="iso-21090 Name Qualifier"/>
  <!-- snip other metadata, including definition of RIM Mapping -->
  <kind value="complex-type"/>
  <context>
    <type value="element"/>
    <expression value="HumanName.given"/>
  </context>    
  <context>
    <type value="element"/>
    <expression value="HumanName.prefix"/>
  </context>    
  <context>
    <type value="element"/>
    <expression value="HumanName.family"/>
  </context>    
  <context>
    <type value="element"/>
    <expression value="HumanName.suffix"/>
  </context>    
  <type value="Extension"/>
  <baseDefinition value="http://hl7.org.fhir/StructureDefinition/Extension"/>
  <derivation value="constraint"/>
  <differential>
    <element>
      <path value="Extension"/>
      <short value="LS | AC | NB | PR | HON | BR | AD | SP | MID | CL | IN"/>
      <definition value="A set of codes each of which specifies a certain subcategory
          of the name part in addition to the main name part type"/>
      <comment value="Used to indicate additional information about the
             name part and how it should be used"/>
      <mustSupport value="false"/>
      <isModifier value="false"/>
    </element>
    <element>
      <path value="Extension.url"/>
      <fixedUri value="http://hl7.org/fhir/StructureDefinition/iso21090-EN-qualifier"/>
    </element>
    <element>
      <path value="Extension.value"/>
      <short value="LS | AC | NB | PR | HON | BR | AD | SP | MID | CL | IN"/>
      <min value="0"/>
      <max value="*"/>
      <type>
         <code value="code"/>
      </type>
      <binding>
        <strength value="required"/>
        <description value="A set of codes each of which specifies a certain subcategory
            of the name part in addition to the main name part type"/>
        <valueSet value="http://hl7.org/fhir/ValueSet/name-part-qualifier"/>
      </binding>
      <mapping>
         <identity value="RIM"/>
         <map value="ENXP.qualifier"/>
      </mapping>
    </element>
  </differential>
</StructureDefinition>

Следует отметить, что в большинстве случаев реальные профили будут создаваться с помощью каких-то инструментов. Этот пример был составлен из определения в виде электронной таблицы с помощью инструмента создания FHIR. Note that usually one would build the actual profile using a tool. This example was built from a spreadsheet definition by the FHIR build tooling.

В этом примере расширение зарегистрировано по адресу http://hl7.org/fhir/StructureDefinition/iso21090-EN-qualifier . Это URL, который появится в элементе определения, когда это расширение будет использоваться.

Для использования расширения в экземпляре, расширение вложено в атрибут, который расширяется. Обратите внимание, что URL расширения ведет на тот адрес, по которому он был зарегистрирован, с идентификатором расширения в качестве фрагмента идентификации.

<name>
  <use value="official"/>
  <given value="Östlund">
     <extension url="http://hl7.org/fhir/StructureDefinition/iso21090-EN-qualifier" >
        <valueCode value="MID"/>
     </extension>
  </given>
</name>

В данном примере используется скандинавское отчество (mellannamn). Дополнительные примеры можно найти в разделе Примеры типов данных.

Defining complex extensions is a little different. They have the same metadata - context, etc. - but differ in the internal structure. As an example, consider enrolling a patient in a clinical trial. There are 3 data items to collect:

Code Name Cardinality Type Content
NCT Clinical Trial number 1..1 string The format for the US ClinicalTrials.gov registry number is "NCT" followed by an 8-digit number, e.g.: NCT00000419
period trialPeriod 0..1 Period The start and end times of the participation of this patient in the clinical trial
reason reason enrolled 0..1 CodableConcept Indication or reason that the patient is part of this trial

Like simple extensions, the first thing to do is to assign a URI to the extension. Since this one is part of the FHIR publication, it is assigned a URI where it will be published: http://hl7.org/fhir/StructureDefinition/patient-clinicalTrial.

Internally, in the extension, the cardinality of the value[x] element is set to 0 since it will not (and cannot) be used. The Extension.extension element is sliced by URL, and 3 slices are defined, each with a fixed relative URI which is the code from the table above. The relevant parts of the definition of this extension are as follows:

<StructureDefinition xmlns="http://hl7.org/fhir">
  <!-- metadata - setting up the base definition -->
  <url value="http://hl7.org/fhir/StructureDefinition/patient-clinicalTrial"/>
  <name value="ClinicalTrialParticipation"/>
  <title value="The patient's participation in clinical trials"/>
  <context>
    <type value="element"/>
    <expression value="Patient"/>
  </context>
  <type value="Extension"/>
  <baseDefinition value="http://hl7.org.fhir/StructureDefinition/Extension"/>
  <derivation value="constraint"/>
  <snapshot>
    <element>
      <path value="Extension"/>
      <!-- etc.-->
    </element>

    <!-- set up the slicing -->
    <element>
      <path value="Extension.extension"/>
      <slicing>
        <discriminator>
          <type value="value"/>
          <path value="url"/>
        </discriminator>
        <ordered value="true"/>
        <rules value="openAtEnd"/>
      </slicing>
    </element>

    <!-- first slice, NCT -->
    <element>
      <path value="Extension.extension"/>
      <sliceName value="NCT"/>
      <short value="National Clinical Trial number"/>
      <min value="1"/>
      <max value="1"/>
    </element>
    <element>
      <path value="Extension.extension.extension"/>
      <min value="0"/>
      <max value="0"/> <!-- not allowed to be used -->
    </element>
    <element>
      <path value="Extension.extension.url"/>
      <min value="1"/>
      <max value="1"/>
      <fixedUri value="NCT"/>
    </element>
    <element>
      <path value="Extension.extension.valueString"/>
      <min value="1"/>
      <max value="1"/>
      <type>
        <code value="string"/>
      </type>
    </element>

    <!-- second slice, period -->
    <element>
      <path value="Extension.extension"/>
      <sliceName value="period"/>
      <short value="The period of participation in the clinical trial"/>
      <min value="0"/>
      <max value="1"/>
    </element>
    </element>
    <element>
      <path value="Extension.extension.extension"/>
      <min value="0"/>
      <max value="0"/>
    </element>
    <element>
      <path value="Extension.extension.url"/>
      <min value="1"/>
      <fixedUri value="period"/>
    </element>
    <element>
      <path value="Extension.extension.valuePeriod"/>
      <type>
        <code value="Period"/>
      </type>
    </element>

    <!-- third slice, reason -->
    <element>
      <path value="Extension.extension"/>
      <sliceName value="reason"/>
      <short value="The reason for participation in the clinical trial"/>
      <min value="0"/>
      <max value="1"/>
    </element>
    <element>
      <path value="Extension.extension.extension"/>
      <min value="0"/>
      <max value="0"/>
    </element>
    <element>
      <path value="Extension.extension.url"/>
      <min value="1"/>
      <fixedUri value="reason"/>
    </element>
    <element>
      <path value="Extension.extension.valueCodeableConcept"/>
      <type>
        <code value="CodeableConcept"/>
      </type>
    </element>

    <!-- last (for order reasons): the fixed URI -->
    <element>
      <path value="Extension.url"/>
      <fixedUri value="http://hl7.org/fhir/StructureDefinition/patient-clinicalTrial"/>
    </element>
    <!-- and no value in the root -->
    <element>
      <path value="Extension.value[x]"/>
      <min value="0"/>
      <max value="0"/>
    </element>
  </snapshot>
</StructureDefinition>

With complex extensions, only the first URL is an absolute URL:

<Patient xmlns="http://hl7.org/fhir">
  <extension url="http://hl7.org/fhir/StructureDefinition/patient-clinicalTrial" >
    <extension url="NCT" >
      <valueString value="NCT00000419"/>
    </extension>
    <extension url="period" >
      <valuePeriod>
        <start value="200140105"/>
        <end value="20120105"/>
      </valuePeriod>
    </extension>
    <extension url="reason" >
      <valueCodeableConcept>
        <text value="NCT00000419"/>
      </valueCodeableConcept>
    </extension>
  </extension>
  <!-- ... -->
</Patient>

This is the same as for a simple extension:

<StructureDefinition xmlns="http://hl7.org/fhir">
  <id value="patient-profile"/>
  <!-- snip other metadata, narrative -->
  <differential>

    <!-- first, the patient root element
      - can be copy/paste from the base patient profile -->
    <element>
      <path value="Patient"/>
      <!-- snip definition -->
    </element>

    <!-- now, the general definition for extensions
      - can be copy/paste from the base patient profile,
      with changes for slicing  -->
    <element>
      <path value="Patient.extension"/>
      <!-- we're going to slice the extension element, and
        one of the extensions is one we have defined -->
      <slicing>
        <!-- extension is always sliced on url -->
        <discriminator>
          <type value="value"/>
          <path value="url"/>
        </discriminator>
        <!-- we don't care what the order of any extensions is -->
        <ordered value="false"/>
        <!-- Other extensions are allowed in addition to this one -->
        <rules value="open"/>
      </slicing>
      <!-- snip definition -->
    </element>

    <!-- now, the slice that contains our extension -->
    <element>
      <max value="1"/>
      <type>
        <!-- obviously it has to be an extension -->
        <code value="Extension"/>
        <!-- and here is the link to the extension definition:
          this extension has to conform to the rules laid down in its definition -->
        <profile value="http://hl7.org/fhir/StructureDefinition/patient-clinicalTrial"/>
      </type>
    </element>

  <!-- snip the rest of the profile -->

  </differential>
</StructureDefinition>