package org.unicode.cldr.util; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Set; import com.google.common.collect.Multimap; import com.ibm.icu.impl.Relation; import com.ibm.icu.util.TimeZone; public class Containment { private static final SupplementalDataInfo supplementalData = SupplementalDataInfo.getInstance(); static final Relation containmentCore = supplementalData .getContainmentCore(); static final Set continents = containmentCore.get("001"); static final Set subcontinents; static { LinkedHashSet temp = new LinkedHashSet(); for (String continent : continents) { temp.addAll(containmentCore.get(continent)); } subcontinents = Collections.unmodifiableSet(temp); } static final Relation containmentFull = supplementalData .getTerritoryToContained(); static final Relation containedToContainer = (Relation) Relation .of(new HashMap>(), HashSet.class) .addAllInverted(containmentFull) .freeze(); static final Relation leavesToContainers; static { leavesToContainers = Relation .of(new HashMap>(), HashSet.class); // for each container, get all of its leaf nodes Set containers = supplementalData.getContainers(); for (String s : containers) { HashSet leaves = new HashSet(); addLeaves(s, leaves, containers); leavesToContainers.putAll(leaves, s); } leavesToContainers.freeze(); // for (Entry> e : leavesToContainers.keyValuesSet()) { // System.out.println(e.getKey() + " " + e.getValue()); // } } static final Relation containedToContainerCore = (Relation) Relation .of(new HashMap>(), HashSet.class) .addAllInverted(containmentCore) .freeze(); static final Map toOrder = new LinkedHashMap(); static int level = 0; static int order; static { initOrder("001"); // Special cases. Cyprus is because it is in the wrong location because it gets picked up in the EU. resetOrder("003", "021"); resetOrder("419", "005"); resetOrder("CY", "BH"); } // static Map zone2country = StandardCodes.make().getZoneToCounty(); public static String getRegionFromZone(String tzid) { if ("Etc/Unknown".equals(tzid)) { return "001"; } try { return TimeZone.getRegion(tzid); } catch (IllegalArgumentException e) { return "ZZ"; } // return zone2country.get(source0); } private static void addLeaves(String s, Set target, Set nonLeaf) { Set contained = supplementalData.getContained(s); if (contained == null) { return; } for (String child : contained) { if (!nonLeaf.contains(child)) { target.add(child); } else { addLeaves(child, target, nonLeaf); } } } public static String getContainer(String territory) { Set containers = containedToContainerCore.get(territory); if (containers == null) { containers = containedToContainer.get(territory); } String container = containers != null ? containers.iterator().next() : territory.equals("001") ? "001" : "ZZ"; return container; } /** * Return all the containers, including deprecated. * @param territory * @return */ public static Set getContainers(String territory) { return containedToContainer.get(territory); } /** * Return the Continent containing the territory, or 001 if the territory is 001, otherwise ZZ * * @param territory */ public static String getContinent(String territory) { while (true) { if (territory == null || territory.equals("001") || territory.equals("ZZ") || continents.contains(territory)) { return territory; } String newTerritory = getContainer(territory); if (newTerritory == null) { return territory; } territory = newTerritory; } } /** * Return the Subcontinent containing the territory, or the continent if it is a continent, or * 001 if it is 001, otherwise ZZ. * * @param territory */ public static String getSubcontinent(String territory) { while (true) { if (territory.equals("001") || territory.equals("ZZ") || continents.contains(territory) || subcontinents.contains(territory)) { return territory; } territory = getContainer(territory); } } public static int getOrder(String territory) { Integer temp = toOrder.get(territory); return temp != null ? temp.intValue() : level; } private static void initOrder(String territory) { if (!toOrder.containsKey(territory)) { toOrder.put(territory, ++level); } Set contained = containmentFull.get(territory); if (contained == null) { return; } for (String subitem : contained) { if (!toOrder.containsKey(subitem)) { toOrder.put(subitem, ++level); } } for (String subitem : contained) { initOrder(subitem); } } private static void resetOrder(String newTerritory, String oldTerritory) { // final Integer newOrder = toOrder.get(newTerritory); // if (newOrder != null) { // throw new IllegalArgumentException(newTerritory + " already defined as " + newOrder); // } final Integer oldOrder = toOrder.get(oldTerritory); if (oldOrder == null) { throw new IllegalArgumentException(oldTerritory + " not yet defined"); } toOrder.put(newTerritory, oldOrder); } public Set getContinents() { return continents; } public Set getSubontinents() { return subcontinents; } public static Set> getAllDirected(Multimap multimap, String lang) { LinkedHashSet> result = new LinkedHashSet>(); getAllDirected(multimap, lang, new ArrayList(), result); return result; } private static void getAllDirected(Multimap multimap, String lang, ArrayList target, Set> targets) { target.add(lang); Collection parents = multimap.get(lang); int size = parents.size(); if (size == 0) { targets.add(target); } else if (size == 1) { for (String parent : parents) { getAllDirected(multimap, parent, target, targets); } } else { for (String parent : parents) { getAllDirected(multimap, parent, (ArrayList) target.clone(), targets); } } } /** * For each leaf region (eg "CO"), return all containers [019, 419, 005, 001] * @param leaf * @return */ public static Set leafToContainer(String leaf) { return leavesToContainers.get(leaf); } public static boolean isLeaf(String region) { return leavesToContainers.containsKey(region); } }