mirror of
				https://github.com/MinimalBible/MinimalBible
				synced 2025-11-04 02:20:26 -05:00 
			
		
		
		
	Kotlin migration is done!
There will of course be refactoring and whatnot, but I consider this an accomplishment.
This commit is contained in:
		@ -2,7 +2,8 @@ package org.bspeice.minimalbible.activity.viewer;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import android.util.Log;
 | 
					import android.util.Log;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import org.bspeice.minimalbible.service.book.VerseLookupModules;
 | 
					import org.bspeice.minimalbible.service.lookup.DefaultVerseLookup;
 | 
				
			||||||
 | 
					import org.bspeice.minimalbible.service.lookup.VerseLookup;
 | 
				
			||||||
import org.bspeice.minimalbible.service.manager.BookManager;
 | 
					import org.bspeice.minimalbible.service.manager.BookManager;
 | 
				
			||||||
import org.crosswire.jsword.book.Book;
 | 
					import org.crosswire.jsword.book.Book;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -26,8 +27,7 @@ import rx.functions.Func1;
 | 
				
			|||||||
                BibleViewer.class,
 | 
					                BibleViewer.class,
 | 
				
			||||||
                BookFragment.class,
 | 
					                BookFragment.class,
 | 
				
			||||||
                BookChapterNavFragment.class
 | 
					                BookChapterNavFragment.class
 | 
				
			||||||
        },
 | 
					        }
 | 
				
			||||||
        includes = VerseLookupModules.class
 | 
					 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
@SuppressWarnings("unused")
 | 
					@SuppressWarnings("unused")
 | 
				
			||||||
public class BibleViewerModules {
 | 
					public class BibleViewerModules {
 | 
				
			||||||
@ -96,4 +96,10 @@ public class BibleViewerModules {
 | 
				
			|||||||
    BookManager bookManager() {
 | 
					    BookManager bookManager() {
 | 
				
			||||||
        return new BookManager();
 | 
					        return new BookManager();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Provides
 | 
				
			||||||
 | 
					    @Singleton
 | 
				
			||||||
 | 
					    VerseLookup verseLookup(@Named("MainBook") Book b) {
 | 
				
			||||||
 | 
					        return new DefaultVerseLookup(b);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -12,7 +12,7 @@ import android.webkit.WebView;
 | 
				
			|||||||
import org.bspeice.minimalbible.Injector;
 | 
					import org.bspeice.minimalbible.Injector;
 | 
				
			||||||
import org.bspeice.minimalbible.R;
 | 
					import org.bspeice.minimalbible.R;
 | 
				
			||||||
import org.bspeice.minimalbible.activity.BaseFragment;
 | 
					import org.bspeice.minimalbible.activity.BaseFragment;
 | 
				
			||||||
import org.bspeice.minimalbible.service.book.VerseLookupService;
 | 
					import org.bspeice.minimalbible.service.lookup.VerseLookup;
 | 
				
			||||||
import org.crosswire.jsword.book.Book;
 | 
					import org.crosswire.jsword.book.Book;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import javax.inject.Inject;
 | 
					import javax.inject.Inject;
 | 
				
			||||||
@ -20,7 +20,6 @@ import javax.inject.Named;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import butterknife.ButterKnife;
 | 
					import butterknife.ButterKnife;
 | 
				
			||||||
import butterknife.InjectView;
 | 
					import butterknife.InjectView;
 | 
				
			||||||
import dagger.Lazy;
 | 
					 | 
				
			||||||
import rx.android.schedulers.AndroidSchedulers;
 | 
					import rx.android.schedulers.AndroidSchedulers;
 | 
				
			||||||
import rx.functions.Action1;
 | 
					import rx.functions.Action1;
 | 
				
			||||||
import rx.subjects.PublishSubject;
 | 
					import rx.subjects.PublishSubject;
 | 
				
			||||||
@ -35,18 +34,15 @@ public class BookFragment extends BaseFragment {
 | 
				
			|||||||
    Injector i;
 | 
					    Injector i;
 | 
				
			||||||
    @Inject
 | 
					    @Inject
 | 
				
			||||||
    @Named("MainBook")
 | 
					    @Named("MainBook")
 | 
				
			||||||
    Lazy<Book> mBook;
 | 
					    Book mBook;
 | 
				
			||||||
 | 
					    @Inject
 | 
				
			||||||
 | 
					    VerseLookup verseLookup;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @InjectView(R.id.book_content)
 | 
					    @InjectView(R.id.book_content)
 | 
				
			||||||
    WebView mainContent;
 | 
					    WebView mainContent;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    PublishSubject<String> titleReceiver = PublishSubject.create();
 | 
					    PublishSubject<String> titleReceiver = PublishSubject.create();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public BookFragment() {
 | 
					 | 
				
			||||||
        // We can't initialize the lookupService here since the fragment hasn't been tied
 | 
					 | 
				
			||||||
        // to the parent activity yet.
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Returns a new instance of this fragment for the given book.
 | 
					     * Returns a new instance of this fragment for the given book.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
@ -76,7 +72,7 @@ public class BookFragment extends BaseFragment {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        // TODO: Load initial text from SharedPreferences, rather than getting the actual book.
 | 
					        // TODO: Load initial text from SharedPreferences, rather than getting the actual book.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        displayBook(mBook.get());
 | 
					        displayBook(mBook);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return rootView;
 | 
					        return rootView;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -103,8 +99,7 @@ public class BookFragment extends BaseFragment {
 | 
				
			|||||||
        ((BibleViewer)getActivity()).setActionBarTitle(b.getInitials());
 | 
					        ((BibleViewer)getActivity()).setActionBarTitle(b.getInitials());
 | 
				
			||||||
        mainContent.loadUrl(getString(R.string.book_html));
 | 
					        mainContent.loadUrl(getString(R.string.book_html));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        VerseLookupService lookupService = new VerseLookupService(i, mBook.get());
 | 
					        BibleViewClient client = new BibleViewClient(b, verseLookup, titleReceiver);
 | 
				
			||||||
        BibleViewClient client = new BibleViewClient(b, lookupService, titleReceiver);
 | 
					 | 
				
			||||||
        titleReceiver
 | 
					        titleReceiver
 | 
				
			||||||
                .observeOn(AndroidSchedulers.mainThread())
 | 
					                .observeOn(AndroidSchedulers.mainThread())
 | 
				
			||||||
                .subscribe(new Action1<String>() {
 | 
					                .subscribe(new Action1<String>() {
 | 
				
			||||||
 | 
				
			|||||||
@ -1,7 +0,0 @@
 | 
				
			|||||||
package org.bspeice.minimalbible.exception;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Error to be thrown when no books are currently installed.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
public class NoBooksInstalledException extends Exception {
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@ -1,25 +0,0 @@
 | 
				
			|||||||
package org.bspeice.minimalbible.service.book;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import android.support.v4.util.LruCache;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import dagger.Module;
 | 
					 | 
				
			||||||
import dagger.Provides;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Created by bspeice on 9/1/14.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
@Module(injects = VerseLookupService.class)
 | 
					 | 
				
			||||||
public class VerseLookupModules {
 | 
					 | 
				
			||||||
    private static final int MAX_SIZE = 1000000; // 1MB
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * Create a new LruCache. We're free to create new ones since they're all backed by the file
 | 
					 | 
				
			||||||
     * system anyways.
 | 
					 | 
				
			||||||
     *
 | 
					 | 
				
			||||||
     * @return The LruCache to use
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    @Provides
 | 
					 | 
				
			||||||
    LruCache<String, String> getLruCache() {
 | 
					 | 
				
			||||||
        return new LruCache<String, String>(MAX_SIZE);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@ -1,148 +0,0 @@
 | 
				
			|||||||
package org.bspeice.minimalbible.service.book;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import android.support.v4.util.LruCache;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import org.bspeice.minimalbible.Injector;
 | 
					 | 
				
			||||||
import org.bspeice.minimalbible.service.format.osisparser.OsisParser;
 | 
					 | 
				
			||||||
import org.crosswire.common.xml.SAXEventProvider;
 | 
					 | 
				
			||||||
import org.crosswire.jsword.book.Book;
 | 
					 | 
				
			||||||
import org.crosswire.jsword.book.BookData;
 | 
					 | 
				
			||||||
import org.crosswire.jsword.book.BookException;
 | 
					 | 
				
			||||||
import org.crosswire.jsword.passage.Verse;
 | 
					 | 
				
			||||||
import org.xml.sax.SAXException;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import javax.inject.Inject;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import rx.functions.Action1;
 | 
					 | 
				
			||||||
import rx.schedulers.Schedulers;
 | 
					 | 
				
			||||||
import rx.subjects.PublishSubject;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * This class has a simple purpose, but implements the dirty work needed to make it happen.
 | 
					 | 
				
			||||||
 * The idea is this: someone wants the text for a verse, we look it up quickly.
 | 
					 | 
				
			||||||
 * This means aggressive caching, cache prediction, and classes letting us know that some verses
 | 
					 | 
				
			||||||
 * may be needed in the future (i.e. searching).
 | 
					 | 
				
			||||||
 * <p/>
 | 
					 | 
				
			||||||
 * There is one VerseLookupService per Book, but multiple VerseLookupServices can work with
 | 
					 | 
				
			||||||
 * the same book. Because the actual caching mechanism is disk-based, we're safe.
 | 
					 | 
				
			||||||
 * <p/>
 | 
					 | 
				
			||||||
 * TODO: Statistics on cache hits/misses vs. verses cached
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
public class VerseLookupService implements Action1<Verse> {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    Book book;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Inject
 | 
					 | 
				
			||||||
    LruCache<String, String> cache;
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * The listener is responsible for delegating calls to cache verses.
 | 
					 | 
				
			||||||
     * This way, @notifyVerse can just tell the listener what's what,
 | 
					 | 
				
			||||||
     * and the listener can delegate to another thread.
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    private PublishSubject<Verse> listener = PublishSubject.create();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public VerseLookupService(Injector i, Book b) {
 | 
					 | 
				
			||||||
        listener.subscribeOn(Schedulers.io())
 | 
					 | 
				
			||||||
                .subscribe(this);
 | 
					 | 
				
			||||||
        this.book = b;
 | 
					 | 
				
			||||||
        i.inject(this);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * Get the text for a corresponding verse
 | 
					 | 
				
			||||||
     * First, check the cache. If that doesn't exist, manually get the verse.
 | 
					 | 
				
			||||||
     * In all cases, notify that we're looking up a verse so we can get the surrounding ones.
 | 
					 | 
				
			||||||
     *
 | 
					 | 
				
			||||||
     * @param v The verse to look up
 | 
					 | 
				
			||||||
     * @return The JSON object for this verse (\<p\/>)
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    public String getJsonVerse(Verse v) {
 | 
					 | 
				
			||||||
        if (contains(v)) {
 | 
					 | 
				
			||||||
            return cache.get(getEntryName(v));
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            // The awkward method calls below are so notifyVerse doesn't
 | 
					 | 
				
			||||||
            // call the same doVerseLookup
 | 
					 | 
				
			||||||
            String verseContent = doVerseLookup(v);
 | 
					 | 
				
			||||||
            notifyVerse(v);
 | 
					 | 
				
			||||||
            return verseContent;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * Perform the ugly work of getting the actual data for a verse
 | 
					 | 
				
			||||||
     * Note that we build the verse object, JS should be left to determine how
 | 
					 | 
				
			||||||
     * it is displayed.
 | 
					 | 
				
			||||||
     *
 | 
					 | 
				
			||||||
     * @param v The verse to look up
 | 
					 | 
				
			||||||
     * @return The JSON content of this verse
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    public String doVerseLookup(Verse v) {
 | 
					 | 
				
			||||||
        BookData bookData = new BookData(book, v);
 | 
					 | 
				
			||||||
        try {
 | 
					 | 
				
			||||||
            SAXEventProvider provider = bookData.getSAXEventProvider();
 | 
					 | 
				
			||||||
            OsisParser handler = new OsisParser();
 | 
					 | 
				
			||||||
            handler.setVerse(v);
 | 
					 | 
				
			||||||
            provider.provideSAXEvents(handler);
 | 
					 | 
				
			||||||
            return handler.getVerseContent().toJson();
 | 
					 | 
				
			||||||
        } catch (BookException e) {
 | 
					 | 
				
			||||||
            e.printStackTrace();
 | 
					 | 
				
			||||||
            return "Unable to locate " + v.toString() + "!";
 | 
					 | 
				
			||||||
        } catch (SAXException e) {
 | 
					 | 
				
			||||||
            e.printStackTrace();
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        return null;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * Not necessary, but helpful if you let us know ahead of time we should pre-cache a verse.
 | 
					 | 
				
			||||||
     * For example, if something showed up in search results, it'd be helpful to start
 | 
					 | 
				
			||||||
     * looking up some of the results.
 | 
					 | 
				
			||||||
     *
 | 
					 | 
				
			||||||
     * @param v The verse we should pre-cache
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    public void notifyVerse(Verse v) {
 | 
					 | 
				
			||||||
        listener.onNext(v);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * Let someone know if the cache contains a verse we want
 | 
					 | 
				
			||||||
     * Also provides a nice wrapper if the underlying cache isn't working properly.
 | 
					 | 
				
			||||||
     *
 | 
					 | 
				
			||||||
     * @param v The verse to check
 | 
					 | 
				
			||||||
     * @return Whether we can retrieve the verse from our cache
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    public boolean contains(Verse v) {
 | 
					 | 
				
			||||||
        return cache.get(getEntryName(v)) != null;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * Given a verse, what should it's name in the cache be?
 | 
					 | 
				
			||||||
     * Example: Matthew 7:7 becomes:
 | 
					 | 
				
			||||||
     * MAT_7_7
 | 
					 | 
				
			||||||
     *
 | 
					 | 
				
			||||||
     * @param v The verse we need to generate a name for
 | 
					 | 
				
			||||||
     * @return The name this verse should have in the cache
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    private String getEntryName(Verse v) {
 | 
					 | 
				
			||||||
        return v.getBook().toString() + "_" +
 | 
					 | 
				
			||||||
                v.getChapter() + "_" +
 | 
					 | 
				
			||||||
                v.getVerse();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /*------------------------------------------------------------------------
 | 
					 | 
				
			||||||
        IO Thread operations below
 | 
					 | 
				
			||||||
    ------------------------------------------------------------------------*/
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * The listener has let us know that we need to look up a verse. So, look up
 | 
					 | 
				
			||||||
     * that one first, and get its surrounding verses as well just in case.
 | 
					 | 
				
			||||||
     * We can safely assume we are not on the main thread.
 | 
					 | 
				
			||||||
     *
 | 
					 | 
				
			||||||
     * @param verse The verse we need to look up
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Override
 | 
					 | 
				
			||||||
    public void call(Verse verse) {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@ -1,35 +1,34 @@
 | 
				
			|||||||
package org.bspeice.minimalbible.activity.viewer
 | 
					package org.bspeice.minimalbible.activity.viewer
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import org.crosswire.jsword.passage.Verse
 | 
					import org.crosswire.jsword.passage.Verse
 | 
				
			||||||
import org.bspeice.minimalbible.service.book.VerseLookupService
 | 
					 | 
				
			||||||
import android.webkit.WebViewClient
 | 
					import android.webkit.WebViewClient
 | 
				
			||||||
import android.webkit.JavascriptInterface
 | 
					import android.webkit.JavascriptInterface
 | 
				
			||||||
import org.crosswire.jsword.book.Book
 | 
					import org.crosswire.jsword.book.Book
 | 
				
			||||||
import java.util.ArrayList
 | 
					 | 
				
			||||||
import android.util.Log
 | 
					import android.util.Log
 | 
				
			||||||
import rx.subjects.PublishSubject
 | 
					import rx.subjects.PublishSubject
 | 
				
			||||||
import org.crosswire.jsword.book.getVersification
 | 
					import org.crosswire.jsword.book.getVersification
 | 
				
			||||||
 | 
					import org.bspeice.minimalbible.service.lookup.VerseLookup
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Created by bspeice on 9/14/14.
 | 
					 * Created by bspeice on 9/14/14.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class BibleViewClient(val b: Book, val lookup: VerseLookupService,
 | 
					class BibleViewClient(val b: Book, val lookup: VerseLookup,
 | 
				
			||||||
                      val subject: PublishSubject<String>?) : WebViewClient() {
 | 
					                      val subject: PublishSubject<String>?) : WebViewClient() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // We can receive and return only primitives and Strings. Still means we can use JSON :)
 | 
					    // We can receive and return only primitives and Strings. Still means we can use JSON :)
 | 
				
			||||||
    JavascriptInterface fun getVerse(ordinal: Int): String {
 | 
					    JavascriptInterface fun getVerse(ordinal: Int): String {
 | 
				
			||||||
        val v = Verse(b.getVersification(), ordinal)
 | 
					        val v = Verse(b.getVersification(), ordinal)
 | 
				
			||||||
        // TODO: WebView should notify us what verse it's on
 | 
					        // TODO: WebView should notify us what verse it's on
 | 
				
			||||||
        subject?.onNext(v.getBook().toString() + " " + v.getChapter() + ":" + v.getVerse())
 | 
					        subject?.onNext("${v.getBook()} ${v.getChapter()}:${v.getVerse()}")
 | 
				
			||||||
        return lookup.getJsonVerse(v)
 | 
					        return lookup getJson v
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    JavascriptInterface fun getVerses(first: Int, count: Int): String {
 | 
					    JavascriptInterface fun getVerses(first: Int, count: Int): String {
 | 
				
			||||||
        Log.e("getVerses", "First: " + first + " count: " + count)
 | 
					        Log.e("getVerses", "First: $first count: $count")
 | 
				
			||||||
        val verses: MutableList<String> = ArrayList<String>()
 | 
					        val verses: MutableList<String> = linkedListOf()
 | 
				
			||||||
        var trueCount: Int
 | 
					        val trueCount: Int
 | 
				
			||||||
        var trueFirst: Int
 | 
					        val trueFirst: Int
 | 
				
			||||||
        when {
 | 
					        when {
 | 
				
			||||||
            first < 0 - count -> return ""
 | 
					            first < 0 - count -> return ""
 | 
				
			||||||
            first < 0 -> {
 | 
					            first < 0 -> {
 | 
				
			||||||
@ -45,7 +44,7 @@ class BibleViewClient(val b: Book, val lookup: VerseLookupService,
 | 
				
			|||||||
        for (i in trueFirst..trueFirst + trueCount - 1) {
 | 
					        for (i in trueFirst..trueFirst + trueCount - 1) {
 | 
				
			||||||
            verses.add(getVerse(i))
 | 
					            verses.add(getVerse(i))
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        Log.e("getVerses", "return verses size: " + verses.size.toString())
 | 
					        Log.e("getVerses", "return verses size: ${verses.size}")
 | 
				
			||||||
        return verses.toString()
 | 
					        return verses.toString()
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -0,0 +1,3 @@
 | 
				
			|||||||
 | 
					package org.bspeice.minimalbible.exception
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class NoBooksInstalledException() : Exception("No books currently installed!") {}
 | 
				
			||||||
@ -22,6 +22,8 @@ class OsisParser() : DefaultHandler() {
 | 
				
			|||||||
    // TODO: Implement a stack to keep min API 8
 | 
					    // TODO: Implement a stack to keep min API 8
 | 
				
			||||||
    val doWrite = ArrayDeque<Boolean>()
 | 
					    val doWrite = ArrayDeque<Boolean>()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fun getJson() = verseContent.toJson()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    override fun startElement(uri: String, localName: String,
 | 
					    override fun startElement(uri: String, localName: String,
 | 
				
			||||||
                              qName: String, attributes: Attributes) {
 | 
					                              qName: String, attributes: Attributes) {
 | 
				
			||||||
        when (localName) {
 | 
					        when (localName) {
 | 
				
			||||||
 | 
				
			|||||||
@ -0,0 +1,84 @@
 | 
				
			|||||||
 | 
					package org.bspeice.minimalbible.service.lookup
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import org.crosswire.jsword.book.Book
 | 
				
			||||||
 | 
					import android.support.v4.util.LruCache
 | 
				
			||||||
 | 
					import rx.functions.Action1
 | 
				
			||||||
 | 
					import org.crosswire.jsword.passage.Verse
 | 
				
			||||||
 | 
					import rx.subjects.PublishSubject
 | 
				
			||||||
 | 
					import rx.schedulers.Schedulers
 | 
				
			||||||
 | 
					import org.crosswire.jsword.book.BookData
 | 
				
			||||||
 | 
					import org.bspeice.minimalbible.service.format.osisparser.OsisParser
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Created by bspeice on 11/12/14.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					open class VerseLookup(val b: Book,
 | 
				
			||||||
 | 
					                       val cache: LruCache<Int, String> = LruCache(1000000)) : Action1<Verse> {
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * The listener servers to let other objects notify us we should pre-cache verses
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    val listener: PublishSubject<Verse> = PublishSubject.create();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        listener.observeOn(Schedulers.io())
 | 
				
			||||||
 | 
					                .subscribe(this)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fun getVerseId(v: Verse) = v.getOrdinal()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fun getJson(v: Verse): String =
 | 
				
			||||||
 | 
					            if (contains(v))
 | 
				
			||||||
 | 
					                cache[getVerseId(v)]
 | 
				
			||||||
 | 
					            else {
 | 
				
			||||||
 | 
					                val content = doLookup(v)
 | 
				
			||||||
 | 
					                notify(v)
 | 
				
			||||||
 | 
					                content
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Perform the ugly work of getting the actual data for a verse
 | 
				
			||||||
 | 
					     * Note that we build the verse object, JS should be left to determine how
 | 
				
			||||||
 | 
					     * it is displayed.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param v The verse to look up
 | 
				
			||||||
 | 
					     * @return The JSON content of this verse
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    fun doLookup(v: Verse): String {
 | 
				
			||||||
 | 
					        val data = BookData(b, v)
 | 
				
			||||||
 | 
					        val provider = data.getSAXEventProvider()
 | 
				
			||||||
 | 
					        val handler = OsisParser()
 | 
				
			||||||
 | 
					        handler.verse = v
 | 
				
			||||||
 | 
					        provider provideSAXEvents handler
 | 
				
			||||||
 | 
					        return handler.getJson()
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Not necessary, but helpful if you let us know ahead of time we should pre-cache a verse.
 | 
				
			||||||
 | 
					     * For example, if something showed up in search results, it'd be helpful to start
 | 
				
			||||||
 | 
					     * looking up some of the results.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param v The verse we should pre-cache
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    fun notify(v: Verse) = listener onNext v
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Let someone know if the cache contains a verse we want
 | 
				
			||||||
 | 
					     * Also provides a nice wrapper if the underlying cache isn't working properly.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param v The verse to check
 | 
				
			||||||
 | 
					     * @return Whether we can retrieve the verse from our cache
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    fun contains(v: Verse) = cache[v.getOrdinal()] != null
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // IO Thread operations begin here
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Someone was nice enough to let us know that a verse was recently called,
 | 
				
			||||||
 | 
					     * we should probably cache its neighbors!
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    override fun call(t1: Verse?) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class DefaultVerseLookup(b: Book) : VerseLookup(b) {}
 | 
				
			||||||
		Reference in New Issue
	
	Block a user