implemented word search

This commit is contained in:
daniel oeh 2012-07-24 16:52:29 +02:00
parent 8bad211f68
commit 7d99031706
6 changed files with 111 additions and 26 deletions

View File

@ -145,6 +145,7 @@
<string name="search_results_label">Search results</string>
<string name="search_term_label">You searched:\u0020</string>
<string name="search_label">Search</string>
<string name="found_in_title_label">Found in title</string>
</resources>

View File

@ -69,7 +69,7 @@ public class SearchActivity extends SherlockListActivity {
Log.d(TAG, "Starting search");
String query = intent.getStringExtra(SearchManager.QUERY);
getSupportActionBar().setSubtitle(
getString(R.string.search_term_label) + query);
getString(R.string.search_term_label) + "\"" + query + "\"");
startSearch(query);
}
}

View File

@ -57,10 +57,13 @@ public class SearchlistAdapter extends ArrayAdapter<SearchResult> {
} else if (component.getClass() == FeedItem.class) {
FeedItem item = (FeedItem) component;
holder.title.setText(item.getTitle());
if (result.getSubtitle() != null) {
holder.subtitle.setVisibility(View.VISIBLE);
holder.subtitle.setText(result.getSubtitle());
}
FeedImageLoader.getInstance().loadBitmap(item.getFeed().getImage(),
holder.cover); }
holder.cover);
}
return convertView;
}

View File

@ -1,24 +1,36 @@
package de.danoeh.antennapod.feed;
import java.util.ArrayList;
import java.util.Collections;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import android.util.Log;
import de.danoeh.antennapod.AppConfig;
import de.danoeh.antennapod.PodcastApp;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.util.SearchResultValueComparator;
/** Performs search on Feeds and FeedItems */
public class FeedSearcher {
private static final String TAG = "FeedSearcher";
// Search result values
private static final int VALUE_FEED_TITLE = 3;
private static final int VALUE_ITEM_TITLE = 2;
private static final int VALUE_ITEM_CHAPTER = 1;
private static final int VALUE_ITEM_DESCRIPTION = 0;
private static final int VALUE_WORD_MATCH = 4;
/** Performs a search in all feeds or one specific feed. */
public static ArrayList<SearchResult> performSearch(final String query,
Feed selectedFeed) {
String lcQuery = query.toLowerCase();
ArrayList<SearchResult> result = new ArrayList<SearchResult>();
if (selectedFeed == null) {
if (AppConfig.DEBUG) Log.d(TAG, "Performing global search");
if (AppConfig.DEBUG)
Log.d(TAG, "Performing global search");
if (AppConfig.DEBUG)
Log.d(TAG, "Searching Feed titles");
searchFeedtitles(lcQuery, result);
@ -42,6 +54,10 @@ public class FeedSearcher {
Log.d(TAG, "Searching item content encoded data");
searchFeedItemContentEncoded(lcQuery, result, selectedFeed);
if (AppConfig.DEBUG)
Log.d(TAG, "Sorting results");
Collections.sort(result, new SearchResultValueComparator());
return result;
}
@ -49,8 +65,10 @@ public class FeedSearcher {
ArrayList<SearchResult> destination) {
FeedManager manager = FeedManager.getInstance();
for (Feed feed : manager.getFeeds()) {
if (feed.getTitle().toLowerCase().contains(query)) {
destination.add(new SearchResult(feed, null));
SearchResult result = createSearchResult(feed, query, feed
.getTitle().toLowerCase(), VALUE_FEED_TITLE);
if (result != null) {
destination.add(result);
}
}
}
@ -70,11 +88,14 @@ public class FeedSearcher {
private static void searchFeedItemTitlesSingleFeed(String query,
ArrayList<SearchResult> destination, Feed feed) {
for (FeedItem item : feed.getItems()) {
if (item.getTitle().toLowerCase().contains(query)) {
destination.add(new SearchResult(item, PodcastApp.getInstance()
.getString(R.string.found_in_label)
+ item.getFeed().getTitle()));
SearchResult result = createSearchResult(item, query, item
.getTitle().toLowerCase(), VALUE_ITEM_TITLE);
if (result != null) {
result.setSubtitle(PodcastApp.getInstance().getString(
R.string.found_in_title_label));
destination.add(result);
}
}
}
@ -95,10 +116,12 @@ public class FeedSearcher {
for (FeedItem item : feed.getItems()) {
if (item.getSimpleChapters() != null) {
for (SimpleChapter sc : item.getSimpleChapters()) {
if (sc.getTitle().toLowerCase().contains(query)) {
destination.add(new SearchResult(item, PodcastApp
.getInstance().getString(
R.string.found_in_chapters_label)));
SearchResult result = createSearchResult(item, query, sc
.getTitle().toLowerCase(), VALUE_ITEM_CHAPTER);
if (result != null) {
result.setSubtitle(PodcastApp.getInstance().getString(
R.string.found_in_chapters_label));
destination.add(result);
}
}
}
@ -121,10 +144,15 @@ public class FeedSearcher {
private static void searchFeedItemDescriptionSingleFeed(String query,
ArrayList<SearchResult> destination, Feed feed) {
for (FeedItem item : feed.getItems()) {
if (item.getDescription() != null
&& item.getDescription().toLowerCase().contains(query)) {
destination.add(new SearchResult(item, PodcastApp.getInstance()
.getString(R.string.found_in_shownotes_label)));
if (item.getDescription() != null) {
SearchResult result = createSearchResult(item, query, item
.getDescription().toLowerCase(), VALUE_ITEM_DESCRIPTION);
if (result != null) {
result.setSubtitle(PodcastApp.getInstance().getString(
R.string.found_in_shownotes_label));
destination.add(result);
}
}
}
}
@ -137,19 +165,47 @@ public class FeedSearcher {
searchFeedItemContentEncodedSingleFeed(query, destination, feed);
}
} else {
searchFeedItemContentEncodedSingleFeed(query, destination, selectedFeed);
searchFeedItemContentEncodedSingleFeed(query, destination,
selectedFeed);
}
}
private static void searchFeedItemContentEncodedSingleFeed(String query,
ArrayList<SearchResult> destination, Feed feed) {
for (FeedItem item : feed.getItems()) {
if (!destination.contains(item) && item.getContentEncoded() != null
&& item.getContentEncoded().toLowerCase().contains(query)) {
destination.add(new SearchResult(item, PodcastApp.getInstance()
.getString(R.string.found_in_shownotes_label)));
if (!destination.contains(item) && item.getContentEncoded() != null) {
SearchResult result = createSearchResult(item, query, item
.getContentEncoded().toLowerCase(),
VALUE_ITEM_DESCRIPTION);
if (result != null) {
result.setSubtitle(PodcastApp.getInstance().getString(
R.string.found_in_shownotes_label));
destination.add(result);
}
}
}
}
private static SearchResult createSearchResult(FeedComponent component,
String query, String text, int baseValue) {
int bonus = 0;
boolean found = false;
// try word search
Pattern word = Pattern.compile("\b" + query + "\b");
Matcher matcher = word.matcher(text);
found = matcher.find();
if (found) {
bonus = VALUE_WORD_MATCH;
} else {
// search for other occurence
found = text.contains(query);
}
if (found) {
return new SearchResult(component, baseValue + bonus);
} else {
return null;
}
}
}

View File

@ -4,11 +4,13 @@ public class SearchResult {
private FeedComponent component;
/** Additional information (e.g. where it was found) */
private String subtitle;
/** Higher value means more importance */
private int value;
public SearchResult(FeedComponent component, String subtitle) {
public SearchResult(FeedComponent component, int value) {
super();
this.component = component;
this.subtitle = subtitle;
this.value = value;
}
public FeedComponent getComponent() {
@ -19,4 +21,13 @@ public class SearchResult {
return subtitle;
}
public void setSubtitle(String subtitle) {
this.subtitle = subtitle;
}
public int getValue() {
return value;
}
}

View File

@ -0,0 +1,14 @@
package de.danoeh.antennapod.util;
import java.util.Comparator;
import de.danoeh.antennapod.feed.SearchResult;
public class SearchResultValueComparator implements Comparator<SearchResult> {
@Override
public int compare(SearchResult lhs, SearchResult rhs) {
return rhs.getValue() - lhs.getValue();
}
}