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