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