Search in sources :

Example 1 with LanguageDialect

use of org.snomed.snowstorm.core.pojo.LanguageDialect in project snowstorm by IHTSDO.

the class ConceptController method findConcepts.

@GetMapping(value = "/{branch}/concepts", produces = { "application/json", "text/csv" })
public ItemsPage<?> findConcepts(@PathVariable String branch, @RequestParam(required = false) Boolean activeFilter, @RequestParam(required = false) String definitionStatusFilter, @ApiParam(value = "Set of module ids to filter concepts by. Defaults to any.") @RequestParam(required = false) Set<Long> module, @ApiParam(value = "Search term to match against concept descriptions using a case-insensitive multi-prefix matching strategy.") @RequestParam(required = false) String term, @RequestParam(required = false) Boolean termActive, @ApiParam(value = "Set of description type ids to use for the term search. Defaults to any. " + "Pick descendants of '900000000000446008 | Description type (core metadata concept) |'. " + "Examples: 900000000000003001 (FSN), 900000000000013009 (Synonym), 900000000000550004 (Definition)") @RequestParam(required = false) Set<Long> descriptionType, @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 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) String ecl, @RequestParam(required = false) Integer effectiveTime, @RequestParam(required = false) Boolean isNullEffectiveTime, @RequestParam(required = false) Boolean isPublished, @RequestParam(required = false) String statedEcl, @RequestParam(required = false) Set<String> conceptIds, @RequestParam(required = false) boolean returnIdOnly, @RequestParam(required = false, defaultValue = "0") int offset, @RequestParam(required = false, defaultValue = "50") int limit, @RequestParam(required = false) String searchAfter, @ApiParam("Accept-Language header can take the format en-x-900000000000508004 which sets the language reference set to use in the results.") @RequestHeader(value = "Accept-Language", defaultValue = Config.DEFAULT_ACCEPT_LANG_HEADER) String acceptLanguageHeader) {
    branch = BranchPathUriUtil.decodePath(branch);
    // Parameter validation
    if (ecl != null && statedEcl != null) {
        throw new IllegalArgumentException("Parameters ecl and statedEcl can not be combined.");
    }
    if ((ecl != null || statedEcl != null) && activeFilter != null && !activeFilter) {
        throw new IllegalArgumentException("ECL search can not be used on inactive concepts.");
    }
    boolean stated = true;
    if (isNotBlank(ecl)) {
        eclValidator.validate(ecl, branch);
        stated = false;
    } else {
        ecl = statedEcl;
    }
    List<LanguageDialect> languageDialects = ControllerHelper.parseAcceptLanguageHeaderWithDefaultFallback(acceptLanguageHeader);
    QueryService.ConceptQueryBuilder queryBuilder = queryService.createQueryBuilder(stated).activeFilter(activeFilter).descriptionCriteria(descriptionCriteria -> descriptionCriteria.active(termActive).term(term).searchLanguageCodes(language).type(descriptionType)).definitionStatusFilter(definitionStatusFilter).module(module).ecl(ecl).effectiveTime(effectiveTime).isNullEffectiveTime(isNullEffectiveTime).isReleased(isPublished).resultLanguageDialects(languageDialects).conceptIds(conceptIds);
    queryBuilder.getDescriptionCriteria().preferredOrAcceptableValues(preferredOrAcceptableIn, preferredIn, acceptableIn);
    PageRequest pageRequest = getPageRequestWithSort(offset, limit, searchAfter, Sort.sort(Concept.class).by(Concept::getConceptId).descending());
    if (ecl != null) {
        pageRequest = getPageRequestWithSort(offset, limit, searchAfter, Sort.sort(QueryConcept.class).by(QueryConcept::getConceptIdL).descending());
    }
    if (returnIdOnly) {
        SearchAfterPage<Long> longsPage = queryService.searchForIds(queryBuilder, branch, pageRequest);
        SearchAfterPageImpl<String> stringPage = new SearchAfterPageImpl<>(longsPage.stream().map(Object::toString).collect(Collectors.toList()), longsPage.getPageable(), longsPage.getTotalElements(), longsPage.getSearchAfter());
        return new ItemsPage<>(stringPage);
    } else {
        return new ItemsPage<>(queryService.search(queryBuilder, branch, pageRequest));
    }
}
Also used : SearchAfterPageImpl(org.snomed.snowstorm.core.util.SearchAfterPageImpl) LanguageDialect(org.snomed.snowstorm.core.pojo.LanguageDialect) SearchAfterPageRequest(org.springframework.data.elasticsearch.core.SearchAfterPageRequest) PageRequest(org.springframework.data.domain.PageRequest)

Example 2 with LanguageDialect

use of org.snomed.snowstorm.core.pojo.LanguageDialect in project snowstorm by IHTSDO.

the class ConceptController method findBrowserConcept.

@ApiOperation(value = "Load a concept in the browser format.", notes = "During content authoring previous versions of the concept can be loaded from version control.\n" + "To do this use the branch path format {branch@" + BranchTimepoint.DATE_FORMAT_STRING + "} or {branch@epoch_milliseconds}.\n" + "The version of the concept when the branch was created can be loaded using {branch@" + BRANCH_CREATION_TIMEPOINT + "}.")
@GetMapping(value = "/browser/{branch}/concepts/{conceptId}")
@JsonView(value = View.Component.class)
public ConceptView findBrowserConcept(@PathVariable String branch, @PathVariable String conceptId, @ApiParam("If this parameter is set a descendantCount will be included in the response using stated/inferred as requested.") @RequestParam(required = false) Relationship.CharacteristicType descendantCountForm, @RequestHeader(value = "Accept-Language", defaultValue = Config.DEFAULT_ACCEPT_LANG_HEADER) String acceptLanguageHeader) {
    List<LanguageDialect> languageDialects = ControllerHelper.parseAcceptLanguageHeaderWithDefaultFallback(acceptLanguageHeader);
    BranchTimepoint branchTimepoint = parseBranchTimepoint(branch);
    Concept concept = conceptService.find(conceptId, languageDialects, branchTimepoint);
    if (descendantCountForm != null) {
        queryService.joinDescendantCount(concept, descendantCountForm, languageDialects, branchTimepoint);
    }
    return ControllerHelper.throwIfNotFound("Concept", concept);
}
Also used : LanguageDialect(org.snomed.snowstorm.core.pojo.LanguageDialect) BranchTimepoint(org.snomed.snowstorm.core.pojo.BranchTimepoint) ControllerHelper.parseBranchTimepoint(org.snomed.snowstorm.rest.ControllerHelper.parseBranchTimepoint) ApiOperation(io.swagger.annotations.ApiOperation) JsonView(com.fasterxml.jackson.annotation.JsonView)

Example 3 with LanguageDialect

use of org.snomed.snowstorm.core.pojo.LanguageDialect in project snowstorm by IHTSDO.

the class ControllerHelper method parseAcceptLanguageHeader.

public static List<LanguageDialect> parseAcceptLanguageHeader(String acceptLanguageHeader) {
    // en-ie-x-21000220103;q=0.8,en-US;q=0.5
    List<LanguageDialect> languageDialects = new ArrayList<>();
    if (acceptLanguageHeader == null) {
        acceptLanguageHeader = "";
    }
    acceptLanguageHeader = acceptLanguageHeader.replaceAll("\\s+", "");
    String[] acceptLanguageList = acceptLanguageHeader.toLowerCase().split(",");
    for (String acceptLanguage : acceptLanguageList) {
        if (acceptLanguage.isEmpty()) {
            continue;
        }
        String languageCode;
        Long languageReferenceSet = null;
        String[] valueAndWeight = acceptLanguage.split(";");
        // We don't use the weight, just take the value
        String value = valueAndWeight[0];
        Matcher matcher = LANGUAGE_PATTERN.matcher(value);
        if (matcher.matches()) {
            languageCode = matcher.group(1);
            // Check if there is a default language reference set for a given language
            languageReferenceSet = DialectConfigurationService.instance().findRefsetForDialect(value);
        } else if ((matcher = LANGUAGE_AND_REFSET_PATTERN.matcher(value)).matches()) {
            languageCode = matcher.group(1);
            languageReferenceSet = parseLong(matcher.group(2));
        } else if ((matcher = LANGUAGE_AND_DIALECT_PATTERN.matcher(value)).matches()) {
            languageCode = matcher.group(1);
            languageReferenceSet = DialectConfigurationService.instance().findRefsetForDialect(value);
        } else if ((matcher = LANGUAGE_AND_DIALECT_AND_REFSET_PATTERN.matcher(value)).matches()) {
            languageCode = matcher.group(1);
            languageReferenceSet = parseLong(matcher.group(3));
        } else {
            throw new IllegalArgumentException("Unexpected value within Accept-Language request header '" + value + "'.");
        }
        LanguageDialect languageDialect = new LanguageDialect(languageCode, languageReferenceSet);
        if (!languageDialects.contains(languageDialect)) {
            // Would normally use a Set here, but the order may be important
            languageDialects.add(languageDialect);
        }
    }
    return languageDialects;
}
Also used : LanguageDialect(org.snomed.snowstorm.core.pojo.LanguageDialect) Matcher(java.util.regex.Matcher) ArrayList(java.util.ArrayList) Long.parseLong(java.lang.Long.parseLong)

Example 4 with LanguageDialect

use of org.snomed.snowstorm.core.pojo.LanguageDialect 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 5 with LanguageDialect

use of org.snomed.snowstorm.core.pojo.LanguageDialect in project snowstorm by IHTSDO.

the class FHIRHelper method getLanguageDialects.

public List<LanguageDialect> getLanguageDialects(List<String> designations, String acceptLanguageHeader) throws FHIROperationException {
    // Use designations preferably, or fall back to language headers
    final List<LanguageDialect> languageDialects = new ArrayList<>();
    if (designations != null) {
        for (String designation : designations) {
            if (designation.length() > MAX_LANGUAGE_CODE_LENGTH) {
                // in this case we're expecting a designation token
                // of the form snomed PIPE langrefsetId
                String[] tokenParts = designation.split(PIPE);
                if (tokenParts.length < 2 || !StringUtils.isNumeric(tokenParts[1]) || // TODO: version support?
                !tokenParts[0].matches(SNOMED_URI + "(/\\d*)?")) {
                    throw new FHIROperationException(IssueType.VALUE, "Malformed designation token '" + designation + "' expected format http://snomed.info/sct(/moduleId) PIPE langrefsetId");
                }
                LanguageDialect languageDialect = new LanguageDialect(null, Long.parseLong(tokenParts[1]));
                if (!languageDialects.contains(languageDialect)) {
                    languageDialects.add(languageDialect);
                }
            } else {
                languageDialects.add(dialectService.getLanguageDialect(designation));
            }
        }
    } else {
        if (acceptLanguageHeader != null) {
            languageDialects.addAll(ControllerHelper.parseAcceptLanguageHeader(acceptLanguageHeader));
        }
    }
    if (languageDialects.isEmpty()) {
        languageDialects.addAll(DEFAULT_LANGUAGE_DIALECTS);
    }
    return languageDialects;
}
Also used : LanguageDialect(org.snomed.snowstorm.core.pojo.LanguageDialect) ArrayList(java.util.ArrayList)

Aggregations

LanguageDialect (org.snomed.snowstorm.core.pojo.LanguageDialect)15 PageRequest (org.springframework.data.domain.PageRequest)8 ApiOperation (io.swagger.annotations.ApiOperation)5 Concept (org.snomed.snowstorm.core.data.domain.Concept)5 ConceptMini (org.snomed.snowstorm.core.data.domain.ConceptMini)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 Description (org.snomed.snowstorm.core.data.domain.Description)4 ConceptCriteria (org.snomed.snowstorm.core.data.services.pojo.ConceptCriteria)4 PageWithBucketAggregations (org.snomed.snowstorm.core.data.services.pojo.PageWithBucketAggregations)4 TimerUtil (org.snomed.snowstorm.core.util.TimerUtil)4 Autowired (org.springframework.beans.factory.annotation.Autowired)4 Long.parseLong (java.lang.Long.parseLong)3 Config (org.snomed.snowstorm.config.Config)3 DescriptionCriteria (org.snomed.snowstorm.core.data.services.pojo.DescriptionCriteria)3 BranchPath (org.snomed.snowstorm.fhir.domain.BranchPath)3 BrowserDescriptionSearchResult (org.snomed.snowstorm.rest.pojo.BrowserDescriptionSearchResult)3 Page (org.springframework.data.domain.Page)3