]> gitweb.fperrin.net Git - Dictionary.git/blob - src/com/hughes/android/dictionary/engine/HtmlEntry.java
Optimize imports, update dictionary info.
[Dictionary.git] / src / com / hughes / android / dictionary / engine / HtmlEntry.java
1 package com.hughes.android.dictionary.engine;
2
3 import android.content.Intent;
4
5 import com.hughes.android.dictionary.C;
6 import com.hughes.util.StringUtil;
7 import com.hughes.util.raf.RAFListSerializer;
8 import com.hughes.util.raf.RAFSerializable;
9 import com.ibm.icu.text.Transliterator;
10
11 import java.io.IOException;
12 import java.io.PrintStream;
13 import java.io.RandomAccessFile;
14 import java.lang.ref.SoftReference;
15 import java.util.List;
16 import java.util.regex.Pattern;
17
18 public class HtmlEntry extends AbstractEntry implements RAFSerializable<HtmlEntry>, Comparable<HtmlEntry> {
19   
20   // Title is not HTML escaped.
21   public final String title;
22   public final LazyHtmlLoader lazyHtmlLoader;
23   public String html;
24   
25   public HtmlEntry(final EntrySource entrySource, String title) {
26     super(entrySource);
27     this.title = title;
28     lazyHtmlLoader = null;
29   }
30   
31   public HtmlEntry(Dictionary dictionary, RandomAccessFile raf, final int index) 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   
90   @Override
91   public int compareTo(HtmlEntry another) {
92     if (title.compareTo(another.title) != 0) {
93       return title.compareTo(another.title);
94     }
95     return getHtml().compareTo(another.getHtml());
96   }
97   
98   @Override
99   public String toString() {
100     return getRawText(false);
101   }
102   
103   // --------------------------------------------------------------------
104   
105
106   public static class Row extends RowBase {
107     
108     boolean isExpanded = false;
109     
110     Row(final RandomAccessFile raf, final int thisRowIndex,
111         final Index index) throws IOException {
112       super(raf, thisRowIndex, index);
113     }
114
115     Row(final int referenceIndex, final int thisRowIndex,
116         final Index index) {
117       super(referenceIndex, thisRowIndex, index);
118     }
119     
120     @Override
121     public String toString() {
122       return getRawText(false);
123     }
124
125     public HtmlEntry getEntry() {
126       return index.dict.htmlEntries.get(referenceIndex);
127     }
128     
129     @Override
130     public void print(PrintStream out) {
131       final HtmlEntry entry = getEntry();
132       out.println("See also HtmlEntry:" + entry.title);
133     }
134
135     @Override
136     public String getRawText(boolean compact) {
137       final HtmlEntry entry = getEntry();
138       return entry.getRawText(compact);
139     }
140
141     @Override
142     public RowMatchType matches(final List<String> searchTokens, final Pattern orderedMatchPattern, final Transliterator normalizer, 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, titleEscaped), 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     public static void quickdicUrlToIntent(final String url, final Intent intent) {
179         int firstColon = url.indexOf("?");
180         if (firstColon == -1) return;
181         int secondColon = url.indexOf("&", firstColon + 1);
182         if (secondColon == -1) return;
183         intent.putExtra(C.SEARCH_TOKEN, StringUtil.decodeFromUrl(url.substring(secondColon + 1)));
184     }
185     
186     // --------------------------------------------------------------------
187     
188     public static final class LazyHtmlLoader {
189         final RandomAccessFile raf;
190         final long offset;
191         final int numBytes;
192         final int numZipBytes;
193         
194         // Not sure this volatile is right, but oh well.
195         volatile SoftReference<String> htmlRef = new SoftReference<String>(null);
196         
197         private LazyHtmlLoader(final RandomAccessFile raf) throws IOException {
198             this.raf = raf;
199             numBytes = raf.readInt();
200             numZipBytes = raf.readInt();
201             offset = raf.getFilePointer();
202             raf.skipBytes(numZipBytes);
203         }
204         
205         public String getHtml() {
206             String html = htmlRef.get();
207             if (html != null) {
208                 return html;
209             }
210             System.out.println("Loading Html: numBytes=" + numBytes + ", numZipBytes=" + numZipBytes);
211             final byte[] bytes = new byte[numBytes];
212             final byte[] zipBytes = new byte[numZipBytes];
213             synchronized (raf) {
214                 try {
215                     raf.seek(offset);
216                     raf.read(zipBytes);
217                 } catch (IOException e) {
218                     throw new RuntimeException(e);
219                 }
220             }
221             try {
222                 StringUtil.unzipFully(zipBytes, bytes);
223                 html = new String(bytes, "UTF-8");
224             } catch (IOException e) {
225                 throw new RuntimeException(e);
226             }
227             htmlRef = new SoftReference<String>(html);
228             return html;
229         }
230     }
231
232 }