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
38     @Override
handleCheck(String path, String fullPath, String value, Options options, List<CheckStatus> result)39     public CheckCLDR handleCheck(String path, String fullPath, String value, Options options,
40         List<CheckStatus> result) {
41         // it helps performance to have a quick reject of most paths
42         if (fullPath == null) return this; // skip paths that we don't have
43         if (fullPath.indexOf("casing") < 0) return this;
44 
45         // pick up the casing attributes from the full path
46         XPathParts parts = XPathParts.getFrozenInstance(fullPath);
47 
48         Case caseTest = Case.mixed;
49         for (int i = 0; i < parts.size(); ++i) {
50             String casingValue = parts.getAttributeValue(i, "casing");
51             if (casingValue == null) {
52                 continue;
53             }
54             caseTest = Case.forString(casingValue);
55             if (caseTest == Case.verbatim) {
56                 return this; // we're done
57             }
58         }
59 
60         String newValue = value;
61         switch (caseTest) {
62         case lowercase_words:
63             newValue = UCharacter.toLowerCase(uLocale, value);
64             break;
65         case titlecase_words:
66             newValue = UCharacter.toTitleCase(uLocale, value, null);
67             break;
68         case titlecase_firstword:
69             newValue = TitleCaseFirst(uLocale, value);
70             break;
71         default:
72             break;
73 
74         }
75         if (!newValue.equals(value)) {
76             // the following is how you signal an error or warning (or add a demo....)
77             result.add(new CheckStatus().setCause(this)
78                 .setMainType(CheckStatus.errorType)
79                 .setSubtype(Subtype.incorrectCasing)
80                 // typically warningType or errorType
81                 .setMessage("Casing incorrect: either should have casing=\"verbatim\" or be <{0}>",
82                     new Object[] { newValue })); // the message; can be MessageFormat with arguments
83         }
84         return this;
85     }
86 
87     // -f(bg|cs|da|el|et|is|it|lt|ro|ru|sl|uk) -t(.*casing.*)
88 
TitleCaseFirst(ULocale locale, String value)89     private String TitleCaseFirst(ULocale locale, String value) {
90         if (value.length() == 0) {
91             return value;
92         }
93         breaker.setText(value);
94         breaker.first();
95         int endOfFirstWord = breaker.next();
96         return UCharacter.toTitleCase(uLocale, value.substring(0, endOfFirstWord), breaker)
97             + value.substring(endOfFirstWord);
98     }
99 
100 }