use of org.hl7.fhir.r4.model.CodeType in project synthea by synthetichealth.
the class FhirStu3 method immunization.
private static BundleEntryComponent immunization(RandomNumberGenerator rand, BundleEntryComponent personEntry, Bundle bundle, BundleEntryComponent encounterEntry, HealthRecord.Entry immunization) {
Immunization immResource = new Immunization();
immResource.setStatus(ImmunizationStatus.COMPLETED);
immResource.setDate(new Date(immunization.start));
immResource.setVaccineCode(mapCodeToCodeableConcept(immunization.codes.get(0), CVX_URI));
immResource.setNotGiven(false);
immResource.setPrimarySource(true);
immResource.setPatient(new Reference(personEntry.getFullUrl()));
immResource.setEncounter(new Reference(encounterEntry.getFullUrl()));
if (USE_SHR_EXTENSIONS) {
immResource.setMeta(new Meta().addProfile(SHR_EXT + "shr-immunization-ImmunizationGiven"));
// profile requires action-PerformedContext-extension, status, notGiven, vaccineCode, patient,
// date, primarySource
Extension performedContext = new Extension();
performedContext.setUrl(SHR_EXT + "shr-action-PerformedContext-extension");
performedContext.addExtension(SHR_EXT + "shr-action-Status-extension", new CodeType("completed"));
immResource.addExtension(performedContext);
}
BundleEntryComponent immunizationEntry = newEntry(rand, bundle, immResource);
immunization.fullUrl = immunizationEntry.getFullUrl();
return immunizationEntry;
}
use of org.hl7.fhir.r4.model.CodeType in project synthea by synthetichealth.
the class FhirStu3 method medication.
/**
* Map the given Medication to a FHIR MedicationRequest resource, and add it to the given Bundle.
*
* @param rand Source of randomness to use when generating ids etc
* @param personEntry The Entry for the Person
* @param bundle Bundle to add the Medication to
* @param encounterEntry Current Encounter entry
* @param medication The Medication
* @return The added Entry
*/
private static BundleEntryComponent medication(RandomNumberGenerator rand, BundleEntryComponent personEntry, Bundle bundle, BundleEntryComponent encounterEntry, Medication medication) {
MedicationRequest medicationResource = new MedicationRequest();
medicationResource.setSubject(new Reference(personEntry.getFullUrl()));
medicationResource.setContext(new Reference(encounterEntry.getFullUrl()));
Code code = medication.codes.get(0);
String system = code.system.equals("SNOMED-CT") ? SNOMED_URI : RXNORM_URI;
medicationResource.setMedication(mapCodeToCodeableConcept(code, system));
medicationResource.setAuthoredOn(new Date(medication.start));
medicationResource.setIntent(MedicationRequestIntent.ORDER);
org.hl7.fhir.dstu3.model.Encounter encounter = (org.hl7.fhir.dstu3.model.Encounter) encounterEntry.getResource();
MedicationRequestRequesterComponent requester = new MedicationRequestRequesterComponent();
requester.setAgent(encounter.getParticipantFirstRep().getIndividual());
requester.setOnBehalfOf(encounter.getServiceProvider());
medicationResource.setRequester(requester);
if (medication.stop != 0L) {
medicationResource.setStatus(MedicationRequestStatus.STOPPED);
} else {
medicationResource.setStatus(MedicationRequestStatus.ACTIVE);
}
if (!medication.reasons.isEmpty()) {
// Only one element in list
Code reason = medication.reasons.get(0);
for (BundleEntryComponent entry : bundle.getEntry()) {
if (entry.getResource().fhirType().equals("Condition")) {
Condition condition = (Condition) entry.getResource();
// Only one element in list
Coding coding = condition.getCode().getCoding().get(0);
if (reason.code.equals(coding.getCode())) {
medicationResource.addReasonReference().setReference(entry.getFullUrl());
}
}
}
}
if (medication.prescriptionDetails != null) {
JsonObject rxInfo = medication.prescriptionDetails;
Dosage dosage = new Dosage();
dosage.setSequence(1);
// as_needed is true if present
dosage.setAsNeeded(new BooleanType(rxInfo.has("as_needed")));
// as_needed is true if present
if ((rxInfo.has("dosage")) && (!rxInfo.has("as_needed"))) {
Timing timing = new Timing();
TimingRepeatComponent timingRepeatComponent = new TimingRepeatComponent();
timingRepeatComponent.setFrequency(rxInfo.get("dosage").getAsJsonObject().get("frequency").getAsInt());
timingRepeatComponent.setPeriod(rxInfo.get("dosage").getAsJsonObject().get("period").getAsDouble());
timingRepeatComponent.setPeriodUnit(convertUcumCode(rxInfo.get("dosage").getAsJsonObject().get("unit").getAsString()));
timing.setRepeat(timingRepeatComponent);
dosage.setTiming(timing);
Quantity dose = new SimpleQuantity().setValue(rxInfo.get("dosage").getAsJsonObject().get("amount").getAsDouble());
dosage.setDose(dose);
if (rxInfo.has("instructions")) {
for (JsonElement instructionElement : rxInfo.get("instructions").getAsJsonArray()) {
JsonObject instruction = instructionElement.getAsJsonObject();
Code instructionCode = new Code(SNOMED_URI, instruction.get("code").getAsString(), instruction.get("display").getAsString());
dosage.addAdditionalInstruction(mapCodeToCodeableConcept(instructionCode, SNOMED_URI));
}
}
}
List<Dosage> dosageInstruction = new ArrayList<Dosage>();
dosageInstruction.add(dosage);
medicationResource.setDosageInstruction(dosageInstruction);
}
if (USE_SHR_EXTENSIONS) {
medicationResource.addExtension().setUrl(SHR_EXT + "shr-base-ActionCode-extension").setValue(PRESCRIPTION_OF_DRUG_CC);
medicationResource.setMeta(new Meta().addProfile(SHR_EXT + "shr-medication-MedicationRequested"));
// required fields for this profile are status, action-RequestedContext-extension,
// medication[x]subject, authoredOn, requester
Extension requestedContext = new Extension();
requestedContext.setUrl(SHR_EXT + "shr-action-RequestedContext-extension");
requestedContext.addExtension(SHR_EXT + "shr-action-Status-extension", new CodeType("completed"));
requestedContext.addExtension(SHR_EXT + "shr-action-RequestIntent-extension", new CodeType("original-order"));
medicationResource.addExtension(requestedContext);
}
BundleEntryComponent medicationEntry = newEntry(rand, bundle, medicationResource);
// create new claim for medication
medicationClaim(rand, personEntry, bundle, encounterEntry, medication.claim, medicationEntry);
// Create new administration for medication, if needed
if (medication.administration) {
medicationAdministration(rand, personEntry, bundle, encounterEntry, medication, medicationResource);
}
return medicationEntry;
}
use of org.hl7.fhir.r4.model.CodeType in project synthea by synthetichealth.
the class FhirStu3 method procedure.
/**
* Map the given Procedure into a FHIR Procedure resource, and add it to the given Bundle.
*
* @param rand Source of randomness to use when generating ids etc
* @param personEntry The Person entry
* @param bundle Bundle to add to
* @param encounterEntry The current Encounter entry
* @param procedure The Procedure
* @return The added Entry
*/
private static BundleEntryComponent procedure(RandomNumberGenerator rand, BundleEntryComponent personEntry, Bundle bundle, BundleEntryComponent encounterEntry, Procedure procedure) {
org.hl7.fhir.dstu3.model.Procedure procedureResource = new org.hl7.fhir.dstu3.model.Procedure();
procedureResource.setStatus(ProcedureStatus.COMPLETED);
procedureResource.setSubject(new Reference(personEntry.getFullUrl()));
procedureResource.setContext(new Reference(encounterEntry.getFullUrl()));
Code code = procedure.codes.get(0);
CodeableConcept procCode = mapCodeToCodeableConcept(code, SNOMED_URI);
procedureResource.setCode(procCode);
if (procedure.stop != 0L) {
Date startDate = new Date(procedure.start);
Date endDate = new Date(procedure.stop);
procedureResource.setPerformed(new Period().setStart(startDate).setEnd(endDate));
} else {
procedureResource.setPerformed(convertFhirDateTime(procedure.start, true));
}
if (!procedure.reasons.isEmpty()) {
// Only one element in list
Code reason = procedure.reasons.get(0);
for (BundleEntryComponent entry : bundle.getEntry()) {
if (entry.getResource().fhirType().equals("Condition")) {
Condition condition = (Condition) entry.getResource();
// Only one element in list
Coding coding = condition.getCode().getCoding().get(0);
if (reason.code.equals(coding.getCode())) {
procedureResource.addReasonReference().setReference(entry.getFullUrl()).setDisplay(reason.display);
}
}
}
}
if (USE_SHR_EXTENSIONS) {
procedureResource.setMeta(new Meta().addProfile(SHR_EXT + "shr-procedure-ProcedurePerformed"));
// required fields for this profile are action-PerformedContext-extension,
// status, code, subject, performed[x]
Extension performedContext = new Extension();
performedContext.setUrl(SHR_EXT + "shr-action-PerformedContext-extension");
performedContext.addExtension(SHR_EXT + "shr-action-Status-extension", new CodeType("completed"));
procedureResource.addExtension(performedContext);
}
BundleEntryComponent procedureEntry = newEntry(rand, bundle, procedureResource);
procedure.fullUrl = procedureEntry.getFullUrl();
return procedureEntry;
}
use of org.hl7.fhir.r4.model.CodeType in project synthea by synthetichealth.
the class FhirStu3 method basicInfo.
/**
* Map the given Person to a FHIR Patient resource, and add it to the given Bundle.
*
* @param person The Person
* @param bundle The Bundle to add to
* @param stopTime Time the simulation ended
* @return The created Entry
*/
@SuppressWarnings("rawtypes")
private static BundleEntryComponent basicInfo(Person person, Bundle bundle, long stopTime) {
Patient patientResource = new Patient();
patientResource.addIdentifier().setSystem("https://github.com/synthetichealth/synthea").setValue((String) person.attributes.get(Person.ID));
Code mrnCode = new Code("http://hl7.org/fhir/v2/0203", "MR", "Medical Record Number");
patientResource.addIdentifier().setType(mapCodeToCodeableConcept(mrnCode, "http://hl7.org/fhir/v2/0203")).setSystem("http://hospital.smarthealthit.org").setValue((String) person.attributes.get(Person.ID));
Code ssnCode = new Code("http://hl7.org/fhir/identifier-type", "SB", "Social Security Number");
patientResource.addIdentifier().setType(mapCodeToCodeableConcept(ssnCode, "http://hl7.org/fhir/identifier-type")).setSystem("http://hl7.org/fhir/sid/us-ssn").setValue((String) person.attributes.get(Person.IDENTIFIER_SSN));
if (person.attributes.get(Person.IDENTIFIER_DRIVERS) != null) {
Code driversCode = new Code("http://hl7.org/fhir/v2/0203", "DL", "Driver's License");
patientResource.addIdentifier().setType(mapCodeToCodeableConcept(driversCode, "http://hl7.org/fhir/v2/0203")).setSystem("urn:oid:2.16.840.1.113883.4.3.25").setValue((String) person.attributes.get(Person.IDENTIFIER_DRIVERS));
}
if (person.attributes.get(Person.IDENTIFIER_PASSPORT) != null) {
Code passportCode = new Code("http://hl7.org/fhir/v2/0203", "PPN", "Passport Number");
patientResource.addIdentifier().setType(mapCodeToCodeableConcept(passportCode, "http://hl7.org/fhir/v2/0203")).setSystem(SHR_EXT + "passportNumber").setValue((String) person.attributes.get(Person.IDENTIFIER_PASSPORT));
}
if (person.attributes.get(Person.CONTACT_EMAIL) != null) {
ContactComponent contact = new ContactComponent();
HumanName contactName = new HumanName();
contactName.setUse(HumanName.NameUse.OFFICIAL);
contactName.addGiven((String) person.attributes.get(Person.CONTACT_GIVEN_NAME));
contactName.setFamily((String) person.attributes.get(Person.CONTACT_FAMILY_NAME));
contact.setName(contactName);
contact.addTelecom().setSystem(ContactPointSystem.EMAIL).setUse(ContactPointUse.HOME).setValue((String) person.attributes.get(Person.CONTACT_EMAIL));
patientResource.addContact(contact);
}
// We do not yet account for mixed race
Extension raceExtension = new Extension("http://hl7.org/fhir/us/core/StructureDefinition/us-core-race");
String race = (String) person.attributes.get(Person.RACE);
String raceDisplay;
switch(race) {
case "white":
raceDisplay = "White";
break;
case "black":
raceDisplay = "Black or African American";
break;
case "asian":
raceDisplay = "Asian";
break;
case "native":
raceDisplay = "American Indian or Alaska Native";
break;
case "hawaiian":
raceDisplay = "Native Hawaiian or Other Pacific Islander";
break;
default:
raceDisplay = "Other";
break;
}
String raceNum = (String) raceEthnicityCodes.get(race);
Extension raceCodingExtension = new Extension("ombCategory");
Coding raceCoding = new Coding();
if (raceDisplay.equals("Other")) {
raceCoding.setSystem("http://hl7.org/fhir/v3/NullFlavor");
raceCoding.setCode("UNK");
raceCoding.setDisplay("Unknown");
} else {
raceCoding.setSystem("urn:oid:2.16.840.1.113883.6.238");
raceCoding.setCode(raceNum);
raceCoding.setDisplay(raceDisplay);
}
raceCodingExtension.setValue(raceCoding);
raceExtension.addExtension(raceCodingExtension);
Extension raceTextExtension = new Extension("text");
raceTextExtension.setValue(new StringType(raceDisplay));
raceExtension.addExtension(raceTextExtension);
patientResource.addExtension(raceExtension);
// We do not yet account for mixed ethnicity
Extension ethnicityExtension = new Extension("http://hl7.org/fhir/us/core/StructureDefinition/us-core-ethnicity");
String ethnicity = (String) person.attributes.get(Person.ETHNICITY);
String ethnicityDisplay;
if (ethnicity.equals("hispanic")) {
ethnicity = "hispanic";
ethnicityDisplay = "Hispanic or Latino";
} else {
ethnicity = "nonhispanic";
ethnicityDisplay = "Not Hispanic or Latino";
}
String ethnicityNum = (String) raceEthnicityCodes.get(ethnicity);
Extension ethnicityCodingExtension = new Extension("ombCategory");
Coding ethnicityCoding = new Coding();
ethnicityCoding.setSystem("urn:oid:2.16.840.1.113883.6.238");
ethnicityCoding.setCode(ethnicityNum);
ethnicityCoding.setDisplay(ethnicityDisplay);
ethnicityCodingExtension.setValue(ethnicityCoding);
ethnicityExtension.addExtension(ethnicityCodingExtension);
Extension ethnicityTextExtension = new Extension("text");
ethnicityTextExtension.setValue(new StringType(ethnicityDisplay));
ethnicityExtension.addExtension(ethnicityTextExtension);
patientResource.addExtension(ethnicityExtension);
String firstLanguage = (String) person.attributes.get(Person.FIRST_LANGUAGE);
Map languageMap = (Map) languageLookup.get(firstLanguage);
Code languageCode = new Code((String) languageMap.get("system"), (String) languageMap.get("code"), (String) languageMap.get("display"));
List<PatientCommunicationComponent> communication = new ArrayList<PatientCommunicationComponent>();
communication.add(new PatientCommunicationComponent(mapCodeToCodeableConcept(languageCode, (String) languageMap.get("system"))));
patientResource.setCommunication(communication);
HumanName name = patientResource.addName();
name.setUse(HumanName.NameUse.OFFICIAL);
name.addGiven((String) person.attributes.get(Person.FIRST_NAME));
name.setFamily((String) person.attributes.get(Person.LAST_NAME));
if (person.attributes.get(Person.NAME_PREFIX) != null) {
name.addPrefix((String) person.attributes.get(Person.NAME_PREFIX));
}
if (person.attributes.get(Person.NAME_SUFFIX) != null) {
name.addSuffix((String) person.attributes.get(Person.NAME_SUFFIX));
}
if (person.attributes.get(Person.MAIDEN_NAME) != null) {
HumanName maidenName = patientResource.addName();
maidenName.setUse(HumanName.NameUse.MAIDEN);
maidenName.addGiven((String) person.attributes.get(Person.FIRST_NAME));
maidenName.setFamily((String) person.attributes.get(Person.MAIDEN_NAME));
if (person.attributes.get(Person.NAME_PREFIX) != null) {
maidenName.addPrefix((String) person.attributes.get(Person.NAME_PREFIX));
}
if (person.attributes.get(Person.NAME_SUFFIX) != null) {
maidenName.addSuffix((String) person.attributes.get(Person.NAME_SUFFIX));
}
}
Extension mothersMaidenNameExtension = new Extension("http://hl7.org/fhir/StructureDefinition/patient-mothersMaidenName");
String mothersMaidenName = (String) person.attributes.get(Person.NAME_MOTHER);
mothersMaidenNameExtension.setValue(new StringType(mothersMaidenName));
patientResource.addExtension(mothersMaidenNameExtension);
long birthdate = (long) person.attributes.get(Person.BIRTHDATE);
patientResource.setBirthDate(new Date(birthdate));
Extension birthSexExtension = new Extension("http://hl7.org/fhir/us/core/StructureDefinition/us-core-birthsex");
if (person.attributes.get(Person.GENDER).equals("M")) {
patientResource.setGender(AdministrativeGender.MALE);
birthSexExtension.setValue(new CodeType("M"));
} else if (person.attributes.get(Person.GENDER).equals("F")) {
patientResource.setGender(AdministrativeGender.FEMALE);
birthSexExtension.setValue(new CodeType("F"));
}
patientResource.addExtension(birthSexExtension);
String state = (String) person.attributes.get(Person.STATE);
Address addrResource = patientResource.addAddress();
addrResource.addLine((String) person.attributes.get(Person.ADDRESS)).setCity((String) person.attributes.get(Person.CITY)).setPostalCode((String) person.attributes.get(Person.ZIP)).setState(state);
if (COUNTRY_CODE != null) {
addrResource.setCountry(COUNTRY_CODE);
}
Address birthplace = new Address();
birthplace.setCity((String) person.attributes.get(Person.BIRTH_CITY)).setState((String) person.attributes.get(Person.BIRTH_STATE)).setCountry((String) person.attributes.get(Person.BIRTH_COUNTRY));
Extension birthplaceExtension = new Extension("http://hl7.org/fhir/StructureDefinition/birthPlace");
birthplaceExtension.setValue(birthplace);
patientResource.addExtension(birthplaceExtension);
if (person.attributes.get(Person.MULTIPLE_BIRTH_STATUS) != null) {
patientResource.setMultipleBirth(new IntegerType((int) person.attributes.get(Person.MULTIPLE_BIRTH_STATUS)));
} else {
patientResource.setMultipleBirth(new BooleanType(false));
}
patientResource.addTelecom().setSystem(ContactPoint.ContactPointSystem.PHONE).setUse(ContactPoint.ContactPointUse.HOME).setValue((String) person.attributes.get(Person.TELECOM));
String maritalStatus = ((String) person.attributes.get(Person.MARITAL_STATUS));
if (maritalStatus != null) {
Code maritalStatusCode = new Code("http://hl7.org/fhir/v3/MaritalStatus", maritalStatus, maritalStatus);
patientResource.setMaritalStatus(mapCodeToCodeableConcept(maritalStatusCode, "http://hl7.org/fhir/v3/MaritalStatus"));
} else {
Code maritalStatusCode = new Code("http://hl7.org/fhir/v3/MaritalStatus", "S", "Never Married");
patientResource.setMaritalStatus(mapCodeToCodeableConcept(maritalStatusCode, "http://hl7.org/fhir/v3/MaritalStatus"));
}
Point2D.Double coord = person.getLonLat();
if (coord != null) {
Extension geolocation = addrResource.addExtension();
geolocation.setUrl("http://hl7.org/fhir/StructureDefinition/geolocation");
geolocation.addExtension("latitude", new DecimalType(coord.getY()));
geolocation.addExtension("longitude", new DecimalType(coord.getX()));
}
if (!person.alive(stopTime)) {
patientResource.setDeceased(convertFhirDateTime((Long) person.attributes.get(Person.DEATHDATE), true));
}
String generatedBySynthea = "Generated by <a href=\"https://github.com/synthetichealth/synthea\">Synthea</a>." + "Version identifier: " + Utilities.SYNTHEA_VERSION + " . " + " Person seed: " + person.getSeed() + " Population seed: " + person.populationSeed;
patientResource.setText(new Narrative().setStatus(NarrativeStatus.GENERATED).setDiv(new XhtmlNode(NodeType.Element).setValue(generatedBySynthea)));
if (USE_SHR_EXTENSIONS) {
patientResource.setMeta(new Meta().addProfile(SHR_EXT + "shr-entity-Patient"));
// Patient profile requires race, ethnicity, birthsex,
// MothersMaidenName, FathersName, Person-extension
patientResource.addExtension().setUrl(SHR_EXT + "shr-actor-FictionalPerson-extension").setValue(new BooleanType(true));
String fathersName = (String) person.attributes.get(Person.NAME_FATHER);
Extension fathersNameExtension = new Extension(SHR_EXT + "shr-entity-FathersName-extension", new HumanName().setText(fathersName));
patientResource.addExtension(fathersNameExtension);
String ssn = (String) person.attributes.get(Person.IDENTIFIER_SSN);
Extension ssnExtension = new Extension(SHR_EXT + "shr-demographics-SocialSecurityNumber-extension", new StringType(ssn));
patientResource.addExtension(ssnExtension);
Basic personResource = new Basic();
// the only required field on this patient resource is code
Coding fixedCode = new Coding("http://standardhealthrecord.org/fhir/basic-resource-type", "shr-entity-Person", "shr-entity-Person");
personResource.setCode(new CodeableConcept().addCoding(fixedCode));
Meta personMeta = new Meta();
personMeta.addProfile(SHR_EXT + "shr-entity-Person");
personResource.setMeta(personMeta);
BundleEntryComponent personEntry = newEntry(person, bundle, personResource);
patientResource.addExtension().setUrl(SHR_EXT + "shr-entity-Person-extension").setValue(new Reference(personEntry.getFullUrl()));
}
// DALY and QALY values
// we only write the last(current) one to the patient record
Double dalyValue = (Double) person.attributes.get("most-recent-daly");
Double qalyValue = (Double) person.attributes.get("most-recent-qaly");
if (dalyValue != null) {
Extension dalyExtension = new Extension(SYNTHEA_EXT + "disability-adjusted-life-years");
DecimalType daly = new DecimalType(dalyValue);
dalyExtension.setValue(daly);
patientResource.addExtension(dalyExtension);
Extension qalyExtension = new Extension(SYNTHEA_EXT + "quality-adjusted-life-years");
DecimalType qaly = new DecimalType(qalyValue);
qalyExtension.setValue(qaly);
patientResource.addExtension(qalyExtension);
}
return newEntry(bundle, patientResource, (String) person.attributes.get(Person.ID));
}
use of org.hl7.fhir.r4.model.CodeType 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;
CqlCompilerException 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 ? CqlCompilerException.ErrorSeverity.Error : CqlCompilerException.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 ? CqlCompilerException.ErrorSeverity.Error : CqlCompilerException.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 ? CqlCompilerException.ErrorSeverity.Error : CqlCompilerException.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 ? CqlCompilerException.ErrorSeverity.Error : CqlCompilerException.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", CqlCompilerException.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 ? CqlCompilerException.ErrorSeverity.Error : CqlCompilerException.ErrorSeverity.Warning, getTrackBack(ctx), e));
}
}
retrieves.add(retrieve);
retrieve.setResultType(new ListType((DataType) namedType));
return retrieve;
}
Aggregations