-//##header\r
-//#if defined(FOUNDATION10) || defined(J2SE13)\r
-//#else\r
-/*\r
-**********************************************************************\r
-* Copyright (c) 2002-2009, International Business Machines\r
-* Corporation and others. All Rights Reserved.\r
-**********************************************************************\r
-* Author: Mark Davis\r
-**********************************************************************\r
-*/\r
-package com.ibm.icu.dev.test.cldr;\r
-\r
-import java.io.File;\r
-\r
-//import org.unicode.cldr.util.LanguageTagParser;\r
-//import org.unicode.cldr.util.Utility;\r
-import java.io.IOException;\r
-import java.io.PrintWriter;\r
-import java.io.StringWriter;\r
-import java.text.ParseException;\r
-import java.util.ArrayList;\r
-import java.util.Collection;\r
-import java.util.Date;\r
-import java.util.HashMap;\r
-import java.util.List;\r
-import java.util.Map;\r
-import java.util.Set;\r
-import java.util.TreeMap;\r
-import java.util.Iterator;\r
-import java.util.TreeSet;\r
-import java.util.regex.Matcher;\r
-import java.util.regex.Pattern;\r
-\r
-import javax.xml.parsers.SAXParser;\r
-import javax.xml.parsers.SAXParserFactory;\r
-\r
-//import org.unicode.cldr.test.CLDRTest;\r
-//import org.unicode.cldr.tool.GenerateCldrTests;\r
-import org.xml.sax.Attributes;\r
-import org.xml.sax.SAXException;\r
-import org.xml.sax.helpers.DefaultHandler;\r
-\r
-import com.ibm.icu.util.Currency;\r
-import com.ibm.icu.util.TimeZone;\r
-import com.ibm.icu.util.ULocale;\r
-import com.ibm.icu.dev.test.TestFmwk;\r
-\r
-import com.ibm.icu.text.Collator;\r
-import com.ibm.icu.text.DateFormat;\r
-import com.ibm.icu.text.NumberFormat;\r
-import com.ibm.icu.text.SimpleDateFormat;\r
-import com.ibm.icu.text.Transliterator;\r
-import com.ibm.icu.text.UTF16;\r
-import com.ibm.icu.text.UnicodeSet;\r
-\r
-/**\r
- * This is a file that runs the CLDR tests for ICU4J, to verify that ICU4J implements them\r
- * correctly.\r
- * WARNING: \r
- * 1. for this to work right, you have to have downloaded the CLDR data, and\r
- * then set the CLDR directory correctly, using\r
- * -DCLDR_DIRECTORY=<top level of cldr>\r
- * 2. You probably also need to increase memory, eg with -Xmx512m\r
- * 3. For speed, you should also use -DCLDR_DTD_CACHE=C:\cldrcache\, where\r
- * C:\cldrcache\ is a temp directory to keep the program from hitting the net for\r
- * each file access.\r
- * 4. You may use other environment variables to narrow what you test. Eg\r
- * -DXML_MATCH=".*" -DTEST_MATCH="zone.*" -DZONE_MATCH="(?!America/Argentina).*" \r
- * a. -DXML_MATCH="de.*" (or whatever regex you want) to just\r
- * test certain locales.\r
- * b. -DTEST_MATCH="zone.*" (or whatever regex you want) to just test collation, numbers, etc.\r
- * c. -DZONE_MATCH=".*Moscow.*" (to only test certain zones)\r
- * @author medavis\r
- */\r
-public class TestCLDRVsICU extends TestFmwk {\r
- static final boolean DEBUG = false;\r
-\r
- //ULocale uLocale = ULocale.ENGLISH;\r
- //Locale oLocale = Locale.ENGLISH; // TODO Drop once ICU4J has ULocale everywhere\r
- //static PrintWriter log;\r
- SAXParser SAX;\r
- static Matcher LOCALE_MATCH, TEST_MATCH, ZONE_MATCH;\r
- static String CLDR_DIRECTORY;\r
- static {\r
- System.out.println();\r
- LOCALE_MATCH = getEnvironmentRegex("XML_MATCH", ".*");\r
- TEST_MATCH = getEnvironmentRegex("TEST_MATCH", ".*");\r
- ZONE_MATCH = getEnvironmentRegex("ZONE_MATCH", ".*"); // example\r
-\r
- // WARNING: THIS IS TEMPORARY UNTIL I GET THE FILES STRAIGHTENED OUT\r
- CLDR_DIRECTORY = getEnvironmentString("CLDR_DIRECTORY", "C:\\Unicode-CVS2\\cldr\\");\r
- System.out.println();\r
- }\r
-\r
- private static Matcher getEnvironmentRegex(String key, String defaultValue) {\r
- return Pattern.compile(getEnvironmentString(key, defaultValue)).matcher("");\r
- }\r
-\r
- private static String getEnvironmentString(String key, String defaultValue) {\r
- String temp = System.getProperty(key);\r
- if (temp == null) temp = defaultValue;\r
- else System.out.print("-D" + key + "=\"" + temp + "\" ");\r
- return temp;\r
- }\r
-\r
- public static void main(String[] args) throws Exception {\r
- new TestCLDRVsICU().run(args);\r
- }\r
-\r
- Set allLocales = new TreeSet();\r
-\r
- public void TestFiles() throws SAXException, IOException {\r
- // only get ICU's locales\r
- Set s = new TreeSet();\r
- addLocales(NumberFormat.getAvailableULocales(), s);\r
- addLocales(DateFormat.getAvailableULocales(), s);\r
- addLocales(Collator.getAvailableULocales(), s);\r
-\r
- // filter, to make tracking down bugs easier\r
-\r
- for (Iterator it = s.iterator(); it.hasNext();) {\r
- String locale = (String)it.next();\r
- if (!LOCALE_MATCH.reset(locale).matches()) continue;\r
- _test(locale);\r
- }\r
- }\r
- \r
- public void addLocales(ULocale[] list, Collection s) {\r
- for (int i = 0; i < list.length; ++i) {\r
- allLocales.add(list[i].toString());\r
- s.add(list[i].getLanguage());\r
- }\r
- }\r
-\r
- public String getLanguage(ULocale uLocale) {\r
- String result = uLocale.getLanguage();\r
- String script = uLocale.getScript();\r
- if (script.length() != 0) result += "_" + script;\r
- return result;\r
- }\r
-\r
- public void _test(String localeName) throws SAXException, IOException {\r
- //uLocale = new ULocale(localeName);\r
- //oLocale = uLocale.toLocale();\r
-\r
- File f = new File(CLDR_DIRECTORY + "common\\test\\"+ localeName + ".xml");\r
- logln("Testing " + f.getCanonicalPath());\r
- SAX.parse(f, DEFAULT_HANDLER);\r
- }\r
-\r
- static Transliterator toUnicode = Transliterator.getInstance("any-hex");\r
- static public String showString(String in) {\r
- return "\u00AB" + in + "\u00BB (" + toUnicode.transliterate(in) + ")";\r
- }\r
- // ============ SAX Handler Infrastructure ============\r
-\r
- abstract public class Handler {\r
- Map settings = new TreeMap();\r
- String name;\r
- List currentLocales = new ArrayList();\r
- int failures = 0;\r
-\r
- void setName(String name) {\r
- this.name = name;\r
- }\r
- void set(String attributeName, String attributeValue) {\r
- //if (DEBUG) logln(attributeName + " => " + attributeValue);\r
- settings.put(attributeName, attributeValue);\r
- }\r
- void checkResult(String value) {\r
- if ("true".equals(settings.get("draft"))) {\r
- return; // skip draft\r
- }\r
- ULocale ul = new ULocale("xx");\r
- try {\r
- for (int i = 0; i < currentLocales.size(); ++i) {\r
- ul = (ULocale)currentLocales.get(i);\r
- //loglnSAX(" Checking " + ul + "(" + ul.getDisplayName(ULocale.ENGLISH) + ")" + " for " + name);\r
- handleResult(ul, value);\r
- if (failures != 0) {\r
- errln("\tTotal Failures: " + failures + "\t" + ul + "(" + ul.getDisplayName(ULocale.ENGLISH) + ")");\r
- failures = 0;\r
- }\r
- }\r
- } catch (Exception e) {\r
- StringWriter sw = new StringWriter();\r
- PrintWriter pw = new PrintWriter(sw);\r
- e.printStackTrace(pw);\r
- pw.flush();\r
- errln("Exception: Locale: " + ul + ",\tValue: <" + value + ">\r\n" + sw.toString());\r
- }\r
- }\r
- public void loglnSAX(String message) {\r
- String temp = message + "\t[" + name;\r
- for (Iterator it = settings.keySet().iterator(); it.hasNext();) {\r
- String attributeName = (String) it.next();\r
- String attributeValue = (String) settings.get(attributeName);\r
- temp += " " + attributeName + "=<" + attributeValue + ">";\r
- }\r
- logln(temp + "]");\r
- }\r
- int lookupValue(Object x, Object[] list) {\r
- for (int i = 0; i < list.length; ++i) {\r
- if (x.equals(list[i])) return i;\r
- }\r
- loglnSAX("Unknown String: " + x);\r
- return -1;\r
- }\r
- abstract void handleResult(ULocale currentLocale, String value) throws Exception;\r
- /**\r
- * @param attributes\r
- */\r
- public void setAttributes(Attributes attributes) {\r
- String localeList = attributes.getValue("locales");\r
- String[] currentLocaleString = new String[50];\r
- com.ibm.icu.impl.Utility.split(localeList, ' ', currentLocaleString);\r
- currentLocales.clear();\r
- for (int i = 0; i < currentLocaleString.length; ++i) {\r
- if (currentLocaleString[i].length() == 0) continue;\r
- if (allLocales.contains("")) {\r
- logln("Skipping locale, not in ICU4J: " + currentLocaleString[i]);\r
- continue;\r
- }\r
- currentLocales.add(new ULocale(currentLocaleString[i]));\r
- }\r
- if (DEBUG) logln("Setting locales: " + currentLocales);\r
- }\r
- }\r
-\r
- public Handler getHandler(String name, Attributes attributes) {\r
- if (DEBUG) logln("Creating Handler: " + name);\r
- Handler result = (Handler) RegisteredHandlers.get(name);\r
- if (result == null) logln("Unexpected test type: " + name);\r
- else {\r
- result.setAttributes(attributes);\r
- }\r
- return result;\r
- }\r
-\r
- public void addHandler(String name, Handler handler) {\r
- if (!TEST_MATCH.reset(name).matches()) handler = new NullHandler();\r
- handler.setName(name);\r
- RegisteredHandlers.put(name, handler);\r
- }\r
- Map RegisteredHandlers = new HashMap();\r
-\r
- class NullHandler extends Handler {\r
- void handleResult(ULocale currentLocale, String value) throws Exception {} \r
- }\r
-\r
- // ============ Statics for Date/Number Support ============\r
-\r
- static TimeZone utc = TimeZone.getTimeZone("GMT");\r
- static DateFormat iso = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");\r
- {\r
- iso.setTimeZone(utc);\r
- }\r
- static int[] DateFormatValues = {-1, DateFormat.SHORT, DateFormat.MEDIUM, DateFormat.LONG, DateFormat.FULL};\r
- static String[] DateFormatNames = {"none", "short", "medium", "long", "full"};\r
-\r
- static String[] NumberNames = {"standard", "integer", "decimal", "percent", "scientific", "GBP"};\r
-\r
-\r
- // ============ Handler for Collation ============ \r
- static UnicodeSet controlsAndSpace = new UnicodeSet("[:cc:]");\r
- \r
- static String remove(String in, UnicodeSet toRemove) {\r
- int cp;\r
- StringBuffer result = new StringBuffer();\r
- for (int i = 0; i < in.length(); i += UTF16.getCharCount(cp)) {\r
- cp = UTF16.charAt(in, i);\r
- if (!toRemove.contains(cp)) UTF16.append(result, cp);\r
- }\r
- return result.toString();\r
- }\r
-\r
- {\r
- addHandler("collation", new Handler() {\r
- public void handleResult(ULocale currentLocale, String value) {\r
- Collator col = Collator.getInstance(currentLocale);\r
- String lastLine = "";\r
- int count = 0;\r
- for (int pos = 0; pos < value.length();) {\r
- int nextPos = value.indexOf('\n', pos);\r
- if (nextPos < 0)\r
- nextPos = value.length();\r
- String line = value.substring(pos, nextPos);\r
- line = remove(line, controlsAndSpace); // HACK for SAX\r
- if (line.trim().length() != 0) { // HACK for SAX\r
- int comp = col.compare(lastLine, line);\r
- if (comp > 0) {\r
- failures++;\r
- errln("\tLine " + (count + 1) + "\tFailure: "\r
- + showString(lastLine) + " should be leq "\r
- + showString(line));\r
- } else if (DEBUG) {\r
- logln("OK: " + line);\r
- }\r
- lastLine = line;\r
- }\r
- pos = nextPos + 1;\r
- count++;\r
- }\r
- }\r
- });\r
-\r
- // ============ Handler for Numbers ============ \r
- addHandler("number", new Handler() {\r
- public void handleResult(ULocale locale, String result) {\r
- NumberFormat nf = null;\r
- double v = Double.NaN;\r
- for (Iterator it = settings.keySet().iterator(); it.hasNext();) {\r
- String attributeName = (String) it.next();\r
- String attributeValue = (String) settings\r
- .get(attributeName);\r
- if (attributeName.equals("input")) {\r
- v = Double.parseDouble(attributeValue);\r
- continue;\r
- }\r
- // must be either numberType at this point\r
- int index = lookupValue(attributeValue, NumberNames);\r
- if (DEBUG) logln("Getting number format for " + locale);\r
- switch(index) {\r
- case 0: nf = NumberFormat.getInstance(locale); break;\r
- case 1: nf = NumberFormat.getIntegerInstance(locale); break;\r
- case 2: nf = NumberFormat.getNumberInstance(locale); break;\r
- case 3: nf = NumberFormat.getPercentInstance(locale); break;\r
- case 4: nf = NumberFormat.getScientificInstance(locale); break;\r
- default: nf = NumberFormat.getCurrencyInstance(locale); \r
- nf.setCurrency(Currency.getInstance(attributeValue)); break;\r
- }\r
- String temp = nf.format(v).trim();\r
- result = result.trim(); // HACK because of SAX\r
- if (!temp.equals(result)) {\r
- errln("Number: Locale: " + locale\r
- + ", \tType: " + attributeValue\r
- + ", \tDraft: " + settings.get("draft")\r
- + ", \tCLDR: <" + result + ">, ICU: <" + temp + ">");\r
- }\r
-\r
- }\r
- }\r
- });\r
-\r
- // ============ Handler for Dates ============\r
- addHandler("date", new Handler() {\r
- public void handleResult(ULocale locale, String result) throws ParseException {\r
- int dateFormat = 0;\r
- int timeFormat = 0;\r
- Date date = new Date();\r
- for (Iterator it = settings.keySet().iterator(); it.hasNext();) {\r
- String attributeName = (String) it.next();\r
- String attributeValue = (String) settings\r
- .get(attributeName);\r
- if (attributeName.equals("input")) {\r
- date = iso.parse(attributeValue);\r
- continue;\r
- }\r
- // must be either dateType or timeType at this point\r
- int index = lookupValue(attributeValue, DateFormatNames);\r
- if (attributeName.equals("dateType"))\r
- dateFormat = index;\r
- else\r
- timeFormat = index;\r
-\r
- }\r
- SimpleDateFormat dt = getDateFormat(locale, dateFormat, timeFormat);\r
- dt.setTimeZone(utc);\r
- String temp = dt.format(date).trim();\r
- result = result.trim(); // HACK because of SAX\r
- if (!temp.equals(result)) {\r
- errln("DateTime: Locale: " + locale \r
- + ", \tDate: " + DateFormatNames[dateFormat]\r
- + ", \tTime: " + DateFormatNames[timeFormat]\r
- + ", \tDraft: " + settings.get("draft")\r
- + ", \tCLDR: <" + result + ">, ICU: <" + temp + ">");\r
- }\r
- }\r
-\r
- private SimpleDateFormat getDateFormat(ULocale locale, int dateFormat, int timeFormat) {\r
- if (DEBUG) logln("Getting date/time format for " + locale);\r
- if (DEBUG && "ar_EG".equals(locale.toString())) {\r
- System.out.println("debug here");\r
- }\r
- DateFormat dt;\r
- if (dateFormat == 0) {\r
- dt = DateFormat.getTimeInstance(DateFormatValues[timeFormat], locale);\r
- if (DEBUG) System.out.print("getTimeInstance");\r
- } else if (timeFormat == 0) {\r
- dt = DateFormat.getDateInstance(DateFormatValues[dateFormat], locale);\r
- if (DEBUG) System.out.print("getDateInstance");\r
- } else {\r
- dt = DateFormat.getDateTimeInstance(DateFormatValues[dateFormat], DateFormatValues[timeFormat], locale);\r
- if (DEBUG) System.out.print("getDateTimeInstance");\r
- }\r
- if (DEBUG) System.out.println("\tinput:\t" + dateFormat + ", " + timeFormat + " => " + ((SimpleDateFormat)dt).toPattern());\r
- return (SimpleDateFormat)dt;\r
- }\r
- });\r
-\r
- // ============ Handler for Zones ============\r
- addHandler("zoneFields", new Handler() {\r
- String date = "";\r
- String zone = "";\r
- String parse = "";\r
- String pattern = "";\r
- \r
- public void handleResult(ULocale locale, String result) throws ParseException {\r
- for (Iterator it = settings.keySet().iterator(); it.hasNext();) {\r
- String attributeName = (String) it.next();\r
- String attributeValue = (String) settings.get(attributeName);\r
- if (attributeName.equals("date")) {\r
- date = attributeValue;\r
- } else if (attributeName.equals("field")) {\r
- pattern = attributeValue;\r
- } else if (attributeName.equals("zone")) {\r
- zone = attributeValue;\r
- } else if (attributeName.equals("parse")) {\r
- parse = attributeValue;\r
- }\r
- }\r
- if (!ZONE_MATCH.reset(zone).matches()) return;\r
- Date dateValue = iso.parse(date);\r
- SimpleDateFormat field = new SimpleDateFormat(pattern, locale);\r
- field.setTimeZone(TimeZone.getTimeZone(zone));\r
- String temp = field.format(dateValue).trim();\r
- // SKIP PARSE FOR NOW\r
- result = result.trim(); // HACK because of SAX\r
- if (!temp.equals(result)) {\r
- temp = field.format(dateValue).trim(); // call again for debugging\r
- errln("Zone Format: Locale: " + locale \r
- + ", \tZone: " + zone\r
- + ", \tDate: " + date\r
- + ", \tField: " + pattern\r
- + ", \tParse: " + parse\r
- + ", \tDraft: " + settings.get("draft")\r
- + ", \tCLDR: <" + result\r
- + ">, \tICU: <" + temp + ">");\r
- }\r
- }\r
- });\r
- }\r
-\r
- // ============ Gorp for SAX ============\r
-\r
- {\r
- try {\r
- SAXParserFactory factory = SAXParserFactory.newInstance();\r
- factory.setValidating(true);\r
- SAX = factory.newSAXParser();\r
- } catch (Exception e) {\r
- throw new IllegalArgumentException("can't start");\r
- }\r
- }\r
-\r
- DefaultHandler DEFAULT_HANDLER = new DefaultHandler() {\r
- static final boolean DEBUG = false;\r
- StringBuffer lastChars = new StringBuffer();\r
- //boolean justPopped = false;\r
- Handler handler;\r
-\r
- public void startElement(\r
- String uri,\r
- String localName,\r
- String qName,\r
- Attributes attributes)\r
- throws SAXException {\r
- //data.put(new ContextStack(contextStack), lastChars);\r
- //lastChars = "";\r
- try {\r
- if (qName.equals("cldrTest")) {\r
- // skip\r
- } else if (qName.equals("result")) {\r
- for (int i = 0; i < attributes.getLength(); ++i) {\r
- handler.set(attributes.getQName(i), attributes.getValue(i));\r
- }\r
- } else {\r
- handler = getHandler(qName, attributes);\r
- //handler.set("locale", uLocale.toString());\r
- }\r
- //if (DEBUG) logln("startElement:\t" + contextStack);\r
- //justPopped = false;\r
- } catch (RuntimeException e) {\r
- e.printStackTrace();\r
- throw e;\r
- }\r
- }\r
- public void endElement(String uri, String localName, String qName)\r
- throws SAXException {\r
- try {\r
- //if (DEBUG) logln("endElement:\t" + contextStack);\r
- if (qName.equals("result")) handler.checkResult(lastChars.toString());\r
- else if (qName.length() != 0) {\r
- //logln("Unexpected contents of: " + qName + ", <" + lastChars + ">");\r
- }\r
- lastChars.setLength(0);\r
- //justPopped = true;\r
- } catch (RuntimeException e) {\r
- e.printStackTrace();\r
- throw e;\r
- }\r
- }\r
- // Have to hack around the fact that the character data might be in pieces\r
- public void characters(char[] ch, int start, int length)\r
- throws SAXException {\r
- try {\r
- String value = new String(ch,start,length);\r
- if (DEBUG) logln("characters:\t" + value);\r
- lastChars.append(value);\r
- //justPopped = false;\r
- } catch (RuntimeException e) {\r
- e.printStackTrace();\r
- throw e;\r
- }\r
- }\r
-\r
- // just for debugging\r
-\r
- public void notationDecl (String name, String publicId, String systemId)\r
- throws SAXException {\r
- logln("notationDecl: " + name\r
- + ", " + publicId\r
- + ", " + systemId\r
- );\r
- }\r
-\r
- public void processingInstruction (String target, String data)\r
- throws SAXException {\r
- logln("processingInstruction: " + target + ", " + data);\r
- }\r
-\r
- public void skippedEntity (String name)\r
- throws SAXException\r
- {\r
- logln("skippedEntity: " + name\r
- );\r
- }\r
-\r
- public void unparsedEntityDecl (String name, String publicId,\r
- String systemId, String notationName)\r
- throws SAXException {\r
- logln("unparsedEntityDecl: " + name\r
- + ", " + publicId\r
- + ", " + systemId\r
- + ", " + notationName\r
- );\r
- }\r
-\r
- };\r
-}\r
-//#endif\r
+//##header J2SE15
+//#if defined(FOUNDATION10) || defined(J2SE13)
+//#else
+/*
+**********************************************************************
+* Copyright (c) 2002-2009, International Business Machines
+* Corporation and others. All Rights Reserved.
+**********************************************************************
+* Author: Mark Davis
+**********************************************************************
+*/
+package com.ibm.icu.dev.test.cldr;
+
+import java.io.File;
+
+//import org.unicode.cldr.util.LanguageTagParser;
+//import org.unicode.cldr.util.Utility;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.text.ParseException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
+import java.util.Iterator;
+import java.util.TreeSet;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+
+//import org.unicode.cldr.test.CLDRTest;
+//import org.unicode.cldr.tool.GenerateCldrTests;
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.DefaultHandler;
+
+import com.ibm.icu.util.Currency;
+import com.ibm.icu.util.TimeZone;
+import com.ibm.icu.util.ULocale;
+import com.ibm.icu.dev.test.TestFmwk;
+
+import com.ibm.icu.text.Collator;
+import com.ibm.icu.text.DateFormat;
+import com.ibm.icu.text.NumberFormat;
+import com.ibm.icu.text.SimpleDateFormat;
+import com.ibm.icu.text.Transliterator;
+import com.ibm.icu.text.UTF16;
+import com.ibm.icu.text.UnicodeSet;
+
+/**
+ * This is a file that runs the CLDR tests for ICU4J, to verify that ICU4J implements them
+ * correctly.
+ * WARNING:
+ * 1. for this to work right, you have to have downloaded the CLDR data, and
+ * then set the CLDR directory correctly, using
+ * -DCLDR_DIRECTORY=<top level of cldr>
+ * 2. You probably also need to increase memory, eg with -Xmx512m
+ * 3. For speed, you should also use -DCLDR_DTD_CACHE=C:\cldrcache\, where
+ * C:\cldrcache\ is a temp directory to keep the program from hitting the net for
+ * each file access.
+ * 4. You may use other environment variables to narrow what you test. Eg
+ * -DXML_MATCH=".*" -DTEST_MATCH="zone.*" -DZONE_MATCH="(?!America/Argentina).*"
+ * a. -DXML_MATCH="de.*" (or whatever regex you want) to just
+ * test certain locales.
+ * b. -DTEST_MATCH="zone.*" (or whatever regex you want) to just test collation, numbers, etc.
+ * c. -DZONE_MATCH=".*Moscow.*" (to only test certain zones)
+ * @author medavis
+ */
+public class TestCLDRVsICU extends TestFmwk {
+ static final boolean DEBUG = false;
+
+ //ULocale uLocale = ULocale.ENGLISH;
+ //Locale oLocale = Locale.ENGLISH; // TODO Drop once ICU4J has ULocale everywhere
+ //static PrintWriter log;
+ SAXParser SAX;
+ static Matcher LOCALE_MATCH, TEST_MATCH, ZONE_MATCH;
+ static String CLDR_DIRECTORY;
+ static {
+ System.out.println();
+ LOCALE_MATCH = getEnvironmentRegex("XML_MATCH", ".*");
+ TEST_MATCH = getEnvironmentRegex("TEST_MATCH", ".*");
+ ZONE_MATCH = getEnvironmentRegex("ZONE_MATCH", ".*"); // example
+
+ // WARNING: THIS IS TEMPORARY UNTIL I GET THE FILES STRAIGHTENED OUT
+ CLDR_DIRECTORY = getEnvironmentString("CLDR_DIRECTORY", "C:\\Unicode-CVS2\\cldr\\");
+ System.out.println();
+ }
+
+ private static Matcher getEnvironmentRegex(String key, String defaultValue) {
+ return Pattern.compile(getEnvironmentString(key, defaultValue)).matcher("");
+ }
+
+ private static String getEnvironmentString(String key, String defaultValue) {
+ String temp = System.getProperty(key);
+ if (temp == null) temp = defaultValue;
+ else System.out.print("-D" + key + "=\"" + temp + "\" ");
+ return temp;
+ }
+
+ public static void main(String[] args) throws Exception {
+ new TestCLDRVsICU().run(args);
+ }
+
+ Set allLocales = new TreeSet();
+
+ public void TestFiles() throws SAXException, IOException {
+ // only get ICU's locales
+ Set s = new TreeSet();
+ addLocales(NumberFormat.getAvailableULocales(), s);
+ addLocales(DateFormat.getAvailableULocales(), s);
+ addLocales(Collator.getAvailableULocales(), s);
+
+ // filter, to make tracking down bugs easier
+
+ for (Iterator it = s.iterator(); it.hasNext();) {
+ String locale = (String)it.next();
+ if (!LOCALE_MATCH.reset(locale).matches()) continue;
+ _test(locale);
+ }
+ }
+
+ public void addLocales(ULocale[] list, Collection s) {
+ for (int i = 0; i < list.length; ++i) {
+ allLocales.add(list[i].toString());
+ s.add(list[i].getLanguage());
+ }
+ }
+
+ public String getLanguage(ULocale uLocale) {
+ String result = uLocale.getLanguage();
+ String script = uLocale.getScript();
+ if (script.length() != 0) result += "_" + script;
+ return result;
+ }
+
+ public void _test(String localeName) throws SAXException, IOException {
+ //uLocale = new ULocale(localeName);
+ //oLocale = uLocale.toLocale();
+
+ File f = new File(CLDR_DIRECTORY + "common\\test\\"+ localeName + ".xml");
+ logln("Testing " + f.getCanonicalPath());
+ SAX.parse(f, DEFAULT_HANDLER);
+ }
+
+ static Transliterator toUnicode = Transliterator.getInstance("any-hex");
+ static public String showString(String in) {
+ return "\u00AB" + in + "\u00BB (" + toUnicode.transliterate(in) + ")";
+ }
+ // ============ SAX Handler Infrastructure ============
+
+ abstract public class Handler {
+ Map settings = new TreeMap();
+ String name;
+ List currentLocales = new ArrayList();
+ int failures = 0;
+
+ void setName(String name) {
+ this.name = name;
+ }
+ void set(String attributeName, String attributeValue) {
+ //if (DEBUG) logln(attributeName + " => " + attributeValue);
+ settings.put(attributeName, attributeValue);
+ }
+ void checkResult(String value) {
+ if ("true".equals(settings.get("draft"))) {
+ return; // skip draft
+ }
+ ULocale ul = new ULocale("xx");
+ try {
+ for (int i = 0; i < currentLocales.size(); ++i) {
+ ul = (ULocale)currentLocales.get(i);
+ //loglnSAX(" Checking " + ul + "(" + ul.getDisplayName(ULocale.ENGLISH) + ")" + " for " + name);
+ handleResult(ul, value);
+ if (failures != 0) {
+ errln("\tTotal Failures: " + failures + "\t" + ul + "(" + ul.getDisplayName(ULocale.ENGLISH) + ")");
+ failures = 0;
+ }
+ }
+ } catch (Exception e) {
+ StringWriter sw = new StringWriter();
+ PrintWriter pw = new PrintWriter(sw);
+ e.printStackTrace(pw);
+ pw.flush();
+ errln("Exception: Locale: " + ul + ",\tValue: <" + value + ">\r\n" + sw.toString());
+ }
+ }
+ public void loglnSAX(String message) {
+ String temp = message + "\t[" + name;
+ for (Iterator it = settings.keySet().iterator(); it.hasNext();) {
+ String attributeName = (String) it.next();
+ String attributeValue = (String) settings.get(attributeName);
+ temp += " " + attributeName + "=<" + attributeValue + ">";
+ }
+ logln(temp + "]");
+ }
+ int lookupValue(Object x, Object[] list) {
+ for (int i = 0; i < list.length; ++i) {
+ if (x.equals(list[i])) return i;
+ }
+ loglnSAX("Unknown String: " + x);
+ return -1;
+ }
+ abstract void handleResult(ULocale currentLocale, String value) throws Exception;
+ /**
+ * @param attributes
+ */
+ public void setAttributes(Attributes attributes) {
+ String localeList = attributes.getValue("locales");
+ String[] currentLocaleString = new String[50];
+ com.ibm.icu.impl.Utility.split(localeList, ' ', currentLocaleString);
+ currentLocales.clear();
+ for (int i = 0; i < currentLocaleString.length; ++i) {
+ if (currentLocaleString[i].length() == 0) continue;
+ if (allLocales.contains("")) {
+ logln("Skipping locale, not in ICU4J: " + currentLocaleString[i]);
+ continue;
+ }
+ currentLocales.add(new ULocale(currentLocaleString[i]));
+ }
+ if (DEBUG) logln("Setting locales: " + currentLocales);
+ }
+ }
+
+ public Handler getHandler(String name, Attributes attributes) {
+ if (DEBUG) logln("Creating Handler: " + name);
+ Handler result = (Handler) RegisteredHandlers.get(name);
+ if (result == null) logln("Unexpected test type: " + name);
+ else {
+ result.setAttributes(attributes);
+ }
+ return result;
+ }
+
+ public void addHandler(String name, Handler handler) {
+ if (!TEST_MATCH.reset(name).matches()) handler = new NullHandler();
+ handler.setName(name);
+ RegisteredHandlers.put(name, handler);
+ }
+ Map RegisteredHandlers = new HashMap();
+
+ class NullHandler extends Handler {
+ void handleResult(ULocale currentLocale, String value) throws Exception {}
+ }
+
+ // ============ Statics for Date/Number Support ============
+
+ static TimeZone utc = TimeZone.getTimeZone("GMT");
+ static DateFormat iso = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
+ {
+ iso.setTimeZone(utc);
+ }
+ static int[] DateFormatValues = {-1, DateFormat.SHORT, DateFormat.MEDIUM, DateFormat.LONG, DateFormat.FULL};
+ static String[] DateFormatNames = {"none", "short", "medium", "long", "full"};
+
+ static String[] NumberNames = {"standard", "integer", "decimal", "percent", "scientific", "GBP"};
+
+
+ // ============ Handler for Collation ============
+ static UnicodeSet controlsAndSpace = new UnicodeSet("[:cc:]");
+
+ static String remove(String in, UnicodeSet toRemove) {
+ int cp;
+ StringBuffer result = new StringBuffer();
+ for (int i = 0; i < in.length(); i += UTF16.getCharCount(cp)) {
+ cp = UTF16.charAt(in, i);
+ if (!toRemove.contains(cp)) UTF16.append(result, cp);
+ }
+ return result.toString();
+ }
+
+ {
+ addHandler("collation", new Handler() {
+ public void handleResult(ULocale currentLocale, String value) {
+ Collator col = Collator.getInstance(currentLocale);
+ String lastLine = "";
+ int count = 0;
+ for (int pos = 0; pos < value.length();) {
+ int nextPos = value.indexOf('\n', pos);
+ if (nextPos < 0)
+ nextPos = value.length();
+ String line = value.substring(pos, nextPos);
+ line = remove(line, controlsAndSpace); // HACK for SAX
+ if (line.trim().length() != 0) { // HACK for SAX
+ int comp = col.compare(lastLine, line);
+ if (comp > 0) {
+ failures++;
+ errln("\tLine " + (count + 1) + "\tFailure: "
+ + showString(lastLine) + " should be leq "
+ + showString(line));
+ } else if (DEBUG) {
+ logln("OK: " + line);
+ }
+ lastLine = line;
+ }
+ pos = nextPos + 1;
+ count++;
+ }
+ }
+ });
+
+ // ============ Handler for Numbers ============
+ addHandler("number", new Handler() {
+ public void handleResult(ULocale locale, String result) {
+ NumberFormat nf = null;
+ double v = Double.NaN;
+ for (Iterator it = settings.keySet().iterator(); it.hasNext();) {
+ String attributeName = (String) it.next();
+ String attributeValue = (String) settings
+ .get(attributeName);
+ if (attributeName.equals("input")) {
+ v = Double.parseDouble(attributeValue);
+ continue;
+ }
+ // must be either numberType at this point
+ int index = lookupValue(attributeValue, NumberNames);
+ if (DEBUG) logln("Getting number format for " + locale);
+ switch(index) {
+ case 0: nf = NumberFormat.getInstance(locale); break;
+ case 1: nf = NumberFormat.getIntegerInstance(locale); break;
+ case 2: nf = NumberFormat.getNumberInstance(locale); break;
+ case 3: nf = NumberFormat.getPercentInstance(locale); break;
+ case 4: nf = NumberFormat.getScientificInstance(locale); break;
+ default: nf = NumberFormat.getCurrencyInstance(locale);
+ nf.setCurrency(Currency.getInstance(attributeValue)); break;
+ }
+ String temp = nf.format(v).trim();
+ result = result.trim(); // HACK because of SAX
+ if (!temp.equals(result)) {
+ errln("Number: Locale: " + locale
+ + ", \tType: " + attributeValue
+ + ", \tDraft: " + settings.get("draft")
+ + ", \tCLDR: <" + result + ">, ICU: <" + temp + ">");
+ }
+
+ }
+ }
+ });
+
+ // ============ Handler for Dates ============
+ addHandler("date", new Handler() {
+ public void handleResult(ULocale locale, String result) throws ParseException {
+ int dateFormat = 0;
+ int timeFormat = 0;
+ Date date = new Date();
+ for (Iterator it = settings.keySet().iterator(); it.hasNext();) {
+ String attributeName = (String) it.next();
+ String attributeValue = (String) settings
+ .get(attributeName);
+ if (attributeName.equals("input")) {
+ date = iso.parse(attributeValue);
+ continue;
+ }
+ // must be either dateType or timeType at this point
+ int index = lookupValue(attributeValue, DateFormatNames);
+ if (attributeName.equals("dateType"))
+ dateFormat = index;
+ else
+ timeFormat = index;
+
+ }
+ SimpleDateFormat dt = getDateFormat(locale, dateFormat, timeFormat);
+ dt.setTimeZone(utc);
+ String temp = dt.format(date).trim();
+ result = result.trim(); // HACK because of SAX
+ if (!temp.equals(result)) {
+ errln("DateTime: Locale: " + locale
+ + ", \tDate: " + DateFormatNames[dateFormat]
+ + ", \tTime: " + DateFormatNames[timeFormat]
+ + ", \tDraft: " + settings.get("draft")
+ + ", \tCLDR: <" + result + ">, ICU: <" + temp + ">");
+ }
+ }
+
+ private SimpleDateFormat getDateFormat(ULocale locale, int dateFormat, int timeFormat) {
+ if (DEBUG) logln("Getting date/time format for " + locale);
+ if (DEBUG && "ar_EG".equals(locale.toString())) {
+ System.out.println("debug here");
+ }
+ DateFormat dt;
+ if (dateFormat == 0) {
+ dt = DateFormat.getTimeInstance(DateFormatValues[timeFormat], locale);
+ if (DEBUG) System.out.print("getTimeInstance");
+ } else if (timeFormat == 0) {
+ dt = DateFormat.getDateInstance(DateFormatValues[dateFormat], locale);
+ if (DEBUG) System.out.print("getDateInstance");
+ } else {
+ dt = DateFormat.getDateTimeInstance(DateFormatValues[dateFormat], DateFormatValues[timeFormat], locale);
+ if (DEBUG) System.out.print("getDateTimeInstance");
+ }
+ if (DEBUG) System.out.println("\tinput:\t" + dateFormat + ", " + timeFormat + " => " + ((SimpleDateFormat)dt).toPattern());
+ return (SimpleDateFormat)dt;
+ }
+ });
+
+ // ============ Handler for Zones ============
+ addHandler("zoneFields", new Handler() {
+ String date = "";
+ String zone = "";
+ String parse = "";
+ String pattern = "";
+
+ public void handleResult(ULocale locale, String result) throws ParseException {
+ for (Iterator it = settings.keySet().iterator(); it.hasNext();) {
+ String attributeName = (String) it.next();
+ String attributeValue = (String) settings.get(attributeName);
+ if (attributeName.equals("date")) {
+ date = attributeValue;
+ } else if (attributeName.equals("field")) {
+ pattern = attributeValue;
+ } else if (attributeName.equals("zone")) {
+ zone = attributeValue;
+ } else if (attributeName.equals("parse")) {
+ parse = attributeValue;
+ }
+ }
+ if (!ZONE_MATCH.reset(zone).matches()) return;
+ Date dateValue = iso.parse(date);
+ SimpleDateFormat field = new SimpleDateFormat(pattern, locale);
+ field.setTimeZone(TimeZone.getTimeZone(zone));
+ String temp = field.format(dateValue).trim();
+ // SKIP PARSE FOR NOW
+ result = result.trim(); // HACK because of SAX
+ if (!temp.equals(result)) {
+ temp = field.format(dateValue).trim(); // call again for debugging
+ errln("Zone Format: Locale: " + locale
+ + ", \tZone: " + zone
+ + ", \tDate: " + date
+ + ", \tField: " + pattern
+ + ", \tParse: " + parse
+ + ", \tDraft: " + settings.get("draft")
+ + ", \tCLDR: <" + result
+ + ">, \tICU: <" + temp + ">");
+ }
+ }
+ });
+ }
+
+ // ============ Gorp for SAX ============
+
+ {
+ try {
+ SAXParserFactory factory = SAXParserFactory.newInstance();
+ factory.setValidating(true);
+ SAX = factory.newSAXParser();
+ } catch (Exception e) {
+ throw new IllegalArgumentException("can't start");
+ }
+ }
+
+ DefaultHandler DEFAULT_HANDLER = new DefaultHandler() {
+ static final boolean DEBUG = false;
+ StringBuffer lastChars = new StringBuffer();
+ //boolean justPopped = false;
+ Handler handler;
+
+ public void startElement(
+ String uri,
+ String localName,
+ String qName,
+ Attributes attributes)
+ throws SAXException {
+ //data.put(new ContextStack(contextStack), lastChars);
+ //lastChars = "";
+ try {
+ if (qName.equals("cldrTest")) {
+ // skip
+ } else if (qName.equals("result")) {
+ for (int i = 0; i < attributes.getLength(); ++i) {
+ handler.set(attributes.getQName(i), attributes.getValue(i));
+ }
+ } else {
+ handler = getHandler(qName, attributes);
+ //handler.set("locale", uLocale.toString());
+ }
+ //if (DEBUG) logln("startElement:\t" + contextStack);
+ //justPopped = false;
+ } catch (RuntimeException e) {
+ e.printStackTrace();
+ throw e;
+ }
+ }
+ public void endElement(String uri, String localName, String qName)
+ throws SAXException {
+ try {
+ //if (DEBUG) logln("endElement:\t" + contextStack);
+ if (qName.equals("result")) handler.checkResult(lastChars.toString());
+ else if (qName.length() != 0) {
+ //logln("Unexpected contents of: " + qName + ", <" + lastChars + ">");
+ }
+ lastChars.setLength(0);
+ //justPopped = true;
+ } catch (RuntimeException e) {
+ e.printStackTrace();
+ throw e;
+ }
+ }
+ // Have to hack around the fact that the character data might be in pieces
+ public void characters(char[] ch, int start, int length)
+ throws SAXException {
+ try {
+ String value = new String(ch,start,length);
+ if (DEBUG) logln("characters:\t" + value);
+ lastChars.append(value);
+ //justPopped = false;
+ } catch (RuntimeException e) {
+ e.printStackTrace();
+ throw e;
+ }
+ }
+
+ // just for debugging
+
+ public void notationDecl (String name, String publicId, String systemId)
+ throws SAXException {
+ logln("notationDecl: " + name
+ + ", " + publicId
+ + ", " + systemId
+ );
+ }
+
+ public void processingInstruction (String target, String data)
+ throws SAXException {
+ logln("processingInstruction: " + target + ", " + data);
+ }
+
+ public void skippedEntity (String name)
+ throws SAXException
+ {
+ logln("skippedEntity: " + name
+ );
+ }
+
+ public void unparsedEntityDecl (String name, String publicId,
+ String systemId, String notationName)
+ throws SAXException {
+ logln("unparsedEntityDecl: " + name
+ + ", " + publicId
+ + ", " + systemId
+ + ", " + notationName
+ );
+ }
+
+ };
+}
+//#endif