]> gitweb.fperrin.net Git - Dictionary.git/blob - src/com/hughes/android/dictionary/engine/HtmlEntry.java
Fixed text color of normal text.
[Dictionary.git] / src / com / hughes / android / dictionary / engine / HtmlEntry.java
1 package com.hughes.android.dictionary.engine;
2
3 import android.content.Intent;
4 import android.net.Uri;
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.io.UnsupportedEncodingException;
17 import java.lang.ref.SoftReference;
18 import java.net.URLEncoder;
19 import java.util.List;
20 import java.util.regex.Pattern;
21
22 public class HtmlEntry extends AbstractEntry implements RAFSerializable<HtmlEntry>, Comparable<HtmlEntry> {
23   
24   // Title is not HTML escaped.
25   public final String title;
26   public final LazyHtmlLoader lazyHtmlLoader;
27   public String html;
28   
29   public HtmlEntry(final EntrySource entrySource, String title) {
30     super(entrySource);
31     this.title = title;
32     lazyHtmlLoader = null;
33   }
34   
35   public HtmlEntry(Dictionary dictionary, RandomAccessFile raf, final int index) 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   
94   @Override
95   public int compareTo(HtmlEntry another) {
96     if (title.compareTo(another.title) != 0) {
97       return title.compareTo(another.title);
98     }
99     return getHtml().compareTo(another.getHtml());
100   }
101   
102   @Override
103   public String toString() {
104     return getRawText(false);
105   }
106   
107   // --------------------------------------------------------------------
108   
109
110   public static class Row extends RowBase {
111     
112     boolean isExpanded = false;
113     
114     Row(final RandomAccessFile raf, final int thisRowIndex,
115         final Index index) throws IOException {
116       super(raf, thisRowIndex, index);
117     }
118
119     Row(final int referenceIndex, final int thisRowIndex,
120         final Index index) {
121       super(referenceIndex, thisRowIndex, index);
122     }
123     
124     @Override
125     public String toString() {
126       return getRawText(false);
127     }
128
129     public HtmlEntry getEntry() {
130       return index.dict.htmlEntries.get(referenceIndex);
131     }
132     
133     @Override
134     public void print(PrintStream out) {
135       final HtmlEntry entry = getEntry();
136       out.println("See also HtmlEntry:" + entry.title);
137     }
138
139     @Override
140     public String getRawText(boolean compact) {
141       final HtmlEntry entry = getEntry();
142       return entry.getRawText(compact);
143     }
144
145     @Override
146     public RowMatchType matches(final List<String> searchTokens, final Pattern orderedMatchPattern, final Transliterator normalizer, 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.escapeToPureHtmlUnicode(htmlEntry.title);
165             result.append(String.format("<h1><a href=\"%s\">%s</a></h1>\n<p>%s\n", 
166                     formatQuickdicUrl(indexShortName, titleEscaped), 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         try {
176             return String.format("qd:%s:%s", indexShortName, URLEncoder.encode(text, "UTF-8"));
177         } catch (UnsupportedEncodingException e) {
178             throw new RuntimeException(e);
179         }
180     }
181
182     public static boolean isQuickdicUrl(String url) {
183         return url.startsWith("qd:");
184     }
185     
186     public static void quickdicUrlToIntent(final String url, final Intent intent) {
187         int firstColon = url.indexOf(":");
188         if (firstColon == -1) return;
189         int secondColon = url.indexOf(":", firstColon + 1);
190         if (secondColon == -1) return;
191         intent.putExtra(C.SEARCH_TOKEN, Uri.decode(url.substring(secondColon + 1)));
192     }
193     
194     // --------------------------------------------------------------------
195     
196     public static final class LazyHtmlLoader {
197         final RandomAccessFile raf;
198         final long offset;
199         final int numBytes;
200         final int numZipBytes;
201         
202         // Not sure this volatile is right, but oh well.
203         volatile SoftReference<String> htmlRef = new SoftReference<String>(null);
204         
205         private LazyHtmlLoader(final RandomAccessFile raf) throws IOException {
206             this.raf = raf;
207             numBytes = raf.readInt();
208             numZipBytes = raf.readInt();
209             offset = raf.getFilePointer();
210             raf.skipBytes(numZipBytes);
211         }
212         
213         public String getHtml() {
214             String html = htmlRef.get();
215             if (html != null) {
216                 return html;
217             }
218             System.out.println("Loading Html: numBytes=" + numBytes + ", numZipBytes=" + numZipBytes);
219             final byte[] bytes = new byte[numBytes];
220             final byte[] zipBytes = new byte[numZipBytes];
221             synchronized (raf) {
222                 try {
223                     raf.seek(offset);
224                     raf.read(zipBytes);
225                 } catch (IOException e) {
226                     throw new RuntimeException(e);
227                 }
228             }
229             try {
230                 StringUtil.unzipFully(zipBytes, bytes);
231                 html = new String(bytes, "UTF-8");
232             } catch (IOException e) {
233                 throw new RuntimeException(e);
234             }
235             htmlRef = new SoftReference<String>(html);
236             return html;
237         }
238     }
239
240 }