[jsword-svn] r1136 - in trunk/jsword/src/main/java/org/crosswire/jsword: . versification

dmsmith at www.crosswire.org dmsmith at www.crosswire.org
Sat Sep 30 19:44:24 MST 2006


Author: dmsmith
Date: 2006-09-30 19:44:18 -0700 (Sat, 30 Sep 2006)
New Revision: 1136

Added:
   trunk/jsword/src/main/java/org/crosswire/jsword/versification/
   trunk/jsword/src/main/java/org/crosswire/jsword/versification/BibleNames.java
   trunk/jsword/src/main/java/org/crosswire/jsword/versification/Msg.java
   trunk/jsword/src/main/java/org/crosswire/jsword/versification/OSISNames.java
Log:
ading English as fallback to non-English locales
refactoring into a versification package

Added: trunk/jsword/src/main/java/org/crosswire/jsword/versification/BibleNames.java
===================================================================
--- trunk/jsword/src/main/java/org/crosswire/jsword/versification/BibleNames.java	2006-09-30 11:24:31 UTC (rev 1135)
+++ trunk/jsword/src/main/java/org/crosswire/jsword/versification/BibleNames.java	2006-10-01 02:44:18 UTC (rev 1136)
@@ -0,0 +1,643 @@
+/**
+ * Distribution License:
+ * JSword is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License, version 2.1 as published by
+ * the Free Software Foundation. This program is distributed in the hope
+ * that it will be useful, but WITHOUT ANY WARRANTY; without even the
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU Lesser General Public License for more details.
+ *
+ * The License is available on the internet at:
+ *       http://www.gnu.org/copyleft/lgpl.html
+ * or by writing to:
+ *      Free Software Foundation, Inc.
+ *      59 Temple Place - Suite 330
+ *      Boston, MA 02111-1307, USA
+ *
+ * Copyright: 2005
+ *     The copyright to this program is held by it's authors.
+ *
+ * ID: $Id: BibleNames.java 1068 2006-04-07 22:20:41 -0400 (Fri, 07 Apr 2006) dmsmith $
+ */
+package org.crosswire.jsword.versification;
+
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
+import java.util.ResourceBundle;
+import java.util.regex.Pattern;
+
+import org.crosswire.common.util.CWClassLoader;
+import org.crosswire.common.util.StringUtil;
+import org.crosswire.jsword.book.CaseType;
+import org.crosswire.jsword.passage.BibleInfo;
+import org.crosswire.jsword.passage.NoSuchVerseException;
+
+/**
+ * BibleNames is a static class that deals with Book name lookup conversions.
+ * We start counting at 1 for books (so Genesis=1, Revelation=66).
+ * However internally books start counting at 0 and go up to 65.
+ *
+ * @see gnu.lgpl.License for license details.
+ *      The copyright to this program is held by it's authors.
+ * @author Joe Walker [joe at eireneh dot com]
+ * @author DM Smith [dmsmith555 at yahoo dot com]
+ */
+public final class BibleNames
+{
+    /**
+     * Ensure that we can not be instantiated
+     */
+    public BibleNames(Locale locale)
+    {
+        this.locale = locale;
+        initialize();
+    }
+
+    /**
+     * Get the preferred name of a book.
+     * Altered by the case setting (see setBookCase() and isLongBookName())
+     * @param book The book number (1-66)
+     * @return The full name of the book
+     * @exception NoSuchVerseException If the book number is not valid
+     */
+    public String getBookName(int book) throws NoSuchVerseException
+    {
+        if (BibleInfo.isFullBookName())
+        {
+            return getLongBookName(book);
+        }
+        return getShortBookName(book);
+    }
+
+    /**
+     * Get the full name of a book (e.g. "Genesis").
+     * Altered by the case setting (see setBookCase())
+     * @param book The book number (1-66)
+     * @return The full name of the book
+     * @exception NoSuchVerseException If the book number is not valid
+     */
+    public String getLongBookName(int book) throws NoSuchVerseException
+    {
+        try
+        {
+            CaseType bookCase = BibleInfo.getDefaultCase();
+
+            if (bookCase == CaseType.LOWER)
+            {
+                return fullBooks[book - 1].toLowerCase();
+            }
+
+            if (bookCase == CaseType.UPPER)
+            {
+                return fullBooks[book - 1].toUpperCase();
+            }
+
+            return fullBooks[book - 1];
+        }
+        catch (ArrayIndexOutOfBoundsException ex)
+        {
+            // 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
+            throw new NoSuchVerseException(Msg.BOOKS_BOOK, new Object[] { new Integer(book) });
+        }
+    }
+
+    /**
+     * Get the short name of a book (e.g. "Gen").
+     * Altered by the case setting (see setBookCase())
+     * @param book The book number (1-66)
+     * @return The short name of the book
+     * @exception NoSuchVerseException If the book number is not valid
+     */
+    public String getShortBookName(int book) throws NoSuchVerseException
+    {
+        try
+        {
+            CaseType bookCase = BibleInfo.getDefaultCase();
+
+            if (bookCase.equals(CaseType.LOWER))
+            {
+                return shortBooks[book - 1].toLowerCase();
+            }
+
+            if (bookCase.equals(CaseType.UPPER))
+            {
+                return shortBooks[book - 1].toUpperCase();
+            }
+
+            return shortBooks[book - 1];
+        }
+        catch (ArrayIndexOutOfBoundsException ex)
+        {
+            // 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
+            throw new NoSuchVerseException(Msg.BOOKS_BOOK, new Object[] { new Integer(book) });
+        }
+    }
+
+    /**
+     * Get the OSIS name for a book.
+     * @param book The book number (1-66)
+     * @return the OSIS defined short name for a book
+     * @exception NoSuchVerseException If the book number is not valid
+     */
+    public String getOSISName(int book) throws NoSuchVerseException
+    {
+        try
+        {
+            return osisBooks[book - 1];
+        }
+        catch (ArrayIndexOutOfBoundsException ex)
+        {
+            // 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
+            throw new NoSuchVerseException(Msg.BOOKS_BOOK, new Object[] { new Integer(book) });
+        }
+    }
+
+    /**
+     * Get number of a book from its name.
+     * @param find The string to identify
+     * @return The book number (1 to 66) On error -1
+     */
+    public int getBookNumber(String find)
+    {
+        String match = normalize(find);
+
+        // Favor OSIS names.
+        Integer bookNum = (Integer) osisMap.get(match);
+        if (bookNum != null)
+        {
+            return bookNum.intValue();
+        }
+
+        bookNum = (Integer) fullBooksMap.get(match);
+        if (bookNum != null)
+        {
+            return bookNum.intValue();
+        }
+
+        bookNum = (Integer) shortBooksMap.get(match);
+        if (bookNum != null)
+        {
+            return bookNum.intValue();
+        }
+
+        bookNum = (Integer) altBooksMap.get(match);
+        if (bookNum != null)
+        {
+            return bookNum.intValue();
+        }
+
+        // Or does it match one of the alternative versions
+        for (int i = 0; i < altBooks.length; i++)
+        {
+            for (int j = 0; j < altBooks[i].length; j++)
+            {
+                String targetBookName = altBooks[i][j];
+                if (targetBookName.startsWith(match) || match.startsWith(targetBookName))
+                {
+                    return i + 1;
+                }
+            }
+        }
+
+        // Does it match a long version of the book or a short version
+        for (int i = 0; i < fullBooksSearch.length; i++)
+        {
+            String targetBookName = fullBooksSearch[i];
+            if (targetBookName.startsWith(match))
+            {
+                return i + 1;
+            }
+
+            targetBookName = shortBooksSearch[i];
+            if (targetBookName.startsWith(match) || match.startsWith(targetBookName))
+            {
+                return i + 1;
+            }
+        }
+
+        return -1;
+    }
+
+    /**
+     * Is the given string a valid book name. If this method returns true then
+     * getBookNumber() will return a number and not throw an exception.
+     * @param find The string to identify
+     * @return The book number (1 to 66)
+     */
+    public boolean isBookName(String find)
+    {
+        return getBookNumber(find) != -1;
+    }
+
+    /**
+     * Is this book part of the Pentateuch?
+     * @param book The book to test
+     * @return True if this book is a part of this section
+     */
+    public static boolean isPentateuch(int book)
+    {
+        return book >= Names.GENESIS && book <= Names.DEUTERONOMY;
+    }
+
+    /**
+     * Is this book part of the OT History?
+     * @param book The book to test
+     * @return True if this book is a part of this section
+     */
+    public static boolean isHistory(int book)
+    {
+        return book >= Names.JOSHUA && book <= Names.ESTHER;
+    }
+
+    /**
+     * Is this book part of the OT History?
+     * @param book The book to test
+     * @return True if this book is a part of this section
+     */
+    public static boolean isPoetry(int book)
+    {
+        return book >= Names.JOB && book <= Names.SONGOFSOLOMON;
+    }
+
+    /**
+     * Is this book part of the major prophets?
+     * @param book The book to test
+     * @return True if this book is a part of this section
+     */
+    public static boolean isMajorProphet(int book)
+    {
+        return book >= Names.ISAIAH && book <= Names.DANIEL;
+    }
+
+    /**
+     * Is this book part of the minor prophets?
+     * @param book The book to test
+     * @return True if this book is a part of this section
+     */
+    public static boolean isMinorProphet(int book)
+    {
+        return book >= Names.HOSEA && book <= Names.MALACHI;
+    }
+
+    /**
+     * Is this book part of the Gospels?
+     * @param book The book to test
+     * @return True if this book is a part of this section
+     */
+    public static boolean isGospel(int book)
+    {
+        return book >= Names.MATTHEW && book <= Names.JOHN;
+    }
+
+    /**
+     * Is this book part of the Gospels or Acts?
+     * @param book The book to test
+     * @return True if this book is a part of this section
+     */
+    public static boolean isGospelOrActs(int book)
+    {
+        return book >= Names.MATTHEW && book <= Names.ACTS;
+    }
+
+    /**
+     * Is this book part of the letters?
+     * @param book The book to test
+     * @return True if this book is a part of this section
+     */
+    public static boolean isLetter(int book)
+    {
+        return book >= Names.ROMANS && book <= Names.JUDE;
+    }
+
+    /**
+     * What section is this book a part of?
+     * @param book The book to test
+     * @return True The section
+     * @see BibleNames.Section
+     */
+    public static int getSection(int book)
+    {
+        // Ordered by section size for speed
+        if (isLetter(book))
+        {
+            return Section.LETTERS;
+        }
+
+        if (isHistory(book))
+        {
+            return Section.HISTORY;
+        }
+
+        if (isMinorProphet(book))
+        {
+            return Section.MINOR_PROPHETS;
+        }
+
+        if (isGospelOrActs(book))
+        {
+            return Section.GOSPELS_AND_ACTS;
+        }
+
+        if (isPentateuch(book))
+        {
+            return Section.PENTATEUCH;
+        }
+
+        if (isPoetry(book))
+        {
+            return Section.POETRY;
+        }
+
+        if (isMajorProphet(book))
+        {
+            return Section.MAJOR_PROPHETS;
+        }
+
+        return Section.REVELATION;
+    }
+
+    /**
+     * Get the full name of a book (e.g. "Genesis").
+     * Altered by the case setting (see setBookCase())
+     * @param section The book number (1-66)
+     * @return The full name of the book
+     * @exception NoSuchVerseException If the book number is not valid
+     */
+    public String getSectionName(int section) throws NoSuchVerseException
+    {
+        if (section == 0)
+        {
+            throw new NoSuchVerseException(Msg.BOOKS_SECTION, new Object[] { new Integer(section)});
+        }
+
+        try
+        {
+            CaseType bookCase = BibleInfo.getDefaultCase();
+
+            if (bookCase.equals(CaseType.LOWER))
+            {
+                return sections[section - 1].toLowerCase();
+            }
+
+            if (bookCase.equals(CaseType.UPPER))
+            {
+                return sections[section - 1].toUpperCase();
+            }
+
+            return sections[section - 1];
+        }
+        catch (ArrayIndexOutOfBoundsException ex)
+        {
+            // 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
+            throw new NoSuchVerseException(Msg.BOOKS_SECTION, new Object[] { new Integer(section) });
+        }
+    }
+
+    /**
+     * Normalize by stripping punctuation and whitespace.
+     * @param str the string to normalize
+     * @return the normalized string
+     */
+    private String normalize(String str)
+    {
+        return normPattern.matcher(str).replaceAll("").toLowerCase(); //$NON-NLS-1$
+    }
+
+    /**
+     * Load up the resources for Bible book and section names,
+     * and cache the upper and lower versions of them.
+     */
+    private void initialize()
+    {
+        int booksInBible = BibleInfo.booksInBible();
+
+        // Create the book name arrays
+        fullBooks = new String[booksInBible];
+        fullBooksSearch = new String[booksInBible];
+        fullBooksMap = new HashMap(booksInBible);
+
+        shortBooks = new String[booksInBible];
+        shortBooksSearch = new String[booksInBible];
+        shortBooksMap = new HashMap(booksInBible);
+
+        altBooks = new String[booksInBible][];
+        altBooksMap = new HashMap(booksInBible);
+
+        ResourceBundle resources = ResourceBundle.getBundle(BibleInfo.class.getName(), locale, new CWClassLoader(BibleInfo.class));
+
+        for (int i = 0; i < booksInBible; i++)
+        {
+            Integer bookNum = new Integer(i + 1);
+            String fullBook = getString(resources, FULL_KEY + (i + 1));
+            String normalized = normalize(fullBook);
+            fullBooks[i] = fullBook;
+            fullBooksSearch[i] = normalized;
+            fullBooksMap.put(normalized, bookNum);
+
+            String shortBook = getString(resources, SHORT_KEY + (i + 1));
+            normalized = normalize(shortBook);
+            shortBooks[i] = shortBook;
+            shortBooksSearch[i] = normalized;
+            shortBooksMap.put(normalized, bookNum);
+
+            String altBook = getString(resources, ALT_KEY + (i + 1));
+            String [] alternates = StringUtil.split(altBook, ',');
+            altBooks[i] = alternates;
+
+            for (int j = 0; j < alternates.length; j++)
+            {
+                altBooksMap.put(alternates[j], bookNum);
+            }
+        }
+
+        sections = new String[SECTIONS_IN_BIBLE];
+
+        for (int i = 0; i < SECTIONS_IN_BIBLE; i++)
+        {
+            String section = getString(resources, SECTION_KEY + (i + 1));
+            sections[i] = section;
+        }
+
+        if (osisBooks == null)
+        {
+            osisBooks = new String[booksInBible];
+            osisMap   = new HashMap(booksInBible);
+
+            // Get all the OSIS standard book names
+            resources = ResourceBundle.getBundle(OSIS_PROPERTIES, Locale.getDefault(), new CWClassLoader(BibleInfo.class));
+
+            for (int i = 0; i < osisBooks.length; i++)
+            {
+                osisBooks[i] = getString(resources, OSIS_KEY + (i + 1));
+                osisMap.put(normalize(osisBooks[i]), new Integer(i + 1));
+            }
+        }
+    }
+
+    /*
+     * Helper to make the code more readable.
+     */
+    private String getString(ResourceBundle resources, String key)
+    {
+        try
+        {
+            return resources.getString(key);
+        }
+        catch (Exception e)
+        {
+            assert false;
+        }
+        return null;
+    }
+
+    private static final String FULL_KEY = "BibleNames.Full."; //$NON-NLS-1$
+    private static final String SHORT_KEY = "BibleNames.Short."; //$NON-NLS-1$
+    private static final String ALT_KEY = "BibleNames.Alt."; //$NON-NLS-1$
+    private static final String SECTION_KEY = "BibleNames.Sections."; //$NON-NLS-1$
+    private static final String OSIS_KEY = "BibleNames.OSIS."; //$NON-NLS-1$
+    private static final String OSIS_PROPERTIES = "OSISNames"; //$NON-NLS-1$
+
+    /**
+     * Handy section finder. There is a bit of moderately bad programming
+     * here because org.crosswire.jsword.control.map.sw*ng.GroupVerseColor
+     * uses these numbers as an index into an array, so we shouldn't
+     * change these numbers without fixing that, however I don't imagine
+     * that this section could ever change without breaking
+     * GroupVerseColor anyway so I don't see it as a big problem.
+     */
+    public static class Section
+    {
+        public static final byte PENTATEUCH = 1;
+        public static final byte HISTORY = 2;
+        public static final byte POETRY = 3;
+        public static final byte MAJOR_PROPHETS = 4;
+        public static final byte MINOR_PROPHETS = 5;
+        public static final byte GOSPELS_AND_ACTS = 6;
+        public static final byte LETTERS = 7;
+        public static final byte REVELATION = 8;
+    }
+
+    /**
+     * Handy book finder
+     */
+    public static class Names
+    {
+        public static final byte GENESIS = 1;
+        public static final byte EXODUS = 2;
+        public static final byte LEVITICUS = 3;
+        public static final byte NUMBERS = 4;
+        public static final byte DEUTERONOMY = 5;
+        public static final byte JOSHUA = 6;
+        public static final byte JUDGES = 7;
+        public static final byte RUTH = 8;
+        public static final byte SAMUEL1 = 9;
+        public static final byte SAMUEL2 = 10;
+        public static final byte KINGS1 = 11;
+        public static final byte KINGS2 = 12;
+        public static final byte CHRONICLES1 = 13;
+        public static final byte CHRONICLES2 = 14;
+        public static final byte EZRA = 15;
+        public static final byte NEHEMIAH = 16;
+        public static final byte ESTHER = 17;
+        public static final byte JOB = 18;
+        public static final byte PSALMS = 19;
+        public static final byte PROVERBS = 20;
+        public static final byte ECCLESIASTES = 21;
+        public static final byte SONGOFSOLOMON = 22;
+        public static final byte ISAIAH = 23;
+        public static final byte JEREMIAH = 24;
+        public static final byte LAMENTATIONS = 25;
+        public static final byte EZEKIEL = 26;
+        public static final byte DANIEL = 27;
+        public static final byte HOSEA = 28;
+        public static final byte JOEL = 29;
+        public static final byte AMOS = 30;
+        public static final byte OBADIAH = 31;
+        public static final byte JONAH = 32;
+        public static final byte MICAH = 33;
+        public static final byte NAHUM = 34;
+        public static final byte HABAKKUK = 35;
+        public static final byte ZEPHANIAH = 36;
+        public static final byte HAGGAI = 37;
+        public static final byte ZECHARIAH = 38;
+        public static final byte MALACHI = 39;
+        public static final byte MATTHEW = 40;
+        public static final byte MARK = 41;
+        public static final byte LUKE = 42;
+        public static final byte JOHN = 43;
+        public static final byte ACTS = 44;
+        public static final byte ROMANS = 45;
+        public static final byte CORINTHIANS1 = 46;
+        public static final byte CORINTHIANS2 = 47;
+        public static final byte GALATIANS = 48;
+        public static final byte EPHESIANS = 49;
+        public static final byte PHILIPPIANS = 50;
+        public static final byte COLOSSIANS = 51;
+        public static final byte THESSALONIANS1 = 52;
+        public static final byte THESSALONIANS2 = 53;
+        public static final byte TIMOTHY1 = 54;
+        public static final byte TIMOTHY2 = 55;
+        public static final byte TITUS = 56;
+        public static final byte PHILEMON = 57;
+        public static final byte HEBREWS = 58;
+        public static final byte JAMES = 59;
+        public static final byte PETER1 = 60;
+        public static final byte PETER2 = 61;
+        public static final byte JOHN1 = 62;
+        public static final byte JOHN2 = 63;
+        public static final byte JOHN3 = 64;
+        public static final byte JUDE = 65;
+        public static final byte REVELATION = 66;
+    }
+
+    /** The locale for the Bible Names */
+    private Locale locale;
+
+    /** The full names of the book of the Bible, in mixed case */
+    private String[] fullBooks;
+
+    /** The full names of the book of the Bible, normalized, generated at runtime */
+    private String[] fullBooksSearch;
+
+    /** The full names of the book of the Bible, normalized, generated at runtime */
+    private Map fullBooksMap;
+
+    /** Standard shortened names for the book of the Bible, in mixed case */
+    private String[] shortBooks;
+
+    /** Standard shortened names for the book of the Bible, normalized, generated at runtime. */
+    private String[] shortBooksSearch;
+
+    /** Standard shortened names for the book of the Bible, normalized, generated at runtime. */
+    private Map shortBooksMap;
+
+     /** Alternative shortened names for the book of the Bible, expected to be normalized */
+    private String[][] altBooks;
+
+    /** Alternative shortened names for the book of the Bible, normalized, generated at runtime */
+    private Map altBooksMap;
+
+    /** Standard OSIS names for the book of the Bible, in mixed case */
+    private static String[] osisBooks;
+
+    /** Standard OSIS names for the book of the Bible, in lowercase, generated at runtime  */
+    private static Map osisMap;
+
+    /** Standard names for the sections */
+    private String[] sections;
+
+    private static Pattern normPattern = Pattern.compile("[. ]"); //$NON-NLS-1$
+
+    /** Constant for the number of sections in the Bible */
+    private static final int SECTIONS_IN_BIBLE = 8;
+
+}

Added: trunk/jsword/src/main/java/org/crosswire/jsword/versification/Msg.java
===================================================================
--- trunk/jsword/src/main/java/org/crosswire/jsword/versification/Msg.java	2006-09-30 11:24:31 UTC (rev 1135)
+++ trunk/jsword/src/main/java/org/crosswire/jsword/versification/Msg.java	2006-10-01 02:44:18 UTC (rev 1136)
@@ -0,0 +1,55 @@
+/**
+ * Distribution License:
+ * JSword is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License, version 2.1 as published by
+ * the Free Software Foundation. This program is distributed in the hope
+ * that it will be useful, but WITHOUT ANY WARRANTY; without even the
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU Lesser General Public License for more details.
+ *
+ * The License is available on the internet at:
+ *       http://www.gnu.org/copyleft/lgpl.html
+ * or by writing to:
+ *      Free Software Foundation, Inc.
+ *      59 Temple Place - Suite 330
+ *      Boston, MA 02111-1307, USA
+ *
+ * Copyright: 2005
+ *     The copyright to this program is held by it's authors.
+ *
+ * ID: $Id: Msg.java 763 2005-07-27 23:26:43Z dmsmith $
+ */
+package org.crosswire.jsword.versification;
+
+import org.crosswire.common.util.MsgBase;
+
+/**
+ * Compile safe Msg resource settings.
+ * 
+ * @see gnu.lgpl.License for license details.
+ *      The copyright to this program is held by it's authors.
+ * @author Joe Walker [joe at eireneh dot com]
+ */
+public final class Msg extends MsgBase
+{
+    static final Msg BOOKS_BOOK = new Msg("BibleInfo.Book"); //$NON-NLS-1$
+    static final Msg BOOKS_SECTION = new Msg("BibleInfo.Section"); //$NON-NLS-1$
+    static final Msg BOOKS_NUMBER = new Msg("BibleInfo.Number"); //$NON-NLS-1$
+    static final Msg BOOKS_FIND = new Msg("BibleInfo.Find"); //$NON-NLS-1$
+    static final Msg BOOKS_BOOKCHAP = new Msg("BibleInfo.BookChap"); //$NON-NLS-1$
+    static final Msg BOOKS_ORDINAL = new Msg("BibleInfo.Ordinal"); //$NON-NLS-1$
+    static final Msg BOOKS_DECODE = new Msg("BibleInfo.Decode"); //$NON-NLS-1$
+    static final Msg BOOKS_CHAPTER = new Msg("BibleInfo.Chapter"); //$NON-NLS-1$
+    static final Msg BOOKS_VERSE = new Msg("BibleInfo.Verse"); //$NON-NLS-1$
+
+    static final Msg ERROR_CASE = new Msg("BibleInfo.ErrorCase"); //$NON-NLS-1$
+
+
+    /**
+     * Passthrough ctor
+     */
+    private Msg(String name)
+    {
+        super(name);
+    }
+}

Added: trunk/jsword/src/main/java/org/crosswire/jsword/versification/OSISNames.java
===================================================================
--- trunk/jsword/src/main/java/org/crosswire/jsword/versification/OSISNames.java	2006-09-30 11:24:31 UTC (rev 1135)
+++ trunk/jsword/src/main/java/org/crosswire/jsword/versification/OSISNames.java	2006-10-01 02:44:18 UTC (rev 1136)
@@ -0,0 +1,170 @@
+/**
+ * Distribution License:
+ * JSword is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License, version 2.1 as published by
+ * the Free Software Foundation. This program is distributed in the hope
+ * that it will be useful, but WITHOUT ANY WARRANTY; without even the
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU Lesser General Public License for more details.
+ *
+ * The License is available on the internet at:
+ *       http://www.gnu.org/copyleft/lgpl.html
+ * or by writing to:
+ *      Free Software Foundation, Inc.
+ *      59 Temple Place - Suite 330
+ *      Boston, MA 02111-1307, USA
+ *
+ * Copyright: 2005
+ *     The copyright to this program is held by it's authors.
+ *
+ * ID: $Id: BibleNames.java 1068 2006-04-07 22:20:41 -0400 (Fri, 07 Apr 2006) dmsmith $
+ */
+package org.crosswire.jsword.versification;
+
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
+import java.util.ResourceBundle;
+import java.util.regex.Pattern;
+
+import org.crosswire.common.util.CWClassLoader;
+import org.crosswire.jsword.passage.BibleInfo;
+import org.crosswire.jsword.passage.NoSuchVerseException;
+
+/**
+ * BibleNames is a static class that deals with Book name lookup conversions.
+ * We start counting at 1 for books (so Genesis=1, Revelation=66).
+ * However internally books start counting at 0 and go up to 65.
+ *
+ * @see gnu.lgpl.License for license details.
+ *      The copyright to this program is held by it's authors.
+ * @author Joe Walker [joe at eireneh dot com]
+ * @author DM Smith [dmsmith555 at yahoo dot com]
+ */
+public final class OSISNames
+{
+    /**
+     * Ensure that we can not be instantiated
+     */
+    private OSISNames()
+    {
+        initialize();
+    }
+
+    /**
+     * Get the OSIS name for a book.
+     * @param book The book number (1-66)
+     * @return the OSIS defined short name for a book
+     * @exception NoSuchVerseException If the book number is not valid
+     */
+    public static String getName(int book) throws NoSuchVerseException
+    {
+        try
+        {
+            return osisBooks[book - 1];
+        }
+        catch (ArrayIndexOutOfBoundsException ex)
+        {
+            // 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
+            throw new NoSuchVerseException(Msg.BOOKS_BOOK, new Object[] { new Integer(book) });
+        }
+    }
+
+    /**
+     * Get number of a book from its name.
+     * @param find The string to identify
+     * @return The book number (1 to 66) On error -1
+     */
+    public static int getBookNumber(String find)
+    {
+        String match = normalize(find);
+
+        // Favor OSIS names.
+        Integer bookNum = (Integer) osisMap.get(match);
+        if (bookNum != null)
+        {
+            return bookNum.intValue();
+        }
+
+        return -1;
+    }
+
+    /**
+     * Is the given string a valid book name. If this method returns true then
+     * getBookNumber() will return a number and not throw an exception.
+     * @param find The string to identify
+     * @return The book number (1 to 66)
+     */
+    public static boolean isBookName(String find)
+    {
+        return getBookNumber(find) != -1;
+    }
+
+    /**
+     * Normalize by stripping punctuation and whitespace.
+     * @param str the string to normalize
+     * @return the normalized string
+     */
+    private static String normalize(String str)
+    {
+        return normPattern.matcher(str).replaceAll("").toLowerCase(); //$NON-NLS-1$
+    }
+
+    /**
+     * Load up the resources for Bible book and section names,
+     * and cache the upper and lower versions of them.
+     */
+    private static void initialize()
+    {
+        int booksInBible = BibleInfo.booksInBible();
+        if (osisBooks == null)
+        {
+            osisBooks = new String[booksInBible];
+            osisMap   = new HashMap(booksInBible);
+
+            // Get all the OSIS standard book names
+            ResourceBundle resources = ResourceBundle.getBundle(OSIS_PROPERTIES, Locale.getDefault(), new CWClassLoader(OSISNames.class));
+
+            for (int i = 0; i < osisBooks.length; i++)
+            {
+                osisBooks[i] = getString(resources, OSIS_KEY + (i + 1));
+                osisMap.put(normalize(osisBooks[i]), new Integer(i + 1));
+            }
+        }
+    }
+
+    /*
+     * Helper to make the code more readable.
+     */
+    private static String getString(ResourceBundle resources, String key)
+    {
+        try
+        {
+            return resources.getString(key);
+        }
+        catch (Exception e)
+        {
+            assert false;
+        }
+        return null;
+    }
+
+    /**
+     * A singleton used to do initialization. Could be used to change static methods to non-static
+     */
+    protected static final OSISNames instance = new OSISNames();
+
+    private static final String OSIS_KEY = "BibleNames.OSIS."; //$NON-NLS-1$
+    private static final String OSIS_PROPERTIES = "OSISNames"; //$NON-NLS-1$
+
+    /** Standard OSIS names for the book of the Bible, in mixed case */
+    private static String[] osisBooks;
+
+    /** Standard OSIS names for the book of the Bible, in lowercase, generated at runtime  */
+    private static Map osisMap;
+
+    private static Pattern normPattern = Pattern.compile("[. ]"); //$NON-NLS-1$
+
+}




More information about the jsword-svn mailing list