group proposal as if they were hierarchical

We interpret dots ('.') as hierarchy delimiter in.
That way we can reduce the number of proposed values
and show only those for the next level.
This commit is contained in:
2019-02-09 15:21:35 +01:00
parent 493971bcf3
commit 27b83234cc
3 changed files with 125 additions and 1 deletions

View File

@@ -0,0 +1,51 @@
package org.lucares.pdb.datastore.lang;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.SortedSet;
import java.util.TreeSet;
import java.util.regex.Pattern;
public class CandidateGrouper {
public SortedSet<String> group(final Collection<String> values, final String queryWithCaretMarker) {
final TreeSet<String> result = new TreeSet<>();
final int numDotsInValue = countDotsInValue(queryWithCaretMarker);
for (final String value : values) {
// keep everyting up to the (numDotsInValue+1)-th
final String[] token = value.split(Pattern.quote("."));
final List<String> tokenlist = new ArrayList<>(Arrays.asList(token));
final List<String> prefix = tokenlist.subList(0, numDotsInValue + 1);
String shortenedValue = String.join(".", prefix);
if (tokenlist.size() > numDotsInValue + 1) {
shortenedValue += ".";
}
result.add(shortenedValue);
}
return result;
}
private int countDotsInValue(final String queryWithCaretMarker) {
int count = 0;
int index = queryWithCaretMarker.indexOf(NewProposerParser.CARET_MARKER) - 1;
final String delimiter = " (),=!";
while (index >= 0) {
final char c = queryWithCaretMarker.charAt(index);
if (delimiter.indexOf(c) >= 0) {
break;
}
if (c == '.') {
count++;
}
index--;
}
return count;
}
}

View File

@@ -167,8 +167,11 @@ public class NewProposerParser {
final SortedSet<String> candidateValues = normalizedExpression final SortedSet<String> candidateValues = normalizedExpression
.visit(new FindValuesForQueryCompletion(queryCompletionIndex)); .visit(new FindValuesForQueryCompletion(queryCompletionIndex));
final SortedSet<String> candidateValuesCutAtDots = cutAtDots(candidateValues, queryWithCaretMarker);
// translate the candidate values to proposals // translate the candidate values to proposals
final List<Proposal> proposals = generateProposals(queryWithCaretMarker, expression, candidateValues); final List<Proposal> proposals = generateProposals(queryWithCaretMarker, expression,
candidateValuesCutAtDots);
return proposals; return proposals;
} catch (final SyntaxException e) { } catch (final SyntaxException e) {
@@ -178,6 +181,11 @@ public class NewProposerParser {
} }
} }
private SortedSet<String> cutAtDots(final SortedSet<String> candidateValues, final String queryWithCaretMarker) {
final CandidateGrouper grouper = new CandidateGrouper();
return grouper.group(candidateValues, queryWithCaretMarker);
}
private List<Proposal> generateProposals(final String queryWithCaretMarker, final Expression expression, private List<Proposal> generateProposals(final String queryWithCaretMarker, final Expression expression,
final SortedSet<String> candidateValues) { final SortedSet<String> candidateValues) {
final List<Proposal> proposals = new ArrayList<>(); final List<Proposal> proposals = new ArrayList<>();

View File

@@ -0,0 +1,65 @@
package org.lucares.pdb.datastore.lang;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.SortedSet;
import org.testng.Assert;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
@Test
public class CandidateGrouperTest {
@DataProvider
public Object[][] providerGroup() {
final List<Object[]> result = new ArrayList<>();
result.add(new Object[] { //
Set.of("aa.xx.AA.XX", "aa.yy.BB", "aa.xx.BB", "aa.xx.AA.YY"), //
"name = |", //
Set.of("aa.") });
result.add(new Object[] { //
Set.of("aa.xx.AA.XX", "aa.yy.BB", "aa.xx.BB", "aa.xx.AA.YY"), //
"name = a|", //
Set.of("aa.") });
result.add(new Object[] { //
Set.of("aa.xx.AA.XX", "aa.yy.BB", "aa.xx.BB", "aa.xx.AA.YY"), //
"name = aa|", //
Set.of("aa.") });
result.add(new Object[] { //
Set.of("aa.xx.AA.XX", "aa.yy.BB", "aa.xx.BB", "aa.xx.AA.YY"), //
"name = aa.|", //
Set.of("aa.xx.", "aa.yy.") });
result.add(new Object[] { //
Set.of("aa.xx.AA.XX", "aa.xx.BB", "aa.xx.AA.YY"), //
"name = aa.x|", //
Set.of("aa.xx.") });
result.add(new Object[] { //
Set.of("aa.xx.AA.XX", "aa.xx.BB", "aa.xx.AA.YY"), //
"name = aa.xx.|", //
Set.of("aa.xx.AA.", "aa.xx.BB") });
result.add(new Object[] { //
Set.of("aa.xx.AA.XX", "aa.xx.AA.YY"), //
"name = aa.xx.AA.|", //
Set.of("aa.xx.AA.XX", "aa.xx.AA.YY") });
result.add(new Object[] { //
Set.of("XX.YY.ZZ", "XX.YY"), //
"name = XX.Y|", //
Set.of("XX.YY.", "XX.YY") });
return result.toArray(new Object[0][]);
}
@Test(dataProvider = "providerGroup")
public void testGroup(final Set<String> values, final String queryWithCaretMarker, final Set<String> expected) {
final CandidateGrouper grouper = new CandidateGrouper();
final String query = queryWithCaretMarker.replace("|", NewProposerParser.CARET_MARKER);
final SortedSet<String> actual = grouper.group(values, query);
Assert.assertEquals(actual, expected);
}
}