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