Repository URL to install this package:
|
Version:
4.0.0 ▾
|
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# Subclassing FHIR's reference to add resolving capabilities
import logging
from . import reference
logger = logging.getLogger(__name__)
class FHIRReference(reference.Reference):
""" Subclassing FHIR's `Reference` resource to add resolving capabilities.
"""
def resolved(self, klass):
""" Resolves the reference and caches the result, returning instance(s)
of the referenced classes.
:param klass: The expected class of the resource
:returns: An instance (or list thereof) of the resolved reference if
dereferencing was successful, `None` otherwise
"""
owning_resource = self.owningResource()
if owning_resource is None:
raise Exception("Cannot resolve reference without having an owner (which must be a `DomainResource`)")
if klass is None:
raise Exception("Cannot resolve reference without knowing the class")
refid = self.processedReferenceIdentifier()
if not refid:
logger.warning("No `reference` set, cannot resolve")
return None
# already resolved and cached?
resolved = owning_resource.resolvedReference(refid)
if resolved is not None:
if isinstance(resolved, klass):
return resolved
logger.warning("Referenced resource {} is not a {} but a {}".format(refid, klass, resolved.__class__))
return None
# not yet resolved, see if it's a contained resource
if owning_resource.contained is not None:
for contained in owning_resource.contained:
if contained.id == refid:
owning_resource.didResolveReference(refid, contained)
if isinstance(contained, klass):
return contained
logger.warning("Contained resource {} is not a {} but a {}".format(refid, klass, contained.__class__))
return None
# are we in a bundle?
ref_is_relative = '://' not in self.reference and 'urn:' != self.reference[:4]
bundle = self.owningBundle()
while bundle is not None:
if bundle.entry is not None:
fullUrl = self.reference
if ref_is_relative:
base = bundle.origin_server.base_uri if bundle.origin_server else ''
fullUrl = base + self.reference
for entry in bundle.entry:
if entry.fullUrl == fullUrl:
found = entry.resource
if isinstance(found, klass):
return found
logger.warning("Bundled resource {} is not a {} but a {}".format(refid, klass, found.__class__))
return None
bundle = bundle.owningBundle()
# relative references, use the same server
server = None
if ref_is_relative:
server = owning_resource.origin_server if owning_resource else None
# TODO: instantiate server for absolute resource
if server is None:
logger.warning("Not implemented: resolving absolute reference to resource {}"
.format(self.reference))
return None
# fetch remote resource; unable to verify klass since we use klass.read_from()
relative = klass.read_from(self.reference, server)
owning_resource.didResolveReference(refid, relative)
return relative
def processedReferenceIdentifier(self):
""" Normalizes the reference-id.
"""
if self.reference and '#' == self.reference[0]:
return self.reference[1:]
return self.reference