1 package org.unicode.cldr.util; 2 3 import com.ibm.icu.text.Transform; 4 import com.ibm.icu.text.UnicodeSet; 5 import com.ibm.icu.util.Output; 6 import java.util.List; 7 import org.unicode.cldr.util.CLDRFile.WinningChoice; 8 import org.unicode.cldr.util.SupplementalDataInfo.PluralInfo; 9 import org.unicode.cldr.util.SupplementalDataInfo.PluralInfo.Count; 10 11 public class ValuePathStatus { 12 13 public enum MissingOK { 14 ok, 15 latin, 16 alias, 17 compact 18 } 19 20 public static final UnicodeSet LATIN = new UnicodeSet("[:sc=Latn:]").freeze(); 21 isLatinScriptLocale(CLDRFile sourceFile)22 public static boolean isLatinScriptLocale(CLDRFile sourceFile) { 23 UnicodeSet main = sourceFile.getExemplarSet("", WinningChoice.WINNING); 24 return LATIN.containsSome(main); 25 } 26 27 public static Transform<String, ValuePathStatus.MissingOK> MISSING_STATUS_TRANSFORM = 28 new Transform<String, ValuePathStatus.MissingOK>() { 29 @Override 30 public ValuePathStatus.MissingOK transform(String source) { 31 return ValuePathStatus.MissingOK.valueOf(source); 32 } 33 }; 34 35 static final RegexLookup<ValuePathStatus.MissingOK> missingOk = 36 new RegexLookup<ValuePathStatus.MissingOK>() 37 .setPatternTransform(RegexLookup.RegexFinderTransformPath) 38 .setValueTransform(MISSING_STATUS_TRANSFORM) 39 .loadFromFile(ValuePathStatus.class, "data/paths/missingOk.txt"); 40 countZeros(String otherValue)41 static int countZeros(String otherValue) { 42 int result = 0; 43 for (int i = 0; i < otherValue.length(); ++i) { 44 if (otherValue.charAt(i) == '0') { 45 ++result; 46 } 47 } 48 return result; 49 } 50 51 static final UnicodeSet ASCII_DIGITS = new UnicodeSet("[0-9]"); 52 isMissingOk( CLDRFile sourceFile, String path, boolean latin, boolean aliased)53 public static boolean isMissingOk( 54 CLDRFile sourceFile, String path, boolean latin, boolean aliased) { 55 if (sourceFile.getLocaleID().equals("en")) { 56 return true; 57 } 58 Output<String[]> arguments = new Output<>(); 59 List<String> failures = null; 60 // if (path.startsWith("//ldml/characters/parseLenients")) { 61 // int debug = 0; 62 // failures = new ArrayList<>(); 63 // } 64 ValuePathStatus.MissingOK value = missingOk.get(path, null, arguments, null, failures); 65 if (value == null) { 66 return false; 67 } 68 switch (value) { 69 case ok: 70 return true; 71 case latin: 72 return latin; 73 case alias: 74 return aliased; 75 case compact: 76 // special processing for compact numbers 77 // //ldml/numbers/decimalFormats[@numberSystem="%A"]/decimalFormatLength[@type="%A"]/decimalFormat[@type="standard"]/pattern[@type="%A"][@count="%A"] ; compact 78 if (path.contains("[@count=\"other\"]")) { 79 return false; // the 'other' class always counts as missing 80 } 81 final String numberSystem = arguments.value[1]; 82 final String formatLength = arguments.value[2]; 83 final String patternType = arguments.value[3]; 84 String otherPath = 85 "//ldml/numbers/decimalFormats[@numberSystem=\"" 86 + numberSystem 87 + "\"]/decimalFormatLength[@type=\"" 88 + formatLength 89 + "\"]/decimalFormat[@type=\"standard\"]/pattern[@type=\"" 90 + patternType 91 + "\"][@count=\"other\"]"; 92 String otherValue = sourceFile.getWinningValue(otherPath); 93 if (otherValue == null) { 94 return false; // something's wrong, bail 95 } 96 int digits = countZeros(otherValue); 97 if (digits > 4) { // we can only handle to 4 digits 98 return false; 99 } 100 // If the count is numeric or if there are no possible Count values for this many 101 // digits, then it is ok to be missing. 102 final String count = arguments.value[4]; 103 if (ASCII_DIGITS.containsAll(count)) { 104 return true; // ok to be missing 105 } 106 Count c = Count.valueOf(count); 107 108 SupplementalDataInfo supplementalDataInfo2 = 109 CLDRConfig.getInstance().getSupplementalDataInfo(); 110 // SupplementalDataInfo.getInstance(sourceFile.getSupplementalDirectory()); 111 PluralInfo plurals = supplementalDataInfo2.getPlurals(sourceFile.getLocaleID()); 112 return plurals == null || !plurals.hasSamples(c, digits); // ok if no samples 113 // TODO: handle fractions 114 default: 115 throw new IllegalArgumentException(); 116 } 117 } 118 } 119