do not move the cursor to the end when applying a proposal

This commit is contained in:
2018-04-08 14:06:13 +02:00
parent 68ee88bce0
commit 1755562a84
8 changed files with 167 additions and 93 deletions

View File

@@ -7,17 +7,26 @@ public class Proposal implements Comparable<Proposal> {
private final boolean hasResults;
public Proposal(final String proposedTag, final String proposedQuery, final boolean hasResults) {
private final String newQuery;
private final int newCaretPosition;
public Proposal(final String proposedTag, final String proposedQuery, final boolean hasResults,
final String newQuery, final int newCaretPosition) {
super();
this.proposedTag = proposedTag;
this.proposedQuery = proposedQuery;
this.hasResults = hasResults;
this.newQuery = newQuery;
this.newCaretPosition = newCaretPosition;
}
public Proposal(final Proposal proposal, final boolean hasResults) {
this.proposedTag = proposal.proposedTag;
this.proposedQuery = proposal.proposedQuery;
this.hasResults = hasResults;
this.newQuery = proposal.newQuery;
this.newCaretPosition = proposal.newCaretPosition;
}
public String getProposedTag() {
@@ -32,38 +41,50 @@ public class Proposal implements Comparable<Proposal> {
return hasResults;
}
@Override
public String toString() {
return "Proposal [proposedTag:" + proposedTag + ", proposedQuery:" + proposedQuery + ", hasResults=" + hasResults
+ "]";
public String getNewQuery() {
return newQuery;
}
public int getNewCaretPosition() {
return newCaretPosition;
}
@Override
public String toString() {
return "Proposal [proposedTag=" + proposedTag + ", proposedQuery=" + proposedQuery + ", hasResults="
+ hasResults + ", newQuery=" + newQuery + ", newCaretPosition=" + newCaretPosition + "]";
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + (hasResults ? 1231 : 1237);
result = prime * result
+ ((proposedQuery == null) ? 0 : proposedQuery.hashCode());
result = prime * result
+ ((proposedTag == null) ? 0 : proposedTag.hashCode());
result = prime * result + newCaretPosition;
result = prime * result + ((newQuery == null) ? 0 : newQuery.hashCode());
result = prime * result + ((proposedQuery == null) ? 0 : proposedQuery.hashCode());
result = prime * result + ((proposedTag == null) ? 0 : proposedTag.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
public boolean equals(final Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Proposal other = (Proposal) obj;
final Proposal other = (Proposal) obj;
if (hasResults != other.hasResults)
return false;
if (newCaretPosition != other.newCaretPosition)
return false;
if (newQuery == null) {
if (other.newQuery != null)
return false;
} else if (!newQuery.equals(other.newQuery))
return false;
if (proposedQuery == null) {
if (other.proposedQuery != null)
return false;
@@ -78,7 +99,7 @@ public class Proposal implements Comparable<Proposal> {
}
@Override
public int compareTo(Proposal o) {
public int compareTo(final Proposal o) {
return proposedTag.compareTo(o.getProposedTag());
}
}

View File

@@ -1,8 +1,6 @@
package org.lucares.pdb.datastore.internal;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.SortedSet;
import java.util.TreeSet;
@@ -46,23 +44,12 @@ public class Proposer {
}
private SortedSet<Proposal> proposeForAllKeys() {
final SortedSet<Proposal> result;
final SortedSet<Proposal> result = new TreeSet<>();
final List<String> fields = dataStore.getAvailableFields();
final Map<String, String> fieldToQuery = CollectionUtils.createMapFromKeys(fields, f -> f + "=*");
result = toProposalsForQueries(fieldToQuery);
return result;
}
private SortedSet<Proposal> toProposalsForQueries(final Map<String, String> keyToQuery) {
final SortedSet<Proposal> result = new TreeSet<>();
for (final Entry<String, String> e : keyToQuery.entrySet()) {
final String key = e.getKey();
final String query = e.getValue();
final Proposal proposal = new Proposal(key, query, true);
for (final String field : fields) {
final String newQuery = field + "=";
final Proposal proposal = new Proposal(field, field + "=*", true, newQuery, newQuery.length());
result.add(proposal);
}

View File

@@ -26,6 +26,8 @@ import org.slf4j.LoggerFactory;
public class QueryCompletionPdbLangParser extends PdbLangParser {
private final static String CARET_MARKER = "\ue002"; // third character in the private use area
private static final Logger METRICS_LOGGER = LoggerFactory.getLogger("org.lucares.metrics.autocomplete");
public class Listener implements PdbLangListener, ANTLRErrorListener {
@@ -64,7 +66,8 @@ public class QueryCompletionPdbLangParser extends PdbLangParser {
final StringBuilder newQuery = new StringBuilder(query);
newQuery.replace(start, end + 1, v + " "); // insert the terminal into the query
return new Proposal(v, newQuery.toString(), false);
return new Proposal(v, newQuery.toString(), false, newQuery.toString(),
start + v.length() + 1);
}).map(p -> {
final int count = dataStore.count(p.getProposedQuery());
@@ -101,13 +104,15 @@ public class QueryCompletionPdbLangParser extends PdbLangParser {
final StringBuilder newQuery = new StringBuilder(query);
newQuery.replace(charPositionInLine, charPositionInLine + text.length(), " and ");
proposals.add(new Proposal(" and ", newQuery.toString(), true));
proposals.add(new Proposal(" and ", newQuery.toString(), true, newQuery.toString(),
charPositionInLine + text.length()));
}
if ("or".startsWith(text)) {
final StringBuilder newQuery = new StringBuilder(query);
newQuery.replace(charPositionInLine, charPositionInLine + text.length(), " or ");
proposals.add(new Proposal(" or ", newQuery.toString(), true));
proposals.add(new Proposal(" or ", newQuery.toString(), true, newQuery.toString(),
charPositionInLine + text.length()));
}
}
}
@@ -121,7 +126,13 @@ public class QueryCompletionPdbLangParser extends PdbLangParser {
matchingKeys.stream()//
.map(key -> {
return new Proposal(key, String.format(newQueryPattern, key + "=* "), false);
final String newQueryWithMarker = String.format(newQueryPattern, key + "=" + CARET_MARKER)
.replaceAll("\\s+", " ");
final int newCaretPosition = newQueryWithMarker.indexOf(CARET_MARKER);
final String newQuery = newQueryWithMarker.replace(CARET_MARKER, "");
return new Proposal(key, String.format(newQueryPattern, key + "=* "), false, newQuery,
newCaretPosition);
}).map(p -> {
final String proposedQuery = p.getProposedQuery();

View File

@@ -41,15 +41,15 @@ public class FolderStorageTest {
final List<Path> actualFiles = getPathsRelativeToDataDirectory();
final List<Path> expectedFiles = Arrays.asList(//
Paths.get("0", "0", "a" + SUFFIX), //
Paths.get("0", "0", "b" + SUFFIX), //
Paths.get("0", "1", "c" + SUFFIX), //
Paths.get("0", "1", "d" + SUFFIX), //
Paths.get("1", "0", "e" + SUFFIX), //
Paths.get("1", "0", "f" + SUFFIX), //
Paths.get("1", "1", "g" + SUFFIX), //
Paths.get("1", "1", "h" + SUFFIX), //
Paths.get("2", "0", "i" + SUFFIX)// The first level might
Paths.get("0", "0", "a$" + SUFFIX), //
Paths.get("0", "0", "b$" + SUFFIX), //
Paths.get("0", "1", "c$" + SUFFIX), //
Paths.get("0", "1", "d$" + SUFFIX), //
Paths.get("1", "0", "e$" + SUFFIX), //
Paths.get("1", "0", "f$" + SUFFIX), //
Paths.get("1", "1", "g$" + SUFFIX), //
Paths.get("1", "1", "h$" + SUFFIX), //
Paths.get("2", "0", "i$" + SUFFIX)// The first level might
// overflow
);
@@ -65,10 +65,10 @@ public class FolderStorageTest {
final List<Path> actualFiles = getPathsRelativeToDataDirectory();
final List<Path> expectedFiles = Arrays.asList(//
Paths.get("0", "0", "a" + SUFFIX), //
Paths.get("0", "0", "a1" + SUFFIX), //
Paths.get("0", "0", "a2" + SUFFIX), //
Paths.get("0", "1", "a" + SUFFIX)//
Paths.get("0", "0", "a$" + SUFFIX), //
Paths.get("0", "0", "a$1" + SUFFIX), //
Paths.get("0", "0", "a$2" + SUFFIX), //
Paths.get("0", "1", "a$" + SUFFIX)//
);
Assert.assertEquals(actualFiles, expectedFiles);

View File

@@ -66,38 +66,38 @@ public class ProposerTest {
public void testEmptyQuery() throws Exception {
assertProposals("", 0, //
new Proposal("name", "name=*", true), //
new Proposal("bird", "bird=*", true), //
new Proposal("dog", "dog=*", true)//
new Proposal("name", "name=*", true, "name=", 5), //
new Proposal("bird", "bird=*", true, "bird=", 5), //
new Proposal("dog", "dog=*", true, "dog=", 4)//
);
assertProposals(" ", 1, //
new Proposal("name", "name=*", true), //
new Proposal("bird", "bird=*", true), //
new Proposal("dog", "dog=*", true)//
new Proposal("name", "name=*", true, "name=", 5), //
new Proposal("bird", "bird=*", true, "bird=", 5), //
new Proposal("dog", "dog=*", true, "dog=", 4)//
);
}
public void testPrefixOfKey() throws Exception {
assertProposals("bi", 2, //
new Proposal("bird", "bird=* ", true) //
new Proposal("bird", "bird=* ", true, "bird=", 5) //
);
assertProposals("bird", 4, //
new Proposal("bird", "bird=* ", true) //
new Proposal("bird", "bird=* ", true, "bird=", 5) //
);
}
public void testPrefixOfValue() throws Exception {
assertProposals("name =Tim", 9, //
new Proposal("Timothy", "name =Timothy ", true));
new Proposal("Timothy", "name =Timothy ", true, "name =Timothy ", 14));
assertProposals("name =Je", 8, //
new Proposal("Jennifer", "name =Jennifer ", true), //
new Proposal("Jenny", "name =Jenny ", true) //
new Proposal("Jennifer", "name =Jennifer ", true, "name =Jennifer ", 15), //
new Proposal("Jenny", "name =Jenny ", true, "name =Jenny ", 12) //
);
assertProposals("bird=eagle and n", 16, //
new Proposal("name", "bird=eagle and name=* ", true) //
new Proposal("name", "bird=eagle and name=* ", true, "bird=eagle and name=", 20) //
);
/*
*/
@@ -105,18 +105,18 @@ public class ProposerTest {
public void testProposalOnEmptyValuePrefix() throws Exception {
assertProposals("name=", 5, //
new Proposal("Jennifer", "name=Jennifer ", true), //
new Proposal("Jenny", "name=Jenny ", true), //
new Proposal("Tim", "name=Tim ", true), //
new Proposal("Timothy", "name=Timothy ", true) //
new Proposal("Jennifer", "name=Jennifer ", true, "name=Jennifer ", 14), //
new Proposal("Jenny", "name=Jenny ", true, "name=Jenny ", 11), //
new Proposal("Tim", "name=Tim ", true, "name=Tim ", 9), //
new Proposal("Timothy", "name=Timothy ", true, "name=Timothy ", 13) //
);
}
public void testProposalOnEmptyKeyPrefix() throws Exception {
assertProposals("name=* and ", 11, //
new Proposal("name", "name=* and name=* ", true), //
new Proposal("bird", "name=* and bird=* ", true), //
new Proposal("dog", "name=* and dog=* ", true) //
new Proposal("name", "name=* and name=* ", true, "name=* and name=", 16), //
new Proposal("bird", "name=* and bird=* ", true, "name=* and bird=", 16), //
new Proposal("dog", "name=* and dog=* ", true, "name=* and dog=", 15) //
);
}
@@ -130,6 +130,6 @@ public class ProposerTest {
System.out.println("\n\n--- " + query + " ---");
System.out.println("actual : " + actual);
System.out.println("expected: " + expectedList);
Assert.assertEquals(expectedList, actual);
Assert.assertEquals(actual, expectedList);
}
}