• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package org.unicode.cldr.util;
2 
3 import java.io.File;
4 import java.util.ArrayList;
5 import java.util.Collections;
6 import java.util.Iterator;
7 import java.util.List;
8 import java.util.Set;
9 import java.util.TreeSet;
10 
11 import org.unicode.cldr.util.CLDRFile.DraftStatus;
12 import org.unicode.cldr.util.CLDRLocale.SublocaleProvider;
13 import org.unicode.cldr.util.XMLSource.ResolvingSource;
14 
15 /**
16  * A factory is the normal method to produce a set of CLDRFiles from a directory of XML files.
17  * See SimpleFactory for a concrete subclass.
18  */
19 public abstract class Factory implements SublocaleProvider {
20 
21     /**
22      * Flag to set more verbose output in makeServolingSource
23      */
24     private static final boolean DEBUG_FACTORY = false;
25 
26     private File supplementalDirectory = null;
27 
28     /**
29      * Note, the source director(ies) may be a list (seed/common). Therefore, this function is deprecated
30      *
31      * @deprecated
32      * @return the first directory
33      */
getSourceDirectory()34     public String getSourceDirectory() {
35         return getSourceDirectories()[0].getAbsolutePath();
36     }
37 
38     /**
39      * Note, the source director(ies) may be a list (seed/common).
40      *
41      * @return the first directory
42      */
getSourceDirectories()43     public abstract File[] getSourceDirectories();
44 
45     /**
46      * Which source directory does this particular localeID belong to?
47      *
48      * @param localeID
49      * @return
50      */
51     @Deprecated
getSourceDirectoryForLocale(String localeID)52     public final File getSourceDirectoryForLocale(String localeID) {
53         List<File> temp = getSourceDirectoriesForLocale(localeID);
54         return temp == null ? null : temp.get(0);
55     }
56 
57     /**
58      * Classify the tree according to type (maturity)
59      *
60      * @author srl
61      *
62      */
63     public enum SourceTreeType {
64         common, seed, other
65     };
66 
67     /**
68      * Returns the source tree type of either an XML file or its parent directory.
69      *
70      * @param fileOrDir
71      * @return
72      */
getSourceTreeType(File fileOrDir)73     public static final SourceTreeType getSourceTreeType(File fileOrDir) {
74         if (fileOrDir == null) return null;
75         File parentDir = fileOrDir.isFile() ? fileOrDir.getParentFile() : fileOrDir;
76         File grandparentDir = parentDir.getParentFile();
77 
78         try {
79             return SourceTreeType.valueOf(grandparentDir.getName());
80         } catch (IllegalArgumentException iae) {
81             try {
82                 return SourceTreeType.valueOf(parentDir.getName());
83             } catch (IllegalArgumentException iae2) {
84                 return SourceTreeType.other;
85             }
86         }
87     }
88 
89     public enum DirectoryType {
90         main, supplemental, bcp47, casing, collation, dtd, rbnf, segments, transforms, other
91     };
92 
getDirectoryType(File fileOrDir)93     public static final DirectoryType getDirectoryType(File fileOrDir) {
94         if (fileOrDir == null) return null;
95         File parentDir = fileOrDir.isFile() ? fileOrDir.getParentFile() : fileOrDir;
96 
97         try {
98             return DirectoryType.valueOf(parentDir.getName());
99         } catch (IllegalArgumentException iae2) {
100             return DirectoryType.other;
101         }
102     }
103 
handleMake(String localeID, boolean resolved, DraftStatus madeWithMinimalDraftStatus)104     protected abstract CLDRFile handleMake(String localeID, boolean resolved, DraftStatus madeWithMinimalDraftStatus);
105 
make(String localeID, boolean resolved, DraftStatus madeWithMinimalDraftStatus)106     public CLDRFile make(String localeID, boolean resolved, DraftStatus madeWithMinimalDraftStatus) {
107         return handleMake(localeID, resolved, madeWithMinimalDraftStatus)
108             .setSupplementalDirectory(getSupplementalDirectory());
109     }
110 
make(String localeID, boolean resolved, boolean includeDraft)111     public CLDRFile make(String localeID, boolean resolved, boolean includeDraft) {
112         return make(localeID, resolved, includeDraft ? DraftStatus.unconfirmed : DraftStatus.approved);
113     }
114 
make(String localeID, boolean resolved)115     public CLDRFile make(String localeID, boolean resolved) {
116         return make(localeID, resolved, getMinimalDraftStatus());
117     }
118 
makeWithFallback(String localeID)119     public CLDRFile makeWithFallback(String localeID) {
120         return makeWithFallback(localeID, getMinimalDraftStatus());
121     }
122 
makeWithFallback(String localeID, DraftStatus madeWithMinimalDraftStatus)123     public CLDRFile makeWithFallback(String localeID, DraftStatus madeWithMinimalDraftStatus) {
124         String currentLocaleID = localeID;
125         Set<String> availableLocales = this.getAvailable();
126         while (!availableLocales.contains(currentLocaleID) && !"root".equals(currentLocaleID)) {
127             currentLocaleID = LocaleIDParser.getParent(currentLocaleID);
128         }
129         return make(currentLocaleID, true, madeWithMinimalDraftStatus);
130     }
131 
makeResolvingSource(List<XMLSource> sources)132     public static XMLSource makeResolvingSource(List<XMLSource> sources) {
133         return new ResolvingSource(sources);
134     }
135 
136     /**
137      * Temporary wrapper for creating an XMLSource. This is a hack and should
138      * only be used in the Survey Tool for now.
139      *
140      * @param localeID
141      * @return
142      */
makeSource(String localeID)143     public final XMLSource makeSource(String localeID) {
144         return make(localeID, false).dataSource;
145     }
146 
147     /**
148      * Creates a resolving source for the given locale ID.
149      *
150      * @param localeID
151      * @param madeWithMinimalDraftStatus
152      * @return
153      */
makeResolvingSource(String localeID, DraftStatus madeWithMinimalDraftStatus)154     protected ResolvingSource makeResolvingSource(String localeID, DraftStatus madeWithMinimalDraftStatus) {
155         List<XMLSource> sourceList = new ArrayList<XMLSource>();
156         String curLocale = localeID;
157         while (curLocale != null) {
158             if (DEBUG_FACTORY) {
159                 System.out.println("Factory.makeResolvingSource: calling handleMake for locale " +
160                     curLocale + " and MimimalDraftStatus " + madeWithMinimalDraftStatus);
161             }
162             CLDRFile file = handleMake(curLocale, false, madeWithMinimalDraftStatus);
163             if (file == null) {
164                 throw new NullPointerException(this + ".handleMake returned a null CLDRFile for " + curLocale);
165             }
166             XMLSource source = file.dataSource;
167             sourceList.add(source);
168             curLocale = LocaleIDParser.getParent(curLocale);
169         }
170         return new ResolvingSource(sourceList);
171     }
172 
getMinimalDraftStatus()173     public abstract DraftStatus getMinimalDraftStatus();
174 
175     /**
176      * Convenience static
177      *
178      * @param path
179      * @param string
180      * @return
181      */
make(String path, String string)182     public static Factory make(String path, String string) {
183         try {
184             return SimpleFactory.make(path, string);
185         } catch (Exception e) {
186             throw new IllegalArgumentException("path: " + path + "; string: " + string, e);
187         }
188     }
189 
190     /**
191      * Convenience static
192      *
193      * @param mainDirectory
194      * @param string
195      * @param approved
196      * @return
197      */
make(String mainDirectory, String string, DraftStatus approved)198     public static Factory make(String mainDirectory, String string, DraftStatus approved) {
199         return SimpleFactory.make(mainDirectory, string, approved);
200     }
201 
202     /**
203      * Get a set of the available locales for the factory.
204      */
getAvailable()205     public Set<String> getAvailable() {
206         return Collections.unmodifiableSet(handleGetAvailable());
207     }
208 
handleGetAvailable()209     protected abstract Set<String> handleGetAvailable();
210 
211     /**
212      * Get a set of the available language locales (according to isLanguage).
213      */
getAvailableLanguages()214     public Set<String> getAvailableLanguages() {
215         Set<String> result = new TreeSet<String>();
216         for (Iterator<String> it = handleGetAvailable().iterator(); it.hasNext();) {
217             String s = it.next();
218             if (XPathParts.isLanguage(s)) result.add(s);
219         }
220         return result;
221     }
222 
223     /**
224      * Get a set of the locales that have the given parent (according to isSubLocale())
225      *
226      * @param isProper
227      *            if false, then parent itself will match
228      */
getAvailableWithParent(String parent, boolean isProper)229     public Set<String> getAvailableWithParent(String parent, boolean isProper) {
230         Set<String> result = new TreeSet<String>();
231 
232         for (Iterator<String> it = handleGetAvailable().iterator(); it.hasNext();) {
233             String s = it.next();
234             int relation = XPathParts.isSubLocale(parent, s);
235             if (relation >= 0 && !(isProper && relation == 0)) result.add(s);
236         }
237         return result;
238     }
239 
getSupplementalDirectory()240     public File getSupplementalDirectory() {
241         return supplementalDirectory;
242     }
243 
244     /**
245      * Sets the supplemental directory to be used by this Factory and CLDRFiles
246      * created by this Factory.
247      *
248      * @param supplementalDirectory
249      * @return
250      */
setSupplementalDirectory(File supplementalDirectory)251     public Factory setSupplementalDirectory(File supplementalDirectory) {
252         this.supplementalDirectory = supplementalDirectory;
253         return this;
254     }
255 
256     // TODO(jchye): Clean this up.
getSupplementalData()257     public CLDRFile getSupplementalData() {
258         try {
259             return make("supplementalData", false);
260         } catch (RuntimeException e) {
261             return Factory.make(getSupplementalDirectory().getPath(), ".*").make("supplementalData", false);
262         }
263     }
264 
getSupplementalMetadata()265     public CLDRFile getSupplementalMetadata() {
266         try {
267             return make("supplementalMetadata", false);
268         } catch (RuntimeException e) {
269             return Factory.make(getSupplementalDirectory().getPath(), ".*").make("supplementalMetadata", false);
270         }
271     }
272 
273     /**
274      * These factory implementations don't do any caching.
275      */
subLocalesOf(CLDRLocale forLocale)276     public Set<CLDRLocale> subLocalesOf(CLDRLocale forLocale) {
277         return calculateSubLocalesOf(forLocale, getAvailableCLDRLocales());
278     }
279 
280     /**
281      * Helper function.
282      *
283      * @return
284      */
getAvailableCLDRLocales()285     public Set<CLDRLocale> getAvailableCLDRLocales() {
286         return CLDRLocale.getInstance(getAvailable());
287     }
288 
289     /**
290      * Helper function. Does not cache.
291      *
292      * @param locale
293      * @param available
294      * @return
295      */
calculateSubLocalesOf(CLDRLocale locale, Set<CLDRLocale> available)296     public Set<CLDRLocale> calculateSubLocalesOf(CLDRLocale locale, Set<CLDRLocale> available) {
297         Set<CLDRLocale> sub = new TreeSet<CLDRLocale>();
298         for (CLDRLocale l : available) {
299             if (l.getParent() == locale) {
300                 sub.add(l);
301             }
302         }
303         return sub;
304     }
305 
306     /**
307      * Get all of the files in the source directories that match localeName (which is really xml file name).
308      * @param localeName
309      * @return
310      */
getSourceDirectoriesForLocale(String localeName)311     public abstract List<File> getSourceDirectoriesForLocale(String localeName);
312 }