Home | History | Annotate | Download | only in util
      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     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      */
     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
     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      */
     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 
     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 
    104     protected abstract CLDRFile handleMake(String localeID, boolean resolved, DraftStatus madeWithMinimalDraftStatus);
    105 
    106     public CLDRFile make(String localeID, boolean resolved, DraftStatus madeWithMinimalDraftStatus) {
    107         return handleMake(localeID, resolved, madeWithMinimalDraftStatus)
    108             .setSupplementalDirectory(getSupplementalDirectory());
    109     }
    110 
    111     public CLDRFile make(String localeID, boolean resolved, boolean includeDraft) {
    112         return make(localeID, resolved, includeDraft ? DraftStatus.unconfirmed : DraftStatus.approved);
    113     }
    114 
    115     public CLDRFile make(String localeID, boolean resolved) {
    116         return make(localeID, resolved, getMinimalDraftStatus());
    117     }
    118 
    119     public CLDRFile makeWithFallback(String localeID) {
    120         return makeWithFallback(localeID, getMinimalDraftStatus());
    121     }
    122 
    123     public CLDRFile makeWithFallback(String localeID, DraftStatus madeWithMinimalDraftStatus) {
    124         String currentLocaleID = localeID;
    125         Set<String> availableLocales = this.getAvailable();
    126         while (!availableLocales.contains(currentLocaleID) && currentLocaleID != "root") {
    127             currentLocaleID = LocaleIDParser.getParent(currentLocaleID);
    128         }
    129         return make(currentLocaleID, true, madeWithMinimalDraftStatus);
    130     }
    131 
    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      */
    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      */
    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 
    173     public abstract DraftStatus getMinimalDraftStatus();
    174 
    175     /**
    176      * Convenience static
    177      *
    178      * @param path
    179      * @param string
    180      * @return
    181      */
    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      */
    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      */
    205     public Set<String> getAvailable() {
    206         return Collections.unmodifiableSet(handleGetAvailable());
    207     }
    208 
    209     protected abstract Set<String> handleGetAvailable();
    210 
    211     /**
    212      * Get a set of the available language locales (according to isLanguage).
    213      */
    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      */
    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 
    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      */
    251     public Factory setSupplementalDirectory(File supplementalDirectory) {
    252         this.supplementalDirectory = supplementalDirectory;
    253         return this;
    254     }
    255 
    256     // TODO(jchye): Clean this up.
    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 
    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      */
    276     public Set<CLDRLocale> subLocalesOf(CLDRLocale forLocale) {
    277         return calculateSubLocalesOf(forLocale, getAvailableCLDRLocales());
    278     }
    279 
    280     /**
    281      * Helper function.
    282      *
    283      * @return
    284      */
    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      */
    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      */
    311     public abstract List<File> getSourceDirectoriesForLocale(String localeName);
    312 }