use of org.hl7.fhir.r4.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;
}
use of org.hl7.fhir.r4.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);
}
use of org.hl7.fhir.r4.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;
}
use of org.hl7.fhir.r4.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;
}
use of org.hl7.fhir.r4.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());
}
Aggregations