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