]> gitweb.fperrin.net Git - DictionaryPC.git/blob - src/com/hughes/android/dictionary/parser/wiktionary/AbstractWiktionaryParser.java
Major en refactoring underway.
[DictionaryPC.git] / src / com / hughes / android / dictionary / parser / wiktionary / AbstractWiktionaryParser.java
1 // Copyright 2012 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.wiktionary;
16
17 import java.io.BufferedInputStream;
18 import java.io.DataInputStream;
19 import java.io.EOFException;
20 import java.io.File;
21 import java.io.FileInputStream;
22 import java.io.IOException;
23 import java.util.LinkedHashMap;
24 import java.util.LinkedHashSet;
25 import java.util.List;
26 import java.util.Map;
27 import java.util.Set;
28 import java.util.SortedMap;
29 import java.util.TreeMap;
30 import java.util.concurrent.atomic.AtomicInteger;
31 import java.util.logging.Level;
32 import java.util.logging.Logger;
33 import java.util.regex.Pattern;
34
35 import com.hughes.android.dictionary.engine.EntrySource;
36 import com.hughes.android.dictionary.engine.EntryTypeName;
37 import com.hughes.android.dictionary.engine.IndexBuilder;
38 import com.hughes.android.dictionary.engine.IndexedEntry;
39 import com.hughes.android.dictionary.parser.Parser;
40 import com.hughes.android.dictionary.parser.WikiTokenizer;
41 import com.hughes.util.EnumUtil;
42
43 public abstract class AbstractWiktionaryParser implements Parser {
44
45   static final Logger LOG = Logger.getLogger("WiktionaryParser");
46
47   final SortedMap<String, AtomicInteger> counters = new TreeMap<String, AtomicInteger>();
48   final Set<String> pairsAdded = new LinkedHashSet<String>();
49   
50   EntrySource entrySource;
51   String title;
52
53
54   abstract void parseSection(final String heading, final String text);
55   
56   @Override
57   public void parse(final File file, final EntrySource entrySource, final int pageLimit) throws IOException {
58     this.entrySource = entrySource;
59     int pageCount = 0;
60     final DataInputStream dis = new DataInputStream(new BufferedInputStream(new FileInputStream(file)));
61     try {
62     while (true) {
63       if (pageLimit >= 0 && pageCount >= pageLimit) {
64         return;
65       }
66       
67       try {
68         title = dis.readUTF();
69       } catch (EOFException e) {
70         LOG.log(Level.INFO, "EOF reading split.");
71         dis.close();
72         return;
73       }
74       final String heading = dis.readUTF();
75       final int bytesLength = dis.readInt();
76       final byte[] bytes = new byte[bytesLength];
77       dis.readFully(bytes);
78       final String text = new String(bytes, "UTF8");
79       
80       parseSection(heading, text);
81
82       ++pageCount;
83       if (pageCount % 1000 == 0) {
84         LOG.info("pageCount=" + pageCount);
85       }
86     }
87     } finally {
88       LOG.info("***COUNTERS***");
89       for (final Map.Entry<String, AtomicInteger> entry : counters.entrySet()) {
90         LOG.info(entry.getKey() + ": " + entry.getValue());
91       }
92     }
93   }
94   
95   static final Pattern whitespace = Pattern.compile("\\s+");
96   static String trim(final String s) {
97     return whitespace.matcher(s).replaceAll(" ").trim();
98   }
99
100   public void incrementCount(final String string) {
101     AtomicInteger counter = counters.get(string);
102     if (counter != null) {
103       counter = new AtomicInteger();
104       counters.put(string, counter);
105     }
106     counter.incrementAndGet();
107   }
108
109   
110   // -------------------------------------------------------------------------
111   
112   static final class AppendAndIndexWikiCallback<T extends AbstractWiktionaryParser> implements WikiTokenizer.Callback {
113
114     final T parser;
115     StringBuilder builder;
116     IndexedEntry indexedEntry;
117     IndexBuilder indexBuilder;
118     final Map<String,FunctionCallback<T>> functionCallbacks = new LinkedHashMap<String, FunctionCallback<T>>();
119     
120     boolean entryTypeNameSticks = false;
121     EntryTypeName entryTypeName = null;
122     
123     final Map<String,AtomicInteger> langCodeToTCount = new LinkedHashMap<String, AtomicInteger>();
124     
125     final NameAndArgs<T> nameAndArgs = new NameAndArgs<T>();
126     
127     public AppendAndIndexWikiCallback(final T parser) {
128       this.parser = parser;
129     }
130     
131     public void reset(final StringBuilder builder, final IndexedEntry indexedEntry) {
132       this.builder = builder;
133       this.indexedEntry = indexedEntry;
134       this.indexBuilder = null;
135       entryTypeName = null;
136       entryTypeNameSticks = false;
137     }
138     
139     public void dispatch(final String wikiText, final IndexBuilder indexBuilder, final EntryTypeName entryTypeName) {
140       final IndexBuilder oldIndexBuilder = this.indexBuilder;
141       final EntryTypeName oldEntryTypeName = this.entryTypeName;
142       this.indexBuilder = indexBuilder;
143       if (!entryTypeNameSticks) {
144         this.entryTypeName = EnumUtil.min(entryTypeName, this.entryTypeName);
145       }
146       if (entryTypeName == null) this.entryTypeName = null;
147       WikiTokenizer.dispatch(wikiText, false, this);
148       this.indexBuilder = oldIndexBuilder;
149       this.entryTypeName = oldEntryTypeName;
150     }
151     
152     public void dispatch(final String wikiText, final EntryTypeName entryTypeName) {
153       dispatch(wikiText, this.indexBuilder, entryTypeName);
154     }
155
156     @Override
157     public void onPlainText(final String plainText) {
158       // The only non-recursive callback.  Just appends to the builder, and indexes.
159       builder.append(plainText);
160       if (indexBuilder != null && entryTypeName != null && indexedEntry != null) {
161         indexBuilder.addEntryWithString(indexedEntry, plainText, entryTypeName);
162       }
163     }
164
165     @Override
166     public void onWikiLink(WikiTokenizer wikiTokenizer) {
167       final String text = wikiTokenizer.wikiLinkText();
168       @SuppressWarnings("unused")
169       final String link = wikiTokenizer.wikiLinkDest();
170       dispatch(text, entryTypeName);
171     }
172
173     @Override
174     public void onFunction(
175         final WikiTokenizer wikiTokenizer,
176         final String name,
177         final List<String> args, 
178         final Map<String, String> namedArgs) {
179       
180       FunctionCallback<T> functionCallback = functionCallbacks.get(name);
181       if (functionCallback == null || !functionCallback.onWikiFunction(wikiTokenizer, name, args, namedArgs, parser, this)) {
182         // Default function handling:
183 //        namedArgs.keySet().removeAll(EnWiktionaryXmlParser.USELESS_WIKI_ARGS);
184         final boolean single = args.isEmpty() && namedArgs.isEmpty();
185         builder.append(single ? "{" : "{{");
186
187         final IndexBuilder oldIndexBuilder = indexBuilder;
188         indexBuilder = null;
189         nameAndArgs.onWikiFunction(wikiTokenizer, name, args, namedArgs, parser, this);
190         indexBuilder = oldIndexBuilder;
191
192         builder.append(single ? "}" : "}}");
193       }
194     }
195
196     @Override
197     public void onHtml(WikiTokenizer wikiTokenizer) {
198       // Unindexed for now.
199       builder.append(wikiTokenizer.token());
200     }
201
202     @Override
203     public void onMarkup(WikiTokenizer wikiTokenizer) {
204       // Do nothing.
205     }
206
207     @Override
208     public final void onComment(WikiTokenizer wikiTokenizer) {
209       // Do nothing.
210     }
211
212     @Override
213     public final void onNewline(WikiTokenizer wikiTokenizer) {
214       assert false;
215     }
216
217     @Override
218     public final void onHeading(WikiTokenizer wikiTokenizer) {
219       assert false;
220     }
221
222     @Override
223     public final void onListItem(WikiTokenizer wikiTokenizer) {
224       assert false;
225     }
226   }
227   
228   // --------------------------------------------------------------------
229   
230   static final class NameAndArgs<T extends AbstractWiktionaryParser> implements FunctionCallback<T> {
231     @Override
232     public boolean onWikiFunction(final WikiTokenizer wikiTokenizer, final String name, final List<String> args,
233         final Map<String, String> namedArgs, final T parser,
234         final AppendAndIndexWikiCallback<T> appendAndIndexWikiCallback) {
235       
236       if (name != null) {
237         appendAndIndexWikiCallback.builder.append(name);
238       }
239       for (int i = 0; i < args.size(); ++i) {
240         if (args.get(i).length() > 0) {
241           appendAndIndexWikiCallback.builder.append("|");
242           appendAndIndexWikiCallback.dispatch(args.get(i), null, null);
243         }
244       }
245       appendNamedArgs(namedArgs, appendAndIndexWikiCallback);
246       return true;
247     }
248   }
249   static NameAndArgs<AbstractWiktionaryParser> NAME_AND_ARGS = new NameAndArgs<AbstractWiktionaryParser>();
250
251   static void appendNamedArgs(final Map<String, String> namedArgs,
252       final AppendAndIndexWikiCallback<?> appendAndIndexWikiCallback) {
253     for (final Map.Entry<String, String> entry : namedArgs.entrySet()) {
254       appendAndIndexWikiCallback.builder.append("|");
255       appendAndIndexWikiCallback.dispatch(entry.getKey(), null, null);
256       appendAndIndexWikiCallback.builder.append("=");
257       EntryTypeName entryTypeName = null;
258       IndexBuilder indexBuilder = null;
259       // This doesn't work: we'd need to add to word-forms.
260 //      System.out.println(entry.getKey());
261 //      if (entry.getKey().equals("tr")) {
262 //        entryTypeName = EntryTypeName.WIKTIONARY_TRANSLITERATION;
263 //        indexBuilder = appendAndIndexWikiCallback.parser.foreignIndexBuilder;
264 //      }
265       appendAndIndexWikiCallback.dispatch(entry.getValue(), indexBuilder, entryTypeName);
266     }
267   }
268
269
270
271 }