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

Side by Side Diff: pkg/serialization/lib/src/serialization_rule.dart

Issue 12136002: Some fixes to work better with the services framework (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Changes from review comments Created 7 years, 10 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 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 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. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 part of serialization; 5 part of serialization;
6 6
7 // TODO(alanknight): We should have an example and tests for subclassing 7 // TODO(alanknight): We should have an example and tests for subclassing
8 // serialization rule rather than using the hard-coded ClosureToMap rule. And 8 // serialization rule rather than using the hard-coded ClosureToMap rule. And
9 // possibly an abstract superclass that's designed to be subclassed that way. 9 // possibly an abstract superclass that's designed to be subclassed that way.
10 /** 10 /**
(...skipping 27 matching lines...) Expand all
38 * where we're writing it, false otherwise. 38 * where we're writing it, false otherwise.
39 */ 39 */
40 bool appliesTo(object, Writer writer); 40 bool appliesTo(object, Writer writer);
41 41
42 /** 42 /**
43 * This extracts the state from the object, calling [f] for each value 43 * This extracts the state from the object, calling [f] for each value
44 * as it is extracted, and returning an object representing the whole 44 * as it is extracted, and returning an object representing the whole
45 * state at the end. The state that results will still have direct 45 * state at the end. The state that results will still have direct
46 * pointers to objects, rather than references. 46 * pointers to objects, rather than references.
47 */ 47 */
48 extractState(object, void f(value)); 48 extractState(object, void f(value), Writer w);
49 49
50 /** 50 /**
51 * Allows rules to tell us how they expect to store their state. If this 51 * Allows rules to tell us how they expect to store their state. If this
52 * isn't specified we can also just look at the data to tell. 52 * isn't specified we can also just look at the data to tell.
53 */ 53 */
54 bool get storesStateAsLists => false; 54 bool get storesStateAsLists => false;
55 bool get storesStateAsMaps => false; 55 bool get storesStateAsMaps => false;
56 bool get storesStateAsPrimitives => false; 56 bool get storesStateAsPrimitives => false;
57 57
58 /** 58 /**
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
135 /** 135 /**
136 * This rule handles things that implement List. It will recreate them as 136 * This rule handles things that implement List. It will recreate them as
137 * whatever the default implemenation of List is on the target platform. 137 * whatever the default implemenation of List is on the target platform.
138 */ 138 */
139 class ListRule extends SerializationRule { 139 class ListRule extends SerializationRule {
140 140
141 appliesTo(object, Writer w) => object is List; 141 appliesTo(object, Writer w) => object is List;
142 142
143 bool get storesStateAsLists => true; 143 bool get storesStateAsLists => true;
144 144
145 List extractState(List list, f) { 145 List extractState(List list, f, Writer w) {
146 var result = new List(); 146 var result = new List();
147 for (var each in list) { 147 for (var each in list) {
148 result.add(each); 148 result.add(each);
149 f(each); 149 f(each);
150 } 150 }
151 return result; 151 return result;
152 } 152 }
153 153
154 inflateEssential(List state, Reader r) => new List(); 154 inflateEssential(List state, Reader r) => new List();
155 155
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
193 * whatever the default implemenation of Map is on the target platform. If a 193 * whatever the default implemenation of Map is on the target platform. If a
194 * map has string keys it will attempt to retain it as a map for JSON formats, 194 * map has string keys it will attempt to retain it as a map for JSON formats,
195 * otherwise it will store it as a list of references to keys and values. 195 * otherwise it will store it as a list of references to keys and values.
196 */ 196 */
197 class MapRule extends SerializationRule { 197 class MapRule extends SerializationRule {
198 198
199 appliesTo(object, Writer w) => object is Map; 199 appliesTo(object, Writer w) => object is Map;
200 200
201 bool get storesStateAsMaps => true; 201 bool get storesStateAsMaps => true;
202 202
203 extractState(Map map, f) { 203 extractState(Map map, f, Writer w) {
204 // Note that we make a copy here because flattening may be destructive. 204 // Note that we make a copy here because flattening may be destructive.
205 var newMap = new Map.from(map); 205 var newMap = new Map.from(map);
206 newMap.forEach((key, value) { 206 newMap.forEach((key, value) {
207 f(key); 207 f(key);
208 f(value); 208 f(value);
209 }); 209 });
210 return newMap; 210 return newMap;
211 } 211 }
212 212
213 /** 213 /**
214 * Change the keys and values of [state] into references in [writer]. 214 * Change the keys and values of [state] into references in [writer].
215 * If [state] is a map whose keys are all strings then we leave the keys 215 * If [state] is a map whose keys are all strings then we leave the keys
216 * as is so that JSON formats will be more readable. If the keys are 216 * as is so that JSON formats will be more readable. If the keys are
217 * arbitrary then we need to turn them into references and replace the 217 * arbitrary then we need to turn them into references and replace the
218 * state with a new Map whose keys are the references. 218 * state with a new Map whose keys are the references.
219 */ 219 */
220 flatten(Map state, Writer writer) { 220 flatten(Map state, Writer writer) {
221 bool keysAreAllStrings = state.keys.every((x) => x is String); 221 bool keysAreAllStrings = state.keys.every((x) => x is String);
222 if (keysAreAllStrings) { 222 if (keysAreAllStrings && !writer.shouldUseReferencesForPrimitives) {
223 keysAndValues(state).forEach( 223 keysAndValues(state).forEach(
224 (key, value) => state[key] = writer._referenceFor(value)); 224 (key, value) => state[key] = writer._referenceFor(value));
225 return state; 225 return state;
226 } else { 226 } else {
227 var newState = []; 227 var newState = [];
228 keysAndValues(state).forEach((key, value) { 228 keysAndValues(state).forEach((key, value) {
229 newState.add(writer._referenceFor(key)); 229 newState.add(writer._referenceFor(key));
230 newState.add(writer._referenceFor(value)); 230 newState.add(writer._referenceFor(value));
231 }); 231 });
232 return newState; 232 return newState;
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
268 268
269 /** 269 /**
270 * This rule handles primitive types, defined as those that we can normally 270 * This rule handles primitive types, defined as those that we can normally
271 * represent directly in the output format. We hard-code that to mean 271 * represent directly in the output format. We hard-code that to mean
272 * num, String, and bool. 272 * num, String, and bool.
273 */ 273 */
274 class PrimitiveRule extends SerializationRule { 274 class PrimitiveRule extends SerializationRule {
275 appliesTo(object, Writer w) { 275 appliesTo(object, Writer w) {
276 return isPrimitive(object); 276 return isPrimitive(object);
277 } 277 }
278 extractState(object, Function f) => object; 278 extractState(object, Function f, Writer w) => object;
279 flatten(object, Writer writer) {} 279 flatten(object, Writer writer) {}
280 inflateEssential(state, Reader r) => state; 280 inflateEssential(state, Reader r) => state;
281 inflateNonEssential(object, _, Reader r) {} 281 inflateNonEssential(object, _, Reader r) {}
282 282
283 bool get storesStateAsPrimitives => true; 283 bool get storesStateAsPrimitives => true;
284 284
285 /** 285 /**
286 * Indicate whether we should save pointers to this object as references 286 * Indicate whether we should save pointers to this object as references
287 * or store the object directly. For primitives this depends on the format, 287 * or store the object directly. For primitives this depends on the format,
288 * so we delegate to the writer. 288 * so we delegate to the writer.
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
348 class NamedObjectRule extends SerializationRule { 348 class NamedObjectRule extends SerializationRule {
349 /** 349 /**
350 * Return true if this rule applies to the object. Checked by looking up 350 * Return true if this rule applies to the object. Checked by looking up
351 * in the namedObjects collection. 351 * in the namedObjects collection.
352 */ 352 */
353 bool appliesTo(object, Writer writer) { 353 bool appliesTo(object, Writer writer) {
354 return writer.hasNameFor(object); 354 return writer.hasNameFor(object);
355 } 355 }
356 356
357 /** Extract the state of the named objects as just the object itself. */ 357 /** Extract the state of the named objects as just the object itself. */
358 extractState(object, Function f) => [object]; 358 extractState(object, Function f, Writer writer) {
359 var result = [nameFor(object, writer)];
360 f(result.first);
361 return result;
362 }
359 363
360 /** When we flatten the state we save it as the name. */ 364 /** When we flatten the state we save it as the name. */
361 // TODO(alanknight): This seems questionable. In a truly flat format we may 365 // TODO(alanknight): This seems questionable. In a truly flat format we may
362 // want to have extracted the name as a string first and flatten it into a 366 // want to have extracted the name as a string first and flatten it into a
363 // reference to that. But that requires adding the Writer as a parameter to 367 // reference to that. But that requires adding the Writer as a parameter to
364 // extractState, and I'm reluctant to add yet another parameter until 368 // extractState, and I'm reluctant to add yet another parameter until
365 // proven necessary. 369 // proven necessary.
366 flatten(state, Writer writer) { 370 flatten(state, Writer writer) {
367 state[0] = nameFor(state.first, writer); 371 state[0] = writer._referenceFor(state[0]);
368 } 372 }
369 373
370 /** Look up the named object and return it. */ 374 /** Look up the named object and return it. */
371 inflateEssential(state, Reader r) => r.objectNamed(state.first); 375 inflateEssential(state, Reader r) =>
376 r.objectNamed(r.resolveReference(state.first));
372 377
373 /** Set any non-essential state on the object. For this rule, a no-op. */ 378 /** Set any non-essential state on the object. For this rule, a no-op. */
374 inflateNonEssential(state, object, Reader r) {} 379 inflateNonEssential(state, object, Reader r) {}
375 380
376 /** Return the name for this object in the Writer. */ 381 /** Return the name for this object in the Writer. */
377 nameFor(object, Writer writer) => writer.nameFor(object); 382 nameFor(object, Writer writer) => writer.nameFor(object);
378 } 383 }
379 384
380 /** 385 /**
381 * This rule handles the special case of Mirrors, restricted to those that 386 * This rule handles the special case of Mirrors. It stores the mirror by its
382 * have a simpleName. It knows that it applies to any such mirror and 387 * qualifiedName and attempts to look it up in both the namedObjects
383 * automatically uses its simpleName as the key into the namedObjects. 388 * collection, or if it's not found there, by looking it up in the mirror
384 * When reading, the user is still responsible for adding the appropriate 389 * system. When reading, the user is responsible for supplying the appropriate
385 * mirrors to namedObject. 390 * values in [namedObjects] or in the [externals] paramter to
391 * [Serialization.read].
386 */ 392 */
387 class MirrorRule extends NamedObjectRule { 393 class MirrorRule extends NamedObjectRule {
388 bool appliesTo(object, Writer writer) => object is DeclarationMirror; 394 bool appliesTo(object, Writer writer) => object is DeclarationMirror;
389 nameFor(DeclarationMirror object, Writer writer) => object.simpleName; 395 nameFor(DeclarationMirror object, Writer writer) => object.qualifiedName;
396
397 inflateEssential(state, Reader r) {
398 var qualifiedName = r.resolveReference(state.first);
399 var lookupFull = r.objectNamed(qualifiedName, (x) => null);
400 if (lookupFull != null) return lookupFull;
401 var lib = qualifiedName.substring(0, qualifiedName.indexOf("."));
402 var type = qualifiedName.substring(qualifiedName.indexOf(".") + 1);
403 var lookup = r.objectNamed(type, (x) => null);
404 if (lookup != null) return lookup;
405 var libMirror = currentMirrorSystem().libraries[lib];
406 return libMirror.classes[type];
407 }
390 } 408 }
391 409
392 /** 410 /**
393 * This provides an abstract superclass for writing your own rules specific to 411 * This provides an abstract superclass for writing your own rules specific to
394 * a class. It makes some assumptions about behaviour, and so can have a 412 * a class. It makes some assumptions about behaviour, and so can have a
395 * simpler set of methods that need to be implemented in order to subclass it. 413 * simpler set of methods that need to be implemented in order to subclass it.
396 * 414 *
397 */ 415 */
398 abstract class CustomRule extends SerializationRule { 416 abstract class CustomRule extends SerializationRule {
399 // TODO(alanknight): It would be nice if we could provide an implementation 417 // TODO(alanknight): It would be nice if we could provide an implementation
(...skipping 23 matching lines...) Expand all
423 */ 441 */
424 create(List state); 442 create(List state);
425 443
426 /** 444 /**
427 * Set any state in [object] which wasn't set in the constructor. Between 445 * Set any state in [object] which wasn't set in the constructor. Between
428 * this method and [create] all of the information in [state] should be set 446 * this method and [create] all of the information in [state] should be set
429 * in the new object. 447 * in the new object.
430 */ 448 */
431 void setState(object, List state); 449 void setState(object, List state);
432 450
433 extractState(instance, Function f) { 451 extractState(instance, Function f, Writer w) {
434 var state = getState(instance); 452 var state = getState(instance);
435 for (var each in values(state)) { 453 for (var each in values(state)) {
436 f(each); 454 f(each);
437 } 455 }
438 return state; 456 return state;
439 } 457 }
440 458
441 inflateEssential(state, Reader r) => create(_lazy(state, r)); 459 inflateEssential(state, Reader r) => create(_lazy(state, r));
442 460
443 void inflateNonEssential(state, object, Reader r) => 461 void inflateNonEssential(state, object, Reader r) {
444 setState(object, _lazy(state, r)); 462 setState(object, _lazy(state, r));
463 }
445 464
446 // We don't want to have to make the end user tell us how long the list is 465 // We don't want to have to make the end user tell us how long the list is
447 // separately, so write it out for each object, even though they're all 466 // separately, so write it out for each object, even though they're all
448 // expected to be the same length. 467 // expected to be the same length.
449 get hasVariableLengthEntries => true; 468 get hasVariableLengthEntries => true;
450 } 469 }
451 470
452 /** Create a lazy list/map that will inflate its items on demand in [r]. */ 471 /** Create a lazy list/map that will inflate its items on demand in [r]. */
453 _lazy(l, Reader r) { 472 _lazy(l, Reader r) {
454 if (l is List) return new _LazyList(l, r); 473 if (l is List) return new _LazyList(l, r);
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
540 retainAll(x) => _throw(); 559 retainAll(x) => _throw();
541 removeMatching(x) => _throw(); 560 removeMatching(x) => _throw();
542 retainMatching(x) => _throw(); 561 retainMatching(x) => _throw();
543 getRange(x, y) => _throw(); 562 getRange(x, y) => _throw();
544 setRange(x, y, z, [a]) => _throw(); 563 setRange(x, y, z, [a]) => _throw();
545 removeRange(x, y) => _throw(); 564 removeRange(x, y) => _throw();
546 insertRange(x, y, [z]) => _throw(); 565 insertRange(x, y, [z]) => _throw();
547 get reversed => _throw(); 566 get reversed => _throw();
548 void set length(x) => _throw(); 567 void set length(x) => _throw();
549 } 568 }
OLDNEW
« no previous file with comments | « pkg/serialization/lib/src/reader_writer.dart ('k') | pkg/serialization/test/serialization_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698