/*
 * Copyright 2010 Google Inc.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package com.google.gwt.tools.cldr;

import com.google.gwt.i18n.shared.GwtLocale;
import com.google.gwt.i18n.shared.GwtLocaleFactory;

import org.unicode.cldr.util.CLDRFile;
import org.unicode.cldr.util.CLDRFile.Factory;
import org.unicode.cldr.util.XPathParts;

import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

/**
 * Collects all the locale data from CLDR, grouping it by how it will be used
 * and removing equivalent values that could be inherited.
 */
public class LocaleData {

  /**
   * Represents data about a single currency in a particular locale from CLDR.
   */
  public static class Currency {

    private static boolean equalsNullCheck(Object a, Object b) {
      if (a == null) {
        return b == null;
      }
      return a.equals(b);
    }

    private static int hashCodeNullCheck(Object obj) {
      return obj == null ? 0 : obj.hashCode();
    }

    private final String code;

    private int decimalDigits;

    private String decimalSeparator;

    private String displayName;

    private String groupingSeparator;

    private boolean inUse;

    private String pattern;

    private String symbol;

    public Currency(String code) {
      this.code = code;
    }

    @Override
    public boolean equals(Object obj) {
      if (obj == this) {
        return true;
      }
      if (!(obj instanceof Currency)) {
        return false;
      }
      Currency other = (Currency) obj;
      return code.equals(other.code)
          && equalsNullCheck(displayName, other.displayName)
          && equalsNullCheck(symbol, other.symbol)
          && equalsNullCheck(pattern, other.pattern)
          && equalsNullCheck(decimalSeparator, other.decimalSeparator)
          && equalsNullCheck(groupingSeparator, other.groupingSeparator)
          && decimalDigits == other.decimalDigits && inUse == other.inUse;
    }

    public String getCode() {
      return code;
    }

    /**
     * @return the number of decimal digits this currency is commonly displayed
     *         with.
     */
    public int getDecimalDigits() {
      return decimalDigits;
    }

    public String getDecimalSeparator() {
      return decimalSeparator;
    }

    public String getDisplayName() {
      return displayName;
    }

    public String getGroupingSeparator() {
      return groupingSeparator;
    }

    public String getPattern() {
      return pattern;
    }

    public String getSymbol() {
      return symbol;
    }

    @Override
    public int hashCode() {
      return code.hashCode() + 17 * hashCodeNullCheck(displayName) + 19
          * hashCodeNullCheck(symbol) + 23 * hashCodeNullCheck(pattern) + 29
          * hashCodeNullCheck(decimalSeparator) + 31
          * hashCodeNullCheck(groupingSeparator) + 37 * decimalDigits
          + (inUse ? 41 : 0);
    }

    /**
     * @return true if this currency is still in regular use.
     */
    public boolean isInUse() {
      return inUse;
    }

    public void setDecimalDigits(int decimalDigits) {
      this.decimalDigits = decimalDigits;
    }

    public void setDecimalSeparator(String decimalSeparator) {
      this.decimalSeparator = decimalSeparator;
    }

    public void setDisplayName(String displayName) {
      this.displayName = displayName;
    }

    public void setGroupingSeparator(String groupingSeparator) {
      this.groupingSeparator = groupingSeparator;
    }

    public void setInUse(boolean inUse) {
      this.inUse = inUse;
    }

    public void setPattern(String pattern) {
      this.pattern = pattern;
    }

    public void setSymbol(String symbol) {
      this.symbol = symbol;
    }

    @Override
    public String toString() {
      StringBuilder buf = new StringBuilder();
      buf.append(code);
      if (displayName != null || symbol != null) {
        buf.append(" (");
      }
      if (displayName != null) {
        buf.append(displayName);
      }
      if (symbol != null) {
        if (displayName != null) {
          buf.append("; ");
        }
        buf.append(symbol);
      }
      if (displayName != null || symbol != null) {
        buf.append(")");
      }
      return buf.toString();
    }
  }

  /**
   * Comparator that orders locales based the inheritance depth.
   */
  private class LocaleComparator implements Comparator<GwtLocale> {
    public int compare(GwtLocale a, GwtLocale b) {
      Integer depthA = localeDepth.get(a);
      Integer depthB = localeDepth.get(b);
      int c = 0;
      if (depthA != null && depthB != null) {
        c = depthB - depthA;
      }
      if (c == 0) {
        c = a.compareTo(b);
      }
      return c;
    }
  }

  /**
   * Encapsulates the key for lookup values, comprising a locale and a category.
   */
  private static class MapKey {
    private final String category;
    private final GwtLocale locale;

    public MapKey(String category, GwtLocale locale) {
      this.category = category;
      this.locale = locale;
    }

    @Override
    public boolean equals(Object obj) {
      if (this == obj) {
        return true;
      }
      if (obj == null || getClass() != obj.getClass()) {
        return false;
      }
      MapKey other = (MapKey) obj;
      return locale.equals(other.locale) && category.equals(other.category);
    }

    public String getCategory() {
      return category;
    }

    public GwtLocale getLocale() {
      return locale;
    }

    @Override
    public int hashCode() {
      return category.hashCode() + 31 * locale.hashCode();
    }

    public MapKey inNewLocale(GwtLocale newLocale) {
      return new MapKey(category, newLocale); 
    }

    @Override
    public String toString() {
      return "[cat=" + category + ", locale=" + locale + "]";
    }
  }

  /**
   * Return the CLDR locale name for a GWT locale.
   * 
   * @param locale
   * @return CLDR locale name for GWT locale
   */
  public static String getCldrLocale(GwtLocale locale) {
    return locale.isDefault() ? "root" : locale.toString();
  }
  
  /**
   * Get the value of a given category of territory data inherited by a locale.
   * 
   * @param locale the locale to search for
   * @param map the map containing territory=>value data
   * @return the requested value from the closest ancestor of the specified
   *     locale, or null if not found
   */
  private static String getTerritoryData(GwtLocale locale,
      Map<String, String> map) {
    if (map == null) {
      return null;
    }
    for (GwtLocale search : locale.getCompleteSearchList()) {
      String region = search.getRegion();
      if (region == null) {
        region = "001";
      }
      String value = map.get(region);
      if (value != null) {
        return value;
      }
    }
    return null;
  }
  
  private final Map<GwtLocale, String> allLocales;

  private final GwtLocale defaultLocale;

  private final HashMap<GwtLocale, GwtLocale> inheritsFrom;
  
  private final Map<GwtLocale, Integer> localeDepth;

  private final GwtLocaleFactory localeFactory;

  private Map<MapKey, Map<String, String>> maps;

  /**
   * Construct a LocaleData object.
   * 
   * @param localeFactory
   * @param localeNames
   */
  public LocaleData(GwtLocaleFactory localeFactory,
      Collection<String> localeNames) {
    this.localeFactory = localeFactory;
    defaultLocale = localeFactory.getDefault();
    allLocales = new HashMap<GwtLocale, String>();
    for (String localeName : localeNames) {
      allLocales.put(getGwtLocale(localeName), localeName);
    }
    inheritsFrom = new HashMap<GwtLocale, GwtLocale>();
    buildInheritsFrom();
    localeDepth = new HashMap<GwtLocale, Integer>();
    maps = new HashMap<MapKey, Map<String, String>>();
    buildLocaleDepth();
  }

  /**
   * Add a single entry from an attribute on a CLDR node.
   * 
   * @param category
   * @param locale
   * @param cldrFactory
   * @param path
   * @param tag
   * @param key
   * @param attribute
   */
  public void addAttributeEntry(String category, GwtLocale locale,
      Factory cldrFactory, String path, String tag, String key,
      String attribute) {
    Map<String, String> map = getMap(category, locale);
    CLDRFile cldr = cldrFactory.make(allLocales.get(locale), true);
    XPathParts parts = new XPathParts();
    parts.set(cldr.getFullXPath(path));
    Map<String, String> attr = parts.findAttributes(tag);
    if (attr == null) {
      return;
    }
    String value = attr.get(attribute);
    map.put(key, value);
  }

  /**
   * Add currency entries for all locales.
   * 
   * @param category
   * @param cldrFactory
   * @param currencyFractions map of currency fraction data extracted from
   *     locale-independent data
   * @param defaultCurrencyFraction
   * @param stillInUse
   */
  public void addCurrencyEntries(String category, Factory cldrFactory,
      Map<String, Integer> currencyFractions, int defaultCurrencyFraction,
      Set<String> stillInUse) {
    for (GwtLocale locale : allLocales.keySet()) {
      // skip the "default" locale for now
      if (locale.isDefault()) {
        continue;
      }
      addCurrencyEntries(category, locale, cldrFactory, currencyFractions,
          defaultCurrencyFraction, stillInUse);
    }
    // run the "default" locale last, to override inherited entries
    GwtLocale locale = localeFactory.getDefault();
    addCurrencyEntries(category, locale, cldrFactory, currencyFractions,
        defaultCurrencyFraction, stillInUse);
  }

  public void addDateTimeFormatEntries(String group, Factory cldrFactory) {
    addAttributeEntries(group, cldrFactory,
        "//ldml/dates/calendars/calendar[@type=\"gregorian\"]/" + group
        + "Formats/default", "default", "default", "choice");
    addDateTimeFormatEntries(group, "full", cldrFactory);
    addDateTimeFormatEntries(group, "long", cldrFactory);
    addDateTimeFormatEntries(group, "medium", cldrFactory);
    addDateTimeFormatEntries(group, "short", cldrFactory);
  }

  public void addEntries(String category, Factory cldrFactory, String prefix,
      String tag, String keyAttribute) {
    for (GwtLocale locale : allLocales.keySet()) {
      addEntries(category, locale, cldrFactory, prefix, tag, keyAttribute);
    }
  }

  public void addEntries(String category, GwtLocale locale, Factory cldrFactory,
      String prefix, String tag, String keyAttribute) {
    Map<String, String> map = getMap(category, locale);
    CLDRFile cldr = cldrFactory.make(allLocales.get(locale), true);
    XPathParts parts = new XPathParts();
    Iterator<String> iterator = cldr.iterator(prefix);
    while (iterator.hasNext()) {
      String path = iterator.next();
      String fullXPath = cldr.getFullXPath(path);
      if (fullXPath == null) {
        fullXPath = path;
      }
      parts.set(fullXPath);
      if (parts.containsAttribute("alt")) {
        // ignore alternate strings
        continue;
      }
      Map<String, String> attr = parts.findAttributes(tag);
      if (attr == null) {
        continue;
      }
      String key = attr.get(keyAttribute);
      String value = cldr.getStringValue(path);
      boolean draft = parts.containsAttribute("draft");
      if (!draft || !map.containsKey(key)) {
        map.put(key, value);
      }
    }
  }

  public void addEntry(String category, GwtLocale locale, String key,
      String value) {
    Map<String, String> map = getMap(category, locale);
    map.put(key, value);
  }

  /**
   * @param period "month", "day", "quarter", "dayPeriod", 
   * @param cldrFactory
   */
  public void addNameEntries(String period, Factory cldrFactory) {
    addEntries(period + "-abbrev", cldrFactory, "//ldml/dates/calendars/calendar[@type=\"gregorian\"]/" + period
        + "s/" + period + "Context[@type=\"format\"]/" + period
        + "Width[@type=\"abbreviated\"]", period, "type");
    addEntries(period + "-narrow", cldrFactory, "//ldml/dates/calendars/calendar[@type=\"gregorian\"]/" + period
        + "s/" + period + "Context[@type=\"format\"]/" + period
        + "Width[@type=\"narrow\"]", period, "type");
    addEntries(period + "-wide", cldrFactory, "//ldml/dates/calendars/calendar[@type=\"gregorian\"]/" + period
        + "s/" + period + "Context[@type=\"format\"]/" + period
        + "Width[@type=\"wide\"]", period, "type");
    addEntries(period + "-sa-abbrev", cldrFactory, "//ldml/dates/calendars/calendar[@type=\"gregorian\"]/" + period
        + "s/" + period + "Context[@type=\"stand-alone\"]/" + period
        + "Width[@type=\"abbreviated\"]", period, "type");
    addEntries(period + "-sa-narrow", cldrFactory, "//ldml/dates/calendars/calendar[@type=\"gregorian\"]/" + period
        + "s/" + period + "Context[@type=\"stand-alone\"]/" + period
        + "Width[@type=\"narrow\"]", period, "type");
    addEntries(period + "-sa-wide", cldrFactory, "//ldml/dates/calendars/calendar[@type=\"gregorian\"]/" + period
        + "s/" + period + "Context[@type=\"stand-alone\"]/" + period
        + "Width[@type=\"wide\"]", period, "type");
  }

  /**
   * Add entries from territory-oriented CLDR data.
   * 
   * @param category category to store resulting data under
   * @param cldrFactory
   * @param regionLanguageData
   * @param prefix the XPath prefix to iterate through
   * @param tag the tag to load
   * @param keyAttribute the attribute in the tag to use as the key
   */
  public void addTerritoryEntries(String category, Factory cldrFactory,
      RegionLanguageData regionLanguageData, String prefix, String tag,
      String keyAttribute) {
    CLDRFile supp = cldrFactory.make("supplementalData", true);
    Map<String, String> map = new HashMap<String, String>();
    XPathParts parts = new XPathParts();
    Iterator<String> iterator = supp.iterator(prefix);
    while (iterator.hasNext()) {
      String path = iterator.next();
      parts.set(supp.getFullXPath(path));
      Map<String, String> attr = parts.findAttributes(tag);
      if (attr == null || attr.get("alt") != null) {
        continue;
      }
      String key = attr.get(keyAttribute);
      String territories = attr.get("territories");
      String draft = attr.get("draft");
      for (String territory : territories.split(" ")) {
        if (draft == null || !map.containsKey(territory)) {
          map.put(territory, key);
        }
      }
    }

    if (regionLanguageData != null) {
      // find the choice used by most literate speakers of each language
      // based on region-based preferences.
      for (GwtLocale locale : allLocales.keySet()) {
        if (locale.getRegion() != null || locale.getLanguage() == null) {
          // skip any that have a region or don't have a language
          continue;
        }
        String language = locale.getAsString();
        Map<String, Double> langMap = new HashMap<String, Double>();
        for (RegionLanguageData.RegionPopulation langData
            : regionLanguageData.getRegions(language)) {
          String region = langData.getRegion();
          GwtLocale regionLocale = localeFactory.fromString(language + "_"
              + region);
          String day = getTerritoryData(regionLocale, map);
          if (day != null) {
            Double pop = langMap.get(day);
            if (pop == null) {
              pop = 0.0;
            }
            pop += langData.getLiteratePopulation();
            langMap.put(day, pop);
          }
        }
        double max = 0;
        String maxDay = null;
        for (Map.Entry<String, Double> entry : langMap.entrySet()) {
          if (entry.getValue() > max) {
            max = entry.getValue();
            maxDay = entry.getKey();
          }
        }
        if (maxDay != null) {
          addEntry(category, locale, tag, maxDay);
        }
      }
    }

    // map locales to territory data
    for (GwtLocale locale : allLocales.keySet()) {
      if (getEntry(category, locale, tag) != null) {
        // don't override what we set above
        continue;
      }
      String day = getTerritoryData(locale, map);
      if (day != null) {
        addEntry(category, locale, tag, day);
      }
    }
  }

  /**
   * Add a redirect entry for each locale where all entries in the standalone
   * category match those in the base category.
   * 
   * @param baseCategory
   * @param standaloneCategory
   */
  public void computeRedirects(String baseCategory,
      String standaloneCategory) {
    for (GwtLocale locale : allLocales.keySet()) {
      MapKey baseKey = new MapKey(baseCategory, locale);
      MapKey standaloneKey = new MapKey(standaloneCategory, locale);
      Map<String, String> baseMap = maps.get(baseKey);
      Map<String, String> standaloneMap = maps.get(standaloneKey);
      if (baseMap != null && standaloneMap != null && (standaloneMap.isEmpty()
          || baseMap.equals(standaloneMap))) {
        addEntry(standaloneCategory + "-redirect", locale, "redirect", "yes");
      }
    }
  }

  /**
   * Copy data from one locale to another.
   * 
   * @param srcLocaleName source locale name
   * @param destLocaleName destination locale name
   * @param categories list of categories to copy
   */
  public void copyLocaleData(String srcLocaleName, String destLocaleName,
      String... categories) {
    GwtLocale src = localeFactory.fromString(srcLocaleName);
    GwtLocale dest = localeFactory.fromString(destLocaleName);
    for (String category : categories) {
      Map<String, String> srcMap = maps.get(new MapKey(category, src));
      if (srcMap == null || srcMap.isEmpty()) {
        continue;
      }
      Map<String, String> destMap = getMap(category, dest);
      destMap.putAll(srcMap);
    }
  }

  public Map<String, Map<String, String>> getAllEntries(String localeName) {
    GwtLocale locale = localeFactory.fromString(localeName);
    Map<String, Map<String, String>> result = new HashMap<String, Map<String, String>>();
    for (Map.Entry<MapKey, Map<String, String>> entry : maps.entrySet()) {
      Map<String, String> map = entry.getValue();
      if (entry.getKey().getLocale().equals(locale) && !map.isEmpty()) {
        result.put(entry.getKey().getCategory(),
            Collections.unmodifiableMap(entry.getValue()));
      }
    }
    return result;
  }

  /**
   * @return all locales present in the CLDR data.
   */
  public Set<GwtLocale> getAllLocales() {
    return Collections.unmodifiableSet(allLocales.keySet());
  }

  /**
   * Return all entries in a given category and locale.
   * 
   * @param category
   * @param locale
   * @return map of keys to localized values
   */
  public Map<String, String> getEntries(String category, GwtLocale locale) {
    MapKey mapKey = new MapKey(category, locale);
    Map<String, String> map = maps.get(mapKey);
    if (map == null) {
      return Collections.emptyMap();
    }
    return Collections.unmodifiableMap(map);
  }

  /**
   * Return a single value.
   * 
   * @param category
   * @param locale
   * @param key
   * @return the requested value, or null if not present
   */
  public String getEntry(String category, GwtLocale locale, String key) {
    MapKey mapKey = new MapKey(category, locale);
    Map<String, String> map = maps.get(mapKey);
    if (map == null) {
      return null;
    }
    return map.get(key);
  }

  /**
   * @param localeName
   * @return GwtLocale instance for CLDR locale
   */
  public GwtLocale getGwtLocale(String localeName) {
    return "root".equals(localeName) ? localeFactory.getDefault()
        : localeFactory.fromString(localeName);
  }

  /**
   * @return all locales that have some data associated with them.
   */
  public Set<GwtLocale> getNonEmptyLocales() {
    Set<GwtLocale> result = new HashSet<GwtLocale>();
    for (Map.Entry<MapKey, Map<String, String>> entry : maps.entrySet()) {
      Map<String, String> map = entry.getValue();
      if (map.isEmpty()) {
        continue;
      }
      result.add(entry.getKey().getLocale());
    }
    return result;
  }

  /**
   * @return all locales that have some data associated with them in the
   *     specified category.
   */
  public Set<GwtLocale> getNonEmptyLocales(String category) {
    Set<GwtLocale> result = new HashSet<GwtLocale>();
    for (Map.Entry<MapKey, Map<String, String>> entry : maps.entrySet()) {
      Map<String, String> map = entry.getValue();
      if (!category.equals(entry.getKey().category) || map.isEmpty()) {
      continue;
      }
      result.add(entry.getKey().getLocale());
    }
    return result;
  }

  /**
   * Return the nearest ancestor locale of the supplied locale which has any
   * values present.
   *
   * @param locale
   * @return GwtLocale of nearest ancestor
   */
  public GwtLocale inheritsFrom(GwtLocale locale) {
    GwtLocale parent = inheritsFrom.get(locale); 
    while (parent != null && parent != defaultLocale) {
      for (Map.Entry<MapKey, Map<String, String>> entry : maps.entrySet()) {
        if (entry.getKey().getLocale().equals(parent)) {
          Map<String, String> map = entry.getValue();
          if (!map.isEmpty()) {
            return parent;
          }
        }
      }
      parent = inheritsFrom.get(parent);
    }
    return parent;
  }

  /**
   * Return the nearest ancestor locale of the supplied locale which has any
   * values present in the specified category.
   *
   * @param category
   * @param locale
   * @return GwtLocale of nearest ancestor with the specified category
   */
  public GwtLocale inheritsFrom(String category, GwtLocale locale) {
    GwtLocale parent = inheritsFrom.get(locale); 
    while (parent != null && parent != defaultLocale) {
      Map<String, String> map = getMap(category, parent);
      if (!map.isEmpty()) {
            return parent;
      }
      parent = inheritsFrom.get(parent);
    }
    return parent;
  }

  /**
   * Remove locale entries that completely duplicate their parent.
   */
  public void removeCompleteDuplicates() {
    removeCompleteDuplicates(null);
  }

  /**
   * Remove locale entries that completely duplicate their parent.
   *
   * @param matchCategory
   */
  public void removeCompleteDuplicates(String matchCategory) {
    MapKey[] keys = getSortedMapKeys();
    for (MapKey key : keys) {
      String category = key.getCategory();
      if (matchCategory != null && !matchCategory.equals(category)) {
        continue;
      }
      GwtLocale locale = key.getLocale();
      GwtLocale parent = inheritsFrom(category, locale);
      if (parent == null) {
        continue;
      }
      MapKey parentKey = key.inNewLocale(parent);
      Map<String, String> parentMap = maps.get(parentKey);
      if (parentMap == null) {
        continue;
      }
      Map<String, String> map = maps.get(key);
      boolean allMatch = true;
      for (Map.Entry<String, String> entry : map.entrySet()) {
        if (!entry.getValue().equals(parentMap.get(entry.getKey()))) {
          allMatch = false;
          break;
        }
      }
      if (allMatch) {
        maps.remove(key);
      }
    }
  }

  /**
   * Remove entries that are duplicates of the entries in the parent locale.
   */
  public void removeDuplicates() {
    removeDuplicates(null);
  }

  /**
   * Remove entries that are duplicates of the entries in the parent locale.
   *
   * @param matchCategory
   */
  public void removeDuplicates(String matchCategory) {
    MapKey[] keys = getSortedMapKeys();
    for (MapKey key : keys) {
      String category = key.getCategory();
      if (matchCategory != null && !matchCategory.equals(category)) {
        continue;
      }
      GwtLocale locale = key.getLocale();
      GwtLocale parent = inheritsFrom(category, locale);
      if (parent == null) {
        continue;
      }
      MapKey parentKey = key.inNewLocale(parent);
      Map<String, String> parentMap = maps.get(parentKey);
      if (parentMap == null) {
        continue;
      }
      Map<String, String> map = maps.get(key);
      Iterator<Map.Entry<String, String>> it = map.entrySet().iterator();
      while (it.hasNext()) {
        Map.Entry<String, String> entry = it.next();
        String value = entry.getValue();
        if (value == null || value.equals(parentMap.get(entry.getKey()))) {
          it.remove();
        }
      }
    }
  }

  /**
   * Remove entries in the specified category and locale which match any of
   * the supplied keys.
   * 
   * @param category
   * @param locale
   * @param keys
   */
  public void removeEntries(String category, GwtLocale locale,
      Collection<String> keys) {
    Map<String, String> map = getMap(category, locale);
    map.keySet().removeAll(keys);
  }

  /**
   * Remove a single entry, if present.
   * 
   * @param category
   * @param locale
   * @param key
   */
  public void removeEntry(String category, GwtLocale locale, String key) {
    Map<String, String> map = getMap(category, locale);
    map.remove(key);
  }

  /**
   * Reset state, forgetting any cached values.
   */
  public void reset() {
    maps.clear();
  }

  private void addAttributeEntries(String category, Factory cldrFactory,
      String prefix, String tag, String key, String attribute) {
    for (GwtLocale locale : allLocales.keySet()) {
      addAttributeEntry(category, locale, cldrFactory, prefix, tag, key,
          attribute);
    }
  }

  /**
   * Add currency entries for the specified locale.  If this locale is not the
   * default locale, also add default entries into the default locale to make
   * sure it has entries for any currency present in any locale.  Note that
   * this means that the default locale must be processed last.
   * 
   * @param category
   * @param locale
   * @param cldrFactory
   * @param currencyFractions map of currency fraction data extracted from
   *     locale-independent data
   * @param defaultCurrencyFraction
   * @param stillInUse
   */
  private void addCurrencyEntries(String category, GwtLocale locale,
      Factory cldrFactory, Map<String, Integer> currencyFractions,
      int defaultCurrencyFraction, Set<String> stillInUse) {
    Map<String, String> outputMap = getMap(category, locale);
    Map<String, String> defaultMap = null;
    if (!locale.isDefault()) {
      defaultMap = getMap(category, localeFactory.getDefault());
    }
    Map<String, Currency> tempMap = new HashMap<String, Currency>();
    CLDRFile cldr = cldrFactory.make(allLocales.get(locale), true);
    XPathParts parts = new XPathParts();
    Iterator<String> iterator = cldr.iterator(
        "//ldml/numbers/currencies");
    while (iterator.hasNext()) {
      String path = iterator.next();
      path = cldr.getFullXPath(path);
      parts.set(path);
      Map<String, String> attr = parts.findAttributes("currency");
      if (attr == null) {
        continue;
      }
      String currencyCode = attr.get("type");
      Currency currency = tempMap.get(currencyCode);
      if (currency == null) {
        currency = new Currency(currencyCode);
        if (currencyFractions.containsKey(currencyCode)) {
          currency.setDecimalDigits(currencyFractions.get(currencyCode));
        } else {
          currency.setDecimalDigits(defaultCurrencyFraction);
        }
        currency.setInUse(stillInUse.contains(currencyCode));
        tempMap.put(currencyCode, currency);
      }
      String field = parts.getElement(4);
      String value = cldr.getStringValue(path);
      attr = parts.findAttributes(field);
      if (attr == null) {
        attr = Collections.emptyMap();
      }
      String draft = attr.get("draft");
      if ("symbol".equalsIgnoreCase(field)) {
        currency.setSymbol(value);
      } else if ("displayName".equalsIgnoreCase(field)) {
        if (attr.get("count") != null) {
          // We don't care about currency "count" names
          continue;
        }
        if (draft == null || currency.getDisplayName() == null) {
          // don't override non-draft name with draft name
          currency.setDisplayName(value);
        }
      } else if ("pattern".equalsIgnoreCase(field)) {
        currency.setPattern(value);
      } else if ("decimal".equalsIgnoreCase(field)) {
        currency.setDecimalSeparator(value);
      } else if ("group".equalsIgnoreCase(field)) {
        currency.setGroupingSeparator(value);
      } else {
        System.err.println("Ignoring unknown field \"" + field
            + "\" on currency data for \"" + currencyCode + "\"");
      }
    }
    for (Currency currency : tempMap.values()) {
      String code = currency.getCode();
      outputMap.put(code, encodeCurrencyData(currency));
      if (defaultMap != null) {
        // Don't copy language-specific things to default
        currency.setDisplayName(code);
        currency.setSymbol(null);
        defaultMap.put(code, encodeCurrencyData(currency));
      }
    }
  }

  private void addDateTimeFormatEntries(String group, String length,
      Factory cldrFactory) {
    addEntries(group, cldrFactory,
        "//ldml/dates/calendars/calendar[@type=\"gregorian\"]/" + group
        + "Formats/" + group + "FormatLength"
        + "[@type=\"" + length + "\"]/" + group + "Format[@type=\"standard\"]"
        + "/pattern[@type=\"standard\"]", group + "FormatLength", "type");
  }

  private void buildInheritsFrom() {
    for (GwtLocale locale : allLocales.keySet()) {
      GwtLocale parent = null;
      for (GwtLocale search : locale.getInheritanceChain()) {
        if (!search.equals(locale) && allLocales.containsKey(search)) {
          parent = search;
          break;
        }
      }
      inheritsFrom.put(locale, parent);
    }
  }

  /**
   * Build a depth map which is used to sort locales such that more derived
   * locales are processed before less derived locales.
   */
  private void buildLocaleDepth() {
    Set<GwtLocale> remaining = new HashSet<GwtLocale>(allLocales.keySet());
    localeDepth.put(defaultLocale, 0);
    remaining.remove(defaultLocale);
    while (!remaining.isEmpty()) {
      Set<GwtLocale> nextPass = new HashSet<GwtLocale>();
      for (GwtLocale locale : remaining) {
        GwtLocale parent = inheritsFrom.get(locale);
        if (localeDepth.containsKey(parent)) {
          int depth = localeDepth.get(parent);
          localeDepth.put(locale, depth + 1);
        } else {
          nextPass.add(locale);
        }
      }
      remaining = nextPass;
    }
  }

  /**
   * Encode the currency data as needed by CurrencyListGenerator.
   * 
   * @param currency
   * @return a string containing the property file entry for the specified
   *     currency
   */
  private String encodeCurrencyData(Currency currency) {
    StringBuilder buf = new StringBuilder();
    String skipped = "";
    String displayName = currency.getDisplayName();
    if (displayName == null) {
      displayName = currency.getCode();
    }
    buf.append(displayName);
    String symbol = currency.getSymbol();
    if (symbol != null && !currency.getCode().equals(symbol)) {
      buf.append('|');
      buf.append(symbol);
      skipped = "";
    } else {
      skipped = "|";
    }
    if (currency.getDecimalDigits() != 2) {
      buf.append(skipped).append('|');
      buf.append(currency.getDecimalDigits());
      skipped = "";
    } else {
      skipped += "|";
    }
    if (!currency.isInUse()) {
      buf.append(skipped).append("|1");
    }
    return buf.toString();
  }

  /**
   * Get a map for a given class/locale combination.
   * @param category 
   * @param locale
   * 
   * @return map for the specified class/locale
   */
  private Map<String, String> getMap(String category, GwtLocale locale) {
    MapKey mapKey = new MapKey(category, locale);
    Map<String, String> map = maps.get(mapKey);
    if (map == null) {
      map = new HashMap<String, String>();
      maps.put(mapKey, map);
    }
    return map;
  }

  /**
   * @return an array of map keys, ordered from most derived to least derived.
   */
  private MapKey[] getSortedMapKeys() {
    Set<MapKey> keySet = maps.keySet();
    MapKey[] keys = keySet.toArray(new MapKey[keySet.size()]);
    Arrays.sort(keys, new Comparator<MapKey>() {
      private final Comparator<GwtLocale> depthComparator = new LocaleComparator();
      
      public int compare(MapKey a, MapKey b) {
        return depthComparator.compare(a.getLocale(), b.getLocale());
      }
    });
    return keys;
  }
}
