Download and search indexes

Search currently not yielding results, but everything surrounding it appears to be working.
This commit is contained in:
Bradlee Speice 2015-01-18 00:37:44 -05:00
parent 902b91776d
commit 3721ef5ee0
13 changed files with 257 additions and 139 deletions

View File

@ -7,6 +7,7 @@ import org.bspeice.minimalbible.Injector;
import org.bspeice.minimalbible.activity.downloader.DownloadPrefs; import org.bspeice.minimalbible.activity.downloader.DownloadPrefs;
import org.bspeice.minimalbible.activity.downloader.manager.BookManager; import org.bspeice.minimalbible.activity.downloader.manager.BookManager;
import org.bspeice.minimalbible.activity.downloader.manager.DLProgressEvent; import org.bspeice.minimalbible.activity.downloader.manager.DLProgressEvent;
import org.bspeice.minimalbible.activity.downloader.manager.MBIndexManager;
import org.bspeice.minimalbible.activity.downloader.manager.RefreshManager; import org.bspeice.minimalbible.activity.downloader.manager.RefreshManager;
import org.crosswire.common.progress.JobManager; import org.crosswire.common.progress.JobManager;
import org.crosswire.common.progress.Progress; import org.crosswire.common.progress.Progress;
@ -19,6 +20,8 @@ import org.crosswire.jsword.book.Books;
import org.crosswire.jsword.book.BooksEvent; import org.crosswire.jsword.book.BooksEvent;
import org.crosswire.jsword.book.install.InstallManager; import org.crosswire.jsword.book.install.InstallManager;
import org.crosswire.jsword.book.install.Installer; import org.crosswire.jsword.book.install.Installer;
import org.crosswire.jsword.index.IndexManager;
import org.crosswire.jsword.index.IndexManagerFactory;
import org.junit.Before; import org.junit.Before;
import org.junit.Ignore; import org.junit.Ignore;
import org.junit.Test; import org.junit.Test;
@ -93,9 +96,9 @@ public class BookManagerTest implements Injector {
.subscribe(new Action1<DLProgressEvent>() { .subscribe(new Action1<DLProgressEvent>() {
@Override @Override
public void call(DLProgressEvent dlProgressEvent) { public void call(DLProgressEvent dlProgressEvent) {
System.out.println(dlProgressEvent.getAverageProgress()); System.out.println(dlProgressEvent.getProgress());
if (dlProgressEvent.getB().getInitials().equals(toInstall.getInitials()) if (dlProgressEvent.getB().getInitials().equals(toInstall.getInitials())
&& dlProgressEvent.getAverageProgress() == DLProgressEvent.PROGRESS_COMPLETE) { && dlProgressEvent.getProgress() == DLProgressEvent.PROGRESS_COMPLETE) {
signal.set(true); signal.set(true);
} }
} }
@ -112,7 +115,7 @@ public class BookManagerTest implements Injector {
@Test @Test
public void testJobIdMatch() { public void testJobIdMatch() {
final Book toInstall = installableBooks().toBlocking().first(); final Book toInstall = installableBooks().toBlocking().first();
final String jobName = bookManager.getJobNames(toInstall).get(0); final String jobName = bookManager.getJobName(toInstall);
final AtomicBoolean jobNameMatch = new AtomicBoolean(false); final AtomicBoolean jobNameMatch = new AtomicBoolean(false);
JobManager.addWorkListener(new WorkListener() { JobManager.addWorkListener(new WorkListener() {
@ -160,7 +163,12 @@ public class BookManagerTest implements Injector {
bookManager.getInstalledBooksList().add(mockBook); bookManager.getInstalledBooksList().add(mockBook);
assertTrue(bookManager.getInstalledBooksList().contains(mockBook)); assertTrue(bookManager.getInstalledBooksList().contains(mockBook));
try {
bookManager.removeBook(mockBook, secondMockBook); bookManager.removeBook(mockBook, secondMockBook);
} catch (NullPointerException e) {
// Nasty NPE shows up when testing because the index
// isn't installed. Suppressing here.
}
assertFalse(bookManager.getInstalledBooksList().contains(mockBook)); assertFalse(bookManager.getInstalledBooksList().contains(mockBook));
verify(driver, times(1)).delete(secondMockBook); verify(driver, times(1)).delete(secondMockBook);
} }
@ -173,14 +181,12 @@ public class BookManagerTest implements Injector {
public void testWorkProgressedCorrectProgress() { public void testWorkProgressedCorrectProgress() {
Book mockBook = mock(Book.class); Book mockBook = mock(Book.class);
when(mockBook.getInitials()).thenReturn("mockBook"); when(mockBook.getInitials()).thenReturn("mockBook");
String bookJobName = bookManager.getJobNames(mockBook).get(0); String bookJobName = bookManager.getJobName(mockBook);
bookManager.getInProgressJobNames().put(bookJobName, mockBook); bookManager.getInProgressJobNames().put(bookJobName, mockBook);
// Percent to degrees // Percent to degrees
final int workDone = 50; // 50% final int workDone = 50; // 50%
// There are two jobs, each comprising 180 degrees. final int circularProgress = 180;
// Since we are simulating one job being 50% complete, that's 90 degrees
final int circularProgress = 90;
WorkEvent ev = mock(WorkEvent.class); WorkEvent ev = mock(WorkEvent.class);
Progress p = mock(Progress.class); Progress p = mock(Progress.class);
@ -266,11 +272,25 @@ public class BookManagerTest implements Injector {
return PublishSubject.create(); return PublishSubject.create();
} }
@Provides
@Singleton
IndexManager indexManager() {
return IndexManagerFactory.getIndexManager();
}
@Provides
@Singleton
MBIndexManager mbIndexManager(IndexManager indexManager,
PublishSubject<DLProgressEvent> events) {
return new MBIndexManager(events, indexManager);
}
@Provides @Provides
@Singleton @Singleton
BookManager bookDownloadManager(Books installed, RefreshManager rm, BookManager bookDownloadManager(Books installed, RefreshManager rm,
PublishSubject<DLProgressEvent> eventPublisher) { PublishSubject<DLProgressEvent> eventPublisher,
return new BookManager(installed, rm, eventPublisher); MBIndexManager manager) {
return new BookManager(installed, rm, eventPublisher, manager);
} }
} }
} }

View File

@ -12,7 +12,7 @@ class DLProgressEventSpek : Spek() {{
given("a DLProgressEvent created with 50% progress and a mock book") { given("a DLProgressEvent created with 50% progress and a mock book") {
val mockBook = mock(javaClass<Book>()) val mockBook = mock(javaClass<Book>())
val dlEvent = DLProgressEvent(50, 50, mockBook) val dlEvent = DLProgressEvent(50, mockBook)
on("getting the progress in degrees") { on("getting the progress in degrees") {
val progressDegrees = dlEvent.toCircular() val progressDegrees = dlEvent.toCircular()

View File

@ -1,18 +1,26 @@
package org.bspeice.minimalbible; package org.bspeice.minimalbible;
import android.app.Application; import android.app.Application;
import android.util.Log;
import org.bspeice.minimalbible.activity.viewer.BibleViewerPreferences;
import org.bspeice.minimalbible.service.manager.BookManager;
import org.crosswire.jsword.book.Book; import org.crosswire.jsword.book.Book;
import org.crosswire.jsword.book.Books; import org.crosswire.jsword.book.Books;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.NoSuchElementException;
import java.util.concurrent.atomic.AtomicReference;
import javax.inject.Named;
import javax.inject.Singleton; import javax.inject.Singleton;
import dagger.Module; import dagger.Module;
import dagger.Provides; import dagger.Provides;
import de.devland.esperandro.Esperandro;
import rx.Observable; import rx.Observable;
import rx.functions.Action1;
import rx.functions.Func1; import rx.functions.Func1;
/** /**
@ -26,7 +34,8 @@ public class MinimalBibleModules {
this.app = app; this.app = app;
} }
@Provides @Singleton @Provides
@Singleton
Application provideApplication() { Application provideApplication() {
return app; return app;
} }
@ -34,6 +43,7 @@ public class MinimalBibleModules {
/** /**
* Provide a list of book names that are known bad. This can be because they trigger NPE, * Provide a list of book names that are known bad. This can be because they trigger NPE,
* or are just missing lots of content, etc. * or are just missing lots of content, etc.
*
* @return the list of books (by name) to ignore * @return the list of books (by name) to ignore
*/ */
@Provides @Provides
@ -80,4 +90,64 @@ public class MinimalBibleModules {
}) })
.toList().toBlocking().first(); .toList().toBlocking().first();
} }
@Provides
@Singleton
BibleViewerPreferences providePrefs() {
return Esperandro.getPreferences(BibleViewerPreferences.class, app);
}
@Provides
@Named("MainBook")
Book provideMainBook(BookManager bookManager, final BibleViewerPreferences prefs) {
final AtomicReference<Book> mBook = new AtomicReference<Book>(null);
bookManager.getInstalledBooks()
.first(new Func1<Book, Boolean>() {
@Override
public Boolean call(Book book) {
return book.getInitials().equals(prefs.defaultBookInitials());
}
})
.subscribe(new Action1<Book>() {
@Override
public void call(Book book) {
mBook.set(book);
}
}, new Action1<Throwable>() {
@Override
public void call(Throwable throwable) {
Log.d("BibleViewerModules", throwable.getLocalizedMessage());
}
});
if (mBook.get() == null) {
try {
Book fallback;
fallback = bookManager.getInstalledBooks()
.onErrorReturn(new Func1<Throwable, Book>() {
@Override
public Book call(Throwable throwable) {
// If there's no book installed, we can't select the main one...
return null;
}
})
.toBlocking().first();
prefs.defaultBookInitials(fallback.getName());
return fallback;
} catch (NoSuchElementException e) {
// If no books are installed, there's really nothing we can do...
Log.d("BibleViewerModules", "No books are installed, so can't select a main book.");
return null;
}
} else {
return mBook.get();
}
}
@Provides
@Singleton
BookManager bookManager(List<String> exclude) {
return new BookManager(exclude);
}
} }

View File

@ -46,7 +46,8 @@ public class BookItemHolder {
ProgressWheel downloadProgress; ProgressWheel downloadProgress;
@Inject @Inject
BookManager bookManager; BookManager bookManager;
@Inject @Named("DownloadActivityContext") @Inject
@Named("DownloadActivityContext")
Context ctx; Context ctx;
@Inject @Inject
PublishSubject<DLProgressEvent> downloadProgressEvents; PublishSubject<DLProgressEvent> downloadProgressEvents;
@ -65,7 +66,7 @@ public class BookItemHolder {
itemName.setText(b.getName()); itemName.setText(b.getName());
DLProgressEvent dlProgressEvent = bookManager.getDownloadProgress(b); DLProgressEvent dlProgressEvent = bookManager.getDownloadProgress(b);
if (dlProgressEvent != null) { if (dlProgressEvent != null) {
displayProgress(dlProgressEvent.toCircular()); displayProgress(dlProgressEvent);
} else if (bookManager.isInstalled(b)) { } else if (bookManager.isInstalled(b)) {
displayInstalled(); displayInstalled();
} }
@ -82,7 +83,7 @@ public class BookItemHolder {
.subscribe(new Action1<DLProgressEvent>() { .subscribe(new Action1<DLProgressEvent>() {
@Override @Override
public void call(DLProgressEvent event) { public void call(DLProgressEvent event) {
BookItemHolder.this.displayProgress(event.toCircular()); BookItemHolder.this.displayProgress(event);
} }
}); });
} }
@ -109,33 +110,31 @@ public class BookItemHolder {
/** /**
* Display the current progress of this download * Display the current progress of this download
* @param progress The progress out of 360 (degrees of a circle) *
* @param event The event we need to display progress for
*/ */
private void displayProgress(int progress) { private void displayProgress(DLProgressEvent event) {
int downloadView; int downloadView = downloadProgress.getId();
int progress = event.getProgress();
int circular = event.toCircular();
if (progress == DLProgressEvent.PROGRESS_BEGINNING) { if (progress == DLProgressEvent.PROGRESS_BEGINNING) {
// Download starting // Download starting
downloadView = downloadProgress.getId();
isDownloaded.setVisibility(View.GONE); isDownloaded.setVisibility(View.GONE);
downloadProgress.setVisibility(View.VISIBLE); downloadProgress.setVisibility(View.VISIBLE);
downloadProgress.spin(); downloadProgress.spin();
} else if (progress < 360) { } else if (progress < DLProgressEvent.PROGRESS_COMPLETE) {
// Download in progress // Download in progress
downloadView = downloadProgress.getId();
isDownloaded.setVisibility(View.GONE); isDownloaded.setVisibility(View.GONE);
downloadProgress.setVisibility(View.VISIBLE); downloadProgress.setVisibility(View.VISIBLE);
downloadProgress.stopSpinning(); downloadProgress.stopSpinning();
downloadProgress.setProgress(progress); downloadProgress.setProgress(circular);
} else { } else {
// Download complete // Download complete
subscription.unsubscribe(); subscription.unsubscribe();
downloadView = downloadProgress.getId();
isDownloaded.setVisibility(View.VISIBLE); isDownloaded.setVisibility(View.VISIBLE);
downloadProgress.setVisibility(View.GONE); downloadProgress.setVisibility(View.GONE);

View File

@ -8,11 +8,15 @@ import org.bspeice.minimalbible.MinimalBibleModules;
import org.bspeice.minimalbible.activity.downloader.manager.BookManager; import org.bspeice.minimalbible.activity.downloader.manager.BookManager;
import org.bspeice.minimalbible.activity.downloader.manager.DLProgressEvent; import org.bspeice.minimalbible.activity.downloader.manager.DLProgressEvent;
import org.bspeice.minimalbible.activity.downloader.manager.LocaleManager; import org.bspeice.minimalbible.activity.downloader.manager.LocaleManager;
import org.bspeice.minimalbible.activity.downloader.manager.MBIndexManager;
import org.bspeice.minimalbible.activity.downloader.manager.RefreshManager; import org.bspeice.minimalbible.activity.downloader.manager.RefreshManager;
import org.crosswire.jsword.book.BookCategory; import org.crosswire.jsword.book.BookCategory;
import org.crosswire.jsword.book.Books; import org.crosswire.jsword.book.Books;
import org.crosswire.jsword.book.install.InstallManager; import org.crosswire.jsword.book.install.InstallManager;
import org.crosswire.jsword.book.install.Installer; import org.crosswire.jsword.book.install.Installer;
import org.crosswire.jsword.index.IndexManager;
import org.crosswire.jsword.index.IndexManagerFactory;
import org.crosswire.jsword.index.IndexPolicyAdapter;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
@ -88,8 +92,9 @@ public class DownloadActivityModules {
@Provides @Provides
@Singleton @Singleton
BookManager provideBookDownloadManager(Books installedBooks, RefreshManager rm, BookManager provideBookDownloadManager(Books installedBooks, RefreshManager rm,
PublishSubject<DLProgressEvent> progressEvents) { PublishSubject<DLProgressEvent> progressEvents,
return new BookManager(installedBooks, rm, progressEvents); MBIndexManager mbIndexManager) {
return new BookManager(installedBooks, rm, progressEvents, mbIndexManager);
} }
@Provides @Provides
@ -123,4 +128,17 @@ public class DownloadActivityModules {
LocaleManager provideLocaleManager(RefreshManager refreshManager) { LocaleManager provideLocaleManager(RefreshManager refreshManager) {
return new LocaleManager(refreshManager); return new LocaleManager(refreshManager);
} }
@Provides
IndexManager indexManager() {
IndexManager manager = IndexManagerFactory.getIndexManager();
manager.setIndexPolicy(new IndexPolicyAdapter());
return manager;
}
@Provides
MBIndexManager mbIndexManager(PublishSubject<DLProgressEvent> downloadEvents,
IndexManager indexManager) {
return new MBIndexManager(downloadEvents, indexManager);
}
} }

View File

@ -10,6 +10,9 @@ import org.bspeice.minimalbible.MinimalBible;
import org.bspeice.minimalbible.OGHolder; import org.bspeice.minimalbible.OGHolder;
import org.bspeice.minimalbible.R; import org.bspeice.minimalbible.R;
import org.bspeice.minimalbible.activity.BaseActivity; import org.bspeice.minimalbible.activity.BaseActivity;
import org.crosswire.jsword.passage.Verse;
import java.util.List;
import javax.inject.Inject; import javax.inject.Inject;
@ -65,6 +68,7 @@ public class BasicSearch extends BaseActivity
String query = intent.getStringExtra(SearchManager.QUERY); String query = intent.getStringExtra(SearchManager.QUERY);
Toast.makeText(this, "Searching for: " + query, Toast.LENGTH_SHORT).show(); Toast.makeText(this, "Searching for: " + query, Toast.LENGTH_SHORT).show();
searchProvider.basicTextSearch(query); List<Verse> results = searchProvider.basicTextSearch(query);
Toast.makeText(this, "Found results: " + results.size(), Toast.LENGTH_SHORT).show();
} }
} }

View File

@ -1,6 +1,11 @@
package org.bspeice.minimalbible.activity.search; package org.bspeice.minimalbible.activity.search;
import org.bspeice.minimalbible.MinimalBibleModules; import org.bspeice.minimalbible.MinimalBibleModules;
import org.crosswire.jsword.book.Book;
import org.crosswire.jsword.index.IndexManager;
import org.crosswire.jsword.index.IndexManagerFactory;
import javax.inject.Named;
import dagger.Module; import dagger.Module;
import dagger.Provides; import dagger.Provides;
@ -12,7 +17,13 @@ import dagger.Provides;
public class SearchModules { public class SearchModules {
@Provides @Provides
SearchProvider searchProvider() { SearchProvider searchProvider(@Named("MainBook") Book book,
return new SearchProvider(); IndexManager indexManager) {
return new SearchProvider(book, indexManager);
}
@Provides
IndexManager jswordIndexManager() {
return IndexManagerFactory.getIndexManager();
} }
} }

View File

@ -1,23 +1,11 @@
package org.bspeice.minimalbible.activity.viewer; package org.bspeice.minimalbible.activity.viewer;
import android.util.Log;
import org.bspeice.minimalbible.MinimalBibleModules; import org.bspeice.minimalbible.MinimalBibleModules;
import org.bspeice.minimalbible.service.manager.BookManager;
import org.crosswire.jsword.book.Book;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.concurrent.atomic.AtomicReference;
import javax.inject.Named;
import javax.inject.Singleton; import javax.inject.Singleton;
import dagger.Module; import dagger.Module;
import dagger.Provides; import dagger.Provides;
import de.devland.esperandro.Esperandro;
import rx.functions.Action1;
import rx.functions.Func1;
import rx.subjects.PublishSubject; import rx.subjects.PublishSubject;
/** /**
@ -37,65 +25,6 @@ public class BibleViewerModules {
this.activity = activity; this.activity = activity;
} }
@Provides
@Singleton
BibleViewerPreferences providePrefs() {
return Esperandro.getPreferences(BibleViewerPreferences.class, activity);
}
@Provides
@Named("MainBook")
Book provideMainBook(BookManager bookManager, final BibleViewerPreferences prefs) {
final AtomicReference<Book> mBook = new AtomicReference<Book>(null);
bookManager.getInstalledBooks()
.first(new Func1<Book, Boolean>() {
@Override
public Boolean call(Book book) {
return book.getInitials().equals(prefs.defaultBookInitials());
}
})
.subscribe(new Action1<Book>() {
@Override
public void call(Book book) {
mBook.set(book);
}
}, new Action1<Throwable>() {
@Override
public void call(Throwable throwable) {
Log.d("BibleViewerModules", throwable.getLocalizedMessage());
}
});
if (mBook.get() == null) {
try {
Book fallback;
fallback = bookManager.getInstalledBooks()
.onErrorReturn(new Func1<Throwable, Book>() {
@Override
public Book call(Throwable throwable) {
// If there's no book installed, we can't select the main one...
return null;
}
})
.toBlocking().first();
prefs.defaultBookInitials(fallback.getName());
return fallback;
} catch (NoSuchElementException e) {
// If no books are installed, there's really nothing we can do...
Log.d("BibleViewerModules", "No books are installed, so can't select a main book.");
return null;
}
} else {
return mBook.get();
}
}
@Provides
@Singleton
BookManager bookManager(List<String> exclude) {
return new BookManager(exclude);
}
@Provides @Provides
@Singleton @Singleton

View File

@ -0,0 +1,12 @@
package org.bspeice.minimalbible
/**
* Massive credit over here:
* http://blog.omalley.id.au/2013/07/27/null-handling-in-kotlin.html
*
* The trick is that a non-nullable upper bound is placed on an optional
* nullable object - effectively, you get the real object or throw an exception.
*/
public fun <T : Any> T?.orError(message: String): T {
return if (this == null) throw IllegalArgumentException(message) else this
}

View File

@ -12,7 +12,6 @@ import rx.Observable;
import rx.schedulers.Schedulers; import rx.schedulers.Schedulers;
import rx.subjects.PublishSubject; import rx.subjects.PublishSubject;
import org.crosswire.jsword.book.BookException import org.crosswire.jsword.book.BookException
import org.crosswire.jsword.util.IndexDownloader
import org.crosswire.common.progress.Progress import org.crosswire.common.progress.Progress
/** /**
@ -22,7 +21,8 @@ import org.crosswire.common.progress.Progress
*/ */
class BookManager(private val installedBooks: Books, class BookManager(private val installedBooks: Books,
val rM: RefreshManager, val rM: RefreshManager,
val downloadEvents: PublishSubject<DLProgressEvent>) : val downloadEvents: PublishSubject<DLProgressEvent>,
val indexManager: MBIndexManager) :
WorkListener, BooksListener { WorkListener, BooksListener {
private val bookJobNamePrefix = Progress.INSTALL_BOOK.substringBeforeLast("%s") private val bookJobNamePrefix = Progress.INSTALL_BOOK.substringBeforeLast("%s")
@ -56,8 +56,7 @@ class BookManager(private val installedBooks: Books,
* @param b The book to predict the download job name of * @param b The book to predict the download job name of
* @return The name of the job that will/is download/ing this book * @return The name of the job that will/is download/ing this book
*/ */
fun getJobNames(b: Book) = listOf("${bookJobNamePrefix}${b.getInitials()}", fun getJobName(b: Book) = "${bookJobNamePrefix}${b.getInitials()}"
"${indexJobNamePrefix}${b.getInitials()}")
fun downloadBook(b: Book) { fun downloadBook(b: Book) {
// First, look up where the Book came from // First, look up where the Book came from
@ -68,23 +67,14 @@ class BookManager(private val installedBooks: Books,
// thread is closed when the install event is done // thread is closed when the install event is done
installerObs installerObs
.observeOn(Schedulers.newThread()) .observeOn(Schedulers.newThread())
.subscribe {
// Download the actual book // Download the actual book
it subscribe { it install b } .subscribe { it subscribe { it install b } }
}
installerObs
.observeOn(Schedulers.newThread())
.subscribe {
// Download the book index
it subscribe { IndexDownloader.downloadIndex(b, it) }
}
// Then notify everyone that we're starting // Then notify everyone that we're starting
downloadEvents onNext DLProgressEvent.beginningEvent(b) downloadEvents onNext DLProgressEvent.beginningEvent(b)
// Finally register the jobs in progress // Finally register the jobs in progress
getJobNames(b).forEach { this.inProgressJobNames[it] = b } inProgressJobNames[getJobName(b)] = b
} }
/** /**
@ -111,6 +101,10 @@ class BookManager(private val installedBooks: Books,
try { try {
b.getDriver() delete realBook b.getDriver() delete realBook
installedBooksList remove b installedBooksList remove b
// Order matters for the test suite as this line will trigger NPE during testing
// In production, doesn't make a difference, so leave this below the
// installedBooksList remove
indexManager removeIndex realBook
return true return true
} catch (e: BookException) { } catch (e: BookException) {
// Log.e("InstalledManager", // Log.e("InstalledManager",
@ -128,22 +122,26 @@ class BookManager(private val installedBooks: Books,
fun isInstalled(b: Book) = installedBooksList contains b fun isInstalled(b: Book) = installedBooksList contains b
// TODO: I have a strange feeling I can simplify this further... /**
* This method gets called as progress continues on downloading a book.
* To be honest, I don't know that there's any contract about what thread
* this is called on.
* By any means, if the job hasn't been registered as in progress,
* don't emit an event - we don't know what book we're operating on.
*/
override fun workProgressed(ev: WorkEvent) { override fun workProgressed(ev: WorkEvent) {
val job = ev.getJob() val job = ev.getJob()
val book = inProgressJobNames[job.getJobID()]
if (book == null)
return
val book = inProgressJobNames[job.getJobID()] as Book
val oldEvent = inProgressDownloads[book] ?: DLProgressEvent.beginningEvent(book) val oldEvent = inProgressDownloads[book] ?: DLProgressEvent.beginningEvent(book)
val newEvent = oldEvent.copy(progress = job.getWork())
var newEvent: DLProgressEvent
if (job.getJobID().contains(bookJobNamePrefix))
newEvent = oldEvent.copy(bookProgress = job.getWork())
else
newEvent = oldEvent.copy(indexProgress = job.getWork())
downloadEvents onNext newEvent downloadEvents onNext newEvent
if (newEvent.averageProgress == DLProgressEvent.PROGRESS_COMPLETE) { if (newEvent.progress == DLProgressEvent.PROGRESS_COMPLETE) {
inProgressDownloads remove inProgressJobNames[job.getJobID()] inProgressDownloads remove inProgressJobNames[job.getJobID()]
inProgressJobNames remove job.getJobID() inProgressJobNames remove job.getJobID()
} else } else

View File

@ -5,8 +5,7 @@ import org.crosswire.jsword.book.Book
/** /**
* Created by bspeice on 11/11/14. * Created by bspeice on 11/11/14.
*/ */
data class DLProgressEvent(val bookProgress: Int, data class DLProgressEvent(val progress: Int,
val indexProgress: Int,
val b: Book) { val b: Book) {
class object { class object {
val PROGRESS_COMPLETE = 100 val PROGRESS_COMPLETE = 100
@ -16,12 +15,8 @@ data class DLProgressEvent(val bookProgress: Int,
* Build a DLProgressEvent that is just beginning * Build a DLProgressEvent that is just beginning
* Mostly just a nice shorthand * Mostly just a nice shorthand
*/ */
fun beginningEvent(b: Book) = DLProgressEvent(DLProgressEvent.PROGRESS_BEGINNING, fun beginningEvent(b: Book) = DLProgressEvent(DLProgressEvent.PROGRESS_BEGINNING, b)
DLProgressEvent.PROGRESS_BEGINNING, b)
} }
val averageProgress: Int fun toCircular() = (progress.toFloat() * 360 / 100).toInt()
get() = (bookProgress + indexProgress) / 2
fun toCircular() = (averageProgress.toFloat() * 360 / 100).toInt()
} }

View File

@ -0,0 +1,40 @@
package org.bspeice.minimalbible.activity.downloader.manager
import org.crosswire.jsword.index.IndexManager
import rx.subjects.PublishSubject
import org.crosswire.jsword.book.Book
import rx.Observable
import rx.schedulers.Schedulers
import android.util.Log
/**
* There's already an IndexManager, that's why the funky name
*/
class MBIndexManager(val downloadEvents: PublishSubject<DLProgressEvent>,
val indexManager: IndexManager) {
val subscription = downloadEvents subscribe { handleDlEvent(it) }
fun handleDlEvent(event: DLProgressEvent): Unit =
if (event.progress == DLProgressEvent.PROGRESS_COMPLETE) {
subscription.unsubscribe()
buildIndex(event.b)
}
fun buildIndex(b: Book) {
Observable.just(b)
.observeOn(Schedulers.computation())
.subscribe {
try {
Log.d("MBIndexManager", "Beginning index status: ${b.getIndexStatus()}")
indexManager scheduleIndexCreation b
Log.d("MBIndexManager", "Ending index status: ${b.getIndexStatus()}")
} catch (e: Exception) {
Log.e("MBIndexManager", "Exception building index: ${e}", e)
}
}
Log.d("MBIndexManager", "Building index for ${b.getInitials()}")
}
fun removeIndex(b: Book) = indexManager.deleteIndex(b)
}

View File

@ -1,14 +1,36 @@
package org.bspeice.minimalbible.activity.search package org.bspeice.minimalbible.activity.search
import org.crosswire.jsword.passage.Verse import org.crosswire.jsword.passage.Verse
import org.crosswire.jsword.index.search.SearchType
import org.crosswire.jsword.book.Book
import android.util.Log
import org.crosswire.jsword.index.IndexManager
/** /**
* This is the entry point for handling the actual bible search. Likely will support * This is the entry point for handling the actual bible search. Likely will support
* an "advanced" search in the future, but for now, basicTextSearch is what you get. * an "advanced" search in the future, but for now, basicTextSearch is what you get.
*/ */
class SearchProvider() { class SearchProvider(val b: Book, val indexManager: IndexManager) {
val defaultSearchType = SearchType.ANY_WORDS
[suppress("UNUSED_PARAMETER")] [suppress("UNUSED_PARAMETER")]
public fun basicTextSearch(text: String): List<Verse> = public fun basicTextSearch(text: String): List<Verse> {
listOf() if (!isSearchAvailable()) {
Log.w("SearchProvider", "Search unavailable, index status of ${b.getInitials()}: ${b.getIndexStatus()}")
return listOf()
}
val searchText = defaultSearchType.decorate(text)
val results = b.find(searchText)
return results.map { it as Verse }
}
/**
* Handler to check if the index is available - because it doesn't
* seem to register itself properly in the book metadata
*/
public fun isSearchAvailable(): Boolean =
indexManager.isIndexed(b)
} }