package net.bible.service.sword;
import net.bible.android.control.ApplicationScope;
import net.bible.service.common.CommonUtils;
import net.bible.service.common.Logger;
import net.bible.service.download.DownloadManager;
import net.bible.service.download.RepoBookDeduplicator;
import net.bible.service.download.RepoFactory;
import net.bible.service.sword.index.IndexCreator;
import org.crosswire.common.util.Version;
import org.crosswire.jsword.book.Book;
import org.crosswire.jsword.book.BookCategory;
import org.crosswire.jsword.book.BookException;
import org.crosswire.jsword.book.BookFilter;
import org.crosswire.jsword.book.BookFilters;
import org.crosswire.jsword.book.Books;
import org.crosswire.jsword.book.Defaults;
import org.crosswire.jsword.book.FeatureType;
import org.crosswire.jsword.book.install.InstallException;
import org.crosswire.jsword.book.sword.SwordBookMetaData;
import org.crosswire.jsword.book.sword.SwordBookPath;
import org.crosswire.jsword.index.IndexManager;
import org.crosswire.jsword.index.IndexManagerFactory;
import org.crosswire.jsword.index.IndexStatus;
import java.io.File;
import java.util.Collections;
import java.util.List;
import javax.inject.Inject;
/** JSword facade
*
* @author Martin Denham [mjdenham at gmail dot com]
* @see gnu.lgpl.License for license details.<br>
* The copyright to this program is held by it's author.
*/
@ApplicationScope
public class SwordDocumentFacade {
private RepoFactory repoFactory;
private static BookFilter SUPPORTED_DOCUMENT_TYPES = new AcceptableBookTypeFilter();
private static final Logger log = new Logger(SwordDocumentFacade.class.getName());
@Inject
public SwordDocumentFacade(RepoFactory repoFactory) {
this.repoFactory = repoFactory;
}
public List<Book> getBibles() {
log.debug("Getting bibles");
List<Book> documents = Books.installed().getBooks(BookFilters.getBibles());
log.debug("Got bibles, Num="+documents.size());
return documents;
}
public List<Book> getBooks(final BookCategory bookCategory) {
log.debug("Getting books of type "+bookCategory.getName());
List<Book> documents = Books.installed().getBooks(new BookFilter() {
@Override
public boolean test(Book book) {
return book.getBookCategory().equals(bookCategory) && !book.isLocked();
}
});
log.debug("Got books, Num="+documents.size());
return documents;
}
/** return all supported documents - bibles and commentaries for now
*/
public List<Book> getDocuments() {
log.debug("Getting books");
// currently only bibles and commentaries are supported
List<Book> allDocuments = Books.installed().getBooks(SUPPORTED_DOCUMENT_TYPES);
log.debug("Got books, Num="+allDocuments.size());
return allDocuments;
}
/** prefer the Real alternatives to the default versions because they contain the native Greek Hebrew words
*/
public Book getDefaultStrongsGreekDictionary() {
// default to StrongsRealGreek or StrongsGreek
String[] preferredBooks = {"StrongsRealGreek", "StrongsGreek"};
for (String prefBook : preferredBooks) {
Book strongs = Books.installed().getBook(prefBook);
if (strongs!=null) {
return strongs;
}
}
return Defaults.getGreekDefinitions();
}
public Book getDefaultStrongsHebrewDictionary() {
// default to StrongsRealHebrew or StrongsHebrew
String[] preferredBooks = {"StrongsRealHebrew", "StrongsHebrew"};
for (String prefBook : preferredBooks) {
Book strongs = Books.installed().getBook(prefBook);
if (strongs!=null) {
return strongs;
}
}
return Defaults.getHebrewDefinitions();
}
public Book getDefaultBibleWithStrongs() {
List<Book> bibles = getBibles();
for (Book book : bibles) {
if (book.hasFeature(FeatureType.STRONGS_NUMBERS)) {
if (book.getIndexStatus().equals(IndexStatus.DONE)) {
return book;
}
}
}
return null;
}
public Book getDocumentByInitials(String initials) {
return Books.installed().getBook(initials);
}
public List<Book> getDownloadableDocuments(boolean refresh) throws InstallException {
log.debug("Getting downloadable documents. Refresh:"+refresh);
try {
// there are so many sbmd's to load that we can only load what is required for the display list.
// If About is selected or a document is downloaded the sbmd is then loaded fully.
SwordBookMetaData.setPartialLoading(true);
RepoBookDeduplicator repoBookDeduplicator = new RepoBookDeduplicator();
repoBookDeduplicator.addAll(repoFactory.getAndBibleRepo().getRepoBooks(refresh));
repoBookDeduplicator.addAll(repoFactory.getIBTRepo().getRepoBooks(refresh));
repoBookDeduplicator.addAll(repoFactory.getCrosswireRepo().getRepoBooks(refresh));
repoBookDeduplicator.addAll(repoFactory.getXiphosRepo().getRepoBooks(refresh));
repoBookDeduplicator.addAll(repoFactory.getEBibleRepo().getRepoBooks(refresh));
// beta repo must never override live books especially if later version so use addIfNotExists
repoBookDeduplicator.addIfNotExists(repoFactory.getBetaRepo().getRepoBooks(refresh));
List<Book> bookList = repoBookDeduplicator.getBooks();
// get them in the correct order
Collections.sort(bookList);
return bookList;
} finally {
SwordBookMetaData.setPartialLoading(false);
}
}
public boolean isIndexDownloadAvailable(Book document) throws InstallException, BookException {
// not sure how to integrate reuse this in JSword index download
String version = document.getBookMetaData().getProperty("Version");
String versionSuffix = version!=null ? "-" + new Version(version).toString() : "";
String url = "http://www.crosswire.org/and-bible/indices/v1/"+document.getInitials()+versionSuffix+".zip";
return CommonUtils.isHttpUrlAvailable(url);
}
public void downloadIndex(Book document) throws InstallException, BookException {
DownloadManager downloadManager = new DownloadManager();
downloadManager.installIndexInNewThread(repoFactory.getAndBibleRepo().getRepoName(), document);
}
public void deleteDocument(Book document) throws BookException {
// make sure we have the correct Book and not just a copy e.g. one from a Download Manager
Book realDocument = getDocumentByInitials(document.getInitials());
// delete index first if it exists but wrap in try to ensure an attempt is made to delete the document
try {
IndexManager imanager = IndexManagerFactory.getIndexManager();
if (imanager.isIndexed(realDocument)) {
imanager.deleteIndex(realDocument);
}
} catch (Exception e) {
// just log index delete error, deleting doc is the important thing
log.error("Error deleting document index", e);
}
document.getDriver().delete(realDocument);
}
public void deleteDocumentIndex(Book document) throws BookException {
// make sure we have the correct Book and not just a copy e.g. one from a Download Manager
Book realDocument = getDocumentByInitials(document.getInitials());
IndexManager imanager = IndexManagerFactory.getIndexManager();
if (imanager.isIndexed(realDocument)) {
imanager.deleteIndex(realDocument);
}
}
/** this custom index creation has been optimised for slow, low memory devices
* If an index is in progress then nothing will happen
*/
public void ensureIndexCreation(Book book) throws BookException {
log.debug("ensureIndexCreation");
// ensure this isn't just the user re-clicking the Index button
if (!book.getIndexStatus().equals(IndexStatus.CREATING) && !book.getIndexStatus().equals(IndexStatus.SCHEDULED)) {
IndexCreator ic = new IndexCreator();
ic.scheduleIndexCreation(book);
}
}
private String getPaths() {
String text = "Paths:";
try {
// SwordBookPath.setAugmentPath(new File[] {new
// File("/data/bible")});
File[] swordBookPaths = SwordBookPath.getSwordPath();
for (File file : swordBookPaths) {
text += file.getAbsolutePath();
}
text += "Augmented paths:";
File[] augBookPaths = SwordBookPath.getAugmentPath();
for (File file : augBookPaths) {
text += file.getAbsolutePath();
}
} catch (Exception e) {
text += e.getMessage();
}
return text;
}
}