Skip to main content
Egg Status Travis Build Status Test Coverage Python Versions Latest Version License https://img.shields.io/badge/code%20style-black-000000.svg

Background (collective.fhirpath)

fhirpath implementation in Plone, essential battery included, ready to use.

Installation

Install collective.fhirpath by adding it to your buildout:

[buildout]
...
eggs +=
    collective.fhirpath

and then running bin/buildout

From Plone controlpanel in the addon settings, install collective.fhirpath.

How It Works

``FhirResource`` the fhirfield

Make sure this specialized field is used properly according to plone.app.fhirfield documentation.

Make field indexable

A specilized Catalog PluginIndexes is named FhirFieldIndex is available, you will use it as like other catalog indexes.

Example:

<?xml version="1.0"?>
<object name="portal_catalog" meta_type="Plone Catalog Tool">
    <index name="organization_resource" meta_type="FhirFieldIndex">
        <indexed_attr value="organization_resource"/>
    </index>
</object>

Elasticsearch settings

Make sure elasticsearch has been configured accourding to collective.elasticsearch docs.

Usages

FHIR Search::
>>> from fhirpath.interfaces import IElasticsearchEngineFactory
>>> from fhirpath.interfaces import IFhirSearch
>>> from fhirpath.interfaces import ISearchContextFactory
>>> from plone import api
>>> from collective.elasticsearch.es import ElasticSearchCatalog
>>> from zope.component import queryMultiAdapter
>>> es_catalog = ElasticSearchCatalog(api.portal.get_tool("portal_catalog"))
>>> factory = queryMultiAdapter(
....        (es_catalog,), IElasticsearchEngineFactory
.... )
>>> engine = factory(fhir_release="STU3")
>>> search_context = queryMultiAdapter((engine,), ISearchContextFactory)(
.... resource_type, unrestricted=False)
>>> search_factory = queryMultiAdapter((search_context,), IFhirSearch)
>>> params = (
....        ("_profile", "http://hl7.org/fhir/Organization"),
....        ("identifier", "urn:oid:2.16.528.1|91654"),
....        ("type", "http://hl7.org/fhir/organization-type|prov"),
....        ("address-postalcode", "9100 AA"),
....        ("address", "Den Burg"),
....    )
>>> bundle = search_factory(params)
>>> len(bundle.entry)
2
>>> # with query string.
>>> # query_string = self.request["QUERY_STRING]
>>> query_string = "_profile=http://hl7.org/fhir/Organization&identifier=urn:oid:2.16.528.1|91654&type=http://hl7.org/fhir/organization-type|prov&address-postalcode=9100+AA"
>>> bundle = search_factory(query_string=query_string)
>>> len(bundle.entry)
2
ZCatlog FHIR Search::
>>> from collective.fhirpath.interfaces import IZCatalogFhirSearch
>>> zcatalog_factory = queryMultiAdapter((search_context,), IZCatalogFhirSearch)
>>> # with query string.
>>> # query_string = self.request["QUERY_STRING]
>>> query_string = "_profile=http://hl7.org/fhir/Organization&identifier=urn:oid:2.16.528.1|91654&type=http://hl7.org/fhir/organization-type|prov&address-postalcode=9100+AA"
>>> brains = zcatalog_factory(query_string=query_string)
>>> len(brains)
2
FHIR Query::
>>> from fhirpath.interfaces import IElasticsearchEngineFactory
>>> from fhirpath.interfaces import IFhirSearch
>>> from fhirpath.interfaces import ISearchContextFactory
>>> from plone import api
>>> from collective.elasticsearch.es import ElasticSearchCatalog
>>> from zope.component import queryMultiAdapter
>>> from fhirpath.query import Q_
>>> from fhirpath.fql import T_
>>> from fhirpath.fql import sort_
>>> from fhirpath.enums import SortOrderType
>>> es_catalog = ElasticSearchCatalog(api.portal.get_tool("portal_catalog"))
>>> factory = queryMultiAdapter(
....        (es_catalog,), IElasticsearchEngineFactory
.... )
>>> engine = factory(fhir_release="STU3")
>>> query_builder = Q_(resource="Organization", engine=engine)
....    query_builder = query_builder.where(
....        T_("Organization.meta.profile", "http://hl7.org/fhir/Organization")
....    ).sort(sort_("Organization.meta.lastUpdated", SortOrderType.DESC))
>>> result = query_builder(async_result=False, unrestricted=True).fetchall()
>>> result.header.total
2
>>> query_result = query_builder(async_result=False, unrestricted=True)
>>> for resource in query_result:
....        count += 1
....        assert resource.__class__.__name__ == "Organization"
>>> query_builder = Q_(resource="Organization", engine=engine)
>>> query_builder = query_builder.where(T_("Organization.id", "f001"))
>>> result_query = query_builder(async_result=False, unrestricted=True)
>>> resource = result_query.single()
>>> resource is not None
True
>>> query_builder = Q_(resource="Organization", engine=engine)
>>> query_builder = query_builder.where(
....        T_("Organization.meta.profile", "http://hl7.org/fhir/Organization")
....    )
>>> result_query = builder(async_result=False, unrestricted=True)
>>> result = result_query.first()
>>> isinstance(result, result_query._query.get_from()[0][1])
True

Use FHIRModelServiceMixin

For better performance optimization, you should use FHIRModelServiceMixin to response FHIRModel, FhirFieldValue object efficiently.

Example 1:

>>> from plone.restapi.services import Service
>>> from collective.fhirpath.utils import FHIRModelServiceMixin
>>> class MyFHIRGetService(FHIRModelServiceMixin, Service):
....     """ """
....     def reply(self):
....        # do return bellow's types of data
....        # could be ``dict`` type data
....        # could be instance of ``FHIRAbstractModel`` derrived class.
....        # could be instance of ``plone.app.fhirfield.FhirResourceValue`` derrived class.
....        # or self.reply_no_content()

configuration

This product provides three plone registry based records fhirpath.es.index.mapping.nested_fields.limit, fhirpath.es.index.mapping.depth.limit, fhirpath.es.index.mapping.total_fields.limit. Those are related to ElasticSearch index mapping setup, if you aware about it, then you have option to modify from plone control panel (Registry).

Documentation

Full documentation for end users can be found in the “docs” folder, and is also available online at https://collective-fhirpath.readthedocs.io/

Contribute

Support

If you are having issues, please let us know at: Md Nazrul Islam<email2nazrul@gmail.com>

License

The project is licensed under the GPLv2.

REST Client Examples

Getting single resource, here we are getting Patient resource by ID.

Example(1):

>>> response = admin_session.get('/@fhir/Patient/19c5245f-89a8-49f8-b244-666b32adb92e')
>>> response.status_code
200
<BLANKLINE>
>>> response.json()['resourceType'] == 'Patient'
True
<BLANKLINE>
>>> response = admin_session.get('/@fhir/Patient/19c5245f-fake-id')
>>> response.status_code
404
<BLANKLINE>

Search Observation by Patient reference with status condition. Any observation until December 2017 and earlier than January 2017.

Example(2):

>>> response = admin_session.get('/@fhir/Observation?patient=Patient/19c5245f-89a8-49f8-b244-666b32adb92e&status=final&_lastUpdated=lt2017-12-31T00%3A00%3A00%2B00%3A00&_lastUpdated=gt2017-01-01T00%3A00%3A00%2B00%3A00')
>>> response.status_code
200
>>> response.json()["total"]
1
<BLANKLINE>

Add FHIR Resource through REST API

Example(3):

>>> import os
>>> import json
>>> import uuid
>>> import DateTime
>>> import time

>>> with open(os.path.join(FIXTURE_PATH, 'Patient.json'), 'r') as f:
...     fhir_json = json.load(f)

>>> fhir_json['id'] = str(uuid.uuid4())
>>> fhir_json['name'][0]['text'] = 'Another Patient'
>>> response = admin_session.post('/@fhir/Patient', json=fhir_json)
>>> response.status_code
201
>>> time.sleep(1)
>>> response = admin_session.get('/@fhir/Patient?active=true')
>>> response.json()["total"]
2

Update (PATCH) FHIR Resource the Patient is currently activated, we will deactive.

Example(4):

>>> patch = [{'op': 'replace', 'path': '/active', 'value': False}]
>>> response = admin_session.patch('/@fhir/Patient/19c5245f-89a8-49f8-b244-666b32adb92e', json={'patch': patch})
>>> response.status_code
204
<BLANKLINE>

Contributors

Changelog

0.8.0 (2022-06-13)

New features

  • A patch has been added in response to issue#91 on collective.elasticsearch.

0.7.6 (2021-05-04)

  • minimum fhir.resources version is now 6.1.0 and minimum collective.elasticsearch version is now 3.0.5

0.7.5 (2020-12-17)

0.7.4 (2020-11-19)

  • Minimum required fhirpath version is now 0.10.4 (see it’s changes log) and added compabilities.

0.7.3 (2020-10-24)

  • new helper function json_body has been created, which is using orjson deserializer.

  • FHIRModelServiceMixin is now more performance optimized.

0.7.2 (2020-10-06)

  • Bundle resposne as dict option enable in ZCatalog based search.

0.7.1 (2020-10-05)

  • fhirpath``minimum version has been updated, which includes minimum ``fhir.resources version 6.0.0b5.

  • Improvements for FHIRModelServiceMixin as orjson serializer used.

0.7.0 (2020-09-25)

Improvements

Fixes

  • utils.FHIRModelServiceMixin can now handle list type data in response.

0.6.1 (2020-09-09)

  • plone.app.fhirfield:default``has been added in dependency, so no need separete install of ``plone.app.fhirfield.

0.6.0 (2020-09-09)

Improvements

  • FHIRModelServiceMixin class has been available under utils module, which can be used with your plone.restapi services to response type as FhirModel aka pydantic’s BaseModel or plone.app.fhirfield.FhirFieldValue object with the best possible effecient way.

0.5.0 (2020-08-18)

Improvements

  • Supports the revolutionary version of fhir.resources via fhirpath we may expect some refactor on your existing codebase because of some breaking changes, please see changes at fhir.resources, plone.app.fhirfield and fhirpath.

  • Brings back support for Python version 3.6

  • Three configurations (fhirpath.es.index.mapping.nested_fields.limit, fhirpath.es.index.mapping.depth.limit, fhirpath.es.index.mapping.total_fields.limit) based on plone registry has now been available.

0.4.0 (2020-05-15)

Breakings

  • As a part of supporting latest fhirpath version (from 0.6.1), drop python version later than 3.7.0.

  • ElasticsearchEngineFactory.__call__’s argument name fhir_version changed to fhir_release.

0.3.0 (2019-11-10)

Improvements

  • ZCatalog featured fhir search added, from which you will get ZCatalog´s brain feature.

  • FhirFieldIndex named PluginIndex is now available.

  • FHIR STU3``and ``R4 search mapping is now available.

  • Others improvements that make able to use in production project (of course without guarantee.)

0.2.0 (2019-09-16)

  • first working versions, with lots of improvements.

0.1.0 (2019-09-06)

  • Initial release. [nazrulworld]

Metadata

Release files for collective.fhirpath 0.8.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for collective.fhirpath 0.8.0
File Size Uploaded
collective.fhirpath-0.8.0.tar.gz 97.5 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for collective.fhirpath 0.8.0
File Interpreter ABI Platform
collective.fhirpath-0.8.0-py2.py3-none-any.whl Python 2, Python 3 none any Details

Total release size: 429.7 kB

Release files / collective.fhirpath-0.8.0.tar.gz

Download URL collective.fhirpath-0.8.0.tar.gz
Size 97.5 kB
Tags Source
SHA-256 checksum
How to use checksums
d58b20f440774b8de287b6ea6d7b13d973822b022977aaf795844b489a4100bf
BLAKE2b-256 checksum
How to use checksums
1a96ef8bab4177fbb5306473aaf46585506d1631e830be7fe9b03bf925759f89
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/3.1.1 pkginfo/1.8.2 requests/2.27.1 setuptools/42.0.2 requests-toolbelt/0.9.1 tqdm/4.63.0 CPython/3.7.8

Release files / collective.fhirpath-0.8.0-py2.py3-none-any.whl

Download URL collective.fhirpath-0.8.0-py2.py3-none-any.whl
Size 332.2 kB
Tags Python 2 Python 3
SHA-256 checksum
How to use checksums
c1116eba802d866c5a67ae4e457a1199dd7188ff1efd2e7f4b97fb8c5c0dc103
BLAKE2b-256 checksum
How to use checksums
304297b93a00d08f1fd84e46d2addf4b169b2e9f234b578cf9ac460cc335aea9
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/3.1.1 pkginfo/1.8.2 requests/2.27.1 setuptools/42.0.2 requests-toolbelt/0.9.1 tqdm/4.63.0 CPython/3.7.8

Release history Release notifications | RSS feed

This release

0.8.0 This release

2 release files

0.7.6

2 release files

0.7.5

2 release files

0.7.4

2 release files

0.7.3

2 release files

0.7.2

2 release files

0.7.1

2 release files

0.7.0

2 release files

0.6.1

2 release files

0.6.0

2 release files

0.5.0

2 release files

0.4.0

2 release files

0.3.0

2 release files

0.2.0

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page