Search in sources :

Example 76 with ConceptSetComponent

use of org.hl7.fhir.r4b.model.ValueSet.ConceptSetComponent in project snowstorm by IHTSDO.

the class FHIRHelper method convertToECL.

public String convertToECL(ConceptSetComponent setDefn) throws FHIROperationException {
    String ecl = "";
    boolean firstItem = true;
    for (ConceptReferenceComponent concept : setDefn.getConcept()) {
        if (firstItem) {
            firstItem = false;
        } else {
            ecl += " OR ";
        }
        ecl += concept.getCode() + "|" + concept.getDisplay() + "|";
    }
    ecl += convertFilterToECL(setDefn, firstItem);
    return ecl;
}
Also used : ConceptReferenceComponent(org.hl7.fhir.r4.model.ValueSet.ConceptReferenceComponent)

Example 77 with ConceptSetComponent

use of org.hl7.fhir.r4b.model.ValueSet.ConceptSetComponent in project snowstorm by IHTSDO.

the class FHIRValueSetProvider method obtainConsistentCodeSystemVersionFromCompose.

private BranchPath obtainConsistentCodeSystemVersionFromCompose(ValueSetComposeComponent compose, BranchPath branchPath) throws FHIROperationException {
    String system = null;
    String version = null;
    // Check all include and exclude elements to ensure they have a consistent snomed URI
    List<ConceptSetComponent> allIncludeExcludes = new ArrayList<>(compose.getInclude());
    allIncludeExcludes.addAll(compose.getExclude());
    for (ConceptSetComponent thisIncludeExclude : allIncludeExcludes) {
        if (thisIncludeExclude.getSystem() != null && !thisIncludeExclude.getSystem().contains(SNOMED_URI)) {
            throw new FHIROperationException(IssueType.NOTSUPPORTED, "Server currently limited to compose elements using SNOMED CT code system");
        }
        if (thisIncludeExclude.getSystem() != null && system == null) {
            system = thisIncludeExclude.getSystem();
        }
        if (thisIncludeExclude.getVersion() != null && version == null) {
            version = thisIncludeExclude.getVersion();
        }
        if (system != null && thisIncludeExclude.getSystem() != null && !system.equals(thisIncludeExclude.getSystem())) {
            String msg = "Server currently requires consistency in ValueSet compose element code systems.";
            msg += " Encoundered both '" + system + "' and '" + thisIncludeExclude.getSystem() + "'.";
            throw new FHIROperationException(IssueType.NOTSUPPORTED, msg);
        }
        if (version != null && thisIncludeExclude.getVersion() != null && !version.equals(thisIncludeExclude.getVersion())) {
            throw new FHIROperationException(IssueType.NOTSUPPORTED, "Server currently requires consistency in ValueSet compose element code system versions");
        }
    }
    StringType codeSystemVersionUri;
    if (version == null) {
        if (system == null) {
            return branchPath;
        } else {
            codeSystemVersionUri = new StringType(system);
        }
    } else {
        codeSystemVersionUri = new StringType(version);
    }
    return fhirHelper.getBranchPathFromURI(codeSystemVersionUri);
}
Also used : ConceptSetComponent(org.hl7.fhir.r4.model.ValueSet.ConceptSetComponent)

Example 78 with ConceptSetComponent

use of org.hl7.fhir.r4b.model.ValueSet.ConceptSetComponent in project snowstorm by IHTSDO.

the class FHIRValueSetProvider method covertComposeToEcl.

public String covertComposeToEcl(ValueSetComposeComponent compose) throws FHIROperationException {
    // Successive include elements will be added using 'OR'
    // While the excludes will be added using 'MINUS'
    String ecl = "";
    boolean isFirstInclude = true;
    for (ConceptSetComponent include : compose.getInclude()) {
        if (isFirstInclude) {
            isFirstInclude = false;
        } else {
            ecl += " OR ";
        }
        ecl += "( " + fhirHelper.convertToECL(include) + " )";
    }
    // We need something to minus!
    if (isFirstInclude) {
        throw new FHIROperationException(IssueType.VALUE, "Invalid use of exclude without include in ValueSet compose element.");
    }
    for (ConceptSetComponent exclude : compose.getExclude()) {
        ecl += " MINUS ( " + fhirHelper.convertToECL(exclude) + " )";
    }
    return ecl;
}
Also used : ConceptSetComponent(org.hl7.fhir.r4.model.ValueSet.ConceptSetComponent)

Example 79 with ConceptSetComponent

use of org.hl7.fhir.r4b.model.ValueSet.ConceptSetComponent in project snowstorm by IHTSDO.

the class FHIRValueSetProvider method doExplicitExpansion.

/**
 * An explicit ValueSet has been saved on the server with a name and id, and
 * is defined by use of the "compose" element within the valueset resource.
 * @param branchPathForced
 */
private Page<ConceptMini> doExplicitExpansion(ValueSet vs, Boolean active, String filter, BranchPath branchPath, List<LanguageDialect> designations, PageRequest pageRequest, boolean branchPathForced) throws FHIROperationException {
    Page<ConceptMini> conceptMiniPage = new PageImpl<>(new ArrayList<>());
    if (vs != null && vs.getCompose() != null && !vs.getCompose().isEmpty()) {
        if (!branchPathForced) {
            branchPath.set(obtainConsistentCodeSystemVersionFromCompose(vs.getCompose(), branchPath));
        }
        ValueSetComposeComponent compose = vs.getCompose();
        Set<String> conceptIds = new HashSet<>();
        StringBuilder filterECL = new StringBuilder();
        boolean firstItem = true;
        for (ConceptSetComponent include : compose.getInclude()) {
            conceptIds.addAll(include.getConcept().stream().map(ValueSet.ConceptReferenceComponent::getCode).collect(Collectors.toSet()));
            filterECL.append(fhirHelper.convertFilterToECL(include, firstItem));
            if (firstItem) {
                firstItem = false;
            }
        }
        firstItem = true;
        for (ConceptSetComponent exclude : compose.getExclude()) {
            conceptIds.addAll(exclude.getConcept().stream().map(ValueSet.ConceptReferenceComponent::getCode).collect(Collectors.toSet()));
            filterECL.append(fhirHelper.convertFilterToECL(exclude, firstItem));
            if (firstItem) {
                firstItem = false;
            }
        }
        String branch = branchPath.toString();
        Collection<ConceptMini> fromService = conceptService.findConceptMinis(branch, conceptIds, designations).getResultsMap().values();
        logger.info("Recovered {} Concepts from branch {} with Compose.", fromService.size(), branch);
        String ecl = filterECL.toString();
        Page<ConceptMini> page = fhirHelper.eclSearch(ecl, active, filter, designations, branchPath, pageRequest);
        Collection<ConceptMini> fromECL = page.getContent();
        logger.info("Recovered {} Concepts from branch {} with ECL {}.", page.getTotalElements(), branch, filterECL);
        List<ConceptMini> conceptMinis = new ArrayList<>();
        conceptMinis.addAll(fromService);
        conceptMinis.addAll(fromECL);
        long totalCount = fromService.size() + page.getTotalElements();
        conceptMiniPage = new PageImpl<ConceptMini>(conceptMinis, page.getPageable(), totalCount);
        logger.info("Collectively recovered {} Concepts from branch {}.", conceptMiniPage.getTotalElements(), branch);
    } else {
        String msg = "Compose element(s) or 'url' parameter is expected to be present for an expansion, containing eg http://snomed.info/sct?fhir_vs=ecl/ or http://snomed.info/sct/45991000052106?fhir_vs=ecl/ ";
        // We don't need ECL if we're expanding a named valueset
        if (vs != null) {
            logger.warn(msg + " when expanding " + vs.getId());
        } else {
            throw new FHIROperationException(IssueType.VALUE, msg);
        }
    }
    return conceptMiniPage;
}
Also used : PageImpl(org.springframework.data.domain.PageImpl) ValueSetComposeComponent(org.hl7.fhir.r4.model.ValueSet.ValueSetComposeComponent) ConceptSetComponent(org.hl7.fhir.r4.model.ValueSet.ConceptSetComponent) ConceptMini(org.snomed.snowstorm.core.data.domain.ConceptMini)

Example 80 with ConceptSetComponent

use of org.hl7.fhir.r4b.model.ValueSet.ConceptSetComponent in project quality-measure-and-cohort-service by Alvearie.

the class R4FileSystemFhirTerminologyProvider method loadFromFile.

/**
 * Loads ValueSet definitions from the filesystem or S3 compatible location
 * ValueSet definitions are expected to be stored in FHIR xml or JSON format
 * named using the valueSet id (ie 2.16.840.1.113762.1.4.1114.7.json)
 *
 * @param valueSetInfo contains information for teh VlaueSet we want to load
 */
protected void loadFromFile(ValueSetInfo valueSetInfo) throws RuntimeException {
    LOG.debug("Entry: loadFromFile() ValueSet.getId=[{}] version=[{}]", valueSetInfo.getId(), valueSetInfo.getVersion());
    VersionedIdentifier valueSetIdentifier = createVersionedIdentifierForValueSet(valueSetInfo);
    String valueSetId = valueSetIdentifier.getId();
    // get the valueSet codes from the cache if it is there
    Map<String, Set<String>> codesToCodeSystems = valueSetToCodesCache.get(valueSetIdentifier);
    List<Code> codeList = valueSetCodeCache.get(valueSetIdentifier);
    if (codesToCodeSystems == null || codeList == null) {
        LOG.debug("loadFromFile() valueSetId={} not found in cache, attempting to load from file", valueSetId);
        FileStatus[] valueSetFiles;
        FileSystem fileSystem;
        // List the files in the terminology directory that end in xml or json
        try {
            fileSystem = terminologyDirectory.getFileSystem(configuration);
            valueSetFiles = fileSystem.listStatus(terminologyDirectory, new PathFilter() {

                @Override
                public boolean accept(Path path) {
                    return path.getName().equalsIgnoreCase(valueSetId + ".json") || path.getName().equalsIgnoreCase(valueSetId + ".xml");
                }
            });
        } catch (ConfigurationException | DataFormatException | IOException e) {
            LOG.error("Error attempting to get ValueSet file for ValueSet [" + valueSetId + " from " + terminologyDirectory.toString(), e);
            throw new RuntimeException("Error attempting to get ValueSet file for ValueSet [" + valueSetId + " from " + terminologyDirectory.toString(), e);
        }
        if (valueSetFiles.length == 0) {
            LOG.error("No valueSet file " + valueSetId + ".json or " + valueSetId + ".xml found in terminology directory " + terminologyDirectory.toString());
            throw new RuntimeException("No valueSet file " + valueSetId + ".json or " + valueSetId + ".xml found in terminology directory " + terminologyDirectory.toString());
        } else {
            if (valueSetFiles.length > 1) {
                LOG.warn("Multiple ValueSet files found for ValueSet {} in terminology directory {}. File {} will be used.", valueSetId, terminologyDirectory.toString(), valueSetFiles[0].toString());
            }
            ValueSet valueSetFhirR4 = null;
            try {
                // Use the fhir parsers to convert file contents back into ValueSet fhir object
                if (valueSetFiles[0].getPath().getName().toLowerCase().endsWith(".xml")) {
                    valueSetFhirR4 = (ValueSet) fhirContext.newXmlParser().parseResource(new InputStreamReader(fileSystem.open(valueSetFiles[0].getPath())));
                    LOG.info("Unmarshalled xml {}", valueSetFhirR4.getId());
                } else if (valueSetFiles[0].getPath().getName().toLowerCase().endsWith(".json")) {
                    valueSetFhirR4 = (ValueSet) fhirContext.newJsonParser().parseResource(new InputStreamReader(fileSystem.open(valueSetFiles[0].getPath())));
                    LOG.info("Unmarshalled json {}", valueSetFhirR4.getId());
                }
                // This improves performance for the in() method for code lookup in large valuesets
                codesToCodeSystems = new HashMap<String, Set<String>>();
                // cache the list of code objects for the expand method
                codeList = new ArrayList<Code>();
                for (ConceptSetComponent csc : valueSetFhirR4.getCompose().getInclude()) {
                    for (ConceptReferenceComponent cfc : csc.getConcept()) {
                        codeList.add(new Code().withCode(cfc.getCode()).withDisplay(cfc.getDisplay()).withSystem(csc.getSystem()).withVersion(csc.getVersion()));
                        Set<String> codeSystems = codesToCodeSystems.get(cfc.getCode());
                        if (codeSystems == null) {
                            codeSystems = new HashSet<String>();
                            codesToCodeSystems.put(cfc.getCode(), codeSystems);
                        }
                        codeSystems.add(csc.getSystem());
                    }
                }
                valueSetToCodesCache.put(valueSetIdentifier, codesToCodeSystems);
                valueSetCodeCache.put(valueSetIdentifier, codeList);
            } catch (ConfigurationException | DataFormatException | IOException e) {
                LOG.error("Error attempting to deserialize ValueSet " + valueSetFiles[0].getPath().toString(), e);
                throw new RuntimeException("Error attempting to deserialize ValueSet " + valueSetFiles[0].getPath().toString(), e);
            }
        }
    }
    LOG.debug("Exit: loadFromFile() ValueSet.getId=[{}] version=[{}]", valueSetInfo.getId(), valueSetInfo.getVersion());
}
Also used : Path(org.apache.hadoop.fs.Path) PathFilter(org.apache.hadoop.fs.PathFilter) ValueSet(org.hl7.fhir.r4.model.ValueSet) HashSet(java.util.HashSet) Set(java.util.Set) FileStatus(org.apache.hadoop.fs.FileStatus) InputStreamReader(java.io.InputStreamReader) IOException(java.io.IOException) Code(org.opencds.cqf.cql.engine.runtime.Code) ConceptReferenceComponent(org.hl7.fhir.r4.model.ValueSet.ConceptReferenceComponent) ConceptSetComponent(org.hl7.fhir.r4.model.ValueSet.ConceptSetComponent) VersionedIdentifier(org.cqframework.cql.elm.execution.VersionedIdentifier) DataFormatException(ca.uhn.fhir.parser.DataFormatException) ConfigurationException(ca.uhn.fhir.context.ConfigurationException) FileSystem(org.apache.hadoop.fs.FileSystem) ValueSet(org.hl7.fhir.r4.model.ValueSet)

Aggregations

ConceptSetComponent (org.hl7.fhir.r5.model.ValueSet.ConceptSetComponent)25 ArrayList (java.util.ArrayList)22 ConceptSetComponent (org.hl7.fhir.r4.model.ValueSet.ConceptSetComponent)21 IOException (java.io.IOException)20 TerminologyServiceException (org.hl7.fhir.exceptions.TerminologyServiceException)20 XhtmlNode (org.hl7.fhir.utilities.xhtml.XhtmlNode)19 FHIRException (org.hl7.fhir.exceptions.FHIRException)17 HashMap (java.util.HashMap)15 ConceptSetComponent (org.hl7.fhir.dstu3.model.ValueSet.ConceptSetComponent)14 ConceptReferenceComponent (org.hl7.fhir.r5.model.ValueSet.ConceptReferenceComponent)14 ValueSet (org.hl7.fhir.r4.model.ValueSet)13 ValueSet (org.hl7.fhir.r5.model.ValueSet)13 DefinitionException (org.hl7.fhir.exceptions.DefinitionException)12 NoTerminologyServiceException (org.hl7.fhir.exceptions.NoTerminologyServiceException)12 ConceptSetComponent (org.hl7.fhir.r4b.model.ValueSet.ConceptSetComponent)12 FileNotFoundException (java.io.FileNotFoundException)10 NotImplementedException (org.apache.commons.lang3.NotImplementedException)10 CodeSystem (org.hl7.fhir.r5.model.CodeSystem)10 CommaSeparatedStringBuilder (org.hl7.fhir.utilities.CommaSeparatedStringBuilder)10 ValueSet (org.hl7.fhir.dstu3.model.ValueSet)9