fume-fhir-converter
Version:
FHIR-Utilized Mapping Engine - Community
147 lines • 9.45 kB
JavaScript
;
/**
* © Copyright Outburn Ltd. 2022-2024 All Rights Reserved
* Project name: FUME-COMMUNITY
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.getElementDefinition = void 0;
const tslib_1 = require("tslib");
/* eslint-disable @typescript-eslint/restrict-plus-operands */
const lodash_1 = tslib_1.__importDefault(require("lodash"));
const config_1 = tslib_1.__importDefault(require("../../config"));
const cache_1 = require("../cache");
const conformance_1 = require("../conformance");
const logger_1 = require("../logger");
const stringFunctions_1 = require("../stringFunctions");
const thrower_1 = tslib_1.__importDefault(require("../thrower"));
const getCurrElement_1 = require("./getCurrElement");
const getSnapshot_1 = require("./getSnapshot");
const returnPathWithoutX_1 = require("./returnPathWithoutX");
const dev = process.env.NODE_ENV === 'dev';
;
const getElementDefinition = async (rootType, path) => {
if (dev)
console.log({ func: exports.getElementDefinition, rootType, path });
if (typeof path === 'string') {
path = { originPath: path, newPath: path };
if (dev)
console.log({ 'typeof path === \'string\'': true, path });
}
const { elementDefinition } = (0, cache_1.getCache)();
// The current root type element determains the existing paths to look out path in.
const currTypeStructureDefinition = await (0, getSnapshot_1.getSnapshot)(rootType, config_1.default.getFhirVersion(), (0, conformance_1.getFhirPackageIndex)(), (0, logger_1.getLogger)());
// Creating a list of all the current path nodes.
const pathNodes = path.newPath.split('.');
if (dev)
console.log({ pathNodes });
// Iterating the nodes, and for each node implementing the logic. The path is being built from the begining to the end
// for the fact that a diversion in the main path can lead to a "leaf", if we're not jumping to another Base element.
for (let nodes = 1; nodes <= pathNodes.length; nodes++) {
// Getting the path up to the current node (to check if it exists and then we can move on)
let currPath = path.newPath.split('.').slice(0, nodes).join('.');
let currElement;
// First checking the definition cache
const cachedElementDefinition = elementDefinition.get(rootType + '-' + currPath);
if (dev)
console.log({ 'fetching from elementDefinition cache': rootType + '-' + currPath, found: !!cachedElementDefinition });
if (cachedElementDefinition) {
currElement = cachedElementDefinition;
if (dev)
console.log({ cachedElementDefinition });
}
else {
// Checking if the current element path exists in the current sd
if (dev)
console.log('(getElementDefinition): getCurrElement()', { currTypeStructureDefinition: currTypeStructureDefinition.id, currPath, nodes, 'path.newPath.split(\'.\')': path.newPath.split('.'), rootType });
currElement = (0, getCurrElement_1.getCurrElement)(currTypeStructureDefinition, currPath, nodes, path.newPath.split('.'), rootType);
if (currElement) {
// If an element has a contentReference field, ), it will not have a type or a profile, since those are defined in the referenced target element.
// The value of the contentReference field will be the target element’s id prefixed by ‘#’.
if (lodash_1.default.get(currElement, 'contentReference')) {
path.newPath = currElement.contentReference.split('.').slice(1).concat(path.newPath.split('.').slice(nodes)).join('.');
return (0, exports.getElementDefinition)(currElement.contentReference.split('.')[0].slice(1), path);
}
else {
elementDefinition.set(rootType + '-' + currPath, currElement);
}
}
}
let baseElem;
// Checking if the current node includes [x], and thats why we didnt find the relevant element.
// so we need to check for all the options.
if (!currElement && pathNodes[nodes - 1].includes('[') && !(nodes >= 2 && pathNodes[nodes - 2].includes('['))) {
baseElem = lodash_1.default.cloneDeep(currTypeStructureDefinition.snapshot.element.find(e => {
return (0, stringFunctions_1.replaceColonsWithBrackets)(e.id) === String(currTypeStructureDefinition?.type) + '.' + String(currPath.split('[')[0]);
}));
if (baseElem) {
// If there’s a type.profile, fetching its snapshot and adding the url to the type.
if (lodash_1.default.get(baseElem, ['type', '0'])) {
let baseElemSnapshot;
try {
baseElemSnapshot = await (0, getSnapshot_1.getSnapshot)(pathNodes[nodes - 1].split('[')[1].split(']')[0], config_1.default.getFhirVersion(), (0, conformance_1.getFhirPackageIndex)(), (0, logger_1.getLogger)());
if (baseElemSnapshot) {
// Fixing the fsh to the element id standard if relevant. (bracets to colon)
const preFixed = currPath;
currPath = currPath.slice(0, -1).split('[').join(':');
path.newPath = path.newPath.replace(preFixed, currPath);
// Making sure we are not referencing a pointer to the element we're changing, but a deepClone of it.
currElement = lodash_1.default.cloneDeep(baseElem);
currElement.type[0].profile = [baseElemSnapshot.url];
currElement.id = currElement.id + ':' + currPath.split(currElement.id.split('.')[currElement.id.split('.').length - 1] + ':')[1];
elementDefinition.set(rootType + '-' + currPath, currElement);
elementDefinition.set(currTypeStructureDefinition.url + '-' + currPath, currElement);
}
}
catch (e) { }
}
}
}
// Checking wether to move on to the next node, to a content reference or throw an error
if (currElement) {
// We found the wanted element - the whole path exists.
if (currPath === path.newPath) {
currElement.__fromDefinition = currTypeStructureDefinition.url;
return currElement;
}
else if (lodash_1.default.get(currElement, ['type', '0', 'code'], '').includes('System')) { // The path is invalid
return thrower_1.default.throwParseError(`The element '${currPath}' does not have child elements.`);
}
else {
// Applying the changes we made in the current fshPath in order to find it in the elements ids, before moving on to the next node.
path.newPath = currElement.id.split('.').length > 1 ? String(currElement.id.split('.').slice(1).join('.')) + '.' + String(pathNodes.slice(nodes).join('.')) : pathNodes.slice(nodes).join('.');
}
}
else {
if (!baseElem && currPath.split('.').length === 1) {
return thrower_1.default.throwParseError(`The element '${path.newPath}' was not found in '${rootType}'`);
}
else {
const prevPath = path.newPath.split('.').slice(0, nodes - 1).join('.');
baseElem = (0, getCurrElement_1.getCurrElement)(currTypeStructureDefinition, prevPath, nodes - 1, path.newPath.split('.'), rootType);
// Moving on to the different Root type - all paths in the current one are not relevant, but there might be in another one.
if (lodash_1.default.get(baseElem, 'contentReference')) {
path.newPath = baseElem.contentReference.split('.').slice(1).join('.');
return (0, exports.getElementDefinition)(baseElem.contentReference.split('.')[0].slice(1), path);
}
path.newPath = path.newPath.split('.').slice(nodes - 1).join('.');
// Going to the profile type if exists.
if (lodash_1.default.get(baseElem, ['type', '0', 'profile'])) {
return (0, exports.getElementDefinition)(baseElem.type[0].profile[0], path);
}
else {
// Selecting the relevant type for polymorphic fields.
if (baseElem?.type.length > 1) {
const splittedOriginPath = path.originPath.split('.').slice(0, -1 * path.newPath.split('.').length);
const specificType = baseElem.type.find(t => splittedOriginPath[splittedOriginPath.length - 1] === (0, returnPathWithoutX_1.returnPathWithoutX)(baseElem.id.split('.')[baseElem.id.split('.').length - 1]) + (0, stringFunctions_1.initCapOnce)(t.code));
return (0, exports.getElementDefinition)(specificType.code, path);
}
else {
return (0, exports.getElementDefinition)(baseElem.type[0].code, path);
}
}
}
}
}
};
exports.getElementDefinition = getElementDefinition;
//# sourceMappingURL=getElementDefinition.js.map