17dd252788645e940eada959bdde927426e2531c9Paul Duffin/*
27dd252788645e940eada959bdde927426e2531c9Paul Duffin * Copyright (C) 2012 The Guava Authors
37dd252788645e940eada959bdde927426e2531c9Paul Duffin *
40888a09821a98ac0680fad765217302858e70fa4Paul Duffin * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
50888a09821a98ac0680fad765217302858e70fa4Paul Duffin * in compliance with the License. You may obtain a copy of the License at
67dd252788645e940eada959bdde927426e2531c9Paul Duffin *
77dd252788645e940eada959bdde927426e2531c9Paul Duffin * http://www.apache.org/licenses/LICENSE-2.0
87dd252788645e940eada959bdde927426e2531c9Paul Duffin *
90888a09821a98ac0680fad765217302858e70fa4Paul Duffin * Unless required by applicable law or agreed to in writing, software distributed under the License
100888a09821a98ac0680fad765217302858e70fa4Paul Duffin * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
110888a09821a98ac0680fad765217302858e70fa4Paul Duffin * or implied. See the License for the specific language governing permissions and limitations under
120888a09821a98ac0680fad765217302858e70fa4Paul Duffin * the License.
137dd252788645e940eada959bdde927426e2531c9Paul Duffin */
147dd252788645e940eada959bdde927426e2531c9Paul Duffin
157dd252788645e940eada959bdde927426e2531c9Paul Duffinpackage com.google.common.collect;
167dd252788645e940eada959bdde927426e2531c9Paul Duffin
177dd252788645e940eada959bdde927426e2531c9Paul Duffinimport static com.google.common.base.Preconditions.checkNotNull;
187dd252788645e940eada959bdde927426e2531c9Paul Duffinimport static com.google.common.base.Preconditions.checkPositionIndex;
197dd252788645e940eada959bdde927426e2531c9Paul Duffin
207dd252788645e940eada959bdde927426e2531c9Paul Duffinimport com.google.common.annotations.GwtCompatible;
217dd252788645e940eada959bdde927426e2531c9Paul Duffinimport com.google.common.base.Predicate;
227dd252788645e940eada959bdde927426e2531c9Paul Duffin
237dd252788645e940eada959bdde927426e2531c9Paul Duffinimport java.util.Collection;
247dd252788645e940eada959bdde927426e2531c9Paul Duffinimport java.util.Collections;
257dd252788645e940eada959bdde927426e2531c9Paul Duffinimport java.util.Iterator;
267dd252788645e940eada959bdde927426e2531c9Paul Duffinimport java.util.List;
277dd252788645e940eada959bdde927426e2531c9Paul Duffinimport java.util.Map;
287dd252788645e940eada959bdde927426e2531c9Paul Duffinimport java.util.Map.Entry;
297dd252788645e940eada959bdde927426e2531c9Paul Duffinimport java.util.Set;
307dd252788645e940eada959bdde927426e2531c9Paul Duffin
317dd252788645e940eada959bdde927426e2531c9Paul Duffinimport javax.annotation.Nullable;
327dd252788645e940eada959bdde927426e2531c9Paul Duffin
337dd252788645e940eada959bdde927426e2531c9Paul Duffin/**
347dd252788645e940eada959bdde927426e2531c9Paul Duffin * Implementation of {@link Multimaps#filterKeys(Multimap, Predicate)}.
357dd252788645e940eada959bdde927426e2531c9Paul Duffin *
367dd252788645e940eada959bdde927426e2531c9Paul Duffin * @author Louis Wasserman
377dd252788645e940eada959bdde927426e2531c9Paul Duffin */
387dd252788645e940eada959bdde927426e2531c9Paul Duffin@GwtCompatible
390888a09821a98ac0680fad765217302858e70fa4Paul Duffinclass FilteredKeyMultimap<K, V> extends AbstractMultimap<K, V> implements FilteredMultimap<K, V> {
400888a09821a98ac0680fad765217302858e70fa4Paul Duffin  final Multimap<K, V> unfiltered;
417dd252788645e940eada959bdde927426e2531c9Paul Duffin  final Predicate<? super K> keyPredicate;
427dd252788645e940eada959bdde927426e2531c9Paul Duffin
437dd252788645e940eada959bdde927426e2531c9Paul Duffin  FilteredKeyMultimap(Multimap<K, V> unfiltered, Predicate<? super K> keyPredicate) {
440888a09821a98ac0680fad765217302858e70fa4Paul Duffin    this.unfiltered = checkNotNull(unfiltered);
457dd252788645e940eada959bdde927426e2531c9Paul Duffin    this.keyPredicate = checkNotNull(keyPredicate);
467dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
477dd252788645e940eada959bdde927426e2531c9Paul Duffin
487dd252788645e940eada959bdde927426e2531c9Paul Duffin  @Override
490888a09821a98ac0680fad765217302858e70fa4Paul Duffin  public Multimap<K, V> unfiltered() {
500888a09821a98ac0680fad765217302858e70fa4Paul Duffin    return unfiltered;
517dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
527dd252788645e940eada959bdde927426e2531c9Paul Duffin
530888a09821a98ac0680fad765217302858e70fa4Paul Duffin  @Override
540888a09821a98ac0680fad765217302858e70fa4Paul Duffin  public Predicate<? super Entry<K, V>> entryPredicate() {
550888a09821a98ac0680fad765217302858e70fa4Paul Duffin    return Maps.keyPredicateOnEntries(keyPredicate);
560888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
570888a09821a98ac0680fad765217302858e70fa4Paul Duffin
580888a09821a98ac0680fad765217302858e70fa4Paul Duffin  @Override
597dd252788645e940eada959bdde927426e2531c9Paul Duffin  public int size() {
607dd252788645e940eada959bdde927426e2531c9Paul Duffin    int size = 0;
617dd252788645e940eada959bdde927426e2531c9Paul Duffin    for (Collection<V> collection : asMap().values()) {
627dd252788645e940eada959bdde927426e2531c9Paul Duffin      size += collection.size();
637dd252788645e940eada959bdde927426e2531c9Paul Duffin    }
647dd252788645e940eada959bdde927426e2531c9Paul Duffin    return size;
657dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
667dd252788645e940eada959bdde927426e2531c9Paul Duffin
670888a09821a98ac0680fad765217302858e70fa4Paul Duffin  @Override
687dd252788645e940eada959bdde927426e2531c9Paul Duffin  public boolean containsKey(@Nullable Object key) {
697dd252788645e940eada959bdde927426e2531c9Paul Duffin    if (unfiltered.containsKey(key)) {
700888a09821a98ac0680fad765217302858e70fa4Paul Duffin      @SuppressWarnings("unchecked") // k is equal to a K, if not one itself
717dd252788645e940eada959bdde927426e2531c9Paul Duffin      K k = (K) key;
727dd252788645e940eada959bdde927426e2531c9Paul Duffin      return keyPredicate.apply(k);
737dd252788645e940eada959bdde927426e2531c9Paul Duffin    }
747dd252788645e940eada959bdde927426e2531c9Paul Duffin    return false;
757dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
767dd252788645e940eada959bdde927426e2531c9Paul Duffin
770888a09821a98ac0680fad765217302858e70fa4Paul Duffin  @Override
787dd252788645e940eada959bdde927426e2531c9Paul Duffin  public Collection<V> removeAll(Object key) {
797dd252788645e940eada959bdde927426e2531c9Paul Duffin    return containsKey(key) ? unfiltered.removeAll(key) : unmodifiableEmptyCollection();
807dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
817dd252788645e940eada959bdde927426e2531c9Paul Duffin
827dd252788645e940eada959bdde927426e2531c9Paul Duffin  Collection<V> unmodifiableEmptyCollection() {
837dd252788645e940eada959bdde927426e2531c9Paul Duffin    if (unfiltered instanceof SetMultimap) {
847dd252788645e940eada959bdde927426e2531c9Paul Duffin      return ImmutableSet.of();
857dd252788645e940eada959bdde927426e2531c9Paul Duffin    } else {
867dd252788645e940eada959bdde927426e2531c9Paul Duffin      return ImmutableList.of();
877dd252788645e940eada959bdde927426e2531c9Paul Duffin    }
887dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
897dd252788645e940eada959bdde927426e2531c9Paul Duffin
900888a09821a98ac0680fad765217302858e70fa4Paul Duffin  @Override
917dd252788645e940eada959bdde927426e2531c9Paul Duffin  public void clear() {
927dd252788645e940eada959bdde927426e2531c9Paul Duffin    keySet().clear();
937dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
947dd252788645e940eada959bdde927426e2531c9Paul Duffin
957dd252788645e940eada959bdde927426e2531c9Paul Duffin  @Override
967dd252788645e940eada959bdde927426e2531c9Paul Duffin  Set<K> createKeySet() {
977dd252788645e940eada959bdde927426e2531c9Paul Duffin    return Sets.filter(unfiltered.keySet(), keyPredicate);
987dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
997dd252788645e940eada959bdde927426e2531c9Paul Duffin
1000888a09821a98ac0680fad765217302858e70fa4Paul Duffin  @Override
1017dd252788645e940eada959bdde927426e2531c9Paul Duffin  public Collection<V> get(K key) {
1027dd252788645e940eada959bdde927426e2531c9Paul Duffin    if (keyPredicate.apply(key)) {
1037dd252788645e940eada959bdde927426e2531c9Paul Duffin      return unfiltered.get(key);
1047dd252788645e940eada959bdde927426e2531c9Paul Duffin    } else if (unfiltered instanceof SetMultimap) {
1057dd252788645e940eada959bdde927426e2531c9Paul Duffin      return new AddRejectingSet<K, V>(key);
1067dd252788645e940eada959bdde927426e2531c9Paul Duffin    } else {
1077dd252788645e940eada959bdde927426e2531c9Paul Duffin      return new AddRejectingList<K, V>(key);
1087dd252788645e940eada959bdde927426e2531c9Paul Duffin    }
1097dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
1107dd252788645e940eada959bdde927426e2531c9Paul Duffin
1117dd252788645e940eada959bdde927426e2531c9Paul Duffin  static class AddRejectingSet<K, V> extends ForwardingSet<V> {
1127dd252788645e940eada959bdde927426e2531c9Paul Duffin    final K key;
1137dd252788645e940eada959bdde927426e2531c9Paul Duffin
1147dd252788645e940eada959bdde927426e2531c9Paul Duffin    AddRejectingSet(K key) {
1157dd252788645e940eada959bdde927426e2531c9Paul Duffin      this.key = key;
1167dd252788645e940eada959bdde927426e2531c9Paul Duffin    }
1177dd252788645e940eada959bdde927426e2531c9Paul Duffin
1187dd252788645e940eada959bdde927426e2531c9Paul Duffin    @Override
1197dd252788645e940eada959bdde927426e2531c9Paul Duffin    public boolean add(V element) {
1207dd252788645e940eada959bdde927426e2531c9Paul Duffin      throw new IllegalArgumentException("Key does not satisfy predicate: " + key);
1217dd252788645e940eada959bdde927426e2531c9Paul Duffin    }
1227dd252788645e940eada959bdde927426e2531c9Paul Duffin
1237dd252788645e940eada959bdde927426e2531c9Paul Duffin    @Override
1247dd252788645e940eada959bdde927426e2531c9Paul Duffin    public boolean addAll(Collection<? extends V> collection) {
1257dd252788645e940eada959bdde927426e2531c9Paul Duffin      checkNotNull(collection);
1267dd252788645e940eada959bdde927426e2531c9Paul Duffin      throw new IllegalArgumentException("Key does not satisfy predicate: " + key);
1277dd252788645e940eada959bdde927426e2531c9Paul Duffin    }
1287dd252788645e940eada959bdde927426e2531c9Paul Duffin
1297dd252788645e940eada959bdde927426e2531c9Paul Duffin    @Override
1307dd252788645e940eada959bdde927426e2531c9Paul Duffin    protected Set<V> delegate() {
1317dd252788645e940eada959bdde927426e2531c9Paul Duffin      return Collections.emptySet();
1327dd252788645e940eada959bdde927426e2531c9Paul Duffin    }
1337dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
1347dd252788645e940eada959bdde927426e2531c9Paul Duffin
1357dd252788645e940eada959bdde927426e2531c9Paul Duffin  static class AddRejectingList<K, V> extends ForwardingList<V> {
1367dd252788645e940eada959bdde927426e2531c9Paul Duffin    final K key;
1377dd252788645e940eada959bdde927426e2531c9Paul Duffin
1387dd252788645e940eada959bdde927426e2531c9Paul Duffin    AddRejectingList(K key) {
1397dd252788645e940eada959bdde927426e2531c9Paul Duffin      this.key = key;
1407dd252788645e940eada959bdde927426e2531c9Paul Duffin    }
1417dd252788645e940eada959bdde927426e2531c9Paul Duffin
1427dd252788645e940eada959bdde927426e2531c9Paul Duffin    @Override
1437dd252788645e940eada959bdde927426e2531c9Paul Duffin    public boolean add(V v) {
1447dd252788645e940eada959bdde927426e2531c9Paul Duffin      add(0, v);
1457dd252788645e940eada959bdde927426e2531c9Paul Duffin      return true;
1467dd252788645e940eada959bdde927426e2531c9Paul Duffin    }
1477dd252788645e940eada959bdde927426e2531c9Paul Duffin
1487dd252788645e940eada959bdde927426e2531c9Paul Duffin    @Override
1497dd252788645e940eada959bdde927426e2531c9Paul Duffin    public boolean addAll(Collection<? extends V> collection) {
1507dd252788645e940eada959bdde927426e2531c9Paul Duffin      addAll(0, collection);
1517dd252788645e940eada959bdde927426e2531c9Paul Duffin      return true;
1527dd252788645e940eada959bdde927426e2531c9Paul Duffin    }
1537dd252788645e940eada959bdde927426e2531c9Paul Duffin
1547dd252788645e940eada959bdde927426e2531c9Paul Duffin    @Override
1557dd252788645e940eada959bdde927426e2531c9Paul Duffin    public void add(int index, V element) {
1567dd252788645e940eada959bdde927426e2531c9Paul Duffin      checkPositionIndex(index, 0);
1577dd252788645e940eada959bdde927426e2531c9Paul Duffin      throw new IllegalArgumentException("Key does not satisfy predicate: " + key);
1587dd252788645e940eada959bdde927426e2531c9Paul Duffin    }
1597dd252788645e940eada959bdde927426e2531c9Paul Duffin
1607dd252788645e940eada959bdde927426e2531c9Paul Duffin    @Override
1617dd252788645e940eada959bdde927426e2531c9Paul Duffin    public boolean addAll(int index, Collection<? extends V> elements) {
1627dd252788645e940eada959bdde927426e2531c9Paul Duffin      checkNotNull(elements);
1637dd252788645e940eada959bdde927426e2531c9Paul Duffin      checkPositionIndex(index, 0);
1647dd252788645e940eada959bdde927426e2531c9Paul Duffin      throw new IllegalArgumentException("Key does not satisfy predicate: " + key);
1657dd252788645e940eada959bdde927426e2531c9Paul Duffin    }
1667dd252788645e940eada959bdde927426e2531c9Paul Duffin
1677dd252788645e940eada959bdde927426e2531c9Paul Duffin    @Override
1687dd252788645e940eada959bdde927426e2531c9Paul Duffin    protected List<V> delegate() {
1697dd252788645e940eada959bdde927426e2531c9Paul Duffin      return Collections.emptyList();
1707dd252788645e940eada959bdde927426e2531c9Paul Duffin    }
1717dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
1727dd252788645e940eada959bdde927426e2531c9Paul Duffin
1737dd252788645e940eada959bdde927426e2531c9Paul Duffin  @Override
1747dd252788645e940eada959bdde927426e2531c9Paul Duffin  Iterator<Entry<K, V>> entryIterator() {
1750888a09821a98ac0680fad765217302858e70fa4Paul Duffin    throw new AssertionError("should never be called");
1767dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
1777dd252788645e940eada959bdde927426e2531c9Paul Duffin
1787dd252788645e940eada959bdde927426e2531c9Paul Duffin  @Override
1797dd252788645e940eada959bdde927426e2531c9Paul Duffin  Collection<Entry<K, V>> createEntries() {
1800888a09821a98ac0680fad765217302858e70fa4Paul Duffin    return new Entries();
1810888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
1827dd252788645e940eada959bdde927426e2531c9Paul Duffin
1830888a09821a98ac0680fad765217302858e70fa4Paul Duffin  class Entries extends ForwardingCollection<Entry<K, V>> {
1840888a09821a98ac0680fad765217302858e70fa4Paul Duffin    @Override
1850888a09821a98ac0680fad765217302858e70fa4Paul Duffin    protected Collection<Entry<K, V>> delegate() {
1860888a09821a98ac0680fad765217302858e70fa4Paul Duffin      return Collections2.filter(unfiltered.entries(), entryPredicate());
1870888a09821a98ac0680fad765217302858e70fa4Paul Duffin    }
1887dd252788645e940eada959bdde927426e2531c9Paul Duffin
1890888a09821a98ac0680fad765217302858e70fa4Paul Duffin    @Override
1900888a09821a98ac0680fad765217302858e70fa4Paul Duffin    @SuppressWarnings("unchecked")
1910888a09821a98ac0680fad765217302858e70fa4Paul Duffin    public boolean remove(@Nullable Object o) {
1920888a09821a98ac0680fad765217302858e70fa4Paul Duffin      if (o instanceof Entry) {
1930888a09821a98ac0680fad765217302858e70fa4Paul Duffin        Entry<?, ?> entry = (Entry<?, ?>) o;
1940888a09821a98ac0680fad765217302858e70fa4Paul Duffin        if (unfiltered.containsKey(entry.getKey())
1950888a09821a98ac0680fad765217302858e70fa4Paul Duffin            // if this holds, then we know entry.getKey() is a K
1960888a09821a98ac0680fad765217302858e70fa4Paul Duffin            && keyPredicate.apply((K) entry.getKey())) {
1970888a09821a98ac0680fad765217302858e70fa4Paul Duffin          return unfiltered.remove(entry.getKey(), entry.getValue());
1987dd252788645e940eada959bdde927426e2531c9Paul Duffin        }
1997dd252788645e940eada959bdde927426e2531c9Paul Duffin      }
2000888a09821a98ac0680fad765217302858e70fa4Paul Duffin      return false;
2010888a09821a98ac0680fad765217302858e70fa4Paul Duffin    }
2020888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
2030888a09821a98ac0680fad765217302858e70fa4Paul Duffin
2040888a09821a98ac0680fad765217302858e70fa4Paul Duffin  @Override
2050888a09821a98ac0680fad765217302858e70fa4Paul Duffin  Collection<V> createValues() {
2060888a09821a98ac0680fad765217302858e70fa4Paul Duffin    return new FilteredMultimapValues<K, V>(this);
2077dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
2087dd252788645e940eada959bdde927426e2531c9Paul Duffin
2097dd252788645e940eada959bdde927426e2531c9Paul Duffin  @Override
2107dd252788645e940eada959bdde927426e2531c9Paul Duffin  Map<K, Collection<V>> createAsMap() {
2117dd252788645e940eada959bdde927426e2531c9Paul Duffin    return Maps.filterKeys(unfiltered.asMap(), keyPredicate);
2127dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
2137dd252788645e940eada959bdde927426e2531c9Paul Duffin
2147dd252788645e940eada959bdde927426e2531c9Paul Duffin  @Override
2157dd252788645e940eada959bdde927426e2531c9Paul Duffin  Multiset<K> createKeys() {
2167dd252788645e940eada959bdde927426e2531c9Paul Duffin    return Multisets.filter(unfiltered.keys(), keyPredicate);
2177dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
2187dd252788645e940eada959bdde927426e2531c9Paul Duffin}
219