1 /* 2 ****************************************************************************** 3 * Copyright (C) 2006-2009,2012, International Business Machines Corporation * 4 * and others. All Rights Reserved. * 5 ****************************************************************************** 6 * $Source$ 7 * $Revision: 12133 $ 8 ****************************************************************************** 9 */ 10 package org.unicode.cldr.test; 11 12 import java.util.ArrayList; 13 import java.util.Arrays; 14 import java.util.Collection; 15 import java.util.Date; 16 import java.util.Iterator; 17 import java.util.LinkedHashMap; 18 import java.util.List; 19 import java.util.Map; 20 import java.util.TreeMap; 21 22 import org.unicode.cldr.util.CLDRFile; 23 import org.unicode.cldr.util.ICUServiceBuilder; 24 import org.unicode.cldr.util.XPathParts; 25 26 import com.ibm.icu.text.DateFormat; 27 import com.ibm.icu.text.DateTimePatternGenerator; 28 import com.ibm.icu.text.DateTimePatternGenerator.PatternInfo; 29 30 /** 31 * Temporary class while refactoring. 32 * 33 * @author markdavis 34 * 35 */ 36 class FlexibleDateFromCLDR { 37 DateTimePatternGenerator gen = DateTimePatternGenerator.getEmptyInstance(); 38 transient XPathParts parts = new XPathParts(null, null); 39 private transient ICUServiceBuilder icuServiceBuilder = new ICUServiceBuilder(); 40 41 static List<String> tests = Arrays.asList(new String[] { 42 43 "HHmmssSSSvvvv", // 'complete' time 44 "HHmm", 45 "HHmmvvvv", 46 "HHmmss", 47 "HHmmssSSSSS", 48 "HHmmssvvvv", 49 50 "MMMd", 51 "Md", 52 53 "YYYYD", // (maybe?) 54 55 "yyyyww", 56 "yyyywwEEE", 57 58 "yyyyQQQQ", 59 "yyyyMM", 60 61 "yyyyMd", 62 "yyyyMMMd", 63 "yyyyMMMEEEd", 64 65 "GyyyyMMMd", 66 "GyyyyMMMEEEd", // 'complete' date 67 68 "YYYYwEEE", // year, week of year, weekday 69 "yyyyDD", // year, day of year 70 "yyyyMMFE", // year, month, nth day of week in month 71 // misc 72 "eG", "dMMy", "GHHmm", "yyyyHHmm", "Kmm", "kmm", 73 "MMdd", "ddHH", "yyyyMMMd", "yyyyMMddHHmmss", 74 "GEEEEyyyyMMddHHmmss", 75 "GuuuuQMMMMwwWddDDDFEEEEaHHmmssSSSvvvv", // bizarre case just for testing 76 }); 77 set(CLDRFile cldrFile)78 public void set(CLDRFile cldrFile) { 79 icuServiceBuilder.setCldrFile(cldrFile); 80 gen = DateTimePatternGenerator.getEmptyInstance(); // for now 81 failureMap.clear(); 82 } 83 84 /** 85 * 86 */ showFlexibles()87 public void showFlexibles() { 88 Map<String, String> items = gen.getSkeletons(new LinkedHashMap<String, String>()); 89 System.out.println("ERRORS"); 90 for (Iterator<String> it = failureMap.keySet().iterator(); it.hasNext();) { 91 String item = it.next(); 92 String value = failureMap.get(item); 93 System.out.println("\t" + value); 94 } 95 for (int i = 0; i < DateTimePatternGenerator.TYPE_LIMIT; ++i) { 96 String format = gen.getAppendItemFormat(i); 97 if (format.indexOf('\u251C') >= 0) { 98 System.out.println("\tMissing AppendItem format:\t" + DISPLAY_NAME_MAP[i]); 99 } 100 if (i == DateTimePatternGenerator.FRACTIONAL_SECOND) continue; // don't need this field 101 String name = gen.getAppendItemName(i); 102 if (name.matches("F[0-9]+")) { 103 System.out.println("\tMissing Field Name:\t" + DISPLAY_NAME_MAP[i]); 104 } 105 } 106 System.out.println("SKELETON\t=> PATTERN LIST"); 107 for (Iterator<String> it = items.keySet().iterator(); it.hasNext();) { 108 String skeleton = it.next(); 109 System.out.println("\t\"" + skeleton + "\"\t=>\t\"" + items.get(skeleton) + "\""); 110 } 111 System.out.println("REDUNDANTS"); 112 Collection<String> redundants = gen.getRedundants(new ArrayList<String>()); 113 for (String item : redundants) { 114 System.out.println("\t" + item); 115 } 116 System.out.println("TESTS"); 117 for (String item : tests) { 118 try { 119 String pat = gen.getBestPattern(item); 120 String sample = "<can't format>"; 121 try { 122 DateFormat df = icuServiceBuilder.getDateFormat("gregorian", pat); 123 sample = df.format(new Date()); 124 } catch (RuntimeException e) { 125 } 126 System.out.println("\t\"" + item + "\"\t=>\t\"" + pat + "\"\t=>\t\"" + sample + "\""); 127 } catch (RuntimeException e) { 128 System.out.println(e.getMessage()); // e.printStackTrace(); 129 } 130 } 131 System.out.println("END"); 132 } 133 134 Map<String, String> failureMap = new TreeMap<String, String>(); 135 136 /** 137 * @param path 138 * @param value 139 * @param fullPath 140 */ checkFlexibles(String path, String value, String fullPath)141 public void checkFlexibles(String path, String value, String fullPath) { 142 if (path.indexOf("numbers/symbols/decimal") >= 0) { 143 gen.setDecimal(value); 144 return; 145 } 146 if (path.indexOf("gregorian") < 0) return; 147 if (path.indexOf("/appendItem") >= 0) { 148 String key = (String) parts.set(path).getAttributeValue(-1, "request"); 149 try { 150 gen.setAppendItemFormat(getIndex(key, APPEND_ITEM_NAME_MAP), value); 151 } catch (RuntimeException e) { 152 failureMap.put(path, "\tWarning: can't set AppendItemFormat:\t" + key + ":\t" + value); 153 } 154 return; 155 } 156 if (path.indexOf("/fields") >= 0) { 157 String key = (String) parts.set(path).getAttributeValue(-2, "type"); 158 try { 159 gen.setAppendItemName(getIndex(key, DISPLAY_NAME_MAP), value); 160 } catch (RuntimeException e) { 161 failureMap.put(path, "\tWarning: can't set AppendItemName:\t" + key + ":\t" + value); 162 } 163 return; 164 } 165 166 if (path.indexOf("pattern") < 0 && path.indexOf("dateFormatItem") < 0 && path.indexOf("intervalFormatItem") < 0) return; 167 // set the am/pm preference 168 if (path.indexOf("timeFormatLength[@type=\"short\"]") >= 0) { 169 fp.set(value); 170 for (Object item : fp.getItems()) { 171 if (item instanceof DateTimePatternGenerator.VariableField) { 172 if (item.toString().charAt(0) == 'h') { 173 isPreferred12Hour = true; 174 } 175 } 176 } 177 } 178 if (path.indexOf("dateTimeFormatLength") > 0) return; // exclude {1} {0} 179 if (path.indexOf("intervalFormatItem") < 0) { 180 // add to generator 181 try { 182 gen.addPattern(value, false, patternInfo); 183 switch (patternInfo.status) { 184 case PatternInfo.CONFLICT: 185 failureMap.put(path, "Conflicting Patterns: \"" + value + "\"\t&\t\"" + patternInfo.conflictingPattern 186 + "\""); 187 break; 188 } 189 } catch (RuntimeException e) { 190 failureMap.put(path, e.getMessage()); 191 } 192 } 193 } 194 stripLiterals(String pattern)195 private String stripLiterals(String pattern) { 196 int i = 0, patlen = pattern.length(); 197 StringBuilder stripped = new StringBuilder(patlen); 198 boolean inLiteral = false; 199 while (i < patlen) { 200 char c = pattern.charAt(i++); 201 if (c == '\'') { 202 inLiteral = !inLiteral; 203 } else if (!inLiteral) { 204 stripped.append(c); 205 } 206 } 207 return stripped.toString(); 208 } 209 checkValueAgainstSkeleton(String path, String value)210 public String checkValueAgainstSkeleton(String path, String value) { 211 String failure = null; 212 String skeleton = null; 213 String strippedPattern = null; 214 if (path.contains("dateFormatItem")) { 215 skeleton = (String) parts.set(path).findAttributeValue("dateFormatItem", "id"); // the skeleton 216 strippedPattern = gen.getSkeleton(value); // the pattern stripped of literals 217 } else if (path.contains("intervalFormatItem")) { 218 skeleton = (String) parts.set(path).findAttributeValue("intervalFormatItem", "id"); // the skeleton 219 strippedPattern = stripLiterals(value); // can't use gen on intervalFormat pattern (throws exception) 220 } 221 if (skeleton != null && strippedPattern != null) { 222 if (skeleton.indexOf('H') >= 0 || skeleton.indexOf('k') >= 0) { // if skeleton uses 24-hour time 223 if (strippedPattern.indexOf('h') >= 0 || strippedPattern.indexOf('K') >= 0) { // but pattern uses 12... 224 failure = "Skeleton uses 24-hour cycle (H,k) but pattern uses 12-hour (h,K)"; 225 } 226 } else if (skeleton.indexOf('h') >= 0 || skeleton.indexOf('K') >= 0) { // if skeleton uses 12-hour time 227 if (strippedPattern.indexOf('H') >= 0 || strippedPattern.indexOf('k') >= 0) { // but pattern uses 24... 228 failure = "Skeleton uses 12-hour cycle (h,K) but pattern uses 24-hour (H,k)"; 229 } 230 } 231 } 232 return failure; 233 } 234 235 DateTimePatternGenerator.FormatParser fp = new DateTimePatternGenerator.FormatParser(); 236 237 boolean isPreferred12Hour = false; 238 239 static private String[] DISPLAY_NAME_MAP = { 240 "era", "year", "quarter", "month", "week", "week_in_month", "weekday", 241 "day", "day_of_year", "day_of_week_in_month", "dayperiod", 242 "hour", "minute", "second", "fractional_second", "zone", "-" 243 }; 244 245 static private String[] APPEND_ITEM_NAME_MAP = { 246 "Era", "Year", "Quarter", "Month", "Week", "Week", "Day-Of-Week", 247 "Day", "Day", "Day-Of-Week", "-", 248 "Hour", "Minute", "Second", "-", "Timezone", "-" 249 }; 250 getIndex(String s, String[] strings)251 int getIndex(String s, String[] strings) { 252 for (int i = 0; i < strings.length; ++i) { 253 if (s.equals(strings[i])) return i; 254 } 255 return -1; 256 } 257 258 PatternInfo patternInfo = new PatternInfo(); 259 getRedundants(Collection<String> output)260 public Collection<String> getRedundants(Collection<String> output) { 261 return gen.getRedundants(output); 262 } 263 getFailurePath(Object path)264 public Object getFailurePath(Object path) { 265 return failureMap.get(path); 266 } 267 preferred12Hour()268 public boolean preferred12Hour() { 269 return isPreferred12Hour; 270 } 271 } 272