Skip to content

Commit

Permalink
CHE-1038: make Navigate To File feature not case-sensitive (#3573)
Browse files Browse the repository at this point in the history
  • Loading branch information
Valeriy Svydenko committed Jan 12, 2017
1 parent 8d2dc2b commit 5bf3d8c
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 31 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@
import org.apache.lucene.search.SearcherFactory;
import org.apache.lucene.search.SearcherManager;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.search.WildcardQuery;
import org.apache.lucene.store.Directory;
import org.apache.lucene.util.IOUtils;
import org.eclipse.che.api.core.ForbiddenException;
Expand Down Expand Up @@ -67,9 +66,11 @@
* @author andrew00x
*/
public abstract class LuceneSearcher implements Searcher {
private static final Logger LOG = LoggerFactory.getLogger(LuceneSearcher.class);

private static final int RESULT_LIMIT = 1000;
private static final Logger LOG = LoggerFactory.getLogger(LuceneSearcher.class);
private static final int RESULT_LIMIT = 1000;
private static final String PATH_FIELD = "path";
private static final String NAME_FIELD = "name";
private static final String TEXT_FIELD = "text";

private final List<VirtualFileFilter> excludeFileIndexFilters;
private final AbstractLuceneSearcherProvider.CloseCallback closeCallback;
Expand Down Expand Up @@ -207,7 +208,7 @@ public SearchResult search(QueryExpression query) throws ServerException {
List<SearchResultEntry> results = newArrayList();
for (int i = 0; i < topDocs.scoreDocs.length; i++) {
ScoreDoc scoreDoc = topDocs.scoreDocs[i];
String filePath = luceneSearcher.doc(scoreDoc.doc).getField("path").stringValue();
String filePath = luceneSearcher.doc(scoreDoc.doc).getField(PATH_FIELD).stringValue();
results.add(new SearchResultEntry(filePath));
}

Expand All @@ -225,7 +226,7 @@ public SearchResult search(QueryExpression query) throws ServerException {
.withNextPageQueryExpression(nextPageQueryExpression)
.withElapsedTimeMillis(elapsedTimeMillis)
.build();
} catch (IOException e) {
} catch (IOException | ParseException e) {
throw new ServerException(e.getMessage(), e);
} finally {
try {
Expand All @@ -236,25 +237,23 @@ public SearchResult search(QueryExpression query) throws ServerException {
}
}

private Query createLuceneQuery(QueryExpression query) throws ServerException {
private Query createLuceneQuery(QueryExpression query) throws ParseException {
final BooleanQuery luceneQuery = new BooleanQuery();
final String name = query.getName();
final String path = query.getPath();
final String text = query.getText();
if (path != null) {
luceneQuery.add(new PrefixQuery(new Term("path", path)), BooleanClause.Occur.MUST);
luceneQuery.add(new PrefixQuery(new Term(PATH_FIELD, path)), BooleanClause.Occur.MUST);
}
if (name != null) {
luceneQuery.add(new WildcardQuery(new Term("name", name)), BooleanClause.Occur.MUST);
QueryParser qParser = new QueryParser(NAME_FIELD, makeAnalyzer());
qParser.setAllowLeadingWildcard(true);
luceneQuery.add(qParser.parse(name), BooleanClause.Occur.MUST);
}
if (text != null) {
QueryParser qParser = new QueryParser("text", makeAnalyzer());
QueryParser qParser = new QueryParser(TEXT_FIELD, makeAnalyzer());
qParser.setAllowLeadingWildcard(true);
try {
luceneQuery.add(qParser.parse(text), BooleanClause.Occur.MUST);
} catch (ParseException e) {
throw new ServerException(e.getMessage());
}
luceneQuery.add(qParser.parse(text), BooleanClause.Occur.MUST);
}
return luceneQuery;
}
Expand Down Expand Up @@ -328,8 +327,8 @@ protected void addFile(VirtualFile virtualFile) throws ServerException {
try (Reader fContentReader = shouldIndexContent(virtualFile)
? new BufferedReader(new InputStreamReader(virtualFile.getContent()))
: null) {
getIndexWriter()
.updateDocument(new Term("path", virtualFile.getPath().toString()), createDocument(virtualFile, fContentReader));
getIndexWriter().updateDocument(new Term(PATH_FIELD, virtualFile.getPath().toString()),
createDocument(virtualFile, fContentReader));
} catch (OutOfMemoryError oome) {
close();
throw oome;
Expand All @@ -345,10 +344,10 @@ protected void addFile(VirtualFile virtualFile) throws ServerException {
public final void delete(String path, boolean isFile) throws ServerException {
try {
if (isFile) {
Term term = new Term("path", path);
Term term = new Term(PATH_FIELD, path);
getIndexWriter().deleteDocuments(term);
} else {
Term term = new Term("path", path + "/");
Term term = new Term(PATH_FIELD, path + '/');
getIndexWriter().deleteDocuments(new PrefixQuery(term));
}
} catch (OutOfMemoryError oome) {
Expand All @@ -361,7 +360,7 @@ public final void delete(String path, boolean isFile) throws ServerException {

@Override
public final void update(VirtualFile virtualFile) throws ServerException {
doUpdate(new Term("path", virtualFile.getPath().toString()), virtualFile);
doUpdate(new Term(PATH_FIELD, virtualFile.getPath().toString()), virtualFile);
}

protected void doUpdate(Term deleteTerm, VirtualFile virtualFile) throws ServerException {
Expand All @@ -381,10 +380,10 @@ protected void doUpdate(Term deleteTerm, VirtualFile virtualFile) throws ServerE

protected Document createDocument(VirtualFile virtualFile, Reader reader) throws ServerException {
final Document doc = new Document();
doc.add(new StringField("path", virtualFile.getPath().toString(), Field.Store.YES));
doc.add(new StringField("name", virtualFile.getName(), Field.Store.YES));
doc.add(new StringField(PATH_FIELD, virtualFile.getPath().toString(), Field.Store.YES));
doc.add(new TextField(NAME_FIELD, virtualFile.getName(), Field.Store.YES));
if (reader != null) {
doc.add(new TextField("text", reader));
doc.add(new TextField(TEXT_FIELD, reader));
}
return doc;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,24 +21,25 @@
import org.eclipse.che.api.vfs.search.SearchResult;
import org.eclipse.che.commons.lang.IoUtil;
import org.eclipse.che.commons.lang.NameGenerator;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentMatcher;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;

import java.io.File;
import java.util.Collections;
import java.util.List;

import static com.google.common.collect.Lists.newArrayList;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.argThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertTrue;

@SuppressWarnings("Duplicates")
public class FSLuceneSearcherTest {
Expand All @@ -54,7 +55,7 @@ public class FSLuceneSearcherTest {
private FSLuceneSearcher searcher;
private AbstractLuceneSearcherProvider.CloseCallback closeCallback;

@Before
@BeforeMethod
public void setUp() throws Exception {
File targetDir = new File(Thread.currentThread().getContextClassLoader().getResource(".").getPath()).getParentFile();
indexDirectory = new File(targetDir, NameGenerator.generate("index-", 4));
Expand All @@ -67,7 +68,7 @@ public void setUp() throws Exception {
searcher = new FSLuceneSearcher(indexDirectory, filter, closeCallback);
}

@After
@AfterMethod
public void tearDown() throws Exception {
searcher.close();
IoUtil.deleteRecursive(indexDirectory);
Expand Down Expand Up @@ -190,6 +191,34 @@ public void searchesByTextAndFileName() throws Exception {
assertEquals(newArrayList("/folder/xxx.txt"), paths);
}

@DataProvider
public Object[][] searchByName() {
return new Object[][]{
{"sameName.txt", "sameName.txt"},
{"notCaseSensitive.txt", "notcasesensitive.txt"},
{"fullName.txt", "full*"},
{"file name.txt", "file name"},
{"prefixFileName.txt", "prefixF*"},
{"name.with.dot.txt", "name.With.Dot.txt"},
};
}

@Test(dataProvider = "searchByName")
public void searchFileByName(String fileName, String searchedFileName) throws Exception {
VirtualFileSystem virtualFileSystem = virtualFileSystem();
VirtualFile folder = virtualFileSystem.getRoot().createFolder("parent/child");
VirtualFile folder2 = virtualFileSystem.getRoot().createFolder("folder2");
folder.createFile(NameGenerator.generate(null,10), TEST_CONTENT[3]);
folder.createFile(fileName, TEST_CONTENT[2]);
folder.createFile(NameGenerator.generate(null,10), TEST_CONTENT[1]);
folder2.createFile(NameGenerator.generate(null,10), TEST_CONTENT[2]);
folder2.createFile(NameGenerator.generate(null,10), TEST_CONTENT[2]);
searcher.init(virtualFileSystem);

List<String> paths = searcher.search(new QueryExpression().setName(searchedFileName)).getFilePaths();
assertEquals(newArrayList("/parent/child/" + fileName), paths);
}

@Test
public void searchesByTextAndPath() throws Exception {
VirtualFileSystem virtualFileSystem = virtualFileSystem();
Expand Down

0 comments on commit 5bf3d8c

Please sign in to comment.