]> gitweb.fperrin.net Git - Dictionary.git/blob - src/com/hughes/android/dictionary/engine/HtmlEntry.java
Auto-format everything.
[Dictionary.git] / src / com / hughes / android / dictionary / engine / HtmlEntry.java
1
2 package com.hughes.android.dictionary.engine;
3
4 import android.content.Intent;
5 import android.util.Log;
6
7 import com.hughes.android.dictionary.C;
8 import com.hughes.util.StringUtil;
9 import com.hughes.util.raf.RAFListSerializer;
10 import com.hughes.util.raf.RAFSerializable;
11 import com.ibm.icu.text.Transliterator;
12
13 import java.io.IOException;
14 import java.io.PrintStream;
15 import java.io.RandomAccessFile;
16 import java.lang.ref.SoftReference;
17 import java.util.List;
18 import java.util.regex.Pattern;
19
20 public class HtmlEntry extends AbstractEntry implements RAFSerializable<HtmlEntry>,
21         Comparable<HtmlEntry> {
22
23     // Title is not HTML escaped.
24     public final String title;
25     public final LazyHtmlLoader lazyHtmlLoader;
26     public String html;
27
28     public HtmlEntry(final EntrySource entrySource, String title) {
29         super(entrySource);
30         this.title = title;
31         lazyHtmlLoader = null;
32     }
33
34     public HtmlEntry(Dictionary dictionary, RandomAccessFile raf, final int index)
35             throws IOException {
36         super(dictionary, raf, index);
37         title = raf.readUTF();
38         lazyHtmlLoader = new LazyHtmlLoader(raf);
39         html = null;
40     }
41
42     @Override
43     public void write(RandomAccessFile raf) throws IOException {
44         super.write(raf);
45         raf.writeUTF(title);
46
47         final byte[] bytes = getHtml().getBytes("UTF-8");
48         final byte[] zipBytes = StringUtil.zipBytes(bytes);
49         raf.writeInt(bytes.length);
50         raf.writeInt(zipBytes.length);
51         raf.write(zipBytes);
52     }
53
54     String getHtml() {
55         return html != null ? html : lazyHtmlLoader.getHtml();
56     }
57
58     @Override
59     public void addToDictionary(Dictionary dictionary) {
60         assert index == -1;
61         dictionary.htmlEntries.add(this);
62         index = dictionary.htmlEntries.size() - 1;
63     }
64
65     @Override
66     public RowBase CreateRow(int rowIndex, Index dictionaryIndex) {
67         return new Row(this.index, rowIndex, dictionaryIndex);
68     }
69
70     static final class Serializer implements RAFListSerializer<HtmlEntry> {
71
72         final Dictionary dictionary;
73
74         Serializer(Dictionary dictionary) {
75             this.dictionary = dictionary;
76         }
77
78         @Override
79         public HtmlEntry read(RandomAccessFile raf, final int index) throws IOException {
80             return new HtmlEntry(dictionary, raf, index);
81         }
82
83         @Override
84         public void write(RandomAccessFile raf, HtmlEntry t) throws IOException {
85             t.write(raf);
86         }
87     };
88
89     public String getRawText(final boolean compact) {
90         return title + ":\n" + getHtml();
91     }
92
93     @Override
94     public int compareTo(HtmlEntry another) {
95         if (title.compareTo(another.title) != 0) {
96             return title.compareTo(another.title);
97         }
98         return getHtml().compareTo(another.getHtml());
99     }
100
101     @Override
102     public String toString() {
103         return getRawText(false);
104     }
105
106     // --------------------------------------------------------------------
107
108     public static class Row extends RowBase {
109
110         boolean isExpanded = false;
111
112         Row(final RandomAccessFile raf, final int thisRowIndex,
113                 final Index index) throws IOException {
114             super(raf, thisRowIndex, index);
115         }
116
117         Row(final int referenceIndex, final int thisRowIndex,
118                 final Index index) {
119             super(referenceIndex, thisRowIndex, index);
120         }
121
122         @Override
123         public String toString() {
124             return getRawText(false);
125         }
126
127         public HtmlEntry getEntry() {
128             return index.dict.htmlEntries.get(referenceIndex);
129         }
130
131         @Override
132         public void print(PrintStream out) {
133             final HtmlEntry entry = getEntry();
134             out.println("See also HtmlEntry:" + entry.title);
135         }
136
137         @Override
138         public String getRawText(boolean compact) {
139             final HtmlEntry entry = getEntry();
140             return entry.getRawText(compact);
141         }
142
143         @Override
144         public RowMatchType matches(final List<String> searchTokens,
145                 final Pattern orderedMatchPattern, final Transliterator normalizer,
146                 final boolean swapPairEntries) {
147             final String text = normalizer.transform(getRawText(false));
148             if (orderedMatchPattern.matcher(text).find()) {
149                 return RowMatchType.ORDERED_MATCH;
150             }
151             for (int i = searchTokens.size() - 1; i >= 0; --i) {
152                 final String searchToken = searchTokens.get(i);
153                 if (!text.contains(searchToken)) {
154                     return RowMatchType.NO_MATCH;
155                 }
156             }
157             return RowMatchType.BAG_OF_WORDS_MATCH;
158         }
159     }
160
161     public static String htmlBody(final List<HtmlEntry> htmlEntries, final String indexShortName) {
162         final StringBuilder result = new StringBuilder();
163         for (final HtmlEntry htmlEntry : htmlEntries) {
164             final String titleEscaped = StringUtil.escapeUnicodeToPureHtml(htmlEntry.title);
165             result.append(String.format("<h1><a href=\"%s\">%s</a></h1>\n<p>%s\n",
166                     formatQuickdicUrl(indexShortName, htmlEntry.title), titleEscaped,
167                     htmlEntry.getHtml()));
168         }
169         return result.toString();
170     }
171
172     public static String formatQuickdicUrl(final String indexShortName, final String text) {
173         assert !indexShortName.contains(":");
174         assert text.length() > 0;
175         return String.format("q://d?%s&%s", indexShortName, StringUtil.encodeForUrl(text));
176     }
177
178     public static boolean isQuickdicUrl(String url) {
179         return url.startsWith("q://d?");
180     }
181
182     public static void quickdicUrlToIntent(final String url, final Intent intent) {
183         int firstColon = url.indexOf("?");
184         if (firstColon == -1)
185             return;
186         int secondColon = url.indexOf("&", firstColon + 1);
187         if (secondColon == -1)
188             return;
189         intent.putExtra(C.SEARCH_TOKEN, StringUtil.decodeFromUrl(url.substring(secondColon + 1)));
190     }
191
192     // --------------------------------------------------------------------
193
194     public static final class LazyHtmlLoader {
195         final RandomAccessFile raf;
196         final long offset;
197         final int numBytes;
198         final int numZipBytes;
199
200         // Not sure this volatile is right, but oh well.
201         volatile SoftReference<String> htmlRef = new SoftReference<String>(null);
202
203         private LazyHtmlLoader(final RandomAccessFile raf) throws IOException {
204             this.raf = raf;
205             numBytes = raf.readInt();
206             numZipBytes = raf.readInt();
207             offset = raf.getFilePointer();
208             raf.skipBytes(numZipBytes);
209         }
210
211         public String getHtml() {
212             String html = htmlRef.get();
213             if (html != null) {
214                 return html;
215             }
216             System.out.println("Loading Html: numBytes=" + numBytes + ", numZipBytes="
217                     + numZipBytes);
218             final byte[] bytes = new byte[numBytes];
219             final byte[] zipBytes = new byte[numZipBytes];
220             synchronized (raf) {
221                 try {
222                     raf.seek(offset);
223                     raf.read(zipBytes);
224                 } catch (IOException e) {
225                     throw new RuntimeException(e);
226                 }
227             }
228             try {
229                 StringUtil.unzipFully(zipBytes, bytes);
230                 html = new String(bytes, "UTF-8");
231             } catch (IOException e) {
232                 throw new RuntimeException(e);
233             }
234             htmlRef = new SoftReference<String>(html);
235             return html;
236         }
237     }
238
239 }