zen.fhir - это пространство имен языка zen-lang, которое используется во всех пакетах, сгенерированных инструментом zen-fhir.
zen.fhir расширяет zen/schema, давая возможность описывать специфичные для FHIR вещи, такие как привязки, ссылки, расширения.
В этой секции приведены примеры описания ограничений FHIR на zen.
В примерах используется это пространство имен:
{:ns fhir
:alias hl7-fhir-r4-core}Это пространство имен вводит псевдонимы для определений FHIR R4 как просто fhir, что позволит позже заменить этот псевдоним на hl7-fhir-r4b-core или на hl7-fhir-r5-core и, таким образом, перенести свои профили на более новую версию FHIR.
Другой распространенной вещью является свойство :zen.fhir/version схем. Оно определяет, какую версию синтаксиса zen.fhir будет использовать ваша схема. В настоящее время указание версии в схемах является обязательным, текущая версия — :zen.fhir/version "0.5.0". В будущем это свойство может быть объявлено устаревшим с соблюдением обратной совместимости.
Создайте схему с тегом zen.fhir/profile-schema. Эта схема должна содержать :zen.fhir/profileUri, по которому на него будут ссылаться ресурсы в атрибуте meta.profile. Вот пример профиля на тип ресурса Patient:
{:ns MyProfiles
:import #{zen.fhir fhir}
MyPatientProfile
{:zen/tags #{zen/schema zen.fhir/profile-schema}
:zen.fhir/version "0.5.0"
:zen.fhir/profileUri "urn:fhir:extension:MyPatientProfile"
:confirms #{fhir/Patient}}}Обратите внимание на часть :confirms #{fhir/Patient}, она означает, что данные, которые будут валидироваться на соответствие вашей схеме, также будут проверены на соответствие базовому типу ресурса Patient.
Профиль создается таким же способом, как и на существующий тип ресурса, однако в элементе :confirms необходимо указать схему профиля вместо схемы базового типа ресурса.
MyPatientProfileOnAProfile
{:zen/tags #{zen/schema zen.fhir/profile-schema}
:zen.fhir/version "0.5.0"
:zen.fhir/profileUri "urn:fhir:extension:MyPatientProfileOnAProfile"
:confirms #{MyPatientProfile}}Если у схемы есть тег zen.fhir/profile-schema, то в ней можно описывать огарничения. Следует понимать, что свойство :confirms не являлется наследованием. Ваша схема не получает неявно никаких свойств из схем, указанных в :confirms. В результате, для описания ограничения вам необходимо явно описать типы и структуру данных. Следующий пример проиллюстрирует это.
В zen-lang, чтобы требовать наличие ключа, вам нужно установить свойство :require. Вот обновленный пример профиля для типа ресурса Patient с обязательными ключами :active и :name:
MyPatientProfile
{:zen/tags #{zen/schema zen.fhir/profile-schema}
:zen.fhir/version "0.5.0"
:zen.fhir/profileUri "urn:fhir:extension:MyPatientProfile"
:confirms #{fhir/Patient}
:type zen/map
:require #{:active :name}}Обратите внимание, что нам пришлось описать :type zen/map, чтобы использовать свойство :require. Ваша схема не наследует неявно :type zen/map от :confirms #{fhir/Patient}. И поскольку :require является свойством типа zen/map, вам необходимо явно указать тип в вашей схеме.
В настоящее время нет возможности запретить использование элемента в zen-lang. Вот ссылка на задачу, чтобы отслеживать её статус.
:type zen/vector предоставляет свойства :minItems и :maxItems. Пример ограничения Patient.name ровно одним элементом:
MyPatientProfile
{:zen/tags #{zen/schema zen.fhir/profile-schema}
:zen.fhir/version "0.5.0"
:zen.fhir/profileUri "urn:fhir:extension:MyPatientProfile"
:confirms #{fhir/Patient}
:type zen/map
:require #{:name}
:keys {:name {:type zen/vector
:minItems 1
:maxItems 1}}}Указание того, что zen/vector имеет минимум 1 элемент, не делает ключ, который хранит это значение, обязательным для присутствия. Нам нужно явно указать, что ключ также требуется.
В профилях FHIR pattern[x] чаще всего используется в срезах. Свойство :match из zen/schema позволяет описать сопоставление с образцом.
Ниже приведен пример определения шаблона для элемента Observation.code, шаблон описывает, что в массиве :coding должен быть хотя бы один объект с ~:system “my-system”~ и ~:code “my-code”~:
MyObservationProfile
{:zen/tags #{zen/schema zen.fhir/profile-schema}
:zen.fhir/version "0.5.0"
:zen.fhir/profileUri "urn:fhir:extension:MyObservationProfile"
:confirms #{fhir/Observation}
:type zen/map
:keys {:code {:match {:coding #{{:system "my-system", :code "my-code"}}}}}}
Синтаксис сопоставления шаблонов :match представляет собой рекурсивную структуру данных, состоящую из нескольких частей:
{} содержит ключи и их шаблоны, примененные к объекту, каждый ключ из {} должен присутствовать в объекте и соответствовать шаблону. Объект может содержать любые дополнительные ключи, не упомянутые в шаблоне.#{} содержит шаблоны, применяемые к массивам, для каждого шаблона из #{} должно быть хотя бы одно совпадение в массиве данных. Массив может содержать любые другие элементы, не соответствующие шаблону.Разбивка приведенного выше примера:
{:coding #{{:system "my-system", :code "my-code"}}};{:coding ...}, it expects data to be an object containing key :coding;#{{:system ...}} is applied;#{} syntax expects the data to be an array containing at least one match to the pattern {:system "my-system", :code "my-code"};{:system "my-system", :code "my-code"} expects data to be an object containing keys :system and :code with values “my-system” and “my-code” respectively.Чтобы определить фиксированное значение, используйте свойство :const из zen/schema, позволяющее описать постоянное значение. Так же, как и шаблоны, value[x] в большинстве случаев используется в срезах, а также для установки URL-адреса расширения. Вместо этого Zen FHIR предлагает расширения первого класса, если вы хотите определить расширение, обратитесь к примеру расширения. Вот пример установки значения элемента Observation.status, которое всегда будет иметь значение final, если оно присутствует:
MyObservationProfile
{:zen/tags #{zen/schema zen.fhir/profile-schema}
:zen.fhir/version "0.5.0"
:zen.fhir/profileUri "urn:fhir:extension:MyObservationProfile"
:confirms #{fhir/Observation}
:type zen/map
:keys {:status {:const {:value "final"}}}}Можно сделать слайсинг в схеме с помощью своейства :slicing, которое позволяет валидировать оперделенные элементы массива, используя отдельные схемы для каждой категории элементов. Чтобы указать правила проверки отдельного среза, опишите его в свойстве :slices. Обратите внимание, что каждый слайс должен иметь свойство :filter, которое должно содержать свойство :match. Элемент становится частью определенного слайса, если указанные данные в свойстве :match совпадают с данными элемента.
MyObservation
{:zen/tags #{zen.fhir/profile-schema zen/schema},
:zen.fhir/profileUri "urn:fhir:Observation"
:zen.fhir/version "0.5.0"
:confirms #{fhir/Observation}
:type zen/map
:keys {:code {:confirms #{fhir/CodeableConcept}
:type zen/map
:keys {:coding
{:slicing
{:type zen/vector
:every {:confirms #{fhir/Coding}
:slices {"HeartRateCode"
{:schema {:type zen/vector
:minItems 1
:maxItems 1
:every {:type zen/map
:keys {:system {:const {:value "http://loinc.org"}
:confirms #{fhir/uri}}
:code {:const {:value "8867-4"}
:confirms #{fhir/code}}
:require #{:system :code}}}}
:filter {:engine :match,
:match {:code "8867-4", :system "http://loinc.org"}}}}}}}}}}}
Если у вас есть схема с тегом zen.fhir/profile-schema, вы можете указать набор значений. Используйте свойство zen.fhir/value-set и укажите существующее имя набора значений в свойстве :symbol. Вам также необходимо указать степень привязки к набору значений в свойстве :strength. Поддерживаемые степени привязки:
MyPatientProfile
{:zen/tags #{zen/schema zen.fhir/profile-schema}
:zen.fhir/version "0.5.0"
:zen.fhir/profileUri "urn:fhir:extension:MyPatientProfile"
:confirms #{fhir/Patient}
:type zen/map
:keys {:gender {:confirms #{fhir/code},
:zen.fhir/value-set {:symbol fhir/administrative-gender,
:strength :required}}Как было сказано ранее, в zen-lang нет наследования, поэтому для описания ограничения вложенного элемента необходимо описать структуру, содержащую этот элемент. В следующем примере требуется, чтобы Patient.name.given присутствовал и содержал хотя бы один элемент:
MyPatientProfile
{:zen/tags #{zen/schema zen.fhir/profile-schema}
:zen.fhir/version "0.5.0"
:zen.fhir/profileUri "urn:fhir:extension:MyPatientProfile"
:confirms #{fhir/Patient}
:type zen/map
:require #{:name}
:keys {:name {:type zen/vector
:minItems 1
:every {:type zen/map
:require #{:given}
:keys {:given {:type zen/vector
:minItems 1}}}}}}Zen FHIR предлагает другой подход к расширениям как к первому классу вместо обычного способа FHIR через срезы. Расширения первого класса описываются так же, как и любые другие атрибуты и ограничения, но с добавлением URL-адреса расширения. В следующем примере описывается расширение первого класса us-core-race прямо внутри профиля:
MyPatientProfile
{:zen/tags #{zen/schema zen.fhir/profile-schema}
:zen.fhir/version "0.5.0"
:zen.fhir/profileUri "urn:fhir:extension:MyPatientProfile"
:confirms #{fhir/Patient}
:type zen/map
:keys {:race
{:type zen/map
:zen/desc "US Core Race Extension",
:fhir/extensionUri "http://hl7.org/fhir/us/core/StructureDefinition/us-core-race"
:require #{:text}
:keys {:ombCategory {:type zen/vector
:maxItems 5
:every {:confirms #{fhir/Coding}
:zen/desc "American Indian or Alaska Native|Asian|Black or African American|Native Hawaiian or Other Pacific Islander|White"
:zen.fhir/value-set {:symbol omb-race-category-value-set
:strength :required}}}
:detailed {:type zen/vector
:every {:confirms #{fhir/Coding}
:zen/desc "Extended race codes"
:zen.fhir/value-set {:symbol detailed-race-value-set
:strength :required}}}
:text {:confirms #{fhir/string}
:zen/desc "Race Text"}}}}}Обратите внимание, что элементы расширения имеют свойство :confirms для указанного примитивного или сложного типа данных FHIR. Ранее они указывались в схеме базового профиля. Эти :confirms и :fhir/extensionUri необходимы для преобразования формата zen FHIR <-> FHIR.
Структура, определяемая этой схемой, описывает данные такой формы:
resourceType: Patient
id: sample-pt
race:
category:
- {system: 'urn:oid:2.16.840.1.113883.6.238', code: 2028-9, display: Asian}
detailed:
- {system: 'urn:oid:2.16.840.1.113883.6.238', code: 2029-7, display: Asian Indian}
text: Asian IndianЗатем его можно преобразовать в формат FHIR, что приведет к следующему результату:
resourceType: Patient
id: sample-pt
extension:
- 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: 2028-9, display: Asian}
- url: detailed
valueCoding: {system: 'urn:oid:2.16.840.1.113883.6.238', code: 2029-7, display: Asian Indian}
- url: text
valueString: Asian IndianРасширения можно помещать в отдельную схему, если вы собираетесь повторно использовать их в разных профилях. Вот профиль us-core-race, обновленный таким образом:
us-core-race
{:zen/tags #{zen/schema zen.fhir/structure-schema}
:zen.fhir/version "0.5.0"
:zen.fhir/profileUri "http://hl7.org/fhir/us/core/StructureDefinition/us-core-race"
:type zen/map
:require #{:text}
:keys {:ombCategory {:type zen/vector
:maxItems 5
:every {:confirms #{fhir/Coding}
:zen/desc "American Indian or Alaska Native|Asian|Black or African American|Native Hawaiian or Other Pacific Islander|White"
:zen.fhir/value-set {:symbol omb-race-category-value-set
:strength :required}}}
:detailed {:type zen/vector
:every {:confirms #{fhir/Coding}
:zen/desc "Extended race codes"
:zen.fhir/value-set {:symbol detailed-race-value-set
:strength :required}}}
:text {:confirms #{fhir/string}
:zen/desc "Race Text"}}}
MyPatientProfile
{:zen/tags #{zen/schema zen.fhir/profile-schema}
:zen.fhir/version "0.5.0"
:zen.fhir/profileUri "urn:fhir:extension:MyPatientProfile"
:confirms #{fhir/Patient}
:type zen/map
:keys {:race {:confirms #{us-core-race}
:zen/desc "US Core Race Extension"
:fhir/extensionUri "http://hl7.org/fhir/us/core/StructureDefinition/us-core-race"}}}Более сложный пример расширения:
MyPatient
{:zen/tags #{zen/schema zen.fhir/profile-schema}
:zen/desc "Patient resource schema with first-class extension definition examples"
:zen.fhir/version "0.5.20"
:confirms #{zen.fhir/Resource}
:zen.fhir/type "Patient"
:zen.fhir/profileUri "urn:profile:MyPatientProfile"
:type zen/map
:keys {:meta {:type zen/map
:keys {:tenant-id
{:confirms #{fhir/string}
:zen/desc "Patient.meta.tenant-id first-class extension"
:fhir/extensionUri "http://tenant-id-extension-url"}}}
:form {:type zen/vector
:zen/desc "Patient.form.[*] array first-class extension"
:every {:confirms #{fhir/uri}
:fhir/extensionUri "http://patient-form-url"}}
:info {:type zen/map
:zen/desc "Patient.info nested first-class extension"
:fhir/extensionUri "http://patient-info"
:keys {:registration {:confirms #{fhir/dateTime}
:zen/desc "Patient.info.registration
extension.url deduced from key"}
:referral {:confirms #{fhir/uri}
:fhir/extensionUri "http://patient-info-referral"
:zen/desc "Patient.info.referral
extension.url is specified"}}}}}TODO
TODO
TODO