Skip to content

Commit

Permalink
Fixed retrieve translation not validating code path and terminology t…
Browse files Browse the repository at this point in the history
…arget.
  • Loading branch information
brynrhodes committed Jun 8, 2017
1 parent 2fe0f7c commit 52a0f93
Show file tree
Hide file tree
Showing 6 changed files with 101 additions and 29 deletions.
2 changes: 1 addition & 1 deletion Src/java/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ allprojects {
apply plugin: 'eclipse'

group = 'info.cqframework'
version = '1.2.2-SNAPSHOT'
version = '1.2.4-SNAPSHOT'
}

subprojects {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1499,25 +1499,7 @@ public Object visitMembershipExpression(@NotNull cqlParser.MembershipExpressionC
} else {
Expression left = parseExpression(ctx.expression(0));
Expression right = parseExpression(ctx.expression(1));
if (right instanceof ValueSetRef) {
InValueSet in = of.createInValueSet()
.withCode(left)
.withValueset((ValueSetRef) right);
libraryBuilder.resolveCall("System", "InValueSet", new InValueSetInvocation(in));
return in;
}

if (right instanceof CodeSystemRef) {
InCodeSystem in = of.createInCodeSystem()
.withCode(left)
.withCodesystem((CodeSystemRef)right);
libraryBuilder.resolveCall("System", "InCodeSystem", new InCodeSystemInvocation(in));
return in;
}

In in = of.createIn().withOperand(left, right);
libraryBuilder.resolveBinaryCall("System", "In", in);
return in;
return libraryBuilder.resolveIn(left, right);
}
case "contains":
if (ctx.dateTimePrecisionSpecifier() != null) {
Expand Down Expand Up @@ -2690,12 +2672,51 @@ public Retrieve visitRetrieve(@NotNull cqlParser.RetrieveContext ctx) {
retrieve.setCodeProperty(classType.getPrimaryCodePath());
}

Property property = null;
if (retrieve.getCodeProperty() == null) {
libraryBuilder.recordParsingException(new CqlSemanticException("Retrieve has a terminology target but does not specify a code path and the type of the retrieve does not have a primary code path defined.",
CqlTranslatorException.ErrorSeverity.Warning, getTrackBack(ctx)));
}
else {
try {
DataType codeType = libraryBuilder.resolvePath((DataType) namedType, retrieve.getCodeProperty());
property = of.createProperty().withPath(retrieve.getCodeProperty());
property.setResultType(codeType);
}
catch (Exception e) {
libraryBuilder.recordParsingException(new CqlSemanticException(String.format("Could not resolve code path %s for the type of the retrieve %s.",
retrieve.getCodeProperty(), namedType.getName()), CqlTranslatorException.ErrorSeverity.Warning, getTrackBack(ctx), e));
}
}

Expression terminology = null;
if (ctx.terminology().qualifiedIdentifier() != null) {
List<String> identifiers = (List<String>) visit(ctx.terminology());
retrieve.setCodes(resolveQualifiedIdentifier(identifiers));
terminology = resolveQualifiedIdentifier(identifiers);
}
else {
retrieve.setCodes(parseExpression(ctx.terminology().expression()));
terminology = parseExpression(ctx.terminology().expression());
}

// Resolve the terminology target using an in operator
try {
Expression in = libraryBuilder.resolveIn(property, terminology);
if (in instanceof In) {
retrieve.setCodes(((In) in).getOperand().get(1));
} else if (in instanceof InValueSet) {
retrieve.setCodes(((InValueSet) in).getValueset());
} else if (in instanceof InCodeSystem) {
retrieve.setCodes(((InCodeSystem) in).getCodesystem());
} else {
libraryBuilder.recordParsingException(new CqlSemanticException(String.format("Unexpected membership operator %s in retrieve", in.getClass().getSimpleName()),
CqlTranslatorException.ErrorSeverity.Warning, getTrackBack(ctx)));
}
}
catch (Exception e) {
// If something goes wrong attempting to resolve, just set to the expression and report it as a warning, it shouldn't prevent translation
retrieve.setCodes(terminology);
libraryBuilder.recordParsingException(new CqlSemanticException("Could not resolve membership operator for terminology target of the retrieve.",
CqlTranslatorException.ErrorSeverity.Warning, getTrackBack(ctx), e));
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -516,6 +516,28 @@ public Expression resolveAggregateCall(String libraryName, String operatorName,
return resolveCall(libraryName, operatorName, new AggregateExpressionInvocation(expression));
}

public Expression resolveIn(Expression left, Expression right) {
if (right instanceof ValueSetRef) {
InValueSet in = of.createInValueSet()
.withCode(left)
.withValueset((ValueSetRef) right);
resolveCall("System", "InValueSet", new InValueSetInvocation(in));
return in;
}

if (right instanceof CodeSystemRef) {
InCodeSystem in = of.createInCodeSystem()
.withCode(left)
.withCodesystem((CodeSystemRef)right);
resolveCall("System", "InCodeSystem", new InCodeSystemInvocation(in));
return in;
}

In in = of.createIn().withOperand(left, right);
resolveBinaryCall("System", "In", in);
return in;
}

public Expression resolveCall(String libraryName, String operatorName, Invocation invocation) {
return resolveCall(libraryName, operatorName, invocation, true);
}
Expand Down Expand Up @@ -1090,6 +1112,14 @@ else if (currentType instanceof ChoiceType) {
}
}
}
else if (currentType instanceof ListType && listTraversal) {
// NOTE: FHIRPath path traversal support
// Resolve property as a list of items of property of the element type
ListType listType = (ListType)currentType;
DataType resultType = resolveProperty(listType.getElementType(), identifier);
return new ListType(resultType);

}

if (currentType.getBaseType() != null) {
currentType = currentType.getBaseType();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,29 @@
{
"library" : {
"annotation" : [ {
"startLine" : 22,
"startChar" : 5,
"endLine" : 22,
"endChar" : 54,
"message" : "Could not resolve code path medication.code for the type of the retrieve QUICK.MedicationPrescription.",
"errorType" : "semantic",
"errorSeverity" : "warning",
"type" : "CqlToElmError"
}, {
"startLine" : 22,
"startChar" : 5,
"endLine" : 22,
"endChar" : 54,
"message" : "Could not resolve membership operator for terminology target of the retrieve.",
"errorType" : "semantic",
"errorSeverity" : "warning",
"type" : "CqlToElmError"
}, {
"message" : "List-valued expression was demoted to a singleton.",
"errorType" : "semantic",
"errorSeverity" : "warning",
"type" : "CqlToElmError"
} ],
"identifier" : {
"id" : "CMS146",
"version" : "2"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@
<ns4:element name="negationRationale" type="System.Code"/>
<ns4:element name="lengthOfStay" type="System.Quantity"/>
</ns4:typeInfo>
<ns4:typeInfo xsi:type="ns4:ClassInfo" name="QDM.Diagnosis" retrievable="true" baseType="QDM.QDMBaseType" label="Diagnosis">
<ns4:typeInfo xsi:type="ns4:ClassInfo" name="QDM.Diagnosis" retrievable="true" baseType="QDM.QDMBaseType" label="Diagnosis" primaryCodePath="code">
<ns4:element name="prevalencePeriod" type="interval&lt;System.DateTime&gt;"/>
<ns4:element name="anatomicalLocationSite" type="System.Code"/>
<ns4:element name="severity" type="System.Code"/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -440,8 +440,7 @@
<ns4:element name="value" type="System.String"/>
</ns4:typeInfo>
<ns4:typeInfo xsi:type="ns4:ClassInfo" name="QUICK.Practitioner" baseType="QUICK.DomainResource"
retrievable="true" identifier="practitioner-qicore-qicore-practitioner" primaryCodePath="practitionerRole[].role">
<!-- note: primaryCodePath is invalid -->
retrievable="true" identifier="practitioner-qicore-qicore-practitioner" primaryCodePath="practitionerRole.role">
<ns4:element name="identifier" type="list&lt;QUICK.Identifier&gt;"/>
<ns4:element name="name" type="QUICK.HumanName"/>
<ns4:element name="telecom" type="list&lt;QUICK.ContactPoint&gt;"/>
Expand Down Expand Up @@ -1523,8 +1522,7 @@
<ns4:element name="related" type="list&lt;QUICK.Observation.Related&gt;"/>
</ns4:typeInfo>
<ns4:typeInfo xsi:type="ns4:ClassInfo" name="QUICK.DiagnosticOrder" baseType="QUICK.DomainResource"
retrievable="true" identifier="diagnosticorder-qicore-qicore-diagnosticorder" primaryCodePath="item[].code">
<!-- note: primaryCodePath is invalid -->
retrievable="true" identifier="diagnosticorder-qicore-qicore-diagnosticorder" primaryCodePath="item.code">
<ns4:element name="subject" type="System.Any"/>
<ns4:element name="orderer" type="System.Any"/>
<ns4:element name="identifier" type="list&lt;QUICK.Identifier&gt;"/>
Expand Down Expand Up @@ -1587,8 +1585,7 @@
<ns4:element name="value" type="System.String"/>
</ns4:typeInfo>
<ns4:typeInfo xsi:type="ns4:ClassInfo" name="QUICK.ImmunizationRecommendation" baseType="QUICK.DomainResource"
retrievable="true" identifier="immunizationrecommendation-qicore-qicore-immunizationrec" primaryCodePath="recommendation[].vaccineType">
<!-- note: primaryCodePath is invalid -->
retrievable="true" identifier="immunizationrecommendation-qicore-qicore-immunizationrec" primaryCodePath="recommendation.vaccineType">
<ns4:element name="identifier" type="list&lt;QUICK.Identifier&gt;"/>
<ns4:element name="patient" type="System.Any"/>
<ns4:element name="recommendation" type="list&lt;QUICK.ImmunizationRecommendation.Recommendation&gt;"/>
Expand Down

0 comments on commit 52a0f93

Please sign in to comment.