OLD | NEW |
| (Empty) |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | |
2 // for details. All rights reserved. Use of this source code is governed by a | |
3 // BSD-style license that can be found in the LICENSE file. | |
4 | |
5 #library('util'); | |
6 | |
7 /** | |
8 * An abstract map implementation. This class can be used as a superclass for | |
9 * implementing maps, requiring only the further implementation of the | |
10 * [:operator []:], [:forEach:] and [:length:] methods to provide a fully | |
11 * implemented immutable map. | |
12 */ | |
13 abstract class AbstractMap<K,V> implements Map<K,V> { | |
14 AbstractMap(); | |
15 AbstractMap.from(Map<K,V> other) { | |
16 other.forEach((k,v) => this[k] = v); | |
17 } | |
18 void operator []=(K key, value) { | |
19 throw new UnsupportedOperationException('[]= is not supported'); | |
20 } | |
21 void clear() { | |
22 throw new UnsupportedOperationException('clear() is not supported'); | |
23 } | |
24 bool containsKey(K key) { | |
25 var found = false; | |
26 forEach((k,_) { | |
27 if (k == key) { | |
28 found = true; | |
29 } | |
30 }); | |
31 return found; | |
32 } | |
33 bool containsValue(V value) { | |
34 var found = false; | |
35 forEach((_,v) { | |
36 if (v == value) { | |
37 found = true; | |
38 } | |
39 }); | |
40 return found; | |
41 } | |
42 Collection<K> getKeys() { | |
43 var keys = <K>[]; | |
44 forEach((k,_) => keys.add(k)); | |
45 return keys; | |
46 } | |
47 Collection<V> getValues() { | |
48 var values = <V>[]; | |
49 forEach((_,v) => values.add(v)); | |
50 return values; | |
51 } | |
52 bool isEmpty() => length == 0; | |
53 V putIfAbsent(K key, V ifAbsent()) { | |
54 if (!containsKey(key)) { | |
55 V value = this[key]; | |
56 this[key] = ifAbsent(); | |
57 return value; | |
58 } | |
59 return null; | |
60 } | |
61 V remove(K key) { | |
62 throw new UnsupportedOperationException('V remove(K key) is not supported'); | |
63 } | |
64 } | |
65 | |
66 /** | |
67 * [ImmutableMapWrapper] wraps a (mutable) map as an immutable map where all | |
68 * mutating operations throw [UnsupportedOperationException] upon invocation. | |
69 */ | |
70 class ImmutableMapWrapper<K,V> extends AbstractMap<K,V> { | |
71 final Map<K,V> _map; | |
72 | |
73 ImmutableMapWrapper(this._map); | |
74 | |
75 int get length => _map.length; | |
76 | |
77 V operator [](K key) { | |
78 if (key is K) { | |
79 return _map[key]; | |
80 } | |
81 return null; | |
82 } | |
83 | |
84 void forEach(void f(K key, V value)) { | |
85 _map.forEach(f); | |
86 } | |
87 } | |
88 | |
89 /** | |
90 * A [Filter] function returns [:true:] iff [value] should be included. | |
91 */ | |
92 typedef bool Filter<V>(V value); | |
93 | |
94 /** | |
95 * An immutable map wrapper capable of filtering the input map. | |
96 */ | |
97 class FilteredImmutableMap<K,V> extends ImmutableMapWrapper<K,V> { | |
98 final Filter<V> _filter; | |
99 | |
100 FilteredImmutableMap(Map<K,V> map, this._filter) : super(map); | |
101 | |
102 int get length { | |
103 var count = 0; | |
104 forEach((k,v) { | |
105 count++; | |
106 }); | |
107 return count; | |
108 } | |
109 | |
110 void forEach(void f(K key, V value)) { | |
111 _map.forEach((K k, V v) { | |
112 if (_filter(v)) { | |
113 f(k, v); | |
114 } | |
115 }); | |
116 } | |
117 } | |
118 | |
119 /** | |
120 * An [AsFilter] takes a [value] of type [V1] and returns [value] iff it is of | |
121 * type [V2] or [:null:] otherwise. An [AsFilter] therefore behaves like the | |
122 * [:as:] expression. | |
123 */ | |
124 typedef V2 AsFilter<V1, V2>(V1 value); | |
125 | |
126 /** | |
127 * An immutable map wrapper capable of filtering the input map based on types. | |
128 * It takes an [AsFilter] function which converts the original values of type | |
129 * [Vin] into values of type [Vout], or returns [:null:] if the value should | |
130 * not be included in the filtered map. | |
131 */ | |
132 class AsFilteredImmutableMap<K, Vin, Vout> extends AbstractMap<K, Vout> { | |
133 final Map<K, Vin> _map; | |
134 final AsFilter<Vin, Vout> _filter; | |
135 | |
136 AsFilteredImmutableMap(this._map, this._filter); | |
137 | |
138 int get length { | |
139 var count = 0; | |
140 forEach((k,v) { | |
141 count++; | |
142 }); | |
143 return count; | |
144 } | |
145 | |
146 Vout operator [](K key) { | |
147 if (key is K) { | |
148 return _filter(_map[key]); | |
149 } | |
150 return null; | |
151 } | |
152 | |
153 void forEach(void f(K key, Vout value)) { | |
154 _map.forEach((K k, Vin v) { | |
155 var value = _filter(v); | |
156 if (value !== null) { | |
157 f(k, value); | |
158 } | |
159 }); | |
160 } | |
161 } | |
OLD | NEW |