1/*
2 * Copyright (C) 2012 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 */
16package com.google.common.collect;
17
18import static com.google.common.base.Preconditions.checkNotNull;
19
20import com.google.common.annotations.GwtCompatible;
21
22import javax.annotation.Nullable;
23
24/**
25 * An implementation of an immutable sorted map with one or more entries.
26 *
27 * @author Louis Wasserman
28 */
29@GwtCompatible(emulated = true)
30@SuppressWarnings("serial") // uses writeReplace, not default serialization
31final class RegularImmutableSortedMap<K, V> extends ImmutableSortedMap<K, V> {
32  private final transient RegularImmutableSortedSet<K> keySet;
33  private final transient ImmutableList<V> valueList;
34
35  RegularImmutableSortedMap(RegularImmutableSortedSet<K> keySet, ImmutableList<V> valueList) {
36    this.keySet = keySet;
37    this.valueList = valueList;
38  }
39
40  RegularImmutableSortedMap(
41      RegularImmutableSortedSet<K> keySet,
42      ImmutableList<V> valueList,
43      ImmutableSortedMap<K, V> descendingMap) {
44    super(descendingMap);
45    this.keySet = keySet;
46    this.valueList = valueList;
47  }
48
49  @Override
50  ImmutableSet<Entry<K, V>> createEntrySet() {
51    return new EntrySet();
52  }
53
54  private class EntrySet extends ImmutableMapEntrySet<K, V> {
55    @Override
56    public UnmodifiableIterator<Entry<K, V>> iterator() {
57      return asList().iterator();
58    }
59
60    @Override
61    ImmutableList<Entry<K, V>> createAsList() {
62      return new ImmutableAsList<Entry<K, V>>() {
63        // avoid additional indirection
64        private final ImmutableList<K> keyList = keySet().asList();
65
66        @Override
67        public Entry<K, V> get(int index) {
68          return Maps.immutableEntry(keyList.get(index), valueList.get(index));
69        }
70
71        @Override
72        ImmutableCollection<Entry<K, V>> delegateCollection() {
73          return EntrySet.this;
74        }
75      };
76    }
77
78    @Override
79    ImmutableMap<K, V> map() {
80      return RegularImmutableSortedMap.this;
81    }
82  }
83
84  @Override
85  public ImmutableSortedSet<K> keySet() {
86    return keySet;
87  }
88
89  @Override
90  public ImmutableCollection<V> values() {
91    return valueList;
92  }
93
94  @Override
95  public V get(@Nullable Object key) {
96    int index = keySet.indexOf(key);
97    return (index == -1) ? null : valueList.get(index);
98  }
99
100  private ImmutableSortedMap<K, V> getSubMap(int fromIndex, int toIndex) {
101    if (fromIndex == 0 && toIndex == size()) {
102      return this;
103    } else if (fromIndex == toIndex) {
104      return emptyMap(comparator());
105    } else {
106      return from(
107          keySet.getSubSet(fromIndex, toIndex),
108          valueList.subList(fromIndex, toIndex));
109    }
110  }
111
112  @Override
113  public ImmutableSortedMap<K, V> headMap(K toKey, boolean inclusive) {
114    return getSubMap(0, keySet.headIndex(checkNotNull(toKey), inclusive));
115  }
116
117  @Override
118  public ImmutableSortedMap<K, V> tailMap(K fromKey, boolean inclusive) {
119    return getSubMap(keySet.tailIndex(checkNotNull(fromKey), inclusive), size());
120  }
121
122  @Override
123  ImmutableSortedMap<K, V> createDescendingMap() {
124    return new RegularImmutableSortedMap<K, V>(
125        (RegularImmutableSortedSet<K>) keySet.descendingSet(),
126        valueList.reverse(),
127        this);
128  }
129
130}
131