Search in sources :

Example 1 with ParametersParameterComponent

use of org.hl7.fhir.r4b.model.Parameters.ParametersParameterComponent in project gpconnect-demonstrator by nhsconnect.

the class PatientResourceProvider method registerPatient.

@Operation(name = REGISTER_PATIENT_OPERATION_NAME)
public Bundle registerPatient(@ResourceParam Parameters params) {
    Patient registeredPatient = null;
    validateParameterNames(params, registerPatientParams);
    Patient unregisteredPatient = params.getParameter().stream().filter(param -> "registerPatient".equalsIgnoreCase(param.getName())).map(ParametersParameterComponent::getResource).map(Patient.class::cast).findFirst().orElse(null);
    String nnn = nhsNumber.fromPatientResource(unregisteredPatient);
    // if its patient 14 spoof not on PDS and return the required error
    if (nnn.equals(patientNotOnSpine)) {
        throw OperationOutcomeFactory.buildOperationOutcomeException(new InvalidRequestException(String.format("Patient (NHS number - %s) not present on PDS", nnn)), SystemCode.INVALID_PATIENT_DEMOGRAPHICS, IssueType.INVALID);
    } else if (nnn.equals(patientSuperseded)) {
        throw OperationOutcomeFactory.buildOperationOutcomeException(new InvalidRequestException(String.format("Patient (NHS number - %s) is superseded", nnn)), SystemCode.INVALID_NHS_NUMBER, IssueType.INVALID);
    }
    if (unregisteredPatient != null) {
        validatePatient(unregisteredPatient);
        // check if the patient already exists
        PatientDetails patientDetails = patientSearch.findPatient(nhsNumber.fromPatientResource(unregisteredPatient));
        if (patientDetails == null || IsInactiveTemporaryPatient(patientDetails)) {
            if (patientDetails == null) {
                patientDetails = registerPatientResourceConverterToPatientDetail(unregisteredPatient);
                patientStore.create(patientDetails);
            } else {
                // reactivate inactive non temporary patient
                patientDetails.setRegistrationStatus(ACTIVE_REGISTRATION_STATUS);
                updateAddressAndTelecom(unregisteredPatient, patientDetails);
                patientStore.update(patientDetails);
            }
            try {
                registeredPatient = patientDetailsToRegisterPatientResourceConverter(patientSearch.findPatient(unregisteredPatient.getIdentifierFirstRep().getValue()));
                addPreferredBranchSurgeryExtension(registeredPatient);
            } catch (FHIRException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        } else if (patientDetails.isDeceased() || patientDetails.isSensitive()) {
            throw OperationOutcomeFactory.buildOperationOutcomeException(new InvalidRequestException(String.format("Patient (NHS number - %s) has invalid demographics", nnn)), SystemCode.INVALID_PATIENT_DEMOGRAPHICS, IssueType.INVALID);
        } else {
            throw OperationOutcomeFactory.buildOperationOutcomeException(new UnclassifiedServerFailureException(409, String.format("Patient (NHS number - %s) already exists", nnn)), SystemCode.DUPLICATE_REJECTED, IssueType.INVALID);
        }
    } else {
        throw OperationOutcomeFactory.buildOperationOutcomeException(new UnprocessableEntityException("Patient record not found"), SystemCode.INVALID_PARAMETER, IssueType.INVALID);
    }
    Bundle bundle = new Bundle().setType(BundleType.SEARCHSET);
    bundle.getMeta().addProfile(SystemURL.SD_GPC_SRCHSET_BUNDLE);
    bundle.addEntry().setResource(registeredPatient);
    return bundle;
}
Also used : UnprocessableEntityException(ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException) UnclassifiedServerFailureException(ca.uhn.fhir.rest.server.exceptions.UnclassifiedServerFailureException) PatientDetails(uk.gov.hscic.model.patient.PatientDetails) PopulateMedicationBundle(uk.gov.hscic.medications.PopulateMedicationBundle) InvalidRequestException(ca.uhn.fhir.rest.server.exceptions.InvalidRequestException) FHIRException(org.hl7.fhir.exceptions.FHIRException)

Example 2 with ParametersParameterComponent

use of org.hl7.fhir.r4b.model.Parameters.ParametersParameterComponent in project gpconnect-demonstrator by nhsconnect.

the class PatientResourceProvider method StructuredRecordOperation.

@Operation(name = GET_STRUCTURED_RECORD_OPERATION_NAME)
public Bundle StructuredRecordOperation(@ResourceParam Parameters params) throws FHIRException {
    Bundle structuredBundle = new Bundle();
    Boolean getAllergies = false;
    Boolean includeResolved = false;
    Boolean getMedications = false;
    Boolean includePrescriptionIssues = false;
    Period medicationPeriod = null;
    String NHS = getNhsNumber(params);
    PatientDetails patientDetails = patientSearch.findPatient(NHS);
    // see https://nhsconnect.github.io/gpconnect/accessrecord_structured_development_retrieve_patient_record.html#error-handling
    if (patientDetails == null || patientDetails.isSensitive() || patientDetails.isDeceased() || !patientDetails.isActive()) {
        throw OperationOutcomeFactory.buildOperationOutcomeException(new ResourceNotFoundException("No patient details found for patient ID: " + NHS), SystemCode.PATIENT_NOT_FOUND, IssueType.NOTFOUND);
    }
    if (NHS.equals(patientNoconsent)) {
        throw OperationOutcomeFactory.buildOperationOutcomeException(new ForbiddenOperationException("No patient consent to share for patient ID: " + NHS), SystemCode.NO_PATIENT_CONSENT, IssueType.FORBIDDEN);
    }
    operationOutcome = null;
    for (ParametersParameterComponent param : params.getParameter()) {
        if (validateParametersName(param.getName())) {
            if (param.getName().equals(SystemConstants.INCLUDE_ALLERGIES)) {
                getAllergies = true;
                if (param.getPart().isEmpty()) {
                    // addWarningIssue(param, IssueType.REQUIRED, "Miss parameter part : " + SystemConstants.INCLUDE_RESOLVED_ALLERGIES);
                    throw OperationOutcomeFactory.buildOperationOutcomeException(new UnprocessableEntityException("Miss parameter : " + SystemConstants.INCLUDE_RESOLVED_ALLERGIES), SystemCode.INVALID_PARAMETER, IssueType.REQUIRED);
                }
                boolean includeResolvedParameterPartPresent = false;
                for (ParametersParameterComponent paramPart : param.getPart()) {
                    if (paramPart.getName().equals(SystemConstants.INCLUDE_RESOLVED_ALLERGIES)) {
                        if (paramPart.getValue() instanceof BooleanType) {
                            includeResolved = Boolean.valueOf(paramPart.getValue().primitiveValue());
                            includeResolvedParameterPartPresent = true;
                        } else {
                            throw OperationOutcomeFactory.buildOperationOutcomeException(new UnprocessableEntityException("Miss parameter : " + SystemConstants.INCLUDE_RESOLVED_ALLERGIES), SystemCode.INVALID_PARAMETER, IssueType.REQUIRED);
                        }
                    } else {
                        addWarningIssue(param, paramPart, IssueType.NOTSUPPORTED);
                    // throw OperationOutcomeFactory.buildOperationOutcomeException(
                    // new UnprocessableEntityException("Incorrect parameter passed : " + paramPart.getName()),
                    // SystemCode.INVALID_PARAMETER, IssueType.INVALID);
                    }
                }
                if (!includeResolvedParameterPartPresent) {
                    throw OperationOutcomeFactory.buildOperationOutcomeException(new UnprocessableEntityException("Miss parameter : " + SystemConstants.INCLUDE_RESOLVED_ALLERGIES), SystemCode.INVALID_PARAMETER, IssueType.REQUIRED);
                }
            }
            if (param.getName().equals(SystemConstants.INCLUDE_MEDICATION)) {
                getMedications = true;
                boolean isIncludedPrescriptionIssuesExist = false;
                for (ParametersParameterComponent paramPart : param.getPart()) {
                    if (paramPart.getName().equals(SystemConstants.INCLUDE_PRESCRIPTION_ISSUES)) {
                        if (paramPart.getValue() instanceof BooleanType) {
                            includePrescriptionIssues = Boolean.valueOf(paramPart.getValue().primitiveValue());
                            isIncludedPrescriptionIssuesExist = true;
                        }
                    } else if (paramPart.getName().equals(SystemConstants.MEDICATION_SEARCH_FROM_DATE) && paramPart.getValue() instanceof DateType) {
                        DateType startDateDt = (DateType) paramPart.getValue();
                        medicationPeriod = new Period();
                        medicationPeriod.setStart(startDateDt.getValue());
                        medicationPeriod.setEnd(null);
                        String startDate = startDateDt.asStringValue();
                        if (!validateStartDateParamAndEndDateParam(startDate, null)) {
                        // addWarningIssue(param, paramPart, IssueType.INVALID, "Invalid date used");
                        }
                    } else {
                        addWarningIssue(param, paramPart, IssueType.NOTSUPPORTED);
                    // throw OperationOutcomeFactory.buildOperationOutcomeException(
                    // new UnprocessableEntityException("Incorrect parameter passed : " + paramPart.getName()),
                    // SystemCode.INVALID_PARAMETER, IssueType.INVALID);
                    }
                }
                if (!isIncludedPrescriptionIssuesExist) {
                    // # 1.2.6 now defaults to true if not provided
                    includePrescriptionIssues = true;
                }
            }
        } else {
            // invalid parameter
            addWarningIssue(param, IssueType.NOTSUPPORTED);
        }
    }
    // for parameter
    // Add Patient
    Patient patient = patientDetailsToPatientResourceConverter(patientDetails);
    if (patient.getIdentifierFirstRep().getValue().equals(NHS)) {
        structuredBundle.addEntry().setResource(patient);
    }
    // Organization from patient
    Set<String> orgIds = new HashSet<>();
    orgIds.add(patientDetails.getManagingOrganization());
    // Practitioner from patient
    Set<String> practitionerIds = new HashSet<>();
    List<Reference> practitionerReferenceList = patient.getGeneralPractitioner();
    practitionerReferenceList.forEach(practitionerReference -> {
        String[] pracRef = practitionerReference.getReference().split("/");
        if (pracRef.length > 1) {
            practitionerIds.add(pracRef[1]);
        }
    });
    if (getAllergies) {
        structuredBundle = structuredAllergyIntoleranceBuilder.buildStructuredAllergyIntolerence(NHS, practitionerIds, structuredBundle, includeResolved);
    }
    if (getMedications) {
        structuredBundle = populateMedicationBundle.addMedicationBundleEntries(structuredBundle, patientDetails, includePrescriptionIssues, medicationPeriod, practitionerIds, orgIds);
    }
    // Add all practitioners and practitioner roles
    for (String practitionerId : practitionerIds) {
        Practitioner pracResource = practitionerResourceProvider.getPractitionerById(new IdType(practitionerId));
        structuredBundle.addEntry().setResource(pracResource);
        List<PractitionerRole> practitionerRoleList = practitionerRoleResourceProvider.getPractitionerRoleByPracticionerId(new IdType(practitionerId));
        for (PractitionerRole role : practitionerRoleList) {
            String[] split = role.getOrganization().getReference().split("/");
            orgIds.add(split[1]);
            structuredBundle.addEntry().setResource(role);
        }
    }
    // Add all organizations
    for (String orgId : orgIds) {
        OrganizationDetails organizationDetails = organizationSearch.findOrganizationDetails(new Long(orgId));
        Organization organization = organizationResourceProvider.convertOrganizationDetailsToOrganization(organizationDetails);
        structuredBundle.addEntry().setResource(organization);
    }
    structuredBundle.setType(BundleType.COLLECTION);
    structuredBundle.getMeta().addProfile(SystemURL.SD_GPC_STRUCTURED_BUNDLE);
    if (operationOutcome != null) {
        structuredBundle.addEntry().setResource(operationOutcome);
    } else {
        removeDuplicateResources(structuredBundle);
    }
    return structuredBundle;
}
Also used : OrganizationDetails(uk.gov.hscic.model.organization.OrganizationDetails) ForbiddenOperationException(ca.uhn.fhir.rest.server.exceptions.ForbiddenOperationException) ResourceNotFoundException(ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException) UnprocessableEntityException(ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException) PopulateMedicationBundle(uk.gov.hscic.medications.PopulateMedicationBundle) PatientDetails(uk.gov.hscic.model.patient.PatientDetails) ParametersParameterComponent(org.hl7.fhir.dstu3.model.Parameters.ParametersParameterComponent)

Example 3 with ParametersParameterComponent

use of org.hl7.fhir.r4b.model.Parameters.ParametersParameterComponent 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;
}
Also used : Parameters(org.hl7.fhir.r4.model.Parameters) ObjectNode(com.fasterxml.jackson.databind.node.ObjectNode) Bundle(org.hl7.fhir.r4.model.Bundle) IBaseResource(org.hl7.fhir.instance.model.api.IBaseResource) Resource(org.hl7.fhir.r4.model.Resource) JsonNode(com.fasterxml.jackson.databind.JsonNode) Coding(org.hl7.fhir.r4.model.Coding) ArrayNode(com.fasterxml.jackson.databind.node.ArrayNode) ConceptMap(org.hl7.fhir.r4.model.ConceptMap) ParametersParameterComponent(org.hl7.fhir.r4.model.Parameters.ParametersParameterComponent)

Example 4 with ParametersParameterComponent

use of org.hl7.fhir.r4b.model.Parameters.ParametersParameterComponent in project cqf-ruler by DBCG.

the class CqlExecutionProvider method evaluate.

/**
 * Evaluates a CQL expression and returns the results as a Parameters resource.
 *
 * @param theRequestDetails   the {@link RequestDetails RequestDetails}
 * @param subject             ***Only Patient is supported as of now*** Subject
 *                            for which the expression will be
 *                            evaluated. This corresponds to the context in
 *                            which the expression will be evaluated and is
 *                            represented as a relative FHIR id (e.g.
 *                            Patient/123), which establishes both the context
 *                            and context value for the evaluation
 * @param expression          Expression to be evaluated. Note that this is an
 *                            expression of CQL, not the text of a library with
 *                            definition statements.
 * @param parameters          Any input parameters for the expression.
 *                            {@link Parameters} Parameters defined in this
 *                            input will be made available by name to the CQL
 *                            expression. Parameter types are mapped to CQL as
 *                            specified in the Using CQL section of the CPG
 *                            Implementation guide. If a parameter appears more
 *                            than once in the input Parameters resource, it is
 *                            represented with a List in the input CQL. If a
 *                            parameter has parts, it is represented as a Tuple
 *                            in the input CQL.
 * @param library             A library to be included. The {@link Library}
 *                            library is resolved by url and made available by
 *                            name within the expression to be evaluated.
 * @param useServerData       Whether to use data from the server performing the
 *                            evaluation. If this parameter is true (the
 *                            default), then the operation will use data first
 *                            from any bundles provided as parameters (through
 *                            the data and prefetch parameters), second data
 *                            from the server performing the operation, and
 *                            third, data from the dataEndpoint parameter (if
 *                            provided). If this parameter is false, the
 *                            operation will use data first from the bundles
 *                            provided in the data or prefetch parameters, and
 *                            second from the dataEndpoint parameter (if
 *                            provided).
 * @param data                Data to be made available to the library
 *                            evaluation. This parameter is exclusive with the
 *                            prefetchData parameter (i.e. either provide all
 *                            data as a single bundle, or provide data using
 *                            multiple bundles with prefetch descriptions).
 * @param prefetchData        ***Not Yet Implemented***
 * @param dataEndpoint        An {@link Endpoint} endpoint to use to access data
 *                            referenced by retrieve operations in the library.
 *                            If provided, this endpoint is used after the data
 *                            or prefetchData bundles, and the server, if the
 *                            useServerData parameter is true.
 * @param contentEndpoint     An {@link Endpoint} endpoint to use to access
 *                            content (i.e. libraries) referenced by the
 *                            library. If no content endpoint is supplied, the
 *                            evaluation will attempt to retrieve content from
 *                            the server on which the operation is being
 *                            performed.
 * @param terminologyEndpoint An {@link Endpoint} endpoint to use to access
 *                            terminology (i.e. valuesets, codesystems, and
 *                            membership testing) referenced by the library. If
 *                            no terminology endpoint is supplied, the
 *                            evaluation will attempt to use the server on which
 *                            the operation is being performed as the
 *                            terminology server.
 * @return The result of evaluating the given expression, returned as a FHIR
 *         type, either a {@link Resource} resource, or a FHIR-defined type
 *         corresponding to the CQL return type, as defined in the Using CQL
 *         section of the CPG Implementation guide. If the result is a List of
 *         resources, the result will be a {@link Bundle} Bundle . If the result
 *         is a CQL system-defined or FHIR-defined type, the result is returned
 *         as a {@link Parameters} Parameters resource
 */
@Operation(name = "$cql")
@Description(shortDefinition = "$cql", value = "Evaluates a CQL expression and returns the results as a Parameters resource. Defined: http://build.fhir.org/ig/HL7/cqf-recommendations/OperationDefinition-cpg-cql.html", example = "$cql?expression=5*5")
public Parameters evaluate(RequestDetails theRequestDetails, @OperationParam(name = "subject", max = 1) String subject, @OperationParam(name = "expression", min = 1, max = 1) String expression, @OperationParam(name = "parameters", max = 1) Parameters parameters, @OperationParam(name = "library") List<Parameters> library, @OperationParam(name = "useServerData", max = 1) BooleanType useServerData, @OperationParam(name = "data", max = 1) Bundle data, @OperationParam(name = "prefetchData") List<Parameters> prefetchData, @OperationParam(name = "dataEndpoint", max = 1) Endpoint dataEndpoint, @OperationParam(name = "contentEndpoint", max = 1) Endpoint contentEndpoint, @OperationParam(name = "terminologyEndpoint", max = 1) Endpoint terminologyEndpoint) {
    if (prefetchData != null) {
        throw new NotImplementedException("prefetchData is not yet supported.");
    }
    if (useServerData == null) {
        useServerData = new BooleanType(true);
    }
    List<LibraryParameter> libraryParameters = new ArrayList<>();
    if (library != null) {
        for (Parameters libraryParameter : library) {
            String url = null;
            String name = null;
            for (ParametersParameterComponent param : libraryParameter.getParameter()) {
                switch(param.getName()) {
                    case "url":
                        url = ((StringType) param.getValue()).asStringValue();
                        break;
                    case "name":
                        name = ((StringType) param.getValue()).asStringValue();
                        break;
                    default:
                        throw new IllegalArgumentException("Only url and name parts are allowed for Parameter: library");
                }
            }
            if (url == null) {
                throw new IllegalArgumentException("If library parameter must provide a url parameter part.");
            }
            libraryParameters.add(new LibraryParameter().withUrl(url).withName(name));
        }
    // Remove LocalLibrary from cache first...
    }
    VersionedIdentifier localLibraryIdentifier = new VersionedIdentifier().withId("LocalLibrary").withVersion("1.0.0");
    globalLibraryCache.remove(localLibraryIdentifier);
    CqlEngine engine = setupEngine(localLibraryIdentifier, expression, libraryParameters, subject, parameters, contentEndpoint, dataEndpoint, terminologyEndpoint, data, useServerData.booleanValue(), theRequestDetails);
    Map<String, Object> resolvedParameters = new HashMap<String, Object>();
    if (parameters != null) {
        for (Parameters.ParametersParameterComponent pc : parameters.getParameter()) {
            resolvedParameters.put(pc.getName(), pc.getValue());
        }
    }
    String contextType = subject != null ? subject.substring(0, subject.lastIndexOf("/") - 1) : null;
    String subjectId = subject != null ? subject.substring(0, subject.lastIndexOf("/") - 1) : null;
    EvaluationResult evalResult = engine.evaluate(localLibraryIdentifier, null, Pair.of(contextType != null ? contextType : "Unspecified", subjectId == null ? "null" : subject), resolvedParameters, this.getDebugMap());
    if (evalResult != null && evalResult.expressionResults != null) {
        if (evalResult.expressionResults.size() > 1) {
            logger.debug("Evaluation resulted in more than one expression result.  ");
        }
        Parameters result = new Parameters();
        resolveResult(theRequestDetails, evalResult, result);
        return result;
    }
    return null;
}
Also used : Parameters(org.hl7.fhir.dstu3.model.Parameters) HashMap(java.util.HashMap) NotImplementedException(org.apache.commons.lang3.NotImplementedException) BooleanType(org.hl7.fhir.dstu3.model.BooleanType) ArrayList(java.util.ArrayList) CqlEngine(org.opencds.cqf.cql.engine.execution.CqlEngine) EvaluationResult(org.opencds.cqf.cql.engine.execution.EvaluationResult) VersionedIdentifier(org.cqframework.cql.elm.execution.VersionedIdentifier) ParametersParameterComponent(org.hl7.fhir.dstu3.model.Parameters.ParametersParameterComponent) ParametersParameterComponent(org.hl7.fhir.dstu3.model.Parameters.ParametersParameterComponent) Description(ca.uhn.fhir.model.api.annotation.Description) Operation(ca.uhn.fhir.rest.annotation.Operation)

Example 5 with ParametersParameterComponent

use of org.hl7.fhir.r4b.model.Parameters.ParametersParameterComponent in project cqf-ruler by DBCG.

the class CqlExecutionProvider method evaluate.

/**
 * Evaluates a CQL expression and returns the results as a Parameters resource.
 *
 * @param theRequestDetails   the {@link RequestDetails RequestDetails}
 * @param subject             Subject for which the expression will be
 *                            evaluated. This corresponds to the context in
 *                            which the expression will be evaluated and is
 *                            represented as a relative FHIR id (e.g.
 *                            Patient/123), which establishes both the context
 *                            and context value for the evaluation
 * @param expression          Expression to be evaluated. Note that this is an
 *                            expression of CQL, not the text of a library with
 *                            definition statements.
 * @param parameters          Any input parameters for the expression.
 *                            {@link Parameters} Parameters defined in this
 *                            input will be made available by name to the CQL
 *                            expression. Parameter types are mapped to CQL as
 *                            specified in the Using CQL section of the CPG
 *                            Implementation guide. If a parameter appears more
 *                            than once in the input Parameters resource, it is
 *                            represented with a List in the input CQL. If a
 *                            parameter has parts, it is represented as a Tuple
 *                            in the input CQL.
 * @param library             A library to be included. The {@link Library}
 *                            library is resolved by url and made available by
 *                            name within the expression to be evaluated.
 * @param useServerData       Whether to use data from the server performing the
 *                            evaluation. If this parameter is true (the
 *                            default), then the operation will use data first
 *                            from any bundles provided as parameters (through
 *                            the data and prefetch parameters), second data
 *                            from the server performing the operation, and
 *                            third, data from the dataEndpoint parameter (if
 *                            provided). If this parameter is false, the
 *                            operation will use data first from the bundles
 *                            provided in the data or prefetch parameters, and
 *                            second from the dataEndpoint parameter (if
 *                            provided).
 * @param data                Data to be made available to the library
 *                            evaluation. This parameter is exclusive with the
 *                            prefetchData parameter (i.e. either provide all
 *                            data as a single bundle, or provide data using
 *                            multiple bundles with prefetch descriptions).
 * @param prefetchData        ***Not Yet Implemented***
 * @param dataEndpoint        An {@link Endpoint} endpoint to use to access data
 *                            referenced by retrieve operations in the library.
 *                            If provided, this endpoint is used after the data
 *                            or prefetchData bundles, and the server, if the
 *                            useServerData parameter is true.
 * @param contentEndpoint     An {@link Endpoint} endpoint to use to access
 *                            content (i.e. libraries) referenced by the
 *                            library. If no content endpoint is supplied, the
 *                            evaluation will attempt to retrieve content from
 *                            the server on which the operation is being
 *                            performed.
 * @param terminologyEndpoint An {@link Endpoint} endpoint to use to access
 *                            terminology (i.e. valuesets, codesystems, and
 *                            membership testing) referenced by the library. If
 *                            no terminology endpoint is supplied, the
 *                            evaluation will attempt to use the server on which
 *                            the operation is being performed as the
 *                            terminology server.
 * @return The result of evaluating the given expression, returned as a FHIR
 *         type, either a {@link Resource} resource, or a FHIR-defined type
 *         corresponding to the CQL return type, as defined in the Using CQL
 *         section of the CPG Implementation guide. If the result is a List of
 *         resources, the result will be a {@link Bundle} Bundle . If the result
 *         is a CQL system-defined or FHIR-defined type, the result is returned
 *         as a {@link Parameters} Parameters resource
 */
@Operation(name = "$cql")
@Description(shortDefinition = "$cql", value = "Evaluates a CQL expression and returns the results as a Parameters resource. Defined: http://build.fhir.org/ig/HL7/cqf-recommendations/OperationDefinition-cpg-cql.html", example = "$cql?expression=5*5")
public Parameters evaluate(RequestDetails theRequestDetails, @OperationParam(name = "subject", max = 1) String subject, @OperationParam(name = "expression", min = 1, max = 1) String expression, @OperationParam(name = "parameters", max = 1) Parameters parameters, @OperationParam(name = "library") List<Parameters> library, @OperationParam(name = "useServerData", max = 1) BooleanType useServerData, @OperationParam(name = "data", max = 1) Bundle data, @OperationParam(name = "prefetchData") List<Parameters> prefetchData, @OperationParam(name = "dataEndpoint", max = 1) Endpoint dataEndpoint, @OperationParam(name = "contentEndpoint", max = 1) Endpoint contentEndpoint, @OperationParam(name = "terminologyEndpoint", max = 1) Endpoint terminologyEndpoint) {
    if (prefetchData != null) {
        throw new NotImplementedException("prefetchData is not yet supported.");
    }
    if (useServerData == null) {
        useServerData = new BooleanType(true);
    }
    List<LibraryParameter> libraryParameters = new ArrayList<>();
    if (library != null) {
        for (Parameters libraryParameter : library) {
            CanonicalType url = null;
            String name = null;
            for (ParametersParameterComponent param : libraryParameter.getParameter()) {
                switch(param.getName()) {
                    case "url":
                        url = ((CanonicalType) param.getValue());
                        break;
                    case "name":
                        name = ((StringType) param.getValue()).asStringValue();
                        break;
                    default:
                        throw new IllegalArgumentException("Only url and name parts are allowed for Parameter: library");
                }
            }
            if (url == null) {
                throw new IllegalArgumentException("If library parameter must provide a url parameter part.");
            }
            libraryParameters.add(new LibraryParameter().withUrl(url).withName(name));
        }
    // Remove LocalLibrary from cache first...
    }
    VersionedIdentifier localLibraryIdentifier = new VersionedIdentifier().withId("LocalLibrary").withVersion("1.0.0");
    globalLibraryCache.remove(localLibraryIdentifier);
    CqlEngine engine = setupEngine(localLibraryIdentifier, expression, libraryParameters, subject, parameters, contentEndpoint, dataEndpoint, terminologyEndpoint, data, useServerData.booleanValue(), theRequestDetails);
    Map<String, Object> resolvedParameters = new HashMap<>();
    if (parameters != null) {
        for (Parameters.ParametersParameterComponent pc : parameters.getParameter()) {
            resolvedParameters.put(pc.getName(), pc.getValue());
        }
    }
    String contextType = subject != null ? subject.substring(0, subject.lastIndexOf("/") - 1) : null;
    String subjectId = subject != null ? subject.substring(0, subject.lastIndexOf("/") - 1) : null;
    EvaluationResult evalResult = engine.evaluate(localLibraryIdentifier, null, Pair.of(contextType != null ? contextType : "Unspecified", subjectId == null ? "null" : subject), resolvedParameters, this.getDebugMap());
    if (evalResult != null && evalResult.expressionResults != null) {
        if (evalResult.expressionResults.size() > 1) {
            logger.debug("Evaluation resulted in more than one expression result.  ");
        }
        Parameters result = new Parameters();
        resolveResult(theRequestDetails, evalResult, result);
        return result;
    }
    return null;
}
Also used : Parameters(org.hl7.fhir.r4.model.Parameters) HashMap(java.util.HashMap) NotImplementedException(org.apache.commons.lang3.NotImplementedException) BooleanType(org.hl7.fhir.r4.model.BooleanType) ArrayList(java.util.ArrayList) CqlEngine(org.opencds.cqf.cql.engine.execution.CqlEngine) CanonicalType(org.hl7.fhir.r4.model.CanonicalType) EvaluationResult(org.opencds.cqf.cql.engine.execution.EvaluationResult) VersionedIdentifier(org.cqframework.cql.elm.execution.VersionedIdentifier) ParametersParameterComponent(org.hl7.fhir.r4.model.Parameters.ParametersParameterComponent) ParametersParameterComponent(org.hl7.fhir.r4.model.Parameters.ParametersParameterComponent) Description(ca.uhn.fhir.model.api.annotation.Description) Operation(ca.uhn.fhir.rest.annotation.Operation)

Aggregations

ParametersParameterComponent (org.hl7.fhir.r4.model.Parameters.ParametersParameterComponent)23 Parameters (org.hl7.fhir.r4.model.Parameters)18 FHIRException (org.hl7.fhir.exceptions.FHIRException)12 IOException (java.io.IOException)7 CodeType (org.hl7.fhir.r4.model.CodeType)7 URISyntaxException (java.net.URISyntaxException)6 Nonnull (javax.annotation.Nonnull)6 ParametersParameterComponent (org.hl7.fhir.dstu3.model.Parameters.ParametersParameterComponent)6 ParametersParameterComponent (org.hl7.fhir.r5.model.Parameters.ParametersParameterComponent)6 Slf4j (lombok.extern.slf4j.Slf4j)5 UrlType (org.hl7.fhir.r4.model.UrlType)5 ParametersParameterComponent (org.hl7.fhir.r4b.model.Parameters.ParametersParameterComponent)5 Test (org.junit.jupiter.api.Test)5 URI (java.net.URI)4 List (java.util.List)4 IBaseResource (org.hl7.fhir.instance.model.api.IBaseResource)4 IssueType (org.hl7.fhir.utilities.validation.ValidationMessage.IssueType)4 FhirEncoders (au.csiro.pathling.encoders.FhirEncoders)2 UnsupportedResourceError (au.csiro.pathling.encoders.UnsupportedResourceError)2 InvalidUserInputError (au.csiro.pathling.errors.InvalidUserInputError)2