Краткое введение в Zen.
Документация по zen-lang: https://github.com/zen-fhir/zen.fhir
Референсная документация по FHIR Shorthand: https://build.fhir.org/ig/HL7/fhir-shorthand/reference.html
Zen-проект - это папка, в которой каждый файл - это namespace.
Имя namespace можно получить, заменив / на . в относительном пути файла.
Например, fhir/ru/patient.edn => fhir.ru.patient.
namespace - это структура данных в формате edn, а точнее это всегда map (словарь, объект), состоящий из ключей и значений.
Почитать про типы данных edn.
{ns fhir.ru.patient
import #{fhir.v4}
Patient
{:zen/tags #{zen/schema}
:confirms #{fhir.v4/Patient}
:type zen/map
:keys {}
}
Race
{:zen/tags #{zen/schema}
:type zen/map
:keys {}
}
}
Ключ задает имя модели, а значение - это ее описание. Модели могут ссылаться друг на друга в рамках namespace просто по имени Patient, а между namespace - по полному имени fhir.ru.patient/Patient.
Zen явно управляет зависимостями, поэтому для того, чтобы ссылаться на модели из других namespace, вам нужно сделать import.
Дополнительно, в файле zendoc/zrc/fhir/ru/core.edn необходимо прописать все созданные неймспейсы.
Пример:
{ns fhir.ru.core
import #{fhir.ru.core.organization
fhir.ru.core.patient
fhir.ru.core.encounter
fhir.ru.core.address
fhir.ru.core.department
fhir.ru.core.practitioner
fhir.ru.diag.nosology
fhir.ru.diag.nu
fhir.ru.diag.encounter
fhir.ru.lab.diagnosticreport
fhir.ru.core.vs-nsi-gender
fhir.ru.core.ext-nsi-gender}}
Модель в zen в общем случае - это произвольная структура данных.
Модель может быть протэгирована с помощью аттрибута :zen/tags #{}, значением которого является множество
символов, ссылающихся на другие модели. Тэги можно воспринимать как множественную классификацию - типы модели.
Zen имeет встроенный язык схем для описания структуры данных.
Модель интерпретируется как схема, если она имеет тэг zen/schema.
Профиль - это описание неких ограничений по сравнению со стандартным ресурсом или другим профилем. Подробнее о профилировании FHIR можно почитать на сайте стандарта.
Профили на ресурсы и типы данных, а также другие FHIR-артефакты (расширения, наборы значений, системы кодирования, системы идентификации) создаются в папке zrc/fhir/ru в соответствующей подпапке, например core, diag, lab, в виде файла с расширением .edn.
В начале указываем неймспейс в соответствии с путем до нашего файла. Например, если путь zrc/fhir/ru/core/observation.edn, значит ns будет fhir.ru.core.observation.
Дальше нужно указать импортируемые неймспейсы:
fhir - определения FHIR-ресурсов, расширений, типов данных в виде zen-схем в файле zrc/fhir.edn (импортируем всегда),zen.fhir - дополнительные схемы и определения zen-тегов, находящиеся в файле zrc/zen/fhir.edn (импортируем всегда),Затем указываем произвольный символ - название нашей схемы в соответствии с принятыми соглашениями по наименованию схем, и саму схему.
В схеме обязательно нужно указать теги :zen/tags.
Тэги служат для двух целей:
:zen/tags - это список схем, которым должна соответствовать наша схема. Если наша схема не соответствует задекларированным тегам, то мы увидим ошибки схемы на табе проверки схемы Schema errors.zen/schema - указываем всегда (для определения расширения, профилей на ресурсы FHIR, профилей на сложные типы данных)Дополнительно указываем теги:
zen.fhir/profile-schema - для профилей на ресурсыzen.fhir/structure-schema zen.fhir/extension - для определений расширенийzen.fhir/structure-schema zen.fhir/datatype - для профиля на сложный тип данныхУказываем элементы:
:type zen/map - указываем всегда, это тип нашей схемы:zendoc - ссылка на страницу документации (файл с расширением .zd) в нотации Zendoc. Эту ссылку можно скопировать в адресной строке браузера, открыв на сайте соотствующую страницу.:zen/desc - текстовое описание схемы, соответствует(?) StructureDefinition.title - человекочитаемое название:confirms - список наследуемых схем. При валидации, экземпляр ресурса будет проверен на соответствие нашей схеме плюс всем перечисленным здесь схемам.:require - список обязательных элементов:zen.fhir/version - версия zen, сейчас "0.5.8":zen.fhir/id - соответствует StructureDefinition.id:zen.fhir/name - соответствует StructureDefinition.name - машиночитаемое название:zen.fhir/type - соответствует StructureDefinition.type - тип ресурса или тип данных:zen.fhir/profileUri - соответствует StructureDefinition.url:zen.fhir/abstract - соответствует StructureDefinition.abstract (false):zen.fhir/status - соответствует StructureDefinition.status: draft | active | retired | unknown:zen.fhir/kind - соответствует StructureDefinition.kind::keys - список элементов ресурса/типа данных, для которых мы хотим ввести ограничения или расширения. Элементы, на которые ограничения не вводятся, не указываются в профиле вообще. Если нужно задать описание элемента на русском языке, то указываем необходимый элемент и задаем ему свойство :zen/desc. Стандартные свойства повторять в схеме профиля нет необходимости благодаря наследованию (элемент :confirms).{message: /app/docs/archive/zen-development/../../zrc/fhir/ru/core/observation.edn (No such file or directory)}
Обязательность атрибута указывается через элемент :require, в котором перечисляются обязательные элементы.
Например в ресурсе Composition:
:require #{:author :date :status :title :type}
Для массивов есть ключи :minItems и :maxItems, которые задают минимальное и максимальное количество элементов для атрибутов-массивов.
:payor {:type zen/vector
:minItems 1
:maxItems 5}
Ссылки на типы ресурсов/профили в элементе типа Reference определяются следующим образом:
у элемента указываем :confirms #{fhir/Reference zen.fhir/Reference}, затем в ключе :zen.fhir/reference {:refers #{fhir/Patient}} перечисляем разрешенные профилем типы ресурсов или схемы профилей на ресурсы.
В секции import необходимо указать файлы для всех внешних схем профилей, на которые мы ссылаемся, иначе будет ошибка.
Пример референса на стандартный тип ресурса Reference(Patient):
:subject {:confirms #{fhir/Reference zen.fhir/Reference}
:zen.fhir/reference {:refers #{fhir/Patient}}}Пример референса на наш профиль на ресурс Reference(CorePatient):
:subject {:confirms #{fhir/Reference zen.fhir/Reference}
:zen.fhir/reference {:refers #{fhir.ru.core.patient/CorePatient}}}Пример референса на несколько стандартных ресурсов Reference(Practitioner | PractitionerRole):
:performer {:confirms #{fhir/Reference zen.fhir/Reference}
:zen.fhir/reference {:refers #{fhir/Practitioner fhir/PractitionerRole}}}Пример референса на несколько профилей Reference(CorePractitioner | CorePractitionerRole):
:performer {:confirms #{fhir/Reference zen.fhir/Reference}
:zen.fhir/reference {:refers #{fhir.ru.core.practitioner/CorePractitioner fhir.ru.core.practitioner/CorePractitionerRole}}}Для указания системы кодирования, например по НСИ ЕГИСЗ, необходимо создать определение набора значений и привязать его к необходимому элементу профиля.
Value set - это набор кодированных значений, разрешенных в элементе.
Системы кодирования определяют концепты и придают им значение через формальные определения, а также назначают коды, которые предсатвляют эти концепты.
Value set задаёт набор кодов, определённых системами кодирования, который можно использовать в конкретном контексте.
Про различия между системой кодирования и набором значений можно посмотреть в Coded Values, Code Systems, and Value Sets и в ValueSet and CodeSystem.
Создать набор значений можно в том же файле, где и профиль, либо вынести в отдельный
{message: /app/docs/archive/zen-development/../../zrc/fhir/ru/support/valueset-template.edn (No such file or directory)}
Затем нужно создать страницу документации для нового набора значений. Это можно сделать по шаблону artifacts.valuesets.vs-template. Страница автоматически попадет в реестр наборов значений.
:zen.fhir/value-set {:symbol CoreVsIdentifierType :strength :extensible}Для добавления флага Must Support укажите в схеме элемента следующее свойство:
:fhir/flags #{:MS}Например:
:gender
{:confirms #{fhir/code}
:fhir/flags #{:MS}}Чтобы сделать элемент схемы ссылкой, укажите в схеме элемента следующее свойство:
:zen.fhir/href "core.Patient#:elements:gender"Например:
:gender
{:confirms #{fhir/code}
:zen.fhir/href "core.Patient#:elements:gender"}