Java tutorial
package com.bellman.bible.android.control.page; import android.util.Log; import android.view.Menu; import android.view.MenuItem; import com.bellman.bible.android.activity.R; import com.bellman.bible.android.control.PassageChangeMediator; import com.bellman.bible.service.common.ParseException; import com.bellman.bible.service.format.HtmlMessageFormatter; import com.bellman.bible.service.format.Note; import com.bellman.bible.service.sword.SwordContentFacade; import com.bellman.bible.service.sword.SwordDocumentFacade; import org.apache.commons.lang3.StringUtils; import org.crosswire.common.activate.Activator; import org.crosswire.jsword.book.Book; import org.crosswire.jsword.passage.Key; import org.json.JSONException; import org.json.JSONObject; import java.util.List; /** Common functionality for different document page types * * @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. */ abstract class CurrentPageBase implements CurrentPage { private static final String TAG = "CurrentPage"; private Book currentDocument; private boolean inhibitChangeNotifications; private float currentYOffsetRatio; private Key keyWhenYOffsetRatioSet; private Book docWhenYOffsetRatioSet; // all bibles and commentaries share the same key private boolean shareKeyBetweenDocs = false; protected CurrentPageBase(boolean shareKeyBetweenDocs) { super(); this.shareKeyBetweenDocs = shareKeyBetweenDocs; } public abstract void doSetKey(Key key); /** notify mediator that page has changed and a lot of things need to update themselves */ protected void beforePageChange() { if (!isInhibitChangeNotifications()) { PassageChangeMediator.getInstance().onBeforeCurrentPageChanged(); } } /** notify mediator that page has changed and a lot of things need to update themselves */ protected void pageChange() { if (!isInhibitChangeNotifications()) { PassageChangeMediator.getInstance().onCurrentPageChanged(); } } @Override public Key getSingleKey() { // by default do not handle single key requirement - it is really just for bibles return getKey(); } @Override public void setKey(Key key) { beforePageChange(); doSetKey(key); pageChange(); } @Override public void next() { } @Override public void previous() { } /** add or subtract a number of pages from the current position and return Page * default is one key per page - all except bible use this default */ public Key getPagePlus(int num) { // If 1 key per page then same as getKeyPlus return getKeyPlus(num); } @Override public boolean isSingleKey() { return false; } @Override public String getCurrentPageContent() throws ParseException { String htmlText = SwordContentFacade.getInstance().readHtmlText(getCurrentDocument(), getKey()); if (StringUtils.isEmpty(htmlText)) { htmlText = HtmlMessageFormatter.format(R.string.error_no_content); } return htmlText; } @Override public List<Note> getCurrentPageFootnotesAndReferences() throws ParseException { List<Note> footnotes = SwordContentFacade.getInstance().readFootnotesAndReferences(getCurrentDocument(), getKey()); return footnotes; } public boolean checkCurrentDocumentStillInstalled() { if (currentDocument != null) { Log.d(TAG, "checkCurrentDocumentStillInstalled:" + currentDocument); // this sets currentDoc to null if it does not exist currentDocument = SwordDocumentFacade.getInstance() .getDocumentByInitials(currentDocument.getInitials()); } return currentDocument != null; } /* (non-Javadoc) * @see com.bellman.bible.android.control.CurrentPage#getCurrentDocument() */ @Override public Book getCurrentDocument() { if (currentDocument == null) { List<Book> books = SwordDocumentFacade.getInstance().getBooks(getBookCategory()); if (books.size() > 0) { currentDocument = books.get(0); } } return currentDocument; } /* Set new doc and if possible show new doc * @see com.bellman.bible.android.control.CurrentPage#setCurrentDocument(org.crosswire.jsword.book.Book) */ @Override public void setCurrentDocument(Book doc) { Log.d(TAG, "Set current doc to " + doc); Book prevDoc = currentDocument; if (!doc.equals(currentDocument) && !shareKeyBetweenDocs && getKey() != null && !doc.contains(getKey())) { doSetKey(null); } localSetCurrentDocument(doc); // try to clear memory to prevent OutOfMemory errors if (!currentDocument.equals(prevDoc)) { Activator.deactivate(prevDoc); } } /* Set new doc and if possible show new doc * @see com.bellman.bible.android.control.CurrentPage#setCurrentDocument(org.crosswire.jsword.book.Book) */ @Override public void setCurrentDocumentAndKey(Book doc, Key key) { doSetKey(key); localSetCurrentDocument(doc); } protected void localSetCurrentDocument(Book doc) { this.currentDocument = doc; } @Override public void updateOptionsMenu(Menu menu) { // these are fine for Bible and commentary MenuItem menuItem = menu.findItem(R.id.searchButton); if (menuItem != null) { menuItem.setEnabled(isSearchable()); } menuItem = menu.findItem(R.id.bookmarksButton); if (menuItem != null) { menuItem.setEnabled(true); } menuItem = menu.findItem(R.id.speakButton); if (menuItem != null) { menuItem.setEnabled(isSpeakable()); } } @Override public boolean isInhibitChangeNotifications() { return inhibitChangeNotifications; } @Override public void setInhibitChangeNotifications(boolean inhibitChangeNotifications) { this.inhibitChangeNotifications = inhibitChangeNotifications; } @Override public void restoreState(JSONObject jsonObject) throws JSONException { if (jsonObject != null) { Log.d(TAG, "Restoring page state"); if (jsonObject.has("document")) { String document = jsonObject.getString("document"); if (StringUtils.isNotEmpty(document)) { Log.d(TAG, "State document:" + document); Book book = SwordDocumentFacade.getInstance().getDocumentByInitials(document); if (book != null) { Log.d(TAG, "Restored document:" + book.getName()); // bypass setter to avoid automatic notifications localSetCurrentDocument(book); try { if (jsonObject.has("key")) { String keyName = jsonObject.getString("key"); if (StringUtils.isNotEmpty(keyName)) { doSetKey(book.getKey(keyName)); Log.d(TAG, "Restored key:" + keyName); } } } catch (Exception e) { Log.e(TAG, "Error restoring key for document category:" + getBookCategory().getName()); } } } } } } /** called during app close down to save state */ @Override public JSONObject getStateJson() throws JSONException { JSONObject object = new JSONObject(); if (currentDocument != null) { Log.d(TAG, "Getting json state for " + getBookCategory().getName()); object.put("document", getCurrentDocument().getInitials()); if (this.getKey() != null) { object.put("key", getKey().getName()); } } return object; } public boolean isShareKeyBetweenDocs() { return shareKeyBetweenDocs; } /** can we enable the main menu Speak button */ @Override public boolean isSpeakable() { return true; } /** how far down the page was the user - allows Back to go to correct line on non-Bible pages (Bibles use verse number for positioning) */ public float getCurrentYOffsetRatio() { try { // if key has changed then offsetRatio must be reset because user has changed page if (getKey() == null || !getKey().equals(keyWhenYOffsetRatioSet) || !getCurrentDocument().equals(docWhenYOffsetRatioSet)) { currentYOffsetRatio = 0; } } catch (Exception e) { // cope with occasional NPE thrown by above if statement // just pretend we are at the top of the page if error occurs currentYOffsetRatio = 0; Log.w(TAG, "NPE getting currentYOffsetRatio"); } return currentYOffsetRatio; } public void setCurrentYOffsetRatio(float currentYOffsetRatio) { this.docWhenYOffsetRatioSet = getCurrentDocument(); this.keyWhenYOffsetRatioSet = getKey(); this.currentYOffsetRatio = currentYOffsetRatio; } }