use of org.hl7.fhir.r5.model.Extension in project health-patterns by LinuxForHealth.
the class TerminologyService method translateResource.
/**
* Translates the given single FHIR resource represented as a {@link JsonNode}.
*
* @param resource the FHIR resource to translate
* @returns true if there was something to translate, false otherwise
* @throws DeIdentifierException if there is an error in the de-identification REST API or parsing the JSON
* @throws IllegalArgumentException if the given JSON does not have a 'resource' object
*/
private boolean translateResource(JsonNode resource) {
boolean translatedSomething = false;
String resourceType = getResourceType(resource);
boolean isTranslatable = StringUtils.equalsAny(resourceType, TRANSLATABLE_FHIR_TYPES);
if (!isTranslatable) {
return translatedSomething;
}
ArrayNode extensions = (ArrayNode) resource.get(EXTENSION_OBJECT);
if (extensions == null) {
return translatedSomething;
}
for (int i = 0; i < extensions.size(); i++) {
JsonNode extension = extensions.get(i);
JsonNode urlJson = extension.get(URL_OBJECT);
JsonNode valueCodeJson = extension.get(VALUE_CODE_OBJECT);
if (urlJson == null || valueCodeJson == null) {
// In order to do a translation we need both the url and the valueCode
continue;
}
// The resource's extension URL is the URL for the StructureDefinition, so we resolve a ValueSet if known
String structureDefinitionURL = urlJson.asText();
String valueSetURL = valueSetForStructureDefinition.get(structureDefinitionURL);
// and if known we check the FHIR Server's known ConceptMaps to see if there is a corresponding one
// http://4603f72b-us-south.lb.appdomain.cloud/fhir-server/api/v4/ConceptMap?_format=json&source-uri=http://hl7.org/fhir/us/core/ValueSet/birthsex
Bundle bundle = fhirClient.search().forResource(ConceptMap.class).where(ConceptMap.SOURCE_URI.hasId(valueSetURL)).returnBundle(Bundle.class).execute();
String conceptMapId;
if (!bundle.getEntry().isEmpty()) {
Resource conceptMap = bundle.getEntry().get(0).getResource();
if (bundle.getEntry().size() > 1) {
System.err.println("Found multiple ConceptMaps that will map " + valueSetURL + " for this StructureDefinition, will use the first one " + conceptMap.getId());
} else {
System.out.println("Found ConceptMap for " + valueSetURL + ": " + conceptMap.getId() + " !!");
}
conceptMapId = conceptMap.getIdElement().getIdPart();
} else {
System.out.println("Did not find ConceptMap for " + valueSetURL + "!!");
continue;
}
// "POST ${FHIR_URL}/${conceptMapID}/$translate?code=${code}&system=${valueSet}&_format=json
String valueCode = valueCodeJson.asText();
String url = String.format("%s/ConceptMap/%s/$translate?code=%s&system=%s&_format=json", fhirClient.getServerBase(), conceptMapId, valueCode, valueSetURL);
Parameters translationResponse = fhirClient.fetchResourceFromUrl(Parameters.class, url);
// This is what comes back from the server
// {
// "resourceType": "Parameters",
// "parameter": [
// {
// "name": "result",
// "valueBoolean": true
// },
// {
// "name": "match",
// "part": [
// {
// "name": "equivalence",
// "valueCode": "equivalent"
// },
// {
// "name": "concept",
// "valueCoding": {
// "system": "http://ibm.com/fhir/cdm/ValueSet/sex-assigned-at-birth",
// "code": "male",
// "display": "Male"
// }
// }
// ]
// }
// ]
// }
Coding translatedCode = null;
List<ParametersParameterComponent> parameters = translationResponse.getParameter();
for (ParametersParameterComponent parameter : parameters) {
if (parameter.getName().equals(MATCH_VALUE)) {
List<ParametersParameterComponent> parts = parameter.getPart();
for (ParametersParameterComponent part : parts) {
if (part.getName().equals(CONCEPT_VALUE)) {
try {
translatedCode = (Coding) part.getValue();
} catch (ClassCastException e) {
String jsonResponse = fhirClient.getFhirContext().newJsonParser().encodeResourceToString(translationResponse);
System.err.println("Found a ConceptMap that will map " + valueSetURL + " for this StructureDefinition, but the FHIR server returned an unknown $translate response (expected a 'valueCoding' part): " + jsonResponse);
}
}
}
}
}
if (translatedCode == null) {
String jsonResponse = fhirClient.getFhirContext().newJsonParser().encodeResourceToString(translationResponse);
System.err.println("Found a ConceptMap that will map " + valueSetURL + " for this StructureDefinition, but the FHIR server returned an unknown $translate response: " + jsonResponse);
continue;
}
System.out.printf("Found ConceptMap %s which translates (valueCode, system) = (%s, %s) for StructureDefinition %s to (valueCode, system) = (%s, %s) %n", conceptMapId, valueCode, valueSetURL, structureDefinitionURL, translatedCode.getCode(), translatedCode.getSystem());
String translatedStructuredData = valueSetForStructureDefinition.get(translatedCode.getSystem());
if (translatedStructuredData == null) {
System.err.printf("Cannot find the mapping from ValueSet '%s' to its corresponding StructureData for this translation, make sure the corresponding mappings configuration file has it.%n", translatedCode.getSystem());
continue;
}
((ObjectNode) extension).set(URL_OBJECT, JsonNodeFactory.instance.textNode(translatedStructuredData));
((ObjectNode) extension).set(VALUE_CODE_OBJECT, JsonNodeFactory.instance.textNode(translatedCode.getCode()));
translatedSomething = true;
}
return translatedSomething;
}
use of org.hl7.fhir.r5.model.Extension in project cqf-ruler by DBCG.
the class R4CarePlanToCdsCard method convert.
private static List<CdsCard> convert(RequestGroup requestGroup) {
List<CdsCard> cards = new ArrayList<>();
// links
List<CdsCard.Links> links = new ArrayList<>();
if (requestGroup.hasExtension()) {
for (Extension extension : requestGroup.getExtension()) {
CdsCard.Links link = new CdsCard.Links();
if (extension.getValue() instanceof Attachment) {
Attachment attachment = (Attachment) extension.getValue();
if (attachment.hasUrl()) {
link.setUrl(attachment.getUrl());
}
if (attachment.hasTitle()) {
link.setLabel(attachment.getTitle());
}
if (attachment.hasExtension()) {
link.setType(attachment.getExtensionFirstRep().getValue().primitiveValue());
}
} else {
throw new RuntimeException("Invalid link extension type: " + extension.getValue().fhirType());
}
links.add(link);
}
}
if (requestGroup.hasAction()) {
for (RequestGroup.RequestGroupActionComponent action : requestGroup.getAction()) {
IParser jsonParser = FhirContext.forCached(FhirVersionEnum.R4).newJsonParser().setPrettyPrint(true);
CdsCard card = new CdsCard(jsonParser);
// basic
if (action.hasTitle()) {
card.setSummary(action.getTitle());
}
if (action.hasDescription()) {
card.setDetail(action.getDescription());
}
if (action.hasExtension()) {
card.setIndicator(action.getExtensionFirstRep().getValue().toString());
}
// source
if (action.hasDocumentation()) {
// Assuming first related artifact has everything
RelatedArtifact documentation = action.getDocumentationFirstRep();
CdsCard.Source source = new CdsCard.Source();
if (documentation.hasDisplay()) {
source.setLabel(documentation.getDisplay());
}
if (documentation.hasUrl()) {
source.setUrl(documentation.getUrl());
}
if (documentation.hasDocument() && documentation.getDocument().hasUrl()) {
source.setIcon(documentation.getDocument().getUrl());
}
card.setSource(source);
}
if (action.hasSelectionBehavior()) {
card.setSelectionBehavior(action.getSelectionBehavior().toCode());
}
// suggestions
// TODO - uuid
boolean hasSuggestions = false;
CdsCard.Suggestions suggestions = new CdsCard.Suggestions();
CdsCard.Suggestions.Action actions = new CdsCard.Suggestions.Action();
if (action.hasPrefix()) {
suggestions.setLabel(action.getPrefix());
hasSuggestions = true;
if (action.hasDescription()) {
actions.setDescription(action.getDescription());
}
if (action.hasType() && !action.getType().getCodingFirstRep().getCode().equals("fire-event")) {
String code = action.getType().getCodingFirstRep().getCode();
actions.setType(CdsCard.Suggestions.Action.ActionType.valueOf(code.equals("remove") ? "delete" : code));
}
if (action.hasResource()) {
if (actions.getType().name().equalsIgnoreCase("create")) {
action.getResourceTarget().setId((String) null);
}
actions.setResource(action.getResourceTarget());
}
}
if (hasSuggestions) {
suggestions.addAction(actions);
card.addSuggestion(suggestions);
}
if (!links.isEmpty()) {
card.setLinks(links);
}
cards.add(card);
}
}
return cards;
}
use of org.hl7.fhir.r5.model.Extension in project cqf-ruler by DBCG.
the class OAuthProvider method extend.
@Override
public void extend(CapabilityStatement metadata) {
metadata.getRestFirstRep().getSecurity().setCors(securityProperties.getOAuth().getSecurityCors());
Extension securityExtension = metadata.getRestFirstRep().getSecurity().addExtension();
securityExtension.setUrl(securityProperties.getOAuth().getSecurityUrl());
// security.extension.extension
Extension securityExtExt = securityExtension.addExtension();
securityExtExt.setUrl(securityProperties.getOAuth().getSecurityExtAuthUrl());
securityExtExt.setValue(new UriType(securityProperties.getOAuth().getSecurityExtAuthValueUri()));
Extension securityTokenExt = securityExtension.addExtension();
securityTokenExt.setUrl(securityProperties.getOAuth().getSecurityExtTokenUrl());
securityTokenExt.setValue(new UriType(securityProperties.getOAuth().getSecurityExtTokenValueUri()));
// security.extension.service
Coding coding = new Coding();
coding.setSystem(securityProperties.getOAuth().getServiceSystem());
coding.setCode(securityProperties.getOAuth().getServiceCode());
coding.setDisplay(securityProperties.getOAuth().getServiceDisplay());
CodeableConcept codeConcept = new CodeableConcept();
codeConcept.addCoding(coding);
metadata.getRestFirstRep().getSecurity().getService().add(codeConcept);
// metadata.getRestFirstRep().getSecurity().getService() //how do we handle "text" on the sample not part of getService
}
use of org.hl7.fhir.r5.model.Extension in project cqf-ruler by DBCG.
the class MeasureEvaluateProvider method evaluateMeasure.
/**
* Implements the <a href=
* "https://www.hl7.org/fhir/operation-measure-evaluate-measure.html">$evaluate-measure</a>
* operation found in the
* <a href="http://www.hl7.org/fhir/clinicalreasoning-module.html">FHIR Clinical
* Reasoning Module</a>. This implementation aims to be compatible with the CQF
* IG.
*
* @param requestDetails The details (such as tenant) of this request. Usually
* auto-populated HAPI.
* @param theId the Id of the Measure to evaluate
* @param periodStart The start of the reporting period
* @param periodEnd The end of the reporting period
* @param reportType The type of MeasureReport to generate
* @param subject the subject to use for the evaluation
* @param practitioner the practitioner to use for the evaluation
* @param lastReceivedOn the date the results of this measure were last
* received.
* @param productLine the productLine (e.g. Medicare, Medicaid, etc) to use
* for the evaluation. This is a non-standard parameter.
* @param additionalData the data bundle containing additional data
* @return the calculated MeasureReport
*/
// warning for greater than 7 parameters
@SuppressWarnings("squid:S00107")
@Description(shortDefinition = "$evaluate-measure", value = "Implements the <a href=\"https://www.hl7.org/fhir/operation-measure-evaluate-measure.html\">$evaluate-measure</a> operation found in the <a href=\"http://www.hl7.org/fhir/clinicalreasoning-module.html\">FHIR Clinical Reasoning Module</a>. This implementation aims to be compatible with the CQF IG.", example = "Measure/example/$evaluate-measure?subject=Patient/123&periodStart=2019&periodEnd=2020")
@Operation(name = "$evaluate-measure", idempotent = true, type = Measure.class)
public MeasureReport evaluateMeasure(RequestDetails requestDetails, @IdParam IdType theId, @OperationParam(name = "periodStart") String periodStart, @OperationParam(name = "periodEnd") String periodEnd, @OperationParam(name = "reportType") String reportType, @OperationParam(name = "subject") String subject, @OperationParam(name = "practitioner") String practitioner, @OperationParam(name = "lastReceivedOn") String lastReceivedOn, @OperationParam(name = "productLine") String productLine, @OperationParam(name = "additionalData") Bundle additionalData) {
Measure measure = read(theId);
TerminologyProvider terminologyProvider = this.jpaTerminologyProviderFactory.create(requestDetails);
DataProvider dataProvider = this.jpaDataProviderFactory.create(requestDetails, terminologyProvider);
LibraryContentProvider libraryContentProvider = this.libraryContentProviderFactory.create(requestDetails);
FhirDal fhirDal = this.fhirDalFactory.create(requestDetails);
org.opencds.cqf.cql.evaluator.measure.r4.R4MeasureProcessor measureProcessor = new org.opencds.cqf.cql.evaluator.measure.r4.R4MeasureProcessor(null, this.dataProviderFactory, null, null, null, terminologyProvider, libraryContentProvider, dataProvider, fhirDal, null, this.globalLibraryCache);
MeasureReport report = measureProcessor.evaluateMeasure(measure.getUrl(), periodStart, periodEnd, reportType, subject, null, lastReceivedOn, null, null, null, additionalData);
if (productLine != null) {
Extension ext = new Extension();
ext.setUrl("http://hl7.org/fhir/us/cqframework/cqfmeasures/StructureDefinition/cqfm-productLine");
ext.setValue(new StringType(productLine));
report.addExtension(ext);
}
return report;
}
use of org.hl7.fhir.r5.model.Extension in project cqf-ruler by DBCG.
the class Session method resolveActions.
private void resolveActions(List<PlanDefinition.PlanDefinitionActionComponent> actions, Context context, String patientId, RequestGroupBuilder requestGroupBuilder, List<RequestGroup.RequestGroupActionComponent> actionComponents, RequestDetails theRequest) {
for (PlanDefinition.PlanDefinitionActionComponent action : actions) {
boolean conditionsMet = true;
for (PlanDefinition.PlanDefinitionActionConditionComponent condition : action.getCondition()) {
if (condition.getKind() == PlanDefinition.ActionConditionKind.APPLICABILITY) {
if (!condition.hasExpression()) {
continue;
}
if (condition.hasExpression() && !condition.getExpression().hasExpression()) {
continue;
}
Object result = context.resolveExpressionRef(condition.getExpression().getExpression()).getExpression().evaluate(context);
if (!(result instanceof Boolean)) {
continue;
}
if (!(Boolean) result) {
conditionsMet = false;
}
}
if (conditionsMet) {
RequestGroupActionBuilder actionBuilder = new RequestGroupActionBuilder();
if (action.hasTitle()) {
actionBuilder.buildTitle(action.getTitle());
}
if (action.hasDescription()) {
actionBuilder.buildDescripition(action.getDescription());
}
// source
if (action.hasDocumentation()) {
RelatedArtifact artifact = action.getDocumentationFirstRep();
RelatedArtifactBuilder artifactBuilder = new RelatedArtifactBuilder();
if (artifact.hasDisplay()) {
artifactBuilder.buildDisplay(artifact.getDisplay());
}
if (artifact.hasUrl()) {
artifactBuilder.buildUrl(artifact.getUrl());
}
if (artifact.hasDocument() && artifact.getDocument().hasUrl()) {
AttachmentBuilder attachmentBuilder = new AttachmentBuilder();
attachmentBuilder.buildUrl(artifact.getDocument().getUrl());
artifactBuilder.buildDocument(attachmentBuilder.build());
}
actionBuilder.buildDocumentation(Collections.singletonList(artifactBuilder.build()));
}
// TODO - uuid
if (action.hasPrefix()) {
actionBuilder.buildPrefix(action.getPrefix());
}
if (action.hasType()) {
actionBuilder.buildType(action.getType());
}
if (action.hasDefinition()) {
if (action.getDefinitionCanonicalType().getValue().contains("ActivityDefinition")) {
ActivityDefinition activityDefinition = this.activityDefinitionDao.read(new IdType("ActivityDefinition", action.getDefinitionCanonicalType().getId()));
if (activityDefinition.hasDescription()) {
actionBuilder.buildDescripition(activityDefinition.getDescription());
}
try {
this.activityDefinitionApplyProvider.apply(theRequest, new IdType(action.getDefinitionCanonicalType().getId()), patientId, null, null, null, null, null, null, null, null).setId(UUID.randomUUID().toString());
} catch (FHIRException e) {
throw new RuntimeException("Error applying ActivityDefinition " + e.getMessage());
}
Parameters inParams = new Parameters();
inParams.addParameter().setName("patient").setValue(new StringType(patientId));
Parameters outParams = this.fhirContext.newRestfulGenericClient(theRequest.getFhirServerBase()).operation().onInstance(new IdDt("ActivityDefinition", action.getDefinition().getId())).named("$apply").withParameters(inParams).useHttpGet().execute();
List<Parameters.ParametersParameterComponent> response = outParams.getParameter();
Resource resource = response.get(0).getResource().setId(UUID.randomUUID().toString());
actionBuilder.buildResourceTarget(resource);
actionBuilder.buildResource(new ReferenceBuilder().buildReference(resource.getId()).build());
}
}
// on here...
if (action.hasDynamicValue()) {
for (PlanDefinition.PlanDefinitionActionDynamicValueComponent dynamicValue : action.getDynamicValue()) {
if (dynamicValue.hasPath() && dynamicValue.hasExpression()) {
if (dynamicValue.getPath().endsWith("title")) {
// summary
String title = (String) context.resolveExpressionRef(dynamicValue.getExpression().getExpression()).evaluate(context);
actionBuilder.buildTitle(title);
} else if (dynamicValue.getPath().endsWith("description")) {
// detail
String description = (String) context.resolveExpressionRef(dynamicValue.getExpression().getExpression()).evaluate(context);
actionBuilder.buildDescripition(description);
} else if (dynamicValue.getPath().endsWith("extension")) {
// indicator
String extension = (String) context.resolveExpressionRef(dynamicValue.getExpression().getExpression()).evaluate(context);
actionBuilder.buildExtension(extension);
}
}
}
}
if (!actionBuilder.build().isEmpty()) {
actionComponents.add(actionBuilder.build());
}
if (action.hasAction()) {
resolveActions(action.getAction(), context, patientId, requestGroupBuilder, actionComponents, theRequest);
}
}
}
}
requestGroupBuilder.buildAction(new ArrayList<>(actionComponents));
}
Aggregations