fhir-crucible / fhir_models Goto Github PK
View Code? Open in Web Editor NEWFHIR Resource Models
License: Apache License 2.0
FHIR Resource Models
License: Apache License 2.0
Generally, whenever I'm deserializing something like a DiagnosticReport
with a bunch of contained observations, I get the warning:
Unhanled and unrecognized class/type: Reference
However, the to_hash code clearly attempts to run FHIR.const_get('Reference')
, which works perfectly well in my terminal. Is there any other reason this might happen?
Hi -- I'm building a list of licenses that the software my company uses, and I'm using some software to do so -- Pivotal's license_finder (https://github.com/pivotal/LicenseFinder).
I see that refer to your Apache license in the README, but the software would pick up the license if you added a LICENSE file with the Apache text. Here's how to do it. (I might normally do a pull request for this, but it strikes me as something a repo owner would want to do herself.)
https://docs.github.com/en/github/building-a-strong-community/adding-a-license-to-a-repository
Our vulnerability scanner was flagging bcp47 as a vulnerable gem, because it includes really outdated gems in it's Gemfile.lock file. After investigating https://rubygems.org/gems/bcp47/versions/0.3.3 it seems like the gem hasn't has a release in over a decade at this point and the homepage (original github repo) has been removed. I would recommend finding an alternative or removing the dependency altogether due to the gem no longer having an upstream repository.
If you are just using the fhir_models gem (without other gems), and try to create a resource (e.g. patient) and then do patient.to_json
without require 'json'
beforehand, an error within the models gem occurs because JSON is never loaded. We should probably require 'json'
in this library where we do to_json
. This also affects the DSTU2 and STU3 libraries.
We haven't noticed this in practice because our applications eventually require JSON somewhere.
Currently, as per README this gem supports only R4 standard. Any plans to support stu3 & dstu2 standard support.
If you attempt to evaluate a FHIRPath that has an extension
somewhere other than the root object, the following error is thrown:
Extension function not applicable to NilClass:
To reproduce:
With this Patient
{
"telecom": [
{
"system": "phone",
"value": "(333) 333-3333",
"extension": [
{
"url": "http://example.com/phone-type",
"valueString": "Smartphone"
}
]
}
],
"resourceType": "Patient"
}
If I call:
FHIRPath.evaluate("Patient.telecom[0].extension('http://example.com/phone-type')", patient_json)
I get the following output:
D, [2021-03-22T18:44:27.444782 #97061] DEBUG -- : TOKENS: ["Patient", "telecom[0]", "extension", "(", "'phone-type'", ")"]
D, [2021-03-22T18:44:27.445396 #97061] DEBUG -- : TREE: ["Patient", "telecom[0]", :extension, ["'phone-type'"]]
D, [2021-03-22T18:44:27.445681 #97061] DEBUG -- : DATA: ["Patient", "telecom[0]", :extension, ["'phone-type'"]]
D, [2021-03-22T18:44:27.456356 #97061] DEBUG -- : V===> [{"telecom"=>[{"system"=>"phone", "value"=>"(333) 333-3333", "rank"=>1, "extension"=>[{"url"=>"http://example.com/phone-type", "valueString"=>"Smartphone"}]}], "resourceType"=>"Patient"}, "telecom[0]", :extension, ["'phone-type'"]]
D, [2021-03-22T18:44:27.456710 #97061] DEBUG -- : V===> [nil, {"system"=>"phone", "value"=>"(333) 333-3333", "rank"=>1, "extension"=>[{"url"=>"http://example.com/phone-type", "valueString"=>"Smartphone"}]}, :extension, ["'phone-type'"]]
D, [2021-03-22T18:44:27.456932 #97061] DEBUG -- : Evaling Extension Block....
*** RuntimeError Exception: Extension function not applicable to NilClass:
As another example, I have also seen an error thrown when attempting to eval a FHIRPath to a US Core ethnicity code, since it is an extension nested within an extension.
In some resources, the list of valid codes for certain fields was expanded too much (e.g. extra codes were improperly added to a ValueSet
). See https://chat.fhir.org/#narrow/stream/179204-crucible/topic/Test.20case.20bugs/near/178390469
our vulnerability scanner is picking this file up and marking it as a false positive because there's a vulnerable version of nokogiri in there, I think there doesn't need to be a Gemfile.lock at all in the gem.
When building a FHIR::MedicationRequest
, you can include the medication in the contained
section. In this case, the medicationReference
is a relatively linked resource. Validation fails in this case.
Example:
puts FHIR::MedicationRequest.new(
medicationReference:
FHIR::Reference.new(
reference: "#medication-1234",
display: 'Med Name',
type: 'Medication'
),
contained: [FHIR::Medication.new]
).validate
This outputs the error:
"medicationReference"=>["MedicationRequest.medication[x]: incorrect Reference type, expected Medication"]
In the case of medicationReference, you should be able to specify a reference URL this is a hash tag.
More info here: http://hl7.org/fhir/STU3/references.html#contained
When JSON/XML is being deserialized, and fails for some reason, we log the entire JSON/XML payload to the error stream. This makes Travis CI very angry, if a large JSON/XML payload doesn't deserialize correctly (e.g. a Conformance Statement). Might it make more sense to log the error/backtrace to the error stream, and the payload at a lower log level, such as debug
/info
?
https://github.com/fhir-crucible/fhir_models/blob/master/lib/fhir_models/bootstrap/json.rb#L19
https://github.com/fhir-crucible/fhir_models/blob/master/lib/fhir_models/bootstrap/xml.rb#L82
For some of the things it might be nice to do with FHIR::Reference
resources, it might be helpful to reproduce some of the inheritance hierarchy specified in the XML schemas / FHIR docs, kind of like this:
module FHIR
# core FHIR::Model supersuperclass
class Model
# anything we want available on every resource
end
class Element < FHIR::Model
attr_accessor :id # 0-1 id
attr_accessor :extension # 0-* [ Extension ]
end
class BackboneElement < FHIR::Element
attr_accessor :modifierExtension # 0-* [ Extension ]
end
# generated Resource and DomainResource superclasses
class Resource < FHIR::Model
attr_accessor :id # 0-1 id
attr_accessor :meta # 0-1 Meta
attr_accessor :implicitRules # 0-1 uri
attr_accessor :language # 0-1 code
end
class DomainResource < FHIR::Model
attr_accessor :text # 0-1 Narrative
attr_accessor :contained # 0-* [ Resource ]
attr_accessor :extension # 0-* [ Extension ]
attr_accessor :modifierExtension # 0-* [ Extension ]
end
# generated resource classes
class Bundle < FHIR::Resource
attr_accessor :type # 1-1 code
attr_accessor :total # 0-1 unsignedInt
attr_accessor :link # 0-* [ Bundle::Link ]
attr_accessor :entry # 0-* [ Bundle::Entry ]
# ...
class Link < FHIR::BackboneElement
# ...
end
end
class Patient < FHIR::DomainResource
attr_accessor :identifier # 0-* [ Identifier ]
attr_accessor :active # 0-1 boolean
attr_accessor :name # 0-* [ HumanName ]
attr_accessor :telecom # 0-* [ ContactPoint ]
# ...
class Contact < FHIR::BackboneElement
# ...
end
end
end
I'm not sure how challenging this would be to implement -- my intuition is that it could actually make some of the generation code simpler, because there would be more of a 1-1 mapping between the XML schemas and the generated model files -- but it might be useful.
FYI. This might not surprise you. But as a first-time user, the following output made me think something was wrong. I would suggest that you put a help message before or after these warnings telling me whether there are any action items I need to take, and what will be the consequences of this missing data.
jw@logopolis:/projects/open/fhir_models$ bundle exec rake fhir:generate
W, [2017-04-28T11:06:29.357037 #3173] WARN -- : MISSING EXPANSION -- DosageInstruction.additionalInstructions 0..*: http://hl7.org/fhir/ValueSet/additional-instructions-codes (example)
W, [2017-04-28T11:06:29.357220 #3173] WARN -- : MISSING EXPANSION -- DosageInstruction.asNeeded[x] 0..1: http://hl7.org/fhir/ValueSet/medication-as-needed-reason (example)
W, [2017-04-28T11:06:29.388548 #3173] WARN -- : MISSING EXPANSION -- Account.currency 0..1: http://www.iso.org/iso/home/standards/currency_codes (example)
W, [2017-04-28T11:06:29.597006 #3173] WARN -- : MISSING EXPANSION -- Diagnosis.diagnosis[x] 1..1: http://hl7.org/fhir/ValueSet/icd-10 (example)
W, [2017-04-28T11:06:29.777231 #3173] WARN -- : MISSING EXPANSION -- Except.class 0..*: http://hl7.org/fhir/ValueSet/consent-content-class (extensible)
W, [2017-04-28T11:06:29.825622 #3173] WARN -- : MISSING EXPANSION -- Coverage.type 0..1: http://hl7.org/fhir/ValueSet/coverage-type (preferred)
W, [2017-04-28T11:06:29.877811 #3173] WARN -- : MISSING EXPANSION -- DeviceComponent.type 1..1: https://rtmms.nist.gov/rtmms/index.htm#!hrosetta (preferred)
W, [2017-04-28T11:06:29.885253 #3173] WARN -- : MISSING EXPANSION -- DeviceMetric.type 1..1: https://rtmms.nist.gov/rtmms/index.htm#!hrosetta (preferred)
W, [2017-04-28T11:06:29.885703 #3173] WARN -- : MISSING EXPANSION -- DeviceMetric.unit 0..1: https://rtmms.nist.gov/rtmms/index.htm#!units (preferred)
W, [2017-04-28T11:06:30.066296 #3173] WARN -- : MISSING EXPANSION -- Content.format 0..*: http://hl7.org/fhir/ValueSet/formatcodes (preferred)
W, [2017-04-28T11:06:30.093596 #3173] WARN -- : MISSING EXPANSION -- Endpoint.payloadType 1..*: http://hl7.org/fhir/ValueSet/endpoint-payload-type (example)
W, [2017-04-28T11:06:30.104193 #3173] WARN -- : MISSING EXPANSION -- Diagnosis.diagnosis[x] 1..1: http://hl7.org/fhir/ValueSet/icd-10 (example)
W, [2017-04-28T11:06:30.200351 #3173] WARN -- : MISSING EXPANSION -- Immunization.vaccineCode 1..1: http://hl7.org/fhir/ValueSet/vaccine-code (example)
W, [2017-04-28T11:06:30.200552 #3173] WARN -- : MISSING EXPANSION -- Immunization.reportOrigin 0..1: http://hl7.org/fhir/ValueSet/immunization-origin (example)
W, [2017-04-28T11:06:30.210997 #3173] WARN -- : MISSING EXPANSION -- Recommendation.vaccineCode 1..1: http://hl7.org/fhir/ValueSet/vaccine-code (example)
W, [2017-04-28T11:06:30.698765 #3173] WARN -- : MISSING EXPANSION -- ReferenceSeq.referenceSeqId 0..1: http://hl7.org/fhir/ValueSet/sequence-referenceSeq (example)
If you have a primitive datatype with an extension the value can not be read. We have a QuestionnaireResponse with extended datatypes for the answers (in this example a date):
"item": [
{
"linkId": "date_1",
"answer": [
{
"_valueDate": {
"extension": [
{
"url": "http://localhost/fhir/StructureDefinition/custom-dateType",
"valueString": "someDateString"
}
]
}
}
]
}
]
As you can see the date is emitted with a _
prefix by HAPI. As described here.
There is no way to access these values. If I do a JSON.dump
of the item I only get the linkId:
{"linkId":"date_1"}
For non-primitive datatypes like Coding it works as expected
For XML responses it works a little better, since the extension value is set as hash on the valueDate field:
<FHIR::QuestionnaireResponse::Item::Answer:0x000055c8b430afc0
@extension=[],
@id=nil,
@item=[],
@modifierExtension=[],
@valueAttachment=nil,
@valueBoolean=nil,
@valueCoding=nil,
@valueDate=nil,
@valueDateTime=nil,
@valueDecimal=
{"extension"=>
{"valueString"=> "someDateString",
"url"=>"http://localhost/fhir/StructureDefinition/custom-dateType"}},
@valueInteger=nil,
@valueQuantity=nil,
@valueReference=nil,
@valueString=nil,
@valueTime=nil,
@valueUri=nil>
I am getting a error when using FHIR::Json.from_json
for this file:
https://www.hl7.org/fhir/encounter-example-f002-lung.json
The problem appears to be this line:
"class": "outpatient",
The version of this file that is in this repository has the following instead:
"class": {
"system": "http://hl7.org/fhir/v3/ActCode",
"code": "AMB",
"display": "ambulatory"
},
Having read the specification a bit, it appears, that the first one is correct:
http://www.hl7.org/FHIR/encounter-definitions.html#Encounter.class
I am not quite sure how this whole project works, there is very little documentation, but it appears, that these classes are generated from a definition somehow. But where is this definition?
Do I correctly understand, that this project uses FHIR STU3, while the hl7.org website refers to DSTU2? If so, how do I generate the classes for DSTU2?
Hello,
My issue is more a question than a bug. I want to extend some behaviors of this gem and I stumbled into the implementation of the conversion of the client response body to JSON and I would like to understand this part line 18:
klass = Module.const_get("FHIR::#{resource_type}")
Why not pass to the #from_json
method the klass
objects from the callers and eventually fallback on retrieving it from the resource_type?
Thanks in advance.
Single (non-Array-wrapped) values can be assigned to elements, but not at initialization. Consider this code sample:
# Initializing an Array-wrapped value
range = FHIR::Range.new(low: [FHIR::Quantity.new(value: 18)])
range.valid? # => true
# Setting a value
range.low = FHIR::Quantity.new(value: 18)
range.valid? # => true
puts range.to_json # => ... (valid FHIR JSON)
# Initializing plain value
range = FHIR::Range.new(low: FHIR::Quantity.new(value: 18))
# => Error: NoMethodError: undefined method `[]' for #<FHIR::Quantity:0x0055e8f174e6d8 @id=nil, @extension=[], @value=18, @comparator=nil, @unit=nil, @system=nil, @code=nil>
# => from /home/vagrant/.rbenv/versions/2.1.6/lib/ruby/gems/2.1.0/gems/fhir_models-3.0.2/lib/fhir_models/bootstrap/model.rb:58:in `method_missing'
I'd love to be able to use nil
or present
(or similar), rather than have to check to see if the object is nil
, []
, or [Object]
.
All non-initialized elements with qty 0..1
could be initialized to []
instead of nil
. That way, at least we can access something with [0]
and see if it's nil
, rather than doing .try(:[], 0)
, which is a little goofy.
It looks like a few value sets are missing from definitions/valuesets/expansions.json
, which is throwing the following console output when we require fhir_models
:
We tried looking up a few of them by their URIs, and actually encountered errors on the main FHIR site when looking for them, so it might be a bug in FHIR itself, but it does seem like an issue worth fixing. We're thinking of silencing the console output but we're not sure if that's the right thing to do.
We've had some difficulties with FHIR model generation as part of our build process -- in particular, we've run into errors where the application errors out the first time we start it (because models aren't generated), then works on successive tries; or issues with continually re-generating the same FHIR models, which seems wasteful. We tried some caching strategies but they were a bit buggy, and it also felt inappropriate to be reaching into the internals of this library -- it feels like if you require fhir_models
, then you should just have FHIR models available.
So instead, we tried just committing the generated FHIR models in this repository, then removing the code to re-generate them from fhir_client
, then including both of those libraries in our app -- and everything started working much more smoothly (and faster, since no regeneration is required).
I'm sure you've already weighed a lot of the pros and cons of committing them vs. not committing them, and it would add more noise to the git history / introduce a danger of the models getting out of sync with the generator, but it might be worth it for simplicity in consuming apps.
There are several regular expressions that end up in the metadata.rb file. These expressions are not anchored, which causes them to be too liberal in what they match.
This is because regular expressions defined in xml schema are automatically anchored, making it necessary for this to be done explicitly in any language implementation that does not also do that automatically.
Is there any tooling or recommendation on how to generate a Narrative div for specific resources?
It's not unusual to be working in an environment where multiple FHIR endpoints are used and it is unlikely that all of them will be able to upgrade to the latest version of the standard at the same time.
How can we support multiple versions of FHIR at the same time?
@jawalonoski What are your thoughts on how to implement this?
The profile validation logic (starting from StructureDefinition.validate_resource
) doesn't validate the FHIR resources as a hierarchy.
As an example, consider the US Core Patient profile: https://hl7.org/fhir/us/core/StructureDefinition-us-core-patient.html
This profile specifies that a Patient may have 1..* Identifier
s, and each Identifier must have 1..1 value
. The profile is represented in JSON with a flat list of elements, so "Patient.Identifier.value" is an element of the list, with cardinality 1..1.
Because the validation process loops over each element individually, when it tries to validate the "Patient.Identifier.value" element it will pull out all nodes from the entire JSON matching path "Patient.Identifier.value" which could be many, if the Patient has many Identifiers. Then the validation can fail because it expects value to have cardinality 1..1 but found many.
(Note that as of right now this example will actually pass, because it will only take the first Identifier of many; I think this is a separate bug and the highlighted line should be pulled out of this loop: https://github.com/fhir-crucible/fhir_models/blob/v1.8.3/lib/fhir_models/fhir_ext/structure_definition.rb#L95 . I found the issue with a more complicated profile where it does fail, this is the best example I see in the core)
One possible change would be to only verify elements within the context of their parent element.
Ex, change verify_element
to take path as a parameter:
def verify_element(element, json, path)
then at the end when it loops over children, validate each child only in the context of the nodes for this element path. In other words, only pass node
to the call to verify_element
instead of passing the entire json
# check children if the element has any
return unless element.children
element.children.each do |child|
nodes.each do |node|
child_path = child.path
current_path = element.path
# .. strip current_path, plus 1 '.' from the start of child_path
verify_element(child, node, child_path)
end
end
That said I'm not sure if this approach would break anything else. I tested it locally and all unit tests pass but I know that doesn't mean it's right.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.