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