1
20 package org.crosswire.jsword.versification;
21
22 import java.util.HashMap;
23 import java.util.LinkedHashMap;
24 import java.util.Locale;
25 import java.util.Map;
26 import java.util.MissingResourceException;
27 import java.util.ResourceBundle;
28
29 import org.crosswire.common.util.CWClassLoader;
30 import org.crosswire.common.util.ClassUtil;
31 import org.crosswire.common.util.StringUtil;
32 import org.crosswire.jsword.internationalisation.LocaleProviderManager;
33
34
41 public final class BibleNames {
42
47 public static BibleNames instance() {
48 return instance;
49 }
50
51
57 public BookName getBookName(BibleBook book) {
58 return getLocalizedBibleNames().getBookName(book);
59 }
60
61
68 public String getPreferredName(BibleBook book) {
69 return getLocalizedBibleNames().getPreferredName(book);
70 }
71
72
79 public String getLongName(BibleBook book) {
80 return getLocalizedBibleNames().getLongName(book);
81 }
82
83
90 public String getShortName(BibleBook book) {
91 return getLocalizedBibleNames().getShortName(book);
92 }
93
94
101 public BibleBook getBook(String find) {
102 BibleBook book = null;
103 if (containsLetter(find)) {
104 book = BibleBook.fromOSIS(find);
105
106 if (book == null) {
107 book = getLocalizedBibleNames().getBook(find, false);
108 }
109
110 if (book == null) {
111 book = englishBibleNames.getBook(find, false);
112 }
113
114 if (book == null) {
115 book = getLocalizedBibleNames().getBook(find, true);
116 }
117
118 if (book == null) {
119 book = englishBibleNames.getBook(find, true);
120 }
121 }
122
123 return book;
124 }
125
126
134 public boolean isBook(String find) {
135 return getBook(find) != null;
136 }
137
138
144 void load(Locale locale) {
145 NameList bibleNames = new NameList(locale);
146 if (localizedBibleNames.get(locale) == null) {
147 localizedBibleNames.put(locale, bibleNames);
148 }
149 }
150
151
154 private BibleNames() {
155 localizedBibleNames = new HashMap<Locale, NameList>();
156 englishBibleNames = getBibleNamesForLocale(Locale.ENGLISH);
157 localizedBibleNames.put(Locale.ENGLISH, englishBibleNames);
158 }
159
160
165 private NameList getLocalizedBibleNames() {
166 return getBibleNamesForLocale(LocaleProviderManager.getLocale());
168 }
169
170
176 private NameList getBibleNamesForLocale(Locale locale) {
177 NameList bibleNames = localizedBibleNames.get(locale);
178 if (bibleNames == null) {
179 bibleNames = new NameList(locale);
180 localizedBibleNames.put(locale, bibleNames);
181 }
182
183 return bibleNames;
184 }
185
186
193 private static boolean containsLetter(String text) {
194 for (int i = 0; i < text.length(); i++) {
195 if (Character.isLetter(text.charAt(i))) {
196 return true;
197 }
198 }
199
200 return false;
201 }
202
203
211 private class NameList {
212
215 NameList(Locale locale) {
216 this.locale = locale;
217 initialize();
218 }
219
220 BookName getBookName(BibleBook book) {
221 return books.get(book);
222 }
223
224
232 String getPreferredName(BibleBook book) {
233 return getBookName(book).getPreferredName();
234 }
235
236
244 String getLongName(BibleBook book) {
245 return getBookName(book).getLongName();
246 }
247
248
256 String getShortName(BibleBook book) {
257 return getBookName(book).getShortName();
258 }
259
260
269 BibleBook getBook(String find, boolean fuzzy) {
270 String match = BookName.normalize(find, locale);
271
272 BookName bookName = fullNT.get(match);
273 if (bookName != null) {
274 return bookName.getBook();
275 }
276
277 bookName = shortNT.get(match);
278 if (bookName != null) {
279 return bookName.getBook();
280 }
281
282 bookName = altNT.get(match);
283 if (bookName != null) {
284 return bookName.getBook();
285 }
286
287 bookName = fullOT.get(match);
288 if (bookName != null) {
289 return bookName.getBook();
290 }
291
292 bookName = shortOT.get(match);
293 if (bookName != null) {
294 return bookName.getBook();
295 }
296
297 bookName = altOT.get(match);
298 if (bookName != null) {
299 return bookName.getBook();
300 }
301
302 bookName = fullNC.get(match);
303 if (bookName != null) {
304 return bookName.getBook();
305 }
306
307 bookName = shortNC.get(match);
308 if (bookName != null) {
309 return bookName.getBook();
310 }
311
312 bookName = altNC.get(match);
313 if (bookName != null) {
314 return bookName.getBook();
315 }
316
317 if (!fuzzy) {
318 return null;
319 }
320
321 for (BookName aBook : books.values()) {
322 if (aBook.match(match)) {
323 return aBook.getBook();
324 }
325 }
326
327 return null;
328 }
329
330
334 private void initialize() {
335 int ntCount = 0;
336 int otCount = 0;
337 int ncCount = 0;
338 BibleBook[] bibleBooks = BibleBook.values();
339 for (BibleBook book : bibleBooks) {
340 int ordinal = book.ordinal();
341 if (ordinal > BibleBook.INTRO_OT.ordinal() && ordinal < BibleBook.INTRO_NT.ordinal()) {
342 ++ntCount;
343 } else if (ordinal > BibleBook.INTRO_NT.ordinal() && ordinal <= BibleBook.REV.ordinal()) {
344 ++otCount;
345 } else {
346 ++ncCount;
347 }
348 }
349
350 books = new LinkedHashMap<BibleBook, BookName>(ntCount + otCount + ncCount);
352
353 String className = BibleNames.class.getName();
354 String shortClassName = ClassUtil.getShortClassName(className);
355 ResourceBundle resources = ResourceBundle.getBundle(shortClassName, locale, CWClassLoader.instance(BibleNames.class));
356
357 fullNT = new HashMap<String, BookName>(ntCount);
358 shortNT = new HashMap<String, BookName>(ntCount);
359 altNT = new HashMap<String, BookName>(ntCount);
360 for (int i = BibleBook.MATT.ordinal(); i <= BibleBook.REV.ordinal(); ++i) {
361 BibleBook book = bibleBooks[i];
362 store(resources, book, fullNT, shortNT, altNT);
363 }
364
365 fullOT = new HashMap<String, BookName>(otCount);
366 shortOT = new HashMap<String, BookName>(otCount);
367 altOT = new HashMap<String, BookName>(otCount);
368 for (int i = BibleBook.GEN.ordinal(); i <= BibleBook.MAL.ordinal(); ++i) {
369 BibleBook book = bibleBooks[i];
370 store(resources, book, fullOT, shortOT, altOT);
371 }
372
373 fullNC = new HashMap<String, BookName>(ncCount);
374 shortNC = new HashMap<String, BookName>(ncCount);
375 altNC = new HashMap<String, BookName>(ncCount);
376 store(resources, BibleBook.INTRO_BIBLE, fullNC, shortNC, altNC);
377 store(resources, BibleBook.INTRO_OT, fullNC, shortNC, altNC);
378 store(resources, BibleBook.INTRO_NT, fullNC, shortNC, altNC);
379 for (int i = BibleBook.REV.ordinal() + 1; i < bibleBooks.length; ++i) {
380 BibleBook book = bibleBooks[i];
381 store(resources, book, fullNC, shortNC, altNC);
382 }
383 }
384
385 private void store(ResourceBundle resources, BibleBook book, Map fullMap, Map shortMap, Map altMap) {
386 String osisName = book.getOSIS();
387
388 String fullBook = getString(resources, osisName + FULL_KEY);
389
390 String shortBook = getString(resources, osisName + SHORT_KEY);
391 if (shortBook.length() == 0) {
392 shortBook = fullBook;
393 }
394
395 String altBook = getString(resources, osisName + ALT_KEY);
396
397 BookName bookName = new BookName(locale, BibleBook.fromOSIS(osisName), fullBook, shortBook, altBook);
398 books.put(book, bookName);
399
400 fullMap.put(bookName.getNormalizedLongName(), bookName);
401
402 shortMap.put(bookName.getNormalizedShortName(), bookName);
403
404 String[] alternates = StringUtil.split(BookName.normalize(altBook, locale), ',');
405
406 for (int j = 0; j < alternates.length; j++) {
407 altMap.put(alternates[j], bookName);
408 }
409 }
410
411
414 private String getString(ResourceBundle resources, String key) {
415 try {
416 return resources.getString(key);
417 } catch (MissingResourceException e) {
418 assert false;
419 }
420 return null;
421 }
422
423 private static final String FULL_KEY = ".Full";
424 private static final String SHORT_KEY = ".Short";
425 private static final String ALT_KEY = ".Alt";
426
427
428 private Locale locale;
429
430
433 private LinkedHashMap<BibleBook, BookName> books;
434
435
439 private Map<String, BookName> fullNT;
440
441
445 private Map<String, BookName> fullOT;
446
447
451 private Map<String, BookName> fullNC;
452
453
457 private Map<String, BookName> shortNT;
458
459
463 private Map<String, BookName> shortOT;
464
465
469 private Map<String, BookName> shortNC;
470
471
475 private Map<String, BookName> altNT;
476
477
481 private Map<String, BookName> altOT;
482
483
487 private Map<String, BookName> altNC;
488 }
489
490
491 private transient Map<Locale, NameList> localizedBibleNames;
492
493
494 private static NameList englishBibleNames;
495
496 private static final BibleNames instance = new BibleNames();
497 }
498