1 package org.unicode.cldr.test; 2 3 import java.util.List; 4 5 import org.unicode.cldr.test.CheckCLDR.CheckStatus.Subtype; 6 import org.unicode.cldr.util.CLDRFile; 7 import org.unicode.cldr.util.XPathParts; 8 9 import com.ibm.icu.lang.UCharacter; 10 import com.ibm.icu.text.BreakIterator; 11 import com.ibm.icu.util.ULocale; 12 13 public class CheckCasing extends CheckCLDR { 14 public enum Case { 15 mixed, lowercase_words, titlecase_words, titlecase_firstword, verbatim; forString(String input)16 public static Case forString(String input) { 17 return valueOf(input.replace('-', '_')); 18 } 19 }; 20 21 // remember to add this class to the list in CheckCLDR.getCheckAll 22 // to run just this test, on just locales starting with 'nl', use CheckCLDR with -fnl.* -t.*Currencies.* 23 24 ULocale uLocale = null; 25 BreakIterator breaker = null; 26 27 @Override setCldrFileToCheck(CLDRFile cldrFileToCheck, Options options, List<CheckStatus> possibleErrors)28 public CheckCLDR setCldrFileToCheck(CLDRFile cldrFileToCheck, Options options, 29 List<CheckStatus> possibleErrors) { 30 if (cldrFileToCheck == null) return this; 31 super.setCldrFileToCheck(cldrFileToCheck, options, possibleErrors); 32 uLocale = new ULocale(cldrFileToCheck.getLocaleID()); 33 breaker = BreakIterator.getWordInstance(uLocale); 34 return this; 35 } 36 37 // If you don't need any file initialization or postprocessing, you only need this one routine handleCheck(String path, String fullPath, String value, Options options, List<CheckStatus> result)38 public CheckCLDR handleCheck(String path, String fullPath, String value, Options options, 39 List<CheckStatus> result) { 40 // it helps performance to have a quick reject of most paths 41 if (fullPath == null) return this; // skip paths that we don't have 42 if (fullPath.indexOf("casing") < 0) return this; 43 44 // pick up the casing attributes from the full path 45 XPathParts parts = XPathParts.getFrozenInstance(fullPath); 46 47 Case caseTest = Case.mixed; 48 for (int i = 0; i < parts.size(); ++i) { 49 String casingValue = parts.getAttributeValue(i, "casing"); 50 if (casingValue == null) { 51 continue; 52 } 53 caseTest = Case.forString(casingValue); 54 if (caseTest == Case.verbatim) { 55 return this; // we're done 56 } 57 } 58 59 String newValue = value; 60 switch (caseTest) { 61 case lowercase_words: 62 newValue = UCharacter.toLowerCase(uLocale, value); 63 break; 64 case titlecase_words: 65 newValue = UCharacter.toTitleCase(uLocale, value, null); 66 break; 67 case titlecase_firstword: 68 newValue = TitleCaseFirst(uLocale, value); 69 break; 70 default: 71 break; 72 73 } 74 if (!newValue.equals(value)) { 75 // the following is how you signal an error or warning (or add a demo....) 76 result.add(new CheckStatus().setCause(this) 77 .setMainType(CheckStatus.errorType) 78 .setSubtype(Subtype.incorrectCasing) 79 // typically warningType or errorType 80 .setMessage("Casing incorrect: either should have casing=\"verbatim\" or be <{0}>", 81 new Object[] { newValue })); // the message; can be MessageFormat with arguments 82 } 83 return this; 84 } 85 86 // -f(bg|cs|da|el|et|is|it|lt|ro|ru|sl|uk) -t(.*casing.*) 87 TitleCaseFirst(ULocale locale, String value)88 private String TitleCaseFirst(ULocale locale, String value) { 89 if (value.length() == 0) { 90 return value; 91 } 92 breaker.setText(value); 93 breaker.first(); 94 int endOfFirstWord = breaker.next(); 95 return UCharacter.toTitleCase(uLocale, value.substring(0, endOfFirstWord), breaker) 96 + value.substring(endOfFirstWord); 97 } 98 99 }