blob: 1a0b01f0d750115f11df10b64857dad4cabba894 [file] [log] [blame]
package org.unicode.cldr.util;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import com.ibm.icu.dev.util.UnicodeMap;
import com.ibm.icu.text.UnicodeSet;
import com.ibm.icu.util.Freezable;
public class UnicodeRelation<T> implements Freezable<UnicodeRelation<T>> {
final UnicodeMap<Set<T>> data = new UnicodeMap<>();
final SetMaker<T> maker;
public interface SetMaker<T> {
Set<T> make();
}
public static SetMaker<Object> HASHSET_MAKER = new SetMaker<Object>() {
@Override
public Set<Object> make() {
return new HashSet<Object>();
}
};
public static final SetMaker<Object> LINKED_HASHSET_MAKER = new SetMaker<Object>() {
public Set<Object> make() {
return new LinkedHashSet<Object>();
}
};
public UnicodeRelation(SetMaker<T> maker) {
this.maker = maker;
}
public UnicodeRelation() {
this.maker = (SetMaker<T>) HASHSET_MAKER;
}
public int size() {
return data.size();
}
public boolean isEmpty() {
return data.isEmpty();
}
public boolean containsKey(int key) {
return data.containsKey(key);
}
public boolean containsKey(String key) {
return data.containsKey(key);
}
public boolean containsValue(T value) {
for (Set<T> v : data.values()) {
if (v.contains(value)) {
return true;
}
}
return false;
}
public Set<T> get(int key) {
return data.get(key);
}
public Set<T> get(String key) {
return data.get((String) key);
}
public UnicodeSet getKeys(T value) {
UnicodeSet result = new UnicodeSet();
for (Entry<String, Set<T>> entry : data.entrySet()) {
if (entry.getValue().contains(value)) {
result.add(entry.getKey());
}
}
return result;
}
public UnicodeRelation<T> add(String key, T value) {
Set<T> newValues = addValue(data.get(key), value);
if (newValues != null) {
data.put(key, newValues);
}
return this;
}
public UnicodeRelation<T> add(int key, T value) {
Set<T> newValues = addValue(data.get(key), value);
if (newValues != null) {
data.put(key, newValues);
}
return this;
}
public UnicodeRelation<T> addAll(String key, Collection<T> values) {
Set<T> newValues = addValues(data.get(key), values);
if (newValues != null) {
data.put(key, newValues);
}
return this;
}
public UnicodeRelation<T> addAll(Map<String, T> m) {
for (Entry<String, T> entry : m.entrySet()) {
add(entry.getKey(), entry.getValue());
}
return this;
}
public UnicodeRelation<T> addAll(UnicodeSet keys, Collection<T> values) {
for (String key : keys) {
addAll(key, values);
}
return this;
}
public UnicodeRelation<T> addAll(UnicodeSet keys, T... values) {
return addAll(keys, Arrays.asList(values));
}
public UnicodeRelation<T> addAll(UnicodeSet keys, T value) {
for (String key : keys) {
add(key, value);
}
return this;
}
private Set<T> addValue(Set<T> oldValues, T value) {
if (oldValues == null) {
return Collections.singleton(value);
} else if (oldValues.contains(value)) {
return null;
} else {
Set<T> newValues = make(oldValues);
newValues.add(value);
return Collections.unmodifiableSet(newValues);
}
}
private final Set<T> make(Collection<T> oldValues) {
Set<T> newValues = maker.make();
newValues.addAll(oldValues);
return newValues;
}
private Set<T> addValues(Set<T> oldValues, Collection<T> values) {
if (oldValues == null) {
if (values.size() == 1) {
return Collections.singleton(values.iterator().next());
} else {
return Collections.unmodifiableSet(make(values));
}
} else if (oldValues.containsAll(values)) {
return null;
} else {
Set<T> newValues = make(oldValues);
newValues.addAll(values);
return Collections.unmodifiableSet(newValues);
}
}
private Set<T> removeValues(Set<T> oldValues, Collection<T> values) {
if (oldValues == null) {
return null;
} else if (Collections.disjoint(oldValues, values)) {
return null;
} else {
Set<T> newValues = make(oldValues);
newValues.removeAll(values);
return newValues.size() == 0 ? Collections.EMPTY_SET : Collections.unmodifiableSet(newValues);
}
}
public UnicodeRelation<T> remove(int key) {
data.remove(key);
return this;
}
public UnicodeRelation<T> remove(String key) {
data.remove(key);
return this;
}
public UnicodeRelation<T> removeValue(T value) {
UnicodeSet toChange = getKeys(value);
for (String key : toChange) {
remove(key, value);
}
return this;
}
public UnicodeRelation<T> remove(int key, T value) {
Set<T> values = data.getValue(key);
if (values != null && values.contains(value)) {
removeExisting(key, value, values);
}
return this;
}
public UnicodeRelation<T> remove(String key, T value) {
Set<T> values = data.getValue(key);
if (values != null && values.contains(value)) {
removeExisting(key, value, values);
}
return this;
}
public UnicodeRelation<T> removeAll(String key, Collection<T> values) {
Set<T> newValues = removeValues(data.get(key), values);
if (newValues != null) {
if (newValues == Collections.EMPTY_SET) {
data.remove(key);
} else {
data.put(key, newValues);
}
}
return this;
}
public UnicodeRelation<T> removeAll(Map<String, T> m) {
for (Entry<String, T> entry : m.entrySet()) {
remove(entry.getKey(), entry.getValue());
}
return this;
}
public UnicodeRelation<T> removeAll(UnicodeSet keys, Collection<T> values) {
for (String key : keys) {
removeAll(key, values);
}
return this;
}
public UnicodeRelation<T> removeAll(UnicodeSet keys, T... values) {
return removeAll(keys, Arrays.asList(values));
}
public UnicodeRelation<T> removeAll(UnicodeSet keys, T value) {
for (String key : keys) {
remove(key, value);
}
return this;
}
private void removeExisting(int key, T value, Set<T> values) {
if (values.size() == 1) {
data.remove(key);
} else {
Set<T> newValues = make(values);
newValues.remove(value);
data.put(key, Collections.unmodifiableSet(newValues));
}
}
private void removeExisting(String key, T value, Set<T> values) {
if (values.size() == 1) {
data.remove(key);
} else {
Set<T> newValues = make(values);
newValues.remove(value);
data.put(key, Collections.unmodifiableSet(newValues));
}
}
public void clear() {
data.clear();
}
public UnicodeSet keySet() {
return data.keySet();
}
public Collection<T> values() {
Set<T> result = maker.make();
for (Set<T> v : data.values()) {
result.addAll(v);
}
return result;
}
public Iterable<Entry<String, Set<T>>> keyValues() {
return data.entrySet();
}
@Override
public String toString() {
return data.toString();
}
@Override
public int hashCode() {
return data.hashCode();
}
@Override
public boolean equals(Object obj) {
return obj instanceof UnicodeRelation && data.equals(((UnicodeRelation) obj).data);
}
@Override
public boolean isFrozen() {
return data.isFrozen();
}
@Override
public UnicodeRelation<T> freeze() {
data.freeze();
return this;
}
@Override
public UnicodeRelation<T> cloneAsThawed() {
throw new UnsupportedOperationException();
}
}