-
Notifications
You must be signed in to change notification settings - Fork 31
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Explore elm types #267
base: master
Are you sure you want to change the base?
Explore elm types #267
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -11,7 +11,7 @@ import { Uncertainty } from '../datatypes/uncertainty'; | |
import { Context } from '../runtime/context'; | ||
import { build } from './builder'; | ||
import { DateTime } from '../datatypes/datetime'; | ||
import ELM from '../types/elm' | ||
import ELM from '../types/elm'; | ||
|
||
export class Add extends Expression { | ||
constructor(json: ELM.Add) { | ||
|
@@ -390,14 +390,14 @@ export class MinValue extends Expression { | |
'{urn:hl7-org:elm-types:r1}Time': MathUtil.MIN_TIME_VALUE | ||
}; | ||
|
||
valueType: keyof typeof MinValue.MIN_VALUES | ||
valueType: keyof typeof MinValue.MIN_VALUES; | ||
|
||
constructor(json: ELM.MinValue) { | ||
super(json); | ||
if (json.valueType in MinValue.MIN_VALUES) { | ||
this.valueType = json.valueType as keyof typeof MinValue.MIN_VALUES | ||
this.valueType = json.valueType as keyof typeof MinValue.MIN_VALUES; | ||
} else { | ||
throw new Error(`Not expecting MIN_VALUE: ${json.valueType})`) | ||
throw new Error(`Not expecting MIN_VALUE: ${json.valueType})`); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This error check breaks the arithmetic tests, but for a very logical reason lol. There is a test case that asserts that any incorrect Since the constructor now throws an error if provided a I'm going to defer to @cmoesel here on how exactly to proceed. I think I might lean towards not throwing an error in a constructor, but I see the merit in the code that you've added. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah def agree with you, both ways have merit. Here is a StackOverflow discussing. I semi-lean towards validation in the constructor as long as that runs over the whole ELM tree as soon as the ELM wrapper is instantiated, just so that it doesn't become possible for execution to 'skip' certain parts of the ELM tree depending on the input patient data (only exec MinValue node if Patient has Condition Y) which could then allow bugs to escape tests more easily. Not sure if that's applicable though? Either way, MIN_VALUES could be an ENUM but SHOULD NOT be added to the ELM generated from the XML because the mappings to There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I can see both arguments -- including the desire to fail immediately upon loading the ELM (rather than on execution, just in case execution never occurs). That said the spec does say this:
One could argue that "attempting to invoke" implies an error on execution, not on loading. (As far as I can tell, this is how the Java cql-engine implementation behaves as well). |
||
} | ||
} | ||
|
||
|
@@ -430,9 +430,9 @@ export class MaxValue extends Expression { | |
constructor(json: ELM.MaxValue) { | ||
super(json); | ||
if (json.valueType in MaxValue.MAX_VALUES) { | ||
this.valueType = json.valueType as keyof typeof MaxValue.MAX_VALUES | ||
this.valueType = json.valueType as keyof typeof MaxValue.MAX_VALUES; | ||
} else { | ||
throw new Error(`Not expecting Max_VALUE: ${json.valueType})`) | ||
throw new Error(`Not expecting Max_VALUE: ${json.valueType})`); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same deal here as my comment about errors for MinValue. |
||
} | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,7 +2,7 @@ import { Expression } from './expression'; | |
import * as dt from '../datatypes/datatypes'; | ||
import { Context } from '../runtime/context'; | ||
import { build } from './builder'; | ||
import ELM from '../types/elm' | ||
import ELM from '../types/elm'; | ||
|
||
export class ValueSetDef extends Expression { | ||
name: string; | ||
|
@@ -54,7 +54,7 @@ export class AnyInValueSet extends Expression { | |
super(json); | ||
this.codes = build(json.codes); | ||
if (json.valueset?.type !== 'ValueSetRef') { | ||
throw new Error('Expecting ValueSetRef Expression') | ||
throw new Error('Expecting ValueSetRef Expression'); | ||
} | ||
this.valueset = new ValueSetRef(json.valueset); | ||
} | ||
|
@@ -79,7 +79,7 @@ export class InValueSet extends Expression { | |
super(json); | ||
this.code = build(json.code); | ||
if (json.valueset?.type !== 'ValueSetRef') { | ||
throw new Error('Expecting ValueSetRef Expression') | ||
throw new Error('Expecting ValueSetRef Expression'); | ||
} | ||
this.valueset = new ValueSetRef(json.valueset); | ||
} | ||
|
@@ -196,7 +196,7 @@ export class ConceptDef extends Expression { | |
display?: string; | ||
|
||
constructor(json: ELM.ConceptDef) { | ||
// @ts-ignore | ||
// @ts-ignore | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same as initial comment with more explanation of ts-ignore and disabling the lint rule |
||
super(json); | ||
this.name = json.name; | ||
this.display = json.display; | ||
|
@@ -215,7 +215,7 @@ export class ConceptDef extends Expression { | |
export class ConceptRef extends Expression { | ||
name: string; | ||
|
||
constructor(json: ELM.ConceptRef) { | ||
constructor(json: ELM.ConceptRef) { | ||
super(json); | ||
this.name = json.name || ''; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ugh you know the drill at this point. My fault again, property can be optional. It's almost like I should've read the dang manual when doing this conversion. Sorry There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I personally don't hate defaulting to empty strings because usually you just do a check like
and null or empty string behave the same way. It also makes the code and types simpler sometimes without having to always check for null in cases where you want to do something like
But the broader discussion goes back to whether there are cases where we'd actually want to update the XML spec itself and change certain properties to required or not. There are pros and cons to having the single source of truth for the ELM spec. But it could get messy if we were to say manually start editing the generated ELM Typescript Types, because then we would not be able to generate it again later when the XML schema changes. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. At this point, unless there is a strong reason for it, I'd shy away from introducing changes to the ELM specification. Those changes are expensive given the governance process on CQL. In cases where something isn't clearly wrong, it may be better just to accommodate for it. |
||
} | ||
|
@@ -259,7 +259,7 @@ export class CalculateAge extends Expression { | |
constructor(json: ELM.CalculateAge) { | ||
super(json); | ||
if (!json.precision) { | ||
throw new Error('Precision is required') | ||
throw new Error('Precision is required'); | ||
} | ||
this.precision = json.precision; | ||
} | ||
|
@@ -278,12 +278,12 @@ export class CalculateAge extends Expression { | |
} | ||
|
||
export class CalculateAgeAt extends Expression { | ||
precision: ELM.DateTimePrecision; | ||
precision: ELM.DateTimePrecision; | ||
|
||
constructor(json: ELM.CalculateAgeAt) { | ||
super(json); | ||
if (!json.precision) { | ||
throw new Error('Precision is required') | ||
throw new Error('Precision is required'); | ||
} | ||
this.precision = json.precision; | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Small (opinionated) comment. Now that we use
keyof typeof MinValue.MIN_VALUES
in more than one place, maybe we can bring it out to its owntype
outside of the class? E.g.:Then we can just re-use this type where applicable. Same applies to max values below
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It also does make sense to pull MIN_VALUE out, and maybe even use an ENUM instead of a dict. But it was a little weird to even have to use
as keyof typeof MinValue.MIN_VALUES
... I thought Typescript would be able to infer that sincejson.valueType in MinValue.MIN_VALUES
must be true