From ce0764d65cc57d86a098f9487308587bd77f07e7 Mon Sep 17 00:00:00 2001 From: Richard Eckart de Castilho Date: Mon, 16 Dec 2019 17:15:01 +0100 Subject: [PATCH] #1549 - Filter entity candidates by description - Allow filtering candidates by description using `::` separator - Allow filtering candidates by label using `"..."` quoting - Added documentation for the new features --- .../ui/kb/feature/ConceptFeatureEditor.java | 44 ++++++++++++++++++- ...n_create-annotations_concept-features.adoc | 11 +++++ 2 files changed, 53 insertions(+), 2 deletions(-) diff --git a/inception-ui-kb/src/main/java/de/tudarmstadt/ukp/inception/ui/kb/feature/ConceptFeatureEditor.java b/inception-ui-kb/src/main/java/de/tudarmstadt/ukp/inception/ui/kb/feature/ConceptFeatureEditor.java index f87d20b2403..0d0dd1409c4 100644 --- a/inception-ui-kb/src/main/java/de/tudarmstadt/ukp/inception/ui/kb/feature/ConceptFeatureEditor.java +++ b/inception-ui-kb/src/main/java/de/tudarmstadt/ukp/inception/ui/kb/feature/ConceptFeatureEditor.java @@ -20,13 +20,17 @@ import static de.tudarmstadt.ukp.clarin.webanno.support.lambda.LambdaBehavior.visibleWhen; import static java.util.Arrays.asList; import static java.util.Collections.emptyList; +import static org.apache.commons.lang3.StringUtils.containsIgnoreCase; import static org.apache.commons.lang3.StringUtils.isNotBlank; +import static org.apache.commons.lang3.StringUtils.substringAfter; +import static org.apache.commons.lang3.StringUtils.substringBefore; import static org.apache.wicket.event.Broadcast.BUBBLE; import static org.apache.wicket.markup.head.JavaScriptHeaderItem.forReference; import java.util.Collections; import java.util.List; import java.util.Locale; +import java.util.stream.Collectors; import org.apache.commons.lang3.StringUtils; import org.apache.uima.cas.CAS; @@ -160,6 +164,29 @@ private List getCandidates(IModel aStateModel, if (aInput == null) { return emptyList(); } + + String input = aInput; + + // Extract filter on the description + final String descriptionFilter; + if (input.contains("::")) { + descriptionFilter = substringAfter(input , "::"); + input = substringBefore(input , "::"); + } + else { + descriptionFilter = null; + } + + // Extract exact match filter on the query + boolean labelFilter = false; + String trimmedInput = input.trim(); + if (trimmedInput.length() > 2 && trimmedInput.startsWith("\"") + && trimmedInput.endsWith("\"")) { + input = StringUtils.substring(trimmedInput, 1, -1); + labelFilter = true; + } + + final String finalInput = input; List choices; try { @@ -185,8 +212,8 @@ private List getCandidates(IModel aStateModel, : -1; choices = clService.getLinkingInstancesInKBScope(traits.getRepositoryId(), - traits.getScope(), traits.getAllowedValueType(), aInput, mention, mentionBegin, - cas, feat.getProject()); + traits.getScope(), traits.getAllowedValueType(), finalInput, mention, + mentionBegin, cas, feat.getProject()); } catch (Exception e) { choices = asList(new KBHandle("http://ERROR", "ERROR", e.getMessage(), "en")); @@ -196,6 +223,19 @@ private List getCandidates(IModel aStateModel, .find(IPartialPageRequestHandler.class) .ifPresent(target -> target.addChildren(getPage(), IFeedback.class)); } + + if (labelFilter) { + choices = choices.stream() + .filter(kb -> containsIgnoreCase(kb.getUiLabel(), finalInput)) + .collect(Collectors.toList()); + } + + if (isNotBlank(descriptionFilter)) { + choices = choices.stream() + .filter(kb -> containsIgnoreCase(kb.getDescription(), descriptionFilter)) + .collect(Collectors.toList()); + } + return choices; } diff --git a/inception-ui-kb/src/main/resources/META-INF/asciidoc/user-guide/annotation_create-annotations_concept-features.adoc b/inception-ui-kb/src/main/resources/META-INF/asciidoc/user-guide/annotation_create-annotations_concept-features.adoc index f53577af8e3..ea520baa96b 100644 --- a/inception-ui-kb/src/main/resources/META-INF/asciidoc/user-guide/annotation_create-annotations_concept-features.adoc +++ b/inception-ui-kb/src/main/resources/META-INF/asciidoc/user-guide/annotation_create-annotations_concept-features.adoc @@ -2,3 +2,14 @@ Concept features are shown as an auto-complete field. Typing into the field triggers a query against the knowledge base and displays candidates in a dropdown list. + +.Filtering by description +The query entered into the field only matches against the label of the knowledge base items, not +against their description. However, you can filter the candidates by their description. E.g. if you +wish to find all knowledge base items with `Obama` in the label and `president` in the description, +then you can write `Obama :: president`. A case-insensitive matching is being used. + +.Substring matching +Depending on the knowledge base and full-text mode being used, there may be fuzzy matching. To +filter the candidate list down to those candidates which contain a particular substring, put +double quotes around the query, e.g. `"County Carlow"`. A case-insensitive matching is being used.