public void run() { StringBuilder patternString = new StringBuilder(); for (Iterator<Pattern> it = searchRequest.getSearchPatterns().iterator(); it.hasNext(); ) { Pattern pattern = it.next(); patternString.append(pattern.pattern()); if (it.hasNext()) { patternString.append(" AND "); } } logger.info("Starting search {} (pattern: {})", searchId, patternString); List<SearchResult> results = new ArrayList<>(); long searchStartTime = System.currentTimeMillis(); fireSearchStarted(); long count = 0; int total = searchMetadataCache.size(); int percent = 0; for (SearchMetadata searchMetadata : searchMetadataCache) { if (!isLatestSearch()) { // New search started logger.info(" Terminating search {} prematurely", searchId); return; } String text = searchMetadata.getSearchString(); boolean matchedAllPatterns = true; int startIndex = 0; ImmutableList.Builder<SearchResultMatch> matchesBuilder = ImmutableList.builder(); for (Pattern pattern : searchRequest.getSearchPatterns()) { if (startIndex >= text.length()) { matchedAllPatterns = false; break; } Matcher matcher = pattern.matcher(text); if (matcher.find()) { SearchResultMatch match = new SearchResultMatch(pattern, matcher.start(), matcher.end()); matchesBuilder.add(match); startIndex = matcher.end() + 1; } else { matchedAllPatterns = false; break; } } if (matchedAllPatterns) { results.add(new SearchResult(searchMetadata, matchesBuilder.build())); } count++; int nextPercent = (int) ((count * 100) / total); if (nextPercent != percent) { percent = nextPercent; fireSearchProgressed(percent, results.size()); } } SearchManager.this.fireSearchFinished(); long searchEndTime = System.currentTimeMillis(); long searchTime = searchEndTime - searchStartTime; logger.info( " Finished search {} in {} ms ({} results)", searchId, searchTime, results.size()); fireSearchFinished(results, searchResultHandler); }