mirror of
https://github.com/MinimalBible/MinimalBible
synced 2025-07-04 15:25:14 -04:00
Download and search indexes
Search currently not yielding results, but everything surrounding it appears to be working.
This commit is contained in:
12
app/src/main/kotlin/org/bspeice/minimalbible/CommonUtil.kt
Normal file
12
app/src/main/kotlin/org/bspeice/minimalbible/CommonUtil.kt
Normal 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
|
||||
}
|
@ -12,7 +12,6 @@ import rx.Observable;
|
||||
import rx.schedulers.Schedulers;
|
||||
import rx.subjects.PublishSubject;
|
||||
import org.crosswire.jsword.book.BookException
|
||||
import org.crosswire.jsword.util.IndexDownloader
|
||||
import org.crosswire.common.progress.Progress
|
||||
|
||||
/**
|
||||
@ -22,7 +21,8 @@ import org.crosswire.common.progress.Progress
|
||||
*/
|
||||
class BookManager(private val installedBooks: Books,
|
||||
val rM: RefreshManager,
|
||||
val downloadEvents: PublishSubject<DLProgressEvent>) :
|
||||
val downloadEvents: PublishSubject<DLProgressEvent>,
|
||||
val indexManager: MBIndexManager) :
|
||||
WorkListener, BooksListener {
|
||||
|
||||
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
|
||||
* @return The name of the job that will/is download/ing this book
|
||||
*/
|
||||
fun getJobNames(b: Book) = listOf("${bookJobNamePrefix}${b.getInitials()}",
|
||||
"${indexJobNamePrefix}${b.getInitials()}")
|
||||
fun getJobName(b: Book) = "${bookJobNamePrefix}${b.getInitials()}"
|
||||
|
||||
fun downloadBook(b: Book) {
|
||||
// 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
|
||||
installerObs
|
||||
.observeOn(Schedulers.newThread())
|
||||
.subscribe {
|
||||
// Download the actual book
|
||||
it subscribe { it install b }
|
||||
}
|
||||
|
||||
installerObs
|
||||
.observeOn(Schedulers.newThread())
|
||||
.subscribe {
|
||||
// Download the book index
|
||||
it subscribe { IndexDownloader.downloadIndex(b, it) }
|
||||
}
|
||||
// Download the actual book
|
||||
.subscribe { it subscribe { it install b } }
|
||||
|
||||
// Then notify everyone that we're starting
|
||||
downloadEvents onNext DLProgressEvent.beginningEvent(b)
|
||||
|
||||
// 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 {
|
||||
b.getDriver() delete realBook
|
||||
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
|
||||
} catch (e: BookException) {
|
||||
// Log.e("InstalledManager",
|
||||
@ -128,22 +122,26 @@ class BookManager(private val installedBooks: Books,
|
||||
|
||||
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) {
|
||||
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)
|
||||
|
||||
var newEvent: DLProgressEvent
|
||||
if (job.getJobID().contains(bookJobNamePrefix))
|
||||
newEvent = oldEvent.copy(bookProgress = job.getWork())
|
||||
else
|
||||
newEvent = oldEvent.copy(indexProgress = job.getWork())
|
||||
val newEvent = oldEvent.copy(progress = job.getWork())
|
||||
|
||||
downloadEvents onNext newEvent
|
||||
|
||||
if (newEvent.averageProgress == DLProgressEvent.PROGRESS_COMPLETE) {
|
||||
if (newEvent.progress == DLProgressEvent.PROGRESS_COMPLETE) {
|
||||
inProgressDownloads remove inProgressJobNames[job.getJobID()]
|
||||
inProgressJobNames remove job.getJobID()
|
||||
} else
|
||||
|
@ -5,8 +5,7 @@ import org.crosswire.jsword.book.Book
|
||||
/**
|
||||
* Created by bspeice on 11/11/14.
|
||||
*/
|
||||
data class DLProgressEvent(val bookProgress: Int,
|
||||
val indexProgress: Int,
|
||||
data class DLProgressEvent(val progress: Int,
|
||||
val b: Book) {
|
||||
class object {
|
||||
val PROGRESS_COMPLETE = 100
|
||||
@ -16,12 +15,8 @@ data class DLProgressEvent(val bookProgress: Int,
|
||||
* Build a DLProgressEvent that is just beginning
|
||||
* Mostly just a nice shorthand
|
||||
*/
|
||||
fun beginningEvent(b: Book) = DLProgressEvent(DLProgressEvent.PROGRESS_BEGINNING,
|
||||
DLProgressEvent.PROGRESS_BEGINNING, b)
|
||||
fun beginningEvent(b: Book) = DLProgressEvent(DLProgressEvent.PROGRESS_BEGINNING, b)
|
||||
}
|
||||
|
||||
val averageProgress: Int
|
||||
get() = (bookProgress + indexProgress) / 2
|
||||
|
||||
fun toCircular() = (averageProgress.toFloat() * 360 / 100).toInt()
|
||||
fun toCircular() = (progress.toFloat() * 360 / 100).toInt()
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
@ -1,14 +1,36 @@
|
||||
package org.bspeice.minimalbible.activity.search
|
||||
|
||||
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
|
||||
* 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")]
|
||||
public fun basicTextSearch(text: String): List<Verse> =
|
||||
listOf()
|
||||
public fun basicTextSearch(text: String): List<Verse> {
|
||||
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)
|
||||
|
||||
}
|
||||
|
Reference in New Issue
Block a user