1/*
2 * Copyright (C) 2008 The Guava Authors
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.google.common.collect;
18
19import static com.google.common.base.Preconditions.checkNotNull;
20import static com.google.common.collect.Maps.safeContainsKey;
21import static com.google.common.collect.Maps.safeGet;
22
23import com.google.common.annotations.GwtCompatible;
24import com.google.common.base.Predicate;
25import com.google.common.base.Predicates;
26import com.google.common.base.Supplier;
27
28import java.io.Serializable;
29import java.util.AbstractCollection;
30import java.util.AbstractMap;
31import java.util.AbstractSet;
32import java.util.Collection;
33import java.util.Iterator;
34import java.util.LinkedHashMap;
35import java.util.Map;
36import java.util.Map.Entry;
37import java.util.Set;
38
39import javax.annotation.Nullable;
40
41/**
42 * {@link Table} implementation backed by a map that associates row keys with
43 * column key / value secondary maps. This class provides rapid access to
44 * records by the row key alone or by both keys, but not by just the column key.
45 *
46 * <p>The views returned by {@link #column}, {@link #columnKeySet()}, and {@link
47 * #columnMap()} have iterators that don't support {@code remove()}. Otherwise,
48 * all optional operations are supported. Null row keys, columns keys, and
49 * values are not supported.
50 *
51 * <p>Lookups by row key are often faster than lookups by column key, because
52 * the data is stored in a {@code Map<R, Map<C, V>>}. A method call like {@code
53 * column(columnKey).get(rowKey)} still runs quickly, since the row key is
54 * provided. However, {@code column(columnKey).size()} takes longer, since an
55 * iteration across all row keys occurs.
56 *
57 * <p>Note that this implementation is not synchronized. If multiple threads
58 * access this table concurrently and one of the threads modifies the table, it
59 * must be synchronized externally.
60 *
61 * @author Jared Levy
62 */
63@GwtCompatible
64class StandardTable<R, C, V> implements Table<R, C, V>, Serializable {
65  @GwtTransient final Map<R, Map<C, V>> backingMap;
66  @GwtTransient final Supplier<? extends Map<C, V>> factory;
67
68  StandardTable(Map<R, Map<C, V>> backingMap,
69      Supplier<? extends Map<C, V>> factory) {
70    this.backingMap = backingMap;
71    this.factory = factory;
72  }
73
74  // Accessors
75
76  @Override public boolean contains(
77      @Nullable Object rowKey, @Nullable Object columnKey) {
78    if ((rowKey == null) || (columnKey == null)) {
79      return false;
80    }
81    Map<C, V> map = safeGet(backingMap, rowKey);
82    return map != null && safeContainsKey(map, columnKey);
83  }
84
85  @Override public boolean containsColumn(@Nullable Object columnKey) {
86    if (columnKey == null) {
87      return false;
88    }
89    for (Map<C, V> map : backingMap.values()) {
90      if (safeContainsKey(map, columnKey)) {
91        return true;
92      }
93    }
94    return false;
95  }
96
97  @Override public boolean containsRow(@Nullable Object rowKey) {
98    return rowKey != null && safeContainsKey(backingMap, rowKey);
99  }
100
101  @Override public boolean containsValue(@Nullable Object value) {
102    if (value == null) {
103      return false;
104    }
105    for (Map<C, V> map : backingMap.values()) {
106      if (map.containsValue(value)) {
107        return true;
108      }
109    }
110    return false;
111  }
112
113  @Override public V get(@Nullable Object rowKey, @Nullable Object columnKey) {
114    if ((rowKey == null) || (columnKey == null)) {
115      return null;
116    }
117    Map<C, V> map = safeGet(backingMap, rowKey);
118    return map == null ? null : safeGet(map, columnKey);
119  }
120
121  @Override public boolean isEmpty() {
122    return backingMap.isEmpty();
123  }
124
125  @Override public int size() {
126    int size = 0;
127    for (Map<C, V> map : backingMap.values()) {
128      size += map.size();
129    }
130    return size;
131  }
132
133  @Override public boolean equals(@Nullable Object obj) {
134    if (obj == this) {
135      return true;
136    }
137    if (obj instanceof Table) {
138      Table<?, ?, ?> other = (Table<?, ?, ?>) obj;
139      return cellSet().equals(other.cellSet());
140    }
141    return false;
142  }
143
144  @Override public int hashCode() {
145    return cellSet().hashCode();
146  }
147
148  /**
149   * Returns the string representation {@code rowMap().toString()}.
150   */
151  @Override public String toString() {
152    return rowMap().toString();
153  }
154
155  // Mutators
156
157  @Override public void clear() {
158    backingMap.clear();
159  }
160
161  private Map<C, V> getOrCreate(R rowKey) {
162    Map<C, V> map = backingMap.get(rowKey);
163    if (map == null) {
164      map = factory.get();
165      backingMap.put(rowKey, map);
166    }
167    return map;
168  }
169
170  @Override public V put(R rowKey, C columnKey, V value) {
171    checkNotNull(rowKey);
172    checkNotNull(columnKey);
173    checkNotNull(value);
174    return getOrCreate(rowKey).put(columnKey, value);
175  }
176
177  @Override public void putAll(
178      Table<? extends R, ? extends C, ? extends V> table) {
179    for (Cell<? extends R, ? extends C, ? extends V> cell : table.cellSet()) {
180      put(cell.getRowKey(), cell.getColumnKey(), cell.getValue());
181    }
182  }
183
184  @Override public V remove(
185      @Nullable Object rowKey, @Nullable Object columnKey) {
186    if ((rowKey == null) || (columnKey == null)) {
187      return null;
188    }
189    Map<C, V> map = safeGet(backingMap, rowKey);
190    if (map == null) {
191      return null;
192    }
193    V value = map.remove(columnKey);
194    if (map.isEmpty()) {
195      backingMap.remove(rowKey);
196    }
197    return value;
198  }
199
200  private Map<R, V> removeColumn(Object column) {
201    Map<R, V> output = new LinkedHashMap<R, V>();
202    Iterator<Entry<R, Map<C, V>>> iterator
203        = backingMap.entrySet().iterator();
204    while (iterator.hasNext()) {
205      Entry<R, Map<C, V>> entry = iterator.next();
206      V value = entry.getValue().remove(column);
207      if (value != null) {
208        output.put(entry.getKey(), value);
209        if (entry.getValue().isEmpty()) {
210          iterator.remove();
211        }
212      }
213    }
214    return output;
215  }
216
217  private boolean containsMapping(
218      Object rowKey, Object columnKey, Object value) {
219    return value != null && value.equals(get(rowKey, columnKey));
220  }
221
222  /** Remove a row key / column key / value mapping, if present. */
223  private boolean removeMapping(Object rowKey, Object columnKey, Object value) {
224    if (containsMapping(rowKey, columnKey, value)) {
225      remove(rowKey, columnKey);
226      return true;
227    }
228    return false;
229  }
230
231  // Views
232
233  /**
234   * Abstract collection whose {@code isEmpty()} returns whether the table is
235   * empty and whose {@code clear()} clears all table mappings.
236   */
237  private abstract class TableCollection<T> extends AbstractCollection<T> {
238    @Override public boolean isEmpty() {
239      return backingMap.isEmpty();
240    }
241
242    @Override public void clear() {
243      backingMap.clear();
244    }
245  }
246
247  /**
248   * Abstract set whose {@code isEmpty()} returns whether the table is empty and
249   * whose {@code clear()} clears all table mappings.
250   */
251  private abstract class TableSet<T> extends AbstractSet<T> {
252    @Override public boolean isEmpty() {
253      return backingMap.isEmpty();
254    }
255
256    @Override public void clear() {
257      backingMap.clear();
258    }
259  }
260
261  private transient CellSet cellSet;
262
263  /**
264   * {@inheritDoc}
265   *
266   * <p>The set's iterator traverses the mappings for the first row, the
267   * mappings for the second row, and so on.
268   *
269   * <p>Each cell is an immutable snapshot of a row key / column key / value
270   * mapping, taken at the time the cell is returned by a method call to the
271   * set or its iterator.
272   */
273  @Override public Set<Cell<R, C, V>> cellSet() {
274    CellSet result = cellSet;
275    return (result == null) ? cellSet = new CellSet() : result;
276  }
277
278  private class CellSet extends TableSet<Cell<R, C, V>> {
279    @Override public Iterator<Cell<R, C, V>> iterator() {
280      return new CellIterator();
281    }
282
283    @Override public int size() {
284      return StandardTable.this.size();
285    }
286
287    @Override public boolean contains(Object obj) {
288      if (obj instanceof Cell) {
289        Cell<?, ?, ?> cell = (Cell<?, ?, ?>) obj;
290        return containsMapping(
291            cell.getRowKey(), cell.getColumnKey(), cell.getValue());
292      }
293      return false;
294    }
295
296    @Override public boolean remove(Object obj) {
297      if (obj instanceof Cell) {
298        Cell<?, ?, ?> cell = (Cell<?, ?, ?>) obj;
299        return removeMapping(
300            cell.getRowKey(), cell.getColumnKey(), cell.getValue());
301      }
302      return false;
303    }
304  }
305
306  private class CellIterator implements Iterator<Cell<R, C, V>> {
307    final Iterator<Entry<R, Map<C, V>>> rowIterator
308        = backingMap.entrySet().iterator();
309    Entry<R, Map<C, V>> rowEntry;
310    Iterator<Entry<C, V>> columnIterator
311        = Iterators.emptyModifiableIterator();
312
313    @Override public boolean hasNext() {
314      return rowIterator.hasNext() || columnIterator.hasNext();
315    }
316
317    @Override public Cell<R, C, V> next() {
318      if (!columnIterator.hasNext()) {
319        rowEntry = rowIterator.next();
320        columnIterator = rowEntry.getValue().entrySet().iterator();
321      }
322      Entry<C, V> columnEntry = columnIterator.next();
323      return Tables.immutableCell(
324          rowEntry.getKey(), columnEntry.getKey(), columnEntry.getValue());
325    }
326
327    @Override public void remove() {
328      columnIterator.remove();
329      if (rowEntry.getValue().isEmpty()) {
330        rowIterator.remove();
331      }
332    }
333  }
334
335  @Override public Map<C, V> row(R rowKey) {
336    return new Row(rowKey);
337  }
338
339  class Row extends AbstractMap<C, V> {
340    final R rowKey;
341
342    Row(R rowKey) {
343      this.rowKey = checkNotNull(rowKey);
344    }
345
346    Map<C, V> backingRowMap;
347
348    Map<C, V> backingRowMap() {
349      return (backingRowMap == null
350              || (backingRowMap.isEmpty() && backingMap.containsKey(rowKey)))
351          ? backingRowMap = computeBackingRowMap()
352          : backingRowMap;
353    }
354
355    Map<C, V> computeBackingRowMap() {
356      return backingMap.get(rowKey);
357    }
358
359    // Call this every time we perform a removal.
360    void maintainEmptyInvariant() {
361      if (backingRowMap() != null && backingRowMap.isEmpty()) {
362        backingMap.remove(rowKey);
363        backingRowMap = null;
364      }
365    }
366
367    @Override
368    public boolean containsKey(Object key) {
369      Map<C, V> backingRowMap = backingRowMap();
370      return (key != null && backingRowMap != null)
371          && Maps.safeContainsKey(backingRowMap, key);
372    }
373
374    @Override
375    public V get(Object key) {
376      Map<C, V> backingRowMap = backingRowMap();
377      return (key != null && backingRowMap != null)
378          ? Maps.safeGet(backingRowMap, key)
379          : null;
380    }
381
382    @Override
383    public V put(C key, V value) {
384      checkNotNull(key);
385      checkNotNull(value);
386      if (backingRowMap != null && !backingRowMap.isEmpty()) {
387        return backingRowMap.put(key, value);
388      }
389      return StandardTable.this.put(rowKey, key, value);
390    }
391
392    @Override
393    public V remove(Object key) {
394      try {
395        Map<C, V> backingRowMap = backingRowMap();
396        if (backingRowMap == null) {
397          return null;
398        }
399        V result = backingRowMap.remove(key);
400        maintainEmptyInvariant();
401        return result;
402      } catch (ClassCastException e) {
403        return null;
404      }
405    }
406
407    @Override
408    public void clear() {
409      Map<C, V> backingRowMap = backingRowMap();
410      if (backingRowMap != null) {
411        backingRowMap.clear();
412      }
413      maintainEmptyInvariant();
414    }
415
416    Set<C> keySet;
417
418    @Override
419    public Set<C> keySet() {
420      Set<C> result = keySet;
421      if (result == null) {
422        return keySet = new Maps.KeySet<C, V>() {
423          @Override
424          Map<C, V> map() {
425            return Row.this;
426          }
427        };
428      }
429      return result;
430    }
431
432    Set<Entry<C, V>> entrySet;
433
434    @Override
435    public Set<Entry<C, V>> entrySet() {
436      Set<Entry<C, V>> result = entrySet;
437      if (result == null) {
438        return entrySet = new RowEntrySet();
439      }
440      return result;
441    }
442
443    private class RowEntrySet extends Maps.EntrySet<C, V> {
444      @Override
445      Map<C, V> map() {
446        return Row.this;
447      }
448
449      @Override
450      public int size() {
451        Map<C, V> map = backingRowMap();
452        return (map == null) ? 0 : map.size();
453      }
454
455      @Override
456      public Iterator<Entry<C, V>> iterator() {
457        final Map<C, V> map = backingRowMap();
458        if (map == null) {
459          return Iterators.emptyModifiableIterator();
460        }
461        final Iterator<Entry<C, V>> iterator = map.entrySet().iterator();
462        return new Iterator<Entry<C, V>>() {
463          @Override public boolean hasNext() {
464            return iterator.hasNext();
465          }
466          @Override public Entry<C, V> next() {
467            final Entry<C, V> entry = iterator.next();
468            return new ForwardingMapEntry<C, V>() {
469              @Override protected Entry<C, V> delegate() {
470                return entry;
471              }
472              @Override public V setValue(V value) {
473                return super.setValue(checkNotNull(value));
474              }
475              @Override
476              public boolean equals(Object object) {
477                // TODO(user): identify why this affects GWT tests
478                return standardEquals(object);
479              }
480            };
481          }
482
483          @Override
484          public void remove() {
485            iterator.remove();
486            maintainEmptyInvariant();
487          }
488        };
489      }
490    }
491  }
492
493  /**
494   * {@inheritDoc}
495   *
496   * <p>The returned map's views have iterators that don't support
497   * {@code remove()}.
498   */
499  @Override public Map<R, V> column(C columnKey) {
500    return new Column(columnKey);
501  }
502
503  private class Column extends Maps.ImprovedAbstractMap<R, V> {
504    final C columnKey;
505
506    Column(C columnKey) {
507      this.columnKey = checkNotNull(columnKey);
508    }
509
510    @Override public V put(R key, V value) {
511      return StandardTable.this.put(key, columnKey, value);
512    }
513
514    @Override public V get(Object key) {
515      return StandardTable.this.get(key, columnKey);
516    }
517
518    @Override public boolean containsKey(Object key) {
519      return StandardTable.this.contains(key, columnKey);
520    }
521
522    @Override public V remove(Object key) {
523      return StandardTable.this.remove(key, columnKey);
524    }
525
526    @Override public Set<Entry<R, V>> createEntrySet() {
527      return new EntrySet();
528    }
529
530    Values columnValues;
531
532    @Override public Collection<V> values() {
533      Values result = columnValues;
534      return (result == null) ? columnValues = new Values() : result;
535    }
536
537    /**
538     * Removes all {@code Column} mappings whose row key and value satisfy the
539     * given predicate.
540     */
541    boolean removePredicate(Predicate<? super Entry<R, V>> predicate) {
542      boolean changed = false;
543      Iterator<Entry<R, Map<C, V>>> iterator
544          = backingMap.entrySet().iterator();
545      while (iterator.hasNext()) {
546        Entry<R, Map<C, V>> entry = iterator.next();
547        Map<C, V> map = entry.getValue();
548        V value = map.get(columnKey);
549        if (value != null
550            && predicate.apply(
551                new ImmutableEntry<R, V>(entry.getKey(), value))) {
552          map.remove(columnKey);
553          changed = true;
554          if (map.isEmpty()) {
555            iterator.remove();
556          }
557        }
558      }
559      return changed;
560    }
561
562    class EntrySet extends AbstractSet<Entry<R, V>> {
563      @Override public Iterator<Entry<R, V>> iterator() {
564        return new EntrySetIterator();
565      }
566
567      @Override public int size() {
568        int size = 0;
569        for (Map<C, V> map : backingMap.values()) {
570          if (map.containsKey(columnKey)) {
571            size++;
572          }
573        }
574        return size;
575      }
576
577      @Override public boolean isEmpty() {
578        return !containsColumn(columnKey);
579      }
580
581      @Override public void clear() {
582        Predicate<Entry<R, V>> predicate = Predicates.alwaysTrue();
583        removePredicate(predicate);
584      }
585
586      @Override public boolean contains(Object o) {
587        if (o instanceof Entry) {
588          Entry<?, ?> entry = (Entry<?, ?>) o;
589          return containsMapping(entry.getKey(), columnKey, entry.getValue());
590        }
591        return false;
592      }
593
594      @Override public boolean remove(Object obj) {
595        if (obj instanceof Entry) {
596          Entry<?, ?> entry = (Entry<?, ?>) obj;
597          return removeMapping(entry.getKey(), columnKey, entry.getValue());
598        }
599        return false;
600      }
601
602      @Override public boolean removeAll(Collection<?> c) {
603        boolean changed = false;
604        for (Object obj : c) {
605          changed |= remove(obj);
606        }
607        return changed;
608      }
609
610      @Override public boolean retainAll(Collection<?> c) {
611        return removePredicate(Predicates.not(Predicates.in(c)));
612      }
613    }
614
615    class EntrySetIterator extends AbstractIterator<Entry<R, V>> {
616      final Iterator<Entry<R, Map<C, V>>> iterator
617          = backingMap.entrySet().iterator();
618      @Override protected Entry<R, V> computeNext() {
619        while (iterator.hasNext()) {
620          final Entry<R, Map<C, V>> entry = iterator.next();
621          if (entry.getValue().containsKey(columnKey)) {
622            return new AbstractMapEntry<R, V>() {
623              @Override public R getKey() {
624                return entry.getKey();
625              }
626              @Override public V getValue() {
627                return entry.getValue().get(columnKey);
628              }
629              @Override public V setValue(V value) {
630                return entry.getValue().put(columnKey, checkNotNull(value));
631              }
632            };
633          }
634        }
635        return endOfData();
636      }
637    }
638
639    KeySet keySet;
640
641    @Override public Set<R> keySet() {
642      KeySet result = keySet;
643      return result == null ? keySet = new KeySet() : result;
644    }
645
646    class KeySet extends AbstractSet<R> {
647      @Override public Iterator<R> iterator() {
648        return keyIteratorImpl(Column.this);
649      }
650
651      @Override public int size() {
652        return entrySet().size();
653      }
654
655      @Override public boolean isEmpty() {
656        return !containsColumn(columnKey);
657      }
658
659      @Override public boolean contains(Object obj) {
660        return StandardTable.this.contains(obj, columnKey);
661      }
662
663      @Override public boolean remove(Object obj) {
664        return StandardTable.this.remove(obj, columnKey) != null;
665      }
666
667      @Override public void clear() {
668        entrySet().clear();
669      }
670
671      @Override public boolean removeAll(final Collection<?> c) {
672        boolean changed = false;
673        for (Object obj : c) {
674          changed |= remove(obj);
675        }
676        return changed;
677      }
678
679      @Override public boolean retainAll(final Collection<?> c) {
680        checkNotNull(c);
681        Predicate<Entry<R, V>> predicate = new Predicate<Entry<R, V>>() {
682          @Override
683          public boolean apply(Entry<R, V> entry) {
684            return !c.contains(entry.getKey());
685          }
686        };
687        return removePredicate(predicate);
688      }
689    }
690
691    class Values extends AbstractCollection<V> {
692      @Override public Iterator<V> iterator() {
693        return valueIteratorImpl(Column.this);
694      }
695
696      @Override public int size() {
697        return entrySet().size();
698      }
699
700      @Override public boolean isEmpty() {
701        return !containsColumn(columnKey);
702      }
703
704      @Override public void clear() {
705        entrySet().clear();
706      }
707
708      @Override public boolean remove(Object obj) {
709        if (obj == null) {
710          return false;
711        }
712        Iterator<Map<C, V>> iterator = backingMap.values().iterator();
713        while (iterator.hasNext()) {
714          Map<C, V> map = iterator.next();
715          if (map.entrySet().remove(
716              new ImmutableEntry<C, Object>(columnKey, obj))) {
717            if (map.isEmpty()) {
718              iterator.remove();
719            }
720            return true;
721          }
722        }
723        return false;
724      }
725
726      @Override public boolean removeAll(final Collection<?> c) {
727        checkNotNull(c);
728        Predicate<Entry<R, V>> predicate = new Predicate<Entry<R, V>>() {
729          @Override
730          public boolean apply(Entry<R, V> entry) {
731            return c.contains(entry.getValue());
732          }
733        };
734        return removePredicate(predicate);
735      }
736
737      @Override public boolean retainAll(final Collection<?> c) {
738        checkNotNull(c);
739        Predicate<Entry<R, V>> predicate = new Predicate<Entry<R, V>>() {
740          @Override
741          public boolean apply(Entry<R, V> entry) {
742            return !c.contains(entry.getValue());
743          }
744        };
745        return removePredicate(predicate);
746      }
747    }
748  }
749
750  private transient RowKeySet rowKeySet;
751
752  @Override public Set<R> rowKeySet() {
753    Set<R> result = rowKeySet;
754    return (result == null) ? rowKeySet = new RowKeySet() : result;
755  }
756
757  class RowKeySet extends TableSet<R> {
758    @Override public Iterator<R> iterator() {
759      return keyIteratorImpl(rowMap());
760    }
761
762    @Override public int size() {
763      return backingMap.size();
764    }
765
766    @Override public boolean contains(Object obj) {
767      return containsRow(obj);
768    }
769
770    @Override public boolean remove(Object obj) {
771      return (obj != null) && backingMap.remove(obj) != null;
772    }
773  }
774
775  private transient Set<C> columnKeySet;
776
777  /**
778   * {@inheritDoc}
779   *
780   * <p>The returned set has an iterator that does not support {@code remove()}.
781   *
782   * <p>The set's iterator traverses the columns of the first row, the
783   * columns of the second row, etc., skipping any columns that have
784   * appeared previously.
785   */
786  @Override
787  public Set<C> columnKeySet() {
788    Set<C> result = columnKeySet;
789    return (result == null) ? columnKeySet = new ColumnKeySet() : result;
790  }
791
792  private class ColumnKeySet extends TableSet<C> {
793    @Override public Iterator<C> iterator() {
794      return createColumnKeyIterator();
795    }
796
797    @Override public int size() {
798      return Iterators.size(iterator());
799    }
800
801    @Override public boolean remove(Object obj) {
802      if (obj == null) {
803        return false;
804      }
805      boolean changed = false;
806      Iterator<Map<C, V>> iterator = backingMap.values().iterator();
807      while (iterator.hasNext()) {
808        Map<C, V> map = iterator.next();
809        if (map.keySet().remove(obj)) {
810          changed = true;
811          if (map.isEmpty()) {
812            iterator.remove();
813          }
814        }
815      }
816      return changed;
817    }
818
819    @Override public boolean removeAll(Collection<?> c) {
820      checkNotNull(c);
821      boolean changed = false;
822      Iterator<Map<C, V>> iterator = backingMap.values().iterator();
823      while (iterator.hasNext()) {
824        Map<C, V> map = iterator.next();
825        // map.keySet().removeAll(c) can throw a NPE when map is a TreeMap with
826        // natural ordering and c contains a null.
827        if (Iterators.removeAll(map.keySet().iterator(), c)) {
828          changed = true;
829          if (map.isEmpty()) {
830            iterator.remove();
831          }
832        }
833      }
834      return changed;
835    }
836
837    @Override public boolean retainAll(Collection<?> c) {
838      checkNotNull(c);
839      boolean changed = false;
840      Iterator<Map<C, V>> iterator = backingMap.values().iterator();
841      while (iterator.hasNext()) {
842        Map<C, V> map = iterator.next();
843        if (map.keySet().retainAll(c)) {
844          changed = true;
845          if (map.isEmpty()) {
846            iterator.remove();
847          }
848        }
849      }
850      return changed;
851    }
852
853    @Override public boolean contains(Object obj) {
854      if (obj == null) {
855        return false;
856      }
857      for (Map<C, V> map : backingMap.values()) {
858        if (map.containsKey(obj)) {
859          return true;
860        }
861      }
862      return false;
863    }
864  }
865
866  /**
867   * Creates an iterator that returns each column value with duplicates
868   * omitted.
869   */
870  Iterator<C> createColumnKeyIterator() {
871    return new ColumnKeyIterator();
872  }
873
874  private class ColumnKeyIterator extends AbstractIterator<C> {
875    // Use the same map type to support TreeMaps with comparators that aren't
876    // consistent with equals().
877    final Map<C, V> seen = factory.get();
878    final Iterator<Map<C, V>> mapIterator = backingMap.values().iterator();
879    Iterator<Entry<C, V>> entryIterator = Iterators.emptyIterator();
880
881    @Override protected C computeNext() {
882      while (true) {
883        if (entryIterator.hasNext()) {
884          Entry<C, V> entry = entryIterator.next();
885          if (!seen.containsKey(entry.getKey())) {
886            seen.put(entry.getKey(), entry.getValue());
887            return entry.getKey();
888          }
889        } else if (mapIterator.hasNext()) {
890          entryIterator = mapIterator.next().entrySet().iterator();
891        } else {
892          return endOfData();
893        }
894      }
895    }
896  }
897
898  private transient Values values;
899
900  /**
901   * {@inheritDoc}
902   *
903   * <p>The collection's iterator traverses the values for the first row,
904   * the values for the second row, and so on.
905   */
906  @Override public Collection<V> values() {
907    Values result = values;
908    return (result == null) ? values = new Values() : result;
909  }
910
911  private class Values extends TableCollection<V> {
912    @Override public Iterator<V> iterator() {
913      final Iterator<Cell<R, C, V>> cellIterator = cellSet().iterator();
914      return new Iterator<V>() {
915        @Override public boolean hasNext() {
916          return cellIterator.hasNext();
917        }
918        @Override public V next() {
919          return cellIterator.next().getValue();
920        }
921        @Override public void remove() {
922          cellIterator.remove();
923        }
924      };
925    }
926
927    @Override public int size() {
928      return StandardTable.this.size();
929    }
930  }
931
932  private transient RowMap rowMap;
933
934  @Override public Map<R, Map<C, V>> rowMap() {
935    RowMap result = rowMap;
936    return (result == null) ? rowMap = new RowMap() : result;
937  }
938
939  class RowMap extends Maps.ImprovedAbstractMap<R, Map<C, V>> {
940    @Override public boolean containsKey(Object key) {
941      return containsRow(key);
942    }
943
944    // performing cast only when key is in backing map and has the correct type
945    @SuppressWarnings("unchecked")
946    @Override public Map<C, V> get(Object key) {
947      return containsRow(key) ? row((R) key) : null;
948    }
949
950    @Override public Set<R> keySet() {
951      return rowKeySet();
952    }
953
954    @Override public Map<C, V> remove(Object key) {
955      return (key == null) ? null : backingMap.remove(key);
956    }
957
958    @Override protected Set<Entry<R, Map<C, V>>> createEntrySet() {
959      return new EntrySet();
960    }
961
962    class EntrySet extends TableSet<Entry<R, Map<C, V>>> {
963      @Override public Iterator<Entry<R, Map<C, V>>> iterator() {
964        return new EntryIterator();
965      }
966
967      @Override public int size() {
968        return backingMap.size();
969      }
970
971      @Override public boolean contains(Object obj) {
972        if (obj instanceof Entry) {
973          Entry<?, ?> entry = (Entry<?, ?>) obj;
974          return entry.getKey() != null
975              && entry.getValue() instanceof Map
976              && Collections2.safeContains(backingMap.entrySet(), entry);
977        }
978        return false;
979      }
980
981      @Override public boolean remove(Object obj) {
982        if (obj instanceof Entry) {
983          Entry<?, ?> entry = (Entry<?, ?>) obj;
984          return entry.getKey() != null
985              && entry.getValue() instanceof Map
986              && backingMap.entrySet().remove(entry);
987        }
988        return false;
989      }
990    }
991
992    class EntryIterator implements Iterator<Entry<R, Map<C, V>>> {
993      final Iterator<R> delegate = backingMap.keySet().iterator();
994
995      @Override public boolean hasNext() {
996        return delegate.hasNext();
997      }
998
999      @Override public Entry<R, Map<C, V>> next() {
1000        R rowKey = delegate.next();
1001        return new ImmutableEntry<R, Map<C, V>>(rowKey, row(rowKey));
1002      }
1003
1004      @Override public void remove() {
1005        delegate.remove();
1006      }
1007    }
1008  }
1009
1010  private transient ColumnMap columnMap;
1011
1012  @Override public Map<C, Map<R, V>> columnMap() {
1013    ColumnMap result = columnMap;
1014    return (result == null) ? columnMap = new ColumnMap() : result;
1015  }
1016
1017  private class ColumnMap extends Maps.ImprovedAbstractMap<C, Map<R, V>> {
1018    // The cast to C occurs only when the key is in the map, implying that it
1019    // has the correct type.
1020    @SuppressWarnings("unchecked")
1021    @Override public Map<R, V> get(Object key) {
1022      return containsColumn(key) ? column((C) key) : null;
1023    }
1024
1025    @Override public boolean containsKey(Object key) {
1026      return containsColumn(key);
1027    }
1028
1029    @Override public Map<R, V> remove(Object key) {
1030      return containsColumn(key) ? removeColumn(key) : null;
1031    }
1032
1033    @Override public Set<Entry<C, Map<R, V>>> createEntrySet() {
1034      return new ColumnMapEntrySet();
1035    }
1036
1037    @Override public Set<C> keySet() {
1038      return columnKeySet();
1039    }
1040
1041    ColumnMapValues columnMapValues;
1042
1043    @Override public Collection<Map<R, V>> values() {
1044      ColumnMapValues result = columnMapValues;
1045      return
1046          (result == null) ? columnMapValues = new ColumnMapValues() : result;
1047    }
1048
1049    class ColumnMapEntrySet extends TableSet<Entry<C, Map<R, V>>> {
1050      @Override public Iterator<Entry<C, Map<R, V>>> iterator() {
1051        final Iterator<C> columnIterator = columnKeySet().iterator();
1052        return new UnmodifiableIterator<Entry<C, Map<R, V>>>() {
1053          @Override public boolean hasNext() {
1054            return columnIterator.hasNext();
1055          }
1056          @Override public Entry<C, Map<R, V>> next() {
1057            C columnKey = columnIterator.next();
1058            return new ImmutableEntry<C, Map<R, V>>(
1059                columnKey, column(columnKey));
1060          }
1061        };
1062      }
1063
1064      @Override public int size() {
1065        return columnKeySet().size();
1066      }
1067
1068      @Override public boolean contains(Object obj) {
1069        if (obj instanceof Entry) {
1070          Entry<?, ?> entry = (Entry<?, ?>) obj;
1071          if (containsColumn(entry.getKey())) {
1072            // The cast to C occurs only when the key is in the map, implying
1073            // that it has the correct type.
1074            @SuppressWarnings("unchecked")
1075            C columnKey = (C) entry.getKey();
1076            return get(columnKey).equals(entry.getValue());
1077          }
1078        }
1079        return false;
1080      }
1081
1082      @Override public boolean remove(Object obj) {
1083        if (contains(obj)) {
1084          Entry<?, ?> entry = (Entry<?, ?>) obj;
1085          removeColumn(entry.getKey());
1086          return true;
1087        }
1088        return false;
1089      }
1090
1091      @Override public boolean removeAll(Collection<?> c) {
1092        boolean changed = false;
1093        for (Object obj : c) {
1094          changed |= remove(obj);
1095        }
1096        return changed;
1097      }
1098
1099      @Override public boolean retainAll(Collection<?> c) {
1100        boolean changed = false;
1101        for (C columnKey : Lists.newArrayList(columnKeySet().iterator())) {
1102          if (!c.contains(new ImmutableEntry<C, Map<R, V>>(
1103              columnKey, column(columnKey)))) {
1104            removeColumn(columnKey);
1105            changed = true;
1106          }
1107        }
1108        return changed;
1109      }
1110    }
1111
1112    private class ColumnMapValues extends TableCollection<Map<R, V>> {
1113      @Override public Iterator<Map<R, V>> iterator() {
1114        return valueIteratorImpl(ColumnMap.this);
1115      }
1116
1117      @Override public boolean remove(Object obj) {
1118        for (Entry<C, Map<R, V>> entry : ColumnMap.this.entrySet()) {
1119          if (entry.getValue().equals(obj)) {
1120            removeColumn(entry.getKey());
1121            return true;
1122          }
1123        }
1124        return false;
1125      }
1126
1127      @Override public boolean removeAll(Collection<?> c) {
1128        checkNotNull(c);
1129        boolean changed = false;
1130        for (C columnKey : Lists.newArrayList(columnKeySet().iterator())) {
1131          if (c.contains(column(columnKey))) {
1132            removeColumn(columnKey);
1133            changed = true;
1134          }
1135        }
1136        return changed;
1137      }
1138
1139      @Override public boolean retainAll(Collection<?> c) {
1140        checkNotNull(c);
1141        boolean changed = false;
1142        for (C columnKey : Lists.newArrayList(columnKeySet().iterator())) {
1143          if (!c.contains(column(columnKey))) {
1144            removeColumn(columnKey);
1145            changed = true;
1146          }
1147        }
1148        return changed;
1149      }
1150
1151      @Override public int size() {
1152        return columnKeySet().size();
1153      }
1154    }
1155  }
1156
1157  private static final long serialVersionUID = 0;
1158
1159  // TODO(kevinb): Move keyIteratorImpl and valueIteratorImpl to Maps, reuse
1160
1161  /**
1162   * Generates the iterator of a map's key set from the map's entry set
1163   * iterator.
1164   */
1165  static <K, V> Iterator<K> keyIteratorImpl(Map<K, V> map) {
1166    final Iterator<Entry<K, V>> entryIterator = map.entrySet().iterator();
1167    return new Iterator<K>() {
1168      @Override public boolean hasNext() {
1169        return entryIterator.hasNext();
1170      }
1171      @Override public K next() {
1172        return entryIterator.next().getKey();
1173      }
1174      @Override public void remove() {
1175        entryIterator.remove();
1176      }
1177    };
1178  }
1179
1180  /**
1181   * Generates the iterator of a map's value collection from the map's entry set
1182   * iterator.
1183   */
1184  static <K, V> Iterator<V> valueIteratorImpl(Map<K, V> map) {
1185    final Iterator<Entry<K, V>> entryIterator = map.entrySet().iterator();
1186    return new Iterator<V>() {
1187      @Override public boolean hasNext() {
1188        return entryIterator.hasNext();
1189      }
1190      @Override public V next() {
1191        return entryIterator.next().getValue();
1192      }
1193      @Override public void remove() {
1194        entryIterator.remove();
1195      }
1196    };
1197  }
1198}
1199