]> gitweb.fperrin.net Git - Dictionary.git/blob - jars/icu4j-4_4_2-src/main/tests/core/src/com/ibm/icu/dev/test/cldr/TestCLDRVsICU.java
go
[Dictionary.git] / jars / icu4j-4_4_2-src / main / tests / core / src / com / ibm / icu / dev / test / cldr / TestCLDRVsICU.java
1 /*\r
2 **********************************************************************\r
3 * Copyright (c) 2002-2010, International Business Machines\r
4 * Corporation and others.  All Rights Reserved.\r
5 **********************************************************************\r
6 * Author: Mark Davis\r
7 **********************************************************************\r
8 */\r
9 package com.ibm.icu.dev.test.cldr;\r
10 \r
11 import java.io.File;\r
12 import java.io.IOException;\r
13 import java.io.PrintWriter;\r
14 import java.io.StringWriter;\r
15 import java.text.ParseException;\r
16 import java.util.ArrayList;\r
17 import java.util.Collection;\r
18 import java.util.Date;\r
19 import java.util.HashMap;\r
20 import java.util.Iterator;\r
21 import java.util.List;\r
22 import java.util.Map;\r
23 import java.util.Set;\r
24 import java.util.TreeMap;\r
25 import java.util.TreeSet;\r
26 import java.util.regex.Matcher;\r
27 import java.util.regex.Pattern;\r
28 \r
29 import javax.xml.parsers.SAXParser;\r
30 import javax.xml.parsers.SAXParserFactory;\r
31 \r
32 import org.xml.sax.Attributes;\r
33 import org.xml.sax.SAXException;\r
34 import org.xml.sax.helpers.DefaultHandler;\r
35 \r
36 import com.ibm.icu.dev.test.TestFmwk;\r
37 import com.ibm.icu.text.DateFormat;\r
38 import com.ibm.icu.text.NumberFormat;\r
39 import com.ibm.icu.text.SimpleDateFormat;\r
40 import com.ibm.icu.text.UTF16;\r
41 import com.ibm.icu.text.UnicodeSet;\r
42 import com.ibm.icu.util.Currency;\r
43 import com.ibm.icu.util.TimeZone;\r
44 import com.ibm.icu.util.ULocale;\r
45 \r
46 /**\r
47  * This is a test file that takes in the CLDR XML test files and test against\r
48  * ICU4J. This test file is used to verify that ICU4J is implemented correctly.\r
49  * As it stands, the test generates all the errors to the console by logging it.\r
50  * The logging is only possible if "-v" or verbose is set as an argument.\r
51  * This will allow users to know what problems occurred within CLDR and ICU.\r
52  * Collator was disabled in this test file and therefore will be skipped.\r
53  * \r
54  * Instructions:\r
55  * 1)   In order for this to work correctly, you must download the latest CLDR data\r
56  *      in the form of XML. You must also set the CLDR directory using:\r
57  *          -DCLDR_DIRECTORY=<top level of cldr>\r
58  * 2)   You may also consider increasing the memory using -Xmx512m.\r
59  * 3)   For speed purposes, you may consider creating a temporary directory for the\r
60  *      CLDR cache using:\r
61  *          -DCLDR_DTD_CACHE=<cldr cache directory>\r
62  * 4)   You may use other environment variables to narrow down your tests using:\r
63  *          -DXML_MATCH=".*"\r
64  *              -DXML_MATCH="de.*"  (or whatever regex you want) to just test certain locales.\r
65  *          -DTEST_MATCH="zone.*"   (or whatever regex you want) to just test collation, numbers, etc.\r
66  *          -DZONE_MATCH="(?!America/Argentina).*" \r
67  *              -DZONE_MATCH=".*Moscow.*" (to only test certain zones)\r
68 \r
69  * @author medavis\r
70  * @author John Huan Vu (johnvu@us.ibm.com)\r
71  */\r
72 public class TestCLDRVsICU extends TestFmwk {\r
73     static final boolean DEBUG = false;\r
74 \r
75     // ULocale uLocale = ULocale.ENGLISH;\r
76     // Locale oLocale = Locale.ENGLISH; // TODO Drop once ICU4J has ULocale everywhere\r
77     // static PrintWriter log;\r
78     SAXParser SAX;\r
79     static Matcher LOCALE_MATCH, TEST_MATCH, ZONE_MATCH;\r
80     static String CLDR_DIRECTORY;\r
81     static {\r
82         System.out.println();\r
83         LOCALE_MATCH = getEnvironmentRegex("XML_MATCH", ".*");\r
84         TEST_MATCH = getEnvironmentRegex("TEST_MATCH", ".*");\r
85         ZONE_MATCH = getEnvironmentRegex("ZONE_MATCH", ".*");\r
86 \r
87         // CLDR_DIRECTORY is where all the CLDR XML test files are located\r
88         // WARNING: THIS IS TEMPORARY DIRECTORY UNTIL THE FILES ARE STRAIGHTENED OUT\r
89         CLDR_DIRECTORY = getEnvironmentString("CLDR_DIRECTORY", "C:\\Unicode-CVS2\\cldr\\");\r
90         System.out.println();\r
91     }\r
92 \r
93     private static Matcher getEnvironmentRegex(String key, String defaultValue) {\r
94         return Pattern.compile(getEnvironmentString(key, defaultValue)).matcher("");\r
95     }\r
96 \r
97     private static String getEnvironmentString(String key, String defaultValue) {\r
98         String temp = System.getProperty(key);\r
99         if (temp == null)\r
100             temp = defaultValue;\r
101         else\r
102             System.out.print("-D" + key + "=\"" + temp + "\" ");\r
103         return temp;\r
104     }\r
105 \r
106     public static void main(String[] args) throws Exception {\r
107         new TestCLDRVsICU().run(args);\r
108     }\r
109 \r
110     Set allLocales = new TreeSet();\r
111 \r
112     public void TestFiles() throws SAXException, IOException {\r
113         // only get ICU's locales\r
114         Set s = new TreeSet();\r
115         addLocales(NumberFormat.getAvailableULocales(), s);\r
116         addLocales(DateFormat.getAvailableULocales(), s);\r
117 \r
118         // johnvu: Collator was originally disabled\r
119         // addLocales(Collator.getAvailableULocales(), s);\r
120 \r
121         // filter, to make tracking down bugs easier\r
122         for (Iterator it = s.iterator(); it.hasNext();) {\r
123             String locale = (String) it.next();\r
124             if (!LOCALE_MATCH.reset(locale).matches())\r
125                 continue;\r
126             _test(locale);\r
127         }\r
128     }\r
129 \r
130     public void addLocales(ULocale[] list, Collection s) {\r
131         for (int i = 0; i < list.length; ++i) {\r
132             allLocales.add(list[i].toString());\r
133             s.add(list[i].getLanguage());\r
134         }\r
135     }\r
136 \r
137     public String getLanguage(ULocale uLocale) {\r
138         String result = uLocale.getLanguage();\r
139         String script = uLocale.getScript();\r
140         if (script.length() != 0)\r
141             result += "_" + script;\r
142         return result;\r
143     }\r
144 \r
145     public void _test(String localeName) throws SAXException, IOException {\r
146         // uLocale = new ULocale(localeName);\r
147         // oLocale = uLocale.toLocale();\r
148 \r
149         File f = new File(CLDR_DIRECTORY, "test/" + localeName + ".xml");\r
150         logln("Testing " + f.getCanonicalPath());\r
151         SAX.parse(f, DEFAULT_HANDLER);\r
152     }  \r
153 \r
154     private static class ToHex {\r
155         public String transliterate(String in) {\r
156             StringBuilder sb = new StringBuilder();\r
157             for (int i = 0; i < in.length(); ++i) {\r
158                 char c = in.charAt(i);\r
159                 sb.append("\\u");\r
160                 if (c < 1000) {\r
161                     sb.append('0');\r
162                     if (c < 100) {\r
163                         sb.append('0');\r
164                         if (c < 10) {\r
165                             sb.append('0');\r
166                         }\r
167                     }\r
168                 }\r
169                 sb.append(Integer.toHexString((int) c));\r
170             }\r
171             return sb.toString();\r
172         }\r
173     }\r
174 \r
175     // static Transliterator toUnicode = Transliterator.getInstance("any-hex");\r
176     private static final ToHex toUnicode = new ToHex();\r
177 \r
178     static public String showString(String in) {\r
179         return "\u00AB" + in + "\u00BB (" + toUnicode.transliterate(in) + ")";\r
180     }\r
181 \r
182     // ============ SAX Handler Infrastructure ============\r
183 \r
184     abstract public class Handler {\r
185         Map settings = new TreeMap();\r
186         String name;\r
187         List currentLocales = new ArrayList();\r
188         int failures = 0;\r
189 \r
190         void setName(String name) {\r
191             this.name = name;\r
192         }\r
193 \r
194         void set(String attributeName, String attributeValue) {\r
195             // if (DEBUG) logln(attributeName + " => " + attributeValue);\r
196             settings.put(attributeName, attributeValue);\r
197         }\r
198 \r
199         void checkResult(String value) {\r
200             if (settings.get("draft").equals("unconfirmed") || settings.get("draft").equals("provisional")) {\r
201                 return; // skip draft\r
202             }\r
203             ULocale ul = new ULocale("xx");\r
204             try {\r
205                 for (int i = 0; i < currentLocales.size(); ++i) {\r
206                     ul = (ULocale) currentLocales.get(i);\r
207                     // loglnSAX("  Checking " + ul + "(" + ul.getDisplayName(ULocale.ENGLISH) + ")" + " for " + name);\r
208                     handleResult(ul, value);\r
209                     if (failures != 0) {\r
210                         errln("\tTotal Failures: " + failures + "\t" + ul + "(" + ul.getDisplayName(ULocale.ENGLISH)\r
211                                 + ")");\r
212                         failures = 0;\r
213                     }\r
214                 }\r
215             } catch (Exception e) {\r
216                 StringWriter sw = new StringWriter();\r
217                 PrintWriter pw = new PrintWriter(sw);\r
218                 e.printStackTrace(pw);\r
219                 pw.flush();\r
220                 errln("Exception: Locale: " + ul + ",\tValue: <" + value + ">\r\n" + sw.toString());\r
221             }\r
222         }\r
223 \r
224         public void loglnSAX(String message) {\r
225             String temp = message + "\t[" + name;\r
226             for (Iterator it = settings.keySet().iterator(); it.hasNext();) {\r
227                 String attributeName = (String) it.next();\r
228                 String attributeValue = (String) settings.get(attributeName);\r
229                 temp += " " + attributeName + "=<" + attributeValue + ">";\r
230             }\r
231             logln(temp + "]");\r
232         }\r
233 \r
234         int lookupValue(Object x, Object[] list) {\r
235             for (int i = 0; i < list.length; ++i) {\r
236                 if (x.equals(list[i]))\r
237                     return i;\r
238             }\r
239             loglnSAX("Unknown String: " + x);\r
240             return -1;\r
241         }\r
242 \r
243         abstract void handleResult(ULocale currentLocale, String value) throws Exception;\r
244 \r
245         /**\r
246          * @param attributes\r
247          */\r
248         public void setAttributes(Attributes attributes) {\r
249             String localeList = attributes.getValue("locales");\r
250             String[] currentLocaleString = new String[50];\r
251             com.ibm.icu.impl.Utility.split(localeList, ' ', currentLocaleString);\r
252             currentLocales.clear();\r
253             for (int i = 0; i < currentLocaleString.length; ++i) {\r
254                 if (currentLocaleString[i].length() == 0)\r
255                     continue;\r
256                 if (allLocales.contains("")) {\r
257                     logln("Skipping locale, not in ICU4J: " + currentLocaleString[i]);\r
258                     continue;\r
259                 }\r
260                 currentLocales.add(new ULocale(currentLocaleString[i]));\r
261             }\r
262             if (DEBUG)\r
263                 logln("Setting locales: " + currentLocales);\r
264         }\r
265     }\r
266 \r
267     public Handler getHandler(String name, Attributes attributes) {\r
268         if (DEBUG)\r
269             logln("Creating Handler: " + name);\r
270         Handler result = (Handler) RegisteredHandlers.get(name);\r
271         if (result == null)\r
272             logln("Unexpected test type: " + name);\r
273         else {\r
274             result.setAttributes(attributes);\r
275         }\r
276         return result;\r
277     }\r
278 \r
279     public void addHandler(String name, Handler handler) {\r
280         if (!TEST_MATCH.reset(name).matches())\r
281             handler = new NullHandler();\r
282         handler.setName(name);\r
283         RegisteredHandlers.put(name, handler);\r
284     }\r
285 \r
286     Map RegisteredHandlers = new HashMap();\r
287 \r
288     class NullHandler extends Handler {\r
289         void handleResult(ULocale currentLocale, String value) throws Exception {\r
290         }\r
291     }\r
292 \r
293     // ============ Statics for Date/Number Support ============\r
294 \r
295     static TimeZone utc = TimeZone.getTimeZone("GMT");\r
296     static DateFormat iso = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");\r
297     {\r
298         iso.setTimeZone(utc);\r
299     }\r
300 \r
301     static int[] DateFormatValues = { -1, DateFormat.SHORT, DateFormat.MEDIUM, DateFormat.LONG, DateFormat.FULL };\r
302 \r
303     // The following are different data format types that are part of the parameters in CLDR\r
304     static String[] DateFormatNames = { "none", "short", "medium", "long", "full" };\r
305 \r
306     // The following are different number types that are part of the parameters in CLDR\r
307     static String[] NumberNames = { "standard", "integer", "decimal", "percent", "scientific", "GBP" };\r
308 \r
309 \r
310     // ============ Handler for Collation ============\r
311     static UnicodeSet controlsAndSpace = new UnicodeSet("[:cc:]");\r
312 \r
313     static String remove(String in, UnicodeSet toRemove) {\r
314         int cp;\r
315         StringBuffer result = new StringBuffer();\r
316         for (int i = 0; i < in.length(); i += UTF16.getCharCount(cp)) {\r
317             cp = UTF16.charAt(in, i);\r
318             if (!toRemove.contains(cp))\r
319                 UTF16.append(result, cp);\r
320         }\r
321         return result.toString();\r
322     }\r
323 \r
324     {\r
325         // johnvu: Collator was originally disabled\r
326         // TODO (dougfelt) move this test\r
327         /*\r
328           addHandler("collation", new Handler() {\r
329              public void handleResult(ULocale currentLocale, String value) {\r
330                  Collator col = Collator.getInstance(currentLocale);\r
331                  String lastLine = "";\r
332                  int count = 0;\r
333                  for (int pos = 0; pos < value.length();) {\r
334                      int nextPos = value.indexOf('\n', pos);\r
335                      if (nextPos < 0)\r
336                          nextPos = value.length();\r
337                      String line = value.substring(pos, nextPos);\r
338                      line = remove(line, controlsAndSpace);  HACK for SAX\r
339                      if (line.trim().length() != 0) {  HACK for SAX\r
340                          int comp = col.compare(lastLine, line);\r
341                          if (comp > 0) {\r
342                              failures++;\r
343                              errln("\tLine " + (count + 1) + "\tFailure: "\r
344                                      + showString(lastLine) + " should be leq "\r
345                                      + showString(line));\r
346                          } else if (DEBUG) {\r
347                              logln("OK: " + line);\r
348                          }\r
349                          lastLine = line;\r
350                      }\r
351                      pos = nextPos + 1;\r
352                      count++;\r
353                  }\r
354              }\r
355          });\r
356         */\r
357 \r
358         // ============ Handler for Numbers ============\r
359         addHandler("number", new Handler() {\r
360             public void handleResult(ULocale locale, String result) {\r
361                 NumberFormat nf = null;\r
362                 double v = Double.NaN;\r
363                 for (Iterator it = settings.keySet().iterator(); it.hasNext();) {\r
364                     String attributeName = (String) it.next();\r
365                     String attributeValue = (String) settings.get(attributeName);\r
366 \r
367                     // Checks if the attribute name is a draft and whether\r
368                     // or not it has been approved / contributed by CLDR yet\r
369                     // otherwise, skips it because it is most likely rejected by ICU\r
370                     if (attributeName.equals("draft")) {\r
371                         if (attributeValue.indexOf("approved") == -1 && attributeValue.indexOf("contributed") == -1) {\r
372                             break;\r
373                         }\r
374                         continue;\r
375                     }\r
376 \r
377                     // Update the value to be checked\r
378                     if (attributeName.equals("input")) {\r
379                         v = Double.parseDouble(attributeValue);\r
380                         continue;\r
381                     }\r
382 \r
383                     // At this point, it must be a numberType\r
384                     int index = lookupValue(attributeValue, NumberNames);\r
385 \r
386                     if (DEBUG)\r
387                         logln("Getting number format for " + locale);\r
388                     switch (index) {\r
389                     case 0:\r
390                         nf = NumberFormat.getInstance(locale);\r
391                         break;\r
392                     case 1:\r
393                         nf = NumberFormat.getIntegerInstance(locale);\r
394                         break;\r
395                     case 2:\r
396                         nf = NumberFormat.getNumberInstance(locale);\r
397                         break;\r
398                     case 3:\r
399                         nf = NumberFormat.getPercentInstance(locale);\r
400                         break;\r
401                     case 4:\r
402                         nf = NumberFormat.getScientificInstance(locale);\r
403                         break;\r
404                     default:\r
405                         nf = NumberFormat.getCurrencyInstance(locale);\r
406                         nf.setCurrency(Currency.getInstance(attributeValue));\r
407                         break;\r
408                     }\r
409                     String temp = nf.format(v).trim();\r
410                     result = result.trim(); // HACK because of SAX\r
411                     if (!temp.equals(result)) {\r
412                         logln("Number: Locale: " + locale +\r
413                                 "\n\tType: " + attributeValue +\r
414                                 "\n\tDraft: " + settings.get("draft") +\r
415                                 "\n\tCLDR: <" + result + ">" +\r
416                                 "\n\tICU: <" + temp + ">");\r
417                     }\r
418 \r
419                 }\r
420             }\r
421         });\r
422 \r
423         // ============ Handler for Dates ============\r
424         addHandler("date", new Handler() {\r
425             public void handleResult(ULocale locale, String result) throws ParseException {\r
426                 int dateFormat = 0;\r
427                 int timeFormat = 0;\r
428                 Date date = new Date();\r
429                 boolean approved = true;\r
430 \r
431                 for (Iterator it = settings.keySet().iterator(); it.hasNext();) {\r
432                     String attributeName = (String) it.next();\r
433                     String attributeValue = (String) settings.get(attributeName);\r
434 \r
435                     // Checks if the attribute name is a draft and whether\r
436                     // or not it has been approved / contributed by CLDR yet\r
437                     // otherwise, skips it because it is most likely rejected by ICU\r
438                     if (attributeName.equals("draft")) {\r
439                         if (attributeValue.indexOf("approved") == -1 && attributeValue.indexOf("contributed") == -1) {\r
440                             approved = false;\r
441                             break;\r
442                         }\r
443                         continue;\r
444                     }\r
445 \r
446                     // Update the value to be checked\r
447                     if (attributeName.equals("input")) {\r
448                         date = iso.parse(attributeValue);\r
449                         continue;\r
450                     }\r
451                     // At this point, it must be either dateType or timeType\r
452                     int index = lookupValue(attributeValue, DateFormatNames);\r
453                     if (attributeName.equals("dateType"))\r
454                         dateFormat = index;\r
455                     else if (attributeName.equals("timeType"))\r
456                         timeFormat = index;\r
457 \r
458                 }\r
459 \r
460                 // The attribute value must be approved in order to be checked,\r
461                 // if it hasn't been approved, it shouldn't be checked if it\r
462                 // matches with ICU\r
463                 if (approved) {\r
464                     SimpleDateFormat dt = getDateFormat(locale, dateFormat, timeFormat);\r
465                     dt.setTimeZone(utc);\r
466                     String temp = dt.format(date).trim();\r
467                     result = result.trim(); // HACK because of SAX\r
468                     if (!temp.equals(result)) {\r
469                         logln("DateTime: Locale: " + locale +\r
470                                 "\n\tDate: " + DateFormatNames[dateFormat] +\r
471                                 "\n\tTime: " + DateFormatNames[timeFormat] +\r
472                                 "\n\tDraft: " + settings.get("draft") +\r
473                                 "\n\tCLDR: <" + result + "> " +\r
474                                 "\n\tICU: <" + temp + ">");\r
475                     }\r
476                 }\r
477             }\r
478 \r
479             private SimpleDateFormat getDateFormat(ULocale locale, int dateFormat, int timeFormat) {\r
480                 if (DEBUG)\r
481                     logln("Getting date/time format for " + locale);\r
482                 if (DEBUG && "ar_EG".equals(locale.toString())) {\r
483                     logln("debug here");\r
484                 }\r
485                 DateFormat dt;\r
486                 if (dateFormat == 0) {\r
487                     dt = DateFormat.getTimeInstance(DateFormatValues[timeFormat], locale);\r
488                     if (DEBUG)\r
489                         System.out.print("getTimeInstance");\r
490                 } else if (timeFormat == 0) {\r
491                     dt = DateFormat.getDateInstance(DateFormatValues[dateFormat], locale);\r
492                     if (DEBUG)\r
493                         System.out.print("getDateInstance");\r
494                 } else {\r
495                     dt = DateFormat.getDateTimeInstance(DateFormatValues[dateFormat], DateFormatValues[timeFormat],\r
496                             locale);\r
497                     if (DEBUG)\r
498                         System.out.print("getDateTimeInstance");\r
499                 }\r
500                 if (DEBUG)\r
501                     logln("\tinput:\t" + dateFormat + ", " + timeFormat + " => " + ((SimpleDateFormat) dt).toPattern());\r
502                 return (SimpleDateFormat) dt;\r
503             }\r
504         });\r
505 \r
506         // ============ Handler for Zones ============\r
507         addHandler("zoneFields", new Handler() {\r
508             String date = "";\r
509             String zone = "";\r
510             String parse = "";\r
511             String pattern = "";\r
512 \r
513             public void handleResult(ULocale locale, String result) throws ParseException {\r
514                 for (Iterator it = settings.keySet().iterator(); it.hasNext();) {\r
515                     String attributeName = (String) it.next();\r
516                     String attributeValue = (String) settings.get(attributeName);\r
517                     if (attributeName.equals("date")) {\r
518                         date = attributeValue;\r
519                     } else if (attributeName.equals("field")) {\r
520                         pattern = attributeValue;\r
521                     } else if (attributeName.equals("zone")) {\r
522                         zone = attributeValue;\r
523                     } else if (attributeName.equals("parse")) {\r
524                         parse = attributeValue;\r
525                     }\r
526                 }\r
527                 \r
528                 if (!ZONE_MATCH.reset(zone).matches()) return;\r
529                 Date dateValue = iso.parse(date);\r
530                 SimpleDateFormat field = new SimpleDateFormat(pattern, locale);\r
531                 field.setTimeZone(TimeZone.getTimeZone(zone));\r
532                 String temp = field.format(dateValue).trim();\r
533                 // SKIP PARSE FOR NOW\r
534                 result = result.trim(); // HACK because of SAX\r
535                 if (!temp.equals(result)) {\r
536                     temp = field.format(dateValue).trim(); // call again for debugging\r
537                     logln("Zone Format: Locale: " + locale \r
538                             + "\n\tZone: " + zone\r
539                             + "\n\tDate: " + date\r
540                             + "\n\tField: " + pattern\r
541                             + "\n\tParse: " + parse\r
542                             + "\n\tDraft: " + settings.get("draft")\r
543                             + "\n\tCLDR: <" + result\r
544                             + ">\n\tICU: <" + temp + ">");\r
545                 }\r
546             }\r
547         });\r
548     }\r
549 \r
550     // ============ Gorp for SAX ============\r
551 \r
552     {\r
553         try {\r
554             SAXParserFactory factory = SAXParserFactory.newInstance();\r
555             factory.setValidating(true);\r
556             SAX = factory.newSAXParser();\r
557         } catch (Exception e) {\r
558             throw new IllegalArgumentException("SAXParserFacotry was unable to start.");\r
559         }\r
560     }\r
561 \r
562     DefaultHandler DEFAULT_HANDLER = new DefaultHandler() {\r
563         static final boolean DEBUG = false;\r
564         StringBuffer lastChars = new StringBuffer();\r
565         // boolean justPopped = false;\r
566         Handler handler;\r
567 \r
568         public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {\r
569             // data.put(new ContextStack(contextStack), lastChars);\r
570             // lastChars = "";\r
571             try {\r
572                 if (qName.equals("cldrTest")) {\r
573                     // skip\r
574                 } else if (qName.equals("result") && handler != null) {\r
575                     for (int i = 0; i < attributes.getLength(); ++i) {\r
576                         handler.set(attributes.getQName(i), attributes.getValue(i));\r
577                     }\r
578                 } else {\r
579                     handler = getHandler(qName, attributes);\r
580                     // handler.set("locale", uLocale.toString());\r
581                 }\r
582                 // if (DEBUG) logln("startElement:\t" + contextStack);\r
583                 // justPopped = false;\r
584             } catch (RuntimeException e) {\r
585                 e.printStackTrace();\r
586                 throw e;\r
587             }\r
588         }\r
589 \r
590         public void endElement(String uri, String localName, String qName) throws SAXException {\r
591             try {\r
592                 // if (DEBUG) logln("endElement:\t" + contextStack);\r
593                 if (qName.equals("result") && handler != null) {\r
594                     handler.checkResult(lastChars.toString());\r
595                 } else if (qName.length() != 0) {\r
596                     // logln("Unexpected contents of: " + qName + ", <" + lastChars + ">");\r
597                 }\r
598                 lastChars.setLength(0);\r
599                 // justPopped = true;\r
600             } catch (RuntimeException e) {\r
601                 e.printStackTrace();\r
602                 throw e;\r
603             }\r
604         }\r
605 \r
606         // Have to hack around the fact that the character data might be in pieces\r
607         public void characters(char[] ch, int start, int length) throws SAXException {\r
608             try {\r
609                 String value = new String(ch, start, length);\r
610                 if (DEBUG)\r
611                     logln("characters:\t" + value);\r
612                 lastChars.append(value);\r
613                 // justPopped = false;\r
614             } catch (RuntimeException e) {\r
615                 e.printStackTrace();\r
616                 throw e;\r
617             }\r
618         }\r
619 \r
620         // just for debugging\r
621 \r
622         public void notationDecl(String name, String publicId, String systemId) throws SAXException {\r
623             logln("notationDecl: " + name + ", " + publicId + ", " + systemId);\r
624         }\r
625 \r
626         public void processingInstruction(String target, String data) throws SAXException {\r
627             logln("processingInstruction: " + target + ", " + data);\r
628         }\r
629 \r
630         public void skippedEntity(String name) throws SAXException {\r
631             logln("skippedEntity: " + name);\r
632         }\r
633 \r
634         public void unparsedEntityDecl(String name, String publicId, String systemId, String notationName)\r
635                 throws SAXException {\r
636             logln("unparsedEntityDecl: " + name + ", " + publicId + ", " + systemId + ", " + notationName);\r
637         }\r
638     };\r
639 }\r