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