Skip to content

Commit

Permalink
Merge pull request #32 from HL7/choice_types
Browse files Browse the repository at this point in the history
Choice types
  • Loading branch information
plynchnlm authored Jan 3, 2020
2 parents ef8b7c5 + 11a8e84 commit c596904
Show file tree
Hide file tree
Showing 36 changed files with 4,626 additions and 1,720 deletions.
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,3 @@ build
.DS_Store
.editorconfig
Makefile
browser-build/fhirpath.min.js.map
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,16 @@
This log documents significant changes for each release. This project follows
[Semantic Versioning](http://semver.org/).

## [1.0.0] - 2019-12-19
### Added
- Support for FHIR "choice types" (e.g. Observation.value). The support is
currently limited to being able to specify paths like Observation.value (when
the resource might actually contain Observation.valueString).
### Changed
- Remove the deprecated "context" parameter from the "compile" function. The
context should be passed into the function that "compile" returns. This
breaking change is the reason for the major version number increment.

## [0.17.5] - 2019-11-18
### Fixed
- Although one could add a Quantity to a date, subtracting the quantity resulted
Expand Down
26 changes: 24 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ npm install –save fhirpath

```js
const fhirpath = require('fhirpath');
// For FHIR model data (choice type support) pull in the model file:
const fhirpath_r4_model = require('fhirpath/fhir-context/r4');
```

### Web-browser:
Expand All @@ -30,6 +32,14 @@ then use as shown below. Note that this file is UTF-8 encoded, and the script
needs to be loaded as such. For an example, see the
browser-build/test/protractor/index.html file, which sets the page to be UTF-8.

For FHIR-specific features (e.g. handling of choice type fields), you will also
want to include a second file with the desired FHIR version model data, e.g.
fhirpath.r4.min.js for pulling in the R4 model. (At the moment, those files are
small, but it would not be surprising if they grew as more support for FHIR type
handling is added, so they are kept seperate from the main FHIRPath file.)
These will define additional global variables like "fhirpath_r4_model" or
"fhirpath_stu3_model".

## Usage
```
// Evaluating FHIRPath
Expand All @@ -41,10 +51,14 @@ fhirpath.evaluate({"resourceType": "Patient", ...}, 'Patient.name.given');
// name/value pairs:
fhirpath.evaluate({}, '%a - 1', {a: 5});
// To include FHIR model data (for support of choice types), pass in the model
// data object as the fourth argument:
fhirpath.evaluate({"resourceType": "Observation", "valueString": "green"},
'Observation.value', null, fhirpath_r4_model);
// Precompiling fhirpath - result can be reused against multiple resources
const path = fhirpath.compile('Patient.name.given');
var res2 = path({"resourceType": "Patient", ...}, {a: 5, ...});
```


Expand Down Expand Up @@ -87,6 +101,13 @@ fhirpath --expression '%v + 2' --resourceJSON '{}' --variables '{"v": 5}'
> ]
```

FHIR model data can be included via --model and the FHIR release version (in
lower case, e.g., 'stu3' or 'r4').

```sh
fhirpath --expression 'Observation.value' --resourceJSON '{"resourceType": "Observation", "valueString": "Green"}' --model r4
```

If given just the FHIRPath expression, the utility will print the parsed tree:

```sh
Expand Down Expand Up @@ -121,7 +142,8 @@ Completed sections:
- 8 (Environment Variables)

We are deferring handling information about FHIR resources, as much as
possible. This affects implementation of the following sections:
possible, with the exception of support for choice types. This affects
implementation of the following sections:
- 6.3 (Types) - deferred
Also, because in JSON DateTime and Time types are represented as strings, if a
string in a resource looks like a DateTime or Time (matches the regular
Expand Down
10 changes: 9 additions & 1 deletion bin/fhirpath
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ options.option('-e, --expression <expr>', 'FHIRPath expression');
options.option('-f, --resourceFile <path name>', 'A file containing the JSON resource.');
options.option('-r, --resourceJSON <JSON>', 'JSON resource.');
options.option('-v, --variables <JSON>', 'JSON hash of variables.');
options.option('-m, --model <stu3 | r4>', 'Include FHIR model data.');
options.parse(process.argv);

// this cli util is part of public interface of fhirpath
Expand Down Expand Up @@ -36,7 +37,14 @@ else {
if (context)
context = JSON.parse(context);
let resource = JSON.parse(resourceJSON);
let res = fp.evaluate(resource, expr, context);
let model;
if (options.model) {
let supportedVersions = ['stu3', 'r4'];
if (supportedVersions.indexOf(options.model) < 0)
throw new Error('FHIR model must be one of '+supportedVersions);
model = require('../fhir-context/'+options.model);
}
let res = fp.evaluate(resource, expr, context, model);
console.log('fhirpath(' + expr + ') =>');
console.log(JSON.stringify(res, null, " "));
}
Expand Down
2 changes: 1 addition & 1 deletion browser-build/.gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
fhirpath.min.js
*.min.js*
fhirpath.zip
19 changes: 16 additions & 3 deletions browser-build/test/protractor/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,30 @@
<textarea id="expression" onkeyup="evaluateFP()"></textarea>
<textarea id="resource" onkeyup="evaluateFP()"></textarea>
<textarea id="result"></textarea>
<br>
FHIR model:
<input id="r4" name="model" type="radio" value="r4" onclick="evaluateFP()"> R4
<input id="stu3" name="model" type="radio" value="stu3" onclick="evaluateFP()"> STU3
<script src="../../fhirpath.min.js"></script>
<script src="../../fhirpath.r4.min.js"></script>
<script src="../../fhirpath.stu3.min.js"></script>
<script>
function evaluateFP() {
var expr = document.getElementById('expression').value;
var resource = document.getElementById('resource').value;
console.log("expr="+expr);
console.log(resource);
var modelChoices = document.getElementsByName('model');
var model;
for (let modelChoice of modelChoices) {
if (modelChoice.checked) {
model = modelChoices.value === 'r4' ? fhirpath_r4_model :
fhirpath_stu3_model;
break;
}
}
if (expr && resource) {
resource = JSON.parse(resource);
document.getElementById('result').value =
JSON.stringify(fhirpath.evaluate(resource, expr));
JSON.stringify(fhirpath.evaluate(resource, expr, null, model));
}
}
</script>
Expand Down
14 changes: 14 additions & 0 deletions browser-build/test/protractor/spec/browser.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,18 @@ describe('Browser build of FHIRPath', function() {
resource.sendKeys('{}');
expect(result.getAttribute('value')).toBe('[3]');
});

it('should have working model files', function() {
browser.get(demoURL);
let expression = $('#expression');
let resource = $('#resource');
resource.sendKeys('{"resourceType": "Observation", "valueString": "green"}');
expression.sendKeys('Observation.value');
let result = $('#result');
expect(result.getAttribute('value')).toBe('[]'); // no model yet
for (let fhirVers of ['stu3', 'r4']) {
$('#'+fhirVers).click(); // changes the model used
expect(result.getAttribute('value')).toBe('["green"]');
}
});
});
81 changes: 51 additions & 30 deletions browser-build/webpack.config.js
Original file line number Diff line number Diff line change
@@ -1,34 +1,55 @@
const CopyPlugin = require('copy-webpack-plugin');

module.exports = {
node: {
fs: "empty"
},
entry: './fhirpathRequire.js',
mode: 'production',
// mode: 'development',
devtool: 'source-map',
output: {
path: __dirname,
filename: './fhirpath.min.js',
},
module: {
rules: [
{
test: /\.m?js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env']
/**
* Returns a base webpack configuration object with settings used by more than
* one output file.
*/
function makeBaseConfig() {
return {
node: {
fs: "empty"
},
mode: 'production',
devtool: 'source-map',
output: {
path: __dirname
},
module: {
rules: [
{
test: /\.m?js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env']
}
}
}
}
]
},
plugins: [
new CopyPlugin([
{ from: '../LICENSE.md', to: '.' }
]),
],
};
]
}
};
}

module.exports = [];

// Main FHIRPath file
let config = makeBaseConfig();
config.entry = '../src/fhirpath';
config.output.filename = './fhirpath.min.js';
config.output.library = 'fhirpath'; // global variable for the library
config.plugins = [
new CopyPlugin([
{ from: '../LICENSE.md', to: '.' }
]),
];
module.exports.push(config);

// FHIR model files
for (let fhirVers of ['stu3', 'r4']) {
config = makeBaseConfig();
config.entry = '../fhir-context/'+fhirVers+'/index';
config.output.filename = './fhirpath.'+fhirVers+'.min.js';
config.output.library = 'fhirpath_'+fhirVers+'_model';
module.exports.push(config);
}
Loading

0 comments on commit c596904

Please sign in to comment.