Search in sources :

Example 51 with ResourceType

use of org.hl7.fhir.r4.model.Enumerations.ResourceType in project pathling by aehrc.

the class TestHelpers method mockResource.

public static void mockResource(@Nonnull final Database database, @Nonnull final SparkSession spark, @Nonnull final ResourceType... resourceTypes) {
    for (final ResourceType resourceType : resourceTypes) {
        final Dataset<Row> dataset = getDatasetForResourceType(spark, resourceType);
        when(database.read(resourceType)).thenReturn(dataset);
    }
}
Also used : ResourceType(org.hl7.fhir.r4.model.Enumerations.ResourceType) Row(org.apache.spark.sql.Row)

Example 52 with ResourceType

use of org.hl7.fhir.r4.model.Enumerations.ResourceType in project redmatch by aehrc.

the class FhirExporter method getValue.

/**
 * Resolves a value.
 *
 * @param value The value specified in the transformation rules.
 * @param fhirType The type of the FHIR attribute where this value will be set.
 * @param vertex A vertex with patient data.
 * @param recordId The id of this record. Used to create the references to FHIR ids.
 * @param enumFactory If the type is an enumeration, this is the factory to create an instance.
 * @param fhirPackage The target FHIR package.
 * @return The value or null if the value cannot be determined. This can also be a list.
 */
private Base getValue(Value value, Class<?> fhirType, JsonObject vertex, String recordId, Class<?> enumFactory, VersionedFhirPackage fhirPackage) throws IOException {
    // If this is a field-based value then make sure that there is a value and if not return null
    if (value instanceof FieldBasedValue) {
        FieldBasedValue fbv = (FieldBasedValue) value;
        // Account for field ids of the form xx___y
        String fieldId = fbv.getFieldId();
        String shortFieldId = null;
        String regex = "(?<fieldId>.*)___\\d+$";
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(fieldId);
        if (matcher.find()) {
            shortFieldId = matcher.group("fieldId");
            log.debug("Transformed fieldId into '" + fieldId + "'");
        }
        boolean hasValue = false;
        JsonElement jsonElement = vertex.get(fieldId);
        if (jsonElement != null) {
            String rawValue = jsonElement.getAsString();
            if (!rawValue.isEmpty()) {
                hasValue = true;
            }
        }
        if (!hasValue && shortFieldId != null) {
            jsonElement = vertex.get(shortFieldId);
            if (jsonElement != null) {
                String rawValue = jsonElement.getAsString();
                if (!rawValue.isEmpty()) {
                    hasValue = true;
                }
            }
        }
        if (!hasValue) {
            return null;
        }
    }
    if (value instanceof BooleanValue) {
        return new BooleanType(((BooleanValue) value).getValue());
    } else if (value instanceof CodeLiteralValue) {
        String code = ((CodeLiteralValue) value).getCode();
        return getCode(code, enumFactory);
    } else if (value instanceof ConceptLiteralValue) {
        ConceptLiteralValue clv = (ConceptLiteralValue) value;
        String system = clv.getSystem();
        String code = clv.getCode();
        String display = clv.getDisplay() != null ? clv.getDisplay() : "";
        return getConcept(system, code, display, fhirType);
    } else if (value instanceof DoubleValue) {
        return new DecimalType(((DoubleValue) value).getValue());
    } else if (value instanceof IntegerValue) {
        return new IntegerType(((IntegerValue) value).getValue());
    } else if (value instanceof ReferenceValue) {
        ReferenceValue rv = (ReferenceValue) value;
        Reference ref = new Reference();
        String resourceType = rv.getResourceType();
        String resourceId = rv.getResourceId();
        boolean unique = uniqueIds.contains(resourceType + "<" + resourceId + ">");
        CodeInfo codeInfo = terminologyService.lookup(fhirPackage, resourceType);
        if (codeInfo.isProfile()) {
            resourceType = StringUtils.getLastPath(codeInfo.getBaseResource());
        }
        if (unique) {
            // This is a reference to a unique resource - no need to append row id
            if (fhirResourceMap.containsKey(resourceId)) {
                ref.setReference("/" + resourceType + "/" + resourceId);
            } else {
                log.debug("Did not find resource " + resourceType + "/" + resourceId);
            }
        } else {
            if (fhirResourceMap.containsKey(resourceId + "-" + recordId)) {
                ref.setReference("/" + resourceType + "/" + resourceId + "-" + recordId);
            } else {
                log.debug("Did not find resource " + resourceType + "/" + resourceId + "-" + recordId);
            }
        }
        return ref;
    } else if (value instanceof StringValue) {
        if (fhirType.equals(StringType.class)) {
            return new StringType(((StringValue) value).getStringValue());
        } else if (fhirType.equals(MarkdownType.class)) {
            return new MarkdownType(((StringValue) value).getStringValue());
        } else if (fhirType.equals(IdType.class)) {
            return new IdType(((StringValue) value).getStringValue());
        } else if (fhirType.equals(UriType.class)) {
            return new UriType(((StringValue) value).getStringValue());
        } else if (fhirType.equals(OidType.class)) {
            return new OidType(((StringValue) value).getStringValue());
        } else if (fhirType.equals(UuidType.class)) {
            return new UuidType(((StringValue) value).getStringValue());
        } else if (fhirType.equals(CanonicalType.class)) {
            return new CanonicalType(((StringValue) value).getStringValue());
        } else if (fhirType.equals(UrlType.class)) {
            return new UrlType(((StringValue) value).getStringValue());
        } else {
            throw new TransformationException("Got StringValue for FHIR type " + fhirType.getName() + ". This should not happen!");
        }
    } else if (value instanceof CodeSelectedValue) {
        CodeSelectedValue csv = (CodeSelectedValue) value;
        String fieldId = csv.getFieldId();
        Mapping m = getSelectedMapping(fieldId, vertex);
        if (m == null) {
            throw new TransformationException("Mapping for field " + fieldId + " is required but was not found.");
        }
        return getTarget(m).getCodeElement();
    } else if (value instanceof ConceptSelectedValue) {
        ConceptSelectedValue csv = (ConceptSelectedValue) value;
        String fieldId = csv.getFieldId();
        Mapping m = getSelectedMapping(fieldId, vertex);
        if (m == null) {
            throw new TransformationException("Mapping for field " + fieldId + " is required but was not found.");
        }
        if (fhirType.isAssignableFrom(Coding.class)) {
            return getTarget(m);
        } else if (fhirType.isAssignableFrom(CodeableConcept.class)) {
            return new CodeableConcept().addCoding(getTarget(m));
        } else {
            throw new TransformationException("FHIR type of field " + fieldId + " (" + fhirType + ") is incompatible with CONCEPT_SELECTED.");
        }
    } else if (value instanceof ConceptValue) {
        // Ontoserver REDCap plugin format: 74400008|Appendicitis|http://snomed.info/sct
        ConceptValue cv = (ConceptValue) value;
        String fieldId = cv.getFieldId();
        Mapping m = getMapping(fieldId);
        if (m != null) {
            if (fhirType.isAssignableFrom(Coding.class)) {
                return getTarget(m);
            } else if (fhirType.isAssignableFrom(CodeableConcept.class)) {
                return new CodeableConcept().addCoding(getTarget(m));
            } else {
                throw new TransformationException("FHIR type of field " + fieldId + " (" + fhirType + ") is incompatible with CONCEPT.");
            }
        } else {
            au.csiro.redmatch.model.Field field = doc.getSchema().getField(fieldId);
            Coding c = field.getCoding(vertex);
            if (c != null) {
                if (fhirType.isAssignableFrom(Coding.class)) {
                    return c;
                } else if (fhirType.isAssignableFrom(CodeableConcept.class)) {
                    return new CodeableConcept().addCoding(c);
                } else {
                    throw new TransformationException("FHIR type of field " + fieldId + " (" + fhirType + ") is incompatible with CONCEPT.");
                }
            }
        }
        throw new TransformationException("Could not get concept for field " + fieldId + ".");
    } else if (value instanceof FieldValue) {
        FieldValue fv = (FieldValue) value;
        String fieldId = fv.getFieldId();
        FieldValue.DatePrecision pr = fv.getDatePrecision();
        au.csiro.redmatch.model.Field field = doc.getSchema().getField(fieldId);
        return field.getValue(vertex, fhirType, pr);
    } else {
        throw new TransformationException("Unable to get VALUE for " + value);
    }
}
Also used : CodeInfo(au.csiro.redmatch.terminology.CodeInfo) Matcher(java.util.regex.Matcher) Field(java.lang.reflect.Field) org.hl7.fhir.r4.model(org.hl7.fhir.r4.model) Pattern(java.util.regex.Pattern) JsonElement(com.google.gson.JsonElement)

Example 53 with ResourceType

use of org.hl7.fhir.r4.model.Enumerations.ResourceType in project redmatch by aehrc.

the class RedmatchApi method exportAll.

/**
 * Runs an operation on all the Redmatch rule documents found in the base folder.
 *
 * @param baseFolder The folder that contains the Redmatch rule documents , one or more schemas referenced by the
 *                   rules and a redmatch-config.yaml file with source server details.
 * @param progressReporter An object used to report progress. Can be null.
 * @param cancelToken Used to check if the user has cancelled the operation.
 * @return Map of diagnostic messages. Key is file where error happened.
 */
public List<Diagnostic> exportAll(@NotNull File baseFolder, ProgressReporter progressReporter, CancelChecker cancelToken) {
    if (!baseFolder.canRead() || !baseFolder.canWrite()) {
        return List.of(new Diagnostic(zeroZero, "Unable to read or write on the base folder.", DiagnosticSeverity.Error, "API"));
    }
    // Get .rdm files
    List<File> rdmFiles;
    try (Stream<Path> walk = Files.walk(baseFolder.toPath())) {
        rdmFiles = walk.filter(p -> !Files.isDirectory(p)).map(Path::toFile).filter(f -> f.getName().endsWith(".rdm")).collect(Collectors.toList());
    } catch (IOException e) {
        return List.of(new Diagnostic(zeroZero, "Unexpected I/O error: " + e.getLocalizedMessage(), DiagnosticSeverity.Error, "API"));
    }
    try {
        List<Diagnostic> diagnostics = new ArrayList<>();
        Map<String, DomainResource> resourcesMap = new HashMap<>();
        for (File rdmFile : rdmFiles) {
            Pair<Map<String, DomainResource>, List<Diagnostic>> data = transform(rdmFile, progressReporter, cancelToken);
            resourcesMap.putAll(data.getValue0());
            diagnostics.addAll(data.getValue1());
        }
        // Group resources by type
        final Map<String, List<DomainResource>> grouped = new HashMap<>();
        for (String key : resourcesMap.keySet()) {
            DomainResource dr = resourcesMap.get(key);
            String resourceType = dr.getResourceType().toString();
            List<DomainResource> list = grouped.computeIfAbsent(resourceType, k -> new ArrayList<>());
            list.add(dr);
        }
        Path outputFolder = createOutputFolder(baseFolder).toPath();
        save(grouped, outputFolder, progressReporter, cancelToken);
        return diagnostics;
    } catch (Exception e) {
        log.error(e);
        return List.of(new Diagnostic(zeroZero, "Could not complete transformation:" + e.getLocalizedMessage(), DiagnosticSeverity.Error, "API"));
    }
}
Also used : Path(java.nio.file.Path) DomainResource(org.hl7.fhir.r4.model.DomainResource) Diagnostic(org.eclipse.lsp4j.Diagnostic)

Example 54 with ResourceType

use of org.hl7.fhir.r4.model.Enumerations.ResourceType in project CRD by HL7-DaVinci.

the class QueryBatchRequest method performQueryBatchRequest.

/**
 * Backfills the missing required values of the response that prefetch may have missed.
 * This implementation pulls the IDs of the required references from the request object's draft
 * orders, checks which of those values are missing from the current CRD response, builds the
 * Query Batch JSON request using
 * http://build.fhir.org/ig/HL7/davinci-crd/hooks.html#fhir-resource-access,
 * then populates the CRD response with the response from the Query Batch.
 */
public void performQueryBatchRequest(CdsRequest<?, ?> cdsRequest, CrdPrefetch crdPrefetch) {
    logger.info("***** ***** Performing Query Batch Request.");
    CrdPrefetch crdResponse = crdPrefetch;
    // The list of references that should be queried in the batch request.
    List<String> requiredReferences = new ArrayList<String>();
    // Get the IDs of references in the request's draft orders.
    Bundle draftOrdersBundle = cdsRequest.getContext().getDraftOrders();
    // This assumes that only the first draft order is relevant.
    Resource initialRequestResource = draftOrdersBundle.getEntry().get(0).getResource();
    ResourceType requestType = initialRequestResource.getResourceType();
    // Extract the references by iterating through the JSON.
    Gson gson = new Gson();
    final JsonObject jsonObject = gson.toJsonTree(initialRequestResource).getAsJsonObject();
    for (Map.Entry<String, JsonElement> entry : jsonObject.entrySet()) {
        FhirRequestProcessor.extractReferenceIds(requiredReferences, entry.getValue());
    }
    // Filter out references that already exist in the CRD Response.
    requiredReferences = requiredReferences.stream().filter(referenceId -> !crdResponse.containsRequestResourceId(referenceId)).collect(Collectors.toList());
    logger.info("References to query: " + requiredReferences);
    if (requiredReferences.isEmpty()) {
        logger.info("A Query Batch Request is not needed: all references have already already fetched.");
        return;
    }
    // Build the Query Batch Request JSON.
    Bundle queryBatchRequestBundle = buildQueryBatchRequestBundle(requiredReferences);
    String queryBatchRequestBody = FhirContext.forR4().newJsonParser().encodeResourceToString(queryBatchRequestBundle);
    // Make the query batch request to the EHR server.
    Bundle queryResponseBundle = null;
    try {
        logger.info("Executing Query Batch Request: " + queryBatchRequestBody);
        queryResponseBundle = (Bundle) FhirRequestProcessor.executeFhirQueryBody(queryBatchRequestBody, cdsRequest, this.fhirComponents, HttpMethod.POST);
        queryResponseBundle = extractNestedBundledResources(queryResponseBundle);
        logger.info("Extracted Query Batch Resources: " + (queryResponseBundle).getEntry().stream().map(entry -> entry.getResource()).collect(Collectors.toList()));
    } catch (Exception e) {
        logger.error("Failed to backfill prefetch with Query Batch Request " + queryBatchRequestBody, e);
    }
    if (queryResponseBundle == null) {
        logger.error("No response recieved from the Query Batch Request.");
        return;
    }
    // Add the request resource to the query batch response as it may be missing.
    // Coverage and Subject are not automatically being
    // linked to the request object. It seems to somehow automatically link during
    // standard prefetch, but not here so we're doing it manually.
    List<Coverage> coverages = FhirRequestProcessor.extractCoverageFromBundle(queryResponseBundle);
    List<Patient> patients = FhirRequestProcessor.extractPatientsFromBundle(queryResponseBundle);
    FhirRequestProcessor.addInsuranceAndSubject(initialRequestResource, patients, coverages);
    BundleEntryComponent newEntry = new BundleEntryComponent();
    newEntry.setResource(initialRequestResource);
    queryResponseBundle.addEntry(newEntry);
    // Add the query batch response resources to the CRD Prefetch request.
    logger.info("Query Batch Response Entries: " + queryResponseBundle.getEntry());
    FhirRequestProcessor.addToCrdPrefetchRequest(crdResponse, requestType, queryResponseBundle.getEntry());
    logger.info("Post-Query Batch CRDResponse: " + crdResponse);
}
Also used : CrdPrefetch(org.hl7.davinci.r4.crdhook.CrdPrefetch) JsonObject(com.google.gson.JsonObject) Logger(org.slf4j.Logger) FhirRequestProcessor(org.hl7.davinci.endpoint.cdshooks.services.crd.r4.FhirRequestProcessor) LoggerFactory(org.slf4j.LoggerFactory) HttpMethod(org.springframework.http.HttpMethod) Resource(org.hl7.fhir.r4.model.Resource) Collectors(java.util.stream.Collectors) ArrayList(java.util.ArrayList) HTTPVerb(org.hl7.fhir.r4.model.Bundle.HTTPVerb) JsonElement(com.google.gson.JsonElement) FhirComponentsT(org.hl7.davinci.FhirComponentsT) BundleEntryRequestComponent(org.hl7.fhir.r4.model.Bundle.BundleEntryRequestComponent) ResourceType(org.hl7.fhir.r4.model.ResourceType) FhirContext(ca.uhn.fhir.context.FhirContext) List(java.util.List) Gson(com.google.gson.Gson) Map(java.util.Map) BundleEntryComponent(org.hl7.fhir.r4.model.Bundle.BundleEntryComponent) Bundle(org.hl7.fhir.r4.model.Bundle) CdsRequest(org.cdshooks.CdsRequest) BundleType(org.hl7.fhir.r4.model.Bundle.BundleType) Coverage(org.hl7.fhir.r4.model.Coverage) Patient(org.hl7.fhir.r4.model.Patient) Bundle(org.hl7.fhir.r4.model.Bundle) ArrayList(java.util.ArrayList) Resource(org.hl7.fhir.r4.model.Resource) Gson(com.google.gson.Gson) JsonObject(com.google.gson.JsonObject) Patient(org.hl7.fhir.r4.model.Patient) ResourceType(org.hl7.fhir.r4.model.ResourceType) Coverage(org.hl7.fhir.r4.model.Coverage) BundleEntryComponent(org.hl7.fhir.r4.model.Bundle.BundleEntryComponent) JsonElement(com.google.gson.JsonElement) CrdPrefetch(org.hl7.davinci.r4.crdhook.CrdPrefetch) Map(java.util.Map)

Example 55 with ResourceType

use of org.hl7.fhir.r4.model.Enumerations.ResourceType in project CRD by HL7-DaVinci.

the class Utilities method bundleAsHashmap.

/**
 * Change a fhir bundle into a hashmap keyed by resources type, where the value is a list of
 * resources of that type.
 * @return a hashmap of a ResourceType as key, and a List of Resources of that type
 */
public static HashMap<String, List<Resource>> bundleAsHashmap(Bundle bundle) {
    HashMap<String, List<Resource>> bundleMap = new HashMap<>();
    for (BundleEntryComponent bec : bundle.getEntry()) {
        if (!bec.hasResource()) {
            continue;
        }
        Resource resource = bec.getResource();
        String resourceType = resource.getResourceType().toString();
        if (!bundleMap.containsKey(resourceType)) {
            bundleMap.put(resourceType, new ArrayList<>());
        }
        List<Resource> resourceList = (List<Resource>) bundleMap.get(resourceType);
        resourceList.add(resource);
    }
    return bundleMap;
}
Also used : BundleEntryComponent(org.hl7.fhir.r4.model.Bundle.BundleEntryComponent) IBaseResource(org.hl7.fhir.instance.model.api.IBaseResource)

Aggregations

JsonElement (com.google.gson.JsonElement)33 HashSet (java.util.HashSet)26 Bundle (org.hl7.fhir.r4.model.Bundle)24 ResourceType (org.hl7.fhir.r4.model.Enumerations.ResourceType)21 Test (org.junit.Test)20 Nonnull (javax.annotation.Nonnull)18 ArrayList (java.util.ArrayList)15 IBaseResource (org.hl7.fhir.instance.model.api.IBaseResource)10 FhirContext (ca.uhn.fhir.context.FhirContext)9 File (java.io.File)9 Row (org.apache.spark.sql.Row)9 IdType (org.hl7.fhir.dstu3.model.IdType)9 BundleEntryComponent (org.hl7.fhir.r4.model.Bundle.BundleEntryComponent)9 JsonObject (com.google.gson.JsonObject)8 Test (org.junit.jupiter.api.Test)8 MockHttpServletResponse (org.springframework.mock.web.MockHttpServletResponse)8 IOException (java.io.IOException)7 List (java.util.List)7 Bundle (org.hl7.fhir.dstu3.model.Bundle)7 Resource (org.hl7.fhir.r4.model.Resource)7