source: osm/applications/editors/josm/plugins/opendata/includes/org/geotools/util/DerivedMap.java@ 28000

Last change on this file since 28000 was 28000, checked in by donvip, 12 years ago

Import new "opendata" JOSM plugin

File size: 9.9 KB
Line 
1/*
2 * GeoTools - The Open Source Java GIS Toolkit
3 * http://geotools.org
4 *
5 * (C) 2004-2008, Open Source Geospatial Foundation (OSGeo)
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation;
10 * version 2.1 of the License.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 */
17package org.geotools.util;
18
19import java.io.Serializable;
20import java.util.AbstractMap;
21import java.util.Collection;
22import java.util.Map;
23import java.util.Set;
24
25
26/**
27 * A map whose keys are derived from an other map. The keys are derived only when
28 * requested, which make it possible to backup potentially large maps. Implementations
29 * need only to overrides {@link #baseToDerived} and {@link #derivedToBase} methods.
30 * This set do not supports {@code null} key, since {@code null} is used
31 * when no mapping from {@linkplain #base} to {@code this} exists.
32 * This class is serializable if the underlying {@linkplain #base} set is serializable
33 * too.
34 * <p>
35 * This class is <strong>not</strong> thread-safe. Synchronizations (if wanted) are user's
36 * reponsability.
37 *
38 * @param <BK> The type of keys in the backing map.
39 * @param <K> The type of keys in this map.
40 * @param <V> The type of values in both this map and the underlying map.
41 *
42 * @since 2.0
43 *
44 * @source $URL: http://svn.osgeo.org/geotools/branches/2.7.x/modules/library/metadata/src/main/java/org/geotools/util/DerivedMap.java $
45 * @version $Id: DerivedMap.java 37298 2011-05-25 05:16:15Z mbedward $
46 * @author Martin Desruisseaux (IRD)
47 */
48public abstract class DerivedMap<BK,K,V> extends AbstractMap<K,V> implements Serializable {
49 /**
50 * Serial number for interoperability with different versions.
51 */
52 private static final long serialVersionUID = -6994867383669885934L;
53
54 /**
55 * The base map whose keys are derived from.
56 *
57 * @see #baseToDerived
58 * @see #derivedToBase
59 */
60 protected final Map<BK,V> base;
61
62 /**
63 * Key set. Will be constructed only when first needed.
64 *
65 * @see #keySet
66 */
67 private transient Set<K> keySet;
68
69 /**
70 * Entry set. Will be constructed only when first needed.
71 *
72 * @see #entrySet
73 */
74 private transient Set<Map.Entry<K,V>> entrySet;
75
76 /**
77 * The derived key type.
78 */
79 private final Class<K> keyType;
80
81 /**
82 * Creates a new derived map from the specified base map.
83 *
84 * @param base The base map.
85 * @param keyType the type of keys in the derived map.
86 *
87 * @since 2.5
88 */
89 public DerivedMap(final Map<BK,V> base, final Class<K> keyType) {
90 this.base = base;
91 this.keyType = keyType;
92 }
93
94 /**
95 * Transforms a key from the {@linkplain #base} map to a key in this map.
96 * If there is no key in the derived map for the specified base key,
97 * then this method returns {@code null}.
98 *
99 * @param key A ley from the {@linkplain #base} map.
100 * @return The key that this view should contains instead of {@code key},
101 * or {@code null}.
102 */
103 protected abstract K baseToDerived(final BK key);
104
105 /**
106 * Transforms a key from this derived map to a key in the {@linkplain #base} map.
107 *
108 * @param key A key in this map.
109 * @return The key stored in the {@linkplain #base} map.
110 */
111 protected abstract BK derivedToBase(final K key);
112
113 /**
114 * Returns the number of key-value mappings in this map.
115 *
116 * @return the number of key-value mappings in this map.
117 */
118 @Override
119 public int size() {
120 return super.size();
121 }
122
123 /**
124 * Returns {@code true} if this map contains no key-value mappings.
125 *
126 * @return {@code true} if this map contains no key-value mappings.
127 */
128 @Override
129 public boolean isEmpty() {
130 return base.isEmpty() || super.isEmpty();
131 }
132
133 /**
134 * Returns {@code true} if this map maps one or more keys to this value.
135 * The default implementation invokes
136 * <code>{@linkplain #base}.containsValue(value)</code>.
137 *
138 * @return {@code true} if this map maps one or more keys to this value.
139 */
140 @Override
141 public boolean containsValue(final Object value) {
142 return base.containsValue(value);
143 }
144
145 /**
146 * Returns {@code true} if this map contains a mapping for the specified key.
147 * The default implementation invokes
148 * <code>{@linkplain #base}.containsKey({@linkplain #derivedToBase derivedToBase}(key))</code>.
149 *
150 * @param key key whose presence in this map is to be tested.
151 * @return {@code true} if this map contains a mapping for the specified key.
152 */
153 @Override
154 public boolean containsKey(final Object key) {
155 if (keyType.isInstance(key)) {
156 return base.containsKey(derivedToBase(keyType.cast(key)));
157 } else {
158 return false;
159 }
160 }
161
162 /**
163 * Returns the value to which this map maps the specified key.
164 * The default implementation invokes
165 * <code>{@linkplain #base}.get({@linkplain #derivedToBase derivedToBase}(key))</code>.
166 *
167 * @param key key whose associated value is to be returned.
168 * @return the value to which this map maps the specified key.
169 */
170 @Override
171 public V get(final Object key) {
172 if (keyType.isInstance(key)) {
173 return base.get(derivedToBase(keyType.cast(key)));
174 } else {
175 return null;
176 }
177 }
178
179 /**
180 * Associates the specified value with the specified key in this map.
181 * The default implementation invokes
182 * <code>{@linkplain #base}.put({@linkplain #derivedToBase derivedToBase}(key), value)</code>.
183 *
184 * @param key key with which the specified value is to be associated.
185 * @param value value to be associated with the specified key.
186 * @return previous value associated with specified key, or {@code null}
187 * if there was no mapping for key.
188 * @throws UnsupportedOperationException if the {@linkplain #base} map doesn't
189 * supports the {@code put} operation.
190 */
191 @Override
192 public V put(final K key, final V value) throws UnsupportedOperationException {
193 return base.put(derivedToBase(key), value);
194 }
195
196 /**
197 * Removes the mapping for this key from this map if present.
198 * The default implementation invokes
199 * <code>{@linkplain #base}.remove({@linkplain #derivedToBase derivedToBase}(key))</code>.
200 *
201 * @param key key whose mapping is to be removed from the map.
202 * @return previous value associated with specified key, or {@code null}
203 * if there was no entry for key.
204 * @throws UnsupportedOperationException if the {@linkplain #base} map doesn't
205 * supports the {@code remove} operation.
206 */
207 @Override
208 public V remove(final Object key) throws UnsupportedOperationException {
209 if (keyType.isInstance(key)) {
210 return base.remove(derivedToBase(keyType.cast(key)));
211 } else {
212 return null;
213 }
214 }
215
216 /**
217 * Returns a set view of the keys contained in this map.
218 *
219 * @return a set view of the keys contained in this map.
220 */
221 @Override
222 public Set<K> keySet() {
223 if (keySet == null) {
224 keySet = new KeySet(base.keySet());
225 }
226 return keySet;
227 }
228
229 /**
230 * Returns a collection view of the values contained in this map.
231 *
232 * @return a collection view of the values contained in this map.
233 */
234 @Override
235 public Collection<V> values() {
236 return base.values();
237 }
238
239 /**
240 * Returns a set view of the mappings contained in this map.
241 *
242 * @return a set view of the mappings contained in this map.
243 */
244 @Override
245 @SuppressWarnings("unchecked")
246 public Set<Map.Entry<K,V>> entrySet() {
247 if (entrySet == null) {
248 entrySet = (Set) new EntrySet(base.entrySet());
249 }
250 return entrySet;
251 }
252
253 /**
254 * The key set.
255 */
256 private final class KeySet extends DerivedSet<BK,K> {
257 private static final long serialVersionUID = -2931806200277420177L;
258
259 public KeySet(final Set<BK> base) {
260 super(base, keyType);
261 }
262
263 protected K baseToDerived(final BK element) {
264 return DerivedMap.this.baseToDerived(element);
265 }
266
267 protected BK derivedToBase(final K element) {
268 return DerivedMap.this.derivedToBase(element);
269 }
270 }
271
272 /**
273 * The entry set.
274 */
275 private final class EntrySet extends DerivedSet<Map.Entry<BK,V>, Entry<BK,K,V>> {
276 private static final long serialVersionUID = -2931806200277420177L;
277
278 @SuppressWarnings("unchecked")
279 public EntrySet(final Set<Map.Entry<BK,V>> base) {
280 super(base, (Class) Entry.class);
281 }
282
283 protected Entry<BK,K,V> baseToDerived(final Map.Entry<BK,V> entry) {
284 final K derived = DerivedMap.this.baseToDerived(entry.getKey());
285 return derived!=null ? new Entry<BK,K,V>(entry, derived) : null;
286 }
287
288 protected Map.Entry<BK,V> derivedToBase(final Entry<BK,K,V> element) {
289 return element.entry;
290 }
291 }
292
293 /**
294 * The entry element.
295 */
296 private static final class Entry<BK,K,V> implements Map.Entry<K,V> {
297 public final Map.Entry<BK,V> entry;
298 private final K derived;
299
300 public Entry(final Map.Entry<BK,V> entry, final K derived) {
301 this.entry = entry;
302 this.derived = derived;
303 }
304
305 public K getKey() {
306 return derived;
307 }
308
309 public V getValue() {
310 return entry.getValue();
311 }
312
313 public V setValue(V value) {
314 return entry.setValue(value);
315 }
316 }
317}
Note: See TracBrowser for help on using the repository browser.