]> 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
130
131   static final Pattern templateName = Pattern.compile("\\{[^,]*,");
132   private void partOfSpeechToQuickDic(final DictionaryBuilder dictBuilder,
133       final int enIndexBuilder, final WikiWord.PartOfSpeech partOfSpeech) {
134     //System.out.println("  pos: " + partOfSpeech.name);
135          
136      for (final WikiWord.Meaning meaning : partOfSpeech.meanings) {
137        //System.out.println("    meaning: " + meaning.meaning);
138        for (final WikiWord.Example example : meaning.examples) {
139          if (example.example.length() > 0) {
140            //System.out.println("      example: " + example.example);
141          }
142          if (example.exampleInEnglish.length() > 0) {
143            //System.out.println("      exampleInEnglish: " + example.exampleInEnglish);
144          }
145        }
146      }
147      
148      
149      if (index != -1) {
150        final boolean formOfSwap = index != 0;
151        for (final FormOf formOf : partOfSpeech.formOfs) {
152          final Pair pair = new Pair(title + ": " + formOf.grammarForm + ": " + formOf.target, "", formOfSwap);
153          final PairEntry pairEntry = new PairEntry(new Pair[] {pair});
154          final EntryData entryData = new EntryData(dictBuilder.dictionary.pairEntries.size(), pairEntry);
155          dictBuilder.dictionary.pairEntries.add(pairEntry);
156   
157          // File under title token.
158          final Set<String> tokens = DictFileParser.tokenize(formOf.target, DictFileParser.NON_CHAR);
159          dictBuilder.indexBuilders.get(index).addEntryWithTokens(entryData, tokens, EntryTypeName.WIKTIONARY_FORM_OF);
160        }
161      }
162
163      
164      if (enIndexBuilder != -1 && index != -1 && enIndexBuilder != index) {
165        final String entryBase = title + " (" + partOfSpeech.name.toLowerCase() + ")";
166        final boolean swap = enIndexBuilder == 1;
167      
168        // Meanings.
169        for (final Meaning meaning : partOfSpeech.meanings) {
170          final List<Pair> pairs = new ArrayList<PairEntry.Pair>();
171          
172          final List<Set<String>> exampleTokens = new ArrayList<Set<String>>();
173          exampleTokens.add(new LinkedHashSet<String>());
174          exampleTokens.add(new LinkedHashSet<String>());
175          
176          if (meaning.meaning != null && meaning.meaning.length() > 0) {
177            final Pair meaningPair = new Pair(meaning.meaning, entryBase, swap);
178            pairs.add(meaningPair);
179          } else {
180            System.err.println("Empty meaning: " + title + ", " + language + ", " + partOfSpeech.name);
181          }
182            
183          // Examples
184          for (final Example example : meaning.examples) {
185            final int dashIndex = example.example.indexOf("—");
186            if (example.exampleInEnglish.length() == 0 && dashIndex != -1) {
187              System.out.println("Splitting example: title=" + title + ", "+ example.example);
188              example.exampleInEnglish.append(example.example.substring(dashIndex + 1).trim());
189              example.example.delete(dashIndex, example.example.length());
190            }
191            
192            if (example.example.length() > 0 && example.exampleInEnglish.length() > 0) {
193              final Pair pair = new Pair(example.exampleInEnglish.toString(), example.example.toString(), swap);
194              pairs.add(pair);
195              
196              for (int i = 0; i < 2; ++i) {
197                exampleTokens.get(i).addAll(DictFileParser.tokenize(pair.get(i), DictFileParser.NON_CHAR));
198              }
199            }
200          }
201
202          // Create EntryData with the PairEntry.
203          final PairEntry pairEntry = new PairEntry(pairs.toArray(new Pair[0]));
204          final EntryData entryData = new EntryData(dictBuilder.dictionary.pairEntries.size(), pairEntry);
205          dictBuilder.dictionary.pairEntries.add(pairEntry);
206
207          // File under title token.
208          final Set<String> titleTokens = DictFileParser.tokenize(title, DictFileParser.NON_CHAR);
209          dictBuilder.indexBuilders.get(index).addEntryWithTokens(entryData, titleTokens, titleTokens.size() == 1 ? EntryTypeName.WIKTIONARY_TITLE_ONE_WORD : EntryTypeName.WIKTIONARY_TITLE_MULTI_WORD);
210        
211          // File under the meaning tokens (English):
212          if (meaning.meaning != null) {
213            // If the meaning contains any templates, strip out the template name
214            // so we don't index it.
215            final String meaningToIndex = templateName.matcher(meaning.meaning).replaceAll("");
216            final Set<String> meaningTokens = DictFileParser.tokenize(meaningToIndex, DictFileParser.NON_CHAR);
217            dictBuilder.indexBuilders.get(enIndexBuilder).addEntryWithTokens(entryData, meaningTokens, meaningTokens.size() == 1 ? EntryTypeName.WIKTIONARY_MEANING_ONE_WORD : EntryTypeName.WIKTIONARY_MEANING_MULTI_WORD);
218          }
219          
220          // File under other tokens that we saw.
221          for (int i = 0; i < 2; ++i) {
222            dictBuilder.indexBuilders.get(i).addEntryWithTokens(entryData, exampleTokens.get(i), EntryTypeName.WIKTIONARY_EXAMPLE_OTHER_WORDS);
223          }         
224        
225          
226        }  // Meanings.
227        
228        
229      }
230      
231      translationSensesToQuickDic(dictBuilder, enIndexBuilder, partOfSpeech);
232   }
233
234
235   private void translationSensesToQuickDic(final DictionaryBuilder dictBuilder,
236       final int enIndexBuilder, final WikiWord.PartOfSpeech partOfSpeech) {
237     if (!partOfSpeech.translationSenses.isEmpty()) {
238        if (!language.equals("English")) {
239          System.err.println("Translation sections not in English.");
240        }
241        
242        final String englishBase = title + " (" + partOfSpeech.name.toLowerCase() + "%s)";
243        
244        final StringBuilder englishPron = new StringBuilder();
245        for (final Map.Entry<String, StringBuilder> accentToPron : accentToPronunciation.entrySet()) {
246          englishPron.append("\n");
247          if (accentToPron.getKey().length() > 0) {
248            englishPron.append(accentToPron.getKey()).append(": ");
249          }
250          englishPron.append(accentToPron.getValue());
251        }
252        
253        for (final TranslationSense translationSense : partOfSpeech.translationSenses) {
254          //System.out.println("    sense: " + translationSense.sense);
255          if (translationSense.sense == null) {
256            //System.err.println("    null sense: " + title);
257          }
258          String englishSense = String.format(englishBase, translationSense.sense != null ? (": " + translationSense.sense) : "");
259          englishSense += englishPron.toString();
260          
261          final StringBuilder[] sideBuilders = new StringBuilder[2];
262          final List<Map<EntryTypeName, List<String>>> sideTokens = new ArrayList<Map<EntryTypeName,List<String>>>();
263          for (int i = 0; i < 2; ++i) {
264            sideBuilders[i] = new StringBuilder();
265            sideTokens.add(new LinkedHashMap<EntryTypeName, List<String>>());
266          }
267          
268          if (enIndexBuilder != -1) {
269            sideBuilders[enIndexBuilder].append(englishSense);
270            addTokens(title, sideTokens.get(enIndexBuilder), EntryTypeName.WIKTIONARY_TITLE_ONE_WORD);
271          }
272          
273          // Get the entries from the translation section.
274          for (int i = 0; i < 2; ++i) {
275            //System.out.println("      lang: " + i);
276            for (final Translation translation : translationSense.translations.get(i)) {
277              //System.out.println("        translation: " + translation);
278              sideBuilders[i].append(sideBuilders[i].length() > 0 ? "\n" : "");
279              if (translationSense.translations.get(i).size() > 1) {
280                sideBuilders[i].append(translation.language).append(": ");
281              }
282              sideBuilders[i].append(translation.text);
283              
284              // TODO: Don't index {m}, {f}
285              // TODO: Don't even show: (1), (1-2), etc.
286              addTokens(translation.text, sideTokens.get(i), EntryTypeName.WIKTIONARY_TRANSLATION_ONE_WORD);
287            }
288          }
289
290          // Construct the Translations-based QuickDic entry for this TranslationSense.
291          if (sideBuilders[0].length() > 0 && sideBuilders[1].length() > 0) {
292            final Pair pair = new Pair(sideBuilders[0].toString(), sideBuilders[1].toString());
293            final PairEntry pairEntry = new PairEntry(new Pair[] { pair });
294            final EntryData entryData = new EntryData(dictBuilder.dictionary.pairEntries.size(), pairEntry);
295            dictBuilder.dictionary.pairEntries.add(pairEntry);
296            
297            // Add the EntryData to the indices under the correct tokens.
298            for (int i = 0; i < 2; ++i) {
299              final IndexBuilder indexBuilder = dictBuilder.indexBuilders.get(i);
300              for (final Map.Entry<EntryTypeName, List<String>> entry : sideTokens.get(i).entrySet()) {
301                for (final String token : entry.getValue()) {
302                  final List<EntryData> entries = indexBuilder.getOrCreateEntries(token, entry.getKey());
303                  entries.add(entryData);
304                }
305              }
306
307            }             
308            
309          }
310        }  // Senses
311      }  // Translations
312   }
313
314   
315   static void addTokens(final String text, final Map<EntryTypeName, List<String>> map,
316       EntryTypeName entryTypeName) {
317     final Set<String> tokens = DictFileParser.tokenize(text, DictFileParser.NON_CHAR);
318     if (tokens.size() > 1 && entryTypeName == EntryTypeName.WIKTIONARY_TITLE_ONE_WORD) {
319       entryTypeName = EntryTypeName.WIKTIONARY_TITLE_MULTI_WORD;
320     }
321     List<String> tokenList = map.get(entryTypeName);
322     if (tokenList == null) {
323       tokenList = new ArrayList<String>();
324       map.put(entryTypeName, tokenList);
325     }
326     tokenList.addAll(tokens);
327   }
328
329
330
331 }