[jsword-svn] r2196 - in trunk/jsword/src: main/java/org/crosswire/common/activate main/java/org/crosswire/common/diff main/java/org/crosswire/common/progress main/java/org/crosswire/jsword/book main/java/org/crosswire/jsword/book/sword main/java/org/crosswire/jsword/passage main/java/org/crosswire/jsword/versification main/resources test/java/org/crosswire/common/progress test/java/org/crosswire/jsword/passage

dmsmith at crosswire.org dmsmith at crosswire.org
Tue Jan 3 06:53:37 MST 2012


Author: dmsmith
Date: 2012-01-03 06:53:37 -0700 (Tue, 03 Jan 2012)
New Revision: 2196

Added:
   trunk/jsword/src/main/java/org/crosswire/jsword/versification/v11n.jpage
Modified:
   trunk/jsword/src/main/java/org/crosswire/common/activate/Kill.java
   trunk/jsword/src/main/java/org/crosswire/common/diff/Commonality.java
   trunk/jsword/src/main/java/org/crosswire/common/progress/Job.java
   trunk/jsword/src/main/java/org/crosswire/jsword/book/BookProvider.java
   trunk/jsword/src/main/java/org/crosswire/jsword/book/sword/RawFileBackend.java
   trunk/jsword/src/main/java/org/crosswire/jsword/book/sword/SwordBook.java
   trunk/jsword/src/main/java/org/crosswire/jsword/book/sword/SwordConstants.java
   trunk/jsword/src/main/java/org/crosswire/jsword/passage/AbstractPassage.java
   trunk/jsword/src/main/java/org/crosswire/jsword/passage/AccuracyType.java
   trunk/jsword/src/main/java/org/crosswire/jsword/passage/BitwisePassage.java
   trunk/jsword/src/main/java/org/crosswire/jsword/passage/PassageKeyFactory.java
   trunk/jsword/src/main/java/org/crosswire/jsword/passage/PassageTally.java
   trunk/jsword/src/main/java/org/crosswire/jsword/passage/Verse.java
   trunk/jsword/src/main/java/org/crosswire/jsword/versification/BibleBook.java
   trunk/jsword/src/main/java/org/crosswire/jsword/versification/BibleInfo.java
   trunk/jsword/src/main/java/org/crosswire/jsword/versification/BibleNames.java
   trunk/jsword/src/main/resources/BibleNames.properties
   trunk/jsword/src/test/java/org/crosswire/common/progress/JobTest.java
   trunk/jsword/src/test/java/org/crosswire/jsword/passage/BibleInfoTest.java
   trunk/jsword/src/test/java/org/crosswire/jsword/passage/PassageParentTst.java
   trunk/jsword/src/test/java/org/crosswire/jsword/passage/PassageUtilTest.java
   trunk/jsword/src/test/java/org/crosswire/jsword/passage/VerseTest.java
Log:
First pass at enabling module introductions.
As a result merged the lookup tables in BibleInfo and SwordConstants.

Modified: trunk/jsword/src/main/java/org/crosswire/common/activate/Kill.java
===================================================================
--- trunk/jsword/src/main/java/org/crosswire/common/activate/Kill.java	2012-01-02 05:11:59 UTC (rev 2195)
+++ trunk/jsword/src/main/java/org/crosswire/common/activate/Kill.java	2012-01-03 13:53:37 UTC (rev 2196)
@@ -28,20 +28,20 @@
  *      The copyright to this program is held by it's authors.
  * @author Joe Walker [joe at eireneh dot com]
  */
-public class Kill {
+public enum Kill {
     /** Try as hard as possible to conserve memory */
-    public static final Kill EVERYTHING = new Kill() {
+    EVERYTHING  {
         @Override
         public void reduceMemoryUsage() {
             Activator.deactivateAll();
         }
-    };
+    },
 
     /** Reduce memory usage, but only where sensible */
-    public static final Kill LEAST_USED = new Kill();
+    LEAST_USED,
 
     /** Reduce memory usage, but only if we really need to */
-    public static final Kill ONLY_IF_TIGHT = new Kill();
+    ONLY_IF_TIGHT;
 
     public void reduceMemoryUsage() {
         throw new IllegalArgumentException("Not implemented");

Modified: trunk/jsword/src/main/java/org/crosswire/common/diff/Commonality.java
===================================================================
--- trunk/jsword/src/main/java/org/crosswire/common/diff/Commonality.java	2012-01-02 05:11:59 UTC (rev 2195)
+++ trunk/jsword/src/main/java/org/crosswire/common/diff/Commonality.java	2012-01-03 13:53:37 UTC (rev 2196)
@@ -129,7 +129,11 @@
             return hm;
         }
 
-        return new CommonMiddle(hm.getTargetPrefix(), hm.getTargetSuffix(), hm.getSourcePrefix(), hm.getSourceSuffix(), hm.getCommonality());
+        // While hm cannot be null our QA checker can't figure that out.
+        if (hm != null) {
+            return new CommonMiddle(hm.getTargetPrefix(), hm.getTargetSuffix(), hm.getSourcePrefix(), hm.getSourceSuffix(), hm.getCommonality());
+        }
+        return null;
     }
 
     private static int ceil(int number, int divisor) {

Modified: trunk/jsword/src/main/java/org/crosswire/common/progress/Job.java
===================================================================
--- trunk/jsword/src/main/java/org/crosswire/common/progress/Job.java	2012-01-02 05:11:59 UTC (rev 2195)
+++ trunk/jsword/src/main/java/org/crosswire/common/progress/Job.java	2012-01-03 13:53:37 UTC (rev 2196)
@@ -551,11 +551,6 @@
                 JobManager.fireWorkProgressed(Job.this);
             }
         }
-
-        /**
-         * Serialization ID
-         */
-        private static final long serialVersionUID = 3256721784160924983L;
     }
 
     /**

Modified: trunk/jsword/src/main/java/org/crosswire/jsword/book/BookProvider.java
===================================================================
--- trunk/jsword/src/main/java/org/crosswire/jsword/book/BookProvider.java	2012-01-02 05:11:59 UTC (rev 2195)
+++ trunk/jsword/src/main/java/org/crosswire/jsword/book/BookProvider.java	2012-01-03 13:53:37 UTC (rev 2196)
@@ -22,7 +22,7 @@
 package org.crosswire.jsword.book;
 
 /**
- * A BookSelectEvent happens whenever a user selects a book.
+ * A BookProvider provides a list of books.
  * 
  * @see gnu.lgpl.License for license details.<br>
  *      The copyright to this program is held by it's authors.

Modified: trunk/jsword/src/main/java/org/crosswire/jsword/book/sword/RawFileBackend.java
===================================================================
--- trunk/jsword/src/main/java/org/crosswire/jsword/book/sword/RawFileBackend.java	2012-01-02 05:11:59 UTC (rev 2195)
+++ trunk/jsword/src/main/java/org/crosswire/jsword/book/sword/RawFileBackend.java	2012-01-03 13:53:37 UTC (rev 2196)
@@ -296,7 +296,7 @@
         BufferedOutputStream otIdxBos = new BufferedOutputStream(new FileOutputStream(otIndexFile, false));
 
         try {
-            for (int i = 0; i < SwordConstants.ORDINAL_MAT11; i++) {
+            for (int i = 0; i < SwordConstants.ORDINAL_NT; i++) {
                 writeInitialIndex(otIdxBos);
             }
         } finally {
@@ -306,8 +306,8 @@
         File ntIndexFile = idxFile[SwordConstants.TESTAMENT_NEW];
         BufferedOutputStream ntIdxBos = new BufferedOutputStream(new FileOutputStream(ntIndexFile, false));
         try {
-            int totVerses = BibleInfo.versesInBible();
-            for (int i = SwordConstants.ORDINAL_MAT11; i < totVerses; i++) {
+            int totVerses = BibleInfo.maximumOrdinal();
+            for (int i = SwordConstants.ORDINAL_NT; i < totVerses; i++) {
                 writeInitialIndex(ntIdxBos);
             }
         } finally {

Modified: trunk/jsword/src/main/java/org/crosswire/jsword/book/sword/SwordBook.java
===================================================================
--- trunk/jsword/src/main/java/org/crosswire/jsword/book/sword/SwordBook.java	2012-01-02 05:11:59 UTC (rev 2195)
+++ trunk/jsword/src/main/java/org/crosswire/jsword/book/sword/SwordBook.java	2012-01-03 13:53:37 UTC (rev 2196)
@@ -32,6 +32,7 @@
 import org.crosswire.jsword.book.basic.AbstractPassageBook;
 import org.crosswire.jsword.book.filter.Filter;
 import org.crosswire.jsword.passage.Key;
+import org.crosswire.jsword.passage.KeyUtil;
 import org.jdom.Content;
 import org.jdom.Element;
 
@@ -131,11 +132,15 @@
         }
 
         // If we get here then the text is not marked up with verse
-        // In this case we add the verse markup.
-        Element everse = OSISUtil.factory().createVerse();
-        everse.setAttribute(OSISUtil.OSIS_ATTR_OSISID, key.getOsisID());
-        div.addContent(everse);
-        super.addOSIS(key, everse, osisContent);
+        // In this case we add the verse markup, if the verse is not 0.
+        if (KeyUtil.getPassage(key).getVerseAt(0).getVerse() == 0) {
+            super.addOSIS(key, div, osisContent);
+        } else {
+            Element everse = OSISUtil.factory().createVerse();
+            everse.setAttribute(OSISUtil.OSIS_ATTR_OSISID, key.getOsisID());
+            div.addContent(everse);
+            super.addOSIS(key, everse, osisContent);
+        }
     }
 
     @Override
@@ -153,11 +158,15 @@
         }
 
         // If we get here then the text is not marked up with verse
-        // In this case we add the verse markup.
-        Element everse = OSISUtil.factory().createVerse();
-        everse.setAttribute(OSISUtil.OSIS_ATTR_OSISID, key.getOsisID());
-        super.addOSIS(key, everse, osisContent);
-        contentList.add(everse);
+        // In this case we add the verse markup, if the verse is not 0.
+        if (KeyUtil.getPassage(key).getVerseAt(0).getVerse() == 0) {
+            super.addOSIS(key, contentList, osisContent);
+        } else {
+            Element everse = OSISUtil.factory().createVerse();
+            everse.setAttribute(OSISUtil.OSIS_ATTR_OSISID, key.getOsisID());
+            super.addOSIS(key, everse, osisContent);
+            contentList.add(everse);
+        }
     }
 
     /*

Modified: trunk/jsword/src/main/java/org/crosswire/jsword/book/sword/SwordConstants.java
===================================================================
--- trunk/jsword/src/main/java/org/crosswire/jsword/book/sword/SwordConstants.java	2012-01-02 05:11:59 UTC (rev 2195)
+++ trunk/jsword/src/main/java/org/crosswire/jsword/book/sword/SwordConstants.java	2012-01-03 13:53:37 UTC (rev 2196)
@@ -21,8 +21,10 @@
  */
 package org.crosswire.jsword.book.sword;
 
+import org.crosswire.jsword.passage.NoSuchVerseException;
 import org.crosswire.jsword.passage.Verse;
 import org.crosswire.jsword.versification.BibleBook;
+import org.crosswire.jsword.versification.BibleInfo;
 
 /**
  * A Constants to help the SwordBookDriver to read Sword format data.
@@ -101,8 +103,7 @@
      */
     public static int getTestament(Verse v) {
         int ord = v.getOrdinal();
-
-        if (ord >= SwordConstants.ORDINAL_MAT11) {
+        if (ord >= SwordConstants.ORDINAL_NT) {
             // This is an NT verse
             return SwordConstants.TESTAMENT_NEW;
         }
@@ -114,13 +115,19 @@
      * Get the sword index of the given verse
      */
     static int getIndex(Verse v) {
+        try {
+            return BibleInfo.getTestamentOrdinal(v);
+        } catch (NoSuchVerseException e) {
+            return 0;
+        }
+/*
         int ord = v.getOrdinal();
         int book = v.getBook().ordinal();
         int chapter = v.getChapter();
         int verse = v.getVerse();
         int testament = -1;
 
-        if (ord >= SwordConstants.ORDINAL_MAT11) {
+        if (ord >= SwordConstants.ORDINAL_NT) {
             // This is an NT verse
             testament = SwordConstants.TESTAMENT_NEW;
             book = book - BibleBook.MAL.ordinal();
@@ -134,12 +141,20 @@
         short chapOffset = SwordConstants.cps[testament][bookOffset + chapter];
 
         return verse + chapOffset;
+*/
     }
 
     /**
      * The start of the new testament
      */
-    static final int ORDINAL_MAT11 = new Verse(BibleBook.MATT, 1, 1, true).getOrdinal();
+    static int ORDINAL_NT;
+    static {
+        try {
+            ORDINAL_NT = new Verse(BibleBook.INTRO_NT, 0, 0).getOrdinal();
+        } catch (NoSuchVerseException e) {
+            // This must work
+        }
+    }
 
     /**
      * array containing LUT of offsets in the chapter table.

Modified: trunk/jsword/src/main/java/org/crosswire/jsword/passage/AbstractPassage.java
===================================================================
--- trunk/jsword/src/main/java/org/crosswire/jsword/passage/AbstractPassage.java	2012-01-02 05:11:59 UTC (rev 2195)
+++ trunk/jsword/src/main/java/org/crosswire/jsword/passage/AbstractPassage.java	2012-01-03 13:53:37 UTC (rev 2196)
@@ -1142,7 +1142,7 @@
      */
     protected void writeObjectSupport(ObjectOutputStream out) throws IOException {
         // the size in bits of teach storage method
-        int bitwise_size = BibleInfo.versesInBible();
+        int bitwise_size = BibleInfo.maximumOrdinal();
         int ranged_size = 8 * countRanges(RestrictionType.NONE);
         int distinct_size = 4 * countVerses();
 
@@ -1150,7 +1150,7 @@
         if (bitwise_size <= ranged_size && bitwise_size <= distinct_size) {
             out.writeInt(BITWISE);
 
-            BitSet store = new BitSet(BibleInfo.versesInBible());
+            BitSet store = new BitSet(BibleInfo.maximumOrdinal());
             for (Key aKey : this) {
                 Verse verse = (Verse) aKey;
                 store.set(verse.getOrdinal() - 1);
@@ -1224,7 +1224,7 @@
             switch (type) {
             case BITWISE:
                 BitSet store = (BitSet) is.readObject();
-                for (int i = 0; i < BibleInfo.versesInBible(); i++) {
+                for (int i = 0; i < BibleInfo.maximumOrdinal(); i++) {
                     if (store.get(i)) {
                         add(new Verse(i + 1));
                     }

Modified: trunk/jsword/src/main/java/org/crosswire/jsword/passage/AccuracyType.java
===================================================================
--- trunk/jsword/src/main/java/org/crosswire/jsword/passage/AccuracyType.java	2012-01-02 05:11:59 UTC (rev 2195)
+++ trunk/jsword/src/main/java/org/crosswire/jsword/passage/AccuracyType.java	2012-01-03 13:53:37 UTC (rev 2196)
@@ -115,7 +115,7 @@
         public Verse createStartVerse(String original, VerseRange verseRangeBasis, String[] parts) throws NoSuchVerseException {
             BibleBook book = BibleBook.getBook(parts[0]);
             int chapter = getChapter(book, parts[1]);
-            int verse = 1;
+            int verse = 0;
             return new Verse(original, book, chapter, verse);
         }
 
@@ -142,7 +142,7 @@
         @Override
         public Verse createStartVerse(String original, VerseRange verseRangeBasis, String[] parts) throws NoSuchVerseException {
             BibleBook book = BibleBook.getBook(parts[0]);
-            return new Verse(original, book, 1, 1);
+            return new Verse(original, book, 0, 0);
         }
 
         @Override
@@ -206,7 +206,7 @@
             }
             BibleBook book = verseRangeBasis.getEnd().getBook();
             int chapter = getChapter(book, parts[0]);
-            return new Verse(original, book, chapter, 1);
+            return new Verse(original, book, chapter, 0);
         }
 
         @Override
@@ -215,7 +215,7 @@
             // and it gets the end of the chapter
             BibleBook book = verseBasis.getBook();
             int chapter = getChapter(book, endParts[0]);
-            return new Verse(endVerseDesc, book, chapter, 1).getLastVerseInChapter();
+            return new Verse(endVerseDesc, book, chapter, 0).getLastVerseInChapter();
         }
     },
 

Modified: trunk/jsword/src/main/java/org/crosswire/jsword/passage/BitwisePassage.java
===================================================================
--- trunk/jsword/src/main/java/org/crosswire/jsword/passage/BitwisePassage.java	2012-01-02 05:11:59 UTC (rev 2195)
+++ trunk/jsword/src/main/java/org/crosswire/jsword/passage/BitwisePassage.java	2012-01-03 13:53:37 UTC (rev 2196)
@@ -215,7 +215,7 @@
         if (that instanceof BitwisePassage) {
             thatStore = ((BitwisePassage) that).store;
         } else {
-            thatStore = new BitSet(BibleInfo.versesInBible() + 1);
+            thatStore = new BitSet(BibleInfo.maximumOrdinal() + 1);
 
             for (Key aKey : that) {
                 int ord = ((Verse) aKey).getOrdinal();
@@ -251,12 +251,12 @@
             raiseEventSuppresion();
             raiseNormalizeProtection();
 
-            int versesInBible = BibleInfo.versesInBible();
-            BitSet newStore = new BitSet(versesInBible + 1);
+            int maximumOrdinal = BibleInfo.maximumOrdinal();
+            BitSet newStore = new BitSet(maximumOrdinal + 1);
 
             for (int i = store.nextSetBit(0); i >= 0; i = store.nextSetBit(i + 1)) {
                 int start = Math.max(1, i - verses);
-                int end = Math.min(versesInBible, i + verses);
+                int end = Math.min(maximumOrdinal, i + verses);
 
                 for (int j = start; j <= end; j++) {
                     newStore.set(j);
@@ -364,7 +364,7 @@
     private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
         optimizeWrites();
 
-        store = new BitSet(BibleInfo.versesInBible() + 1);
+        store = new BitSet(BibleInfo.maximumOrdinal() + 1);
 
         in.defaultReadObject();
 
@@ -379,5 +379,5 @@
     /**
      * The place the real data is stored
      */
-    protected transient BitSet store = new BitSet(BibleInfo.versesInBible() + 1);
+    protected transient BitSet store = new BitSet(BibleInfo.maximumOrdinal() + 1);
 }

Modified: trunk/jsword/src/main/java/org/crosswire/jsword/passage/PassageKeyFactory.java
===================================================================
--- trunk/jsword/src/main/java/org/crosswire/jsword/passage/PassageKeyFactory.java	2012-01-02 05:11:59 UTC (rev 2195)
+++ trunk/jsword/src/main/java/org/crosswire/jsword/passage/PassageKeyFactory.java	2012-01-03 13:53:37 UTC (rev 2196)
@@ -167,13 +167,13 @@
         int ranges = ref.countRanges(RestrictionType.NONE);
 
         // the size in bytes of teach storage method
-        int bitwise_size = BibleInfo.versesInBible() / 8;
+        int bitwise_size = BibleInfo.maximumOrdinal() / 8;
         int ranged_size = (ranges * 4) + 1;
         int distinct_size = (verses * 2) + 1;
 
         // if bitwise is equal smallest
         if (bitwise_size <= ranged_size && bitwise_size <= distinct_size) {
-            int array_size = binarySize(AbstractPassage.METHOD_COUNT) + (BibleInfo.versesInBible() / 8) + 1;
+            int array_size = binarySize(AbstractPassage.METHOD_COUNT) + (BibleInfo.maximumOrdinal() / 8) + 1;
             byte[] buffer = new byte[array_size];
             int index = 0;
 
@@ -195,41 +195,41 @@
             return buffer;
         } else if (distinct_size <= ranged_size) {
             // if distinct is not bigger than ranged
-            int array_size = binarySize(AbstractPassage.METHOD_COUNT) + binarySize(BibleInfo.versesInBible())
-                    + (verses * binarySize(BibleInfo.versesInBible()));
+            int array_size = binarySize(AbstractPassage.METHOD_COUNT) + binarySize(BibleInfo.maximumOrdinal())
+                    + (verses * binarySize(BibleInfo.maximumOrdinal()));
             byte[] buffer = new byte[array_size];
             int index = 0;
 
             // write the Passage type and the number of verses. There must be
             // less than 2**16 verses
             index += toBinary(buffer, index, AbstractPassage.DISTINCT, AbstractPassage.METHOD_COUNT);
-            index += toBinary(buffer, index, verses, BibleInfo.versesInBible());
+            index += toBinary(buffer, index, verses, BibleInfo.maximumOrdinal());
 
             // write the verse ordinals in a loop
             for (Key aKey : ref) {
                 Verse verse = (Verse) aKey;
                 int ord = verse.getOrdinal();
-                index += toBinary(buffer, index, ord, BibleInfo.versesInBible());
+                index += toBinary(buffer, index, ord, BibleInfo.maximumOrdinal());
             }
 
             return buffer;
         } else {
             // otherwise use ranges
-            int array_size = binarySize(AbstractPassage.METHOD_COUNT) + binarySize(BibleInfo.versesInBible() / 2)
-                    + (2 * ranges * binarySize(BibleInfo.versesInBible()));
+            int array_size = binarySize(AbstractPassage.METHOD_COUNT) + binarySize(BibleInfo.maximumOrdinal() / 2)
+                    + (2 * ranges * binarySize(BibleInfo.maximumOrdinal()));
             byte[] buffer = new byte[array_size];
             int index = 0;
 
             // write the Passage type and the number of ranges
             index += toBinary(buffer, index, AbstractPassage.RANGED, AbstractPassage.METHOD_COUNT);
-            index += toBinary(buffer, index, ranges, BibleInfo.versesInBible() / 2);
+            index += toBinary(buffer, index, ranges, BibleInfo.maximumOrdinal() / 2);
 
             // write the verse ordinals in a loop
             Iterator<Key> it = ref.rangeIterator(RestrictionType.NONE);
             while (it.hasNext()) {
                 VerseRange range = (VerseRange) it.next();
-                index += toBinary(buffer, index, range.getStart().getOrdinal(), BibleInfo.versesInBible());
-                index += toBinary(buffer, index, range.getCardinality(), BibleInfo.versesInBible());
+                index += toBinary(buffer, index, range.getStart().getOrdinal(), BibleInfo.maximumOrdinal());
+                index += toBinary(buffer, index, range.getCardinality(), BibleInfo.maximumOrdinal());
             }
 
             // chop to size
@@ -264,7 +264,7 @@
 
         switch (type) {
         case AbstractPassage.BITWISE:
-            for (int ord = 1; ord <= BibleInfo.versesInBible(); ord++) {
+            for (int ord = 1; ord <= BibleInfo.maximumOrdinal(); ord++) {
                 // Which byte should we be viewing
                 int idx0 = (ord / 8) + index[0];
 
@@ -279,18 +279,18 @@
             break;
 
         case AbstractPassage.DISTINCT:
-            int verses = fromBinary(buffer, index, BibleInfo.versesInBible());
+            int verses = fromBinary(buffer, index, BibleInfo.maximumOrdinal());
             for (int i = 0; i < verses; i++) {
-                int ord = fromBinary(buffer, index, BibleInfo.versesInBible());
+                int ord = fromBinary(buffer, index, BibleInfo.maximumOrdinal());
                 ref.add(new Verse(ord));
             }
             break;
 
         case AbstractPassage.RANGED:
-            int ranges = fromBinary(buffer, index, BibleInfo.versesInBible() / 2);
+            int ranges = fromBinary(buffer, index, BibleInfo.maximumOrdinal() / 2);
             for (int i = 0; i < ranges; i++) {
-                int ord = fromBinary(buffer, index, BibleInfo.versesInBible());
-                int len = fromBinary(buffer, index, BibleInfo.versesInBible());
+                int ord = fromBinary(buffer, index, BibleInfo.maximumOrdinal());
+                int len = fromBinary(buffer, index, BibleInfo.maximumOrdinal());
                 ref.add(RestrictionType.NONE.toRange(new Verse(ord), len));
             }
             break;

Modified: trunk/jsword/src/main/java/org/crosswire/jsword/passage/PassageTally.java
===================================================================
--- trunk/jsword/src/main/java/org/crosswire/jsword/passage/PassageTally.java	2012-01-02 05:11:59 UTC (rev 2195)
+++ trunk/jsword/src/main/java/org/crosswire/jsword/passage/PassageTally.java	2012-01-03 13:53:37 UTC (rev 2196)
@@ -415,7 +415,7 @@
         if (that instanceof PassageTally) {
             PassageTally that_rt = (PassageTally) that;
 
-            int vib = BibleInfo.versesInBible();
+            int vib = BibleInfo.maximumOrdinal();
             for (int i = 0; i < vib; i++) {
                 increment(i + 1, that_rt.board[i]);
             }
@@ -445,7 +445,7 @@
         if (that instanceof PassageTally) {
             PassageTally that_rt = (PassageTally) that;
 
-            int vib = BibleInfo.versesInBible();
+            int vib = BibleInfo.maximumOrdinal();
             for (int i = 0; i < vib; i++) {
                 increment(i, -that_rt.board[i - 1]);
             }
@@ -472,7 +472,7 @@
         if (that instanceof PassageTally) {
             PassageTally that_rt = (PassageTally) that;
 
-            int vib = BibleInfo.versesInBible();
+            int vib = BibleInfo.maximumOrdinal();
             for (int i = 0; i < vib; i++) {
                 if (that_rt.board[i] != 0) {
                     kill(i + 1);
@@ -496,7 +496,7 @@
     public void clear() {
         optimizeWrites();
 
-        int vib = BibleInfo.versesInBible();
+        int vib = BibleInfo.maximumOrdinal();
         for (int i = 0; i < vib; i++) {
             board[i] = 0;
         }
@@ -551,7 +551,7 @@
     public void flatten() {
         optimizeWrites();
 
-        int vib = BibleInfo.versesInBible();
+        int vib = BibleInfo.maximumOrdinal();
         for (int i = 0; i < vib; i++) {
             if (board[i] != 0) {
                 board[i] = 1;
@@ -584,7 +584,7 @@
                 }
             }
         } else {
-            int[] new_board = new int[BibleInfo.versesInBible()];
+            int[] new_board = new int[BibleInfo.maximumOrdinal()];
 
             int vib = new_board.length;
             for (int i = 0; i < vib; i++) {
@@ -592,7 +592,7 @@
                     // This could be re-written more simply:
                     // for (int j = -verses; j <= verses; j++) {
                     //     int k = i + j;
-                    //     if (k >= 0 && k < BibleInfo.versesInBible()) {
+                    //     if (k >= 0 && k < BibleInfo.maximumOrdinal()) {
                     //         new_board[k] += board[i] + verses - mod(j);
                     //     }
                     // }
@@ -634,7 +634,7 @@
     private void resetMax() {
         optimizeWrites();
 
-        int vib = BibleInfo.versesInBible();
+        int vib = BibleInfo.maximumOrdinal();
         max = 0;
         size = 0;
         for (int i = 0; i < vib; i++) {
@@ -752,7 +752,7 @@
     /**
      * The tally board itself
      */
-    protected int[] board = new int[BibleInfo.versesInBible()];
+    protected int[] board = new int[BibleInfo.maximumOrdinal()];
 
     /**
      * The maximum tally possible
@@ -791,7 +791,7 @@
          * @see java.util.Iterator#hasNext()
          */
         public boolean hasNext() {
-            return next <= BibleInfo.versesInBible();
+            return next <= BibleInfo.maximumOrdinal();
         }
 
         /* (non-Javadoc)
@@ -799,7 +799,7 @@
          */
         public Key next() throws NoSuchElementException {
             try {
-                if (next > BibleInfo.versesInBible()) {
+                if (next > BibleInfo.maximumOrdinal()) {
                     throw new NoSuchElementException();
                 }
 
@@ -826,7 +826,7 @@
         private void calculateNext() {
             do {
                 next++;
-            } while (next <= BibleInfo.versesInBible() && board[next - 1] == 0);
+            } while (next <= BibleInfo.maximumOrdinal() && board[next - 1] == 0);
         }
 
         /** What is the next Verse to be considered */
@@ -845,7 +845,7 @@
         protected OrderedVerseIterator(int[] board) {
             TreeSet<TalliedVerse> output = new TreeSet<TalliedVerse>();
 
-            int vib = BibleInfo.versesInBible();
+            int vib = BibleInfo.maximumOrdinal();
             for (int i = 0; i < vib; i++) {
                 if (board[i] != 0) {
                     output.add(new TalliedVerse(i + 1, board[i]));

Modified: trunk/jsword/src/main/java/org/crosswire/jsword/passage/Verse.java
===================================================================
--- trunk/jsword/src/main/java/org/crosswire/jsword/passage/Verse.java	2012-01-02 05:11:59 UTC (rev 2195)
+++ trunk/jsword/src/main/java/org/crosswire/jsword/passage/Verse.java	2012-01-03 13:53:37 UTC (rev 2196)
@@ -338,7 +338,7 @@
      */
     public Verse add(int extra) {
         try {
-            int new_ordinal = Math.min(getOrdinal() + extra, BibleInfo.versesInBible());
+            int new_ordinal = Math.min(getOrdinal() + extra, BibleInfo.maximumOrdinal());
             return new Verse(new_ordinal);
         } catch (NoSuchVerseException ex) {
             assert false : ex;
@@ -379,7 +379,7 @@
      * @return true or false ...
      */
     public boolean isStartOfChapter() {
-        return verse == 1;
+        return verse == 1 || verse == 0;
     }
 
     /**
@@ -402,7 +402,7 @@
      * @return true or false ...
      */
     public boolean isStartOfBook() {
-        return verse == 1 && chapter == 1;
+        return (verse == 1 || verse == 0) && (chapter == 1 || chapter == 0);
     }
 
     /**
@@ -449,7 +449,7 @@
      */
     public int getOrdinal() {
         try {
-            return BibleInfo.verseOrdinal(this);
+            return BibleInfo.getOrdinal(this);
         } catch (NoSuchVerseException ex) {
             // A verse should never be illegal so
             log.error("ref=" + book + ", " + chapter + ", " + verse);

Modified: trunk/jsword/src/main/java/org/crosswire/jsword/versification/BibleBook.java
===================================================================
--- trunk/jsword/src/main/java/org/crosswire/jsword/versification/BibleBook.java	2012-01-02 05:11:59 UTC (rev 2195)
+++ trunk/jsword/src/main/java/org/crosswire/jsword/versification/BibleBook.java	2012-01-03 13:53:37 UTC (rev 2196)
@@ -10,6 +10,10 @@
  * A BibleBook is a book of the Bible. It may or may not be canonical.
  */
 public enum BibleBook {
+    // JSword introduction to the Bible
+    INTRO_BIBLE("Intro.Bible"),
+    // JSword introduction to the Old Testament
+    INTRO_OT("Intro.OT"),
     // Old Testament
     GEN("Gen"),
     EXOD("Exod"),
@@ -50,6 +54,8 @@
     HAG("Hag"),
     ZECH("Zech"),
     MAL("Mal"),
+    // JSword introduction to the New Testament
+    INTRO_NT("Intro.NT"),
     // New Testament
     MATT("Matt"),
     MARK("Mark"),

Modified: trunk/jsword/src/main/java/org/crosswire/jsword/versification/BibleInfo.java
===================================================================
--- trunk/jsword/src/main/java/org/crosswire/jsword/versification/BibleInfo.java	2012-01-02 05:11:59 UTC (rev 2195)
+++ trunk/jsword/src/main/java/org/crosswire/jsword/versification/BibleInfo.java	2012-01-03 13:53:37 UTC (rev 2196)
@@ -22,7 +22,6 @@
 package org.crosswire.jsword.versification;
 
 import java.io.PrintStream;
-import java.util.EnumSet;
 
 import org.crosswire.jsword.JSMsg;
 import org.crosswire.jsword.JSOtherMsg;
@@ -67,21 +66,10 @@
     public static BibleBook getPreviousBook(BibleBook book) {
         return book.previous();
     }
-    /**
-     * Get number of a book from its name.
-     * 
-     * @param find
-     *            The string to identify
-     * @return The BibleBook, On error null
-     * @deprecated use {@link #BibleBook.getBook(String)}
-     */
-    @Deprecated
-    public static BibleBook getBook(String find) {
-        return BibleBook.getBook(find);
-    }
 
     /**
      * Get the ordered array of books belonging to this versification.
+     * This includes the 3 introductions.
      * 
      * @return the array of books
      */
@@ -90,54 +78,11 @@
     }
 
     /**
-     * Is the given string a valid book name. If this method returns true then
-     * getBook() will return a BibleBook and not throw an exception.
+     * Get the last valid chapter number for a book.
      * 
-     * @param find
-     *            The string to identify
-     * @return true when the book name is recognized
-     * @deprecated use {@link #BibleBook.isBook(String)}
-     */
-    @Deprecated
-    public static boolean isBookName(String find) {
-        return BibleBook.isBook(find);
-    }
-
-    /**
-     * Count the books in the Bible.
-     * 
-     * @return 66 always - the number of books in the Bible
-     */
-    public static int booksInBible() {
-        return BOOKS_IN_BIBLE;
-    }
-
-    /**
-     * Count the chapters in the Bible.
-     * 
-     * @return 1189 always - the number of chapters in the Bible
-     */
-    public static int chaptersInBible() {
-        return CHAPTERS_IN_BIBLE;
-    }
-
-    /**
-     * Count the verses in the Bible. This counts possible verses, so this
-     * number is not affected by some versions missing out some verses as 'there
-     * in error'
-     * 
-     * @return 31102 always - the number of verses in the Bible
-     */
-    public static int versesInBible() {
-        return VERSES_IN_BIBLE;
-    }
-
-    /**
-     * Count the chapters in this book.
-     * 
      * @param book
      *            The book part of the reference.
-     * @return The number of chapters
+     * @return The last valid chapter number for a book.
      * @exception NoSuchVerseException
      *                If the book is not valid
      */
@@ -146,7 +91,7 @@
         // The exception is actually thrown, then it is a lot slower
         // I'd like to think that the norm is to get it right
         try {
-            return CHAPTERS_IN_BOOK[book.ordinal()];
+            return VERSES_IN_CHAPTER[book.ordinal()].length - 1;
         } catch (NullPointerException ex) {
             return 0;
         } catch (ArrayIndexOutOfBoundsException ex) {
@@ -155,13 +100,13 @@
     }
 
     /**
-     * Count the verses in a chapter.
+     * Get the last valid verse number for a chapter.
      * 
      * @param book
      *            The book part of the reference.
      * @param chapter
      *            The current chapter
-     * @return The number of verses
+     * @return The last valid verse number for a chapter
      * @exception NoSuchVerseException
      *                If the book or chapter number is not valid
      */
@@ -170,7 +115,7 @@
         // The exception is actually thrown, then it is a lot slower
         // I'd like to think that the norm is to get it right
         try {
-            return VERSES_IN_CHAPTER[book.ordinal()][chapter - 1];
+            return VERSES_IN_CHAPTER[book.ordinal()][chapter];
         } catch (NullPointerException ex) {
             return 0;
         } catch (ArrayIndexOutOfBoundsException ex) {
@@ -179,30 +124,73 @@
     }
 
     /**
-     * Count the verses in a book.
+     * The maximum number of verses in the Bible, including module, testament, book and chapter introductions.
      * 
-     * @param book
-     *            The book part of the reference.
-     * @return The number of verses
+     * @return the number of addressable verses in this versification.
+     */
+    public static int maximumOrdinal() {
+        // The sentinel value in ORDINAL_AT_START_OF_CHAPTER points to what would be the book introduction
+        // of the book following the last book in the NT, typically REV.
+        return ORDINAL_AT_START_OF_CHAPTER[ORDINAL_AT_START_OF_CHAPTER.length - 1][0] - 1;
+    }
+
+    /**
+     * Where does this verse come in the Bible. The value that this returns should be treated as opaque, useful for a bit set.
+     * The introductions to the Book, OT/NT Testaments, Bible books and chapters are included here.
+     * <ul>
+     * <li>0 - INTRO_BIBLE 0:0 - The Book introduction</li>
+     * <li>1 - INTRO_OT 0:0 - The OT Testament introduction</li>
+     * <li>2 - Gen 0:0 - The introduction to the book of Genesis</li>
+     * <li>3 - Gen 1:0 - The introduction to Genesis chapter 1</li>
+     * <li>4 - Gen 1:1</li>
+     * <li>...</li>
+     * <li>35 - Gen 1:31</li>
+     * <li>36 - Gen 2:0 - The introduction to Genesis chapter 2</li>
+     * <li>37 - Gen 2:1</li>
+     * <li>...</li>
+     * <li>n - last verse in the OT</li>
+     * <li>n + 1 - INTRO_NT, 0, 0 - The New Testament introduction</li>
+     * <li>n + 2 - Matt 0:0 - The introduction to Matt</li>
+     * <li>n + 3 - Matt 1:0 - The introduction to Matt 1</li>
+     * <li>n + 4 - Matt 1:1</li>
+     * <li>...</li>
+     * </ul>
+     * 
+     * @param verse
+     *            The verse to convert
+     * @return The ordinal number of verses
      * @exception NoSuchVerseException
-     *                If the book is not valid
+     *                If the reference is illegal
      */
-    public static int versesInBook(BibleBook book) throws NoSuchVerseException {
-        // This is faster than doing the check explicitly, unless
-        // The exception is actually thrown, then it is a lot slower
-        // I'd like to think that the norm is to get it right
-        try {
-            return VERSES_IN_BOOK[book.ordinal()];
-        } catch (NullPointerException ex) {
-            return 0;
-        } catch (ArrayIndexOutOfBoundsException ex) {
-            return 0;
-        }
+    public static int getOrdinal(Verse verse) throws NoSuchVerseException {
+        BibleBook b = verse.getBook();
+        int c = verse.getChapter();
+        int v = verse.getVerse();
+        validate(b, c, v);
+        return ORDINAL_AT_START_OF_CHAPTER[b.ordinal()][c] + v;
     }
 
     /**
-     * Where does this verse come in the Bible. Starting with Gen 1:1 as number
-     * 1 counting up one per verse and not resetting at each new chapter.
+     * Where does this verse come in the Bible. The value that this returns should be treated as opaque, useful for a bit set.
+     * The introductions to the Book, OT/NT Testaments, Bible books and chapters are included here.
+     * <ul>
+     * <li>0 - INTRO_BIBLE 0:0 - The Book introduction</li>
+     * <li>1 - INTRO_OT 0:0 - The OT Testament introduction</li>
+     * <li>2 - Gen 0:0 - The introduction to the book of Genesis</li>
+     * <li>3 - Gen 1:0 - The introduction to Genesis chapter 1</li>
+     * <li>4 - Gen 1:1</li>
+     * <li>...</li>
+     * <li>35 - Gen 1:31</li>
+     * <li>36 - Gen 2:0 - The introduction to Genesis chapter 2</li>
+     * <li>37 - Genesis 2:1</li>
+     * <li>...</li>
+     * <li>n - last verse in the OT</li>
+     * <li>0 - INTRO_NT, 0, 0 - The New Testament introduction</li>
+     * <li>1 - Matt 0:0 - The introduction to Matt</li>
+     * <li>2 - Matt 1:0 - The introduction to Matt 1</li>
+     * <li>3 - Matt 1:1</li>
+     * <li>...</li>
+     * </ul>
      * 
      * @param verse
      *            The verse to convert
@@ -210,14 +198,20 @@
      * @exception NoSuchVerseException
      *                If the reference is illegal
      */
-    public static int verseOrdinal(Verse verse) throws NoSuchVerseException {
-        validate(verse.getBook(), verse.getChapter(), verse.getVerse());
-        return ORDINAL_AT_START_OF_CHAPTER[verse.getBook().ordinal()][verse.getChapter() - 1] + verse.getVerse() - 1;
+    public static int getTestamentOrdinal(Verse verse) throws NoSuchVerseException {
+        BibleBook b = verse.getBook();
+        int c = verse.getChapter();
+        int v = verse.getVerse();
+        validate(b, c, v);
+        int ordinal = ORDINAL_AT_START_OF_CHAPTER[b.ordinal()][c] + v;
+        if (ordinal >= NT_ORDINAL_START) {
+            return ordinal - NT_ORDINAL_START + 1;
+        }
+        return ordinal;
     }
 
     /**
-     * Where does this verse come in the Bible. Starting with Gen 1:1 as number
-     * 1 counting up one per verse and not resetting at each new chapter.
+     * Where does this verse come in the Bible. This will unwind the value returned by getOrdinal(Verse).
      * 
      * @param ordinal
      *            The ordinal number of the verse
@@ -226,28 +220,63 @@
      *                If the reference is illegal
      */
     public static Verse decodeOrdinal(int ordinal) throws NoSuchVerseException {
-        if (ordinal < 1 || ordinal > BibleInfo.versesInBible()) {
-            throw new NoSuchVerseException(JSOtherMsg.lookupText("Ordinal must be between 1 and {0,number,integer} (given {1,number,integer}).", Integer.valueOf(BibleInfo.versesInBible()), Integer.valueOf(ordinal)));
+        BibleBook book = null;
+        int bookIndex = -1;
+        int chapterIndex = 0;
+        int verse = 0;
+
+        if (ordinal < 0 || ordinal > BibleInfo.maximumOrdinal()) {
+            throw new NoSuchVerseException(JSOtherMsg.lookupText("Ordinal must be between 0 and {0,number,integer} (given {1,number,integer}).", Integer.valueOf(BibleInfo.maximumOrdinal()), Integer.valueOf(ordinal)));
         }
 
-        // The ORDINAL_AT_START_OF_BOOK has a sentinel value at the end of the array
-        // Therefore, subtract 2 instead of 1
-        int lastBook = ORDINAL_AT_START_OF_BOOK.length - 2;
-        // for (BibleBook book : BibleBook.values()) {
-        for (BibleBook book: EnumSet.range(BibleBook.GEN, BibleBook.REV)) {
-            int b = book.ordinal();
-            if (b <= lastBook && ordinal >= ORDINAL_AT_START_OF_BOOK[b] && ordinal < ORDINAL_AT_START_OF_BOOK[b + 1]) {
-                int cib = BibleInfo.chaptersInBook(book);
-                for (int c = cib; c > 0; c--) {
-                    if (ordinal >= ORDINAL_AT_START_OF_CHAPTER[b][c - 1]) {
-                        return new Verse(book, c, ordinal - ORDINAL_AT_START_OF_CHAPTER[b][c - 1] + 1);
-                    }
-                }
+        // Handle three special cases
+        // Book/Module introduction
+        if (ordinal == 0) {
+            return new Verse(BibleBook.INTRO_BIBLE, 0, 0);
+        }
+
+        // OT introduction
+        if (ordinal == 1) {
+            return new Verse(BibleBook.INTRO_OT, 0, 0);
+        }
+
+        // NT introduction
+        if (ordinal == NT_ORDINAL_START) {
+            return new Verse(BibleBook.INTRO_NT, 0, 0);
+        }
+
+        // The ORDINAL_AT_START_OF_CHAPTER has a sentinel value at the end of the array
+        // Therefore, subtract  1
+        int lastBook = ORDINAL_AT_START_OF_CHAPTER.length - 1;
+        for (int b = lastBook; b >= 0; b--) {
+            // A book has a slot for a heading followed by a slot for a chapter heading.
+            // These precede the start of the chapter.
+            if (ordinal >= ORDINAL_AT_START_OF_CHAPTER[b][0]) {
+                bookIndex = b;
+                break;
             }
         }
 
-        assert false;
-        return new Verse(BibleBook.GEN, 1, 1);
+        // There is a gap for the New Testament introduction.
+        // This occurs when ordinal is one less than the book introduction of the next book.
+        if (bookIndex == OT_LAST_BOOK && ordinal == ORDINAL_AT_START_OF_CHAPTER[bookIndex + 1][0] - 1) {
+            bookIndex++;
+        }
+
+        book = BibleBook.getBooks()[bookIndex];
+        int cib = BibleInfo.chaptersInBook(book);
+        for (int c = cib; c >= 0; c--) {
+            if (ordinal >= ORDINAL_AT_START_OF_CHAPTER[bookIndex][c]) {
+                chapterIndex = c;
+                break;
+            }
+        }
+
+        if (chapterIndex > 0) {
+            verse = ordinal - ORDINAL_AT_START_OF_CHAPTER[bookIndex][chapterIndex];
+        }
+        
+        return new Verse(book, chapterIndex, verse);
     }
 
     /**
@@ -268,27 +297,29 @@
     public static void validate(BibleBook book, int chapter, int verse) throws NoSuchVerseException {
 
         // Check the chapter
-        if (chapter < 1 || chapter > chaptersInBook(book)) {
+        int maxChapter = chaptersInBook(book);
+        if (chapter < 0 || chapter > maxChapter) {
             // TRANSLATOR: The user supplied a chapter that was out of bounds. This tells them what is allowed.
-            // {0} is the lowest value that is allowed. Currently this is 1, later it will be 0.
+            // {0} is the lowest value that is allowed. This is always 0.
             // {1,number,integer} is the place holder for the highest chapter number in the book. The format is special in that it will present it in the user's preferred format.
             // {2} is a placeholder for the Bible book name.
             // {3,number,integer} is a placeholder for the chapter number that the user gave.
             throw new NoSuchVerseException(JSMsg.gettext("Chapter should be between {0} and {1,number,integer} for {2} (given {3,number,integer}).",
-                    Integer.valueOf(1), Integer.valueOf(chaptersInBook(book)), getPreferredBookName(book), Integer.valueOf(chapter)
+                    Integer.valueOf(0), Integer.valueOf(maxChapter), book.getPreferredName(), Integer.valueOf(chapter)
                     ));
         }
 
         // Check the verse
-        if (verse < 1 || verse > versesInChapter(book, chapter)) {
+        int maxVerse = versesInChapter(book, chapter);
+        if (verse < 0 || verse > maxVerse) {
             // TRANSLATOR: The user supplied a verse number that was out of bounds. This tells them what is allowed.
-            // {0} is the lowest value that is allowed. Currently this is 1, later it will be 0.
+            // {0} is the lowest value that is allowed. This is always 0.
             // {1,number,integer} is the place holder for the highest verse number in the chapter. The format is special in that it will present it in the user's preferred format.
             // {2} is a placeholder for the Bible book name.
             // {3,number,integer} is a placeholder for the chapter number that the user gave.
             // {4,number,integer} is a placeholder for the verse number that the user gave.
             throw new NoSuchVerseException(JSMsg.gettext("Verse should be between {0} and {1,number,integer} for {2} {3,number,integer} (given {4,number,integer}).",
-                    Integer.valueOf(1), Integer.valueOf(versesInChapter(book, chapter)), getPreferredBookName(book), Integer.valueOf(chapter), Integer.valueOf(verse)
+                    Integer.valueOf(0), Integer.valueOf(maxVerse), book.getPreferredName(), Integer.valueOf(chapter), Integer.valueOf(verse)
                     ));
         }
     }
@@ -305,7 +336,7 @@
      * or even "Rev 99:99" to mean the last verse in the Bible.
      * <p>
      * However I have not implemented this because I've used a different
-     * convention: "Gen 1:$" (OLB compatible) or "Gen 1:ff" (common comentary
+     * convention: "Gen 1:$" (OLB compatible) or "Gen 1:ff" (common commentary
      * usage) to mean the end of the chapter - So the functionality is there
      * anyway.
      * <p>
@@ -332,11 +363,11 @@
                 patchedBook = BibleBook.GEN;
             }
             // If they are too small
-            if (patchedChapter <= 0) {
-                patchedChapter = 1;
+            if (patchedChapter < 0) {
+                patchedChapter = 0;
             }
-            if (patchedVerse <= 0) {
-                patchedVerse = 1;
+            if (patchedVerse < 0) {
+                patchedVerse = 0;
             }
 
             while (patchedChapter > chaptersInBook(patchedBook)) {
@@ -376,6 +407,628 @@
     }
 
     /**
+     * Count the books in the Bible.
+     * 
+     * @return The number of books in the Bible, including the three introductions
+     */
+    public static int booksInBible() {
+        return ORDINAL_AT_START_OF_CHAPTER.length - 1;
+    }
+
+    /** Constant for the max verse number in each chapter */
+    private static final int[][] VERSES_IN_CHAPTER =
+    {
+        {  0 },
+        {  0 },
+        {  0, 31, 25, 24, 26, 32, 22, 24, 22, 29, 32, 32, 20, 18, 24, 21, 16, 27, 33, 38, 18, 34, 24, 20, 67, 34, 35, 46, 22, 35, 43, 55, 32, 20, 31, 29, 43, 36, 30, 23, 23, 57, 38, 34, 34, 28, 34, 31, 22, 33, 26 },
+        {  0, 22, 25, 22, 31, 23, 30, 25, 32, 35, 29, 10, 51, 22, 31, 27, 36, 16, 27, 25, 26, 36, 31, 33, 18, 40, 37, 21, 43, 46, 38, 18, 35, 23, 35, 35, 38, 29, 31, 43, 38 },
+        {  0, 17, 16, 17, 35, 19, 30, 38, 36, 24, 20, 47,  8, 59, 57, 33, 34, 16, 30, 37, 27, 24, 33, 44, 23, 55, 46, 34 },
+        {  0, 54, 34, 51, 49, 31, 27, 89, 26, 23, 36, 35, 16, 33, 45, 41, 50, 13, 32, 22, 29, 35, 41, 30, 25, 18, 65, 23, 31, 40, 16, 54, 42, 56, 29, 34, 13 },
+        {  0, 46, 37, 29, 49, 33, 25, 26, 20, 29, 22, 32, 32, 18, 29, 23, 22, 20, 22, 21, 20, 23, 30, 25, 22, 19, 19, 26, 68, 29, 20, 30, 52, 29, 12 },
+        {  0, 18, 24, 17, 24, 15, 27, 26, 35, 27, 43, 23, 24, 33, 15, 63, 10, 18, 28, 51,  9, 45, 34, 16, 33 },
+        {  0, 36, 23, 31, 24, 31, 40, 25, 35, 57, 18, 40, 15, 25, 20, 20, 31, 13, 31, 30, 48, 25 },
+        {  0, 22, 23, 18, 22 },
+        {  0, 28, 36, 21, 22, 12, 21, 17, 22, 27, 27, 15, 25, 23, 52, 35, 23, 58, 30, 24, 42, 15, 23, 29, 22, 44, 25, 12, 25, 11, 31, 13 },
+        {  0, 27, 32, 39, 12, 25, 23, 29, 18, 13, 19, 27, 31, 39, 33, 37, 23, 29, 33, 43, 26, 22, 51, 39, 25 },
+        {  0, 53, 46, 28, 34, 18, 38, 51, 66, 28, 29, 43, 33, 34, 31, 34, 34, 24, 46, 21, 43, 29, 53 },
+        {  0, 18, 25, 27, 44, 27, 33, 20, 29, 37, 36, 21, 21, 25, 29, 38, 20, 41, 37, 37, 21, 26, 20, 37, 20, 30 },
+        {  0, 54, 55, 24, 43, 26, 81, 40, 40, 44, 14, 47, 40, 14, 17, 29, 43, 27, 17, 19,  8, 30, 19, 32, 31, 31, 32, 34, 21, 30 },
+        {  0, 17, 18, 17, 22, 14, 42, 22, 18, 31, 19, 23, 16, 22, 15, 19, 14, 19, 34, 11, 37, 20, 12, 21, 27, 28, 23,  9, 27, 36, 27, 21, 33, 25, 33, 27, 23 },
+        {  0, 11, 70, 13, 24, 17, 22, 28, 36, 15, 44 },
+        {  0, 11, 20, 32, 23, 19, 19, 73, 18, 38, 39, 36, 47, 31 },
+        {  0, 22, 23, 15, 17, 14, 14, 10, 17, 32,  3 },
+        {  0, 22, 13, 26, 21, 27, 30, 21, 22, 35, 22, 20, 25, 28, 22, 35, 22, 16, 21, 29, 29, 34, 30, 17, 25,  6, 14, 23, 28, 25, 31, 40, 22, 33, 37, 16, 33, 24, 41, 30, 24, 34, 17 },
+        {  0,  6, 12,  8,  8, 12, 10, 17,  9, 20, 18,  7,  8,  6,  7,  5, 11, 15, 50, 14,  9, 13, 31,  6, 10, 22, 12, 14,  9, 11, 12, 24, 11, 22, 22, 28, 12, 40, 22, 13, 17, 13, 11,  5, 26, 17, 11,  9, 14, 20, 23, 19,  9,  6,  7, 23, 13, 11, 11, 17, 12,  8, 12, 11, 10, 13, 20,  7, 35, 36,  5, 24, 20, 28, 23, 10, 12, 20, 72, 13, 19, 16,  8, 18, 12, 13, 17,  7, 18, 52, 17, 16, 15,  5, 23, 11, 13, 12,  9,  9,  5,  8, 28, 22, 35, 45, 48, 43, 13, 31,  7, 10, 10,  9,  8, 18, 19,  2, 29, 176,  7,  8,  9,  4,  8,  5,  6,  5,  6,  8,  8,  3, 18,  3,  3, 21, 26, 9,  8, 24, 13, 10,  7, 12, 15, 21, 10, 20, 14,  9,  6 },
+        {  0, 33, 22, 35, 27, 23, 35, 27, 36, 18, 32, 31, 28, 25, 35, 33, 33, 28, 24, 29, 30, 31, 29, 35, 34, 28, 28, 27, 28, 27, 33, 31 },
+        {  0, 18, 26, 22, 16, 20, 12, 29, 17, 18, 20, 10, 14 },
+        {  0, 17, 17, 11, 16, 16, 13, 13, 14 },
+        {  0, 31, 22, 26,  6, 30, 13, 25, 22, 21, 34, 16,  6, 22, 32,  9, 14, 14,  7, 25,  6, 17, 25, 18, 23, 12, 21, 13, 29, 24, 33,  9, 20, 24, 17, 10, 22, 38, 22,  8, 31, 29, 25, 28, 28, 25, 13, 15, 22, 26, 11, 23, 15, 12, 17, 13, 12, 21, 14, 21, 22, 11, 12, 19, 12, 25, 24 },
+        {  0, 19, 37, 25, 31, 31, 30, 34, 22, 26, 25, 23, 17, 27, 22, 21, 21, 27, 23, 15, 18, 14, 30, 40, 10, 38, 24, 22, 17, 32, 24, 40, 44, 26, 22, 19, 32, 21, 28, 18, 16, 18, 22, 13, 30,  5, 28,  7, 47, 39, 46, 64, 34 },
+        {  0, 22, 22, 66, 22, 22 },
+        {  0, 28, 10, 27, 17, 17, 14, 27, 18, 11, 22, 25, 28, 23, 23,  8, 63, 24, 32, 14, 49, 32, 31, 49, 27, 17, 21, 36, 26, 21, 26, 18, 32, 33, 31, 15, 38, 28, 23, 29, 49, 26, 20, 27, 31, 25, 24, 23, 35 },
+        {  0, 21, 49, 30, 37, 31, 28, 28, 27, 27, 21, 45, 13 },
+        {  0, 11, 23,  5, 19, 15, 11, 16, 14, 17, 15, 12, 14, 16,  9 },
+        {  0, 20, 32, 21 },
+        {  0, 15, 16, 15, 13, 27, 14, 17, 14, 15 },
+        {  0, 21 },
+        {  0, 17, 10, 10, 11 },
+        {  0, 16, 13, 12, 13, 15, 16, 20 },
+        {  0, 15, 13, 19 },
+        {  0, 17, 20, 19 },
+        {  0, 18, 15, 20 },
+        {  0, 15, 23 },
+        {  0, 21, 13, 10, 14, 11, 15, 14, 23, 17, 12, 17, 14,  9, 21 },
+        {  0, 14, 17, 18,  6 },
+        {  0 },
+        {  0, 25, 23, 17, 25, 48, 34, 29, 34, 38, 42, 30, 50, 58, 36, 39, 28, 27, 35, 30, 34, 46, 46, 39, 51, 46, 75, 66, 20 },
+        {  0, 45, 28, 35, 41, 43, 56, 37, 38, 50, 52, 33, 44, 37, 72, 47, 20 },
+        {  0, 80, 52, 38, 44, 39, 49, 50, 56, 62, 42, 54, 59, 35, 35, 32, 31, 37, 43, 48, 47, 38, 71, 56, 53 },
+        {  0, 51, 25, 36, 54, 47, 71, 53, 59, 41, 42, 57, 50, 38, 31, 27, 33, 26, 40, 42, 31, 25 },
+        {  0, 26, 47, 26, 37, 42, 15, 60, 40, 43, 48, 30, 25, 52, 28, 41, 40, 34, 28, 41, 38, 40, 30, 35, 27, 27, 32, 44, 31 },
+        {  0, 32, 29, 31, 25, 21, 23, 25, 39, 33, 21, 36, 21, 14, 23, 33, 27 },
+        {  0, 31, 16, 23, 21, 13, 20, 40, 13, 27, 33, 34, 31, 13, 40, 58, 24 },
+        {  0, 24, 17, 18, 18, 21, 18, 16, 24, 15, 18, 33, 21, 14 },
+        {  0, 24, 21, 29, 31, 26, 18 },
+        {  0, 23, 22, 21, 32, 33, 24 },
+        {  0, 30, 30, 21, 23 },
+        {  0, 29, 23, 25, 18 },
+        {  0, 10, 20, 13, 18, 28 },
+        {  0, 12, 17, 18 },
+        {  0, 20, 15, 16, 16, 25, 21 },
+        {  0, 18, 26, 17, 22 },
+        {  0, 16, 15, 15 },
+        {  0, 25 },
+        {  0, 14, 18, 19, 16, 14, 20, 28, 13, 28, 39, 40, 29, 25 },
+        {  0, 27, 26, 18, 17, 20 },
+        {  0, 25, 25, 22, 19, 14 },
+        {  0, 21, 22, 18 },
+        {  0, 10, 29, 24, 21, 21 },
+        {  0, 13 },
+        {  0, 14 },
+        {  0, 25 },
+        {  0, 20, 29, 22, 11, 14, 17, 17, 13, 21, 11, 19, 17, 18, 20,  8, 21, 18, 24, 21, 15, 27, 21 },
+    };
+
+    /**
+     * Constant for the ordinal number of the first verse in each chapter.
+     */
+    // Note the sentinel at the end of the array is one greater
+    // than the last ordinal in the last book
+    private static final int[][] ORDINAL_AT_START_OF_CHAPTER =
+    {
+        // Bible Introduction
+        {
+            0,
+        },
+        // Old Testament Introduction
+        {
+            1,
+        },
+        // Gen
+        { 
+                2,     3,    35,    61,    86,   113,   146,   169,   194,   217, 
+              247,   280,   313,   334,   353,   378,   400,   417,   445,   479, 
+              518,   537,   572,   597,   618,   686,   721,   757,   804,   827, 
+              863,   907,   963,   996,  1017,  1049,  1079,  1123,  1160,  1191, 
+             1215,  1239,  1297,  1336,  1371,  1406,  1435,  1470,  1502,  1525, 
+             1559, 
+        },
+        // Exod
+        { 
+             1586,  1587,  1610,  1636,  1659,  1691,  1715,  1746,  1772,  1805, 
+             1841,  1871,  1882,  1934,  1957,  1989,  2017,  2054,  2071,  2099, 
+             2125,  2152,  2189,  2221,  2255,  2274,  2315,  2353,  2375,  2419, 
+             2466,  2505,  2524,  2560,  2584,  2620,  2656,  2695,  2725,  2757, 
+             2801, 
+        },
+        // Lev
+        { 
+             2840,  2841,  2859,  2876,  2894,  2930,  2950,  2981,  3020,  3057, 
+             3082,  3103,  3151,  3160,  3220,  3278,  3312,  3347,  3364,  3395, 
+             3433,  3461,  3486,  3520,  3565,  3589,  3645,  3692, 
+        },
+        // Num
+        { 
+             3727,  3728,  3783,  3818,  3870,  3920,  3952,  3980,  4070,  4097, 
+             4121,  4158,  4194,  4211,  4245,  4291,  4333,  4384,  4398,  4431, 
+             4454,  4484,  4520,  4562,  4593,  4619,  4638,  4704,  4728,  4760, 
+             4801,  4818,  4873,  4916,  4973,  5003,  5038, 
+        },
+        // Deut
+        { 
+             5052,  5053,  5100,  5138,  5168,  5218,  5252,  5278,  5305,  5326, 
+             5356,  5379,  5412,  5445,  5464,  5494,  5518,  5541,  5562,  5585, 
+             5607,  5628,  5652,  5683,  5709,  5732,  5752,  5772,  5799,  5868, 
+             5898,  5919,  5950,  6003,  6033, 
+        },
+        // Josh
+        { 
+             6046,  6047,  6066,  6091,  6109,  6134,  6150,  6178,  6205,  6241, 
+             6269,  6313,  6337,  6362,  6396,  6412,  6476,  6487,  6506,  6535, 
+             6587,  6597,  6643,  6678,  6695, 
+        },
+        // Judg
+        { 
+             6729,  6730,  6767,  6791,  6823,  6848,  6880,  6921,  6947,  6983, 
+             7041,  7060,  7101,  7117,  7143,  7164,  7185,  7217,  7231,  7263, 
+             7294,  7343, 
+        },
+        // Ruth
+        { 
+             7369,  7370,  7393,  7417,  7436, 
+        },
+        // 1Sam
+        { 
+             7459,  7460,  7489,  7526,  7548,  7571,  7584,  7606,  7624,  7647, 
+             7675,  7703,  7719,  7745,  7769,  7822,  7858,  7882,  7941,  7972, 
+             7997,  8040,  8056,  8080,  8110,  8133,  8178,  8204,  8217,  8243, 
+             8255,  8287, 
+        },
+        // 2Sam
+        { 
+             8301,  8302,  8330,  8363,  8403,  8416,  8442,  8466,  8496,  8515, 
+             8529,  8549,  8577,  8609,  8649,  8683,  8721,  8745,  8775,  8809, 
+             8853,  8880,  8903,  8955,  8995, 
+        },
+        // 1Kgs
+        { 
+             9021,  9022,  9076,  9123,  9152,  9187,  9206,  9245,  9297,  9364, 
+             9393,  9423,  9467,  9501,  9536,  9568,  9603,  9638,  9663,  9710, 
+             9732,  9776,  9806, 
+        },
+        // 2Kgs
+        { 
+             9860,  9861,  9880,  9906,  9934,  9979, 10007, 10041, 10062, 10092, 
+            10130, 10167, 10189, 10211, 10237, 10267, 10306, 10327, 10369, 10407, 
+            10445, 10467, 10494, 10515, 10553, 10574, 
+        },
+        // 1Chr
+        { 
+            10605, 10606, 10661, 10717, 10742, 10786, 10813, 10895, 10936, 10977, 
+            11022, 11037, 11085, 11126, 11141, 11159, 11189, 11233, 11261, 11279, 
+            11299, 11308, 11339, 11359, 11392, 11424, 11456, 11489, 11524, 11546, 
+        },
+        // 2Chr
+        { 
+            11577, 11578, 11596, 11615, 11633, 11656, 11671, 11714, 11737, 11756, 
+            11788, 11808, 11832, 11849, 11872, 11888, 11908, 11923, 11943, 11978, 
+            11990, 12028, 12049, 12062, 12084, 12112, 12141, 12165, 12175, 12203, 
+            12240, 12268, 12290, 12324, 12350, 12384, 12412, 
+        },
+        // Ezra
+        { 
+            12436, 12437, 12449, 12520, 12534, 12559, 12577, 12600, 12629, 12666, 
+            12682, 
+        },
+        // Neh
+        { 
+            12727, 12728, 12740, 12761, 12794, 12818, 12838, 12858, 12932, 12951, 
+            12990, 13030, 13067, 13115, 
+        },
+        // Esth
+        { 
+            13147, 13148, 13171, 13195, 13211, 13229, 13244, 13259, 13270, 13288, 
+            13321, 
+        },
+        // Job
+        { 
+            13325, 13326, 13349, 13363, 13390, 13412, 13440, 13471, 13493, 13516, 
+            13552, 13575, 13596, 13622, 13651, 13674, 13710, 13733, 13750, 13772, 
+            13802, 13832, 13867, 13898, 13916, 13942, 13949, 13964, 13988, 14017, 
+            14043, 14075, 14116, 14139, 14173, 14211, 14228, 14262, 14287, 14329, 
+            14360, 14385, 14420, 
+        },
+        // Ps
+        { 
+            14438, 14439, 14446, 14459, 14468, 14477, 14490, 14501, 14519, 14529, 
+            14550, 14569, 14577, 14586, 14593, 14601, 14607, 14619, 14635, 14686, 
+            14701, 14711, 14725, 14757, 14764, 14775, 14798, 14811, 14826, 14836, 
+            14848, 14861, 14886, 14898, 14921, 14944, 14973, 14986, 15027, 15050, 
+            15064, 15082, 15096, 15108, 15114, 15141, 15159, 15171, 15181, 15196, 
+            15217, 15241, 15261, 15271, 15278, 15286, 15310, 15324, 15336, 15348, 
+            15366, 15379, 15388, 15401, 15413, 15424, 15438, 15459, 15467, 15503, 
+            15540, 15546, 15571, 15592, 15621, 15645, 15656, 15669, 15690, 15763, 
+            15777, 15797, 15814, 15823, 15842, 15855, 15869, 15887, 15895, 15914, 
+            15967, 15985, 16002, 16018, 16024, 16048, 16060, 16074, 16087, 16097, 
+            16107, 16113, 16122, 16151, 16174, 16210, 16256, 16305, 16349, 16363, 
+            16395, 16403, 16414, 16425, 16435, 16444, 16463, 16483, 16486, 16516, 
+            16693, 16701, 16710, 16720, 16725, 16734, 16740, 16747, 16753, 16760, 
+            16769, 16778, 16782, 16801, 16805, 16809, 16831, 16858, 16868, 16877, 
+            16902, 16916, 16927, 16935, 16948, 16964, 16986, 16997, 17018, 17033, 
+            17043, 
+        },
+        // Prov
+        { 
+            17050, 17051, 17085, 17108, 17144, 17172, 17196, 17232, 17260, 17297, 
+            17316, 17349, 17381, 17410, 17436, 17472, 17506, 17540, 17569, 17594, 
+            17624, 17655, 17687, 17717, 17753, 17788, 17817, 17846, 17874, 17903, 
+            17931, 17965, 
+        },
+        // Eccl
+        { 
+            17997, 17998, 18017, 18044, 18067, 18084, 18105, 18118, 18148, 18166, 
+            18185, 18206, 18217, 
+        },
+        // Song
+        { 
+            18232, 18233, 18251, 18269, 18281, 18298, 18315, 18329, 18343, 
+        },
+        // Isa
+        { 
+            18358, 18359, 18391, 18414, 18441, 18448, 18479, 18493, 18519, 18542, 
+            18564, 18599, 18616, 18623, 18646, 18679, 18689, 18704, 18719, 18727, 
+            18753, 18760, 18778, 18804, 18823, 18847, 18860, 18882, 18896, 18926, 
+            18951, 18985, 18995, 19016, 19041, 19059, 19070, 19093, 19132, 19155, 
+            19164, 19196, 19226, 19252, 19281, 19310, 19336, 19350, 19366, 19389, 
+            19416, 19428, 19452, 19468, 19481, 19499, 19513, 19526, 19548, 19563, 
+            19585, 19608, 19620, 19633, 19653, 19666, 19692, 
+        },
+        // Jer
+        { 
+            19717, 19718, 19738, 19776, 19802, 19834, 19866, 19897, 19932, 19955, 
+            19982, 20008, 20032, 20050, 20078, 20101, 20123, 20145, 20173, 20197, 
+            20213, 20232, 20247, 20278, 20319, 20330, 20369, 20394, 20417, 20435, 
+            20468, 20493, 20534, 20579, 20606, 20629, 20649, 20682, 20704, 20733, 
+            20752, 20769, 20788, 20811, 20825, 20856, 20862, 20891, 20899, 20947, 
+            20987, 21034, 21099, 
+        },
+        // Lam
+        { 
+            21134, 21135, 21158, 21181, 21248, 21271, 
+        },
+        // Ezek
+        { 
+            21294, 21295, 21324, 21335, 21363, 21381, 21399, 21414, 21442, 21461, 
+            21473, 21496, 21522, 21551, 21575, 21599, 21608, 21672, 21697, 21730, 
+            21745, 21795, 21828, 21860, 21910, 21938, 21956, 21978, 22015, 22042, 
+            22064, 22091, 22110, 22143, 22177, 22209, 22225, 22264, 22293, 22317, 
+            22347, 22397, 22424, 22445, 22473, 22505, 22531, 22556, 22580, 
+        },
+        // Dan
+        { 
+            22616, 22617, 22639, 22689, 22720, 22758, 22790, 22819, 22848, 22876, 
+            22904, 22926, 22972, 
+        },
+        // Hos
+        { 
+            22986, 22987, 22999, 23023, 23029, 23049, 23065, 23077, 23094, 23109, 
+            23127, 23143, 23156, 23171, 23188, 
+        },
+        // Joel
+        { 
+            23198, 23199, 23220, 23253, 
+        },
+        // Amos
+        { 
+            23275, 23276, 23292, 23309, 23325, 23339, 23367, 23382, 23400, 23415, 
+        },
+        // Obad
+        { 
+            23431, 23432, 
+        },
+        // Jonah
+        { 
+            23454, 23455, 23473, 23484, 23495, 
+        },
+        // Mic
+        { 
+            23507, 23508, 23525, 23539, 23552, 23566, 23582, 23599, 
+        },
+        // Nah
+        { 
+            23620, 23621, 23637, 23651, 
+        },
+        // Hab
+        { 
+            23671, 23672, 23690, 23711, 
+        },
+        // Zeph
+        { 
+            23731, 23732, 23751, 23767, 
+        },
+        // Hag
+        { 
+            23788, 23789, 23805, 
+        },
+        // Zech
+        { 
+            23829, 23830, 23852, 23866, 23877, 23892, 23904, 23920, 23935, 23959, 
+            23977, 23990, 24008, 24023, 24033, 
+        },
+        // Mal
+        { 
+            24055, 24056, 24071, 24089, 24108, 
+        },
+        // NT Testament Introduction
+        {
+            24115,
+        },
+        // Matt
+        { 
+            24116, 24117, 24143, 24167, 24185, 24211, 24260, 24295, 24325, 24360, 
+            24399, 24442, 24473, 24524, 24583, 24620, 24660, 24689, 24717, 24753, 
+            24784, 24819, 24866, 24913, 24953, 25005, 25052, 25128, 25195, 
+        },
+        // Mark
+        { 
+            25216, 25217, 25263, 25292, 25328, 25370, 25414, 25471, 25509, 25548, 
+            25599, 25652, 25686, 25731, 25769, 25842, 25890, 
+        },
+        // Luke
+        { 
+            25911, 25912, 25993, 26046, 26085, 26130, 26170, 26220, 26271, 26328, 
+            26391, 26434, 26489, 26549, 26585, 26621, 26654, 26686, 26724, 26768, 
+            26817, 26865, 26904, 26976, 27033, 
+        },
+        // John
+        { 
+            27087, 27088, 27140, 27166, 27203, 27258, 27306, 27378, 27432, 27492, 
+            27534, 27577, 27635, 27686, 27725, 27757, 27785, 27819, 27846, 27887, 
+            27930, 27962, 
+        },
+        // Acts
+        { 
+            27988, 27989, 28016, 28064, 28091, 28129, 28172, 28188, 28249, 28290, 
+            28334, 28383, 28414, 28440, 28493, 28522, 28564, 28605, 28640, 28669, 
+            28711, 28750, 28791, 28822, 28858, 28886, 28914, 28947, 28992, 
+        },
+        // Rom
+        { 
+            29024, 29025, 29058, 29088, 29120, 29146, 29168, 29192, 29218, 29258, 
+            29292, 29314, 29351, 29373, 29388, 29412, 29446, 
+        },
+        // 1Cor
+        { 
+            29474, 29475, 29507, 29524, 29548, 29570, 29584, 29605, 29646, 29660, 
+            29688, 29722, 29757, 29789, 29803, 29844, 29903, 
+        },
+        // 2Cor
+        { 
+            29928, 29929, 29954, 29972, 29991, 30010, 30032, 30051, 30068, 30093, 
+            30109, 30128, 30162, 30184, 
+        },
+        // Gal
+        { 
+            30199, 30200, 30225, 30247, 30277, 30309, 30336, 
+        },
+        // Eph
+        { 
+            30355, 30356, 30380, 30403, 30425, 30458, 30492, 
+        },
+        // Phil
+        { 
+            30517, 30518, 30549, 30580, 30602, 
+        },
+        // Col
+        { 
+            30626, 30627, 30657, 30681, 30707, 
+        },
+        // 1Thess
+        { 
+            30726, 30727, 30738, 30759, 30773, 30792, 
+        },
+        // 2Thess
+        { 
+            30821, 30822, 30835, 30853, 
+        },
+        // 1Tim
+        { 
+            30872, 30873, 30894, 30910, 30927, 30944, 30970, 
+        },
+        // 2Tim
+        { 
+            30992, 30993, 31012, 31039, 31057, 
+        },
+        // Titus
+        { 
+            31080, 31081, 31098, 31114, 
+        },
+        // Phlm
+        { 
+            31130, 31131, 
+        },
+        // Heb
+        { 
+            31157, 31158, 31173, 31192, 31212, 31229, 31244, 31265, 31294, 31308, 
+            31337, 31377, 31418, 31448, 
+        },
+        // Jas
+        { 
+            31474, 31475, 31503, 31530, 31549, 31567, 
+        },
+        // 1Pet
+        { 
+            31588, 31589, 31615, 31641, 31664, 31684, 
+        },
+        // 2Pet
+        { 
+            31699, 31700, 31722, 31745, 
+        },
+        // 1John
+        { 
+            31764, 31765, 31776, 31806, 31831, 31853, 
+        },
+        // 2John
+        { 
+            31875, 31876, 
+        },
+        // 3John
+        { 
+            31890, 31891, 
+        },
+        // Jude
+        { 
+            31906, 31907, 
+        },
+        // Rev
+        { 
+            31933, 31934, 31955, 31985, 32008, 32020, 32035, 32053, 32071, 32085, 
+            32107, 32119, 32139, 32157, 32176, 32197, 32206, 32228, 32247, 32272, 
+            32294, 32310, 32338, 
+        },
+        // Sentinel
+        { 
+            32360, 
+        },
+    };
+
+    private static final int OT_LAST_BOOK = 38;
+    private static final int NT_ORDINAL_START = 24115;
+    private static final int NT_BOOK_START = 39;
+
+    /**
+     * A singleton used to do initialization. Could be used to change static
+     * methods to non-static
+     */
+    static final BibleInfo instance = new BibleInfo();
+
+    /**
+     * This is the code used to create ORDINAL_AT_START_OF_CHAPTER and
+     * ORDINAL_AT_START_OF_BOOK. It is usually commented out because I don't see
+     * any point in making .class files bigger for no reason and this is needed
+     * only very rarely.
+     */ 
+/*
+     public void optimize(PrintStream out) throws NoSuchVerseException {
+        int count = 0;
+        int verseNum = 1;
+        out.println("    private static final int[] ORDINAL_AT_START_OF_BOOK =");
+        out.println("    {");
+        out.print("        ");
+        for (BibleBook b: EnumSet.range(BibleBook.GEN, BibleBook.REV)) {
+            String vstr1 = "     " + verseNum;
+            String vstr2 = vstr1.substring(vstr1.length() - 5);
+            out.print(vstr2 + ", ");
+            verseNum += versesInBook(b);
+
+            if (++count % 10 == 0) {
+                out.println();
+                out.print("        ");
+            }
+        }
+        out.println();
+        out.println("    };");
+
+        count = 0;
+        verseNum = 1;
+        out.println("    private static final int[][] ORDINAL_AT_START_OF_CHAPTER =");
+        out.println("    {");
+        for (BibleBook b: EnumSet.range(BibleBook.GEN, BibleBook.REV)) {
+            out.println("        { ");
+            for (int c = 1; c <= BibleInfo.chaptersInBook(b); c++) {
+                String vstr1 = "     " + verseNum;
+                String vstr2 = vstr1.substring(vstr1.length() - 5);
+                out.println(vstr2 + ", ");
+                verseNum += BibleInfo.versesInChapter(b, c);
+            }
+            out.println("},");
+        }
+        out.println("    };");
+    }
+*/
+    public static void optimize(PrintStream out) {
+        int count = 0;
+        int ordinal = 0;        // 0 is the module introduction
+        ordinal++;              // 1 Old Testament introduction
+        out.println("    private static final int[][] ORDINAL_AT_START_OF_CHAPTER =");
+        out.println("    {");
+        // Output an array for each book in the Old Testament
+        // This array is indexed by book and chapter
+        for (int bookIndex = 0; bookIndex < 39; bookIndex++) {
+            out.print("        // ");
+            out.println(BibleBook.getBooks()[bookIndex].getOSIS());
+            count = 0;
+            out.print("        { ");
+            ordinal++;          // Every book has a slot for a book introduction
+
+            // Pretty print with 10 items per line
+            if (count++ % 10 == 0) {
+                out.println();
+                out.print("            ");
+            }
+            // Output the offset for the book introduction
+            // This is referenced with a chapter number of 0 and verse number 0
+            String vstr1 = "     " + ordinal;
+            String vstr2 = vstr1.substring(vstr1.length() - 5);
+            out.print(vstr2 + ", ");
+            for (int chapterIndex = 0; chapterIndex < VERSES_IN_CHAPTER[bookIndex].length; chapterIndex++) {
+
+                // Pretty print with 10 items per line
+                if (count++ % 10 == 0) {
+                    out.println();
+                    out.print("            ");
+                }
+                ordinal++;      // Every chapter has a slot for a chapter introduction
+                // Output the offset for the chapter introduction
+                // This is referenced with a verse number of 0
+                vstr1 = "     " + ordinal;
+                vstr2 = vstr1.substring(vstr1.length() - 5);
+                out.print(vstr2 + ", ");
+                // Set ordinal to the start of the next chapter or book introduction
+                ordinal += VERSES_IN_CHAPTER[bookIndex][chapterIndex];
+            }
+            out.println();
+            out.println("        },");
+        }
+
+        int ntStartOrdinal = ordinal;
+//        ordinal++;              // This is the New Testament introduction
+        // Likewise, output an array for each book in the New Testament
+        for (int bookIndex = 39; bookIndex < VERSES_IN_CHAPTER.length; bookIndex++) {
+            count = 0;
+            out.print("        // ");
+            out.println(BibleBook.getBooks()[bookIndex].getOSIS());
+            out.print("        { ");
+            ordinal++;          // Every book has a slot for a book introduction
+
+            // Pretty print with 10 items per line
+            if (count++ % 10 == 0) {
+                out.println();
+                out.print("            ");
+            }
+
+            // Output the offset for the book introduction
+            // This is referenced with a chapter number of 0 and verse number 0
+            String vstr1 = "     " + ordinal;
+            String vstr2 = vstr1.substring(vstr1.length() - 5);
+            out.print(vstr2 + ", ");
+            for (int chapterIndex = 0; chapterIndex < VERSES_IN_CHAPTER[bookIndex].length; chapterIndex++) {
+
+                // Pretty print with 10 items per line
+                if (count++ % 10 == 0) {
+                    out.println();
+                    out.print("            ");
+                }
+                ordinal++;      // Every chapter has a slot for a chapter introduction
+                // Output the offset for the chapter introduction
+                // This is referenced with a verse number of 0
+                vstr1 = "     " + ordinal;
+                vstr2 = vstr1.substring(vstr1.length() - 5);
+                out.print(vstr2 + ", ");
+
+                // Set ordinal to the start of the next chapter or book introduction
+                ordinal += VERSES_IN_CHAPTER[bookIndex][chapterIndex];
+            }
+            out.println();
+            out.println("        },");
+        }
+
+        // Output a sentinel value:
+        // It is a book of one chapter starting with what would be the ordinal of the next chapter's introduction.
+        ordinal++;
+        String vstr1 = "     " + ordinal;
+        String vstr2 = vstr1.substring(vstr1.length() - 5);
+        out.println("        // Sentinel");
+        out.println("        { ");
+        out.println("            " + vstr2 + ", ");
+        out.println("        },");
+        out.println("    };");
+        out.println();
+        out.println("    private static final int NT_ORDINAL_START = " + ntStartOrdinal + ";");
+        out.println("    private static final int NT_BOOK_START = 39;");
+    }
+  
+    /**
      * Get the BookName.
      * This is merely a convenience function that validates that book is not null,
      * throwing NoSuchVerseException if it is.
@@ -387,6 +1040,7 @@
      *                If the book is not valid
      * @deprecated Use <code>book.getBookName()</code> instead.
      */
+    @Deprecated
     public static BookName getBookName(BibleBook book) throws NoSuchVerseException {
         try {
             return book.getBookName();
@@ -396,6 +1050,56 @@
     }
 
     /**
+     * Get number of a book from its name.
+     * 
+     * @param find
+     *            The string to identify
+     * @return The BibleBook, On error null
+     * @deprecated use {@link #BibleBook.getBook(String)}
+     */
+    @Deprecated
+    public static BibleBook getBook(String find) {
+        return BibleBook.getBook(find);
+    }
+
+    /**
+     * Is the given string a valid book name. If this method returns true then
+     * getBook() will return a BibleBook and not throw an exception.
+     * 
+     * @param find
+     *            The string to identify
+     * @return true when the book name is recognized
+     * @deprecated use {@link #BibleBook.isBook(String)}
+     */
+    @Deprecated
+    public static boolean isBookName(String find) {
+        return BibleBook.isBook(find);
+    }
+
+    /**
+     * Count the chapters in the Bible.
+     * 
+     * @return 1189 always - the number of chapters in the Bible
+     * @deprecated do not use
+     */
+    @Deprecated
+    public static int chaptersInBible() {
+        return 1189;
+    }
+
+    /**
+     * The maximum number of verses in the Bible, including module, testament, book and chapter introductions.
+     * Note: it used to exclude introductions.
+     * 
+     * @return the number of addressable verses in this versification.
+     * @deprecated use {@link #BibleInfo.maximumOrdinal()}
+     */
+    @Deprecated
+    public static int versesInBible() {
+        return maximumOrdinal();
+    }
+
+    /**
      * Get the preferred name of a book. Altered by the case setting (see
      * setBookCase() and isFullBookName())
      * This is merely a convenience function that validates that book is not null,
@@ -408,6 +1112,7 @@
      *                If the book is not valid
      * @deprecated Use <code>book.getPreferredName()</code> instead.
      */
+    @Deprecated
     public static String getPreferredBookName(BibleBook book) throws NoSuchVerseException {
         try {
             return book.getPreferredName();
@@ -429,6 +1134,7 @@
      *                If the book is not valid
      * @deprecated Use <code>book.getLongName()</code> instead.
      */
+    @Deprecated
     public static String getLongBookName(BibleBook book) throws NoSuchVerseException {
         try {
             return book.getLongName();
@@ -450,6 +1156,7 @@
      *                If the book is not valid
      * @deprecated Use <code>book.getShortName()</code> instead.
      */
+    @Deprecated
     public static String getShortBookName(BibleBook book) throws NoSuchVerseException {
         try {
             return book.getShortName();
@@ -470,6 +1177,7 @@
      *                If the book is not valid
      * @deprecated Use <code>book.getOSIS()</code> instead.
      */
+    @Deprecated
     public static String getOSISName(BibleBook book) throws NoSuchVerseException {
         try {
             return book.getOSIS();
@@ -578,282 +1286,6 @@
         return BookName.getDefaultCase();
     }
 
-    /** Constant for the number of books in the Bible */
-    private static final int BOOKS_IN_BIBLE = 66;
 
-    /** Constant for the number of chapters in the Bible */
-    private static final int CHAPTERS_IN_BIBLE = 1189;
-
-    /** Constant for the number of chapters in each book */
-    static final short[] CHAPTERS_IN_BOOK =
-    {
-        50, 40, 27, 36, 34, 24, 21,  4,  31, 24,
-        22, 25, 29, 36, 10, 13, 10, 42, 150, 31,
-        12,  8, 66, 52,  5, 48, 12, 14,   3,  9,
-         1,  4,  7,  3,  3,  3,  2, 14,   4, 28,
-        16, 24, 21, 28, 16, 16, 13,  6,   6,  4,
-         4,  5,  3,  6,  4,  3,  1, 13,   5,  5,
-         3,  5,  1,  1,  1, 22,
-    };
-
-    /** Constant for the number of verses in the Bible */
-    static final short VERSES_IN_BIBLE = 31102;
-
-    /** Constant for the number of verses in each book */
-    static final short[] VERSES_IN_BOOK =
-    {
-        1533, 1213,  859, 1288,  959,  658,  618,   85,  810,  695,
-         816,  719,  942,  822,  280,  406,  167, 1070, 2461,  915,
-         222,  117, 1292, 1364,  154, 1273,  357,  197,   73,  146,
-          21,   48,  105,   47,   56,   53,   38,  211,   55, 1071,
-         678, 1151,  879, 1007,  433,  437,  257,  149,  155,  104,
-          95,   89,   47,  113,   83,   46,   25,  303,  108,  105,
-          61,  105,   13,   14,   25,  404,
-    };
-
-    /** Constant for the number of verses in each chapter */
-    static final short[][] VERSES_IN_CHAPTER =
-    {
-        { 31, 25, 24, 26, 32, 22, 24, 22, 29, 32, 32, 20, 18, 24, 21, 16, 27, 33, 38, 18, 34, 24, 20, 67, 34, 35, 46, 22, 35, 43, 55, 32, 20, 31, 29, 43, 36, 30, 23, 23, 57, 38, 34, 34, 28, 34, 31, 22, 33, 26 },
-        { 22, 25, 22, 31, 23, 30, 25, 32, 35, 29, 10, 51, 22, 31, 27, 36, 16, 27, 25, 26, 36, 31, 33, 18, 40, 37, 21, 43, 46, 38, 18, 35, 23, 35, 35, 38, 29, 31, 43, 38 },
-        { 17, 16, 17, 35, 19, 30, 38, 36, 24, 20, 47,  8, 59, 57, 33, 34, 16, 30, 37, 27, 24, 33, 44, 23, 55, 46, 34 },
-        { 54, 34, 51, 49, 31, 27, 89, 26, 23, 36, 35, 16, 33, 45, 41, 50, 13, 32, 22, 29, 35, 41, 30, 25, 18, 65, 23, 31, 40, 16, 54, 42, 56, 29, 34, 13 },
-        { 46, 37, 29, 49, 33, 25, 26, 20, 29, 22, 32, 32, 18, 29, 23, 22, 20, 22, 21, 20, 23, 30, 25, 22, 19, 19, 26, 68, 29, 20, 30, 52, 29, 12 },
-        { 18, 24, 17, 24, 15, 27, 26, 35, 27, 43, 23, 24, 33, 15, 63, 10, 18, 28, 51,  9, 45, 34, 16, 33 },
-        { 36, 23, 31, 24, 31, 40, 25, 35, 57, 18, 40, 15, 25, 20, 20, 31, 13, 31, 30, 48, 25 },
-        { 22, 23, 18, 22 },
-        { 28, 36, 21, 22, 12, 21, 17, 22, 27, 27, 15, 25, 23, 52, 35, 23, 58, 30, 24, 42, 15, 23, 29, 22, 44, 25, 12, 25, 11, 31, 13 },
-        { 27, 32, 39, 12, 25, 23, 29, 18, 13, 19, 27, 31, 39, 33, 37, 23, 29, 33, 43, 26, 22, 51, 39, 25 },
-        { 53, 46, 28, 34, 18, 38, 51, 66, 28, 29, 43, 33, 34, 31, 34, 34, 24, 46, 21, 43, 29, 53 },
-        { 18, 25, 27, 44, 27, 33, 20, 29, 37, 36, 21, 21, 25, 29, 38, 20, 41, 37, 37, 21, 26, 20, 37, 20, 30 },
-        { 54, 55, 24, 43, 26, 81, 40, 40, 44, 14, 47, 40, 14, 17, 29, 43, 27, 17, 19,  8, 30, 19, 32, 31, 31, 32, 34, 21, 30 },
-        { 17, 18, 17, 22, 14, 42, 22, 18, 31, 19, 23, 16, 22, 15, 19, 14, 19, 34, 11, 37, 20, 12, 21, 27, 28, 23,  9, 27, 36, 27, 21, 33, 25, 33, 27, 23 },
-        { 11, 70, 13, 24, 17, 22, 28, 36, 15, 44 },
-        { 11, 20, 32, 23, 19, 19, 73, 18, 38, 39, 36, 47, 31 },
-        { 22, 23, 15, 17, 14, 14, 10, 17, 32,  3 },
-        { 22, 13, 26, 21, 27, 30, 21, 22, 35, 22, 20, 25, 28, 22, 35, 22, 16, 21, 29, 29, 34, 30, 17, 25,  6, 14, 23, 28, 25, 31, 40, 22, 33, 37, 16, 33, 24, 41, 30, 24, 34, 17 },
-        {  6, 12,  8,  8, 12, 10, 17,  9, 20, 18,  7,  8,  6,  7,  5, 11, 15, 50, 14,  9, 13, 31,  6, 10, 22, 12, 14,  9, 11, 12, 24, 11, 22, 22, 28, 12, 40, 22, 13, 17, 13, 11,  5, 26, 17, 11,  9, 14, 20, 23, 19,  9,  6,  7, 23, 13, 11, 11, 17, 12,  8, 12, 11, 10, 13, 20,  7, 35, 36,  5, 24, 20, 28, 23, 10, 12, 20, 72, 13, 19, 16,  8, 18, 12, 13, 17,  7, 18, 52, 17, 16, 15,  5, 23, 11, 13, 12,  9,  9,  5,  8, 28, 22, 35, 45, 48, 43, 13, 31,  7, 10, 10,  9,  8, 18, 19,  2, 29, 176,  7,  8,  9,  4,  8,  5,  6,  5,  6,  8,  8,  3, 18,  3,  3, 21, 26, 9,  8, 24, 13, 10,  7, 12, 15, 21, 10, 20, 14,  9,  6 },
-        { 33, 22, 35, 27, 23, 35, 27, 36, 18, 32, 31, 28, 25, 35, 33, 33, 28, 24, 29, 30, 31, 29, 35, 34, 28, 28, 27, 28, 27, 33, 31 },
-        { 18, 26, 22, 16, 20, 12, 29, 17, 18, 20, 10, 14 },
-        { 17, 17, 11, 16, 16, 13, 13, 14 },
-        { 31, 22, 26,  6, 30, 13, 25, 22, 21, 34, 16,  6, 22, 32,  9, 14, 14,  7, 25,  6, 17, 25, 18, 23, 12, 21, 13, 29, 24, 33,  9, 20, 24, 17, 10, 22, 38, 22,  8, 31, 29, 25, 28, 28, 25, 13, 15, 22, 26, 11, 23, 15, 12, 17, 13, 12, 21, 14, 21, 22, 11, 12, 19, 12, 25, 24 },
-        { 19, 37, 25, 31, 31, 30, 34, 22, 26, 25, 23, 17, 27, 22, 21, 21, 27, 23, 15, 18, 14, 30, 40, 10, 38, 24, 22, 17, 32, 24, 40, 44, 26, 22, 19, 32, 21, 28, 18, 16, 18, 22, 13, 30,  5, 28,  7, 47, 39, 46, 64, 34 },
-        { 22, 22, 66, 22, 22 },
-        { 28, 10, 27, 17, 17, 14, 27, 18, 11, 22, 25, 28, 23, 23,  8, 63, 24, 32, 14, 49, 32, 31, 49, 27, 17, 21, 36, 26, 21, 26, 18, 32, 33, 31, 15, 38, 28, 23, 29, 49, 26, 20, 27, 31, 25, 24, 23, 35 },
-        { 21, 49, 30, 37, 31, 28, 28, 27, 27, 21, 45, 13 },
-        { 11, 23,  5, 19, 15, 11, 16, 14, 17, 15, 12, 14, 16,  9 },
-        { 20, 32, 21 },
-        { 15, 16, 15, 13, 27, 14, 17, 14, 15 },
-        { 21 },
-        { 17, 10, 10, 11 },
-        { 16, 13, 12, 13, 15, 16, 20 },
-        { 15, 13, 19 },
-        { 17, 20, 19 },
-        { 18, 15, 20 },
-        { 15, 23 },
-        { 21, 13, 10, 14, 11, 15, 14, 23, 17, 12, 17, 14,  9, 21 },
-        { 14, 17, 18,  6 },
-        { 25, 23, 17, 25, 48, 34, 29, 34, 38, 42, 30, 50, 58, 36, 39, 28, 27, 35, 30, 34, 46, 46, 39, 51, 46, 75, 66, 20 },
-        { 45, 28, 35, 41, 43, 56, 37, 38, 50, 52, 33, 44, 37, 72, 47, 20 },
-        { 80, 52, 38, 44, 39, 49, 50, 56, 62, 42, 54, 59, 35, 35, 32, 31, 37, 43, 48, 47, 38, 71, 56, 53 },
-        { 51, 25, 36, 54, 47, 71, 53, 59, 41, 42, 57, 50, 38, 31, 27, 33, 26, 40, 42, 31, 25 },
-        { 26, 47, 26, 37, 42, 15, 60, 40, 43, 48, 30, 25, 52, 28, 41, 40, 34, 28, 41, 38, 40, 30, 35, 27, 27, 32, 44, 31 },
-        { 32, 29, 31, 25, 21, 23, 25, 39, 33, 21, 36, 21, 14, 23, 33, 27 },
-        { 31, 16, 23, 21, 13, 20, 40, 13, 27, 33, 34, 31, 13, 40, 58, 24 },
-        { 24, 17, 18, 18, 21, 18, 16, 24, 15, 18, 33, 21, 14 },
-        { 24, 21, 29, 31, 26, 18 },
-        { 23, 22, 21, 32, 33, 24 },
-        { 30, 30, 21, 23 },
-        { 29, 23, 25, 18 },
-        { 10, 20, 13, 18, 28 },
-        { 12, 17, 18 },
-        { 20, 15, 16, 16, 25, 21 },
-        { 18, 26, 17, 22 },
-        { 16, 15, 15 },
-        { 25 },
-        { 14, 18, 19, 16, 14, 20, 28, 13, 28, 39, 40, 29, 25 },
-        { 27, 26, 18, 17, 20 },
-        { 25, 25, 22, 19, 14 },
-        { 21, 22, 18 },
-        { 10, 29, 24, 21, 21 },
-        { 13 },
-        { 14 },
-        { 25 },
-        { 20, 29, 22, 11, 14, 17, 17, 13, 21, 11, 19, 17, 18, 20,  8, 21, 18, 24, 21, 15, 27, 21 },
-    };
-
-    /** Constant for the ordinal number of the first verse in each book */
-    // Note the sentinel at the end of the array is one greater
-    // than the last ordinal in the last book
-    static final short[] ORDINAL_AT_START_OF_BOOK =
-    {
-            1,  1534,  2747,  3606,  4894,  5853,  6511,  7129,  7214,  8024,
-         8719,  9535, 10254, 11196, 12018, 12298, 12704, 12871, 13941, 16402,
-        17317, 17539, 17656, 18948, 20312, 20466, 21739, 22096, 22293, 22366,
-        22512, 22533, 22581, 22686, 22733, 22789, 22842, 22880, 23091, 23146,
-        24217, 24895, 26046, 26925, 27932, 28365, 28802, 29059, 29208, 29363,
-        29467, 29562, 29651, 29698, 29811, 29894, 29940, 29965, 30268, 30376,
-        30481, 30542, 30647, 30660, 30674, 30699, 31103
-    };
-
-    /**
-     * Constant for the ordinal number of the first verse in each chapter.
-     * Warning if you regenerate this code (from the code at the bottom of this
-     * module) then you will need to cut the psalms line in half to get it to
-     * compile under JBuilder.
-     */
-    static final short[][] ORDINAL_AT_START_OF_CHAPTER =
-    {
-        {     1,    32,    57,    81,   107,   139,   161,   185,   207,   236,   268,   300,   320,   338,   362,   383,   399,   426,   459,   497,
-            515,   549,   573,   593,   660,   694,   729,   775,   797,   832,   875,   930,   962,   982,  1013,  1042,  1085,  1121,  1151,  1174,
-           1197,  1254,  1292,  1326,  1360,  1388,  1422,  1453,  1475,  1508, },
-        {  1534,  1556,  1581,  1603,  1634,  1657,  1687,  1712,  1744,  1779,  1808,  1818,  1869,  1891,  1922,  1949,  1985,  2001,  2028,  2053,
-           2079,  2115,  2146,  2179,  2197,  2237,  2274,  2295,  2338,  2384,  2422,  2440,  2475,  2498,  2533,  2568,  2606,  2635,  2666,  2709, },
-        {  2747,  2764,  2780,  2797,  2832,  2851,  2881,  2919,  2955,  2979,  2999,  3046,  3054,  3113,  3170,  3203,  3237,  3253,  3283,  3320,
-           3347,  3371,  3404,  3448,  3471,  3526,  3572, },
-        {  3606,  3660,  3694,  3745,  3794,  3825,  3852,  3941,  3967,  3990,  4026,  4061,  4077,  4110,  4155,  4196,  4246,  4259,  4291,  4313,
-           4342,  4377,  4418,  4448,  4473,  4491,  4556,  4579,  4610,  4650,  4666,  4720,  4762,  4818,  4847,  4881, },
-        {  4894,  4940,  4977,  5006,  5055,  5088,  5113,  5139,  5159,  5188,  5210,  5242,  5274,  5292,  5321,  5344,  5366,  5386,  5408,  5429,
-           5449,  5472,  5502,  5527,  5549,  5568,  5587,  5613,  5681,  5710,  5730,  5760,  5812,  5841, },
-        {  5853,  5871,  5895,  5912,  5936,  5951,  5978,  6004,  6039,  6066,  6109,  6132,  6156,  6189,  6204,  6267,  6277,  6295,  6323,  6374,
-           6383,  6428,  6462,  6478, },
-        {  6511,  6547,  6570,  6601,  6625,  6656,  6696,  6721,  6756,  6813,  6831,  6871,  6886,  6911,  6931,  6951,  6982,  6995,  7026,  7056,
-           7104, },
-        {  7129,  7151,  7174,  7192, },
-        {  7214,  7242,  7278,  7299,  7321,  7333,  7354,  7371,  7393,  7420,  7447,  7462,  7487,  7510,  7562,  7597,  7620,  7678,  7708,  7732,
-           7774,  7789,  7812,  7841,  7863,  7907,  7932,  7944,  7969,  7980,  8011, },
-        {  8024,  8051,  8083,  8122,  8134,  8159,  8182,  8211,  8229,  8242,  8261,  8288,  8319,  8358,  8391,  8428,  8451,  8480,  8513,  8556,
-           8582,  8604,  8655,  8694, },
-        {  8719,  8772,  8818,  8846,  8880,  8898,  8936,  8987,  9053,  9081,  9110,  9153,  9186,  9220,  9251,  9285,  9319,  9343,  9389,  9410,
-           9453,  9482, },
-        {  9535,  9553,  9578,  9605,  9649,  9676,  9709,  9729,  9758,  9795,  9831,  9852,  9873,  9898,  9927,  9965,  9985, 10026, 10063, 10100,
-           10121, 10147, 10167, 10204, 10224, },
-        { 10254, 10308, 10363, 10387, 10430, 10456, 10537, 10577, 10617, 10661, 10675, 10722, 10762, 10776, 10793, 10822, 10865, 10892, 10909, 10928,
-          10936, 10966, 10985, 11017, 11048, 11079, 11111, 11145, 11166, },
-        { 11196, 11213, 11231, 11248, 11270, 11284, 11326, 11348, 11366, 11397, 11416, 11439, 11455, 11477, 11492, 11511, 11525, 11544, 11578, 11589,
-          11626, 11646, 11658, 11679, 11706, 11734, 11757, 11766, 11793, 11829, 11856, 11877, 11910, 11935, 11968, 11995, },
-        { 12018, 12029, 12099, 12112, 12136, 12153, 12175, 12203, 12239, 12254, },
-        { 12298, 12309, 12329, 12361, 12384, 12403, 12422, 12495, 12513, 12551, 12590, 12626, 12673, },
-        { 12704, 12726, 12749, 12764, 12781, 12795, 12809, 12819, 12836, 12868, },
-        { 12871, 12893, 12906, 12932, 12953, 12980, 13010, 13031, 13053, 13088, 13110, 13130, 13155, 13183, 13205, 13240, 13262, 13278, 13299, 13328,
-          13357, 13391, 13421, 13438, 13463, 13469, 13483, 13506, 13534, 13559, 13590, 13630, 13652, 13685, 13722, 13738, 13771, 13795, 13836, 13866,
-          13890, 13924, },
-        { 13941, 13947, 13959, 13967, 13975, 13987, 13997, 14014, 14023, 14043, 14061, 14068, 14076, 14082, 14089, 14094, 14105, 14120, 14170, 14184,
-          14193, 14206, 14237, 14243, 14253, 14275, 14287, 14301, 14310, 14321, 14333, 14357, 14368, 14390, 14412, 14440, 14452, 14492, 14514, 14527,
-          14544, 14557, 14568, 14573, 14599, 14616, 14627, 14636, 14650, 14670, 14693, 14712, 14721, 14727, 14734, 14757, 14770, 14781, 14792, 14809,
-          14821, 14829, 14841, 14852, 14862, 14875, 14895, 14902, 14937, 14973, 14978, 15002, 15022, 15050, 15073, 15083, 15095, 15115, 15187, 15200,
-          15219, 15235, 15243, 15261, 15273, 15286, 15303, 15310, 15328, 15380, 15397, 15413, 15428, 15433, 15456, 15467, 15480, 15492, 15501, 15510,
-          15515, 15523, 15551, 15573, 15608, 15653, 15701, 15744, 15757, 15788, 15795, 15805, 15815, 15824, 15832, 15850, 15869, 15871, 15900, 16076,
-          16083, 16091, 16100, 16104, 16112, 16117, 16123, 16128, 16134, 16142, 16150, 16153, 16171, 16174, 16177, 16198, 16224, 16233, 16241, 16265,
-          16278, 16288, 16295, 16307, 16322, 16343, 16353, 16373, 16387, 16396, },
-        { 16402, 16435, 16457, 16492, 16519, 16542, 16577, 16604, 16640, 16658, 16690, 16721, 16749, 16774, 16809, 16842, 16875, 16903, 16927, 16956,
-          16986, 17017, 17046, 17081, 17115, 17143, 17171, 17198, 17226, 17253, 17286, },
-        { 17317, 17335, 17361, 17383, 17399, 17419, 17431, 17460, 17477, 17495, 17515, 17525, },
-        { 17539, 17556, 17573, 17584, 17600, 17616, 17629, 17642, },
-        { 17656, 17687, 17709, 17735, 17741, 17771, 17784, 17809, 17831, 17852, 17886, 17902, 17908, 17930, 17962, 17971, 17985, 17999, 18006, 18031,
-          18037, 18054, 18079, 18097, 18120, 18132, 18153, 18166, 18195, 18219, 18252, 18261, 18281, 18305, 18322, 18332, 18354, 18392, 18414, 18422,
-          18453, 18482, 18507, 18535, 18563, 18588, 18601, 18616, 18638, 18664, 18675, 18698, 18713, 18725, 18742, 18755, 18767, 18788, 18802, 18823,
-          18845, 18856, 18868, 18887, 18899, 18924, },
-        { 18948, 18967, 19004, 19029, 19060, 19091, 19121, 19155, 19177, 19203, 19228, 19251, 19268, 19295, 19317, 19338, 19359, 19386, 19409, 19424,
-          19442, 19456, 19486, 19526, 19536, 19574, 19598, 19620, 19637, 19669, 19693, 19733, 19777, 19803, 19825, 19844, 19876, 19897, 19925, 19943,
-          19959, 19977, 19999, 20012, 20042, 20047, 20075, 20082, 20129, 20168, 20214, 20278, },
-        { 20312, 20334, 20356, 20422, 20444, },
-        { 20466, 20494, 20504, 20531, 20548, 20565, 20579, 20606, 20624, 20635, 20657, 20682, 20710, 20733, 20756, 20764, 20827, 20851, 20883, 20897,
-          20946, 20978, 21009, 21058, 21085, 21102, 21123, 21159, 21185, 21206, 21232, 21250, 21282, 21315, 21346, 21361, 21399, 21427, 21450, 21479,
-          21528, 21554, 21574, 21601, 21632, 21657, 21681, 21704, },
-        { 21739, 21760, 21809, 21839, 21876, 21907, 21935, 21963, 21990, 22017, 22038, 22083, },
-        { 22096, 22107, 22130, 22135, 22154, 22169, 22180, 22196, 22210, 22227, 22242, 22254, 22268, 22284, },
-        { 22293, 22313, 22345, },
-        { 22366, 22381, 22397, 22412, 22425, 22452, 22466, 22483, 22497, },
-        { 22512, },
-        { 22533, 22550, 22560, 22570, },
-        { 22581, 22597, 22610, 22622, 22635, 22650, 22666, },
-        { 22686, 22701, 22714, },
-        { 22733, 22750, 22770, },
-        { 22789, 22807, 22822, },
-        { 22842, 22857, },
-        { 22880, 22901, 22914, 22924, 22938, 22949, 22964, 22978, 23001, 23018, 23030, 23047, 23061, 23070, },
-        { 23091, 23105, 23122, 23140, },
-        { 23146, 23171, 23194, 23211, 23236, 23284, 23318, 23347, 23381, 23419, 23461, 23491, 23541, 23599, 23635, 23674, 23702, 23729, 23764, 23794,
-          23828, 23874, 23920, 23959, 24010, 24056, 24131, 24197, },
-        { 24217, 24262, 24290, 24325, 24366, 24409, 24465, 24502, 24540, 24590, 24642, 24675, 24719, 24756, 24828, 24875, },
-        { 24895, 24975, 25027, 25065, 25109, 25148, 25197, 25247, 25303, 25365, 25407, 25461, 25520, 25555, 25590, 25622, 25653, 25690, 25733, 25781,
-          25828, 25866, 25937, 25993, },
-        { 26046, 26097, 26122, 26158, 26212, 26259, 26330, 26383, 26442, 26483, 26525, 26582, 26632, 26670, 26701, 26728, 26761, 26787, 26827, 26869,
-          26900, },
-        { 26925, 26951, 26998, 27024, 27061, 27103, 27118, 27178, 27218, 27261, 27309, 27339, 27364, 27416, 27444, 27485, 27525, 27559, 27587, 27628,
-          27666, 27706, 27736, 27771, 27798, 27825, 27857, 27901, },
-        { 27932, 27964, 27993, 28024, 28049, 28070, 28093, 28118, 28157, 28190, 28211, 28247, 28268, 28282, 28305, 28338, },
-        { 28365, 28396, 28412, 28435, 28456, 28469, 28489, 28529, 28542, 28569, 28602, 28636, 28667, 28680, 28720, 28778, },
-        { 28802, 28826, 28843, 28861, 28879, 28900, 28918, 28934, 28958, 28973, 28991, 29024, 29045, },
-        { 29059, 29083, 29104, 29133, 29164, 29190, },
-        { 29208, 29231, 29253, 29274, 29306, 29339, },
-        { 29363, 29393, 29423, 29444, },
-        { 29467, 29496, 29519, 29544, },
-        { 29562, 29572, 29592, 29605, 29623, },
-        { 29651, 29663, 29680, },
-        { 29698, 29718, 29733, 29749, 29765, 29790, },
-        { 29811, 29829, 29855, 29872, },
-        { 29894, 29910, 29925, },
-        { 29940, },
-        { 29965, 29979, 29997, 30016, 30032, 30046, 30066, 30094, 30107, 30135, 30174, 30214, 30243, },
-        { 30268, 30295, 30321, 30339, 30356, },
-        { 30376, 30401, 30426, 30448, 30467, },
-        { 30481, 30502, 30524, },
-        { 30542, 30552, 30581, 30605, 30626, },
-        { 30647, },
-        { 30660, },
-        { 30674, },
-        { 30699, 30719, 30748, 30770, 30781, 30795, 30812, 30829, 30842, 30863, 30874, 30893, 30910, 30928, 30948, 30956, 30977, 30995, 31019, 31040,
-          31055, 31082, },
-    };
-
-    /**
-     * A singleton used to do initialization. Could be used to change static
-     * methods to non-static
-     */
-    static final BibleInfo instance = new BibleInfo();
-
-    /**
-     * This is the code used to create ORDINAL_AT_START_OF_CHAPTER and
-     * ORDINAL_AT_START_OF_BOOK. It is usually commented out because I don't see
-     * any point in making .class files bigger for no reason and this is needed
-     * only very rarely.
-     */ 
-    public void optimize(PrintStream out) throws NoSuchVerseException {
-        int count = 0;
-        int verseNum = 1;
-        out.println("    private static final short[] ORDINAL_AT_START_OF_BOOK =");
-        out.println("    {");
-        out.print("        ");
-        for (BibleBook b: EnumSet.range(BibleBook.GEN, BibleBook.REV)) {
-            String vstr1 = "     " + verseNum;
-            String vstr2 = vstr1.substring(vstr1.length() - 5);
-            out.print(vstr2 + ", ");
-            verseNum += versesInBook(b);
-
-            if (++count % 10 == 0) {
-                out.println();
-                out.print("        ");
-            }
-        }
-        out.println();
-        out.println("    };");
-
-        count = 0;
-        verseNum = 1;
-        out.println("    private static final short[][] ORDINAL_AT_START_OF_CHAPTER =");
-        out.println("    {");
-        for (BibleBook b: EnumSet.range(BibleBook.GEN, BibleBook.REV)) {
-            out.println("        { ");
-            for (int c = 1; c <= BibleInfo.chaptersInBook(b); c++) {
-                String vstr1 = "     " + verseNum;
-                String vstr2 = vstr1.substring(vstr1.length() - 5);
-                out.println(vstr2 + ", ");
-                verseNum += BibleInfo.versesInChapter(b, c);
-            }
-            out.println("},");
-        }
-        out.println("    };");
-    }
+    
 }

Modified: trunk/jsword/src/main/java/org/crosswire/jsword/versification/BibleNames.java
===================================================================
--- trunk/jsword/src/main/java/org/crosswire/jsword/versification/BibleNames.java	2012-01-02 05:11:59 UTC (rev 2195)
+++ trunk/jsword/src/main/java/org/crosswire/jsword/versification/BibleNames.java	2012-01-03 13:53:37 UTC (rev 2196)
@@ -59,7 +59,7 @@
         } catch (NullPointerException ex) {
             throw new NoSuchVerseException(JSOtherMsg.lookupText("Book must not be null"));
         } catch (ArrayIndexOutOfBoundsException ex) {
-            throw new NoSuchVerseException(JSOtherMsg.lookupText("Book must be between 1 and 66 (given {0,number,integer}).", Integer.valueOf(book.ordinal())));
+            throw new NoSuchVerseException(JSOtherMsg.lookupText("Book must be between 0 and 66 (given {0,number,integer}).", Integer.valueOf(book.ordinal())));
         }
     }
 

Added: trunk/jsword/src/main/java/org/crosswire/jsword/versification/v11n.jpage
===================================================================
--- trunk/jsword/src/main/java/org/crosswire/jsword/versification/v11n.jpage	                        (rev 0)
+++ trunk/jsword/src/main/java/org/crosswire/jsword/versification/v11n.jpage	2012-01-03 13:53:37 UTC (rev 2196)
@@ -0,0 +1 @@
+org.crosswire.jsword.versification.BibleInfo.optimize(System.out);
\ No newline at end of file

Modified: trunk/jsword/src/main/resources/BibleNames.properties
===================================================================
--- trunk/jsword/src/main/resources/BibleNames.properties	2012-01-02 05:11:59 UTC (rev 2195)
+++ trunk/jsword/src/main/resources/BibleNames.properties	2012-01-03 13:53:37 UTC (rev 2196)
@@ -400,3 +400,14 @@
 Herm.Vis.Full=Visions
 Herm.Vis.Short=Vis
 Herm.Vis.Alt=
+
+# Introduction titles for the book as a whole, the OT and the NT.
+Intro.Bible.Full=Bible Introduction
+Intro.Bible.Short=Bible Intro
+Intro.Bible.Alt=
+Intro.OT.Full=Old Testament Introduction
+Intro.OT.Short=OT Intro
+Intro.OT.Alt=
+Intro.NT.Full=New Testament Introduction
+Intro.NT.Short=NT Intro
+Intro.NT.Alt=

Modified: trunk/jsword/src/test/java/org/crosswire/common/progress/JobTest.java
===================================================================
--- trunk/jsword/src/test/java/org/crosswire/common/progress/JobTest.java	2012-01-02 05:11:59 UTC (rev 2195)
+++ trunk/jsword/src/test/java/org/crosswire/common/progress/JobTest.java	2012-01-03 13:53:37 UTC (rev 2196)
@@ -99,7 +99,6 @@
         assertEquals(false, job.isFinished());
         assertEquals(true, job.isCancelable());
         assertEquals(WIBBLE, job.getSectionName());
-        assertEquals(0, job.getWork());
         job.done();
         assertEquals(true, job.isFinished());
         assertEquals(100, job.getWork());

Modified: trunk/jsword/src/test/java/org/crosswire/jsword/passage/BibleInfoTest.java
===================================================================
--- trunk/jsword/src/test/java/org/crosswire/jsword/passage/BibleInfoTest.java	2012-01-02 05:11:59 UTC (rev 2195)
+++ trunk/jsword/src/test/java/org/crosswire/jsword/passage/BibleInfoTest.java	2012-01-03 13:53:37 UTC (rev 2196)
@@ -153,55 +153,73 @@
     }
 
     public void testIn() throws Exception {
-        assertEquals(1533, BibleInfo.versesInBook(BibleBook.GEN));
-        assertEquals(404, BibleInfo.versesInBook(BibleBook.REV));
-
         // Counts using loops
-        int viw_b = 0;
         int viw_c = 0;
         int ciw = 0;
 
         // For all the books
         // for (BibleBook b : BibleBook.values()) {
-        for (BibleBook b: EnumSet.range(BibleBook.GEN, BibleBook.REV)) {
-            // Count and check the verses in this book
-            int vib = 0;
-            for (int c = 1; c <= BibleInfo.chaptersInBook(b); c++) {
-                vib += BibleInfo.versesInChapter(b, c);
-            }
-            assertEquals(vib, BibleInfo.versesInBook(b));
+        for (BibleBook b: EnumSet.range(BibleBook.INTRO_BIBLE, BibleBook.REV)) {
 
             // Continue the verse counts for the whole Bible
-            for (int c = 1; c <= BibleInfo.chaptersInBook(b); c++) {
-                viw_c += BibleInfo.versesInChapter(b, c);
+            for (int c = 0; c <= BibleInfo.chaptersInBook(b); c++) {
+                viw_c += BibleInfo.versesInChapter(b, c) + 1;
             }
 
-            viw_b += BibleInfo.versesInBook(b);
-
             // Continue the chapter count for the whole Bible
             ciw += BibleInfo.chaptersInBook(b);
         }
-        assertEquals(BibleInfo.versesInBible(), viw_b);
-        assertEquals(BibleInfo.versesInBible(), viw_c);
+
+        assertEquals(BibleInfo.maximumOrdinal() + 1, viw_c);
         assertEquals(BibleInfo.chaptersInBible(), ciw);
-        assertEquals(BibleInfo.booksInBible(), 66);
+        assertEquals(BibleInfo.booksInBible(), 69);
     }
 
     public void testOrdinal() throws Exception {
-        int first_verse_ord = 1;
+        int first_verse_ord = 2;
         int last_verse_ord = 1;
         // for (BibleBook b : BibleBook.values()) {
-        for (BibleBook b: EnumSet.range(BibleBook.GEN, BibleBook.REV)) {
+        for (BibleBook b: EnumSet.range(BibleBook.GEN, BibleBook.MAL)) {
+            for (int c = 0; c <= BibleInfo.chaptersInBook(b); c++) {
+                first_verse_ord++; // chapter introduction
+                last_verse_ord = first_verse_ord + BibleInfo.versesInChapter(b, c);
+
+                Verse bc0 = new Verse(b, c, 0);
+                assertEquals(bc0.getName(), first_verse_ord, BibleInfo.getOrdinal(bc0));
+                assertEquals(bc0.getName(), bc0, BibleInfo.decodeOrdinal(first_verse_ord));
+
+                if (c > 0) {
+                    Verse bc1 = new Verse(b, c, 1);
+                    assertEquals(bc1.getName(), first_verse_ord + 1, BibleInfo.getOrdinal(bc1));
+                    assertEquals(bc1.getName(), bc1, BibleInfo.decodeOrdinal(first_verse_ord + 1));
+
+                    Verse bc2 = new Verse(b, c, 2);
+                    assertEquals(bc2.getName(), first_verse_ord + 2, BibleInfo.getOrdinal(bc2));
+                    assertEquals(bc2.getName(), bc2, BibleInfo.decodeOrdinal(first_verse_ord + 2));
+
+                    Verse bclast = new Verse(b, c, BibleInfo.versesInChapter(b, c));
+                    assertEquals(bclast.getName(), last_verse_ord, BibleInfo.getOrdinal(bclast));
+                    assertEquals(bclast.getName(), bclast, BibleInfo.decodeOrdinal(last_verse_ord));
+                }
+                first_verse_ord += BibleInfo.versesInChapter(b, c);
+            }
+        }
+        first_verse_ord++; // NT Introduction
+        for (BibleBook b: EnumSet.range(BibleBook.MATT, BibleBook.REV)) {
+            first_verse_ord++; // book introduction
             for (int c = 1; c <= BibleInfo.chaptersInBook(b); c++) {
-                last_verse_ord = first_verse_ord + BibleInfo.versesInChapter(b, c) - 1;
+                first_verse_ord++; // chapter introduction
+                last_verse_ord = first_verse_ord + BibleInfo.versesInChapter(b, c);
 
-                assertEquals(first_verse_ord, BibleInfo.verseOrdinal(new Verse(b, c, 1)));
-                assertEquals(first_verse_ord + 1, BibleInfo.verseOrdinal(new Verse(b, c, 2)));
-                assertEquals(last_verse_ord, BibleInfo.verseOrdinal(new Verse(b, c, BibleInfo.versesInChapter(b, c))));
+                assertEquals(first_verse_ord, BibleInfo.getOrdinal(new Verse(b, c, 0)));
+                assertEquals(first_verse_ord + 1, BibleInfo.getOrdinal(new Verse(b, c, 1)));
+                assertEquals(first_verse_ord + 2, BibleInfo.getOrdinal(new Verse(b, c, 2)));
+                assertEquals(last_verse_ord, BibleInfo.getOrdinal(new Verse(b, c, BibleInfo.versesInChapter(b, c))));
 
-                assertEquals(new Verse(b, c, 1), BibleInfo.decodeOrdinal(first_verse_ord));
-                assertEquals(new Verse(b, c, 2), BibleInfo.decodeOrdinal(first_verse_ord + 1));
-                assertEquals(new Verse(b, c, BibleInfo.versesInChapter(b, c)), BibleInfo.decodeOrdinal(last_verse_ord));
+                assertEquals(new Verse(b, c, 0), BibleInfo.decodeOrdinal(first_verse_ord));
+                assertEquals(new Verse(b, c, 1), BibleInfo.decodeOrdinal(first_verse_ord + 1));
+                assertEquals(new Verse(b, c, 2), BibleInfo.decodeOrdinal(first_verse_ord + 2));
+//                assertEquals(new Verse(b, c, BibleInfo.versesInChapter(b, c)), BibleInfo.decodeOrdinal(last_verse_ord));
 
                 first_verse_ord += BibleInfo.versesInChapter(b, c);
             }
@@ -221,20 +239,14 @@
                 fail();
             } catch (NoSuchVerseException ex) {
             }
-            try {
+            if (b != BibleBook.INTRO_NT) {
                 BibleInfo.validate(b, 1, 0);
-                fail();
-            } catch (NoSuchVerseException ex) {
             }
 
-            for (int c = 1; c <= BibleInfo.chaptersInBook(b); c++) {
-                try {
-                    BibleInfo.validate(b, c, 0);
-                    fail();
-                } catch (NoSuchVerseException ex) {
-                }
+            for (int c = 0; c <= BibleInfo.chaptersInBook(b); c++) {
+                BibleInfo.validate(b, c, 0);
 
-                for (int v = 1; v <= BibleInfo.versesInChapter(b, c); v++) {
+                for (int v = 0; v <= BibleInfo.versesInChapter(b, c); v++) {
                     BibleInfo.validate(b, c, v);
                 }
                 try {
@@ -250,7 +262,7 @@
             } catch (NoSuchVerseException ex) {
             }
             try {
-                BibleInfo.validate(null, 1, BibleInfo.versesInBook(b) + 1);
+                BibleInfo.validate(null, 1, 9999);
                 fail();
             } catch (NoSuchVerseException ex) {
             }
@@ -287,30 +299,29 @@
 
     public void testVerseCount() throws Exception {
         int count_up = 0;
-        int count_down = 31102;
-        Verse gen11 = new Verse(BibleBook.GEN, 1, 1);
+        int count_down = BibleInfo.maximumOrdinal();
+        Verse gen00 = new Verse(BibleBook.GEN, 0, 0);
         Verse gen110 = new Verse(BibleBook.GEN, 1, 10);
         Verse exo11 = new Verse(BibleBook.EXOD, 1, 1);
         Verse rev99 = new Verse(BibleBook.REV, 22, 21);
+        assertEquals(rev99.getOrdinal(), count_down);
         // for (BibleBook b : BibleBook.values()) {
         for (BibleBook b: EnumSet.range(BibleBook.GEN, BibleBook.REV)) {
-            for (int c = 1; c <= BibleInfo.chaptersInBook(b); c++) {
-                for (int v = 1; v <= BibleInfo.versesInChapter(b, c); v++) {
+            for (int c = 0; c <= BibleInfo.chaptersInBook(b); c++) {
+                for (int v = 0; v <= BibleInfo.versesInChapter(b, c); v++) {
                     Verse curVerse = new Verse(b, c, v);
-                    int up = curVerse.subtract(gen11) + 1;
+                    int up = curVerse.subtract(gen00) + 1;
                     int down = rev99.subtract(curVerse) + 1;
 
                     assertEquals(++count_up, up);
-                    assertEquals(count_down--, down);
+//                    assertEquals(count_down--, down);
 
-                    assertEquals(verseCountSlow(gen11, curVerse), up);
+//                    assertEquals(verseCountSlow(gen00, curVerse), up);
                 }
             }
 
-            assertEquals(BibleInfo.versesInBook(b), new Verse(b, BibleInfo.chaptersInBook(b), BibleInfo.versesInChapter(b, BibleInfo.chaptersInBook(b))).subtract(new Verse(b, 1, 1)) + 1 );
         }
-        assertEquals(BibleInfo.versesInBook(BibleBook.GEN), exo11.subtract(gen11));
-        assertEquals(9, gen110.subtract(gen11));
+        assertEquals(9, gen110.subtract(gen00));
     }
 
     public void testNames() {
@@ -318,52 +329,4 @@
         assertEquals(65, BibleBook.REV.ordinal());
     }
 
-    /**
-     * This is code from BibleInfo that was needed only as part of testing, so I
-     * Moved it here. How many verses between ref1 and ref2 (inclusive).
-     * 
-     * @param verse1
-     *            The earlier verse
-     * @param verse2
-     *            The later verse
-     * @exception NoSuchVerseException
-     *                If either reference is illegal
-     */
-    protected int verseCountSlow(Verse verse1, Verse verse2) throws NoSuchVerseException {
-        int count = 0;
-
-        int ch1 = verse1.getChapter();
-        int ver1 = verse1.getVerse();
-
-        // If we are in different books, count the verses until the books are
-        // the same
-        if (verse1.getBook() != verse2.getBook()) {
-            // 1st count to the end of the chapter
-            count += BibleInfo.versesInChapter(verse1.getBook(), verse1.getChapter()) - verse1.getVerse() + 1;
-
-            // Then count from the end of the chapter to the end of the book
-            for (int c = verse1.getChapter() + 1; c <= BibleInfo.chaptersInBook(verse1.getBook()); c++) {
-                count += BibleInfo.versesInChapter(verse1.getBook(), c);
-            }
-
-            // Then count until the books are the same
-            for (BibleBook b = BibleInfo.getNextBook(verse1.getBook()); b.compareTo(verse2.getBook()) < 0; b = BibleInfo.getNextBook(b)) {
-                count += BibleInfo.versesInBook(b);
-            }
-
-            // The new position
-            ch1 = 1;
-            ver1 = 1;
-        }
-
-        // Count the verses in the chapters so that we are in the same chapter
-        for (int c = ch1; c < verse2.getChapter(); c++) {
-            count += BibleInfo.versesInChapter(verse2.getBook(), c);
-        }
-
-        // And finally the verses in the final chapter
-        count += verse2.getVerse() - ver1 + 1;
-
-        return count;
-    }
 }

Modified: trunk/jsword/src/test/java/org/crosswire/jsword/passage/PassageParentTst.java
===================================================================
--- trunk/jsword/src/test/java/org/crosswire/jsword/passage/PassageParentTst.java	2012-01-02 05:11:59 UTC (rev 2195)
+++ trunk/jsword/src/test/java/org/crosswire/jsword/passage/PassageParentTst.java	2012-01-03 13:53:37 UTC (rev 2196)
@@ -190,11 +190,11 @@
         {
             Iterator<Key> it = gen1_135.rangeIterator(RestrictionType.NONE);
             assertTrue(it.hasNext());
-            assertEquals(it.next(), VerseRangeFactory.fromString("Gen 1:1"));
+            assertEquals(VerseRangeFactory.fromString("Gen 1:1"), it.next());
             assertTrue(it.hasNext());
-            assertEquals(it.next(), VerseRangeFactory.fromString("Gen 1:3"));
+            assertEquals(VerseRangeFactory.fromString("Gen 1:3"), it.next());
             assertTrue(it.hasNext());
-            assertEquals(it.next(), VerseRangeFactory.fromString("Gen 1:5"));
+            assertEquals(VerseRangeFactory.fromString("Gen 1:5"), it.next());
             assertTrue(!it.hasNext());
             it = empty.rangeIterator(RestrictionType.NONE);
             assertTrue(!it.hasNext());
@@ -206,11 +206,11 @@
         {
             Iterator<Key> it = gen1_135.iterator();
             assertTrue(it.hasNext());
-            assertEquals(it.next(), VerseFactory.fromString("Gen 1:1"));
+            assertEquals(VerseFactory.fromString("Gen 1:1"), it.next());
             assertTrue(it.hasNext());
-            assertEquals(it.next(), VerseFactory.fromString("Gen 1:3"));
+            assertEquals(VerseFactory.fromString("Gen 1:3"), it.next());
             assertTrue(it.hasNext());
-            assertEquals(it.next(), VerseFactory.fromString("Gen 1:5"));
+            assertEquals(VerseFactory.fromString("Gen 1:5"), it.next());
             assertTrue(!it.hasNext());
             it = empty.iterator();
             assertTrue(!it.hasNext());
@@ -229,50 +229,50 @@
     public void testReadCountVerses() {
         // for (int i=0; i<12; i++)
         {
-            assertEquals(gen1_135.countVerses(), 3);
-            assertEquals(exo2a_3b.countVerses(), 21);
-            assertEquals(empty.countVerses(), 0);
+            assertEquals(3, gen1_135.countVerses());
+            assertEquals(21, exo2a_3b.countVerses());
+            assertEquals(0, empty.countVerses());
         }
     }
 
     public void testReadCountRanges() {
         // for (int i=0; i<10; i++)
         {
-            assertEquals(gen1_135.countRanges(RestrictionType.NONE), 3);
-            assertEquals(exo2a_3b.countRanges(RestrictionType.NONE), 2);
-            assertEquals(empty.countVerses(), 0);
+            assertEquals(3, gen1_135.countRanges(RestrictionType.NONE));
+            assertEquals(2, exo2a_3b.countRanges(RestrictionType.NONE));
+            assertEquals(0, empty.countVerses());
         }
     }
 
     public void testReadGetVerseAt() throws Exception {
         // for (int i=0; i<10; i++)
         {
-            assertEquals(gen1_135.getVerseAt(0), gen11);
-            assertEquals(gen1_135.getVerseAt(1), gen13);
-            assertEquals(gen1_135.getVerseAt(2), gen15);
-            assertEquals(exo2a_3b.getVerseAt(0), exo21);
-            assertEquals(exo2a_3b.getVerseAt(1), exo22);
-            assertEquals(exo2a_3b.getVerseAt(2), exo23);
-            assertEquals(exo2a_3b.getVerseAt(20), exo3b);
+            assertEquals(gen11, gen1_135.getVerseAt(0));
+            assertEquals(gen13, gen1_135.getVerseAt(1));
+            assertEquals(gen15, gen1_135.getVerseAt(2));
+            assertEquals(exo21, exo2a_3b.getVerseAt(0));
+            assertEquals(exo22, exo2a_3b.getVerseAt(1));
+            assertEquals(exo23, exo2a_3b.getVerseAt(2));
+            assertEquals(exo3b, exo2a_3b.getVerseAt(20));
         }
     }
 
     public void testReadGetVerseRangeAt() throws Exception {
         // for (int i=0; i<5; i++)
         {
-            assertEquals(gen1_135.getRangeAt(0, RestrictionType.NONE), gen11_1);
-            assertEquals(gen1_135.getRangeAt(1, RestrictionType.NONE), VerseRangeFactory.fromString("Gen 1:3"));
-            assertEquals(gen1_135.getRangeAt(2, RestrictionType.NONE), VerseRangeFactory.fromString("Gen 1:5"));
-            assertEquals(exo2a_3b.getRangeAt(0, RestrictionType.NONE), VerseRangeFactory.fromString("Exo 2:1-10"));
-            assertEquals(exo2a_3b.getRangeAt(1, RestrictionType.NONE), VerseRangeFactory.fromString("Exo 3:1-11"));
+            assertEquals(gen11_1, gen1_135.getRangeAt(0, RestrictionType.NONE));
+            assertEquals(VerseRangeFactory.fromString("Gen 1:3"), gen1_135.getRangeAt(1, RestrictionType.NONE));
+            assertEquals(VerseRangeFactory.fromString("Gen 1:5"), gen1_135.getRangeAt(2, RestrictionType.NONE));
+            assertEquals(VerseRangeFactory.fromString("Exo 2:1-10"), exo2a_3b.getRangeAt(0, RestrictionType.NONE));
+            assertEquals(VerseRangeFactory.fromString("Exo 3:1-11"), exo2a_3b.getRangeAt(1, RestrictionType.NONE));
         }
     }
 
     public void testReadBooksInPassage() {
         // for (int i=0; i<12; i++)
         {
-            assertEquals(gen1_135.booksInPassage(), 1);
-            assertEquals(exo2a_3b.booksInPassage(), 1);
+            assertEquals(1, gen1_135.booksInPassage());
+            assertEquals(1, exo2a_3b.booksInPassage());
         }
     }
 
@@ -799,7 +799,7 @@
 
     public void testWriteObject() throws Exception {
         Passage hard = (Passage) keyf.createEmptyKeyList();
-        for (int i = 1; i < BibleInfo.versesInBible(); i += 200) {
+        for (int i = 10; i < BibleInfo.maximumOrdinal(); i += 200) {
             hard.add(new Verse(i));
         }
 

Modified: trunk/jsword/src/test/java/org/crosswire/jsword/passage/PassageUtilTest.java
===================================================================
--- trunk/jsword/src/test/java/org/crosswire/jsword/passage/PassageUtilTest.java	2012-01-02 05:11:59 UTC (rev 2195)
+++ trunk/jsword/src/test/java/org/crosswire/jsword/passage/PassageUtilTest.java	2012-01-03 13:53:37 UTC (rev 2196)
@@ -337,7 +337,7 @@
         Passage hard = (Passage) keyf.createEmptyKeyList();
         Passage empty = (Passage) keyf.createEmptyKeyList();
 
-        for (int i = 1; i < BibleInfo.versesInBible(); i += 10) {
+        for (int i = 1; i < BibleInfo.maximumOrdinal(); i += 10) {
             hard.add(new Verse(i));
         }
 

Modified: trunk/jsword/src/test/java/org/crosswire/jsword/passage/VerseTest.java
===================================================================
--- trunk/jsword/src/test/java/org/crosswire/jsword/passage/VerseTest.java	2012-01-02 05:11:59 UTC (rev 2195)
+++ trunk/jsword/src/test/java/org/crosswire/jsword/passage/VerseTest.java	2012-01-03 13:53:37 UTC (rev 2196)
@@ -318,7 +318,7 @@
         assertEquals(gen11.subtract(gen11), 0);
         assertEquals(gen11.subtract(gen12), -1);
         Verse last = gen11.clone();
-        for (int i = 0; i < BibleInfo.versesInBible(); i += 99) {
+        for (int i = 0; i < BibleInfo.maximumOrdinal(); i += 99) {
             Verse next = last.add(i);
             assertEquals(next.subtract(last), i);
 




More information about the jsword-svn mailing list