Chromium Code Reviews| Index: lib/dartdoc/mirrors/util.dart |
| diff --git a/lib/dartdoc/mirrors/util.dart b/lib/dartdoc/mirrors/util.dart |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..588fd430591e035c54156fc4edf349b480239dba |
| --- /dev/null |
| +++ b/lib/dartdoc/mirrors/util.dart |
| @@ -0,0 +1,158 @@ |
| +// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| +// for details. All rights reserved. Use of this source code is governed by a |
| +// BSD-style license that can be found in the LICENSE file. |
| + |
| +#library('util'); |
| + |
| +/** |
| + * An abstract map implementation. This class can be used as a superclass for |
| + * implementing maps, requiring only the further implementation of the |
| + * [:operator []:], [:forEach:] and [:length:] methods to provide a fully |
| + * implemented immutable map. |
|
Lasse Reichstein Nielsen
2012/07/04 10:58:59
That's what the Map class itself should be!
Eventu
Johnni Winther
2012/07/04 13:19:17
Yes, an iterator is wanted/needed.
|
| + */ |
| +abstract class AbstractMap<K,V> implements Map<K,V> { |
| + AbstractMap(); |
| + AbstractMap.from(Map<K,V> other) { |
| + other.forEach((k,v) => this[k] = v); |
| + } |
| + void operator []=(K key, value) { |
| + throw new UnsupportedOperationException('[]= is not supported'); |
| + } |
| + void clear() { |
| + throw new UnsupportedOperationException('clear() is not supported'); |
| + } |
| + bool containsKey(K key) { |
| + var found = false; |
| + forEach((k,_) { |
| + if (k == key) { |
| + found = true; |
| + } |
| + }); |
| + return found; |
| + } |
| + bool containsValue(V value) { |
| + var found = false; |
| + forEach((_,v) { |
| + if (v == value) { |
| + found = true; |
| + } |
| + }); |
| + return found; |
| + } |
| + Collection<K> getKeys() { |
| + var keys = <K>[]; |
| + forEach((k,_) => keys.add(k)); |
| + return keys; |
| + } |
| + Collection<V> getValues() { |
| + var values = <V>[]; |
| + forEach((_,v) => values.add(v)); |
| + return values; |
| + } |
| + bool isEmpty() => length == 0; |
| + V putIfAbsent(K key, V ifAbsent()) { |
| + if (!containsKey(key)) { |
| + V value = this[key]; |
| + this[key] = ifAbsent(); |
| + return value; |
| + } |
| + return null; |
| + } |
| + V remove(K key) { |
| + throw new UnsupportedOperationException('V remove(K key) is not supported'); |
| + } |
| +} |
| + |
| +/** |
| + * [ImmutableMapWrapper] wraps a (mutable) map as an immutable map where all |
| + * mutable operations throw [UnsupportedOperationException] upon invocation. |
|
Lasse Reichstein Nielsen
2012/07/04 10:58:59
"mutable operations" -> "mutating operations"
Johnni Winther
2012/07/04 13:19:17
Done.
|
| + */ |
| +class ImmutableMapWrapper<K,V> extends AbstractMap<K,V> { |
| + final Map<K,V> _map; |
| + |
| + ImmutableMapWrapper(this._map); |
| + |
| + int get length() => _map.length; |
| + |
| + V operator [](K key) { |
| + if (key is K) { |
| + return _map[key]; |
| + } |
| + return null; |
| + } |
| + |
| + void forEach(void f(K key, V value)) { |
| + _map.forEach(f); |
| + } |
| +} |
| + |
| +/** |
| + * A [Filter] function returns [:true:] iff [value] should be included. |
| + */ |
| +typedef bool Filter<V>(V value); |
| + |
| +/** |
| + * An immutable map wrapper capable of filtering the input map. |
| + */ |
| +class FilteredImmutableMapWrapper<K,V> extends ImmutableMapWrapper<K,V> { |
|
Lasse Reichstein Nielsen
2012/07/04 10:58:59
ImmutableValueFilterMap?
I don't see the need for
|
| + final Filter<V> _filter; |
| + |
| + FilteredImmutableMapWrapper(Map<K,V> map, this._filter) : super(map); |
| + |
| + int get length() { |
| + var count = 0; |
| + forEach((k,v) { |
| + count++; |
| + }); |
| + return count; |
| + } |
| + |
| + void forEach(void f(K key, V value)) { |
| + _map.forEach((K k, V v) { |
| + if (_filter(v)) { |
| + f(k, v); |
| + } |
| + }); |
| + } |
| +} |
| + |
| +/** |
| + * An [AsFilter] takes a [value] of type [V1] and returns [value] iff it is of |
| + * type [V2] or [:null:] otherwise. An [AsFilter] therefore behaves like the |
| + * [:as:] expression. |
| + */ |
| +typedef V2 AsFilter<V1,V2>(V1 value); |
|
Lasse Reichstein Nielsen
2012/07/04 10:58:59
Space after comma, evertwhere.
Johnni Winther
2012/07/04 13:19:17
Done.
|
| + |
| +/** |
| + * An immutable map wrapper capable of filtering the input map based on types. |
|
Lasse Reichstein Nielsen
2012/07/04 10:58:59
Tricky. Might need more comments.
Johnni Winther
2012/07/04 13:19:17
Done. (Or tried!)
|
| + */ |
| +class AsFilteredImmutableMapWrapper<K,Vin,Vout> extends AbstractMap<K,Vout> { |
|
Lasse Reichstein Nielsen
2012/07/04 10:58:59
The "filter" method don't need to do a cast. It ca
Johnni Winther
2012/07/04 13:19:17
The filter method could be used for other purposes
|
| + final Map<K,Vin> _map; |
| + final AsFilter<Vin,Vout> _filter; |
| + |
| + AsFilteredImmutableMapWrapper(this._map, this._filter); |
|
Lasse Reichstein Nielsen
2012/07/04 10:58:59
Indentation is one too deep from here.
Johnni Winther
2012/07/04 13:19:17
Done.
|
| + |
|
Lasse Reichstein Nielsen
2012/07/04 10:58:59
Should you override containsKey/containsValue to r
Johnni Winther
2012/07/04 13:19:17
It works with the current implementation of Abstra
|
| + int get length() { |
| + var count = 0; |
| + forEach((k,v) { |
| + count++; |
| + }); |
| + return count; |
| + } |
| + |
| + Vout operator [](K key) { |
| + if (key is K) { |
| + return _filter(_map[key]); |
| + } |
| + return null; |
| + } |
| + |
| + void forEach(void f(K key, Vout value)) { |
| + _map.forEach((K k, Vin v) { |
| + var value = _filter(v); |
| + if (value !== null) { |
| + f(k, value); |
| + } |
| + }); |
| + } |
| +} |