]> gitweb.fperrin.net Git - Dictionary.git/commitdiff
go
authorThad Hughes <thad.hughes@gmail.com>
Sun, 21 Nov 2010 02:58:45 +0000 (18:58 -0800)
committerThad Hughes <thad.hughes@gmail.com>
Sun, 21 Nov 2010 02:58:45 +0000 (18:58 -0800)
.classpath
images/icon.odg
images/icon.png
res/drawable/icon.png
src/com/hughes/android/dictionary/DictionaryActivity.java
src/com/hughes/android/dictionary/engine/Index.java
src/com/hughes/android/dictionary/engine/Language.java

index f033a2aba58ce0061634524784b17f98308eac4c..123204872d6a4462b988af6cbf7c9819213200a3 100644 (file)
@@ -3,7 +3,7 @@
        <classpathentry kind="src" path="src"/>
        <classpathentry kind="src" path="gen"/>
        <classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
-       <classpathentry exported="true" kind="lib" path="jars/icu4j-4_2_1-src/icu4j.jar"/>
        <classpathentry combineaccessrules="false" exported="true" kind="src" path="/Util"/>
+       <classpathentry exported="true" kind="lib" path="jars/icu4j-4_4_2-src/out/module/lib/icu4j-module.jar"/>
        <classpathentry kind="output" path="bin"/>
 </classpath>
index f70cbd713e3fad8e4f3177f4f044b2bce984264a..a3d19d6332576897a54d2432cb0d179fb79cceaa 100644 (file)
Binary files a/images/icon.odg and b/images/icon.odg differ
index 99ae67fb4184fb3ddc360e666822add617675cbc..dc1df50d0fcb0c0ad9e82a36cb7679f78740489c 100644 (file)
Binary files a/images/icon.png and b/images/icon.png differ
index 99ae67fb4184fb3ddc360e666822add617675cbc..dc1df50d0fcb0c0ad9e82a36cb7679f78740489c 100644 (file)
Binary files a/res/drawable/icon.png and b/res/drawable/icon.png differ
index afca2b59e7aa84fa69094fe6386ba59d03e9b148..a1521fa2fecae8db0c4d9367576dc1812e97249d 100644 (file)
@@ -139,9 +139,7 @@ public class DictionaryActivity extends ListActivity {
       public void run() {\r
         final long startMillis = System.currentTimeMillis();\r
         for (final Index index : dictionary.indices) {\r
-          index.sortLanguage.getFindCollator();\r
-          final com.ibm.icu.text.Collator c = index.sortLanguage\r
-              .getSortCollator();\r
+          final com.ibm.icu.text.Collator c = index.sortLanguage.getCollator();\r
           if (c.compare("pre-print", "preppy") >= 0) {\r
             Log.e(LOG, c.getClass()\r
                 + " is buggy, lookups may not work properly.");\r
@@ -438,19 +436,19 @@ public class DictionaryActivity extends ListActivity {
       return;\r
     }\r
     \r
-    final Index.SearchResult searchResult = searchOperation.searchResult;\r
+    final Index.IndexEntry searchResult = searchOperation.searchResult;\r
     Log.d(LOG, "searchFinished: " + searchOperation + ", searchResult=" + searchResult);\r
 \r
     jumpToRow(searchResult.longestPrefix.startRow);\r
     \r
-    if (!searchResult.success) {\r
-      if (vibrator != null) {\r
-        vibrator.vibrate(VIBRATE_MILLIS);\r
-      }\r
-      searchText.setText(searchResult.longestPrefixString);\r
-      searchText.setSelection(searchResult.longestPrefixString.length());\r
-      return;\r
-    }\r
+//    if (!searchResult.success) {\r
+//      if (vibrator != null) {\r
+//        vibrator.vibrate(VIBRATE_MILLIS);\r
+//      }\r
+//      searchText.setText(searchResult.longestPrefixString);\r
+//      searchText.setSelection(searchResult.longestPrefixString.length());\r
+//      return;\r
+//    }\r
   }\r
   \r
   private final void jumpToRow(final int row) {\r
@@ -466,7 +464,7 @@ public class DictionaryActivity extends ListActivity {
     \r
     long searchStartMillis;\r
 \r
-    Index.SearchResult searchResult;\r
+    Index.IndexEntry searchResult;\r
     \r
     SearchOperation(final String searchText, final Index index) {\r
       this.searchText = searchText.trim();\r
@@ -480,7 +478,7 @@ public class DictionaryActivity extends ListActivity {
     @Override\r
     public void run() {\r
       searchStartMillis = System.currentTimeMillis();\r
-      searchResult = index.findLongestSubstring(searchText, interrupted);\r
+      searchResult = index.findInsertionPoint(searchText, interrupted);\r
       Log.d(LOG, "searchText=" + searchText + ", searchDuration="\r
           + (System.currentTimeMillis() - searchStartMillis) + ", interrupted="\r
           + interrupted.get());\r
index 2d3d42f98e7b48804a021e69574e2b57a9cca710..7cee7460c8e2f90702aaf98ca66ca8bcbb7171b2 100644 (file)
@@ -17,6 +17,7 @@ import com.hughes.util.raf.RAFSerializable;
 import com.hughes.util.raf.RAFSerializer;
 import com.hughes.util.raf.UniformRAFList;
 import com.ibm.icu.text.Collator;
+import com.ibm.icu.text.Transliterator;
 
 public final class Index implements RAFSerializable<Index> {
   
@@ -29,6 +30,10 @@ public final class Index implements RAFSerializable<Index> {
   
   // persisted: tells how the entries are sorted.
   public final Language sortLanguage;
+  final String normalizerRules;
+  
+  // Built from the two above.
+  final Transliterator normalizer;
     
   // persisted
   public final List<IndexEntry> sortedIndexEntries;
@@ -42,14 +47,17 @@ public final class Index implements RAFSerializable<Index> {
   
   // --------------------------------------------------------------------------
   
-  public Index(final Dictionary dict, final String shortName, final String longName, final Language sortLanguage, final boolean swapPairEntries) {
+  public Index(final Dictionary dict, final String shortName, final String longName, final Language sortLanguage, final String normalizerRules, final boolean swapPairEntries) {
     this.dict = dict;
     this.shortName = shortName;
     this.longName = longName;
     this.sortLanguage = sortLanguage;
+    this.normalizerRules = normalizerRules;
     this.swapPairEntries = swapPairEntries;
     sortedIndexEntries = new ArrayList<IndexEntry>();
     rows = new ArrayList<RowBase>();
+    
+    normalizer = Transliterator.createFromRules("", normalizerRules, Transliterator.FORWARD);
   }
   
   public Index(final Dictionary dict, final RandomAccessFile raf) throws IOException {
@@ -58,12 +66,15 @@ public final class Index implements RAFSerializable<Index> {
     longName = raf.readUTF();
     final String languageCode = raf.readUTF();
     sortLanguage = Language.lookup(languageCode);
+    normalizerRules = raf.readUTF();
     swapPairEntries = raf.readBoolean();
     if (sortLanguage == null) {
       throw new IOException("Unsupported language: " + languageCode);
     }
     sortedIndexEntries = CachingList.create(RAFList.create(raf, IndexEntry.SERIALIZER, raf.getFilePointer()), CACHE_SIZE);
     rows = CachingList.create(UniformRAFList.create(raf, new RowBase.Serializer(this), raf.getFilePointer()), CACHE_SIZE);
+
+    normalizer = Transliterator.createFromRules("", normalizerRules, Transliterator.FORWARD);
   }
   
   @Override
@@ -71,6 +82,7 @@ public final class Index implements RAFSerializable<Index> {
     raf.writeUTF(shortName);
     raf.writeUTF(longName);
     raf.writeUTF(sortLanguage.getSymbol());
+    raf.writeUTF(normalizerRules);
     raf.writeBoolean(swapPairEntries);
     RAFList.write(raf, sortedIndexEntries, IndexEntry.SERIALIZER);
     UniformRAFList.write(raf, (Collection<RowBase>) rows, new RowBase.Serializer(this), 5);
@@ -87,6 +99,8 @@ public final class Index implements RAFSerializable<Index> {
     public final int startRow;
     public final int numRows;
     
+    private String normalizedToken;
+    
     static final RAFSerializer<IndexEntry> SERIALIZER = new RAFSerializer<IndexEntry> () {
       @Override
       public IndexEntry read(RandomAccessFile raf) throws IOException {
@@ -120,15 +134,22 @@ public final class Index implements RAFSerializable<Index> {
     public String toString() {
       return String.format("%s@%d(%d)", token, startRow, numRows);
     }
+
+    public synchronized String normalizedToken(final Transliterator normalizer) {
+      if (normalizedToken == null) {
+        normalizedToken = normalizer.transform(token);
+      }
+      return normalizedToken;
+    }
   }
   
   public IndexEntry findInsertionPoint(String token, final AtomicBoolean interrupted) {
-    token = sortLanguage.textNorm(token, true);
+    token = normalizer.transliterate(token);
 
     int start = 0;
     int end = sortedIndexEntries.size();
     
-    final Collator sortCollator = sortLanguage.getSortCollator();
+    final Collator sortCollator = sortLanguage.getCollator();
     while (start < end) {
       final int mid = (start + end) / 2;
       if (interrupted.get()) {
@@ -136,22 +157,22 @@ public final class Index implements RAFSerializable<Index> {
       }
       final IndexEntry midEntry = sortedIndexEntries.get(mid);
 
-      final int comp = sortCollator.compare(token, sortLanguage.textNorm(midEntry.token, true));
+      final int comp = sortCollator.compare(token, midEntry.normalizedToken(normalizer));
       if (comp == 0) {
-        final int result = windBackCase(token, mid, sortCollator, interrupted);
+        final int result = windBackCase(token, mid, interrupted);
         return sortedIndexEntries.get(result);
       } else if (comp < 0) {
-//        Log.d("THAD", "Upper bound: " + midEntry);
+        System.out.println("Upper bound: " + midEntry + ", norm=" + midEntry.normalizedToken(normalizer) + ", mid=" + mid);
         end = mid;
       } else {
-//        Log.d("THAD", "Lower bound: " + midEntry);
+        System.out.println("Lower bound: " + midEntry + ", norm=" + midEntry.normalizedToken(normalizer) + ", mid=" + mid);
         start = mid + 1;
       }
     }
 
     // If we search for a substring of a string that's in there, return that.
     int result = Math.min(start, sortedIndexEntries.size() - 1);
-    result = windBackCase(sortLanguage.textNorm(sortedIndexEntries.get(result).token, true), result, sortCollator, interrupted);
+    result = windBackCase(sortedIndexEntries.get(result).normalizedToken(normalizer), result, interrupted);
     return sortedIndexEntries.get(result);
   }
   
@@ -175,32 +196,33 @@ public final class Index implements RAFSerializable<Index> {
     }
   }
   
-  public SearchResult findLongestSubstring(String token, final AtomicBoolean interrupted) {
-    if (token.length() == 0) {
-      return new SearchResult(sortedIndexEntries.get(0), sortedIndexEntries.get(0), "", true);
-    }
-    IndexEntry insertionPoint = null;
-    IndexEntry result = null;
-    boolean unmodified = true;
-    while (!interrupted.get() && token.length() > 0) {
-      result = findInsertionPoint(token, interrupted);
-      if (result == null) {
-        return null;
-      }
-      if (unmodified) {
-        insertionPoint = result;
-      }
-      if (sortLanguage.textNorm(result.token, true).startsWith(sortLanguage.textNorm(token, true))) {
-        return new SearchResult(insertionPoint, result, token, unmodified);
-      }
-      unmodified = false;
-      token = token.substring(0, token.length() - 1);      
-    }
-    return new SearchResult(insertionPoint, sortedIndexEntries.get(0), "", false);
-  }
+//  public SearchResult findLongestSubstring(String token, final AtomicBoolean interrupted) {
+//    token = normalizer.transliterate(token);
+//    if (token.length() == 0) {
+//      return new SearchResult(sortedIndexEntries.get(0), sortedIndexEntries.get(0), "", true);
+//    }
+//    IndexEntry insertionPoint = null;
+//    IndexEntry result = null;
+//    boolean unmodified = true;
+//    while (!interrupted.get() && token.length() > 0) {
+//      result = findInsertionPoint(token, interrupted);
+//      if (result == null) {
+//        return null;
+//      }
+//      if (unmodified) {
+//        insertionPoint = result;
+//      }
+//      if (result.normalizedToken(normalizer).startsWith(token)) {
+//        return new SearchResult(insertionPoint, result, token, unmodified);
+//      }
+//      unmodified = false;
+//      token = token.substring(0, token.length() - 1);      
+//    }
+//    return new SearchResult(insertionPoint, sortedIndexEntries.get(0), "", false);
+//  }
   
-  private final int windBackCase(final String token, int result, final Collator sortCollator, final AtomicBoolean interrupted) {
-    while (result > 0 && sortCollator.compare(sortLanguage.textNorm(sortedIndexEntries.get(result - 1).token, true), token) >= 0) {
+  private final int windBackCase(final String token, int result, final AtomicBoolean interrupted) {
+    while (result > 0 && sortedIndexEntries.get(result - 1).normalizedToken(normalizer).equals(token)) {
       --result;
       if (interrupted.get()) {
         return result;
index b4d8558358a86a91ff4513fa2381c5fe6d13727f..42ad7b60c43b758399db8a4e59a95de773ea6578 100755 (executable)
@@ -1,6 +1,5 @@
 package com.hughes.android.dictionary.engine;\r
 \r
-import java.util.Comparator;\r
 import java.util.LinkedHashMap;\r
 import java.util.Locale;\r
 import java.util.Map;\r
@@ -13,36 +12,18 @@ public class Language {
 \r
   final String symbol;\r
   final Locale locale;\r
-\r
-  Collator sortCollator;\r
-  final Comparator<String> sortComparator;\r
-\r
-  private Collator findCollator;\r
-  final Comparator<String> findComparator;\r
+  \r
+  final Collator collator;\r
 \r
   public Language(final Locale locale) {\r
     this.symbol = locale.getLanguage();\r
     this.locale = locale;\r
+    this.collator = Collator.getInstance(locale);\r
+    this.collator.setStrength(Collator.IDENTICAL);\r
 \r
-    this.sortComparator = new Comparator<String>() {\r
-      public int compare(final String s1, final String s2) {\r
-        return getSortCollator().compare(textNorm(s1, false), textNorm(s2, false));\r
-      }\r
-    };\r
-\r
-    this.findComparator = new Comparator<String>() {\r
-      public int compare(final String s1, final String s2) {\r
-        return getFindCollator().compare(textNorm(s1, false), textNorm(s2, false));\r
-      }\r
-    };\r
-    \r
     symbolToLangauge.put(symbol.toLowerCase(), this);\r
   }\r
 \r
-  public String textNorm(final String s, final boolean toLower) {\r
-    return toLower ? s.toLowerCase() : s;\r
-  }\r
-\r
   @Override\r
   public String toString() {\r
     return locale.toString();\r
@@ -52,24 +33,13 @@ public class Language {
     return symbol;\r
   }\r
   \r
-  public synchronized Collator getFindCollator() {\r
-    if (findCollator == null) {\r
-      findCollator = Collator.getInstance(locale);\r
-      findCollator.setDecomposition(Collator.CANONICAL_DECOMPOSITION);\r
-      findCollator.setStrength(Collator.SECONDARY);\r
-    }\r
-    return findCollator;\r
+  public Collator getCollator() {\r
+    return collator;\r
   }\r
-\r
-  public synchronized Collator getSortCollator() {\r
-    if (sortCollator == null) {\r
-      sortCollator = Collator.getInstance(locale);\r
-      sortCollator.setDecomposition(Collator.CANONICAL_DECOMPOSITION);\r
-      sortCollator.setStrength(Collator.IDENTICAL);\r
-    }\r
-    return sortCollator;\r
+  \r
+  public String getDefaultNormalizerRules() {\r
+    return ":: Any-Latin; :: Lower; :: NFD; :: [:Nonspacing Mark:] Remove; :: NFC ;";\r
   }\r
-\r
   // ----------------------------------------------------------------\r
 \r
   public static final Language en = new Language(Locale.ENGLISH);\r
@@ -78,37 +48,8 @@ public class Language {
 \r
   public static final Language de = new Language(Locale.GERMAN) {\r
     @Override\r
-    public String textNorm(String token, final boolean toLower) {\r
-      if (toLower) {\r
-        token = token.toLowerCase();\r
-      }\r
-      boolean sub = false;\r
-      // This is meant to be fast: occurrences of ae, oe, ue are probably rare.\r
-      for (int ePos = token.indexOf('e', 1); ePos != -1; ePos = token.indexOf(\r
-          'e', ePos + 1)) {\r
-        final char pre = Character.toLowerCase(token.charAt(ePos - 1));\r
-        if (pre == 'a' || pre == 'o' || pre == 'u') {\r
-          sub = true;\r
-          break;\r
-        }\r
-      }\r
-      if (!sub) {\r
-        return token;\r
-      }\r
-      \r
-      token = token.replaceAll("ae", "ä");\r
-      token = token.replaceAll("oe", "ö");\r
-      token = token.replaceAll("ue", "ü");\r
-\r
-      token = token.replaceAll("Ae", "Ä");\r
-      token = token.replaceAll("Oe", "Ö");\r
-      token = token.replaceAll("Ue", "Ü");\r
-\r
-      token = token.replaceAll("AE", "Ä");\r
-      token = token.replaceAll("OE", "Ö");\r
-      token = token.replaceAll("UE", "Ü");\r
-      \r
-      return token;   \r
+    public String getDefaultNormalizerRules() {\r
+      return ":: Lower; 'ae' > 'ä'; 'oe' > 'ö'; 'ue' > 'ü'; 'ß' > 'ss'; ";\r
     }\r
   };\r
   \r