• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2007 Google Inc.
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 
17 package com.google.common.collect;
18 
19 import com.google.common.annotations.GwtCompatible;
20 import static com.google.common.base.Preconditions.checkNotNull;
21 
22 import java.util.Collection;
23 import java.util.Iterator;
24 import java.util.Map;
25 import java.util.Set;
26 
27 import javax.annotation.Nullable;
28 
29 /**
30  * Factory and utilities pertaining to the {@code MapConstraint} interface.
31  *
32  * @author Mike Bostock
33  */
34 @GwtCompatible
35 class ConstrainedMap<K, V> extends ForwardingMap<K, V> {
36   final Map<K, V> delegate;
37   final MapConstraint<? super K, ? super V> constraint;
38   private volatile Set<Entry<K, V>> entrySet;
39 
ConstrainedMap( Map<K, V> delegate, MapConstraint<? super K, ? super V> constraint)40   ConstrainedMap(
41       Map<K, V> delegate, MapConstraint<? super K, ? super V> constraint) {
42     this.delegate = checkNotNull(delegate);
43     this.constraint = checkNotNull(constraint);
44   }
45 
delegate()46   @Override protected Map<K, V> delegate() {
47     return delegate;
48   }
entrySet()49   @Override public Set<Entry<K, V>> entrySet() {
50     if (entrySet == null) {
51       entrySet = constrainedEntrySet(delegate.entrySet(), constraint);
52     }
53     return entrySet;
54   }
put(K key, V value)55   @Override public V put(K key, V value) {
56     constraint.checkKeyValue(key, value);
57     return delegate.put(key, value);
58   }
putAll(Map<? extends K, ? extends V> map)59   @Override public void putAll(Map<? extends K, ? extends V> map) {
60     for (Entry<? extends K, ? extends V> entry : map.entrySet()) {
61       put(entry.getKey(), entry.getValue());
62     }
63   }
64 
constrainedEntry( final Entry<K, V> entry, final MapConstraint<? super K, ? super V> constraint)65   private static <K, V> Entry<K, V> constrainedEntry(
66       final Entry<K, V> entry,
67       final MapConstraint<? super K, ? super V> constraint) {
68     checkNotNull(entry);
69     checkNotNull(constraint);
70     return new ForwardingMapEntry<K, V>() {
71       @Override protected Entry<K, V> delegate() {
72         return entry;
73       }
74       @Override public V setValue(V value) {
75         constraint.checkKeyValue(getKey(), value);
76         return entry.setValue(value);
77       }
78     };
79   }
80 
81   private static <K, V> Set<Entry<K, V>> constrainedEntrySet(
82       Set<Entry<K, V>> entries,
83       MapConstraint<? super K, ? super V> constraint) {
84     return new ConstrainedEntrySet<K, V>(entries, constraint);
85   }
86 
87   private static class ConstrainedEntries<K, V>
88       extends ForwardingCollection<Entry<K, V>> {
89     final MapConstraint<? super K, ? super V> constraint;
90     final Collection<Entry<K, V>> entries;
91 
92     ConstrainedEntries(Collection<Entry<K, V>> entries,
93         MapConstraint<? super K, ? super V> constraint) {
94       this.entries = entries;
95       this.constraint = constraint;
96     }
97     @Override protected Collection<Entry<K, V>> delegate() {
98       return entries;
99     }
100 
101     @Override public Iterator<Entry<K, V>> iterator() {
102       final Iterator<Entry<K, V>> iterator = entries.iterator();
103       return new ForwardingIterator<Entry<K, V>>() {
104         @Override public Entry<K, V> next() {
105           return constrainedEntry(iterator.next(), constraint);
106         }
107         @Override protected Iterator<Entry<K, V>> delegate() {
108           return iterator;
109         }
110       };
111     }
112 
113     // See Collections.CheckedMap.CheckedEntrySet for details on attacks.
114 
115     @Override public Object[] toArray() {
116       return ObjectArrays.toArrayImpl(this);
117     }
118     @Override public <T> T[] toArray(T[] array) {
119       return ObjectArrays.toArrayImpl(this, array);
120     }
121     @Override public boolean contains(Object o) {
122       return Maps.containsEntryImpl(delegate(), o);
123     }
124     @Override public boolean containsAll(Collection<?> c) {
125       return Collections2.containsAll(this, c);
126     }
127     @Override public boolean remove(Object o) {
128       return Maps.removeEntryImpl(delegate(), o);
129     }
130     @Override public boolean removeAll(Collection<?> c) {
131       return Iterators.removeAll(iterator(), c);
132     }
133     @Override public boolean retainAll(Collection<?> c) {
134       return Iterators.retainAll(iterator(), c);
135     }
136   }
137 
138   static class ConstrainedEntrySet<K, V>
139       extends ConstrainedEntries<K, V> implements Set<Entry<K, V>> {
140     ConstrainedEntrySet(Set<Entry<K, V>> entries,
141         MapConstraint<? super K, ? super V> constraint) {
142       super(entries, constraint);
143     }
144 
145     // See Collections.CheckedMap.CheckedEntrySet for details on attacks.
146 
147     @Override public boolean equals(@Nullable Object object) {
148       return Collections2.setEquals(this, object);
149     }
150 
151     @Override public int hashCode() {
152       return Sets.hashCodeImpl(this);
153     }
154   }
155 }
156