ICU-6824 Update Relation from CLDR
X-SVN-Rev: 26401
This commit is contained in:
parent
cd7e4f87e7
commit
34583efe1c
@ -1,122 +1,291 @@
|
||||
/*
|
||||
**********************************************************************
|
||||
* Copyright (c) 2002-2006, International Business Machines
|
||||
* Corporation and others. All Rights Reserved.
|
||||
**********************************************************************
|
||||
* Author: Mark Davis
|
||||
**********************************************************************
|
||||
*/
|
||||
**********************************************************************
|
||||
* Copyright (c) 2002-2009, International Business Machines
|
||||
* Corporation and others. All Rights Reserved.
|
||||
**********************************************************************
|
||||
* Author: Mark Davis
|
||||
**********************************************************************
|
||||
*/
|
||||
package com.ibm.icu.dev.test.util;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import com.ibm.icu.util.Freezable;
|
||||
|
||||
/**
|
||||
* A Relation is a set of mappings from keys to values.
|
||||
* Unlike Map, there is not guaranteed to be a single value per key.
|
||||
* The Map-like APIs return collections for values.
|
||||
* @author medavis
|
||||
*
|
||||
* TODO To change the template for this generated type comment go to
|
||||
* Window - Preferences - Java - Code Style - Code Templates
|
||||
*/
|
||||
public class Relation {
|
||||
private Map m;
|
||||
private CollectionFactory subcollection;
|
||||
|
||||
public Relation(Map mainMap, CollectionFactory subcollection) {
|
||||
m = mainMap;
|
||||
if (subcollection == null) subcollection = new CollectionMaker(null);
|
||||
this.subcollection = subcollection;
|
||||
*/
|
||||
public class Relation<K, V> implements Freezable {
|
||||
private Map<K, Set<V>> data;
|
||||
|
||||
Constructor<Set<V>> setCreator;
|
||||
Object[] setComparatorParam;
|
||||
|
||||
public Relation(Map<K, Set<V>> map, Class<Set<V>> setCreator) {
|
||||
this(map, setCreator, null);
|
||||
}
|
||||
|
||||
public Relation(Map<K, Set<V>> map, Class<Set<V>> setCreator, Comparator<V> setComparator) {
|
||||
try {
|
||||
setComparatorParam = setComparator == null ? null : new Object[]{setComparator};
|
||||
if (setComparator == null) {
|
||||
this.setCreator = setCreator.getConstructor();
|
||||
this.setCreator.newInstance(setComparatorParam); // check to make sure compiles
|
||||
} else {
|
||||
this.setCreator = setCreator.getConstructor(Comparator.class);
|
||||
this.setCreator.newInstance(setComparatorParam); // check to make sure compiles
|
||||
}
|
||||
data = map == null ? new HashMap() : map;
|
||||
} catch (Exception e) {
|
||||
throw (RuntimeException) new IllegalArgumentException("Can't create new set").initCause(e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
m.clear();
|
||||
data.clear();
|
||||
}
|
||||
|
||||
public boolean containsKey(Object key) {
|
||||
return m.containsKey(key);
|
||||
return data.containsKey(key);
|
||||
}
|
||||
|
||||
public boolean containsValue(Object value) {
|
||||
return m.containsValue(value);
|
||||
for (Set<V> values : data.values()) {
|
||||
if (values.contains(value))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
public Set entrySet() {
|
||||
return m.entrySet();
|
||||
|
||||
public Set<Entry<K, V>> entrySet() {
|
||||
Set<Entry<K, V>> result = new LinkedHashSet();
|
||||
for (K key : data.keySet()) {
|
||||
for (V value : data.get(key)) {
|
||||
result.add(new SimpleEntry(key, value));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
public boolean equals(Object obj) {
|
||||
return m.equals(obj);
|
||||
|
||||
public boolean equals(Object o) {
|
||||
if (o == null)
|
||||
return false;
|
||||
if (o.getClass() != this.getClass())
|
||||
return false;
|
||||
return data.equals(((Relation) o).data);
|
||||
}
|
||||
|
||||
// public V get(Object key) {
|
||||
// Set<V> set = data.get(key);
|
||||
// if (set == null || set.size() == 0)
|
||||
// return null;
|
||||
// return set.iterator().next();
|
||||
// }
|
||||
|
||||
public Set<V> getAll(Object key) {
|
||||
return data.get(key);
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return m.hashCode();
|
||||
return data.hashCode();
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return m.isEmpty();
|
||||
return data.isEmpty();
|
||||
}
|
||||
public Object remove(Object key) {
|
||||
return m.remove(key);
|
||||
|
||||
public Set<K> keySet() {
|
||||
return data.keySet();
|
||||
}
|
||||
|
||||
public V put(K key, V value) {
|
||||
Set<V> set = data.get(key);
|
||||
if (set == null) {
|
||||
data.put(key, set = newSet());
|
||||
}
|
||||
set.add(value);
|
||||
return value;
|
||||
}
|
||||
|
||||
public V putAll(K key, Collection<V> value) {
|
||||
Set<V> set = data.get(key);
|
||||
if (set == null) {
|
||||
data.put(key, set = newSet());
|
||||
}
|
||||
set.addAll(value);
|
||||
return value.size() == 0 ? null : value.iterator().next();
|
||||
}
|
||||
|
||||
public V putAll(Collection<K> keys, V value) {
|
||||
V result = null;
|
||||
for (K key : keys) {
|
||||
result = put(key, value);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private Set<V> newSet() {
|
||||
try {
|
||||
return (Set<V>) setCreator.newInstance(setComparatorParam);
|
||||
} catch (Exception e) {
|
||||
throw (RuntimeException) new IllegalArgumentException("Can't create new set").initCause(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void putAll(Map<? extends K, ? extends V> t) {
|
||||
for (K key : t.keySet()) {
|
||||
put(key, t.get(key));
|
||||
}
|
||||
}
|
||||
|
||||
public void putAll(Relation<? extends K, ? extends V> t) {
|
||||
for (K key : t.keySet()) {
|
||||
for (V value : t.getAll(key)) {
|
||||
put(key, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Set<V> removeAll(K key) {
|
||||
return data.remove(key);
|
||||
}
|
||||
|
||||
public boolean remove(K key, V value) {
|
||||
Set<V> set = data.get(key);
|
||||
if (set == null) return false;
|
||||
boolean result = set.remove(value);
|
||||
if (set.size() == 0) {
|
||||
data.remove(key);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public int size() {
|
||||
return m.size();
|
||||
return data.size();
|
||||
}
|
||||
|
||||
public Collection<V> values() {
|
||||
Set<V> result = newSet();
|
||||
for (K key : data.keySet()) {
|
||||
result.addAll(data.get(key));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return m.toString();
|
||||
}
|
||||
public Set keySet() {
|
||||
return m.keySet();
|
||||
}
|
||||
/*
|
||||
public void addAll(Relation t) {
|
||||
for (Iterator it = t.keySet().iterator(); it.hasNext();) {
|
||||
Object key = it.next();
|
||||
add(key, t.get(key));
|
||||
}
|
||||
}
|
||||
*/
|
||||
public Collection values() {
|
||||
return m.values();
|
||||
}
|
||||
public Collection get(Object key, Collection output) {
|
||||
output.addAll((Collection)m.get(key));
|
||||
return output;
|
||||
}
|
||||
public void add(Object key, Object value) {
|
||||
Collection o = (Collection) m.get(key);
|
||||
if (o == null) m.put(key, o = subcollection.make());
|
||||
o.add(value);
|
||||
}
|
||||
public Iterator iterator() {
|
||||
return m.keySet().iterator();
|
||||
}
|
||||
public interface CollectionFactory {
|
||||
Collection make();
|
||||
return data.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* This is just temporary, and may change!!
|
||||
* @author medavis
|
||||
*
|
||||
* TODO To change the template for this generated type comment go to
|
||||
* Window - Preferences - Java - Code Style - Code Templates
|
||||
*/
|
||||
public static class CollectionMaker implements CollectionFactory {
|
||||
public static final int HASH = 0, TREE = 1;
|
||||
private Comparator comparator = null;
|
||||
private int type = HASH;
|
||||
static class SimpleEntry<K, V> implements Entry<K, V> {
|
||||
K key;
|
||||
|
||||
public CollectionMaker(int type) {
|
||||
this.type = type;
|
||||
V value;
|
||||
|
||||
public SimpleEntry(K key, V value) {
|
||||
this.key = key;
|
||||
this.value = value;
|
||||
}
|
||||
public CollectionMaker(Comparator comparator) {
|
||||
this.comparator = comparator;
|
||||
|
||||
public SimpleEntry(Entry<K, V> e) {
|
||||
this.key = e.getKey();
|
||||
this.value = e.getValue();
|
||||
}
|
||||
public Collection make() {
|
||||
if (comparator != null) return new TreeSet(comparator);
|
||||
else if (type == HASH) return new HashSet();
|
||||
else return new TreeSet();
|
||||
|
||||
public K getKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
public V getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public V setValue(V value) {
|
||||
V oldValue = this.value;
|
||||
this.value = value;
|
||||
return oldValue;
|
||||
}
|
||||
}
|
||||
|
||||
public Relation<K,V> addAllInverted(Relation<V,K> source) {
|
||||
for (V value : source.data.keySet()) {
|
||||
for (K key : source.data.get(value)) {
|
||||
put(key, value);
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public Relation<K,V> addAllInverted(Map<V,K> source) {
|
||||
for (V value : source.keySet()) {
|
||||
put(source.get(value), value);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
boolean frozen = false;
|
||||
|
||||
public boolean isFrozen() {
|
||||
return frozen;
|
||||
}
|
||||
|
||||
public Object freeze() {
|
||||
if (!frozen) {
|
||||
frozen = true;
|
||||
// does not handle one level down, so we do that on a case-by-case basis
|
||||
for (K key : data.keySet()) {
|
||||
data.put(key, Collections.unmodifiableSet(data.get(key)));
|
||||
}
|
||||
// now do top level
|
||||
data = Collections.unmodifiableMap(data);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public Object cloneAsThawed() {
|
||||
// TODO do later
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public boolean removeAll(Relation<K, V> toBeRemoved) {
|
||||
boolean result = false;
|
||||
for (K key : toBeRemoved.keySet()) {
|
||||
Set<V> values = toBeRemoved.getAll(key);
|
||||
if (values != null) {
|
||||
result |= removeAll(key, values);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public boolean removeAll(K key, Iterable<V> all) {
|
||||
boolean result = false;
|
||||
for (V value : all) {
|
||||
result |= remove(key, value);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public Set<V> removeAll(Collection<K> toBeRemoved) {
|
||||
Set<V> result = new LinkedHashSet();
|
||||
for (K key : toBeRemoved) {
|
||||
final Set<V> removals = data.remove(key);
|
||||
if (removals != null) {
|
||||
result.addAll(removals);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user