1
1
part of angular.formatter_internal;
2
2
3
- // Too bad you can't stick typedef's inside a class.
4
- typedef bool _Predicate (e);
5
- typedef bool _Equals (a, b);
3
+ typedef bool _PredicateFn (e);
4
+ typedef bool _CompareFn (a, b);
6
5
7
6
/**
8
7
* Selects a subset of items from the provided [List] and returns it as a new
@@ -17,37 +16,37 @@ typedef bool _Equals(a, b);
17
16
*
18
17
* The expression can be of the following types:
19
18
*
20
- * - [String] , [bool] and [num] : Only items in the list that directly
19
+ * - [String] , [bool] and [num] : Only items in the list that directly
21
20
* match this expression, items that are Maps with any value matching this
22
21
* item, and items that are lists containing a matching items are returned.
23
22
*
24
- * - [Map] : This defines a pattern map. Filters specific properties on objects
23
+ * - [Map] : This defines a pattern map. Filters specific properties on objects
25
24
* contained in the input list. For example `{name:"M", phone:"1"}` predicate
26
25
* will return a list of items which have property `name` containing "M" and
27
26
* property `phone` containing "1". A special property name, `$` , can be used
28
27
* (as in `{$: "text"}` ) to accept a match against any property of the object.
29
28
* That's equivalent to the simple substring match with a `String` as
30
29
* described above.
31
30
*
32
- * - [Function] : This allows you to supply a custom function to filter the
33
- * List. The function is called for each element of the List. The returned
31
+ * - [Function] : This allows you to supply a custom function to filter the
32
+ * List. The function is called for each element of the List. The returned
34
33
* List contains exactly those elements for which this function returned
35
34
* `true` .
36
35
*
37
36
*
38
37
* The comparator is optional and can be one of the following:
39
38
*
40
- * - `bool comparator(expected, actual)` : The function will be called with the
39
+ * - `bool comparator(expected, actual)` : The function will be called with the
41
40
* object value and the predicate value to compare and should return true if
42
41
* the item should be included in filtered result.
43
42
*
44
43
* - `true` : Specifies that only identical objects matching the expression
45
- * exactly should be considered matches. Two strings are considered identical
46
- * if they are equal. Two numbers are considered identical if they are either
47
- * equal or both are `NaN` . All other objects are identical iff
44
+ * exactly should be considered matches. Two strings are considered identical
45
+ * if they are equal. Two numbers are considered identical if they are either
46
+ * equal or both are `NaN` . All other objects are identical iff
48
47
* identical(expected, actual) is true.
49
48
*
50
- * - `false|null` : Specifies case insensitive substring matching.
49
+ * - `false|null` : Specifies case insensitive substring matching.
51
50
*
52
51
*
53
52
* # Example ([view in plunker] (http://plnkr.co/edit/6Mxz6r?p=info)):
@@ -105,27 +104,30 @@ typedef bool _Equals(a, b);
105
104
@Formatter (name: 'filter' )
106
105
class Filter implements Function {
107
106
Parser _parser;
108
- _Equals _comparator;
109
- _Equals _stringComparator;
107
+ _CompareFn _comparator;
108
+ _CompareFn _stringComparator;
110
109
111
110
static _nop (e) => e;
111
+
112
112
static _ensureBool (val) => (val is bool && val);
113
+
113
114
static _isSubstringCaseInsensitive (String a, String b) =>
114
115
a != null && b != null && a.toLowerCase ().contains (b.toLowerCase ());
116
+
115
117
static _identical (a, b) => identical (a, b) ||
116
118
(a is String && b is String && a == b) ||
117
119
(a is num && b is num && a.isNaN && b.isNaN);
118
120
119
121
Filter (this ._parser);
120
122
121
- void _configureComparator (var comparatorExpression) {
123
+ void _configureComparator (comparatorExpression) {
122
124
if (comparatorExpression == null || comparatorExpression == false ) {
123
125
_stringComparator = _isSubstringCaseInsensitive;
124
126
_comparator = _defaultComparator;
125
127
} else if (comparatorExpression == true ) {
126
128
_stringComparator = _identical;
127
129
_comparator = _defaultComparator;
128
- } else if (comparatorExpression is _Equals ) {
130
+ } else if (comparatorExpression is _CompareFn ) {
129
131
_comparator = (a, b) => _ensureBool (comparatorExpression (a, b));
130
132
} else {
131
133
_comparator = null ;
@@ -135,67 +137,58 @@ class Filter implements Function {
135
137
// Preconditions
136
138
// - what: NOT a Map
137
139
// - item: neither a Map nor a List
138
- bool _defaultComparator (var item, var what) {
139
- if (what == null ) {
140
- return false ;
141
- } else if (item == null ) {
142
- return what == '' ;
143
- } else if (what is String && what.startsWith ('!' )) {
144
- return ! _search (item, what.substring (1 ));
145
- } else if (item is String ) {
146
- return (what is String ) && _stringComparator (item, what);
147
- } else if (item is bool ) {
140
+ bool _defaultComparator (item, what) {
141
+ if (what == null ) return false ;
142
+ if (item == null ) return what == '' ;
143
+ if (what is String && what.startsWith ('!' )) return ! _search (item, what.substring (1 ));
144
+ if (item is String ) return (what is String ) && _stringComparator (item, what);
145
+ if (item is bool ) {
148
146
if (what is bool ) {
149
147
return item == what;
150
148
} else if (what is String ) {
151
149
what = (what as String ).toLowerCase ();
152
150
return item ? (what == "true" || what == "yes" || what == "on" )
153
151
: (what == "false" || what == "no" || what == "off" );
154
- } else {
155
- return false ;
156
152
}
157
- } else if (item is num ) {
158
- if (what is num ) {
159
- return item == what || (item.isNaN && what.isNaN);
160
- } else {
161
- return what is String && _stringComparator ('$item ' , what);
162
- }
163
- } else {
164
- return false ; // Unsupported item type.
153
+ return false ;
165
154
}
155
+ if (item is num ) {
156
+ return what is num ?
157
+ item == what || (item.isNaN && what.isNaN) :
158
+ what is String && _stringComparator ('$item ' , what);
159
+ }
160
+ return false ; // Unsupported item type.
166
161
}
167
162
168
- bool _search (var item, var what) {
163
+ bool _search (item, what) {
169
164
if (what is Map ) {
170
165
return what.keys.every ((key) => _search (
171
166
(key == r'$' ) ? item : _parser (key).eval (item), what[key]));
172
- } else if (item is Map ) {
173
- return item.keys.any ((k) => ! k.startsWith (r'$' ) && _search (item[k], what));
174
- } else if (item is List ) {
175
- return item.any ((i) => _search (i, what));
176
- } else {
177
- return _comparator (item, what);
178
167
}
168
+ if (item is Map ) return item.keys.any ((k) => ! k.startsWith (r'$' ) && _search (item[k], what));
169
+ if (item is List ) return item.any ((i) => _search (i, what));
170
+ return _comparator (item, what);
179
171
}
180
172
181
- _Predicate _toPredicate (var expression) {
182
- if (expression is _Predicate ) {
183
- return (item) => _ensureBool (expression (item));
184
- } else if (_comparator == null ) {
185
- return (item) => false ; // Bad comparator → no items for you!
186
- } else {
187
- return (item) => _search (item, expression);
188
- }
173
+ _PredicateFn _toPredicate (var expression) {
174
+ if (expression is _PredicateFn ) return (item) => _ensureBool (expression (item));
175
+ if (_comparator == null ) return (_) => false ; // Bad comparator → no items for you!
176
+ return (item) => _search (item, expression);
189
177
}
190
178
191
- List call (List items, var expression, [var comparator]) {
192
- if (expression == null ) {
193
- return items.toList (growable: false ); // Missing expression → passthrough.
194
- } else if (expression is ! Map && expression is ! Function &&
195
- expression is ! String && expression is ! bool &&
196
- expression is ! num ) {
197
- return const []; // Bad expression → no items for you!
179
+ List call (List items, expression, [comparator]) {
180
+ // Missing expression → passthrough.
181
+ if (expression == null ) return items.toList (growable: false );
182
+
183
+ // Bad expression → no items for you!
184
+ if (expression is ! Map &&
185
+ expression is ! Function &&
186
+ expression is ! String &&
187
+ expression is ! bool &&
188
+ expression is ! num ) {
189
+ return const [];
198
190
}
191
+
199
192
_configureComparator (comparator);
200
193
List results = items.where (_toPredicate (expression)).toList (growable: false );
201
194
_comparator = null ;
0 commit comments