Closed lmsurpre closed 5 years ago
We have a use case for a European Union sponsored project where patients are reporting on what they ate via an application. This information is used by a dietician to help track their progress. We can imagine that together with this, the patients could be monitored by IoT devices, (e.g. fitbits etc), and therefore wanted to use FHIR to store this information.
It turns out, that there are no FHIR v4 resources that come close to reporting on food consumed (e.g. 250 grams of fish, 1 cup of milk for lunch), and therefore we experimented creating a "Meal" virtual resource.
This was really handy to have and certainly presented a more logical representation to the application than our alternative, which is using an "Observation" resource and adding resources - not to mention that there were several fields in the Observation resource that are required fields, but not relevant to the use case.
That being said, virtual resources in their current form cannot be used by FHIR client code which is a major limitation.
My vote would be to keep virtual resources, but to autogenerate the class file required by the client API.
Thanks Eliot. John opened https://chat.fhir.org/#narrow/stream/179166-implementers/topic/observation.20about.20food.20consumed for bringing this use case to the FHIR community.
My vote would be to keep virtual resources, but to autogenerate the class file required by the client API.
I like this line of thought but would prefer to restrict the "virtual resource" abstraction to the client side if possible. That would provide a couple key benefits:
@JohnTimm and I have kicked some ideas around for generating Java model objects for FHIR Profiles and this might be a good use case for fleshing out that idea. Basically, it would work like this:
fhir-tools
to better support generating java model objects that extend the fhir-model from FHIR profiles.fhir-tools
Here's an example using Observation:
Observation foodIntakeObservation = Observation.builder()
.status(ObservationStatus.FINAL)
.code(CodeableConcept.builder()
.coding(Coding.builder()
.system(Uri.of("http://snomed.info/sct"))
.code(Code.of("226379006"))
.display(string("Food intake"))
.build())
.build())
.component(Component.builder()
.code(CodeableConcept.builder()
.coding(Coding.builder()
.system(Uri.of("http://snomed.info/sct"))
.code(Code.of("226441002"))
.display(string("Fish intake"))
.build())
.build())
.value(Quantity.builder()
.value(Decimal.of(250))
.system(Uri.of("http://unitsofmeasure.org"))
.code(Code.of("g"))
.unit(string("grams"))
.build())
.build())
.component(Component.builder()
.code(CodeableConcept.builder()
.coding(Coding.builder()
.system(Uri.of("http://snomed.info/sct"))
.code(Code.of("226404003"))
.display(string("Milk intake"))
.build())
.build())
.value(Quantity.builder()
.value(Decimal.of(1))
.system(Uri.of("http://unitsofmeasure.org"))
.code(Code.of("[cup_us]"))
.unit(string("cup"))
.build())
.build())
.build();
which yields:
{
"resourceType": "Observation",
"status": "final",
"code": {
"coding": [
{
"system": "http://snomed.info/sct",
"code": "226379006",
"display": "Food intake"
}
]
},
"component": [
{
"code": {
"coding": [
{
"system": "http://snomed.info/sct",
"code": "226441002",
"display": "Fish intake"
}
]
},
"valueQuantity": {
"value": 250,
"unit": "grams",
"system": "http://unitsofmeasure.org",
"code": "g"
}
},
{
"code": {
"coding": [
{
"system": "http://snomed.info/sct",
"code": "226404003",
"display": "Milk intake"
}
]
},
"valueQuantity": {
"value": 1,
"unit": "cup",
"system": "http://unitsofmeasure.org",
"code": "[cup_us]"
}
}
]
}
which isn't terribly complex. That said, I agree with @lmsurpre that we could make this easier on the client side through generated APIs, etc.
Yes, but if we are talking about doing a POST via REST, I can compose a clean object like: { "resourceType": "Meal", "references": "Patient/123", "specifics": { "type": "Breakfast", "amount": 123.4, "units": "grams", "foodEaten": "Hot dogs and rice" }, "date": "December 10, 2019", "comment": "It was good" }
Actually, if you do this on the client side, behind the scenes, then doesn't that mean that the user will be unaware of exactly how you are doing the translation? In this case, this will mean that if the user wants to use ReST he/she will have no idea of how the the virtual resource should be composed (for the POST for example) or how to query on the GET...
In our DSTU2 release, we supported a feature called "virtual resources" where the REST layer had a facade (implemented via servlet filters) for accepting custom JSON at endpoints beyond the scope of the FHIR Resources.
When the JSON hit the server, we'd convert it to a Basic resource with extensions, and we'd set the code of the Basic resource to the name of the virtual resource. Similarly, we'd support some level of retrieval for the virtual resources so that clients could "pretend" like they were using real FHIR resources.
Unfortunately, over time, this feature was hard to maintain and the abstraction was quite leaky. For example, a query for Basic resources would return all the virtual resources and so in some cases the users needed to understand the "magic" being performed on the server.
Our theory is that, with the expanded set of Resources available in FHIR R4, then need for virtual resources should be much less and so our plan is to remove the feature.
Currently, the feature is sprinkled throughout the code, but almost certainly fails to work due to new code that was added which assume its removal.
Unless we want to revisit the need for this feature, we should remove all traces of it from our codebase, including but not limited to: