• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package org.unicode.cldr.test;
2 
3 import static java.util.Collections.disjoint;
4 
5 import java.util.ArrayList;
6 import java.util.List;
7 import java.util.Set;
8 import java.util.TreeSet;
9 
10 import org.unicode.cldr.tool.ToolConfig;
11 import org.unicode.cldr.util.Builder;
12 import org.unicode.cldr.util.CLDRConfig;
13 import org.unicode.cldr.util.CLDRFile;
14 import org.unicode.cldr.util.CLDRPaths;
15 import org.unicode.cldr.util.LanguageTagParser;
16 import org.unicode.cldr.util.Level;
17 import org.unicode.cldr.util.RegexLookup;
18 import org.unicode.cldr.util.RegexLookup.Finder;
19 import org.unicode.cldr.util.RegexLookup.RegexFinder;
20 import org.unicode.cldr.util.SupplementalDataInfo;
21 import org.unicode.cldr.util.SupplementalDataInfo.CoverageLevelInfo;
22 import org.unicode.cldr.util.SupplementalDataInfo.CoverageVariableInfo;
23 import org.unicode.cldr.util.Timer;
24 
25 import com.ibm.icu.util.Output;
26 import com.ibm.icu.util.ULocale;
27 
28 public class CoverageLevel2 {
29 
30     // To modify the results, see /cldr/common/supplemental/coverageLevels.xml
31 
32     /**
33      * Enable to get more verbose output when debugging
34      */
35     private static final boolean DEBUG_LOOKUP = false;
36 
37     private RegexLookup<Level> lookup = null;
38 
39     enum SetMatchType {
40         Target_Language, Target_Scripts, Target_Territories, Target_TimeZones, Target_Currencies, Target_Plurals, Calendar_List
41     }
42 
43     private static class LocaleSpecificInfo {
44         CoverageVariableInfo cvi;
45         String targetLanguage;
46     }
47 
48     final LocaleSpecificInfo myInfo = new LocaleSpecificInfo();
49 
50     /**
51      * We define a regex finder for use in the lookup. It has extra tests based on the ci value and the cvi value,
52      * duplicating
53      * what was in SupplementalDataInfo. It uses the sets instead of converting to regex strings.
54      *
55      * @author markdavis
56      *
57      */
58     public static class MyRegexFinder extends RegexFinder {
59         final private SetMatchType additionalMatch;
60         final private CoverageLevelInfo ci;
61 
MyRegexFinder(String pattern, String additionalMatch, CoverageLevelInfo ci)62         public MyRegexFinder(String pattern, String additionalMatch, CoverageLevelInfo ci) {
63             super(pattern);
64             // remove the ${ and the }, and change - to _.
65             this.additionalMatch = additionalMatch == null
66                 ? null
67                 : SetMatchType.valueOf(
68                     additionalMatch.substring(2, additionalMatch.length() - 1).replace('-', '_'));
69             this.ci = ci;
70         }
71 
72         @Override
find(String item, Object context, Info info)73         public boolean find(String item, Object context, Info info) {
74             LocaleSpecificInfo localeSpecificInfo = (LocaleSpecificInfo) context;
75             // Modified the logic to handle the case where we want specific languages and specific territories.
76             // Any match in language script or territory will succeed when multiple items are present.
77             boolean lstOK = false;
78             if (ci.inLanguage == null && ci.inScriptSet == null && ci.inTerritorySet == null) {
79                 lstOK = true;
80             } else if (ci.inLanguage != null
81                 && ci.inLanguage.matcher(localeSpecificInfo.targetLanguage).matches()) {
82                 lstOK = true;
83             } else if (ci.inScriptSet != null
84                 && !disjoint(ci.inScriptSet, localeSpecificInfo.cvi.targetScripts)) {
85                 lstOK = true;
86             } else if (ci.inTerritorySet != null
87                 && !disjoint(ci.inTerritorySet, localeSpecificInfo.cvi.targetTerritories)) {
88                 lstOK = true;
89             }
90 
91             if (!lstOK) {
92                 return false;
93             }
94             boolean result = super.find(item, context, info); // also sets matcher in RegexFinder
95             if (!result) {
96                 return false;
97             }
98             if (additionalMatch != null) {
99                 String groupMatch = info.value[1];
100 //                    String groupMatch = matcher.group(1);
101                 // we match on a group, so get the right one
102                 switch (additionalMatch) {
103                 case Target_Language:
104                     return localeSpecificInfo.targetLanguage.equals(groupMatch);
105                 case Target_Scripts:
106                     return localeSpecificInfo.cvi.targetScripts.contains(groupMatch);
107                 case Target_Territories:
108                     return localeSpecificInfo.cvi.targetTerritories.contains(groupMatch);
109                 case Target_TimeZones:
110                     return localeSpecificInfo.cvi.targetTimeZones.contains(groupMatch);
111                 case Target_Currencies:
112                     return localeSpecificInfo.cvi.targetCurrencies.contains(groupMatch);
113                 // For Target_Plurals, we have to account for the fact that the @count= part might not be in the
114                 // xpath, so we shouldn't reject the match because of that. ( i.e. The regex is usually
115                 // ([@count='${Target-Plurals}'])?
116                 case Target_Plurals:
117                     return (groupMatch == null ||
118                         groupMatch.length() == 0 || localeSpecificInfo.cvi.targetPlurals.contains(groupMatch));
119                 case Calendar_List:
120                     return localeSpecificInfo.cvi.calendars.contains(groupMatch);
121                 }
122             }
123 
124             return true;
125         }
126 
127         @Override
equals(Object obj)128         public boolean equals(Object obj) {
129             return false;
130         }
131     }
132 
CoverageLevel2(SupplementalDataInfo sdi, String locale)133     private CoverageLevel2(SupplementalDataInfo sdi, String locale) {
134         myInfo.targetLanguage = new LanguageTagParser().set(locale).getLanguage();
135         myInfo.cvi = sdi.getCoverageVariableInfo(myInfo.targetLanguage);
136         lookup = sdi.getCoverageLookup();
137     }
138 
139     /**
140      * get an instance, using CldrUtility.SUPPLEMENTAL_DIRECTORY
141      *
142      * @param locale
143      * @return
144      * @deprecated Don't use this. call the version which takes a SupplementalDataInfo as an argument.
145      * @see #getInstance(SupplementalDataInfo, String)
146      * @see CLDRPaths#SUPPLEMENTAL_DIRECTORY
147      */
148     @Deprecated
getInstance(String locale)149     public static CoverageLevel2 getInstance(String locale) {
150         return new CoverageLevel2(SupplementalDataInfo.getInstance(), locale);
151     }
152 
getInstance(SupplementalDataInfo sdi, String locale)153     public static CoverageLevel2 getInstance(SupplementalDataInfo sdi, String locale) {
154         return new CoverageLevel2(sdi, locale);
155     }
156 
getLevel(String path)157     public Level getLevel(String path) {
158         if (path == null) {
159             return Level.UNDETERMINED;
160         }
161         synchronized (lookup) { // synchronize on the class, since the Matchers are changed during the matching process
162             Level result;
163             if (DEBUG_LOOKUP) { // for testing
164                 Output<String[]> checkItems = new Output<>();
165                 Output<Finder> matcherFound = new Output<>();
166                 List<String> failures = new ArrayList<>();
167                 result = lookup.get(path, myInfo, checkItems, matcherFound, failures);
168                 for (String s : failures) {
169                     System.out.println(s);
170                 }
171             } else {
172                 result = lookup.get(path, myInfo, null);
173             }
174             return result == null ? Level.COMPREHENSIVE : result;
175         }
176     }
177 
getIntLevel(String path)178     public int getIntLevel(String path) {
179         return getLevel(path).getLevel();
180     }
181 
main(String[] args)182     public static void main(String[] args) {
183         // quick test
184         // TODO convert to unit test
185         CoverageLevel2 cv2 = CoverageLevel2.getInstance("de");
186         ULocale uloc = new ULocale("de");
187         CLDRConfig testInfo = ToolConfig.getToolInstance();
188         SupplementalDataInfo supplementalDataInfo2 = testInfo.getSupplementalDataInfo();
189         CLDRFile englishPaths1 = testInfo.getEnglish();
190         Set<String> englishPaths = Builder.with(new TreeSet<String>()).addAll(englishPaths1).get();
191 
192         Timer timer = new Timer();
193         timer.start();
194         for (String path : englishPaths) {
195             int oldLevel = supplementalDataInfo2.getCoverageValueOld(path, uloc);
196         }
197         long oldTime = timer.getDuration();
198         System.out.println(timer.toString(1));
199 
200         timer.start();
201         for (String path : englishPaths) {
202             int newLevel = cv2.getIntLevel(path);
203         }
204         System.out.println(timer.toString(1, oldTime));
205 
206         for (String path : englishPaths) {
207             int newLevel = cv2.getIntLevel(path);
208             int oldLevel = supplementalDataInfo2.getCoverageValueOld(path, uloc);
209             if (newLevel != oldLevel) {
210                 newLevel = cv2.getIntLevel(path);
211                 System.out.println(oldLevel + "\t" + newLevel + "\t" + path);
212             }
213         }
214     }
215 
216 }
217