Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(72)

Side by Side Diff: packages/charted/lib/charts/data_transformers/aggregation_item.dart

Issue 1521693002: Roll Observatory deps (charted -> ^0.3.0) (Closed) Base URL: https://chromium.googlesource.com/external/github.com/dart-lang/observatory_pub_packages.git@master
Patch Set: Created 5 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 //
2 * Copyright 2014 Google Inc. All rights reserved. 2 // Copyright 2014 Google Inc. All rights reserved.
3 * 3 //
4 * Use of this source code is governed by a BSD-style 4 // Use of this source code is governed by a BSD-style
5 * license that can be found in the LICENSE file or at 5 // license that can be found in the LICENSE file or at
6 * https://developers.google.com/open-source/licenses/bsd 6 // https://developers.google.com/open-source/licenses/bsd
7 */ 7 //
8 8
9 part of charted.charts; 9 part of charted.charts;
10 10
11 /** 11 /// AggregationItem is created by [AggregationModel] to make access to facts
12 * AggregationItem is created by [AggregationModel] to make access to facts 12 /// observable. Users must use AggregationItem.isValid before trying to access
13 * observable. Users must use AggregationItem.isValid before trying to access 13 /// the aggregations.
14 * the aggregations.
15 */
16 abstract class AggregationItem extends ChangeNotifier { 14 abstract class AggregationItem extends ChangeNotifier {
17 /** 15 /// List of dimension fields in effect
18 * List of dimension fields in effect
19 */
20 List<String> dimensions; 16 List<String> dimensions;
21 17
22 /** 18 /// Check if this entity is valid.
23 * Check if this entity is valid. 19 /// Currently the only case where an entity becomes invalid
24 * Currently the only case where an entity becomes invalid 20 /// is when a groupBy is called on the model.
25 * is when a groupBy is called on the model.
26 */
27 bool get isValid; 21 bool get isValid;
28 22
29 /** 23 /// Fetch the fact from AggregationModel and return it
30 * Fetch the fact from AggregationModel and return it 24 /// Currently takes keys in the form of "sum(spend)", where sum is
31 * Currently takes keys in the form of "sum(spend)", where sum is 25 /// the aggregation type and spend is fact's field name.
32 * the aggregation type and spend is fact's field name. 26 ///
33 * 27 /// Currently, "sum", "count", "min", "max", "avg", "valid" and "avgOfValid"
34 * Currently, "sum", "count", "min", "max", "avg", "valid" and "avgOfValid" 28 /// are supported as the operators.
35 * are supported as the operators. 29 operator [](String key);
36 */
37 30
38 operator[](String key); 31 /// Check if we support a given key.
39
40 /**
41 * Check if we support a given key.
42 */
43 bool containsKey(String key); 32 bool containsKey(String key);
44 33
45 /** 34 /// List of valid field names for this entity.
46 * List of valid field names for this entity. 35 /// It's the combined list of accessors for individual items, items in
47 * It's the combined list of accessors for individual items, items in 36 /// the next dimension and all possible facts defined on the view.
48 * the next dimension and all possible facts defined on the view.
49 */
50 Iterable<String> get fieldNames; 37 Iterable<String> get fieldNames;
51 } 38 }
52 39
53 /* 40 /// Implementation of AggregationItem
54 * Implementation of AggregationItem 41 /// Instances of _AggregationItemImpl are created only by AggregationModel
55 * Instances of _AggregationItemImpl are created only by AggregationModel
56 */
57 class _AggregationItemImpl extends ChangeNotifier implements AggregationItem { 42 class _AggregationItemImpl extends ChangeNotifier implements AggregationItem {
58 static final List<String> derivedAggregationTypes = ['count', 'avg']; 43 static final List<String> derivedAggregationTypes = ['count', 'avg'];
59 44
60 AggregationModel model; 45 AggregationModel model;
61 List<String> dimensions; 46 List<String> dimensions;
62 47
63 String _key; 48 String _key;
64 49
65 int _factsOffset; 50 int _factsOffset;
66 51
67 /* 52 /// Currently entities are created only when they have valid aggregations
68 * Currently entities are created only when they have valid aggregations
69 */
70 _AggregationItemImpl(this.model, this.dimensions, this._key) { 53 _AggregationItemImpl(this.model, this.dimensions, this._key) {
71 if (model == null) { 54 if (model == null) {
72 throw new ArgumentError('Model cannot be null'); 55 throw new ArgumentError('Model cannot be null');
73 } 56 }
74 if (_key == null) { 57 if (_key == null) {
75 _key = ''; 58 _key = '';
76 } 59 }
77 60
78 // facts + list of items + list of children (drilldown) 61 // facts + list of items + list of children (drilldown)
79 _factsOffset = model._dimToAggrMap[_key]; 62 _factsOffset = model._dimToAggrMap[_key];
80 } 63 }
81 64
82 /** 65 /// _dimToAggrMap got updated on the model, update ourselves accordingly
83 * _dimToAggrMap got updated on the model, update ourselves accordingly
84 */
85 void update() { 66 void update() {
86 _factsOffset = model._dimToAggrMap[_key]; 67 _factsOffset = model._dimToAggrMap[_key];
87 } 68 }
88 69
89 /* 70 /// Mark this entity as invalid.
90 * Mark this entity as invalid.
91 */
92 void clear() { 71 void clear() {
93 _factsOffset = null; 72 _factsOffset = null;
94 } 73 }
95 74
96 bool get isValid => _factsOffset != null; 75 bool get isValid => _factsOffset != null;
97 76
98 dynamic operator[](String key) { 77 dynamic operator [](String key) {
99 if (!isValid) { 78 if (!isValid) {
100 throw new StateError('Entity is not valid anymore'); 79 throw new StateError('Entity is not valid anymore');
101 } 80 }
102 81
103 int argPos = key.indexOf('('); 82 int argPos = key.indexOf('(');
104 if (argPos == -1) { 83 if (argPos == -1) {
105 return _nonAggregationMember(key); 84 return _nonAggregationMember(key);
106 } 85 }
107 86
108 String aggrFunc = key.substring(0, argPos); 87 String aggrFunc = key.substring(0, argPos);
109 int aggrFuncIndex = model.computedAggregationTypes.indexOf(aggrFunc); 88 int aggrFuncIndex = model.computedAggregationTypes.indexOf(aggrFunc);
110 if (aggrFuncIndex == -1 && !derivedAggregationTypes.contains(aggrFunc)) { 89 if (aggrFuncIndex == -1 && !derivedAggregationTypes.contains(aggrFunc)) {
111 throw new ArgumentError('Unknown aggregation method: ${aggrFunc}'); 90 throw new ArgumentError('Unknown aggregation method: ${aggrFunc}');
112 } 91 }
113 92
114 String factName = key.substring(argPos + 1, key.lastIndexOf(')')); 93 String factName = key.substring(argPos + 1, key.lastIndexOf(')'));
115 int factIndex = model._factFields.indexOf(factName); 94 int factIndex = model._factFields.indexOf(factName);
116 95
117 // Try parsing int if every element in factFields is int. 96 // Try parsing int if every element in factFields is int.
118 if (model._factFields.every((e) => e is int)) { 97 if (model._factFields.every((e) => e is int)) {
119 factIndex = model._factFields.indexOf(int.parse(factName, 98 factIndex = model._factFields.indexOf(int.parse(factName, onError: (e) {
120 onError: (e) { 99 throw new ArgumentError('Type of factFields are int but factName' +
121 throw new ArgumentError('Type of factFields are int but factName' + 100 'contains non int value');
122 'contains non int value'); 101 }));
123 }));
124 } 102 }
125 if (factIndex == -1) { 103 if (factIndex == -1) {
126 throw new ArgumentError('Model not configured for ${factName}'); 104 throw new ArgumentError('Model not configured for ${factName}');
127 } 105 }
128 106
129 int offset = _factsOffset + factIndex * model._aggregationTypesCount; 107 int offset = _factsOffset + factIndex * model._aggregationTypesCount;
130 // No items for the corresponding fact, so return null. 108 // No items for the corresponding fact, so return null.
131 if (aggrFunc != 'count' && aggrFunc != 'avg' && 109 if (aggrFunc != 'count' &&
110 aggrFunc != 'avg' &&
132 model._aggregations[offset + model._offsetCnt].toInt() == 0) { 111 model._aggregations[offset + model._offsetCnt].toInt() == 0) {
133 return null; 112 return null;
134 } 113 }
135 114
136 if (aggrFuncIndex != -1) { 115 if (aggrFuncIndex != -1) {
137 return model._aggregations[offset + aggrFuncIndex]; 116 return model._aggregations[offset + aggrFuncIndex];
138 } else if (aggrFunc == 'count') { 117 } else if (aggrFunc == 'count') {
139 return model._aggregations[_factsOffset + 118 return model._aggregations[_factsOffset + model._offsetFilteredCount]
140 model._offsetFilteredCount].toInt(); 119 .toInt();
141 } else if (aggrFunc == 'avg') { 120 } else if (aggrFunc == 'avg') {
142 return model._aggregations[offset + model._offsetSum] / 121 return model._aggregations[offset + model._offsetSum] /
143 model._aggregations[_factsOffset + model._offsetFilteredCount]. 122 model._aggregations[_factsOffset + model._offsetFilteredCount]
144 toInt(); 123 .toInt();
145 } else if (aggrFunc == 'avgOfValid') { 124 } else if (aggrFunc == 'avgOfValid') {
146 return model._aggregations[offset + model._offsetSum] / 125 return model._aggregations[offset + model._offsetSum] /
147 model._aggregations[offset + model._offsetCnt].toInt(); 126 model._aggregations[offset + model._offsetCnt].toInt();
148 } 127 }
149 return null; 128 return null;
150 } 129 }
151 130
152 dynamic _nonAggregationMember(String key) { 131 dynamic _nonAggregationMember(String key) {
153 if (key == 'items') { 132 if (key == 'items') {
154 return new _AggregationItemsIterator(model, dimensions, _key); 133 return new _AggregationItemsIterator(model, dimensions, _key);
155 } 134 }
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
191 model._factFields.forEach((var name) { 170 model._factFields.forEach((var name) {
192 AggregationModel.supportedAggregationTypes.forEach((String aggrType) { 171 AggregationModel.supportedAggregationTypes.forEach((String aggrType) {
193 cache.add('${aggrType}(${name})'); 172 cache.add('${aggrType}(${name})');
194 }); 173 });
195 }); 174 });
196 model._itemFieldNamesCache = cache; 175 model._itemFieldNamesCache = cache;
197 } 176 }
198 return model._itemFieldNamesCache; 177 return model._itemFieldNamesCache;
199 } 178 }
200 179
201 /* 180 // TODO(prsd): Implementation of [Observable]
202 * TODO(prsd): Implementation of [Observable]
203 */
204 Stream<List<ChangeRecord>> get changes { 181 Stream<List<ChangeRecord>> get changes {
205 throw new UnimplementedError(); 182 throw new UnimplementedError();
206 } 183 }
207 } 184 }
208 185
209 class _AggregationItemsIterator implements Iterator { 186 class _AggregationItemsIterator implements Iterator {
210 final AggregationModel model; 187 final AggregationModel model;
211 List<String> dimensions; 188 List<String> dimensions;
212 String key; 189 String key;
213 190
214 int _current; 191 int _current;
215 int _counter = 0; 192 int _counter = 0;
216 193
217 int _start; 194 int _start;
218 int _count; 195 int _count;
219 int _endOfRows; 196 int _endOfRows;
220 197
221 _AggregationItemsIterator(this.model, List<String> this.dimensions, 198 _AggregationItemsIterator(
222 String this.key) { 199 this.model, List<String> this.dimensions, String this.key) {
223 int offset = model._dimToAggrMap[key]; 200 int offset = model._dimToAggrMap[key];
224 if (offset != null) { 201 if (offset != null) {
225 int factsEndOffset = offset + 202 int factsEndOffset =
226 model._factFields.length * model._aggregationTypesCount; 203 offset + model._factFields.length * model._aggregationTypesCount;
227 _start = model._aggregations[factsEndOffset].toInt(); 204 _start = model._aggregations[factsEndOffset].toInt();
228 _count = model._aggregations[factsEndOffset + 1].toInt(); 205 _count = model._aggregations[factsEndOffset + 1].toInt();
229 _endOfRows = model._rows.length; 206 _endOfRows = model._rows.length;
230 } 207 }
231 } 208 }
232 209
233 bool moveNext() { 210 bool moveNext() {
234 if (_current == null) { 211 if (_current == null) {
235 _current = _start; 212 _current = _start;
236 } else { 213 } else {
237 ++_current; 214 ++_current;
238 } 215 }
239 216
240 if (++_counter > _count) { 217 if (++_counter > _count) {
241 return false; 218 return false;
242 } 219 }
243 220
244 /* 221 // If model had a filter applied, then check if _current points to a
245 * If model had a filter applied, then check if _current points to a 222 // filtered-in row, else skip till we find one.
246 * filtered-in row, else skip till we find one. 223 // Also, make sure (even if something else went wrong) we don't go
247 * Also, make sure (even if something else went wrong) we don't go 224 // beyond the number of items in the model.
248 * beyond the number of items in the model.
249 */
250 if (this.model._filterResults != null) { 225 if (this.model._filterResults != null) {
251 while ((this.model._filterResults[_current ~/ AggregationModel.SMI_BITS] & 226 while ((this.model._filterResults[_current ~/ AggregationModel.SMI_BITS] &
252 (1 << _current % AggregationModel.SMI_BITS)) == 0 && 227 (1 << _current % AggregationModel.SMI_BITS)) ==
228 0 &&
253 _current <= _endOfRows) { 229 _current <= _endOfRows) {
254 ++_current; 230 ++_current;
255 } 231 }
256 } 232 }
257 return (_current < _endOfRows); 233 return (_current < _endOfRows);
258 } 234 }
259 235
260 get current { 236 get current {
261 if (_current == null || _counter > _count) { 237 if (_current == null || _counter > _count) {
262 return null; 238 return null;
263 } 239 }
264 return model._rows[model._sorted[_current]]; 240 return model._rows[model._sorted[_current]];
265 } 241 }
266 } 242 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698