]> gitweb.fperrin.net Git - DictionaryPC.git/blob - src/com/hughes/android/dictionary/parser/WikiWord.java.old
Apache license.
[DictionaryPC.git] / src / com / hughes / android / dictionary / parser / WikiWord.java.old
1 // Copyright 2011 Google Inc. All Rights Reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 package com.hughes.android.dictionary.parser;
16
17 import java.util.ArrayList;
18 import java.util.LinkedHashMap;
19 import java.util.LinkedHashSet;
20 import java.util.List;
21 import java.util.Map;
22 import java.util.Set;
23 import java.util.regex.Pattern;
24
25 import com.hughes.android.dictionary.engine.DictionaryBuilder;
26 import com.hughes.android.dictionary.engine.IndexedEntry;
27 import com.hughes.android.dictionary.engine.EntryTypeName;
28 import com.hughes.android.dictionary.engine.IndexBuilder;
29 import com.hughes.android.dictionary.engine.PairEntry;
30 import com.hughes.android.dictionary.engine.PairEntry.Pair;
31 import com.hughes.util.ListUtil;
32
33 public class WikiWord {
34   final int depth;
35   
36   final String title;
37   String language;
38
39   int index;
40   
41   final Map<String, StringBuilder> accentToPronunciation = new LinkedHashMap<String, StringBuilder>();
42   StringBuilder currentPronunciation = null;
43
44   final List<PartOfSpeech> partsOfSpeech = new ArrayList<WikiWord.PartOfSpeech>();
45   
46   public WikiWord(final String title, int depth) {
47     this.title = title.intern();
48     this.depth = depth;
49   }
50
51   static class PartOfSpeech {
52     final int depth;
53     final String name;
54
55     final List<Meaning> meanings = new ArrayList<WikiWord.Meaning>();
56     
57     final List<TranslationSense> translationSenses = new ArrayList<WikiWord.TranslationSense>();
58     
59     final List<FormOf> formOfs = new ArrayList<WikiWord.FormOf>();
60     
61     public PartOfSpeech(final int depth, String name) {
62       this.depth = depth;
63       this.name = name.intern();
64     }
65
66     public Meaning newMeaning() {
67       final Meaning meaning = new Meaning();
68       meanings.add(meaning);
69       return meaning;
70     }
71
72     public Meaning lastMeaning() {
73       return meanings.isEmpty() ? newMeaning() : ListUtil.getLast(meanings);
74     }
75   }
76   
77   static class TranslationSense {
78     String sense;
79     List<List<Translation>> translations = new ArrayList<List<Translation>>();
80     {
81       translations.add(new ArrayList<Translation>());
82       translations.add(new ArrayList<Translation>());
83     }
84   }
85   
86   static class Translation {
87     String language;
88     String text;
89     
90     public Translation(final String language, final String text) {
91       this.language = language;
92       this.text = text;
93     }
94
95     @Override
96     public String toString() {
97       return language + ": " + text;
98     }
99   }
100   
101   static class FormOf {
102     final String grammarForm;
103     final String target;
104     
105     public FormOf(final String grammarForm, final String token) {
106       this.grammarForm = grammarForm;
107       this.target = token;
108     }
109   }
110   
111   static class Meaning {
112     String meaning;
113     final List<Example> examples = new ArrayList<WikiWord.Example>();
114     
115     public Example newExample() {
116       final Example example = new Example();
117       this.examples.add(example);
118       return example;
119     }
120
121     public Example lastExample() {
122       return examples.isEmpty() ? newExample() : ListUtil.getLast(examples);
123     }
124   }
125   
126   static class Example {
127     String source;
128     final StringBuilder example = new StringBuilder();
129     final StringBuilder exampleInEnglish = new StringBuilder();
130   }
131   
132   // -------------------------------------------------------------------------
133   
134   void wikiWordToQuickDic(final DictionaryBuilder dictBuilder, final int enIndexBuilder) {
135     //System.out.println("\n" + title + ", " + language + ", pron=" + accentToPronunciation);
136      if (partsOfSpeech.isEmpty() && title.indexOf(":") == -1 && !language.equals("Translingual")) {
137        System.err.println("Word with no POS: " + title);
138      }
139      for (final WikiWord.PartOfSpeech partOfSpeech : partsOfSpeech) {
140        partOfSpeechToQuickDic(dictBuilder, enIndexBuilder, partOfSpeech);
141      }  // PartOfSpeech
142
143      // Pronunciation.
144      if (index != -1) {
145        final PairEntry pronEntry = new PairEntry();
146        for (final Map.Entry<String, StringBuilder> accentToPron : accentToPronunciation.entrySet()) {
147          String accent = accentToPron.getKey();
148          if (accent.length() > 0) {
149            accent = accent + ": ";
150          }         
151          pronEntry.pairs.add(new Pair(accent + accentToPron.getValue(), "", index != 0));
152        }
153        if (pronEntry.pairs.size() > 0) {
154          final IndexedEntry entryData = new IndexedEntry(dictBuilder.dictionary.pairEntries.size(), pronEntry);
155          dictBuilder.dictionary.pairEntries.add(pronEntry);
156          final Set<String> tokens = DictFileParser.tokenize(title, DictFileParser.NON_CHAR);
157          dictBuilder.indexBuilders.get(index).addEntryWithTokens(entryData, tokens, EntryTypeName.WIKTIONARY_PRONUNCIATION);
158        }
159      }
160   }
161
162
163   static final Pattern templateName = Pattern.compile("\\{[^,]*,");
164   private void partOfSpeechToQuickDic(final DictionaryBuilder dictBuilder,
165       final int enIndexBuilder, final WikiWord.PartOfSpeech partOfSpeech) {
166     //System.out.println("  pos: " + partOfSpeech.name);
167          
168      for (final WikiWord.Meaning meaning : partOfSpeech.meanings) {
169        //System.out.println("    meaning: " + meaning.meaning);
170        for (final WikiWord.Example example : meaning.examples) {
171          if (example.example.length() > 0) {
172            //System.out.println("      example: " + example.example);
173          }
174          if (example.exampleInEnglish.length() > 0) {
175            //System.out.println("      exampleInEnglish: " + example.exampleInEnglish);
176          }
177        }
178      }
179      
180      if (index != -1) {
181        final boolean formOfSwap = index != 0;
182        for (final FormOf formOf : partOfSpeech.formOfs) {
183          final Pair pair = new Pair(title + ": " + formOf.grammarForm + ": " + formOf.target, "", formOfSwap);
184          final PairEntry pairEntry = new PairEntry();
185          pairEntry.pairs.add(pair);
186          final IndexedEntry entryData = new IndexedEntry(dictBuilder.dictionary.pairEntries.size(), pairEntry);
187          dictBuilder.dictionary.pairEntries.add(pairEntry);
188   
189          // File under title token.
190          final Set<String> tokens = DictFileParser.tokenize(formOf.target, DictFileParser.NON_CHAR);
191          dictBuilder.indexBuilders.get(index).addEntryWithTokens(entryData, tokens, EntryTypeName.WIKTIONARY_FORM_OF);
192        }
193      }
194
195      
196      if (enIndexBuilder != -1 && index != -1 && enIndexBuilder != index) {
197        final String entryBase = title + " (" + partOfSpeech.name.toLowerCase() + ")";
198        final boolean swap = enIndexBuilder == 1;
199      
200        // Meanings.
201        for (final Meaning meaning : partOfSpeech.meanings) {
202          final PairEntry pairEntry = new PairEntry();
203          final List<Pair> pairs = pairEntry.pairs;
204
205          final List<Set<String>> exampleTokens = new ArrayList<Set<String>>();
206          exampleTokens.add(new LinkedHashSet<String>());
207          exampleTokens.add(new LinkedHashSet<String>());
208          
209          if (meaning.meaning != null && meaning.meaning.length() > 0) {
210            final Pair meaningPair = new Pair(meaning.meaning, entryBase, swap);
211            pairs.add(meaningPair);
212          } else {
213            System.err.println("Empty meaning: " + title + ", " + language + ", " + partOfSpeech.name);
214          }
215            
216          // Examples
217          for (final Example example : meaning.examples) {
218            final int dashIndex = example.example.indexOf("—");
219            if (example.exampleInEnglish.length() == 0 && dashIndex != -1) {
220              System.out.println("Splitting example: title=" + title + ", "+ example.example);
221              example.exampleInEnglish.append(example.example.substring(dashIndex + 1).trim());
222              example.example.delete(dashIndex, example.example.length());
223            }
224            
225            if (example.example.length() > 0 && example.exampleInEnglish.length() > 0) {
226              final Pair pair = new Pair(example.exampleInEnglish.toString(), example.example.toString(), swap);
227              pairs.add(pair);
228              
229              for (int i = 0; i < 2; ++i) {
230                exampleTokens.get(i).addAll(DictFileParser.tokenize(pair.get(i), DictFileParser.NON_CHAR));
231              }
232            }
233          }
234
235          // Create EntryData with the PairEntry.
236          final IndexedEntry entryData = new IndexedEntry(dictBuilder.dictionary.pairEntries.size(), pairEntry);
237          dictBuilder.dictionary.pairEntries.add(pairEntry);
238
239          // File under title token.
240          final Set<String> titleTokens = DictFileParser.tokenize(title, DictFileParser.NON_CHAR);
241          dictBuilder.indexBuilders.get(index).addEntryWithTokens(entryData, titleTokens, titleTokens.size() == 1 ? EntryTypeName.WIKTIONARY_TITLE_ONE_WORD : EntryTypeName.WIKTIONARY_TITLE_MULTI_WORD);
242        
243          // File under the meaning tokens (English):
244          if (meaning.meaning != null) {
245            // If the meaning contains any templates, strip out the template name
246            // so we don't index it.
247            final String meaningToIndex = templateName.matcher(meaning.meaning).replaceAll("");
248            final Set<String> meaningTokens = DictFileParser.tokenize(meaningToIndex, DictFileParser.NON_CHAR);
249            dictBuilder.indexBuilders.get(enIndexBuilder).addEntryWithTokens(entryData, meaningTokens, meaningTokens.size() == 1 ? EntryTypeName.WIKTIONARY_MEANING_ONE_WORD : EntryTypeName.WIKTIONARY_MEANING_MULTI_WORD);
250          }
251          
252          // File under other tokens that we saw.
253          for (int i = 0; i < 2; ++i) {
254            dictBuilder.indexBuilders.get(i).addEntryWithTokens(entryData, exampleTokens.get(i), EntryTypeName.WIKTIONARY_EXAMPLE_OTHER_WORDS);
255          }         
256        
257          
258        }  // Meanings.
259        
260      }
261      
262      translationSensesToQuickDic(dictBuilder, enIndexBuilder, partOfSpeech);
263   }
264
265
266   private void translationSensesToQuickDic(final DictionaryBuilder dictBuilder,
267       final int enIndexBuilder, final WikiWord.PartOfSpeech partOfSpeech) {
268     if (!partOfSpeech.translationSenses.isEmpty()) {
269        if (!language.equals("English")) {
270          System.err.println("Translation sections not in English.");
271        }
272        
273        final String englishBase = title + " (" + partOfSpeech.name.toLowerCase() + "%s)";
274        
275        for (final TranslationSense translationSense : partOfSpeech.translationSenses) {
276          //System.out.println("    sense: " + translationSense.sense);
277          if (translationSense.sense == null) {
278            //System.err.println("    null sense: " + title);
279          }
280          String englishSense = String.format(englishBase, translationSense.sense != null ? (": " + translationSense.sense) : "");
281          
282          final StringBuilder[] sideBuilders = new StringBuilder[2];
283          final List<Map<EntryTypeName, List<String>>> sideTokens = new ArrayList<Map<EntryTypeName,List<String>>>();
284          for (int i = 0; i < 2; ++i) {
285            sideBuilders[i] = new StringBuilder();
286            sideTokens.add(new LinkedHashMap<EntryTypeName, List<String>>());
287          }
288          
289          if (enIndexBuilder != -1) {
290            sideBuilders[enIndexBuilder].append(englishSense);
291            addTokens(title, sideTokens.get(enIndexBuilder), EntryTypeName.WIKTIONARY_TITLE_ONE_WORD);
292          }
293          
294          // Get the entries from the translation section.
295          for (int i = 0; i < 2; ++i) {
296            //System.out.println("      lang: " + i);
297            for (final Translation translation : translationSense.translations.get(i)) {
298              //System.out.println("        translation: " + translation);
299              sideBuilders[i].append(sideBuilders[i].length() > 0 ? "\n" : "");
300              if (translationSense.translations.get(i).size() > 1) {
301                sideBuilders[i].append(translation.language).append(": ");
302              }
303              sideBuilders[i].append(translation.text);
304              
305              // TODO: Don't index {m}, {f}
306              // TODO: Don't even show: (1), (1-2), etc.
307              addTokens(translation.text, sideTokens.get(i), EntryTypeName.WIKTIONARY_TRANSLATION_ONE_WORD);
308            }
309          }
310
311          // Construct the Translations-based QuickDic entry for this TranslationSense.
312          if (sideBuilders[0].length() > 0 && sideBuilders[1].length() > 0) {
313            final Pair pair = new Pair(sideBuilders[0].toString(), sideBuilders[1].toString());
314            final PairEntry pairEntry = new PairEntry();
315            pairEntry.pairs.add(pair);
316            final IndexedEntry entryData = new IndexedEntry(dictBuilder.dictionary.pairEntries.size(), pairEntry);
317            dictBuilder.dictionary.pairEntries.add(pairEntry);
318            
319            // Add the EntryData to the indices under the correct tokens.
320            for (int i = 0; i < 2; ++i) {
321              final IndexBuilder indexBuilder = dictBuilder.indexBuilders.get(i);
322              for (final Map.Entry<EntryTypeName, List<String>> entry : sideTokens.get(i).entrySet()) {
323                for (final String token : entry.getValue()) {
324                  final List<IndexedEntry> entries = indexBuilder.getOrCreateEntries(token, entry.getKey());
325                  entries.add(entryData);
326                }
327              }
328
329            }             
330            
331          }
332        }  // Senses
333      }  // Translations
334   }
335
336   
337   static void addTokens(final String text, final Map<EntryTypeName, List<String>> map,
338       EntryTypeName entryTypeName) {
339     final Set<String> tokens = DictFileParser.tokenize(text, DictFileParser.NON_CHAR);
340     if (tokens.size() > 1 && entryTypeName == EntryTypeName.WIKTIONARY_TITLE_ONE_WORD) {
341       entryTypeName = EntryTypeName.WIKTIONARY_TITLE_MULTI_WORD;
342     }
343     List<String> tokenList = map.get(entryTypeName);
344     if (tokenList == null) {
345       tokenList = new ArrayList<String>();
346       map.put(entryTypeName, tokenList);
347     }
348     tokenList.addAll(tokens);
349   }
350
351
352
353 }