Line data Source code
1 : part of flutter_data;
2 :
3 : abstract class DataSupport<T extends DataSupport<T>> {
4 : Object get id;
5 :
6 : // "late" finals
7 : String _key;
8 : Map<String, RemoteAdapter> _adapters;
9 :
10 : // computed
11 10 : String get _type => DataHelpers.getType<T>();
12 20 : RemoteAdapter<T> get _adapter => _adapters[_type] as RemoteAdapter<T>;
13 15 : bool get _isInitialized => _key != null && _adapters != null;
14 :
15 : // initializers
16 :
17 5 : @protected
18 : T debugInit(dynamic repository) {
19 5 : assert(repository is Repository<T>);
20 10 : return _initialize((repository as Repository<T>)._adapters, save: true);
21 : }
22 :
23 5 : T _initialize(final Map<String, RemoteAdapter> adapters,
24 : {final String key, final bool save = false}) {
25 10 : if (_isInitialized) return _this;
26 :
27 10 : _this._adapters = adapters;
28 :
29 5 : assert(_adapter != null, '''\n
30 : Please ensure the type `$T` has been correctly initialized.\n
31 0 : ''');
32 :
33 : // model.id could be null, that's okay
34 50 : _this._key = _adapter.graph.getKeyForId(_this._adapter.type, _this.id,
35 5 : keyIfAbsent: key ?? DataHelpers.generateKey<T>());
36 :
37 : if (save) {
38 30 : _adapter.localAdapter.save(_this._key, _this);
39 : }
40 :
41 : // initialize relationships
42 : for (final metadata
43 29 : in _adapter.localAdapter.relationshipsFor(_this).entries) {
44 8 : final relationship = metadata.value['instance'] as Relationship;
45 :
46 4 : relationship?.initialize(
47 : adapters: adapters,
48 4 : owner: _this,
49 4 : name: metadata.key,
50 8 : inverseName: metadata.value['inverse'] as String,
51 : );
52 : }
53 :
54 5 : return _this;
55 : }
56 : }
57 :
58 : // ignore_for_file: unused_element
59 : extension DataSupportExtension<T extends DataSupport<T>> on DataSupport<T> {
60 1 : T get _this => this as T;
61 :
62 1 : T was(T model) {
63 1 : assert(model != null && model._isInitialized,
64 : 'Please initialize model before passing it to `was`');
65 : // initialize this model with existing model's repo & key
66 4 : return _this._initialize(model._adapters, key: model._key, save: true);
67 : }
68 :
69 1 : Future<T> save(
70 : {bool remote,
71 : Map<String, dynamic> params,
72 : Map<String, String> headers}) async {
73 4 : return await _adapter.save(_this,
74 : remote: remote, params: params, headers: headers, init: true);
75 : }
76 :
77 1 : Future<void> delete(
78 : {bool remote,
79 : Map<String, dynamic> params,
80 : Map<String, String> headers}) async {
81 4 : await _adapter.delete(_this,
82 : remote: remote, params: params, headers: headers);
83 : }
84 :
85 1 : Future<T> reload(
86 : {bool remote,
87 : Map<String, dynamic> params,
88 : Map<String, String> headers}) async {
89 4 : return await _adapter.findOne(_this,
90 : remote: remote, params: params, headers: headers, init: true);
91 : }
92 :
93 1 : DataStateNotifier<T> watch(
94 : {bool remote,
95 : Map<String, dynamic> params,
96 : Map<String, String> headers,
97 : AlsoWatch<T> alsoWatch}) {
98 3 : return _adapter.watchOne(_this,
99 : remote: remote, params: params, headers: headers, alsoWatch: alsoWatch);
100 : }
101 : }
102 :
103 : extension IterableDataSupportX<T extends DataSupport<T>> on Iterable<T> {
104 1 : List<T> _initialize(Map<String, RemoteAdapter> adapters,
105 : {String key, bool save = false}) {
106 4 : return map((m) => m._initialize(adapters, save: save)).toImmutableList();
107 : }
108 : }
109 :
110 1 : @visibleForTesting
111 1 : String keyFor<T extends DataSupport<T>>(T model) => model?._key;
|