Welcome to fhirbug’s documentation!

Fhirbug intends to be a full-featured FHIR server for python >= 3.6. It has been designed to be easy to set up and configure and be flexible when it comes to the rest of tools it is combined with, like web frameworks and database interfaces. In most simple cases, very little code has to be written apart from field mappings.

Fhirbug is still under development! The API may still change at any time, it probably contains heaps of bugs and has never been tested in production. If you are interested in making it better, you are very welcome to contribute!

What fhirbug does:

  • It provides the ability to create “real time” transformations between your ORM models to valid FHIR resources through an extensive mapping API.
  • Has been designed to work with existing data-sets and database schemas but can of course be used with its own database.
  • It’s compatible with the SQLAlchemy, DjangoORM and PyMODM ORMs, so if you can describe your database in one of them, you are good to go. It should also be pretty easy to extend to support any other ORM, feel free to submit a pull request!
  • Handles many of the FHIR REST operations and searches like creating and updating resources, performing advanced queries such as reverse includes, paginated bundles, contained or referenced resources, and more.
  • Provides the ability to audit each request, at the granularity that you desire, all the way down to limiting which of the attributes for each model should be accessible for each user.

What fhirbug does not do:

  • Provide a ready to use solution for a Fhir server. Fhirbug is a framework, we want things to be as easy as possible but you will still have to write code.
  • Contain a web server. Fhirbug takes over once there is a request string and request body and returns a json object. You have to handle the actual requests and responses.
  • Handle authentication and authorization. It supports it, but you must write the implementation.
  • A ton of smaller stuff, which you can find in the Roadmap_.

Quickstart

This section contains a brief example of creating a simple application using fhirbug. It’s goal is to give the reader a general idea of how fhirbug works, not to provide them with in-depth knowledge about it.

For a more detailed guide check out the Overview and the API docs.

Preparation

In this example we will use an sqlite3 database with SQLAlchemy and flask. The first is in the standard library, you can install SQLAlchemy and flask using pip:

$ pip install sqlalchemy flask

Let’s say we have a very simple database schema, for now only containing a table for Patients and one for hospital admissions. The SQLAlchemy models look like this:

models.py
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, DateTime, Integer, String, ForeignKey
from sqlalchemy.orm import relationship

Base = declarative_base()


class PatientModel(Base):
    __tablename__ = 'patients'

    patient_id = Column(Integer, primary_key=True)
    first_name = Column(String)
    last_name = Column(String)
    dob = Column(DateTime)    # date of birth
    gender = Column(Integer)  # 0: female, 1: male, 2: other, 3: unknown


class AdmissionModel(Base):
    __tablename__ = 'admissions'

    id = Column(Integer, primary_key=True)
    status = Column(String) # 'a': active, 'c': closed
    patient_id = Column(Integer, ForeignKey('patients.patient_id'))
    date_start = Column(DateTime)  # date and time of admission
    date_end = Column(DateTime)    # date and time of release

    patient = relationship("patientmodel", back_populates="admissions")

To create the database and tables, open an interactive python shell and type the following:

>>> from sqlalchemy import create_engine
>>> from models import Base

>>> engine = create_engine('sqlite:///:memory:')
>>> Base.metadata.create_all(engine)

Creating your first Mappings

We will start by creating mappings between our Patient and Admission models and the Patient and Encounter FHIR resources. In our simple example the mapping we want to create looks something like this:

Relationships between db columns and fhir attributes for the Patient
DB column FHIR attribute notes
patient_id id read-only
first_name, last_name name first and last name must be combined into a HumanName resource
dob birthDate must be converted to type FHIRDate
gender gender values must be translated between the two systems (eg: 0 -> ‘female’)

Mapping in fhirbug is pretty straightforward. All we need to do is:

  1. Subclass the model class, inheriting from FhirBaseModel
  2. Add a member class called FhirMap
  3. Inside it, add class attributes using the names of the fhir attributes of the resource you are setting up.
  4. Use Attributes to describe how the conversion between db columns and FHIR attributes should happen

Since we are using SQLAlchemy, we will use the fhirbug.db.backends.SQLAlchemy module, and more specifically inherit our Mappings from fhirbug.db.backends.SQLAlchemy.models.FhirBaseModel

So, we start describing our mapping for the Patient resource from the id field which is the simplest:

Warning

Fhirbug needs to know which ORM the mappings we create are for. Therefore, before importing FhirBaseModel, we must have configured the fhirbug settings. If you write the following code in an interactive session instead of a file, you will get an error unless you configure fhirbug first. To do so, just paste the code described below.

mappings.py
from models import Patient as PatientModel
from fhirbug.db.backends.SQLAlchemy.models import FhirBaseModel
from fhirbug.models.attributes import Attribute

class Patient(PatientModel, FhirBaseModel):
    class FhirMap:
        id = Attribute('patient_id')

Note

The fact that we named the mapper class Patient is important, since when fhirbug looks for a mapper, it looks by default for a class with the same name as the fhir resource.

By passing the column name as a string to the Attribute we tell fhirbug that the id attribute of the Patient FHIR resource should be retrieved from the patient_id column.

For the birthDate attribute we get the information from a single database column, but it must be converted to and from a FHIR DateTime datatype. So, we will use the DateAttribute helper and let it handle conversions automatically.

We will also add the name attribute, using the NameAttribute helper. We tell it that we get and set the family name from the column last_name and the given name from first_name

mappings.py
from models import Patient as PatientModel
from fhirbug.db.backends.SQLAlchemy.models import FhirBaseModel
from fhirbug.models.attributes import Attribute, DateAttribute, NameAttribute

class Patient(PatientModel, FhirBaseModel):
    class FhirMap:
        id = Attribute('patient_id')
        birthDate = DateAttribute('dob')
        name = NameAttribute(family_getter='last_name',
                             family_setter='last_name',
                             given_getter='first_name',
                             given_setter='first_name')

Letting the magic happen

Let’s test what we have so far. First, we must provide fhirbug with some basic configuration:

>>> from fhirbug.config import settings
>>> settings.configure({
...     'DB_BACKEND': 'SQLAlchemy',
...     'SQLALCHEMY_CONFIG': {
...         'URI': 'sqlite:///:memory:'
...     }
... })

Now, we import or mapper class and create an item just as we would if it were a simple SQLAlchemy model:

>>> from datetime import datetime
>>> from mappings import Patient
>>> patient = Patient(dob=datetime(1980, 11, 11),
...                   first_name='Alice',
...                   last_name='Alison')

This patient object we have created here is a classic SQLAlchemy model. We can save it, delete it, change values for its columns, etc. But it has also been enhanced by fhirbug.

Here’s some stuff that we can do with it:

>>> to_fhir = patient.to_fhir()
>>> to_fhir.as_json()
{
    'birthDate': '1980-11-11T00:00:00',
    'name': [{'family': 'Alison', 'given': ['Alice']}],
    'resourceType': 'Patient'
}

The same way that all model attributes are accessible from the patient instance, all FHIR attributes are accessible from patient.Fhir:

>>> patient.Fhir.name
<fhirbug.Fhir.Resources.humanname.HumanName at 0x7fc62e1cbcf8>
>>> patient.Fhir.name.as_json()
{'family': 'Alison', 'given': ['Alice']}
>>> patient.Fhir.name.family
'Alison'
>>> patient.Fhir.name.given
['Alice']

If you set an attribute on the FHIR resource:

>>> patient.Fhir.name.family = 'Walker'

The change is applied to the actual database model!

>>> patient.last_name
'Walker'
>>> patient.Fhir.birthDate = datetime(1970, 11, 11)
>>> patient.dob
datetime.datetime(1970, 11, 11, 0, 0)

Handling requests

We will finish this quick introduction to fhirbug with a look on how requests are handled. First, let’s create a couple more entries:

>>> from datetime import datetime
>>> from fhirbug.config import settings
>>> settings.configure({
...     'DB_BACKEND': 'SQLAlchemy',
...     'SQLALCHEMY_CONFIG': {
...         'URI': 'sqlite:///:memory:'
...     }
... })
>>> from fhirbug.db.backends.SQLAlchemy.base import session
>>> from mappings import Patient
>>> session.add_all([
...     Patient(first_name='Some', last_name='Guy', dob=datetime(1990, 10, 10)),
...     Patient(first_name='Someone', last_name='Else', dob=datetime(1993, 12, 18)),
...     Patient(first_name='Not', last_name='Me', dob=datetime(1985, 6, 6)),
... ])
>>> session.commit()

Great! Now we can simulate some requests. The mapper class we defined earlier is enough for us to get some nice FHIR functionality like searches.

Let’s start by asking for all Patient entries:

>>> from fhirbug.server.requestparser import parse_url
>>> query = parse_url('Patient')
>>> Patient.get(query, strict=False)
{
    "entry": [
        {
            "resource": {
                "birthDate": "1990-10-10T00:00:00",
                "name": [{"family": "Guy", "given": ["Some"]}],
                "resourceType": "Patient",
            }
        },
        {
            "resource": {
                "birthDate": "1993-12-18T00:00:00",
                "name": [{"family": "Else", "given": ["Someone"]}],
                "resourceType": "Patient",
            }
        },
        {
            "resource": {
                "birthDate": "1985-06-06T00:00:00",
                "name": [{"family": "Me", "given": ["Not"]}],
                "resourceType": "Patient",
            }
        },
    ],
    "resourceType": "Bundle",
    "total": 3,
    "type": "searchset",
}

We get a proper Bundle Resource containing all of our Patient records!

Advanced Queries

This quick guide is almost over, but before that let us see some more things Fhirbug can do. We start by asking only one result per page.

>>> query = parse_url('Patient?_count=1')
>>> Patient.get(query, strict=False)
{
    "entry": [
        {
            "resource": {
                "birthDate": "1990-10-10T00:00:00",
                "name": [{"family": "Guy", "given": ["Some"]}],
                "resourceType": "Patient",
            }
        }
    ],
    "link": [
        {"relation": "next", "url": "Patient/?_count=1&search-offset=2"},
        {"relation": "previous", "url": "Patient/?_count=1&search-offset=1"},
    ],
    "resourceType": "Bundle",
    "total": 4,
    "type": "searchset",
}

Notice how when defining our mappings we declared birthDate as a DateAttribute and name as a NameAttribute? This allows us to use several automations that Fhirbug provides like advanced searches:

>>> query = parse_url('Patient?birthDate=gt1990&given:contains=one')
>>> Patient.get(query, strict=False)
{
    "entry": [
        {
            "resource": {
                "birthDate": "1993-12-18T00:00:00",
                "name": [{"family": "Else", "given": ["Someone"]}],
                "resourceType": "Patient",
            }
        }
    ],
    "resourceType": "Bundle",
    "total": 1,
    "type": "searchset",
}

Here, we ask for all Patients that were born after 1990-01-01 and whose given name contains one.

Further Reading

You can dive into the actual documentation starting at the Overview or read the docs for the API.

Overview

Creating Mappings

Fhirbug offers a simple declarative way to map your database tables to Fhir Resources. You need to have created models for your tables using one of the supported ORMs.

Let’s see an example using SQLAlchemy. Suppose we have this model of our database table where patient personal infrormation is stored.

(Note that we have named the model Patient. This allows Fhirbug to match it to the corresponding resource automatically. If we wanted to give it a different name, we would then have to define __Resource__ = ‘Patient’ after the __tablename__)

from sqlalchemy import Column, Integer, String

class Patient(Base):
    __tablename__ = "PatientEntries"

    id = Column(Integer, primary_key=True)
    name_first = Column(String)
    name_last = Column(String)
    gender = Column(Integer)  # 0: unknown, 1:female, 2:male
    ssn = Column(Integer)

To map this table to the Patient resource, we will make it inherit it fhirbug.db.backends.SQLAlchemy.FhirBaseModel instead of Base. Then we add a class named FhirMap as a member and add all fhir fields we want to support using Attributes:

Note

You do not need to put your FhirMap in the same class as your models. You could just as well extend it in a second class while using FhirBaseModel as a mixin.

from sqlalchemy import Column, Integer, String
from fhirbug.db.backends.SQLAlchemy import FhirBaseModel
from fhirbug.models import Attribute, NameAttribute
from fhirbug.db.backends.SQLAlchemy.searches import NumericSearch

class Patient(FhirBaseModel):
    __tablename__ = "PatientEntries"

    pat_id = Column(Integer, primary_key=True)
    name_first = Column(String)
    name_last = Column(String)
    gender = Column(Integer)  # 0: unknown, 1:female, 2:male, 3:other
    ssn = Column(Integer)

    @property
    def get_gender(self):
        genders = ['unknown', 'female', 'male', 'other']
        return genders[self.gender]

    @set_gender.setter
    def set_gender(self, value):
        genders = {'unknown': 0, 'female': 1, 'male': 2, 'other': 3}
        self.gender = genders[value]

    class FhirMap:
        id = Attribute('pat_id', searcher=NumericSearch('pid'))
        name = NameAttribute(given_getter='name_first', family_getter='name_last')
        def get_name(instance):
        gender = Attribute('get_gender', 'set_gender')

FHIR Resources

Fhirbug uses fhir-parser to automatically parse the Fhir specification and generate classes for resources based on resource definitions. It’s an excellent tool that downloads the Resource Definition files from the official website of FHIR and generates classes automatically. For more details, check out the project’s repository.

Fhirbug comes with pre-generated classes for all FHIR Resources, which live inside fhirbug.Fhir.resources. You can generate your own resource classes based on a subset or extension of the default resource definitions but this is not currently covered by this documentation.

Uses of FHIR Resources in Fhirbug

As return values of mapper.to_fhir()

FHIR Resource classes are used when a mapper instance is converted to a FHIR Resource using .to_fhir().

Supposing we have defined a mapper for the Location resource, we could see the following:

>>> Location
mappings.Location
>>> location = Location.query.first()
<mappings.Location>
>>> location.to_fhir()
<fhirbug.Fhir.Resources.patient.Patient>
As values for mapper Attributes

FHIR Resources are also used as values for mapper attributes that are either references to other Resources, Backbone Elements or complex datatypes.

For example, let’s return back to the Location example. As we can see in the FHIR specification, the Location.address attribute is of type Address. This would mean something like this:

>>> location.Fhir.address
<fhirbug.Fhir.Resources.address.Address>
>>> location.Fhir.address.as_json()
{
    'use': 'work',
    'type': 'physical',
    [...]
}
>>> location.Fhir.address.use
'work'

Creating resources

You will be wanting to use the Resource classes to create return values for your mapper attributes.

The default way for creating resource instances is by passing a json object to the constructor:

>>> from fhirbug.Fhir.resources import Observation
>>> o = Observation({
...     'id': '2',
...     'status': 'final',
...     'code': {'coding': [{'code': '5', 'system': 'test'}]},
... })

As you can see, this may get a but verbose so there are several shortcuts to help with that.

Resource instances can be created:

  • by passing a dict with the proper json structure as we already saw

  • by passing the same values as keyword arguments:

    >>> o = Observation(
    ...     id='2', status='final', code={'coding': [{'code': '5', 'system': 'test'}]}
    ... )
    
  • when an attribute’s type is a Backbone Element or a complex type, we can pass a resource:

    >>> from fhirbug.Fhir.resources import CodeableConcept
    >>> test_code = CodeableConcept(coding=[{'code': '5', 'system': 'test'}])
    >>> o = Observation(id='2', status='final', code=test_code)
    
  • When an attribute has a cardinality larger than one, that is its values are part of an array, but we only want to pass one value, we can skip the array:

    >>> test_code = CodeableConcept(coding={'code': '5', 'system': 'test'})
    >>> o = Observation(id='2', status='final', code=test_code)
    

Fhirbug tries to make it as easy to create resources as possible by providing several shortcuts with the base contructor.

Ignore missing required Attributes

If you try to initialize a resource without providing a value for a required attribute you will get an error:

>>> o = Observation(id='2', status='final')
FHIRValidationError: {root}:
'Non-optional property "code" on <fhirbug.Fhir.Resources.observation.Observation object>
is missing'

You can suppress errors into warnings by passing the strict=False argument:

>>> o = Observation(id='2', status='final', strict=False)

Fhirbug will display a warning but it will not complain again if you try to save or serve the instance. It’s up to you make sure that your data is well defined.

The base Resource class

Tis is the abstract class used as a base to provide common functionality to all produced Resource classes. It has been modified in order to provide a convenient API for Creating resources.

class fhirbug.Fhir.base.fhirabstractbase.FHIRAbstractBase
FHIRAbstractBase.__init__(jsondict=None, strict=True, **kwargs)

Initializer. If strict is true, raises on errors, otherwise uses logger.warning().

Raises:

FHIRValidationError on validation errors, unless strict is False

Parameters:
  • jsondict (dict) – A JSON dictionary or array or an (array of) instance(s) of an other resource to use for initialization
  • strict (bool) – If True (the default), invalid variables will raise a TypeError
  • kwargs – Instead of a JSON dict, parameters can also be passed as keyword arguments

Parameters that are not defined in FHIR for this resource are ignored.

FHIRAbstractBase.as_json()

Serializes to JSON by inspecting elementProperties() and creating a JSON dictionary of all registered properties. Checks:

  • whether required properties are not None (and lists not empty)
  • whether not-None properties are of the correct type
Raises:FHIRValidationError if properties have the wrong type or if required properties are empty
Returns:A validated dict object that can be JSON serialized
FHIRAbstractBase.elementProperties()

Returns a list of tuples, one tuple for each property that should be serialized, as: (“name”, “json_name”, type, is_list, “of_many”, not_optional)

FHIRAbstractBase.mandatoryFields()

Returns a list of properties that are marked as mandatory / not_optional.

FHIRAbstractBase.owningResource()

Walks the owner hierarchy and returns the next parent that is a DomainResource instance.

FHIRAbstractBase.owningBundle()

Walks the owner hierarchy and returns the next parent that is a Bundle instance.

Auditing

With Fhirbug you can audit requests on three levels:

  • Request level: Allow or disallow the specific operation on the specific resource, and
  • Resource level: Allow or disallow access to each individual resource and/or limit access to each of its attributes.
  • Attribute level: Allow or disallow access to each individual attribute for each resource.

Warning

The Auditing API is still undergoing heavy changes and is even more unstable than the rest of the project. Use it at your own risk!

Auditing at the request level

All you need to do do in order to implement request-level auditing in Fhribug is to provide the built-in fhirbug.server.requesthandlers with an extra method called audit_request.

This method should accept a single positional parameter, a FhirRequestQuery and should return an AuditEvent. If the outcome attribute of the returned AuditEvent is “0” (the code for “Success”), the request is processed normally.

from fhirbug.server.requesthandlers import GetRequestHandler
from fhirbug.Fhir.resources import AuditEvent

class CustomGetRequestHandler(GetRequestHandler):
    def audit_request(self, query):
        return AuditEvent(outcome="0", strict=False)

The simplest possible auditing handler, one that approves all requests.

In any other case, the request fails with status code 403, and returns an OperationOutcome resource containing the outcomeDesc of the AuditEvent. This way you can return information about the reasons for failure.

from fhirbug.server.requesthandlers import GetRequestHandler
from fhirbug.Fhir.resources import AuditEvent

class CustomGetRequestHandler(GetRequestHandler):
    def audit_request(self, query):
        if "_history" in query.modifiers:
            if is_authorized(query.context.user):
                return AuditEvent(outcome="0", strict=False)
            else:
                return AuditEvent(
                    outcome="8",
                    outcomeDesc="Unauthorized accounts can not access resource history.",
                    strict=False
                )

Note

Notice how we passed strict=False to the AuditEvent constructor? That’s because without it, it would not allow us to create an AuditEvent resource without filling in all its required fields.

However, since we do not store it in this example and instead just use it to communicate with the rest of the application, there is no need to let it validate our resource.

Since Fhirbug does not care about your web server implementation, or your authentication mechanism, you need to collect and provide the information neccessary for authenticationg the request to the audit_request method.

Fhirbug’s suggestion is passing this information through the query.context object, by providing query_context when calling the request handler’s handle method.

Auditing at the resource level

Controlling access to the entire resource

In order to implement auditing at the resource level, give your mapper models one or more of the methods audit_read, audit_create, audit_update, audit_delete. The signature for these methods is the same as the one for request handlers we saw above. They accept a single parameter holding a FhirRequestQuery and should return an AuditEvent, whose outcome should be "0" for success and anything else for failure.

class Patient(FhirBaseModel):
    # Database field definitions go here

    def audit_read(self, query):
        return AuditEvent(outcome="0", strict=False)

    class FhirMap:
        # Fhirbug Attributes go here

You can use Mixins to let resources share common auditing methods:

class OnlyForAdmins:
    def audit_read(self, query):
        # Assuming you have passed the appropriate query cintext to the request handler
        isSuperUser = query.context.User.is_superuser

        return (
            AuditEvent(outcome="0", strict=False)
            if isSuperUser
            else AuditEvent(
                outcome="4",
                outcomeDesc="Only admins can access this resource",
                strict=False,
            )
        )

class AuditRequest(OnlyForAdmins, FhirBaseModel):
    # Mapping goes here

class OperationOutcome(OnlyForAdmins, FhirBaseModel):
    # Mapping goes here

    ...
Controlling access to specific attributes

If you want more refined control over which attributes can be changed and displayed, during the execution of one of the above audit_* methods, you can call self.protect_attributes(*attrs*) and /or self.hide_attributes(*attrs*) inside them.

In both cases, *attrs* should be an iterable that contains a list of attribute names that should be protected or hidden.

protect_attributes()

The list of attributes passed to protect_attributes will be marked as protected for the duration of this request and will not be allowed to change

hide_attributes()

The list of attributes passed to hide_attributes will be marked as hidden for the current request. This means that in case of a POST or PUT request they may be changed but they will not be included in the response.

For example if we wanted to hide patient contact information from unauthorized users, we could do the following:

class Patient(FhirBaseModel):
    # Database field definitions go here

    def audit_read(self, query):
        if not is_authorized(query.context.user):
            self.hide_attributes(['contact'])
        return AuditEvent(outcome="0", strict=False)

    class FhirMap:
        # Fhirbug Attributes go here

Similarly, if we wanted to only prevent unauthorized users from changing the Identifiers of Patients we would use protect_attributes:

class Patient(FhirBaseModel):
    # Database field definitions go here

    def audit_update(self, query):
        if not is_authorized(query.context.user):
            self.protect_attributes = ['identifier']
        return AuditEvent(outcome="0", strict=False)

    class FhirMap:
        # Fhirbug Attributes go here

Auditing at the attribute level

Warning

This feature is more experimental than the rest. If you intend to use it be aware of the complications that may rise because you are inside a desciptor getter (For example trying to get the specific attribute’s value would result in an infinte loop)

When declaring attributes, you can provide a function to the audit_set and audit_get keyword arguments. These functions accept three positional arguments:

The first is the instance of the Attribute descriptor, the second, query being the FhirRequestQuery for this request and the third being the attribute’s name It should return True if access to the attribute is allowed, or False otherwise.

It’s also possible to deny the entire request by throwing an AuthorizationError

audit_get(descriptor, query, attribute_name) → boolean
Parameters:
  • query (FhirRequestQuery) – The FhirRequestQuery object for this request
  • attribute_name (str) – The name this attribute has been assigned to
Returns:

True if access to this attribute is allowed, False otherwise

Return type:

boolean

audit_set(descriptor, query, attribute_name) → boolean
Parameters:
  • query (FhirRequestQuery) – The FhirRequestQuery object for this request
  • attribute_name (str) – The name this attribute has been assigned to
Returns:

True if changing this attribute is allowed, False otherwise

Return type:

boolean

Logging

Fhirbug’s RequestHandlers all have a method called log_request that is called whenever a request is done being proccessed with several information about the request.

By default, this method returns an AuditEvent FHIR resource instance populated with available information about the request.

Enhancing or persisting the default handler

Enhancing the generated AuditEvents with extra information about the request and Persisiting them is pretty simple. Just use custom RequestHandlers and override the log_request method:

from fhirbug.Fhir.resources import AuditEventEntity
from fhirbug.config import import_models

class EnhancedLoggingMixin:
    def log_request(self, *args, **kwargs):
        audit_event = super(EnhancedLoggingMixin, self).log_request(*args, **kwargs)

        context = kwargs["query"].context
        user = context.user
        # We populate the entity field with info about the user
        audit_event.entity = [
            AuditEventEntity({
                "type": {"display": "Person"},
                "name": user.username,
                "description": user.userid,
            })
        ]
        return audit_event


class PersistentLoggingMixin:
    def log_request(self, *args, **kwargs):
        audit_event = super(PersistentLoggingMixin, self).log_request(*args, **kwargs)
        models = import_models()
        AuditEvent = getattr(models, 'AuditEvent')
        audit_event_model = AuditEvent.create_from_resource(audit_event)
        return audit_event

# Create the handler
class CustomGetRequestHandler(
    PersistentLoggingMixin, EnhancedLoggingMixin, GetRequestHandler
):
    pass

Note

In order to have access to the user instance we assume you have passed a query context to the request handler’s handle method containing the necessary info

Note

Note that the order in which we pass the mixins to the custom handler class is important. Python applies mixins from right to left, meaning PersistentLoggingMixin’s super() method will call EnhancedLoggingMixin’s log_request and EnhancedLoggingMixin’s super() method will call GetRequestHandler’s

So, we expect the AuditEvent that is persisted by the PersistentLoggingMixin to contain information about the user because it is comes before EnhancedLoggingMixin in the class definition

Creating a custom log handler

If you don’t want to use fhirbug’s default log handling and want to implement something your self, the process is pretty much the same. You implement your own log_request method and process the information that is passed to it by fhirbug any way you want. Essentially the only difference with the examples above is that you do not call super() inside your custom log function.

The signature of the log_request function is the following:

AbstractRequestHandler.log_request(self, url, query, status, method, resource=None, OperationOutcome=None, request_body=None, time=datetime.now())[source]

Create an AuditEvent resource that contains details about the request.

Parameters:
  • url (string) – The initial url that was requested
  • query (FhirRequestQuery) – The FhirRequestQuery that was generated
  • status (int) – The status code that was returned
  • method (string) – The request method
  • resource (FhirResource) – A Fhir resource, possibly a bundle, of the resources that were accessed or modified during the request
  • OperationOutcome (OperationOutcome) – An OperationOutcome related to the requset
  • request_body – The body of the request
  • time (datetime) – The time the request occured

Here’s an example where we use python’s built-in logging module:

from datetme import datetime
from logging import getLogger

logger = getLogger(__name__)

class CustomGetRequestHandler(GetRequestHandler):
    def log_request(self, url, status, method, *args, **kwargs):
        logger.info("%s: %s %s %s" % (datetime.now(), method, url, status))

API

Attributes

class fhirbug.models.attributes.Attribute(getter=None, setter=None, searcher=None, search_regex=None, audit_get=None, audit_set=None)[source]

The base class for declaring db to fhir mappings. Accepts three positional arguments, a getter, a setter and a searcher.

The getter parameter can be a string, a tuple, a callable or type const.

  • Using a string:
>>> from types import SimpleNamespace as SN
>>> class Bla:
...   _model = SN(column_name=12)
...   p = Attribute('column_name')
...
>>> b = Bla()
>>> b.p
12
  • Strings can also be properties:
>>> class Model:
...  column_name = property(lambda x: 13)
>>> class Bla:
...   _model = Model()
...   p = Attribute('column_name')
...
>>> b = Bla()
>>> b.p
13
  • Callables will be called:
>>> class Bla:
...   _model = SN(column_name=12)
...   def get_col(self):
...     return 'test'
...   p = Attribute(get_col)
...
>>> b = Bla()
>>> b.p
'test'
  • As a shortcut, a tuple (col_name, callable) can be passed. The result will be callable(_model.col_name)
>>> import datetime
>>> class Bla:
...  _model = SN(date='2012')
...  p = Attribute(('date', int))
...
>>> b = Bla()
>>> b.p
2012

The setter parameter can be a string, a tuple, a callable or type const.

  • Using a string:
>>> class Bla:
...  _model = SN(date='2012')
...  p = Attribute(setter='date')
...
>>> b = Bla()
>>> b.p = '2013'
>>> b._model.date
'2013'
  • Again, the string can point to a property with a setter:
>>> class Model:
...  b = 12
...  def set_b(self, value):
...    self.b = value
...  column_name = property(lambda self: self.b, set_b)
>>> class Bla:
...   _model = Model()
...   p = Attribute(getter='column_name', setter='column_name')
...
>>> b = Bla()
>>> b.p = 13
>>> b.p == b._model.b == 13
True
  • Callables will be called:
>>> class Bla:
...   _model = SN(column_name=12)
...   def set_col(self, value):
...     self._model.column_name = value
...   p = Attribute(setter=set_col)
...
>>> b = Bla()
>>> b.p = 'test'
>>> b._model.column_name
'test'
  • Two-tuples contain a column name and a callable or const. Set the column to the result of the callable or const
>>> def add(column, value):
...  return column + value
>>> class Bla:
...   _model = SN(column_name=12)
...   p = Attribute(setter=('column_name', add))
...
>>> b = Bla()
>>> b.p = 3
>>> b._model.column_name
15
class fhirbug.models.attributes.BooleanAttribute(*args, save_true_as=1, save_false_as=0, default=None, truthy_values=['true', 'True', 1, '1'], falsy_values=['false', 'False', '0', 0], **kwargs)[source]

Used for attributes representing boolean types. truthy_values and falsy_values are used to determine which possible values from the database we should consider as True and False. Values that are not in any of the lists are mapped to default and if that is None, a MappingValidationError is thrown.

Parameters:
  • save_true_as – How do we save True in the database
  • save_false_as – How do we save Fasle in the database
  • deafult – If we read a value that is not in truthy_values or falsy_values, it will default to ths value.
  • truthy_values (list) – Which values, when read from the database should be mapped to True
  • falsy_values (list) – Which values, when read from the database should be mapped to False
class fhirbug.models.attributes.DateAttribute(field, audit_get=None, audit_set=None)[source]
class fhirbug.models.attributes.EmbeddedAttribute(*args, type=None, **kwargs)[source]

An attribute representing a BackboneElement that is described by a model and is stored using an ORM relationship, usually a ForeignKeyField or an embedded mongo document.

dict_to_resource(dict)[source]

Convert a dictionary to an instance of the corresponding FHIR resource

class fhirbug.models.attributes.NameAttribute(family_getter=None, given_getter=None, family_setter=None, given_setter=None, join_given_names=False, pass_given_names=False, getter=None, setter=None, searcher=None, given_join_separator=' ', audit_get=None, audit_set=None)[source]

NameAttribute is for used on fields that represnt a HumanName resource. The parameters can be any of the valid getter and setter types for simple Attribute

Parameters:
  • family_getter – A getter type parameter for the family name.
  • given_getter – A getter type parameter for the given name
  • family_setter – A setter type parameter for the family name
  • given_setter – A getter type parameter for the given name
class fhirbug.models.attributes.ReferenceAttribute(cls, id, name, setter=None, force_display=False, searcher=None)[source]

A Reference to some other Resource that may be contained.

fhirbug.models.attributes.audited(func)[source]

A decorator that adds auditing functionality to the __get__ and __set__ methods of descriptor Attributes. Attribute auditors, depending on the result of the audit, can return True, meaning access to the attribute has been granted or False, meaning access has been denied but execution should continue normally. If execution should stop and an error returned to the requester, it should raise an exception.

class fhirbug.models.attributes.const(value)[source]

const can be used as a getter for an attribute that should always return the same value

>>> from types import SimpleNamespace as SN
>>> class Bla:
...   p = Attribute(const(12))
...
>>> b = Bla()
>>> b.p
12

Mixins

class fhirbug.models.mixins.FhirAbstractBaseMixin[source]

Adds additional fhir related functionality to all models. Most importantly, it provides the .to_fhir() method that handles the transformation from an SQLAlchemy model to a Fhir resource. User-defined models subclassing this class must implement a FhirMap nested class.

classmethod from_resource(resource, query=None)[source]

Creates and saves a new row from a Fhir.Resource object

get_params_dict(resource, elements=None)[source]

Return a dictionary of all valid values this instance can provide for a resource of the type resource.

Parameters:resource – The class of the resource we wish to create
Returns:A dictionary to be used as an argument to initialize a resource instance
get_rev_includes(query)[source]

Read the _revincludes that were asked for in the request, query the database to retrieve them and add them to the initial resources contained field.

Parameters:query (fhirbug.server.requestparser.FhirRequestQuery) – A FhirRequestQuery object holding the current request.
Returns:None
hide_attributes(attribute_names=[])[source]

Accepts a list of attribute names and marks them as hidden, meaning they will not be included in json representations of this item. Subsequent calls replace the previous attribute list.

Parameters:attribute_names (list) – A list of Fhir attribute names to set as hidden
protect_attributes(attribute_names=[])[source]

Accepts a list of attribute names and protects them for the duration of the current operation. Protected attributes can not be changed when creating or editing a resource. Subsequent calls replace the previous attribute list.

Parameters:attribute_names (list) – A list of Fhir attribute names to set as protected
to_fhir(*args, query=None, **kwargs)[source]

Convert from a BaseModel to a Fhir Resource and return it.

If param query is passed and is of type server.FhirRequestQuery, it is used to allow for additional functionality like contained resources.

update_from_resource(resource, query=None)[source]

Edits an existing row from a Fhir.Resource object

class fhirbug.models.mixins.FhirBaseModelMixin[source]
Fhir

Wrapper property that initializes an instance of FhirMap.

classmethod get(query, *args, **kwargs)[source]

Handle a GET request

classmethod get_searcher(query_string)[source]

Return the first search function that matches the provided query string

Parameters:query_string (string) – A query string that is matched against registered field names or regular expressions by existing searchers
Returns:function
classmethod has_searcher(query_string)[source]

Search if this resource has a registered searcher for the provided query string

Parameters:query_string (string) – A query string that is matched against registered field names or regular expressions by existing searchers
Returns:bool
classmethod searchables()[source]

Returns a list od two-tuples containing the name of a searchable attribute and the function that searches for it based on the Attribute definitions in the FhirMap subclass.

fhirbug.models.mixins.get_pagination_info(query)[source]

Reads item count and offset from the provided FhirRequestQuery instance, or the application settings. It makes count obay MAX_BUNDLE_SIZE and calculates which page we are on.

Parameters:query (FhirRequestQuery) – The FhirRequestQuery object for this request.
Returns:(page, count, prev_offset, next_offset) The number of the page we are on, how many items we should show, the offset of the next page and the offset of the previous page.
Return type:(int, int, int, int)

fhirbug.server

Request Parsing

class fhirbug.server.requestparser.FhirRequestQuery(resource, resourceId=None, operation=None, operationId=None, modifiers={}, search_params={}, body=None, request=None)[source]

Represents parsed parameters from requests.

modifiers = None

Dictionary. Keys are modifier names and values are the provided values. Holds search parameters that start with an underscore. For example Patient/123?_format=json would have a modifiers value of {'_format': 'json'}

operation = None

A string holding the requested operation such as $meta or $validate

operationId = None

Extra parameters passed after the operation. For example if Patient/123/_history/2 was requested, operation would be _history and operationId would be 2

resource = None

A string containing the name of the requested Resource. eg: 'Procedure'

resourceId = None

The id of the requested resource if a specific resource was requested else None

search_params = None

Dictionary. Keys are parameter names and values are the provided values. Holds search parameters that are not modifiers For example Patient/123?_format=json would have a modifiers value of {'_format': 'json'}

fhirbug.server.requestparser.generate_query_string(query)[source]

Convert a FhirRequestQuery back to a query string.

fhirbug.server.requestparser.parse_url(url)[source]

Parse an http request string and produce an option dict.

>>> p = parse_url('Patient/123/$validate?_format=json')
>>> p.resource
'Patient'
>>> p.resourceId
'123'
>>> p.operation
'$validate'
>>> p.modifiers
{'_format': ['json']}
>>> p.search_params
{}
Parameters:url – a string containing the path of the request. It should not contain the server path. For example: Patients/123?name:contains=Jo
Returns:A FhirRequestQuery object
fhirbug.server.requestparser.split_join(lst)[source]

Accepts a list of comma separated strings, splits them and joins them in a new list

>>> split_join(['a,b,c', 'd', 'e,f'])
['a', 'b', 'c', 'd', 'e', 'f']
fhirbug.server.requestparser.validate_params(params)[source]

Validate a parameter dictionary. If the parameters are invalid, raise a QueryValidationError with the details.

Parameters:params – Parameter dictionary produced by parse_url
Returns:
Raises:fhirbug.exceptions.QueryValidationError

Request Handling

class fhirbug.server.requesthandlers.AbstractRequestHandler[source]

Base class for request handlers

log_request(url, query, status, method, resource=None, OperationOutcome=None, request_body=None, time=datetime.datetime(2020, 1, 4, 11, 45, 36, 279217))[source]

Create an AuditEvent resource that contains details about the request.

Parameters:
  • url (string) – The initial url that was requested
  • query (FhirRequestQuery) – The FhirRequestQuery that was generated
  • status (int) – The status code that was returned
  • method (string) – The request method
  • resource (FhirResource) – A Fhir resource, possibly a bundle, of the resources that were accessed or modified during the request
  • OperationOutcome (OperationOutcome) – An OperationOutcome related to the requset
  • request_body – The body of the request
  • time (datetime) – The time the request occured
class fhirbug.server.requesthandlers.DeleteRequestHandler[source]

Receive a request url and the request body of a DELETE request and handle it. This includes parsing the string into a fhirbug.server.requestparser.FhirRequestQuery, finding the model for the requested resource and deleting it. It returns a tuple (response json, status code). If an error occurs during the process, an OperationOutcome is returned.

Parameters:url (string) – a string containing the path of the request. It should not contain the server path. For example: Patients/123?name:contains=Jo
Returns:A tuple (response_json, status code), where response_json may be the requested resource, a Bundle or an OperationOutcome in case of an error.
Return type:tuple
log_request(url, query, status, method, resource=None, OperationOutcome=None, request_body=None, time=datetime.datetime(2020, 1, 4, 11, 45, 36, 279217))

Create an AuditEvent resource that contains details about the request.

Parameters:
  • url (string) – The initial url that was requested
  • query (FhirRequestQuery) – The FhirRequestQuery that was generated
  • status (int) – The status code that was returned
  • method (string) – The request method
  • resource (FhirResource) – A Fhir resource, possibly a bundle, of the resources that were accessed or modified during the request
  • OperationOutcome (OperationOutcome) – An OperationOutcome related to the requset
  • request_body – The body of the request
  • time (datetime) – The time the request occured
class fhirbug.server.requesthandlers.GetRequestHandler[source]

Receive a request url as a string and handle it. This includes parsing the string into a fhirbug.server.requestparser.FhirRequestQuery, finding the model for the requested resource and calling Resource.get on it. It returns a tuple (response json, status code). If an error occurs during the process, an OperationOutcome is returned.

Parameters:url – a string containing the path of the request. It should not contain the server path. For example: Patients/123?name:contains=Jo
Returns:A tuple (response json, status code) where response_json may be the requested resource, a Bundle or an OperationOutcome in case of an error.
Return type:tuple
log_request(url, query, status, method, resource=None, OperationOutcome=None, request_body=None, time=datetime.datetime(2020, 1, 4, 11, 45, 36, 279217))

Create an AuditEvent resource that contains details about the request.

Parameters:
  • url (string) – The initial url that was requested
  • query (FhirRequestQuery) – The FhirRequestQuery that was generated
  • status (int) – The status code that was returned
  • method (string) – The request method
  • resource (FhirResource) – A Fhir resource, possibly a bundle, of the resources that were accessed or modified during the request
  • OperationOutcome (OperationOutcome) – An OperationOutcome related to the requset
  • request_body – The body of the request
  • time (datetime) – The time the request occured
class fhirbug.server.requesthandlers.PostRequestHandler[source]

Receive a request url and the request body of a POST request and handle it. This includes parsing the string into a fhirbug.server.requestparser.FhirRequestQuery, finding the model for the requested resource and creating a new instance. It returns a tuple (response json, status code). If an error occurs during the process, an OperationOutcome is returned.

Parameters:
  • url (string) – a string containing the path of the request. It should not contain the server path. For example: Patients/123?name:contains=Jo
  • body (dict) – a dictionary containing all data that was sent with the request
Returns:

A tuple (response_json, status code), where response_json may be the requested resource, a Bundle or an OperationOutcome in case of an error.

Return type:

tuple

log_request(url, query, status, method, resource=None, OperationOutcome=None, request_body=None, time=datetime.datetime(2020, 1, 4, 11, 45, 36, 279217))

Create an AuditEvent resource that contains details about the request.

Parameters:
  • url (string) – The initial url that was requested
  • query (FhirRequestQuery) – The FhirRequestQuery that was generated
  • status (int) – The status code that was returned
  • method (string) – The request method
  • resource (FhirResource) – A Fhir resource, possibly a bundle, of the resources that were accessed or modified during the request
  • OperationOutcome (OperationOutcome) – An OperationOutcome related to the requset
  • request_body – The body of the request
  • time (datetime) – The time the request occured
class fhirbug.server.requesthandlers.PutRequestHandler[source]

Receive a request url and the request body of a POST request and handle it. This includes parsing the string into a fhirbug.server.requestparser.FhirRequestQuery, finding the model for the requested resource and creating a new instance. It returns a tuple (response json, status code). If an error occurs during the process, an OperationOutcome is returned.

Parameters:
  • url (string) – a string containing the path of the request. It should not contain the server path. For example: Patients/123?name:contains=Jo
  • body (dict) – a dictionary containing all data that was sent with the request
Returns:

A tuple (response_json, status code), where response_json may be the requested resource, a Bundle or an OperationOutcome in case of an error.

Return type:

tuple

log_request(url, query, status, method, resource=None, OperationOutcome=None, request_body=None, time=datetime.datetime(2020, 1, 4, 11, 45, 36, 279217))

Create an AuditEvent resource that contains details about the request.

Parameters:
  • url (string) – The initial url that was requested
  • query (FhirRequestQuery) – The FhirRequestQuery that was generated
  • status (int) – The status code that was returned
  • method (string) – The request method
  • resource (FhirResource) – A Fhir resource, possibly a bundle, of the resources that were accessed or modified during the request
  • OperationOutcome (OperationOutcome) – An OperationOutcome related to the requset
  • request_body – The body of the request
  • time (datetime) – The time the request occured

fhirbug.exceptions

exception fhirbug.exceptions.AuthorizationError(auditEvent, query=None)[source]

The request could not be authorized.

auditEvent = None

This exception carries an auditEvent resource describing why authorization failed It can be thrown anywhere in a mappings .get() method.

with_traceback()

Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.

exception fhirbug.exceptions.ConfigurationError[source]

Something is wrong with the settings

with_traceback()

Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.

exception fhirbug.exceptions.DoesNotExistError(pk=None, resource_type=None)[source]

A http request query was malformed or not understood by the server

with_traceback()

Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.

exception fhirbug.exceptions.InvalidOperationError[source]

The requested opertion is not valid

with_traceback()

Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.

exception fhirbug.exceptions.MappingException[source]

A fhir mapping received data that was not correct

with_traceback()

Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.

exception fhirbug.exceptions.MappingValidationError[source]

A fhir mapping has been set up wrong

with_traceback()

Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.

exception fhirbug.exceptions.OperationError(severity='error', code='exception', diagnostics='', status_code=500)[source]

An exception that happens during a requested operation that should be returned as an OperationOutcome to the user.

to_fhir()[source]

Express the exception as an OperationOutcome resource. This allows us to catch it and immediately return it to the user.

with_traceback()

Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.

exception fhirbug.exceptions.QueryValidationError[source]

A http request query was malformed or not understood by the server

with_traceback()

Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.

exception fhirbug.exceptions.UnsupportedOperationError[source]

The requested opertion is not supported by this server

with_traceback()

Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.

Examples

PyMODM Autogenerated

This is an example implementation of a fhirbug server using mongodb via PyMODM.

Warning

This is meant as a demo implementation aimed to demonstrate some of the capabilities of fhirbug. IT IS NOT A PRODUCTION READY SERVER, please do not use it as one!

It uses models generated from the FHIR specification files so it covers pretty much every possible resource and can populate the database using FHIR’s official examples.

Installation

Running the example server locally

The only requirement besides the python packages is mongodb. If you are on Linux, installing it is probably as simple as:

$ sudo apt install mongodb-server

or equivalent. See detailed instructions for your platform here.

All python packages required are in requirements.txt, so, in a Python >= 3.6 environment, do:
$ pip install -r requirements.txt

and you should be set to go.

Starting the development server

In order to run the server locally for testing/debugging run:

$ python examples/pymodm_autogenerated/flask_app.py

from the project’s root directory.

Deploying using gunicorn

If you intend to put heavier load on the server,it is recommended to run it using a wsgi server. Fhirbug comes with gunicorn included in it’s requirements but you can use any alternative as long as it can serve a flak app (so all of them).

So, if you haven’t installed gunicorn from the server’s requirements.txt, do:

$ pip install gunicorn

and then:

$ cd examples/pymodm_autogenerated

$ gunicorn --bind 0.0.0.0:5001 flask_app:app

It is recommended to serve the app behind a proxy server like nginx. Have a look at https://gunicorn.org/#deployment for more details.

Deploying via docker

First, make sure you have Docker and Docker Compose installed.

Then, simply clone the git repository and start the instances:

$ git clone https://github.com/zensoup/fhirbug.git

$ cd fhirbug/examples/pymodm_autogenerated

$ sudo docker-compose up

By default, this will create one docker instance for mongodb and one for python. It will then download the example files from fhir.org and populate the database with the example resources. Finally, it will start serving the application, binding to port 5000.

If you do not want to generate example resources you can edit the DockerFile before running docker-compose up.

If you want to acces the mongo database from the host machine for debugging purposes edit docker-compose.yml to contain the following:

 version: '3'
 services:
   web:
     build: .
     ports:
         - "5000:5000"
     depends_on:
         - mongo
   mongo:
     image: "mongo:4"
     ports:
         - "27018:27017"

Then, you can connect to the db from the command line:

$ mongo mongodb://localhost:27018

Generating Example data

The demo server comes with a couple of scripts that download the FHIR specification files from http://hl7.org/fhir/ and populates the database with the examples included within it.

Note

If you are developing on fhirbug please note that these files are also used to generate the fixtures for some of fhirbug’s tests. So you should be aware that you may see failing tests if you change these files.

Downloading the specification files

To download the specification files fron the hl7 archive can either use:

$ python examples/pymodm_autogenerated/tools/download_examples.py examples/pymodm_autogenerated/test_cache

or:

$ cd examples/pymodm_autogenerated/

$ python tools/download_examples.py

This will create a folder called test_cache inside the dem server’s root directory.

Using your own sample data

You can feed the fixture generation script any valid FHIR JSON formatted data and it will seed the database using them, as long as you place inside the test_cache folder. For the script to recogninse them as seed data, they must fit the glob pattern *example*.json. So any set of files like example-1.json, example-2.json, etc would be recognized and parsed for use as seed data.

Populating the database

Once you have a cache folder with the seed data you want to use, run:

$ python examples/pymodm_autogenerated/generate_examples.py

This script will read the database configuration in examples/pymodm_autogenerated/settings.py and use that caonnection to write the documents.

Warning

This script drops the database before starting so you will loose any existing documents in that database.

Generating the Models

Note

These models have already been generated and live in examples/pymodm_autogenerated/mappings.py. This section only applies if you want to customize the way models are generated.

The script in examples/pymodm_autogenerated/tools/generate_pymodm_schema.py goes through all of fhirbug’s FHIR resource classes and creates code for the corresponding fhirbug Mappings.

You can call it simply by calling:

$ python examples/pymodm_autogenerated/tools/generate_pymodm_schema.py <output_path>

By default this will create a file in examples/pymodm_autogenerated called mappings.py. You can pass a path to the script to override this behavior.

Limitations

  • There is currently a bug in pymodm that does not allow cyclic references between models. This means that some resource attributes have not been included in the generated models.

    Namely, the attributes that are missing from the generated models are:

    CodeSystemConcept.concept
    CompositionSection.section
    ConsentProvision.provision
    ContractTerm.group
    ExampleScenarioProcessStep.process
    ExampleScenarioProcessStepAlternative.step
    Extension.extension
    FHIRReference.identifier
    GraphDefinitionLinkTarget.link
    ImplementationGuideDefinitionPage.page
    MedicinalProductAuthorizationProcedure.application
    MedicinalProductPackagedPackageItem.packageItem
    OperationDefinitionParameter.part
    ParametersParameter.part
    QuestionnaireItem.item
    QuestionnaireResponseItem.item
    QuestionnaireResponseItemAnswer.item
    RequestGroupAction.action
    resource.action
    StructureMapGroupRule.rule
    SubstanceSpecificationName.synonym
    SubstanceSpecificationName.translation
    ValueSetExpansionContains.contains
    

    plus all of the value attributes of the Extension resource:

    valueAddress, valueAge, valueAnnotation, valueAttachment, valueCodeableConcept, valueCoding, valueContactDetail, valueContactPoint, valueContributor, valueCount, valueDataRequirement, valueDistance, valueDosage, valueDuration, valueExpression, valueHumanName, valueIdentifier, valueMoney, valueParameterDefinition, valuePeriod, valueQuantity, valueRange, valueRatio, valueReference, valueRelatedArtifact, valueSampledData, valueSignature, valueTiming, valueTriggerDefinition, valueUsageContext,
    

Indices and tables