BookName.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, 2007 - 2016 18 * 19 */ 20 package org.crosswire.jsword.versification; 21 22 import java.util.Locale; 23 import java.util.regex.Pattern; 24 25 import org.crosswire.common.util.StringUtil; 26 import org.crosswire.jsword.book.CaseType; 27 28 /** 29 * BookName represents the different ways a book of the bible is named. 30 * 31 * @see gnu.lgpl.License The GNU Lesser General Public License for details. 32 * @author DM Smith 33 */ 34 public final class BookName { 35 /** 36 * Create a BookName for a Book of the Bible in a given language. 37 * 38 * @param locale 39 * the language of this BookName 40 * @param book 41 * the Book's canonical number 42 * @param longName 43 * the Book's long name 44 * @param shortName 45 * the Book's short name, if any 46 * @param alternateNames 47 * optional comma separated list of alternates for the Book 48 */ 49 public BookName(Locale locale, BibleBook book, String longName, String shortName, String alternateNames) { 50 this.locale = locale; 51 this.book = book; 52 this.longName = longName; 53 this.normalizedLongName = normalize(longName, locale); 54 this.shortName = shortName; 55 this.normalizedShortName = normalize(shortName, locale); 56 57 if (alternateNames != null) { 58 this.alternateNames = StringUtil.split(normalize(alternateNames, locale), ','); 59 } 60 } 61 62 /** 63 * Get the BibleBook to which this set of names is tied. 64 * 65 * @return The book 66 */ 67 public BibleBook getBook() { 68 return book; 69 } 70 71 /** 72 * Get the preferred name of a book. Altered by the case setting (see 73 * setBookCase() and isFullBookName()) 74 * 75 * @return The preferred name of the book 76 */ 77 public String getPreferredName() { 78 if (BookName.isFullBookName()) { 79 return getLongName(); 80 } 81 return getShortName(); 82 } 83 84 /** 85 * Get the full name of a book (e.g. "Genesis"). Altered by the case setting 86 * (see setBookCase()) 87 * 88 * @return The full name of the book 89 */ 90 public String getLongName() { 91 CaseType caseType = BookName.getDefaultCase(); 92 93 if (caseType == CaseType.LOWER) { 94 return longName.toLowerCase(locale); 95 } 96 97 if (caseType == CaseType.UPPER) { 98 return longName.toUpperCase(locale); 99 } 100 101 return longName; 102 } 103 104 /** 105 * Get the short name of a book (e.g. "Gen"). Altered by the case setting 106 * (see setBookCase()) 107 * 108 * @return The short name of the book 109 */ 110 public String getShortName() { 111 CaseType caseType = BookName.getDefaultCase(); 112 113 if (caseType == CaseType.LOWER) { 114 return shortName.toLowerCase(locale); 115 } 116 117 if (caseType == CaseType.UPPER) { 118 return shortName.toUpperCase(locale); 119 } 120 121 return shortName; 122 } 123 124 /** 125 * @return the normalizedLongName 126 */ 127 public String getNormalizedLongName() { 128 return normalizedLongName; 129 } 130 131 /** 132 * @return the normalizedShortName 133 */ 134 public String getNormalizedShortName() { 135 return normalizedShortName; 136 } 137 138 /** 139 * Match the normalized name as closely as possible. It will match if: 140 * <ol> 141 * <li>it is a prefix of a normalized alternate name</li> 142 * <li>a normalized alternate name is a prefix of it</li> 143 * <li>it is a prefix of a normalized long name</li> 144 * <li>it is a prefix of a normalized short name</li> 145 * <li>a normalized short name is a prefix of it</li> 146 * </ol> 147 * 148 * @param normalizedName 149 * the already normalized name to match against. 150 * @return true of false 151 */ 152 public boolean match(String normalizedName) { 153 // Does it match one of the alternative versions 154 for (int j = 0; j < alternateNames.length; j++) { 155 String targetBookName = alternateNames[j]; 156 if (targetBookName.startsWith(normalizedName) || normalizedName.startsWith(targetBookName)) { 157 return true; 158 } 159 } 160 161 // Does it match a long version of the book 162 if (normalizedLongName.startsWith(normalizedName)) { 163 return true; 164 } 165 166 // or a short version 167 if (normalizedShortName.startsWith(normalizedName) || (normalizedShortName.length() > 0 && normalizedName.startsWith(normalizedShortName))) { 168 return true; 169 } 170 171 return false; 172 } 173 174 /* 175 * (non-Javadoc) 176 * 177 * @see java.lang.Object#hashCode() 178 */ 179 @Override 180 public int hashCode() { 181 return book.hashCode(); 182 } 183 184 /* 185 * (non-Javadoc) 186 * 187 * @see java.lang.Object#equals(java.lang.Object) 188 */ 189 @Override 190 public boolean equals(Object obj) { 191 if (this == obj) { 192 return true; 193 } 194 195 if (obj == null) { 196 return false; 197 } 198 199 if (getClass() != obj.getClass()) { 200 return false; 201 } 202 203 final BookName other = (BookName) obj; 204 return book == other.book; 205 } 206 207 /* 208 * (non-Javadoc) 209 * 210 * @see java.lang.Object#toString() 211 */ 212 @Override 213 public String toString() { 214 return getPreferredName(); 215 } 216 217 /** 218 * Normalize by stripping punctuation and whitespace and lowercasing. 219 * 220 * @param str 221 * the string to normalize 222 * @param locale the locale that should be used for normalization 223 * @return the normalized string 224 */ 225 public static String normalize(String str, Locale locale) { 226 return normPattern.matcher(str).replaceAll("").toLowerCase(locale); 227 } 228 229 /** 230 * This is only used by config. 231 * 232 * @param bookCase 233 * The new case to use for reporting book names 234 * @exception IllegalArgumentException 235 * If the case is not between 0 and 2 236 * @see #getCase() 237 */ 238 public static void setCase(int bookCase) { 239 BookName.bookCase = CaseType.fromInteger(bookCase); 240 } 241 242 /** 243 * How do we report the names of the books?. These are static. This is on 244 * the assumption that we will not want to have different sections of the 245 * app using a different format. I expect this to be a good assumption, and 246 * it saves passing a Book class around everywhere. CaseType.MIXED is not 247 * allowed 248 * 249 * @param newBookCase 250 * The new case to use for reporting book names 251 * @exception IllegalArgumentException 252 * If the case is not between 0 and 2 253 * @see #getCase() 254 */ 255 public static void setCase(CaseType newBookCase) { 256 BookName.bookCase = newBookCase; 257 } 258 259 /** 260 * This is only used by config 261 * 262 * @return The current case setting 263 * @see #setCase(CaseType) 264 */ 265 public static int getCase() { 266 return BookName.bookCase.toInteger(); 267 } 268 269 /** 270 * This is only used by config 271 * 272 * @return Whether the name is long or short. Default is Full (true). 273 * @see #setFullBookName(boolean) 274 */ 275 public static boolean isFullBookName() { 276 return BookName.fullBookName; 277 } 278 279 /** 280 * Set whether the name should be full or abbreviated, long or short. 281 * 282 * @param fullName 283 * The new case to use for reporting book names 284 * @see #isFullBookName() 285 */ 286 public static void setFullBookName(boolean fullName) { 287 BookName.fullBookName = fullName; 288 } 289 290 /** 291 * How do we report the names of the books?. 292 * 293 * @return The current case setting 294 * @see #setCase(int) 295 */ 296 public static CaseType getDefaultCase() { 297 return BookName.bookCase; 298 } 299 300 /** remove spaces and some punctuation in Book Name (make sure , is allowed) */ 301 private static Pattern normPattern = Pattern.compile("[. ]"); 302 303 private BibleBook book; 304 private String longName; 305 private String normalizedLongName; 306 private String shortName; 307 private String normalizedShortName; 308 private String[] alternateNames; 309 310 /** The locale for the Book Name */ 311 private Locale locale; 312 313 /** How the book names are reported. */ 314 private static CaseType bookCase = CaseType.SENTENCE; 315 316 /** Whether long or short, full or abbreviated names are used. */ 317 private static boolean fullBookName = true; 318 319 } 320