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

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

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

Powered by Google App Engine
This is Rietveld 408576698