Skip to content

Commit

Permalink
Extract characteristics for Logicals
Browse files Browse the repository at this point in the history
Logical models use special extensions to set their type characteristics.
Check for these extensions when extracting keywords. Do not create caret
rules for these extensions.
  • Loading branch information
mint-thompson committed Nov 15, 2023
1 parent 8668264 commit 235bba9
Show file tree
Hide file tree
Showing 6 changed files with 133 additions and 1 deletion.
17 changes: 16 additions & 1 deletion src/extractor/CaretValueRuleExtractor.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
import { fhirtypes, fshtypes, utils } from 'fsh-sushi';
import { cloneDeep, isEqual, differenceWith, toPairs } from 'lodash';
import { ProcessableElementDefinition, ProcessableStructureDefinition } from '../processor';
import {
LOGICAL_TARGET_EXTENSION,
ProcessableElementDefinition,
ProcessableStructureDefinition,
TYPE_CHARACTERISTICS_EXTENSION
} from '../processor';
import { ExportableCaretValueRule } from '../exportable';
import { getFSHValue, getPath, getPathValuePairs, logger, isFSHValueEmpty } from '../utils';

Expand Down Expand Up @@ -125,6 +130,16 @@ export class CaretValueRuleExtractor {
delete parent.context;
}

// if this is a Logical, ignore characteristic-setting extensions, since those are covered by a keyword
if (sd.kind === 'logical' && sd.derivation === 'specialization') {
sd.extension = sd.extension?.filter((ext: fhirtypes.Extension) => {
return !(
ext.url === TYPE_CHARACTERISTICS_EXTENSION ||
(ext.url === LOGICAL_TARGET_EXTENSION && ext.valueBoolean === true)
);
});
}

// Remove properties that are covered by other extractors or keywords
RESOURCE_IGNORED_PROPERTIES['StructureDefinition'].forEach(prop => {
delete sd[prop];
Expand Down
21 changes: 21 additions & 0 deletions src/processor/StructureDefinitionProcessor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@ import { getAncestorSliceDefinition, getPath, logger } from '../utils';
import { fshifyString } from '../exportable/common';
import { isUri } from 'valid-url';

export const TYPE_CHARACTERISTICS_EXTENSION =
'http://hl7.org/fhir/StructureDefinition/structuredefinition-type-characteristics';
export const LOGICAL_TARGET_EXTENSION =
'http://hl7.org/fhir/tools/StructureDefinition/logical-target';

export class StructureDefinitionProcessor {
static process(
input: any,
Expand Down Expand Up @@ -143,6 +148,21 @@ export class StructureDefinitionProcessor {
}
});
}
if (target instanceof ExportableLogical && input.extension) {
// most characteristics use TYPE_CHARACTERISTICS_EXTENSION,
// but there may also be LOGICAL_TARGET_EXTENSION with valueBoolean true for the can-be-target characteristic.
const characteristics: string[] = [];
input.extension.forEach(ext => {
if (ext.url === TYPE_CHARACTERISTICS_EXTENSION && ext.valueCode != null) {
characteristics.push(ext.valueCode);
} else if (ext.url === LOGICAL_TARGET_EXTENSION && ext.valueBoolean === true) {
characteristics.push('can-be-target');
}
});
if (characteristics.length) {
target.characteristics = characteristics;
}
}
}

static extractRules(
Expand Down Expand Up @@ -276,6 +296,7 @@ export interface ProcessableStructureDefinition {
derivation?: string;
mapping?: fhirtypes.StructureDefinitionMapping[];
context?: fhirtypes.StructureDefinitionContext[];
extension?: fhirtypes.Extension[];
differential?: {
element: any[];
};
Expand Down
24 changes: 24 additions & 0 deletions test/extractor/CaretValueRuleExtractor.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ describe('CaretValueRuleExtractor', () => {
let looseBSSD: any;
let looseTPESD: any;
let looseExtSD: any;
let looseLogicalSD: any;
let config: fshtypes.Configuration;
let defs: FHIRDefinitions;

Expand Down Expand Up @@ -54,6 +55,14 @@ describe('CaretValueRuleExtractor', () => {
.readFileSync(path.join(__dirname, 'fixtures', 'extension-with-context.json'), 'utf-8')
.trim()
);
looseLogicalSD = JSON.parse(
fs
.readFileSync(
path.join(__dirname, 'fixtures', 'logical-with-characteristics.json'),
'utf-8'
)
.trim()
);
});

beforeEach(() => {
Expand All @@ -75,6 +84,21 @@ describe('CaretValueRuleExtractor', () => {
expect(caretRules).toEqual<ExportableCaretValueRule[]>([]);
});

it('should not extract any SD caret rules for characteristics on a Logical', () => {
const caretRules = CaretValueRuleExtractor.processStructureDefinition(
looseLogicalSD,
defs,
config
);
// the rule on "kind" may be removed later by an optimizer,
// but there should not be any "extension" rules.
expect(caretRules).not.toContainEqual(
expect.objectContaining({
caretPath: expect.stringMatching(/^extension/)
})
);
});

it('should extract a url-setting caret rules when a non-standard url is included on a StructureDefinition', () => {
const urlSD = cloneDeep(looseSD);
urlSD.url = 'http://diferenturl.com';
Expand Down
26 changes: 26 additions & 0 deletions test/extractor/fixtures/logical-with-characteristics.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{
"resourceType": "StructureDefinition",
"id": "logical-with-characteristics",
"url": "http://hl7.org/fhir/sushi-test/StructureDefinition/logical-with-characteristics",
"kind": "logical",
"derivation": "specialization",
"type": "Base",
"name": "LogicalWithCharacteristics",
"title": "My Logical Model with Characteristics",
"description": "This is my fancy new logical model that has several characteristics.",
"baseDefinition": "http://hl7.org/fhir/StructureDefinition/Base",
"extension": [
{
"url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-type-characteristics",
"valueCode": "has-units"
},
{
"url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-type-characteristics",
"valueCode": "has-length"
},
{
"url": "http://hl7.org/fhir/tools/StructureDefinition/logical-target",
"valueBoolean": true
}
]
}
20 changes: 20 additions & 0 deletions test/processor/StructureDefinitionProcessor.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -354,6 +354,26 @@ describe('StructureDefinitionProcessor', () => {
expect(workingLogical.title).toBe('My Logical Model');
expect(workingLogical.description).toBe('This is my fancy new logical model.');
});

it('should get characteristics for a Logical with characteristics', () => {
const input = JSON.parse(
fs.readFileSync(
path.join(__dirname, 'fixtures', 'logical-with-characteristics.json'),
'utf-8'
)
);
const workingLogical = new ExportableLogical(input.name);
StructureDefinitionProcessor.extractKeywords(input, workingLogical);

expect(workingLogical.id).toBe('logical-with-characteristics');
expect(workingLogical.title).toBe('My Logical Model with Characteristics');
expect(workingLogical.description).toBe(
'This is my fancy new logical model that has several characteristics.'
);
expect(workingLogical.characteristics).toContain('can-be-target');
expect(workingLogical.characteristics).toContain('has-units');
expect(workingLogical.characteristics).toContain('has-length');
});
});

describe('#extractRules', () => {
Expand Down
26 changes: 26 additions & 0 deletions test/processor/fixtures/logical-with-characteristics.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{
"resourceType": "StructureDefinition",
"id": "logical-with-characteristics",
"url": "http://hl7.org/fhir/sushi-test/StructureDefinition/logical-with-characteristics",
"kind": "logical",
"derivation": "specialization",
"type": "Base",
"name": "LogicalWithCharacteristics",
"title": "My Logical Model with Characteristics",
"description": "This is my fancy new logical model that has several characteristics.",
"baseDefinition": "http://hl7.org/fhir/StructureDefinition/Base",
"extension": [
{
"url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-type-characteristics",
"valueCode": "has-units"
},
{
"url": "http://hl7.org/fhir/StructureDefinition/structuredefinition-type-characteristics",
"valueCode": "has-length"
},
{
"url": "http://hl7.org/fhir/tools/StructureDefinition/logical-target",
"valueBoolean": true
}
]
}

0 comments on commit 235bba9

Please sign in to comment.