/*
 * 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;
  }
}
