/*
 * 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.XPathParts;

import java.util.ArrayList;
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.List;
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 int rounding;

    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
          && rounding == other.rounding;
    }

    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 int getRounding() {
      return rounding;
    }

    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)
          + 43 * rounding;
    }

    /**
     * @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 setRounding(int rounding) {
      this.rounding = rounding;
    }

    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> {
    @Override
    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
   */
  void addAttributeEntry(String category, GwtLocale locale, InputFactory cldrFactory,
      String path, String tag, String key, String attribute, String defaultValue) {
    Map<String, String> map = getMap(category, locale);
    InputFile cldr = cldrFactory.load(allLocales.get(locale));
    XPathParts parts = new XPathParts();
    String fullPath = cldr.getFullXPath(path);

    Map<String, String> attr = null;
    if (fullPath != null) {
      parts.set(fullPath);
      attr = parts.findAttributes(tag);
    }

    String value;
    if (attr != null) {
      value = attr.get(attribute);
    } else if (defaultValue != null) {
      value = defaultValue;
    } else {
      return;
    }

    map.put(key, value);
  }

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

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

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

  void addEntries(String category, GwtLocale locale, InputFactory cldrFactory, String prefix,
      String tag, String keyAttribute) {
    Map<String, String> map = getMap(category, locale);
    InputFile cldr = cldrFactory.load(allLocales.get(locale));
    XPathParts parts = new XPathParts();
    for (String path : cldr.listPaths(prefix)) {
      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 value = cldr.getStringValue(path);
      boolean draft = parts.containsAttribute("draft");
      String key = keyAttribute != null ? attr.get(keyAttribute) : "value";
      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",
   */
  void addNameEntries(String period, InputFactory 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, InputFactory cldrFactory,
      RegionLanguageData regionLanguageData, String prefix, String tag, String keyAttribute) {
    InputFile supp = cldrFactory.getSupplementalData();
    Map<String, String> map = new HashMap<String, String>();
    XPathParts parts = new XPathParts();
    for (String path : supp.listPaths(prefix)) {
      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.
      summarizeTerritoryEntries(category, regionLanguageData, tag, map);
    }
  }

  void addVersions(InputFactory inputFactory) {
    for (GwtLocale locale : allLocales.keySet()) {
      Map<String, String> map = getMap("version", locale);
      InputFile file = inputFactory.load(allLocales.get(locale));
      XPathParts parts = new XPathParts();
      for (String path : file.listPaths("//ldml/identity")) {
        String fullXPath = file.getFullXPath(path);
        if (fullXPath == null) {
          fullXPath = path;
        }
        parts.set(fullXPath);
        Map<String, String> attr = parts.getAttributes(2);
        if (attr == null) {
          continue;
        }
        for (Map.Entry<String, String> entry : attr.entrySet()) {
          map.put(entry.getKey(), entry.getValue());
        }
      }
    }
  }

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

  /**
   * Returns the keys of all entries in a given cateogry and locale.
   */
  List<String> getKeys(String category, GwtLocale locale) {
    MapKey mapKey = new MapKey(category, locale);

    Map<String, String> map = maps.get(mapKey);
    if (map == null) {
      return new ArrayList<String>();
    }

    ArrayList<String> out = new ArrayList<String>(map.keySet());
    Collections.sort(out);
    return out;
  }

  /**
   * 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 a single value, following locale inheritance.
   * 
   * @param category
   * @param locale
   * @param key
   * @return the requested value, or null if not present
   */
  public String getInheritedEntry(String category, GwtLocale locale, String key) {
    for (GwtLocale search : locale.getCompleteSearchList()) {
      String value = getEntry(category, search, key);
      if (value != null) {
        return value;
      }
    }
    return null;
  }

  /**
   * @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();
      // Ignore version entries
      if ("version".equals(entry.getKey().getCategory()) || map.isEmpty()) {
        continue;
      }
      result.add(entry.getKey().getLocale());
    }
    return result;
  }

  /**
   * @param category 
   * @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()) {
        MapKey key = entry.getKey();
        // Version entries are always present, so ignore them
        if (!"version".equals(key.getCategory()) && key.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();
  }

  /**
   * Summarize values known by territories to bare languages, based on
   * populations using a particular value.
   * 
   * @param category
   * @param key
   * @param values map of region codes to values
   */
  public void summarizeTerritoryEntries(String category, RegionLanguageData regionLanguageData,
      String key, Map<String, String> values) {
    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> valueMap = new HashMap<String, Double>();
      for (RegionLanguageData.RegionPopulation langData : regionLanguageData.getRegions(language)) {
        String region = langData.getRegion();
        GwtLocale regionLocale = localeFactory.fromString(language + "_" + region);
        String value = getTerritoryData(regionLocale, values);
        if (value != null) {
          Double pop = valueMap.get(value);
          if (pop == null) {
            pop = 0.0;
          }
          pop += langData.getLiteratePopulation();
          valueMap.put(value, pop);
        }
      }
      double max = 0;
      String maxValue = null;
      for (Map.Entry<String, Double> entry : valueMap.entrySet()) {
        if (entry.getValue() > max) {
          max = entry.getValue();
          maxValue = entry.getKey();
        }
      }
      if (maxValue != null) {
        addEntry(category, locale, key, maxValue);
      }
    }

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

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

  /**
   * 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 currencyFractions map of currency fraction data extracted from
   *          locale-independent data
   */
  private void addCurrencyEntries(String category, GwtLocale locale, InputFactory inputFactory,
      Map<String, Integer> currencyFractions, int defaultCurrencyFraction, Set<String> stillInUse,
      Map<String, Integer> rounding) {
    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>();
    InputFile file = inputFactory.load(allLocales.get(locale));
    XPathParts parts = new XPathParts();
    for (String path : file.listPaths("//ldml/numbers/currencies")) {
      String fullPath = file.getFullXPath(path);
      if (fullPath == null) {
        fullPath = path;
      }
      parts.set(fullPath);
      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);
        Integer roundingMult = rounding.get(currencyCode);
        if (roundingMult != null) {
          currency.setRounding(roundingMult);
        }
      }
      String field = parts.getElement(4);
      String value = file.getStringValue(fullPath);
      attr = parts.findAttributes(field);
      if (attr == null) {
        attr = Collections.emptyMap();
      }
      String draft = attr.get("draft");
      if ("symbol".equalsIgnoreCase(field)) {
        // Don't overwrite symbol with narrow dollar value
        if (currency.getSymbol() == null || !"narrow".equals(parts.getAttributeValue(4, "alt"))) {
          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, InputFactory 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");
      skipped = "";
    } else {
      skipped += "|";
    }
    if (currency.getRounding() != 0) {
      buf.append(skipped).append("|").append(currency.getRounding());
    }
    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();

      @Override
      public int compare(MapKey a, MapKey b) {
        return depthComparator.compare(a.getLocale(), b.getLocale());
      }
    });
    return keys;
  }
}
