BibleBookList.java |
1 /** 2 * Distribution License: 3 * JSword is free software; you can redistribute it and/or modify it under 4 * the terms of the GNU Lesser General Public License, version 2.1 or later 5 * as published by the Free Software Foundation. This program is distributed 6 * in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even 7 * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 8 * See the GNU Lesser General Public License for more details. 9 * 10 * The License is available on the internet at: 11 * http://www.gnu.org/copyleft/lgpl.html 12 * or by writing to: 13 * Free Software Foundation, Inc. 14 * 59 Temple Place - Suite 330 15 * Boston, MA 02111-1307, USA 16 * 17 * © CrossWire Bible Society, 2012 - 2016 18 * 19 */ 20 package org.crosswire.jsword.versification; 21 22 import java.io.Serializable; 23 import java.util.Iterator; 24 import java.util.NoSuchElementException; 25 26 /** 27 * A BibleBookList is an ordered list of one or more BibleBooks. 28 * Typically, a BibleBookList is a member of a Versification. 29 * 30 * @see gnu.lgpl.License The GNU Lesser General Public License for details. 31 * @author DM Smith 32 */ 33 /* pkg protected */ class BibleBookList implements Iterable<BibleBook>, Serializable { 34 /** 35 * Create an ordered BibleBookList from the input. 36 * @param books 37 */ 38 BibleBookList(BibleBook[] books) { 39 this.books = books.clone(); 40 initialize(); 41 } 42 43 /** 44 * Does this Versification contain the BibleBook. 45 * 46 * @param book 47 * @return true if it is present. 48 */ 49 public boolean contains(BibleBook book) { 50 return book != null && bookMap[book.ordinal()] != -1; 51 } 52 53 /** 54 * Where does the BibleBook come in the order of books of the Bible. 55 * The first book is 0, the next is 1 and so forth. 56 * If the BibleBook is not in this Reference System, 57 * then the return value of this routine is -1. 58 * 59 * @param book 60 * @return the ordinal value of the book or -1 if not present 61 */ 62 public int getOrdinal(BibleBook book) { 63 return bookMap[book.ordinal()]; 64 } 65 66 /** 67 * Get the number of books in this Versification. 68 * @return the number of books 69 */ 70 public int getBookCount() { 71 return books.length; 72 } 73 74 /** 75 * Get the BibleBook by its position in this Versification. 76 * If the position is negative, return the first book. 77 * If the position is greater than the last, return the last book. 78 * 79 * @param ordinal 80 * @return the indicated book 81 */ 82 public BibleBook getBook(int ordinal) { 83 int ord = ordinal; 84 if (ord < 0) { 85 ord = 0; 86 } 87 if (ord >= books.length) { 88 ord = books.length - 1; 89 } 90 return books[ord]; 91 } 92 93 /** 94 * Get the BibleBooks in this Versification. 95 * 96 * @return an Iterator over the books 97 */ 98 public Iterator<BibleBook> iterator() { 99 return new Iterator<BibleBook>() { 100 101 private BibleBook nextBook = books[0]; 102 103 public boolean hasNext() { 104 return nextBook != null; 105 } 106 107 public BibleBook next() { 108 109 if (nextBook == null) { 110 throw new NoSuchElementException(); 111 } 112 113 BibleBook current = nextBook; 114 nextBook = getNextBook(nextBook); 115 return current; 116 } 117 118 public void remove() { 119 throw new UnsupportedOperationException(); 120 } 121 122 }; 123 } 124 125 /** 126 * Return the first book in the list. 127 * 128 * @return the first book in the list 129 */ 130 public BibleBook getFirstBook() { 131 return books[0]; 132 } 133 134 /** 135 * Return the first book in the list. 136 * 137 * @return the first book in the list 138 */ 139 public BibleBook getLastBook() { 140 return books[books.length - 1]; 141 } 142 143 /** 144 * Given a BibleBook, get the previous BibleBook in this Versification. If it is the first book, return null. 145 * @param book A BibleBook in the Versification 146 * @return the previous BibleBook or null. 147 */ 148 public BibleBook getPreviousBook(BibleBook book) { 149 int ordinal = book.ordinal(); 150 int position = bookMap[ordinal]; 151 if (position > 0) { 152 return books[position - 1]; 153 } 154 155 return null; 156 } 157 158 /** 159 * Given a BibleBook, get the next BibleBook in this Versification. If it is the last book, return null. 160 * @param book A BibleBook in the Versification 161 * @return the previous BibleBook or null. 162 */ 163 public BibleBook getNextBook(BibleBook book) { 164 int ordinal = book.ordinal(); 165 int position = bookMap[ordinal]; 166 if (position != -1 && position + 1 < books.length) { 167 return books[position + 1]; 168 } 169 return null; 170 } 171 172 /** 173 * The bookMap contains one slot for every BibleBook, indexed by it's ordinal value. 174 * The value of that entry is the position of the book in the BookList. 175 * If the BibleBook is not present in books, it's value is -1. 176 */ 177 private void initialize() { 178 bookMap = new int[BibleBook.values().length + 1]; 179 // Initialize all slots to -1 180 for (BibleBook b : BibleBook.values()) { 181 bookMap[b.ordinal()] = -1; 182 } 183 184 // Fill in the position of the books into that list 185 for (int i = 0; i < books.length; i++) { 186 bookMap[books[i].ordinal()] = i; 187 } 188 } 189 190 /** The ordered books in this list */ 191 protected BibleBook[] books; 192 193 /** The bookMap maps from a BibleBook to the position that it has in <code>books</code>. */ 194 private int[] bookMap; 195 196 /** 197 * Serialization ID 198 */ 199 private static final long serialVersionUID = -2681289798451902815L; 200 } 201