12ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller/* GENERATED SOURCE. DO NOT MODIFY. */
2f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert// © 2016 and later: Unicode, Inc. and others.
3f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert// License & terms of use: http://www.unicode.org/copyright.html#License
42ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller/*
52ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller **********************************************************************
62ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * Copyright (c) 2002-2015, International Business Machines
72ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * Corporation and others.  All Rights Reserved.
82ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller **********************************************************************
92ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * Author: Mark Davis
102ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller **********************************************************************
112ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller */
122ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fullerpackage android.icu.impl;
132ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
142ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fullerimport java.lang.reflect.Constructor;
152ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fullerimport java.util.Arrays;
162ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fullerimport java.util.Collection;
172ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fullerimport java.util.Collections;
182ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fullerimport java.util.Comparator;
192ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fullerimport java.util.HashMap;
202ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fullerimport java.util.LinkedHashSet;
212ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fullerimport java.util.Map;
222ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fullerimport java.util.Map.Entry;
232ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fullerimport java.util.Set;
242ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
252ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fullerimport android.icu.util.Freezable;
262ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
272ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller/**
282ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * A Relation is a set of mappings from keys to values.
292ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * Unlike Map, there is not guaranteed to be a single value per key.
302ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * The Map-like APIs return collections for values.
312ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @author medavis
32836e6b40a94ec3fb7545a76cb072960442b7eee9Neil Fuller * @hide Only a subset of ICU is exposed in Android
331537b2f39245c07b00aa78c3600f7aebcb172490Neil Fuller
342ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller */
352ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fullerpublic class Relation<K, V> implements Freezable<Relation<K,V>> { // TODO: add , Map<K, Collection<V>>, but requires API changes
362ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    private Map<K, Set<V>> data;
372ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
382ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    Constructor<? extends Set<V>> setCreator;
392ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    Object[] setComparatorParam;
402ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
412ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public static <K, V> Relation<K, V> of(Map<K, Set<V>> map, Class<?> setCreator) {
422ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return new Relation<K, V>(map, setCreator);
432ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
442ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
452ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public static <K,V> Relation<K, V> of(Map<K, Set<V>> map, Class<?> setCreator, Comparator<V> setComparator) {
462ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return new Relation<K, V>(map, setCreator, setComparator);
472ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
482ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
492ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public Relation(Map<K, Set<V>> map, Class<?> setCreator) {
502ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        this(map, setCreator, null);
512ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
522ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
532ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    @SuppressWarnings("unchecked")
542ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public Relation(Map<K, Set<V>> map, Class<?> setCreator, Comparator<V> setComparator) {
552ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        try {
562ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            setComparatorParam = setComparator == null ? null : new Object[]{setComparator};
572ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            if (setComparator == null) {
582ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                this.setCreator = ((Class<? extends Set<V>>)setCreator).getConstructor();
592ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                this.setCreator.newInstance(setComparatorParam); // check to make sure compiles
602ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            } else {
612ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                this.setCreator = ((Class<? extends Set<V>>)setCreator).getConstructor(Comparator.class);
62f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert                this.setCreator.newInstance(setComparatorParam); // check to make sure compiles
632ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            }
642ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            data = map == null ? new HashMap<K, Set<V>>() : map;
652ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        } catch (Exception e) {
662ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            throw (RuntimeException) new IllegalArgumentException("Can't create new set").initCause(e);
672ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
682ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
692ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
702ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public void clear() {
712ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        data.clear();
722ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
732ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
742ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public boolean containsKey(Object key) {
752ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return data.containsKey(key);
762ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
772ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
782ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public boolean containsValue(Object value) {
792ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        for (Set<V> values : data.values()) {
802ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            if (values.contains(value)) {
812ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                return true;
822ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            }
832ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
842ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return false;
852ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
862ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
872ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public final Set<Entry<K, V>> entrySet() {
882ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return keyValueSet();
892ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
90f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert
912ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public Set<Entry<K, Set<V>>> keyValuesSet() {
922ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return data.entrySet();
932ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
94f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert
952ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public Set<Entry<K, V>> keyValueSet() {
962ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        Set<Entry<K, V>> result = new LinkedHashSet<Entry<K, V>>();
972ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        for (K key : data.keySet()) {
982ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            for (V value : data.get(key)) {
992ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                result.add(new SimpleEntry<K, V>(key, value));
1002ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            }
1012ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
1022ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return result;
1032ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
1042ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
105f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    @Override
1062ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public boolean equals(Object o) {
1072ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        if (o == null)
1082ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            return false;
1092ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        if (o.getClass() != this.getClass())
1102ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            return false;
1112ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return data.equals(((Relation<?, ?>) o).data);
1122ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
1132ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
1142ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    //  public V get(Object key) {
1152ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    //      Set<V> set = data.get(key);
1162ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    //      if (set == null || set.size() == 0)
1172ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    //        return null;
1182ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    //      return set.iterator().next();
1192ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    //  }
1202ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
1212ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public Set<V> getAll(Object key) {
1222ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return data.get(key);
1232ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
1242ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
1252ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public Set<V> get(Object key) {
1262ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return data.get(key);
1272ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
1282ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
129f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    @Override
1302ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public int hashCode() {
1312ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return data.hashCode();
1322ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
1332ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
1342ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public boolean isEmpty() {
1352ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return data.isEmpty();
1362ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
1372ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
1382ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public Set<K> keySet() {
1392ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return data.keySet();
1402ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
1412ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
1422ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public V put(K key, V value) {
1432ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        Set<V> set = data.get(key);
1442ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        if (set == null) {
1452ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            data.put(key, set = newSet());
1462ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
1472ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        set.add(value);
1482ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return value;
1492ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
1502ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
1512ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public V putAll(K key, Collection<? extends V> values) {
1522ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        Set<V> set = data.get(key);
1532ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        if (set == null) {
1542ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            data.put(key, set = newSet());
1552ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
1562ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        set.addAll(values);
1572ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return values.size() == 0 ? null : values.iterator().next();
1582ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
1592ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
1602ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public V putAll(Collection<K> keys, V value) {
1612ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        V result = null;
1622ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        for (K key : keys) {
1632ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            result = put(key, value);
1642ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
1652ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return result;
1662ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
1672ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
1682ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    private Set<V> newSet() {
1692ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        try {
170f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert            return setCreator.newInstance(setComparatorParam);
1712ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        } catch (Exception e) {
1722ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            throw (RuntimeException) new IllegalArgumentException("Can't create new set").initCause(e);
1732ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
1742ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
1752ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
1762ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public void putAll(Map<? extends K, ? extends V> t) {
177f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        for (Map.Entry<? extends K, ? extends V> entry : t.entrySet()) {
178f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert            put(entry.getKey(), entry.getValue());
1792ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
1802ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
1812ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
1822ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public void putAll(Relation<? extends K, ? extends V> t) {
1832ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        for (K key : t.keySet()) {
1842ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            for (V value : t.getAll(key)) {
1852ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                put(key, value);
1862ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            }
1872ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
1882ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
1892ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
1902ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public Set<V> removeAll(K key) {
1912ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        try {
1922ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            return data.remove(key);
1932ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        } catch (NullPointerException e) {
1942ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            return null; // data doesn't allow null, eg ConcurrentHashMap
1952ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
1962ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
1972ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
1982ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public boolean remove(K key, V value) {
1992ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        try {
2002ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            Set<V> set = data.get(key);
2012ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            if (set == null) {
2022ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                return false;
2032ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            }
2042ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            boolean result = set.remove(value);
2052ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            if (set.size() == 0) {
2062ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                data.remove(key);
2072ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            }
2082ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            return result;
2092ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        } catch (NullPointerException e) {
2102ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            return false; // data doesn't allow null, eg ConcurrentHashMap
2112ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
2122ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
2132ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
2142ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public int size() {
2152ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return data.size();
2162ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
2172ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
2182ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public Set<V> values() {
2192ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return values(new LinkedHashSet<V>());
2202ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
2212ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
2222ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public <C extends Collection<V>> C values(C result) {
2232ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        for (Entry<K, Set<V>> keyValue : data.entrySet()) {
2242ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            result.addAll(keyValue.getValue());
2252ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
2262ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return result;
2272ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
2282ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
229f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    @Override
2302ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public String toString() {
2312ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return data.toString();
2322ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
2332ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
2342ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    static class SimpleEntry<K, V> implements Entry<K, V> {
2352ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        K key;
2362ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
2372ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        V value;
2382ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
2392ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        public SimpleEntry(K key, V value) {
2402ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            this.key = key;
2412ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            this.value = value;
2422ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
2432ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
2442ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        public SimpleEntry(Entry<K, V> e) {
2452ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            this.key = e.getKey();
2462ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            this.value = e.getValue();
2472ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
2482ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
249f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        @Override
2502ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        public K getKey() {
2512ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            return key;
2522ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
2532ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
254f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        @Override
2552ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        public V getValue() {
2562ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            return value;
2572ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
2582ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
259f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        @Override
2602ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        public V setValue(V value) {
2612ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            V oldValue = this.value;
2622ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            this.value = value;
2632ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            return oldValue;
2642ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
2652ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
2662ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
2672ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public Relation<K,V> addAllInverted(Relation<V,K> source) {
2682ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        for (V value : source.data.keySet()) {
2692ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            for (K key : source.data.get(value)) {
2702ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                put(key, value);
2712ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            }
2722ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
2732ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return this;
2742ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
2752ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
2762ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public Relation<K,V> addAllInverted(Map<V,K> source) {
277f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        for (Map.Entry<V,K> entry : source.entrySet()) {
278f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert            put(entry.getValue(), entry.getKey());
2792ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
2802ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return this;
2812ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
2822ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
2832ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    volatile boolean frozen = false;
2842ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
285f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    @Override
2862ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public boolean isFrozen() {
2872ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return frozen;
2882ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
2892ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
290f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    @Override
2912ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public Relation<K, V> freeze() {
2922ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        if (!frozen) {
2932ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            // does not handle one level down, so we do that on a case-by-case basis
2942ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            for (K key : data.keySet()) {
2952ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                data.put(key, Collections.unmodifiableSet(data.get(key)));
2962ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            }
2972ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            // now do top level
2982ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            data = Collections.unmodifiableMap(data);
2992ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            frozen = true;
3002ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
3012ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return this;
3022ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
3032ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
304f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    @Override
3052ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public Relation<K, V> cloneAsThawed() {
3062ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        // TODO do later
3072ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        throw new UnsupportedOperationException();
3082ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
3092ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
3102ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public boolean removeAll(Relation<K, V> toBeRemoved) {
3112ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        boolean result = false;
3122ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        for (K key : toBeRemoved.keySet()) {
3132ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            try {
3142ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                Set<V> values = toBeRemoved.getAll(key);
3152ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                if (values != null) {
3162ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    result |= removeAll(key, values);
3172ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                }
3182ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            } catch (NullPointerException e) {
3192ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                // data doesn't allow null, eg ConcurrentHashMap
3202ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            }
3212ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
3222ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return result;
3232ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
3242ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
3252ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public Set<V> removeAll(K... keys) {
3262ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return removeAll(Arrays.asList(keys));
3272ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
3282ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
3292ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public boolean removeAll(K key, Iterable<V> toBeRemoved) {
3302ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        boolean result = false;
3312ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        for (V value : toBeRemoved) {
3322ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            result |= remove(key, value);
3332ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
3342ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return result;
3352ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
3362ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
3372ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public Set<V> removeAll(Collection<K> toBeRemoved) {
3382ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        Set<V> result = new LinkedHashSet<V>();
3392ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        for (K key : toBeRemoved) {
3402ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            try {
3412ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                final Set<V> removals = data.remove(key);
3422ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                if (removals != null) {
3432ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    result.addAll(removals);
3442ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                }
3452ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            } catch (NullPointerException e) {
3462ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                // data doesn't allow null, eg ConcurrentHashMap
3472ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            }
3482ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
3492ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return result;
3502ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
351f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert}
352