blob: a4aeb829cf056fa68fe2abeb24417da8266387d6 [file] [log] [blame]
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<String, String> containmentCore = supplementalData
.getContainmentCore();
static final Set<String> continents = containmentCore.get("001");
static final Set<String> subcontinents;
static {
LinkedHashSet<String> temp = new LinkedHashSet<String>();
for (String continent : continents) {
temp.addAll(containmentCore.get(continent));
}
subcontinents = Collections.unmodifiableSet(temp);
}
static final Relation<String, String> containmentFull = supplementalData
.getTerritoryToContained();
static final Relation<String, String> containedToContainer = (Relation<String, String>) Relation
.of(new HashMap<String, Set<String>>(),
HashSet.class)
.addAllInverted(containmentFull)
.freeze();
static final Relation<String, String> leavesToContainers;
static {
leavesToContainers = Relation
.of(new HashMap<String, Set<String>>(),
HashSet.class);
// for each container, get all of its leaf nodes
Set<String> containers = supplementalData.getContainers();
for (String s : containers) {
HashSet<String> leaves = new HashSet<String>();
addLeaves(s, leaves, containers);
leavesToContainers.putAll(leaves, s);
}
leavesToContainers.freeze();
// for (Entry<String, Set<String>> e : leavesToContainers.keyValuesSet()) {
// System.out.println(e.getKey() + " " + e.getValue());
// }
}
static final Relation<String, String> containedToContainerCore = (Relation<String, String>) Relation
.of(new HashMap<String, Set<String>>(),
HashSet.class)
.addAllInverted(containmentCore)
.freeze();
static final Map<String, Integer> toOrder = new LinkedHashMap<String, Integer>();
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<String, String> 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<String> target, Set<String> nonLeaf) {
Set<String> 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<String> 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<String> 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<String> 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<String> getContinents() {
return continents;
}
public Set<String> getSubontinents() {
return subcontinents;
}
public static Set<List<String>> getAllDirected(Multimap<String, String> multimap, String lang) {
LinkedHashSet<List<String>> result = new LinkedHashSet<List<String>>();
getAllDirected(multimap, lang, new ArrayList<String>(), result);
return result;
}
private static void getAllDirected(Multimap<String, String> multimap, String lang, ArrayList<String> target, Set<List<String>> targets) {
target.add(lang);
Collection<String> 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<String>) target.clone(), targets);
}
}
}
/**
* For each leaf region (eg "CO"), return all containers [019, 419, 005, 001]
* @param leaf
* @return
*/
public static Set<String> leafToContainer(String leaf) {
return leavesToContainers.get(leaf);
}
public static boolean isLeaf(String region) {
return leavesToContainers.containsKey(region);
}
}