MDM supports flexible survivorship rules that determine which attributes are replaced and which are preserved in the Golden Record after MDM operations. These rules are defined as JavaScript handler functions in the MDM survivorship rules module configuration section. Rules can be defined at four different scopes: global, operation type, resource type, and both, operation and resource type. In case multiple handlers are defined, only the most specific one will be called. Please note that the script is not intended to preserve state. Please use bindings to track any required state.
The global handler function is applied to all MDM resources and request types, unless a more specific handler function is available.
function mdmApplySurvivorshipRules(targetRec, goldenRec, transactionContext) {
// rule implementation goes here
}
Operation type handler is more specific than the global handler. It is run on the MDM operations regardless of the resource type provided to the operation.
Handler function should follow the convention mdmApplySurvivorshipRulesOn<OperationType>, where <OperationType> is one of the MDM operation types:
An example handler function for all resources for MergeGoldenResources operation type is included below:
function mdmApplySurvivorshipRulesOnMergeGoldenResources(fromGoldenRec, toGoldenRec, transactionContext) {
// rule implementation goes here
}
Resource type handlers apply to all requests with a given MDM resource type. Resource type handlers are considered more specific than operation type handlers. If resource type handler is available, operation type and global handlers will not be executed.
JavaScript function should be named as mdmApplySurvivorshipRulesFor<Resource>Type. <Resource> is any of the supported MDM resource types.
function mdmApplySurvivorshipRulesForPatientType(targetRec, goldenRec, transactionContext) {
// rule implementation goes here
}
Operation and Resource type handlers are the most specific handler that are applied to MDM requests. JavaScript function should be named using the following convention: mdmApplySurvivorshipRulesOn<OperationType>For<Resource>Type. Where <OperationType> should be one of the MDM supported operation types and <Resource> is any of the supported MDM resource types.
function mdmApplySurvivorshipRulesOnCreateResourceForPatientType(targetRec, goldenRec, transactionContext) {
// rule implementation goes here
}
The MdmHelper
object is available to the survivorship script. It can be used for copying values from the target record to the golden record. The MdmHelper
supports the following methods:
Method | Description |
---|---|
MdmHelper(Fhir.getContext(), targetRec, goldenRec, transactionContext ) | Constructor that accepts FHIR context, target record to copy values from, golden record to copy values to and transaction context. |
helper.mergeAll() | Adds all values from the target record to the golden record. IDs, identifiers and metadata values are not merged. |
helper.replaceAll() | Replaces all values in the golden resource with the values in the target resource. IDs, identifiers and metadata are not replaced. |
helper.merge(fieldName) | Adds the values from the field identified by the fieldName from target record to the golden record. |
helper.mergeFields(fieldNames) | Adds values from the fields in the fieldNames array from target record to the golden record. |
helper.replace(fieldName) | Replaces the values from the field identified by the fieldName from target record to the golden record. |
helper.replaceFields(fieldNames) | Replaces the values from the fields in the fieldNames array from target record to the golden record. |
helper.isGoldenResourceFieldEmpty(fieldName) | Checks if the fieldName is empty on the golden resource. |
helper.isTargetFieldEmpty(fieldName) | Checks if the fieldName is empty on the target resource. |
helper.isValidTargetResourceField(fieldName) | Checks if the fieldName exists on the target resource. |
helper.isValidGoldenResourceField(fieldName) | Checks if the fieldName exists on the golden resource. |
helper.isGoldenResourceOlderThanTarget() | Checks if Golden Resource was last modified before the Target Resource (i.e. so that the values form the Target Resources are more recent and we need to modify the Golden Resource appropriately, for instance). This method will return false if timestamp is missing on either the Target or Golden Resource. |
There are also additional objects available to the survivorship script that might be helpful. To learn more about them, please refer to the JavaScript Execution Environment.
Instance | Description |
---|---|
BundleUtil | Convenience object for retrieving resources with the resourceName from the provided bundle. |
Converter | Utility instance for converting HL7v2 time to FHIR format and decoding/encoding URL stings. |
Environment | Convenience object for retrieving JavaScript-related system properties. |
Exceptions | Convenience object for creating exception instances. |
Fhir | Utility object for accessing FHIR context. |
FhirClientFactory | Factory object for creating new FHIR client instances. |
Hl7V2 | Utility for creating HL7 v2 message segments. |
Http | Factory object for building HTTP requests. |
LdapFactory | Utility object for creating LDAP resources. |
Log | Convenience logger instance. |
OAuth2Exceptions | Utility object for creating authentication / authorization exceptions. |
ResourceBuilder | Builder object responsible for creating new FHIR resource instances |
TransactionBuilder | Builder object responsible for creating new transaction bundles. |
Util | Utility object pausing current execution. |
Uuid | Helper object for generating UUIDs. |
/*
Objects available to the survivorship script:
* BundleUtil - Convenience object for retrieving resources with the resourceName from the provided bundle.
* Converter - Utility instance for converting HL7v2 time to FHIR format and decoding/encoding URL stings.
* Environment - Convenience object for retrieving JavaScript-related system properties.
* Exceptions - Convenience object for creating exception instances.
* Fhir - Utility object for accessing FHIR context.
* FhirClientFactory - Factory object for creating new FHIR client instances.
* Hl7V2 - Utility for creating HL7 v2 message segments.
* Http - Factory object for building HTTP requests.
* LdapFactory - Utility object for creating LDAP resources.
* Log - Convenience logger instance.
* OAuth2Exceptions - Utility object for creating authentication / authorization exceptions.
* ResourceBuilder - Builder object responsible for creating new FHIR resource instances
* TransactionBuilder - Builder object responsible for creating new transaction bundles.
* Util - Utility object pausing current execution.
* Uuid - Helper object for generating UUIDs.
*/
/*
Global handler
*/
function mdmApplySurvivorshipRules(targetRec, goldenRec, transactionContext) {
// by default replace name on the golden record, if target has it
var helper = new MdmHelper(Fhir.getContext(), targetRec, goldenRec, transactionContext);
if (!helper.isTargetFieldEmpty('name')) {
helper.replace('name');
}
// also replace DOB and phone
helper.replaceFields(['birthDate', 'telecom']);
}
/*
Request Type handler
*/
function mdmApplySurvivorshipRulesOnMergeGoldenResources(fromGoldenRec, toGoldenRec, transactionContext) {
// merge all fields by default
var helper = new MdmHelper(Fhir.getContext(), targetRec, goldenRec, transactionContext);
helper.mergeAll();
}
/*
Request and resource type handlers
*/
function mdmApplySurvivorshipRulesOnMergeGoldenResourcesForPatientType(targetRec, goldenRec, transactionContext) {
var helper = new MdmHelper(Fhir.getContext(), targetRec, goldenRec, transactionContext);
if (helper.isGoldenResourceFieldEmpty('address')) {
// if golden resource has no address, keep the address from the target resource
helper.replace('address');
} else {
// otherwise keep all addresses
helper.merge('address');
}
// re-apply global handler
mdmApplySurvivorshipRules(targetRec, goldenRec, transactionContext);
}
/*
Global handler, that copy identifiers in golden records.
*/
function mdmApplySurvivorshipRules(targetRec, goldenRec, txContext) {
var helper = new MdmHelper(Fhir.getContext(), targetRec, goldenRec, txContext);
// Replaces all values in the golden resource with the values in the target resource.
// But IDs, identifiers and metadata are not replaced.
helper.replaceAll();
// Now, copy identifiers (system and value) in the golden record
for (let i = 0; i < targetRec.getIdentifier().size(); i++) {
let targetId = targetRec.getIdentifier().get(i);
let goldenId = getIdentifier(goldenRec, targetId.getSystem());
if (goldenId === null) {
goldenRec.addIdentifier(targetId.copy());
} else {
goldenId.setValue(targetId.getValue());
}
}
}
function getIdentifier(resource, system) {
for (let i = 0; i < resource.getIdentifier().size(); i++) {
var id = resource.getIdentifier().get(i);
if (id.getSystem().equals(system)) {
return id;
}
}
return null;
}
Please follow steps 1 to 4 in the Smile CDR MDM Quickstart Guide to set up the MDM module, and make sure the module is successfully started.
By now, you should already have the following suvivorship rules set up. The script contains a global handler that replaces all fields using the values from the target resource, and a Merge Golden Resources operation handler that merges all fields of the fromGoldenRec
to the toGoldenRec
.
function mdmApplySurvivorshipRules(targetRec, goldenRec, transactionContext) {
// by default replace name on the golden record, if target has it
var helper = new MdmHelper(Fhir.getContext(), targetRec, goldenRec, transactionContext);
helper.replaceAll();
}
function mdmApplySurvivorshipRulesOnMergeGoldenResources(fromGoldenRec, toGoldenRec, transactionContext) {
// merge all fields by default
var helper = new MdmHelper(Fhir.getContext(), fromGoldenRec, toGoldenRec, transactionContext);
helper.mergeAll();
}
Let's send a few requests to see their effects concretely. Create a Patient resource: POST {{base_url}}/Patient
{
"resourceType": "Patient",
"identifier": [
{
"use": "usual",
"type": {
"coding": [
{
"system": "http://terminology.hl7.org/CodeSystem/v2-0203",
"code": "MR"
}
]
},
"system": "http://my-lab-system",
"value": "123"
}
],
"active": true,
"name": [
{
"use": "official",
"family": "Chalmers",
"given": [
"Peter",
"James"
]
}
],
"birthDate": "1974-12-25",
"gender": "male",
"address": [
{
"use": "home",
"type": "both",
"text": "534 Erewhon St PeasantVille, Rainbow, Vic 3999",
"line": [
"534 Erewhon St"
],
"city": "PleasantVille",
"district": "Rainbow",
"state": "Vic",
"postalCode": "3999",
"period": {
"start": "1974-12-25"
}
}
]
}
{
"resourceType": "Patient",
"id": "xxxx",
"meta": {
"versionId": "1",
"lastUpdated": "2023-09-15T11:45:09.705-04:00",
"tag": [
{
"system": "http://hapifhir.io/fhir/NamingSystem/mdm-record-status",
"version": "1",
"code": "GOLDEN_RECORD",
"display": "Golden Record",
"userSelected": false
},
{
"system": "https://hapifhir.org/NamingSystem/managing-mdm-system",
"version": "1",
"code": "HAPI-MDM",
"display": "This Golden Resource can only be modified by HAPI MDM system.",
"userSelected": false
}
]
},
"identifier": [
{
"system": "http://hapifhir.io/fhir/NamingSystem/mdm-golden-resource-enterprise-id",
"value": "11f70e3a-7988-4410-af6b-545deb50c68f"
}
],
"active": true,
"name": [
{
"use": "official",
"family": "Chalmers",
"given": [
"Peter",
"James"
]
}
],
"gender": "male",
"birthDate": "1974-12-25",
"address": [
{
"use": "home",
"type": "both",
"text": "534 Erewhon St PeasantVille, Rainbow, Vic 3999",
"line": [
"534 Erewhon St"
],
"city": "PleasantVille",
"district": "Rainbow",
"state": "Vic",
"postalCode": "3999",
"period": {
"start": "1974-12-25"
}
}
]
}
{
"resourceType": "Patient",
"identifier": [
{
"use": "usual",
"type": {
"coding": [
{
"system": "http://terminology.hl7.org/CodeSystem/v2-0203",
"code": "MR"
}
]
},
"system": "http://my-lab-system",
"value": "123"
}
],
"active": true,
"name": [
{
"use": "official",
"family": "Chalmers",
"given": [
"Peter",
"James"
]
}
],
"birthDate": "1974-12-25",
"gender": "female",
"address": [
{
"use": "home",
"type": "both",
"text": "111 University St PeasantVille, Rainbow, Vic 1111",
"line": [
"111 University St"
],
"city": "PleasantVille",
"district": "Rainbow",
"state": "Vic",
"postalCode": "1111",
"period": {
"start": "1974-12-25"
}
}
]
}
{
"resourceType": "Patient",
"id": "xxxx",
"meta": {
"versionId": "1",
"lastUpdated": "2023-09-15T11:45:09.705-04:00",
"tag": [
{
"system": "http://hapifhir.io/fhir/NamingSystem/mdm-record-status",
"version": "1",
"code": "GOLDEN_RECORD",
"display": "Golden Record",
"userSelected": false
},
{
"system": "https://hapifhir.org/NamingSystem/managing-mdm-system",
"version": "1",
"code": "HAPI-MDM",
"display": "This Golden Resource can only be modified by HAPI MDM system.",
"userSelected": false
}
]
},
"identifier": [
{
"system": "http://hapifhir.io/fhir/NamingSystem/mdm-golden-resource-enterprise-id",
"value": "11f70e3a-7988-4410-af6b-545deb50c68f"
}
],
"active": true,
"name": [
{
"use": "official",
"family": "Chalmers",
"given": [
"Peter",
"James"
]
}
],
"gender": "female",
"birthDate": "1974-12-25",
"address": [
{
"use": "home",
"type": "both",
"text": "111 University St PeasantVille, Rainbow, Vic 1111",
"line": [
"111 University St"
],
"city": "PleasantVille",
"district": "Rainbow",
"state": "Vic",
"postalCode": "1111",
"period": {
"start": "1974-12-25"
}
}
]
}