]> gitweb.fperrin.net Git - Dictionary.git/blob - src/com/hughes/android/dictionary/Dictionary.java
go
[Dictionary.git] / src / com / hughes / android / dictionary / Dictionary.java
1 package com.hughes.android.dictionary;\r
2 \r
3 import java.io.IOException;\r
4 import java.io.RandomAccessFile;\r
5 import java.util.ArrayList;\r
6 import java.util.Comparator;\r
7 import java.util.List;\r
8 import java.util.concurrent.atomic.AtomicBoolean;\r
9 \r
10 import com.hughes.util.CachingList;\r
11 import com.hughes.util.raf.FileList;\r
12 import com.hughes.util.raf.RAFFactory;\r
13 import com.hughes.util.raf.RAFSerializable;\r
14 import com.hughes.util.raf.RAFSerializableSerializer;\r
15 import com.hughes.util.raf.RAFSerializer;\r
16 import com.hughes.util.raf.UniformFileList;\r
17 \r
18 public final class Dictionary implements RAFSerializable<Dictionary> {\r
19 \r
20   static final RAFSerializer<Entry> ENTRY_SERIALIZER = new RAFSerializableSerializer<Entry>(\r
21       Entry.RAF_FACTORY);\r
22   static final RAFSerializer<Row> ROW_SERIALIZER = new RAFSerializableSerializer<Row>(\r
23       Row.RAF_FACTORY);\r
24   static final RAFSerializer<IndexEntry> INDEX_ENTRY_SERIALIZER = new RAFSerializableSerializer<IndexEntry>(\r
25       IndexEntry.RAF_FACTORY);\r
26 \r
27   final List<Entry> entries;\r
28   final Language[] languages = new Language[2];\r
29 \r
30   public Dictionary(final String lang0, final String lang1) {\r
31     languages[0] = new Language(lang0, Entry.LANG1);\r
32     languages[1] = new Language(lang1, Entry.LANG2);\r
33     entries = new ArrayList<Entry>();\r
34   }\r
35 \r
36   public Dictionary(final RandomAccessFile raf) throws IOException {\r
37     entries = CachingList.create(FileList.create(raf, ENTRY_SERIALIZER, raf\r
38         .getFilePointer()), 10000);\r
39     languages[0] = new Language(raf, Entry.LANG1);\r
40     languages[1] = new Language(raf, Entry.LANG2);\r
41   }\r
42 \r
43   public void write(RandomAccessFile raf) throws IOException {\r
44     FileList.write(raf, entries, ENTRY_SERIALIZER);\r
45     languages[0].write(raf);\r
46     languages[1].write(raf);\r
47   }\r
48 \r
49   final class Language implements RAFSerializable<Language> {\r
50     final byte lang;\r
51     final String symbol;\r
52     final List<Row> rows;\r
53     final List<IndexEntry> sortedIndex;\r
54     final Comparator<String> comparator = EntryFactory.entryFactory\r
55         .getEntryComparator();\r
56 \r
57     Language(final String symbol, final byte lang) {\r
58       this.lang = lang;\r
59       this.symbol = symbol;\r
60       rows = new ArrayList<Row>();\r
61       sortedIndex = new ArrayList<IndexEntry>();\r
62     }\r
63 \r
64     Language(final RandomAccessFile raf, final byte lang) throws IOException {\r
65       this.lang = lang;\r
66       symbol = raf.readUTF();\r
67       rows = CachingList.create(UniformFileList.create(raf, ROW_SERIALIZER, raf\r
68           .getFilePointer()), 10000);\r
69       sortedIndex = CachingList.create(FileList.create(raf,\r
70           INDEX_ENTRY_SERIALIZER, raf.getFilePointer()), 10000);\r
71     }\r
72 \r
73     public void write(final RandomAccessFile raf) throws IOException {\r
74       raf.writeUTF(symbol);\r
75       UniformFileList.write(raf, rows, ROW_SERIALIZER, 4);\r
76       FileList.write(raf, sortedIndex, INDEX_ENTRY_SERIALIZER);\r
77     }\r
78 \r
79     String rowToString(final Row row) {\r
80       return row.isToken() ? sortedIndex.get(row.getIndex()).word : entries\r
81           .get(row.getIndex()).toString();\r
82     }\r
83 \r
84     int lookup(String word, final AtomicBoolean interrupted) {\r
85       word = word.toLowerCase();\r
86 \r
87       int start = 0;\r
88       int end = sortedIndex.size();\r
89       while (start < end) {\r
90         final int mid = (start + end) / 2;\r
91         if (interrupted.get()) {\r
92           return mid;\r
93         }\r
94         final IndexEntry midEntry = sortedIndex.get(mid);\r
95 \r
96         final int comp = comparator.compare(word, midEntry.word.toLowerCase());\r
97         if (comp == 0) {\r
98           int result = mid;\r
99           while (result > 0 && comparator.compare(word, sortedIndex.get(result - 1).word.toLowerCase()) == 0) {\r
100             --result;\r
101             if (interrupted.get()) {\r
102               return result;\r
103             }\r
104           }\r
105           return result;\r
106         } else if (comp < 0) {\r
107           end = mid;\r
108         } else {\r
109           start = mid + 1;\r
110         }\r
111       }\r
112       return start;\r
113     }\r
114   }\r
115 \r
116   public static final class Row implements RAFSerializable<Row> {\r
117     final int index;\r
118 \r
119     public Row(final int index) {\r
120       this.index = index;\r
121     }\r
122 \r
123     static final RAFFactory<Row> RAF_FACTORY = new RAFFactory<Row>() {\r
124       public Row create(RandomAccessFile raf) throws IOException {\r
125         return new Row(raf.readInt());\r
126       }\r
127     };\r
128 \r
129     public void write(RandomAccessFile raf) throws IOException {\r
130       raf.writeInt(index);\r
131     }\r
132 \r
133     boolean isToken() {\r
134       return index < 0;\r
135     }\r
136 \r
137     public int getIndex() {\r
138       if (index >= 0) {\r
139         return index;\r
140       }\r
141       return -index - 1;\r
142     }\r
143   }\r
144 \r
145   public static final class IndexEntry implements RAFSerializable<IndexEntry> {\r
146     final String word;\r
147     final int startRow;\r
148 \r
149     public IndexEntry(final String word, final int startRow) {\r
150       this.word = word;\r
151       this.startRow = startRow;\r
152     }\r
153 \r
154     static final RAFFactory<IndexEntry> RAF_FACTORY = new RAFFactory<IndexEntry>() {\r
155       public IndexEntry create(RandomAccessFile raf) throws IOException {\r
156         final String word = raf.readUTF();\r
157         final int startRow = raf.readInt();\r
158         return new IndexEntry(word, startRow);\r
159       }\r
160     };\r
161 \r
162     public void write(final RandomAccessFile raf) throws IOException {\r
163       raf.writeUTF(word);\r
164       raf.writeInt(startRow);\r
165     }\r
166 \r
167     @Override\r
168     public String toString() {\r
169       return word + "@" + startRow;\r
170     }\r
171 \r
172   }\r
173 \r
174 }\r