]> gitweb.fperrin.net Git - DictionaryPC.git/blob - src/com/hughes/android/dictionary/WiktionaryXmlParser.java
31d8c926ffc11dadf2d41b54080badc8b24f7745
[DictionaryPC.git] / src / com / hughes / android / dictionary / WiktionaryXmlParser.java
1 package com.hughes.android.dictionary;
2
3 import java.io.File;
4 import java.io.IOException;
5 import java.util.ArrayList;
6 import java.util.Collections;
7 import java.util.LinkedHashMap;
8 import java.util.List;
9 import java.util.Map;
10 import java.util.TreeMap;
11 import java.util.concurrent.atomic.AtomicInteger;
12 import java.util.regex.Pattern;
13
14 import javax.xml.parsers.ParserConfigurationException;
15 import javax.xml.parsers.SAXParser;
16 import javax.xml.parsers.SAXParserFactory;
17
18 import org.xml.sax.Attributes;
19 import org.xml.sax.SAXException;
20
21 import com.hughes.android.dictionary.engine.Dictionary;
22 import com.hughes.util.MapUtil;
23 import com.hughes.util.StringUtil;
24
25 public class WiktionaryXmlParser extends org.xml.sax.helpers.DefaultHandler {
26
27   final Dictionary dict;
28
29   StringBuilder titleBuilder;
30   StringBuilder textBuilder;
31   StringBuilder currentBuilder = null;
32
33   public WiktionaryXmlParser(final Dictionary dict) {
34     this.dict = dict;
35   }
36
37   @Override
38   public void startElement(String uri, String localName, String qName,
39       Attributes attributes) {
40     currentBuilder = null;
41     if ("page".equals(qName)) {
42       titleBuilder = new StringBuilder();
43       textBuilder = new StringBuilder();
44     } else if ("title".equals(qName)) {
45       currentBuilder = titleBuilder;
46     } else if ("text".equals(qName)) {
47       currentBuilder = textBuilder;
48     }
49   }
50
51   @Override
52   public void characters(char[] ch, int start, int length) throws SAXException {
53     if (currentBuilder != null) {
54       currentBuilder.append(ch, start, length);
55     }
56   }
57
58   @Override
59   public void endElement(String uri, String localName, String qName)
60       throws SAXException {
61     currentBuilder = null;
62     if ("page".equals(qName)) {
63       endPage();
64     }
65   }
66
67   private static final Pattern NEWLINE = Pattern.compile("\n", Pattern.LITERAL);
68
69   // MULTILINE for ^
70   private static final Pattern SECTION_HEADER = Pattern
71       .compile("=== *\\{\\{Wortart\\|");
72
73   private static final Pattern WORTART_DELIM = Pattern.compile("===",
74       Pattern.LITERAL);
75   private static final Pattern GENDER = Pattern.compile("\\{\\{([mfn])\\}\\}");
76
77   private static final Pattern WIKI_QUOTE = Pattern.compile("''",
78       Pattern.LITERAL);
79   private static final Pattern WIKI_DOUBLE_BRACE = Pattern
80       .compile("\\{\\{([^}]+)\\}\\}");
81   private static final Pattern WIKI_DOUBLE_BRACKET = Pattern
82       .compile("\\[\\[([^\\]]+)\\]\\]");
83   private static final Pattern WIKI_NEW_SECTION = Pattern.compile("^\\{\\{([^}]+)\\}\\}|^=", Pattern.MULTILINE);
84
85   enum Field {
86     Wortart("Wortart", null),
87
88     Aussprache("Aussprache", null),
89
90     Bedeutungen("Bedeutungen", Pattern.compile("\\{\\{Bedeutungen\\}\\}")),
91
92     Verkleinerungsformen("Verkleinerungsformen", Pattern.compile("\\{\\{Verkleinerungsformen\\}\\}")),
93
94     Synonome("Synonyme", Pattern.compile("\\{\\{Synonyme\\}\\}")),
95
96     Gegenworte("Gegenworte", Pattern.compile("\\{\\{Gegenworte\\}\\}")),
97
98     Oberbegriffe("Oberbegriffe", Pattern.compile("\\{\\{Oberbegriffe\\}\\}")),
99
100     Unterbegriffe("Unterbegriffe", Pattern.compile("\\{\\{Unterbegriffe\\}\\}")),
101
102     Beispiele("Beispiele", Pattern.compile("\\{\\{Beispiele\\}\\}")),
103
104     Redewendungen("Redewendungen", Pattern.compile("\\{\\{Redewendungen\\}\\}")),
105
106     CharakteristischeWortkombinationen("Charakteristische Wortkombinationen",
107         Pattern.compile("\\{\\{Charakteristische Wortkombinationen\\}\\}")),
108
109     AbgeleiteteBegriffe("Abgeleitete Begriffe", Pattern
110         .compile("\\{\\{Abgeleitete Begriffe\\}\\}")),
111
112     Herkunft("Herkunft", Pattern.compile("\\{\\{Herkunft\\}\\}")),
113     
114     Silbentrennung(null, Pattern.compile("\\{\\{Silbentrennung\\}\\}")),
115     
116     ;
117
118     final String name;
119     final Pattern listPattern;
120
121     Field(final String name, final Pattern listPattern) {
122       this.name = name;
123       this.listPattern = listPattern;
124     }
125   }
126
127   private static final Pattern WORTART = Pattern
128       .compile("\\{\\{Wortart\\|([^}]+)\\|([^}]+)\\}\\}");
129   private static final Pattern AUSSPRACHE = Pattern.compile(":Hilfe:IPA|IPA:",
130       Pattern.LITERAL);
131
132   private final Map<String, AtomicInteger> errorCounts = new TreeMap<String, AtomicInteger>();
133
134   private void endPage() {
135
136     StringBuilder text = textBuilder;
137     text = new StringBuilder(WIKI_QUOTE.matcher(text).replaceAll("\""));
138     text = new StringBuilder(WIKI_DOUBLE_BRACKET.matcher(text).replaceAll("$1"));
139
140     // Remove comments.
141     StringUtil.removeAll(text, Pattern.compile("<!--", Pattern.LITERAL),
142         Pattern.compile("-->", Pattern.LITERAL));
143
144     String sectionString;
145     while ((sectionString = StringUtil.remove(text, SECTION_HEADER,
146         SECTION_HEADER, false)) != null) {
147       final StringBuilder section = new StringBuilder(sectionString);
148
149       String wortart = StringUtil.remove(section, WORTART_DELIM, WORTART_DELIM,
150           true);
151       if (wortart.contains("\n") || !wortart.contains("eutsch")) {
152         MapUtil.safeGet(errorCounts, "Invalid wortart: " + wortart,
153             AtomicInteger.class).incrementAndGet();
154         continue;
155       }
156
157       final LinkedHashMap<Field, List<String>> fieldToValue = new LinkedHashMap<Field, List<String>>();
158
159       wortart = wortart.replaceAll("===", "");
160       wortart = WORTART.matcher(wortart).replaceAll("$1");
161       wortart = GENDER.matcher(wortart).replaceAll("{$1}");
162       wortart = WIKI_DOUBLE_BRACE.matcher(wortart).replaceAll("$1");
163       wortart = wortart.replaceAll("Wortart\\|", "");
164       wortart = wortart.trim();
165       fieldToValue.put(Field.Wortart, Collections.singletonList(wortart));
166
167       String aussprache = StringUtil
168           .remove(section, AUSSPRACHE, NEWLINE, false);
169       if (aussprache != null) {
170         aussprache = AUSSPRACHE.matcher(aussprache).replaceFirst("");
171         aussprache = WIKI_DOUBLE_BRACE.matcher(aussprache).replaceAll("$1");
172         aussprache = aussprache.replaceAll("Lautschrift\\|ˈ?", "");
173         aussprache = aussprache.trim();
174         fieldToValue.put(Field.Aussprache, Collections
175             .singletonList(aussprache));
176       }
177
178       for (final Field field : Field.values()) {
179         if (field.listPattern != null) {
180           fieldToValue.put(field, extractList(section, field.listPattern));
181         }
182       }
183
184       System.out.println(titleBuilder);
185       for (final Field field : Field.values()) {
186         if (!fieldToValue.containsKey(field) || fieldToValue.get(field).isEmpty()) {
187           fieldToValue.remove(field);
188         } else {
189           if (field.name != null) {
190 //            System.out.println(field.name);
191 //            for (final String line : fieldToValue.get(field)) {
192 //              System.out.println("  " + line);
193 //            }
194           }
195         }
196       }
197 //      System.out.println("WHAT'S LEFT:");
198 //      System.out.println(section);
199 //      System.out.println("------------------------------------------------");
200
201     }
202
203   }
204
205   private List<String> extractList(final StringBuilder section,
206       final Pattern start) {
207     final List<String> result = new ArrayList<String>();
208     final String linesString = StringUtil.remove(section, start,
209         WIKI_NEW_SECTION, false);
210     if (linesString != null) {
211       String[] lines = linesString.split("\n");
212       for (int i = 1; i < lines.length; ++i) {
213         String bedeutung = lines[i];
214         bedeutung = bedeutung.replaceFirst("^:+", "");
215         bedeutung = bedeutung.trim();
216         if (bedeutung.length() > 0) {
217           result.add(bedeutung);
218         }
219       }
220     }
221     return result;
222   }
223
224   void parse(final File file) throws ParserConfigurationException,
225       SAXException, IOException {
226     final SAXParser parser = SAXParserFactory.newInstance().newSAXParser();
227     parser.parse(file, this);
228     System.out.println(errorCounts);
229   }
230
231 }