/*
* Copyright (C) 2013 Alex Kuiper
*
* This file is part of PageTurner
*
* PageTurner is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* PageTurner is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with PageTurner. If not, see <http://www.gnu.org/licenses/>.*
*/
package net.nightwhistler.pageturner.epub;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
import jedi.option.Option;
import net.nightwhistler.htmlspanner.HtmlSpanner;
import net.nightwhistler.htmlspanner.SpanStack;
import net.nightwhistler.htmlspanner.TagNodeHandler;
import net.nightwhistler.htmlspanner.handlers.TableHandler;
import net.nightwhistler.pageturner.dto.SearchResult;
import net.nightwhistler.pageturner.scheduling.QueueableAsyncTask;
import nl.siegmann.epublib.domain.Book;
import nl.siegmann.epublib.domain.Resource;
import org.htmlcleaner.TagNode;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import static jedi.functional.FunctionalPrimitives.isEmpty;
import static jedi.option.Options.none;
import static jedi.option.Options.option;
public class SearchTextTask extends QueueableAsyncTask<String, SearchResult, List<SearchResult>> {
private Book book;
private HtmlSpanner spanner;
public SearchTextTask(Book book) {
this.book = book;
this.spanner = new HtmlSpanner();
DummyHandler dummy = new DummyHandler();
spanner.registerHandler("img", dummy );
spanner.registerHandler("image", dummy );
spanner.registerHandler("table", new TableHandler() );
}
@Override
public Option<List<SearchResult>> doInBackground(String... params) {
String searchTerm = params[0];
Pattern pattern = Pattern.compile(Pattern.quote((searchTerm)),Pattern.CASE_INSENSITIVE);
List<SearchResult> result = new ArrayList<>();
try {
PageTurnerSpine spine = new PageTurnerSpine(book);
for ( int index=0; index < spine.size(); index++ ) {
spine.navigateByIndex(index);
publishProgress( new SearchResult(null, null, index, 0, 0) );
Option<Resource> currentResource = spine.getCurrentResource();
if ( ! isEmpty(currentResource) ) {
Spanned spanned = spanner.fromHtml( currentResource.unsafeGet().getReader());
Matcher matcher = pattern.matcher(spanned);
while (matcher.find()) {
int from = Math.max(0, matcher.start() - 20);
int to = Math.min(spanned.length() - 1, matcher.end() + 20);
if (isCancelled()) {
return none();
}
String text = "…" + spanned.subSequence(from, to).toString().trim() + "…";
SearchResult res = new SearchResult(searchTerm, text, index, matcher.start(), matcher.end());
this.publishProgress(res);
result.add(res);
}
} else {
return none();
}
}
} catch (IOException io) {
return none();
}
return option(result);
}
private static class DummyHandler extends TagNodeHandler {
@Override
public void handleTagNode(TagNode node, SpannableStringBuilder builder,
int start, int end, SpanStack stack) {
builder.append("\uFFFC");
}
}
}