use of org.hl7.elm_modelinfo.r1.ModelInfo in project clinical_quality_language by cqframework.
the class TypeBuilder method dataTypeToQName.
public QName dataTypeToQName(DataType type) {
if (type instanceof NamedType) {
NamedType namedType = (NamedType) type;
ModelInfo modelInfo = mr.getModel(namedType.getNamespace()).getModelInfo();
return new QName(modelInfo.getTargetUrl() != null ? modelInfo.getTargetUrl() : modelInfo.getUrl(), namedType.getTarget() != null ? namedType.getTarget() : namedType.getSimpleName());
}
// ERROR:
throw new IllegalArgumentException("A named type is required in this context.");
}
use of org.hl7.elm_modelinfo.r1.ModelInfo in project clinical_quality_language by cqframework.
the class DataRequirementsProcessorTest method TestDataRequirementsProcessorOpioidIssueLibrary.
@Test
public void TestDataRequirementsProcessorOpioidIssueLibrary() {
CqlTranslatorOptions cqlTranslatorOptions = new CqlTranslatorOptions();
cqlTranslatorOptions.getFormats().add(CqlTranslator.Format.JSON);
cqlTranslatorOptions.setCollapseDataRequirements(true);
cqlTranslatorOptions.setAnalyzeDataRequirements(true);
try {
NamespaceInfo ni = new NamespaceInfo("fhir.cdc.opioid-cds", "http://fhir.org/guides/cdc/opioid-cds");
CqlTranslator translator = createTranslator(ni, "OpioidCDSSTU3/cql/OpioidCDSREC10_bug_repo.cql", cqlTranslatorOptions);
translator.toELM();
assertTrue(translator.getErrors().isEmpty());
libraryManager.cacheLibrary(translator.getTranslatedLibrary());
DataRequirementsProcessor dqReqTrans = new DataRequirementsProcessor();
org.hl7.fhir.r5.model.Library moduleDefinitionLibrary = dqReqTrans.gatherDataRequirements(libraryManager, translator.getTranslatedLibrary(), cqlTranslatorOptions, null, false);
assertNotNull(moduleDefinitionLibrary);
RelatedArtifact ra = null;
// FHIR-ModelInfo
ra = getDependency(moduleDefinitionLibrary, "http://fhir.org/guides/cqf/common/Library/FHIR-ModelInfo|3.0.0");
assertNotNull(ra, "Expected depends-on http://fhir.org/guides/cqf/common/Library/FHIR-ModelInfo|3.0.0");
// FHIRHelpers
ra = getDependency(moduleDefinitionLibrary, "http://hl7.org/fhir/Library/FHIRHelpers|3.0.0");
assertNotNull(ra, "Expected depends-on http://hl7.org/fhir/Library/FHIRHelpers|3.0.0");
// OpioidCDSCommon
ra = getDependency(moduleDefinitionLibrary, "http://fhir.org/guides/cdc/opioid-cds/Library/OpioidCDSCommon|1.2.3");
assertNotNull(ra, "Expected depends-on http://fhir.org/guides/cdc/opioid-cds/Library/OpioidCDSCommon|1.2.3");
// OpioidCDSRoutines
ra = getDependency(moduleDefinitionLibrary, "http://fhir.org/guides/cdc/opioid-cds/Library/OpioidCDSRoutines|1.2.3");
assertNotNull(ra, "Expected depends-on http://fhir.org/guides/cdc/opioid-cds/Library/OpioidCDSRoutines|1.2.3");
// OpioidCDSCommonConfig
ra = getDependency(moduleDefinitionLibrary, "http://fhir.org/guides/cdc/opioid-cds/Library/OpioidCDSCommonConfig|1.2.3");
assertNotNull(ra, "Expected depends-on http://fhir.org/guides/cdc/opioid-cds/Library/OpioidCDSCommonConfig|1.2.3");
// depends-on http://fhir.org/guides/cdc/opioid-cds/ValueSet/observation-category-laboratory
ra = getDependency(moduleDefinitionLibrary, "http://fhir.org/guides/cdc/opioid-cds/ValueSet/observation-category-laboratory");
assertNotNull(ra, "Expected depends-on http://fhir.org/guides/cdc/opioid-cds/ValueSet/observation-category-laboratory");
// depends-on http://fhir.org/guides/cdc/opioid-cds/ValueSet/pcp-medications
ra = getDependency(moduleDefinitionLibrary, "http://fhir.org/guides/cdc/opioid-cds/ValueSet/pcp-medications");
assertNotNull(ra, "Expected depends-on http://fhir.org/guides/cdc/opioid-cds/ValueSet/pcp-medications");
// depends-on http://fhir.org/guides/cdc/opioid-cds/ValueSet/cocaine-medications
ra = getDependency(moduleDefinitionLibrary, "http://fhir.org/guides/cdc/opioid-cds/ValueSet/cocaine-medications");
assertNotNull(ra, "Expected depends-on http://fhir.org/guides/cdc/opioid-cds/ValueSet/cocaine-medications");
// parameter "Negative PCP Screenings Count Since Last POS": integer
ParameterDefinition pd = null;
pd = getParameter(moduleDefinitionLibrary, "ContextPrescriptions");
assertNotNull(pd, "Expected parameter ContextPrescriptions");
assertEquals(pd.getType(), Enumerations.FHIRAllTypes.MEDICATIONREQUEST);
assertEquals(pd.getUse(), Enumerations.OperationParameterUse.IN);
assertEquals(pd.getMax(), "*");
pd = getParameter(moduleDefinitionLibrary, "Patient");
assertNotNull(pd, "Expected parameter Patient");
assertEquals(pd.getType(), Enumerations.FHIRAllTypes.PATIENT);
assertEquals(pd.getUse(), Enumerations.OperationParameterUse.OUT);
assertEquals(pd.getMax(), "1");
pd = getParameter(moduleDefinitionLibrary, "Lookback Year");
assertNotNull(pd, "Expected parameter Lookback Year");
assertEquals(pd.getType(), Enumerations.FHIRAllTypes.PERIOD);
assertEquals(pd.getUse(), Enumerations.OperationParameterUse.OUT);
assertEquals(pd.getMax(), "1");
pd = getParameter(moduleDefinitionLibrary, "PCP Screenings");
assertNotNull(pd, "Expected parameter PCP Screenings");
assertEquals(pd.getType(), Enumerations.FHIRAllTypes.OBSERVATION);
assertEquals(pd.getUse(), Enumerations.OperationParameterUse.OUT);
assertEquals(pd.getMax(), "*");
pd = getParameter(moduleDefinitionLibrary, "Positive PCP Screenings");
assertNotNull(pd, "Expected parameter Positive PCP Screenings");
assertEquals(pd.getType(), Enumerations.FHIRAllTypes.OBSERVATION);
assertEquals(pd.getUse(), Enumerations.OperationParameterUse.OUT);
assertEquals(pd.getMax(), "*");
pd = getParameter(moduleDefinitionLibrary, "Negative PCP Screenings");
assertNotNull(pd, "Expected parameter Negative PCP Screenings");
assertEquals(pd.getType(), Enumerations.FHIRAllTypes.OBSERVATION);
assertEquals(pd.getUse(), Enumerations.OperationParameterUse.OUT);
assertEquals(pd.getMax(), "*");
pd = getParameter(moduleDefinitionLibrary, "Negative PCP Screenings Count Since Last POS");
assertNotNull(pd, "Expected parameter Negative PCP Screenings Count Since Last POS");
assertEquals(pd.getType(), Enumerations.FHIRAllTypes.INTEGER);
assertEquals(pd.getUse(), Enumerations.OperationParameterUse.OUT);
assertEquals(pd.getMax(), "1");
pd = getParameter(moduleDefinitionLibrary, "Positive PCP Dates in Lookback Period");
assertNotNull(pd, "Expected parameter Positive PCP Dates in Lookback Period");
assertEquals(pd.getType(), Enumerations.FHIRAllTypes.STRING);
assertEquals(pd.getUse(), Enumerations.OperationParameterUse.OUT);
assertEquals(pd.getMax(), "*");
pd = getParameter(moduleDefinitionLibrary, "Has Positive Screening for PCP in Last 12 Months");
assertNotNull(pd, "Expected parameter Has Positive Screening for PCP in Last 12 Months");
assertEquals(pd.getType(), Enumerations.FHIRAllTypes.BOOLEAN);
assertEquals(pd.getUse(), Enumerations.OperationParameterUse.OUT);
assertEquals(pd.getMax(), "1");
pd = getParameter(moduleDefinitionLibrary, "PCP Summary");
assertNotNull(pd, "Expected parameter PCPSummary");
assertEquals(pd.getType(), Enumerations.FHIRAllTypes.STRING);
assertEquals(pd.getUse(), Enumerations.OperationParameterUse.OUT);
assertEquals(pd.getMax(), "1");
// dataRequirement Observation {
// ms: { code, category, value, status, status.value, effective },
// codeFilter {
// { category in http://fhir.org/guides/cdc/opioid-cds/ValueSet/observation-category-laboratory },
// { code in http://fhir.org/guides/cdc/opioid-cds/ValueSet/pcp-medications }
// }
// }
assertTrue(moduleDefinitionLibrary.getDataRequirement().size() == 2);
DataRequirement dr = null;
for (DataRequirement r : moduleDefinitionLibrary.getDataRequirement()) {
if (r.getType() == Enumerations.FHIRAllTypes.OBSERVATION) {
dr = r;
break;
}
}
assertNotNull(dr);
assertEquals(dr.getType(), Enumerations.FHIRAllTypes.OBSERVATION);
assertTrue(dr.getMustSupport().size() == 6);
assertTrue(dr.getMustSupport().stream().filter(x -> x.getValue().equals("code")).count() == 1);
assertTrue(dr.getMustSupport().stream().filter(x -> x.getValue().equals("category")).count() == 1);
assertTrue(dr.getMustSupport().stream().filter(x -> x.getValue().equals("value")).count() == 1);
assertTrue(dr.getMustSupport().stream().filter(x -> x.getValue().equals("status")).count() == 1);
assertTrue(dr.getMustSupport().stream().filter(x -> x.getValue().equals("status.value")).count() == 1);
assertTrue(dr.getMustSupport().stream().filter(x -> x.getValue().equals("effective")).count() == 1);
assertTrue(dr.getCodeFilter().size() == 2);
DataRequirement.DataRequirementCodeFilterComponent cf = null;
for (DataRequirement.DataRequirementCodeFilterComponent drcf : dr.getCodeFilter()) {
if (drcf.getPath().equals("category") && drcf.getValueSet().equals("http://fhir.org/guides/cdc/opioid-cds/ValueSet/observation-category-laboratory")) {
cf = drcf;
break;
}
}
assertNotNull(cf, "Expected filter on category");
cf = null;
for (DataRequirement.DataRequirementCodeFilterComponent drcf : dr.getCodeFilter()) {
if (drcf.getPath().equals("code") && drcf.getValueSet().equals("http://fhir.org/guides/cdc/opioid-cds/ValueSet/pcp-medications")) {
cf = drcf;
break;
}
}
assertNotNull(cf, "Expected filter on code");
} catch (IOException ioException) {
ioException.printStackTrace();
}
}
use of org.hl7.elm_modelinfo.r1.ModelInfo in project clinical_quality_language by cqframework.
the class TestTypes method testModelImporter.
@Test
public void testModelImporter() {
InputStream is = null;
try {
File f = new File(TestTypes.class.getResource("fhir-single.xsd").getFile());
is = new FileInputStream(f);
XmlSchemaCollection schemaCol = new XmlSchemaCollection();
schemaCol.setBaseUri(f.getPath());
XmlSchema schema = schemaCol.read(new StreamSource(is));
ModelInfo modelInfo = ModelImporter.fromXsd(schema, new ModelImporterOptions().withModel("QUICK").withElementRedeclarationPolicy(ModelImporterOptions.ElementRedeclarationPolicy.RENAME_INVALID_REDECLARATIONS), null);
assertThat(modelInfo.getName(), is("QUICK"));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
use of org.hl7.elm_modelinfo.r1.ModelInfo in project clinical_quality_language by cqframework.
the class Cql2ElmVisitor method visitRetrieve.
@Override
@SuppressWarnings("unchecked")
public Retrieve visitRetrieve(cqlParser.RetrieveContext ctx) {
libraryBuilder.checkLiteralContext();
List<String> qualifiers = parseQualifiers(ctx.namedTypeSpecifier());
String model = getModelIdentifier(qualifiers);
String label = getTypeIdentifier(qualifiers, parseString(ctx.namedTypeSpecifier().referentialOrTypeNameIdentifier()));
DataType dataType = libraryBuilder.resolveTypeName(model, label);
if (dataType == null) {
// ERROR:
throw new IllegalArgumentException(String.format("Could not resolve type name %s.", label));
}
if (!(dataType instanceof ClassType) || !((ClassType) dataType).isRetrievable()) {
// ERROR:
throw new IllegalArgumentException(String.format("Specified data type %s does not support retrieval.", label));
}
ClassType classType = (ClassType) dataType;
// BTR -> The original intent of this code was to have the retrieve return the base type, and use the "templateId"
// element of the retrieve to communicate the "positive" or "negative" profile to the data access layer.
// However, because this notion of carrying the "profile" through a type is not general, it causes inconsistencies
// when using retrieve results with functions defined in terms of the same type (see GitHub Issue #131).
// Based on the discussion there, the retrieve will now return the declared type, whether it is a profile or not.
// ProfileType profileType = dataType instanceof ProfileType ? (ProfileType)dataType : null;
// NamedType namedType = profileType == null ? classType : (NamedType)classType.getBaseType();
NamedType namedType = classType;
ModelInfo modelInfo = libraryBuilder.getModel(namedType.getNamespace()).getModelInfo();
boolean useStrictRetrieveTyping = modelInfo.isStrictRetrieveTyping() != null && modelInfo.isStrictRetrieveTyping();
Retrieve retrieve = of.createRetrieve().withDataType(libraryBuilder.dataTypeToQName((DataType) namedType)).withTemplateId(classType.getIdentifier());
if (ctx.contextIdentifier() != null) {
List<String> identifiers = (List<String>) visit(ctx.contextIdentifier());
Expression contextExpression = resolveQualifiedIdentifier(identifiers);
retrieve.setContext(contextExpression);
}
if (ctx.terminology() != null) {
if (ctx.codePath() != null) {
String identifiers = (String) visit(ctx.codePath());
retrieve.setCodeProperty(identifiers);
} else if (classType.getPrimaryCodePath() != null) {
retrieve.setCodeProperty(classType.getPrimaryCodePath());
}
Property property = null;
CqlTranslatorException propertyException = null;
if (retrieve.getCodeProperty() == null) {
// ERROR:
// WARNING:
propertyException = 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.", useStrictRetrieveTyping ? CqlTranslatorException.ErrorSeverity.Error : CqlTranslatorException.ErrorSeverity.Warning, getTrackBack(ctx));
libraryBuilder.recordParsingException(propertyException);
} else {
try {
DataType codeType = libraryBuilder.resolvePath((DataType) namedType, retrieve.getCodeProperty());
property = of.createProperty().withPath(retrieve.getCodeProperty());
property.setResultType(codeType);
} catch (Exception e) {
// ERROR:
// WARNING:
propertyException = new CqlSemanticException(String.format("Could not resolve code path %s for the type of the retrieve %s.", retrieve.getCodeProperty(), namedType.getName()), useStrictRetrieveTyping ? CqlTranslatorException.ErrorSeverity.Error : CqlTranslatorException.ErrorSeverity.Warning, getTrackBack(ctx), e);
libraryBuilder.recordParsingException(propertyException);
}
}
Expression terminology = null;
if (ctx.terminology().qualifiedIdentifierExpression() != null) {
List<String> identifiers = (List<String>) visit(ctx.terminology());
terminology = resolveQualifiedIdentifier(identifiers);
track(terminology, ctx.terminology().qualifiedIdentifierExpression());
} else {
terminology = parseExpression(ctx.terminology().expression());
}
String codeComparator = ctx.codeComparator() != null ? (String) visit(ctx.codeComparator()) : null;
// Resolve the terminology target using an in or ~ operator
try {
if (codeComparator == null) {
codeComparator = (terminology.getResultType() instanceof ListType || (libraryBuilder.isCompatibleWith("1.5") && terminology.getResultType().isSubTypeOf(libraryBuilder.resolveTypeName("System", "Vocabulary")))) ? "in" : "~";
}
if (property == null) {
throw propertyException;
}
switch(codeComparator) {
case "in":
{
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 if (in instanceof AnyInValueSet) {
retrieve.setCodes(((AnyInValueSet) in).getValueset());
} else if (in instanceof AnyInCodeSystem) {
retrieve.setCodes(((AnyInCodeSystem) in).getCodesystem());
} else {
// ERROR:
// WARNING:
libraryBuilder.recordParsingException(new CqlSemanticException(String.format("Unexpected membership operator %s in retrieve", in.getClass().getSimpleName()), useStrictRetrieveTyping ? CqlTranslatorException.ErrorSeverity.Error : CqlTranslatorException.ErrorSeverity.Warning, getTrackBack(ctx)));
}
}
break;
case "~":
{
// Resolve with equivalent to verify the type of the target
BinaryExpression equivalent = of.createEquivalent().withOperand(property, terminology);
libraryBuilder.resolveBinaryCall("System", "Equivalent", equivalent);
// Automatically promote to a list for use in the retrieve target
if (!(equivalent.getOperand().get(1).getResultType() instanceof ListType)) {
retrieve.setCodes(libraryBuilder.resolveToList(equivalent.getOperand().get(1)));
} else {
retrieve.setCodes(equivalent.getOperand().get(1));
}
}
break;
case "=":
{
// Resolve with equality to verify the type of the source and target
BinaryExpression equal = of.createEqual().withOperand(property, terminology);
libraryBuilder.resolveBinaryCall("System", "Equal", equal);
// Automatically promote to a list for use in the retrieve target
if (!(equal.getOperand().get(1).getResultType() instanceof ListType)) {
retrieve.setCodes(libraryBuilder.resolveToList(equal.getOperand().get(1)));
} else {
retrieve.setCodes(equal.getOperand().get(1));
}
}
break;
default:
// ERROR:
// WARNING:
libraryBuilder.recordParsingException(new CqlSemanticException(String.format("Unknown code comparator % in retrieve", codeComparator), useStrictRetrieveTyping ? CqlTranslatorException.ErrorSeverity.Error : CqlTranslatorException.ErrorSeverity.Warning, getTrackBack(ctx.codeComparator())));
}
retrieve.setCodeComparator(codeComparator);
// In that case, convert to a list of code (Union the Code elements of the Concepts in the list)
if (retrieve.getCodes() != null && retrieve.getCodes().getResultType() != null && retrieve.getCodes().getResultType() instanceof ListType && ((ListType) retrieve.getCodes().getResultType()).getElementType().equals(libraryBuilder.resolveTypeName("System", "Concept"))) {
if (retrieve.getCodes() instanceof ToList) {
// ToList will always have a single argument
ToList toList = (ToList) retrieve.getCodes();
// If that argument is a ToConcept, replace the ToList argument with the code (skip the implicit conversion, the data access layer is responsible for it)
if (toList.getOperand() instanceof ToConcept) {
toList.setOperand(((ToConcept) toList.getOperand()).getOperand());
} else {
// Otherwise, access the codes property of the resulting Concept
Expression codesAccessor = libraryBuilder.buildProperty(toList.getOperand(), "codes", false, toList.getOperand().getResultType());
retrieve.setCodes(codesAccessor);
}
} else {
// WARNING:
libraryBuilder.recordParsingException(new CqlSemanticException("Terminology target is a list of concepts, but expects a list of codes", CqlTranslatorException.ErrorSeverity.Warning, getTrackBack(ctx)));
}
}
} catch (Exception e) {
// it shouldn't prevent translation unless the modelinfo indicates strict retrieve typing
if ((libraryBuilder.isCompatibleWith("1.5") && !(terminology.getResultType().isSubTypeOf(libraryBuilder.resolveTypeName("System", "Vocabulary")))) || (!libraryBuilder.isCompatibleWith("1.5") && !(terminology.getResultType() instanceof ListType))) {
retrieve.setCodes(libraryBuilder.resolveToList(terminology));
} else {
retrieve.setCodes(terminology);
}
retrieve.setCodeComparator(codeComparator);
// ERROR:
// WARNING:
libraryBuilder.recordParsingException(new CqlSemanticException("Could not resolve membership operator for terminology target of the retrieve.", useStrictRetrieveTyping ? CqlTranslatorException.ErrorSeverity.Error : CqlTranslatorException.ErrorSeverity.Warning, getTrackBack(ctx), e));
}
}
retrieves.add(retrieve);
retrieve.setResultType(new ListType((DataType) namedType));
return retrieve;
}
Aggregations