[jsword-svn] r1647 - in trunk: biblemapper/src/main/java/org/crosswire/biblemapper/swing common/src/main/java/org/crosswire/common/icu common-swing/src/main/java/org/crosswire/common/swing jsword/src/main/java/org/crosswire/jsword/book jsword/src/main/java/org/crosswire/jsword/book/install/sword jsword/src/main/java/org/crosswire/jsword/passage jsword-limbo/src/main/java/org/crosswire/jsword/book/install/sword

dmsmith at www.crosswire.org dmsmith at www.crosswire.org
Sun Aug 5 18:35:25 MST 2007


Author: dmsmith
Date: 2007-08-05 18:35:25 -0700 (Sun, 05 Aug 2007)
New Revision: 1647

Modified:
   trunk/biblemapper/src/main/java/org/crosswire/biblemapper/swing/BookChooser.java
   trunk/common-swing/src/main/java/org/crosswire/common/swing/Msg_fa.properties
   trunk/common/src/main/java/org/crosswire/common/icu/NumberShaper.java
   trunk/jsword-limbo/src/main/java/org/crosswire/jsword/book/install/sword/FTPMsg.properties
   trunk/jsword/src/main/java/org/crosswire/jsword/book/Books.java
   trunk/jsword/src/main/java/org/crosswire/jsword/book/install/sword/Msg.properties
   trunk/jsword/src/main/java/org/crosswire/jsword/passage/VerseRangeFactory.java
Log:
Fixed spelling in documentation.
Added a method to determine the longest string length of a property in a filtered list of books.
Added a partial fix to the display of chapter:verse in Farsi.

Modified: trunk/biblemapper/src/main/java/org/crosswire/biblemapper/swing/BookChooser.java
===================================================================
--- trunk/biblemapper/src/main/java/org/crosswire/biblemapper/swing/BookChooser.java	2007-08-06 01:12:14 UTC (rev 1646)
+++ trunk/biblemapper/src/main/java/org/crosswire/biblemapper/swing/BookChooser.java	2007-08-06 01:35:25 UTC (rev 1647)
@@ -223,7 +223,7 @@
     public static final int APPROVE_OPTION = 0;
 
     /**
-     * Return value if an error occured
+     * Return value if an error occurred
      */
     public static final int ERROR_OPTION = -1;
 

Modified: trunk/common/src/main/java/org/crosswire/common/icu/NumberShaper.java
===================================================================
--- trunk/common/src/main/java/org/crosswire/common/icu/NumberShaper.java	2007-08-06 01:12:14 UTC (rev 1646)
+++ trunk/common/src/main/java/org/crosswire/common/icu/NumberShaper.java	2007-08-06 01:35:25 UTC (rev 1647)
@@ -22,11 +22,8 @@
 
 package org.crosswire.common.icu;
 
-import java.awt.font.NumericShaper;
 import java.util.Locale;
 
-import org.crosswire.common.util.ReflectionUtil;
-
 /**
  * NumberShaper changes numbers from one number system to another.
  * That is, the numbers 0-9 have different representations in some
@@ -37,6 +34,14 @@
  * they should show as a user wishes. Further user input may, optionally,
  * use the external form.
  * </p>
+ * <p>
+ * This shaper has special behavior for Arabic numbers that are in the form "12:34"
+ * as this is taken as chapter:verse. Normally, a ':' is treated as a numeric
+ * separator, this results in "12:34", but for verses it should be "34:12".
+ * That is, Arabic, numbers are left-to-right (even though the rest of the language
+ * is right-to-left) and the ':' as a numeric separator does not change that.
+ * So to get around this we mark the ':' as a right-to-left character.
+ * </p>
  * @see java.awt.font.NumericShaper
  * @see com.ibm.icu.text.ArabicShaping
  * @see gnu.lgpl.License for license details.<br>
@@ -62,46 +67,6 @@
     {
         this.locale = locale;
         this.nineShape = '\u0000';
-
-        if (locale.getLanguage().equals("fa")) //$NON-NLS-1$
-        {
-            try
-            {
-                Class[] classTypes = { int.class };
-                Object[] shape = { new Integer(ICU_DIGIT_TYPE_AN_EXTENDED | ICU_DIGITS_EN2AN) };
-                Object[] unshape = { new Integer(ICU_DIGIT_TYPE_AN_EXTENDED | ICU_DIGITS_AN2EN) };
-                arabicShaper = ReflectionUtil.construct("com.ibm.icu.text.ArabicShaping", shape, classTypes); //$NON-NLS-1$
-                unArabicShaper = ReflectionUtil.construct("com.ibm.icu.text.ArabicShaping", unshape, classTypes); //$NON-NLS-1$
-            }
-            catch (Exception e)
-            {
-                // This is OK. The jar is not on the classpath
-            }
-            if (arabicShaper == null)
-            {
-                numericShaper = NumericShaper.getShaper(NumericShaper.EASTERN_ARABIC);
-            }
-        }
-
-        if (locale.getLanguage().equals("ar")) //$NON-NLS-1$
-        {
-            try
-            {
-                Class[] classTypes = { int.class };
-                Object[] shape = { new Integer(ICU_DIGIT_TYPE_AN | ICU_DIGITS_EN2AN) };
-                Object[] unshape = { new Integer(ICU_DIGIT_TYPE_AN | ICU_DIGITS_AN2EN) };
-                arabicShaper = ReflectionUtil.construct("com.ibm.icu.text.ArabicShaping", shape, classTypes); //$NON-NLS-1$
-                unArabicShaper = ReflectionUtil.construct("com.ibm.icu.text.ArabicShaping", unshape, classTypes); //$NON-NLS-1$
-            }
-            catch (Exception e)
-            {
-                // This is OK. The jar is not on the classpath
-            }
-            if (arabicShaper == null)
-            {
-                numericShaper = NumericShaper.getShaper(NumericShaper.EASTERN_ARABIC);
-            }
-        }
     }
 
     /**
@@ -111,7 +76,8 @@
      */
     public boolean canShape()
     {
-        return arabicShaper != null || numericShaper != null || getNine() != '9';
+        //return arabicShaper != null || numericShaper != null || getNine() != '9';
+        return getNine() != '9';
     }
 
     /**
@@ -127,30 +93,13 @@
             return input;
         }
 
-        if (arabicShaper != null)
-        {
-            Object[] params = { input };
-            try
-            {
-                return (String) ReflectionUtil.invoke(arabicShaper, "shape", params); //$NON-NLS-1$
-            }
-            catch (Exception e)
-            {
-                // do nothing as it is OK for jar to not be present.
-            }
-        }
-
-        if (numericShaper != null)
-        {
-            char[] src = input.toCharArray();
-            numericShaper.shape(src, 0, src.length);
-            return new String(src);
-        }
-
         char[] src = input.toCharArray();
-        if (shape(src, 0, src.length))
+        boolean[] transformed = new boolean[1];
+        transformed[0] = false;
+        char[] dest = shaped(src, transformed);
+        if (transformed[0])
         {
-            return new String(src);
+            return new String(dest);
         }
 
         return input;
@@ -174,82 +123,178 @@
      */
     public String unshape(String input)
     {
-        if (unArabicShaper != null)
-        {
-            Object[] params = { input };
-            try
-            {
-                return (String) ReflectionUtil.invoke(unArabicShaper, "shape", params); //$NON-NLS-1$
-            }
-            catch (Exception e)
-            {
-                // do nothing as it is OK for jar to not be present.
-            }
-        }
-
         char[] src = input.toCharArray();
-        if (unshape(src, 0, src.length))
+        boolean[] transformed = new boolean[1];
+        transformed[0] = false;
+        char[] dest = unshaped(src, transformed);
+        if (transformed[0])
         {
-            return new String(src);
+            return new String(dest);
         }
         
         return input;
     }
 
     /**
-     * Perform shaping from 0-9 into target script.
+     * Perform shaping back to 0-9.
      */
-    private boolean shape(char[] src, int start, int count)
+    private char[] unshaped(char[] src, boolean[] transformed)
     {
-        char nine = getNine();
+        int nine = getNine();
         if (nine == '9')
         {
-            return false;
+            return src;
         }
 
-        return transform(src, start, count, '0', '9', nine - '9');
+        int zero = nine - 9;
+        return transform(src, zero, nine, '9' - nine, transformed);
     }
 
     /**
-     * Perform shaping back to 0-9.
+     * @param src
+     * @param transformed
+     * @return
      */
-    private boolean unshape(char[] src, int start, int count)
+    private char[] shaped(char[] src, boolean[] transformed)
     {
-        int nine = getNine();
+        char nine = getNine();
         if (nine == '9')
         {
-            return false;
+            return src;
         }
 
-        int zero = nine - 9;
-        return transform(src, start, count, zero, nine, '9' - nine);
+        return transform(src, '0', '9', nine - '9', transformed);
     }
 
     /**
-     * Transform in place either to or from 0-9 and the script representation, returning true when at least one character is transformed.
+     * Transform either to or from 0-9 and the script representation, returning the result and true when at least one character is transformed.
      * 
      * @param src the text to transform
-     * @param start the place in the string in which to start
-     * @param count the number of characters to consume
      * @param zero zero in the source representation
      * @param nine nine in the source representation
-     * @param offset the distance between zeros in the source and target representation 
+     * @param offset the distance between zeros in the source and target representation
+     * @param transformed an input parameter of one boolean that can hold whether there was a transformation
      * @return
      */
-    private boolean transform(char[] src, int start, int count, int zero, int nine, int offset)
+    private char[] transform(char[] src, int zero, int nine, int offset, boolean[] transformed)
     {
         char[] text = src;
-        boolean transformed = false;
-        for (int i = start, e = start + count; i < e; ++i)
+        int srcLen = text.length;
+        int destLen = srcLen;
+
+        // offset > 0 when we are going from 0-9
+        if (offset > 0 && srcLen > 3)
         {
+            // count the number of ':' flanked by '0' to '9'
+            // each one of these is going
+            // to be bracketed with RLO and PDF.
+            for (int i = 1; i < srcLen - 1; i++)
+            {
+                char prevChar = text[i - 1];
+                char curChar = text[i];
+                char nextChar = text[i + 1];
+                if (curChar == ':' && prevChar >= '0' && prevChar <= '9' && nextChar >= '0' && nextChar <= '9')
+                {
+                    destLen += 2;
+                }
+            }
+
+            // Did we actually see a ':'
+            if (destLen != srcLen)
+            {
+                transformed[0] = true;
+                int sPos = 0;
+                int dPos = 0;
+                int stop = srcLen - 1; // ensure look-ahead
+                char[] dest = new char[destLen];
+                dest[dPos++] = text[sPos++];
+                while (sPos < stop)
+                {
+                    char prevChar = text[sPos - 1];
+                    char nextChar = text[sPos + 1];
+                    char curChar = text[sPos++];
+                    if (curChar == ':' && prevChar >= '0' && prevChar <= '9' && nextChar >= '0' && nextChar <= '9')
+                    {
+                        dest[dPos++] = '\u202E'; // RLO
+                        dest[dPos++] = curChar;
+                        dest[dPos++] = '\u202C'; // PDF
+                    }
+                    else if (curChar >= zero && curChar <= nine)
+                    {
+                        dest[dPos++] = (char)(curChar + offset);
+                    }
+                    else
+                    {
+                        dest[dPos++] = curChar;
+                    }
+                }
+                // copy the rest
+                while (sPos < srcLen)
+                {
+                    dest[dPos++] = text[sPos++];
+                }
+                return dest;
+            }
+        }
+        // Are we going to '0' - '9' with embedded, specially marked ':'
+        else if (offset < 0 && srcLen > 3)
+        {
+            for (int sPos = 0; sPos < srcLen - 2; sPos++)
+            {
+                if (text[sPos] == '\u202E' && text[sPos + 1] == ':' && text[sPos + 2] == '\u202C')
+                {
+                    destLen -= 2;
+                    sPos += 2;
+                }
+            }
+
+            // Did we actually see a '\u202E:\u202C'
+            if (destLen != srcLen)
+            {
+                transformed[0] = true;
+                char[] dest = new char[destLen];
+                int sPos = 0;
+                int dPos = 0;
+                int stop = srcLen - 2; // ensure look-ahead
+                while (sPos < stop)
+                {
+                    char curChar = text[sPos++];
+                    if (curChar == '\u202E' && text[sPos] == ':' && text[sPos + 1] == '\u202C')
+                    {
+                        dest[dPos++] = ':';
+                        sPos += 2; // skip the whole pattern
+                    }
+                    else if (curChar >= zero && curChar <= nine)
+                    {
+                        dest[dPos++] = (char)(curChar + offset);
+                    }
+                    else
+                    {
+                        dest[dPos++] = curChar;
+                    }
+                }
+
+                // copy the rest
+                while (sPos < srcLen)
+                {
+                    dest[dPos++] = text[sPos++];
+                }
+                
+                return dest;
+            }
+        }
+
+        for (int i = 0, e = src.length; i < e; i++)
+        {
             char c = text[i];
             if (c >= zero && c <= nine)
             {
                 text[i] = (char)(c + offset);
-                transformed = true;
+                transformed[0] = true;
             }
         }
-        return transformed;
+
+        return text;
     }
 
     /**
@@ -262,11 +307,11 @@
         if (nineShape == '\u0000')
         {
             nineShape = '9';
-            if (locale.getLanguage().equals("fa")) //$NON-NLS-1$
+            if ("fa".equals(locale.getLanguage())) //$NON-NLS-1$
             {
                 nineShape = '\u06f9';
             }
-            else if (locale.getLanguage().equals("ar")) //$NON-NLS-1$
+            else if ("ar".equals(locale.getLanguage())) //$NON-NLS-1$
             {
                 nineShape = '\u0669';
             }
@@ -274,34 +319,7 @@
         return nineShape;
     }
 
-    // The following 4 values are replicated here from ArabicShaper.
-    // This is needed for the sake of reflection.
-    // If any of these change in ArabicShaper, they will need to be changed here as well.
     /**
-     * Digit shaping option: Replace European digits (U+0030...U+0039) by Arabic-Indic digits.
-     * @stable ICU 2.0
-     */
-    private static final int ICU_DIGITS_EN2AN = 0x20;
-
-    /**
-     * Digit shaping option: Replace Arabic-Indic digits by European digits (U+0030...U+0039).
-     * @stable ICU 2.0
-     */
-    private static final int ICU_DIGITS_AN2EN = 0x40;
-
-    /** 
-     * Digit type option: Use Arabic-Indic digits (U+0660...U+0669). 
-     * @stable ICU 2.0
-     */
-    private static final int ICU_DIGIT_TYPE_AN = 0;
-
-    /** 
-     * Digit type option: Use Eastern (Extended) Arabic-Indic digits (U+06f0...U+06f9). 
-     * @stable ICU 2.0
-     */
-    private static final int ICU_DIGIT_TYPE_AN_EXTENDED = 0x100;
-
-    /**
      * The locale for this shaper.
      */
     private Locale locale;
@@ -310,14 +328,4 @@
      * Nine for this shaper.
      */
     private char nineShape;
-
-    /**
-     * Convert 0-9 to \u06f0-\u06f9 for Persian, and \u0660-\u0669 for Arabic
-     */
-    private Object arabicShaper;
-    /**
-     * Revert \u06f0-\u06f9 for Persian, and \u0660-\u0669 for Arabic to 0-9
-     */
-    private Object unArabicShaper;
-    private NumericShaper numericShaper;
 }

Modified: trunk/common-swing/src/main/java/org/crosswire/common/swing/Msg_fa.properties
===================================================================
--- trunk/common-swing/src/main/java/org/crosswire/common/swing/Msg_fa.properties	2007-08-06 01:12:14 UTC (rev 1646)
+++ trunk/common-swing/src/main/java/org/crosswire/common/swing/Msg_fa.properties	2007-08-06 01:35:25 UTC (rev 1647)
@@ -7,7 +7,7 @@
 
 BeanPanel.ErrorReading=\u0627\u0634\u062A\u0628\u0627 \u062F\u0631 \u062E\u0648\u0627\u0646\u062F\u0646 \u060C \u0634\u0645\u0627\u0631\u0647  {0}
 EirPanel.Close=\u0628\u062A\u0646
-ExceptionPane.ErrorOccurred=An error has occured:
+ExceptionPane.ErrorOccurred=An error has occurred:
 ExceptionPane.OK=\u0642\u0628\u0648\u0644
 ExceptionPane.Details=\u062C\u0632\u062B\u06CC\u0627\u062A
 ExceptionPane.NoFile=\u067E\u0631\u0648\u0646\u062F\u0647 \u0648\u062C\u0648\u062F \u0646\u062F\u0627\u0631\u062F

Modified: trunk/jsword/src/main/java/org/crosswire/jsword/book/Books.java
===================================================================
--- trunk/jsword/src/main/java/org/crosswire/jsword/book/Books.java	2007-08-06 01:12:14 UTC (rev 1646)
+++ trunk/jsword/src/main/java/org/crosswire/jsword/book/Books.java	2007-08-06 01:35:25 UTC (rev 1647)
@@ -37,7 +37,7 @@
 import org.crosswire.common.util.Reporter;
 
 /**
- * The Bibles class (along with Bible) is the central point of contact
+ * The Books class (along with Book) is the central point of contact
  * between the rest of the world and this set of packages.
  *
  * @see gnu.lgpl.License for license details.
@@ -142,6 +142,47 @@
         return new BookSet(temp);
     }
 
+    /**
+     * Get the maximum string length of a property
+     * @param propertyKey The desired property
+     * @return -1 if there is no match, otherwise the maximum length.
+     */
+    public int getMaxLength(String propertyKey)
+    {
+        int max = -1;
+        List bookList = getBooks();
+        Iterator iter = bookList.iterator();
+        while (iter.hasNext())
+        {
+            Book book = (Book) iter.next();
+            Object property = book.getProperty(propertyKey);
+            String value = property instanceof String ? (String) property : property.toString();
+            max = Math.max(max, value == null ? -1 : value.length());
+        }
+        return max;
+    }
+
+    /**
+     * Get the maximum string length of a property on a subset of books.
+     * @param propertyKey The desired property
+     * @param filter The filter
+     * @return -1 if there is no match, otherwise the maximum length.
+     */
+    public int getMaxLength(String propertyKey, BookFilter filter)
+    {
+        int max = -1;
+        List bookList = getBooks(filter);
+        Iterator iter = bookList.iterator();
+        while (iter.hasNext())
+        {
+            Book book = (Book) iter.next();
+            Object property = book.getProperty(propertyKey);
+            String value = property instanceof String ? (String) property : property.toString();
+            max = Math.max(max, value == null ? -1 : value.length());
+        }
+        return max;
+    }
+
     /* (non-Javadoc)
      * @see org.crosswire.jsword.book.BookList#addBooksListener(org.crosswire.jsword.book.BooksListener)
      */

Modified: trunk/jsword/src/main/java/org/crosswire/jsword/book/install/sword/Msg.properties
===================================================================
--- trunk/jsword/src/main/java/org/crosswire/jsword/book/install/sword/Msg.properties	2007-08-06 01:12:14 UTC (rev 1646)
+++ trunk/jsword/src/main/java/org/crosswire/jsword/book/install/sword/Msg.properties	2007-08-06 01:35:25 UTC (rev 1647)
@@ -9,7 +9,7 @@
 SwordInstaller.ConnectRefused=Failed to connect to remote server: {0}. FTP code={1}, {2}
 SwordInstaller.CWDRefused=Failed to change to remote directory: {0}. FTP code={1}, {2}
 SwordInstaller.DownloadRefused=Failed to download index file: {0}. FTP code={1}, {2}
-SwordInstaller.UnknownError=Unexpected Error occured
+SwordInstaller.UnknownError=Unexpected Error occurred
 SwordInstaller.CacheError=Error loading from cache
 SwordInstaller.InvalidURL=Not enough / symbols in url: {0}
 SwordInstaller.Installed=Book already installed: {0}

Modified: trunk/jsword/src/main/java/org/crosswire/jsword/passage/VerseRangeFactory.java
===================================================================
--- trunk/jsword/src/main/java/org/crosswire/jsword/passage/VerseRangeFactory.java	2007-08-06 01:12:14 UTC (rev 1646)
+++ trunk/jsword/src/main/java/org/crosswire/jsword/passage/VerseRangeFactory.java	2007-08-06 01:35:25 UTC (rev 1647)
@@ -60,12 +60,12 @@
      * range of 5 verses starting at Gen 1:1.
      * <p>This constructor is different from the (String, Verse) constructor in that
      * if the basis is a range that exactly covers a chapter and the string is a
-     * single number, then we assume that the number referrs to a chapter and not to
+     * single number, then we assume that the number refers to a chapter and not to
      * a verse. This allows us to have a Passage like "Gen 1,2" and have the 2
-     * understood as chapter 2 and not verse 2 of Gen 1, which would have occured
+     * understood as chapter 2 and not verse 2 of Gen 1, which would have occurred
      * otherwise.
      * @param original The string describing the verse e.g "2:2"
-     * @param basis The verse that forms the basis by which to understand the orginal.
+     * @param basis The verse that forms the basis by which to understand the original.
      * @exception NoSuchVerseException If the reference is illegal
      */
     public static VerseRange fromString(String original, VerseRange basis) throws NoSuchVerseException

Modified: trunk/jsword-limbo/src/main/java/org/crosswire/jsword/book/install/sword/FTPMsg.properties
===================================================================
--- trunk/jsword-limbo/src/main/java/org/crosswire/jsword/book/install/sword/FTPMsg.properties	2007-08-06 01:12:14 UTC (rev 1646)
+++ trunk/jsword-limbo/src/main/java/org/crosswire/jsword/book/install/sword/FTPMsg.properties	2007-08-06 01:35:25 UTC (rev 1647)
@@ -5,7 +5,7 @@
 # The MessageName should be mixed case, with a leading capital.
 # It should have no spaces or other punctuation (e.g. _, -, ', ...)
 
-SwordInstaller.UnknownError=Unexpected Error occured
+SwordInstaller.UnknownError=Unexpected Error occurred
 SwordInstaller.CacheError=Error loading from cache
 SwordInstaller.InvalidURL=Not enough / symbols in url: {0}
 SwordInstallerFactory.URLAtCount=Too many @ symbols in url: {0}




More information about the jsword-svn mailing list