Search in sources :

Example 1 with ConceptMini

use of org.snomed.snowstorm.core.data.domain.ConceptMini in project snowstorm by IHTSDO.

the class DescriptionController method findBrowserDescriptions.

@ApiOperation(value = "Search for concept descriptions.", notes = "The Accept-Language header is used to specify the user's preferred language, 'en' is always added as a fallback if not already included in the list. " + "Each language is used as an optional clause for matching and will include the correct character folding behaviour for that language. " + "The Accept-Language header list is also used to chose the best translated FSN and PT values in the response.")
@RequestMapping(value = "browser/{branch}/descriptions", method = RequestMethod.GET)
@JsonView(value = View.Component.class)
public Page<BrowserDescriptionSearchResult> findBrowserDescriptions(@PathVariable String branch, @RequestParam(required = false) String term, @RequestParam(required = false) Boolean active, @RequestParam(required = false) Set<String> module, @ApiParam(value = "Set of two character language codes to match. " + "The English language code 'en' will not be added automatically, in contrast to the Accept-Language header which always includes it. " + "Accept-Language header still controls result FSN and PT language selection.") @RequestParam(required = false) Set<String> language, @ApiParam(value = "Set of description type ids to use include. Defaults to any. " + "Pick descendants of '900000000000446008 | Description type (core metadata concept) |'. " + "Examples: 900000000000003001 (FSN), 900000000000013009 (Synonym), 900000000000550004 (Definition)") @RequestParam(required = false) Set<Long> type, @Deprecated @RequestParam(required = false) String semanticTag, @ApiParam(value = "Set of semantic tags.") @RequestParam(required = false) Set<String> semanticTags, @ApiParam(value = "Set of description language reference sets. The description must be preferred in at least one of these to match.") @RequestParam(required = false) Set<Long> preferredIn, @ApiParam(value = "Set of description language reference sets. The description must be acceptable in at least one of these to match.") @RequestParam(required = false) Set<Long> acceptableIn, @ApiParam(value = "Set of description language reference sets. The description must be preferred OR acceptable in at least one of these to match.") @RequestParam(required = false) Set<Long> preferredOrAcceptableIn, @RequestParam(required = false) Boolean conceptActive, @RequestParam(required = false) String conceptRefset, @RequestParam(defaultValue = "false") boolean groupByConcept, @RequestParam(defaultValue = "STANDARD") DescriptionService.SearchMode searchMode, @RequestParam(defaultValue = "0") int offset, @RequestParam(defaultValue = "50") int limit, @RequestHeader(value = "Accept-Language", defaultValue = Config.DEFAULT_ACCEPT_LANG_HEADER) String acceptLanguageHeader) throws TooCostlyException {
    branch = BranchPathUriUtil.decodePath(branch);
    PageRequest pageRequest = ControllerHelper.getPageRequest(offset, limit);
    List<LanguageDialect> languageDialects = ControllerHelper.parseAcceptLanguageHeaderWithDefaultFallback(acceptLanguageHeader);
    PageWithBucketAggregations<Description> page = descriptionService.findDescriptionsWithAggregations(branch, new DescriptionCriteria().term(term).active(active).modules(module).searchLanguageCodes(language).type(type).semanticTag(semanticTag).semanticTags(semanticTags).preferredIn(preferredIn).acceptableIn(acceptableIn).preferredOrAcceptableIn(preferredOrAcceptableIn).conceptActive(conceptActive).conceptRefset(conceptRefset).groupByConcept(groupByConcept).searchMode(searchMode), // Page
    pageRequest);
    Set<String> conceptIds = page.getContent().stream().map(Description::getConceptId).collect(Collectors.toSet());
    Map<String, ConceptMini> conceptMinis = conceptService.findConceptMinis(branch, conceptIds, languageDialects).getResultsMap();
    List<BrowserDescriptionSearchResult> results = new ArrayList<>();
    page.getContent().forEach(d -> results.add(new BrowserDescriptionSearchResult(d.getTerm(), d.isActive(), d.getLanguageCode(), d.getModuleId(), conceptMinis.get(d.getConceptId()))));
    PageWithBucketAggregations<BrowserDescriptionSearchResult> pageWithBucketAggregations = new PageWithBucketAggregations<>(results, page.getPageable(), page.getTotalElements(), page.getBuckets());
    addBucketConcepts(branch, languageDialects, pageWithBucketAggregations);
    addLanguageNames(pageWithBucketAggregations);
    return pageWithBucketAggregations;
}
Also used : Description(org.snomed.snowstorm.core.data.domain.Description) LanguageDialect(org.snomed.snowstorm.core.pojo.LanguageDialect) PageWithBucketAggregations(org.snomed.snowstorm.core.data.services.pojo.PageWithBucketAggregations) BrowserDescriptionSearchResult(org.snomed.snowstorm.rest.pojo.BrowserDescriptionSearchResult) PageRequest(org.springframework.data.domain.PageRequest) ConceptMini(org.snomed.snowstorm.core.data.domain.ConceptMini) DescriptionCriteria(org.snomed.snowstorm.core.data.services.pojo.DescriptionCriteria) ApiOperation(io.swagger.annotations.ApiOperation) JsonView(com.fasterxml.jackson.annotation.JsonView)

Example 2 with ConceptMini

use of org.snomed.snowstorm.core.data.domain.ConceptMini in project snowstorm by IHTSDO.

the class MRCMService method retrieveConceptModelAttributeHierarchy.

public ConceptMini retrieveConceptModelAttributeHierarchy(String branch, List<LanguageDialect> languageDialects) {
    logger.info("Loading concept model attribute hierarchy.");
    TimerUtil timer = new TimerUtil("attribute-tree", Level.INFO);
    String topId = Concepts.CONCEPT_MODEL_ATTRIBUTE;
    long topIdLong = parseLong(topId);
    // Load all attributes including terms
    List<ConceptMini> allAttributes = ecl("<<" + topId, branch, languageDialects);
    timer.checkpoint("load all with terms");
    Map<Long, ConceptMini> attributeMap = allAttributes.stream().collect(Collectors.toMap(ConceptMini::getConceptIdAsLong, Function.identity()));
    if (!attributeMap.containsKey(topIdLong)) {
        throw new IllegalStateException("Concept not found: " + topId + " | Concept model attribute (attribute) |.");
    }
    Set<Long> remainingAttributes = new HashSet<>(attributeMap.keySet());
    remainingAttributes.remove(topIdLong);
    BranchCriteria branchCriteria = versionControlHelper.getBranchCriteria(branch);
    NativeSearchQueryBuilder queryConceptQuery = new NativeSearchQueryBuilder().withQuery(boolQuery().must(branchCriteria.getEntityBranchCriteria(QueryConcept.class)).must(termQuery(QueryConcept.Fields.STATED, false)).filter(termsQuery(QueryConcept.Fields.CONCEPT_ID, remainingAttributes))).withFields(QueryConcept.Fields.CONCEPT_ID, QueryConcept.Fields.PARENTS).withPageable(LARGE_PAGE);
    try (SearchHitsIterator<QueryConcept> queryConcepts = elasticsearchTemplate.searchForStream(queryConceptQuery.build(), QueryConcept.class)) {
        queryConcepts.forEachRemaining(hit -> {
            for (Long parent : hit.getContent().getParents()) {
                ConceptMini parentMini = attributeMap.get(parent);
                if (parentMini.getExtraFields() == null || parentMini.getExtraFields().get(CHILDREN) == null) {
                    parentMini.addExtraField(CHILDREN, new ArrayList<>());
                }
                @SuppressWarnings("unchecked") List<ConceptMini> children = (List<ConceptMini>) parentMini.getExtraFields().get(CHILDREN);
                children.add(attributeMap.get(hit.getContent().getConceptIdL()));
                children.sort(Comparator.comparing(ConceptMini::getFsnTerm));
            }
        });
    }
    timer.finish();
    return attributeMap.get(topIdLong);
}
Also used : BranchCriteria(io.kaicode.elasticvc.api.BranchCriteria) QueryConcept(org.snomed.snowstorm.core.data.domain.QueryConcept) ConceptMini(org.snomed.snowstorm.core.data.domain.ConceptMini) TimerUtil(org.snomed.snowstorm.core.util.TimerUtil) Long.parseLong(java.lang.Long.parseLong) NativeSearchQueryBuilder(org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder)

Example 3 with ConceptMini

use of org.snomed.snowstorm.core.data.domain.ConceptMini in project snowstorm by IHTSDO.

the class FHIRValueSetProvider method validateCode.

private Parameters validateCode(IdType id, UriType urlType, StringType codeSystem, CodeType code, String display, StringType version, DateTimeType date, Coding coding, Coding codeableConcept, String context, BooleanType abstractBool, String displayLanguage, List<LanguageDialect> languageDialects) throws FHIROperationException {
    String url = urlType == null ? null : urlType.primitiveValue();
    doParameterValidation(url, codeSystem, code, coding, codeableConcept, context, display, date, version, abstractBool);
    // Can we get a codeSystem from the URL?
    if (url != null && url.startsWith(SNOMED_URI) && url.indexOf("?") > SNOMED_URI.length()) {
        if (codeSystem != null) {
            throw new FHIROperationException(IssueType.INVARIANT, "Cannot handle CodeSystem defined via both url and codeSystem parameter");
        }
        codeSystem = new StringType(url.substring(0, url.indexOf("?")));
    }
    if (version != null) {
        if (codeSystem == null) {
            codeSystem = new StringType(SNOMED_URI + "/version/" + version.toString());
        } else {
            fhirHelper.append(codeSystem, "/version/" + version.toString());
        }
    }
    // From either a saved VS instance or some implcit url, can we recover some ECL?
    String ecl = getECL(id, url == null ? null : url);
    if (ecl != null) {
        String conceptId = fhirHelper.recoverConceptId(code, coding);
        BranchPath branchPath = fhirHelper.getBranchPathFromURI(codeSystem);
        // Construct ECL to find the intersection of these two sets
        String intersectionEcl = conceptId + " AND (" + ecl + ")";
        Page<ConceptMini> result = fhirHelper.eclSearch(intersectionEcl, null, null, languageDialects, branchPath, FHIRHelper.SINGLE_ITEM_PAGE);
        if (result.getContent().size() == 1) {
            ConceptMini concept = result.getContent().get(0);
            if (!concept.getConceptId().equals(conceptId)) {
                throw new FHIROperationException(IssueType.PROCESSING, "ECL recovered an unexpected concept id (" + concept.getConceptId() + ") using " + intersectionEcl);
            }
            Concept fullConcept = conceptService.find(conceptId, languageDialects, branchPath.toString());
            return paramMapper.mapToFHIR(fullConcept, display);
        } else {
            // Now it might be that in this case we do not have this ValueSet loaded at all - or it's been
            // defined or the substrate has changed such that it has no members.   MAINT-1261 refers
            result = fhirHelper.eclSearch(ecl, null, null, languageDialects, branchPath, FHIRHelper.SINGLE_ITEM_PAGE);
            if (result.getContent().size() == 0) {
                throw new FHIROperationException(IssueType.PROCESSING, "Concept not found and additionally the Valueset contains no members when expanded against the specified substrate. Check any relevant reference set is actually loaded.  ECL = " + ecl + ", branch path = " + branchPath);
            }
            return paramMapper.conceptNotFound();
        }
    } else {
        // TODO We have some sort of enumerated valueset saved, we need to just search through the members
        throw new FHIROperationException(IssueType.NOTSUPPORTED, "Validating code against enumerated ValueSets has still to be implemented");
    }
}
Also used : BranchPath(org.snomed.snowstorm.fhir.domain.BranchPath) Concept(org.snomed.snowstorm.core.data.domain.Concept) ConceptMini(org.snomed.snowstorm.core.data.domain.ConceptMini)

Example 4 with ConceptMini

use of org.snomed.snowstorm.core.data.domain.ConceptMini in project snowstorm by IHTSDO.

the class HapiValueSetMapper method addExpansion.

private void addExpansion(ValueSet vs, List<ConceptMini> concepts, Map<String, Concept> conceptDetails, List<LanguageDialect> designations, Boolean includeDesignations) {
    // Will autocreate
    ValueSetExpansionComponent expansion = vs.getExpansion();
    for (ConceptMini concept : concepts) {
        ValueSetExpansionContainsComponent component = expansion.addContains().setCode(concept.getConceptId()).setSystem(SNOMED_URI);
        if (conceptDetails != null && conceptDetails.containsKey(concept.getConceptId())) {
            Concept c = conceptDetails.get(concept.getConceptId());
            for (Description d : c.getActiveDescriptions()) {
                if (includeDesignations && d.hasAcceptability(designations)) {
                    component.addDesignation(asDesignation(d));
                }
                // Use the preferred term in the specified display language.
                if (!designations.isEmpty() && d.hasAcceptability(Concepts.PREFERRED, designations.get(0)) && d.getTypeId().equals(Concepts.SYNONYM)) {
                    component.setDisplay(d.getTerm());
                    boolean inactive = !c.isActive();
                    if (inactive) {
                        component.setInactive(inactive);
                    }
                }
            }
        }
    }
}
Also used : ValueSetExpansionComponent(org.hl7.fhir.r4.model.ValueSet.ValueSetExpansionComponent) Concept(org.snomed.snowstorm.core.data.domain.Concept) ValueSetExpansionContainsComponent(org.hl7.fhir.r4.model.ValueSet.ValueSetExpansionContainsComponent) Description(org.snomed.snowstorm.core.data.domain.Description) ConceptMini(org.snomed.snowstorm.core.data.domain.ConceptMini)

Example 5 with ConceptMini

use of org.snomed.snowstorm.core.data.domain.ConceptMini in project snowstorm by IHTSDO.

the class MultiSearchController method findDescriptions.

@ApiOperation("Search descriptions across multiple Code Systems.")
@RequestMapping(value = "multisearch/descriptions", method = RequestMethod.GET)
@JsonView(value = View.Component.class)
public ItemsPage<BrowserDescriptionSearchResult> findDescriptions(// Required!
@RequestParam String term, @RequestParam(required = false) Boolean active, @RequestParam(required = false) Collection<String> module, @ApiParam(value = "Set of two character language codes to match. " + "The English language code 'en' will not be added automatically, in contrast to the Accept-Language header which always includes it. " + "Accept-Language header still controls result FSN and PT language selection.") @RequestParam(required = false) Set<String> language, @ApiParam(value = "Set of description types to include. Pick descendants of '900000000000446008 | Description type (core metadata concept) |'.") @RequestParam(required = false) Set<Long> type, @RequestParam(required = false) Boolean conceptActive, @RequestParam(defaultValue = "ALL_PUBLISHED_CONTENT") ContentScope contentScope, @RequestParam(defaultValue = "0") int offset, @RequestParam(defaultValue = "50") int limit, @RequestHeader(value = "Accept-Language", defaultValue = Config.DEFAULT_ACCEPT_LANG_HEADER) String acceptLanguageHeader) throws TooCostlyException {
    TimerUtil timer = new TimerUtil("MultiSearch - Descriptions");
    DescriptionCriteria descriptionCriteria = new DescriptionCriteria().term(term).active(active).modules(module).searchLanguageCodes(language).type(type).conceptActive(conceptActive);
    PageRequest pageRequest = ControllerHelper.getPageRequest(offset, limit);
    Page<Description> descriptions = multiSearchService.findDescriptions(descriptionCriteria, pageRequest);
    timer.checkpoint("description search");
    Map<String, List<Description>> branchDescriptions = new HashMap<>();
    Map<String, List<String>> branchConceptIds = new HashMap<>();
    for (Description description : descriptions) {
        branchDescriptions.computeIfAbsent(description.getPath(), s -> new ArrayList<>()).add(description);
        branchConceptIds.computeIfAbsent(description.getPath(), s -> new ArrayList<>()).add(description.getConceptId());
    }
    List<LanguageDialect> languageDialects = ControllerHelper.parseAcceptLanguageHeaderWithDefaultFallback(acceptLanguageHeader);
    Map<String, ConceptMini> conceptMiniMap = new HashMap<>();
    for (String branchPath : branchConceptIds.keySet()) {
        conceptMiniMap.putAll(conceptService.findConceptMinis(branchPath, branchConceptIds.get(branchPath), languageDialects).getResultsMap());
        timer.checkpoint("Join concepts from " + branchPath);
    }
    List<BrowserDescriptionSearchResult> results = new ArrayList<>();
    for (Description description : descriptions) {
        BrowserDescriptionSearchResult result = new BrowserDescriptionSearchResult(description.getTerm(), description.isActive(), description.getLanguageCode(), description.getModuleId(), conceptMiniMap.get(description.getConceptId()));
        result.addExtraField("branchPath", description.getPath());
        results.add(result);
    }
    timer.finish();
    return new ItemsPage<>(new PageImpl<>(results, pageRequest, descriptions.getTotalElements()));
}
Also used : java.util(java.util) JsonView(com.fasterxml.jackson.annotation.JsonView) ApiParam(io.swagger.annotations.ApiParam) PageWithBucketAggregations(org.snomed.snowstorm.core.data.services.pojo.PageWithBucketAggregations) Autowired(org.springframework.beans.factory.annotation.Autowired) MultiSearchService(org.snomed.snowstorm.core.data.services.MultiSearchService) Concept(org.snomed.snowstorm.core.data.domain.Concept) ApiOperation(io.swagger.annotations.ApiOperation) BrowserDescriptionSearchResult(org.snomed.snowstorm.rest.pojo.BrowserDescriptionSearchResult) Description(org.snomed.snowstorm.core.data.domain.Description) Api(io.swagger.annotations.Api) LanguageDialect(org.snomed.snowstorm.core.pojo.LanguageDialect) Config(org.snomed.snowstorm.config.Config) ConceptMini(org.snomed.snowstorm.core.data.domain.ConceptMini) ConceptCriteria(org.snomed.snowstorm.core.data.services.pojo.ConceptCriteria) ItemsPage(org.snomed.snowstorm.rest.pojo.ItemsPage) PageRequest(org.springframework.data.domain.PageRequest) Page(org.springframework.data.domain.Page) Collectors(java.util.stream.Collectors) ConceptService(org.snomed.snowstorm.core.data.services.ConceptService) DescriptionCriteria(org.snomed.snowstorm.core.data.services.pojo.DescriptionCriteria) org.springframework.web.bind.annotation(org.springframework.web.bind.annotation) TooCostlyException(org.snomed.snowstorm.core.data.services.TooCostlyException) TimerUtil(org.snomed.snowstorm.core.util.TimerUtil) PageImpl(org.springframework.data.domain.PageImpl) Description(org.snomed.snowstorm.core.data.domain.Description) LanguageDialect(org.snomed.snowstorm.core.pojo.LanguageDialect) BrowserDescriptionSearchResult(org.snomed.snowstorm.rest.pojo.BrowserDescriptionSearchResult) PageRequest(org.springframework.data.domain.PageRequest) ItemsPage(org.snomed.snowstorm.rest.pojo.ItemsPage) ConceptMini(org.snomed.snowstorm.core.data.domain.ConceptMini) TimerUtil(org.snomed.snowstorm.core.util.TimerUtil) DescriptionCriteria(org.snomed.snowstorm.core.data.services.pojo.DescriptionCriteria) ApiOperation(io.swagger.annotations.ApiOperation) JsonView(com.fasterxml.jackson.annotation.JsonView)

Aggregations

ConceptMini (org.snomed.snowstorm.core.data.domain.ConceptMini)17 Concept (org.snomed.snowstorm.core.data.domain.Concept)7 Description (org.snomed.snowstorm.core.data.domain.Description)6 LanguageDialect (org.snomed.snowstorm.core.pojo.LanguageDialect)6 PageRequest (org.springframework.data.domain.PageRequest)6 ApiOperation (io.swagger.annotations.ApiOperation)5 ReferenceSetMember (org.snomed.snowstorm.core.data.domain.ReferenceSetMember)5 TimerUtil (org.snomed.snowstorm.core.util.TimerUtil)5 PageImpl (org.springframework.data.domain.PageImpl)5 JsonView (com.fasterxml.jackson.annotation.JsonView)4 BranchCriteria (io.kaicode.elasticvc.api.BranchCriteria)4 java.util (java.util)4 Collectors (java.util.stream.Collectors)4 Config (org.snomed.snowstorm.config.Config)4 ConceptService (org.snomed.snowstorm.core.data.services.ConceptService)4 DescriptionCriteria (org.snomed.snowstorm.core.data.services.pojo.DescriptionCriteria)4 PageWithBucketAggregations (org.snomed.snowstorm.core.data.services.pojo.PageWithBucketAggregations)4 BrowserDescriptionSearchResult (org.snomed.snowstorm.rest.pojo.BrowserDescriptionSearchResult)4 Autowired (org.springframework.beans.factory.annotation.Autowired)4 Api (io.swagger.annotations.Api)3