Skip to content

Commit

Permalink
Merge pull request #60 from suyashkumar/s/handle-fhir-decimals
Browse files Browse the repository at this point in the history
Evaluate FHIR.decimal.value directly to a System.Decimal
  • Loading branch information
evan-gordon authored Aug 3, 2024
2 parents dbc5bc9 + 9ae8a9e commit bcc03a2
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 4 deletions.
9 changes: 6 additions & 3 deletions interpreter/operator_type.go
Original file line number Diff line number Diff line change
Expand Up @@ -248,15 +248,18 @@ func evalToDecimalString(m model.IUnaryExpression, opObj result.Value) (result.V
if err != nil {
return result.Value{}, err
}
return toDecimalFromString(op)
}

func toDecimalFromString(s string) (result.Value, error) {
// Check that the string meets the CQL decimal spec requirements.
found := decimalStringRegex.FindString(op)
if found == "" || found != op {
found := decimalStringRegex.FindString(s)
if found == "" || found != s {
return result.New(nil)
}

// ParseFloat works for every string that meets the CQL spec.
f, err := strconv.ParseFloat(op, 64)
f, err := strconv.ParseFloat(s, 64)
if err != nil {
return result.Value{}, err
}
Expand Down
14 changes: 13 additions & 1 deletion interpreter/property.go
Original file line number Diff line number Diff line change
Expand Up @@ -157,13 +157,25 @@ func (i *interpreter) protoProperty(source result.Named, property string, static
// For .value properties on FHIR.dateTime, FHIR.time, FHIR.date, the result type is expected to be
// a System.DateTime, System.Time, System.Date. This is not how the data is represented in the
// FHIR proto data model, so we must catch this case and apply manual conversion.

if property == "value" && (source.RuntimeType.Equal(&types.Named{TypeName: "FHIR.dateTime"}) ||
source.RuntimeType.Equal(&types.Named{TypeName: "FHIR.time"}) ||
source.RuntimeType.Equal(&types.Named{TypeName: "FHIR.date"})) {
return handleDateTimeValueProperty(source.Value, property, i.evaluationTimestamp.Location())
}

// For .value properties on FHIR.decimal, the result type is expected to be a System.Decimal, but
// this is not how the data is represented in the FHIR proto data model, so we must catch this
// case and apply manual conversion. We may wish to consider applying a parser insertion in the
// future.
if property == "value" && source.RuntimeType.Equal(&types.Named{TypeName: "FHIR.decimal"}) {
d, ok := source.Value.(*d4pb.Decimal)
if !ok {
return result.Value{}, fmt.Errorf("Unable to convert result type of FHIR.decimal to a *d4pb.decimal")
}
valueStr := d.Value
return toDecimalFromString(valueStr)
}

protoProperty, err := protoFieldFromJSONName(source.Value, property)
if err != nil {
return result.Value{}, err
Expand Down
10 changes: 10 additions & 0 deletions tests/enginetests/property_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,16 @@ func TestProperty(t *testing.T) {
},
wantResult: newOrFatal(t, result.Named{Value: &d4pb.String{Value: "obsValue"}, RuntimeType: &types.Named{TypeName: "FHIR.string"}}),
},
{
name: "FHIR.decimal.value returns a System.Decimal",
cql: dedent.Dedent(`
define FirstObservation: First([Observation])
define TESTRESULT: (FirstObservation.value as FHIR.Quantity).value.value`),
resources: []*r4pb.ContainedResource{
containedFromObservation(&r4observationpb.Observation{Value: &r4observationpb.Observation_ValueX{Choice: &r4observationpb.Observation_ValueX_Quantity{Quantity: &d4pb.Quantity{Value: &d4pb.Decimal{Value: "100.1"}}}}}),
},
wantResult: newOrFatal(t, 100.1),
},
{
name: "dateTime inside oneof returns dateTime proto",
cql: dedent.Dedent(`
Expand Down

0 comments on commit bcc03a2

Please sign in to comment.