blob: f83b054b1894b215d56afe1da9ee41297b06b768 [file] [log] [blame]
/*
// Licensed to Julian Hyde under one or more contributor license
// agreements. See the NOTICE file distributed with this work for
// additional information regarding copyright ownership.
//
// Julian Hyde licenses this file to you under the Apache License,
// Version 2.0 (the "License"); you may not use this file except in
// compliance with the License. You may obtain a copy of the License at:
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
*/
package net.hydromatic.linq4j;
import net.hydromatic.linq4j.function.Function2;
import java.util.*;
/**
* Implementation of {@link Lookup} that uses an underlying map.
*/
class LookupImpl<K, V> extends AbstractEnumerable<Grouping<K, V>>
implements Lookup<K, V> {
private final Map<K, List<V>> map;
/**
* Creates a MultiMapImpl.
*
* @param map Underlying map
*/
LookupImpl(Map<K, List<V>> map) {
this.map = map;
}
public Enumerator<Grouping<K, V>> enumerator() {
return new Enumerator<Grouping<K, V>>() {
Enumerator<Entry<K, List<V>>> enumerator = Linq4j.enumerator(
map.entrySet());
public Grouping<K, V> current() {
final Entry<K, List<V>> keyAndList = enumerator.current();
return new GroupingImpl<K, V>(keyAndList.getKey(),
keyAndList.getValue());
}
public boolean moveNext() {
return enumerator.moveNext();
}
public void reset() {
enumerator.reset();
}
};
}
// Map methods
public int size() {
return map.size();
}
public boolean isEmpty() {
return map.isEmpty();
}
public boolean containsKey(Object key) {
return map.containsKey(key);
}
public boolean containsValue(Object value) {
@SuppressWarnings("unchecked")
List<V> list = (List<V>) value;
Enumerable<V> enumerable = Linq4j.asEnumerable(list);
return map.containsValue(enumerable);
}
public Enumerable<V> get(Object key) {
final List<V> list = map.get(key);
return list == null ? null : Linq4j.asEnumerable(list);
}
public Enumerable<V> put(K key, Enumerable<V> value) {
final List<V> list = map.put(key, value.toList());
return list == null ? null : Linq4j.asEnumerable(list);
}
public Enumerable<V> remove(Object key) {
final List<V> list = map.remove(key);
return list == null ? null : Linq4j.asEnumerable(list);
}
public void putAll(Map<? extends K, ? extends Enumerable<V>> m) {
for (Entry<? extends K, ? extends Enumerable<V>> entry : m.entrySet()) {
map.put(entry.getKey(), entry.getValue().toList());
}
}
public void clear() {
map.clear();
}
public Set<K> keySet() {
return map.keySet();
}
public Collection<Enumerable<V>> values() {
final Collection<List<V>> lists = map.values();
return new AbstractCollection<Enumerable<V>>() {
public Iterator<Enumerable<V>> iterator() {
return new Iterator<Enumerable<V>>() {
final Iterator<List<V>> iterator = lists.iterator();
public boolean hasNext() {
return iterator.hasNext();
}
public Enumerable<V> next() {
return Linq4j.asEnumerable(iterator.next());
}
public void remove() {
iterator.remove();
}
};
}
public int size() {
return lists.size();
}
};
}
public Set<Entry<K, Enumerable<V>>> entrySet() {
final Set<Entry<K, List<V>>> entries = map.entrySet();
return new AbstractSet<Entry<K, Enumerable<V>>>() {
public Iterator<Entry<K, Enumerable<V>>> iterator() {
final Iterator<Entry<K, List<V>>> iterator = entries.iterator();
return new Iterator<Entry<K, Enumerable<V>>>() {
public boolean hasNext() {
return iterator.hasNext();
}
public Entry<K, Enumerable<V>> next() {
final Entry<K, List<V>> entry = iterator.next();
return new AbstractMap.SimpleEntry<K, Enumerable<V>>(entry.getKey(),
Linq4j.asEnumerable(entry.getValue()));
}
public void remove() {
iterator.remove();
}
};
}
public int size() {
return entries.size();
}
};
}
public <TResult> Enumerable<TResult> applyResultSelector(
final Function2<K, Enumerable<V>, TResult> resultSelector) {
return new AbstractEnumerable<TResult>() {
public Enumerator<TResult> enumerator() {
final Enumerator<Grouping<K, V>> groupingEnumerator =
LookupImpl.this.enumerator();
return new Enumerator<TResult>() {
public TResult current() {
final Grouping<K, V> grouping = groupingEnumerator.current();
return resultSelector.apply(grouping.getKey(), grouping);
}
public boolean moveNext() {
return groupingEnumerator.moveNext();
}
public void reset() {
groupingEnumerator.reset();
}
};
}
};
}
/**
* Returns an enumerable over the values in this lookup, in map order.
* If the map is sorted, the values will be emitted sorted by key.
*/
public Enumerable<V> valuesEnumerable() {
return new AbstractEnumerable<V>() {
public Enumerator<V> enumerator() {
final Enumerator<Enumerable<V>> listEnumerator =
Linq4j.iterableEnumerator(values());
return new Enumerator<V>() {
Enumerator<V> enumerator = Linq4j.emptyEnumerator();
public V current() {
return enumerator.current();
}
public boolean moveNext() {
for (;;) {
if (enumerator.moveNext()) {
return true;
}
if (!listEnumerator.moveNext()) {
return false;
}
enumerator = listEnumerator.current().enumerator();
}
}
public void reset() {
listEnumerator.reset();
enumerator = Linq4j.emptyEnumerator();
}
};
}
};
}
}
// End LookupImpl.java