LCOV - code coverage report
Current view: top level - model/relationship - relationship.dart (source / functions) Hit Total Coverage
Test: lcov.info Lines: 69 69 100.0 %
Date: 2022-05-06 22:54:19 Functions: 0 0 -

          Line data    Source code
       1             : part of flutter_data;
       2             : 
       3             : /// A `Set` that models a relationship between one or more [DataModel] objects
       4             : /// and their a [DataModel] owner. Backed by a [GraphNotifier].
       5             : abstract class Relationship<E extends DataModel<E>, N> with EquatableMixin {
       6           1 :   @protected
       7           5 :   Relationship(Set<E>? models) : this._(models?.map((m) => m._key).toSet());
       8             : 
       9           1 :   Relationship._(this._uninitializedKeys);
      10             : 
      11           1 :   Relationship._remove() : _uninitializedKeys = {};
      12             : 
      13             :   String? _ownerKey;
      14             :   String? _name;
      15             :   String? _inverseName;
      16             : 
      17           1 :   RemoteAdapter<E> get _adapter =>
      18           4 :       internalRepositories[_internalType]!.remoteAdapter as RemoteAdapter<E>;
      19           4 :   GraphNotifier get _graph => _adapter.localAdapter.graph;
      20             : 
      21             :   final Set<String>? _uninitializedKeys;
      22           2 :   String get _internalType => DataHelpers.getType<E>();
      23             : 
      24             :   /// Initializes this relationship (typically when initializing the owner
      25             :   /// in [DataModel]) by supplying the owner, and related metadata.
      26           1 :   Relationship<E, N> initialize(
      27             :       {required final DataModel owner,
      28             :       required final String name,
      29             :       final String? inverseName}) {
      30           1 :     if (_ownerKey != null) {
      31             :       return this; // return if already initialized
      32             :     }
      33             : 
      34           2 :     _ownerKey = owner._key;
      35           1 :     _name = name;
      36           1 :     _inverseName = inverseName;
      37             : 
      38           1 :     if (_uninitializedKeys == null) {
      39             :       // means it was omitted (remote-omitted, or loaded locally), so skip
      40             :       return this;
      41             :     }
      42             : 
      43             :     // setting up from scratch, remove all and add keys
      44             : 
      45           3 :     _graph._removeEdges(_ownerKey!,
      46           2 :         metadata: _name!, inverseMetadata: _inverseName, notify: false);
      47             : 
      48           2 :     _graph._addEdges(
      49           1 :       _ownerKey!,
      50           1 :       tos: _uninitializedKeys!,
      51           1 :       metadata: _name!,
      52           1 :       inverseMetadata: _inverseName,
      53             :       notify: false,
      54             :     );
      55           2 :     _uninitializedKeys!.clear();
      56             : 
      57             :     return this;
      58             :   }
      59             : 
      60             :   // implement collection-like methods
      61             : 
      62             :   /// Add a [value] to this [Relationship]
      63             :   ///
      64             :   /// Attempting to add an existing [value] has no effect as this is a [Set]
      65           1 :   bool add(E value, {bool notify = true}) {
      66           1 :     if (contains(value)) {
      67             :       return false;
      68             :     }
      69             : 
      70           4 :     _graph._addEdge(_ownerKey!, value._key,
      71           2 :         metadata: _name!, inverseMetadata: _inverseName, notify: false);
      72             :     if (notify) {
      73           2 :       _graph._notify(
      74           3 :         [_ownerKey!, value._key],
      75           1 :         metadata: _name,
      76             :         type: DataGraphEventType.addEdge,
      77             :       );
      78             :     }
      79             : 
      80             :     return true;
      81             :   }
      82             : 
      83           1 :   bool contains(Object? element) {
      84           2 :     return _iterable.contains(element);
      85             :   }
      86             : 
      87             :   /// Removes a [value] from this [Relationship]
      88           1 :   bool remove(Object? value, {bool notify = true}) {
      89             :     assert(value is E);
      90             :     final model = value as E;
      91             : 
      92           2 :     _graph._removeEdge(
      93           1 :       _ownerKey!,
      94           1 :       model._key,
      95           1 :       metadata: _name!,
      96           1 :       inverseMetadata: _inverseName,
      97             :       notify: false,
      98             :     );
      99             :     if (notify) {
     100           2 :       _graph._notify(
     101           3 :         [_ownerKey!, value._key],
     102           1 :         metadata: _name,
     103             :         type: DataGraphEventType.removeEdge,
     104             :       );
     105             :     }
     106             :     return true;
     107             :   }
     108             : 
     109           3 :   Set<E> toSet() => _iterable.toSet();
     110             : 
     111           3 :   List<E> toList() => _iterable.toList();
     112             : 
     113           3 :   int get length => _iterable.length;
     114             : 
     115             :   //
     116             : 
     117           3 :   E get first => _iterable.first;
     118             : 
     119           3 :   bool get isEmpty => _iterable.isEmpty;
     120             : 
     121           3 :   bool get isNotEmpty => _iterable.isNotEmpty;
     122             : 
     123           3 :   Iterable<E> where(bool Function(E) test) => _iterable.where(test);
     124             : 
     125           3 :   Iterable<T> map<T>(T Function(E) f) => _iterable.map(f);
     126             : 
     127             :   // support methods
     128             : 
     129           1 :   Iterable<E> get _iterable {
     130           7 :     return keys.map((key) => _adapter.localAdapter.findOne(key)).filterNulls;
     131             :   }
     132             : 
     133             :   /// Returns keys as [Set] in relationship
     134           1 :   @protected
     135             :   @visibleForTesting
     136             :   Set<String> get keys {
     137           5 :     return _graph._getEdge(_ownerKey!, metadata: _name!).toSet();
     138             :   }
     139             : 
     140           1 :   Set<String> get ids {
     141           7 :     return keys.map((key) => _graph.getIdForKey(key)).filterNulls.toSet();
     142             :   }
     143             : 
     144           1 :   Set<Relationship?> andEach(AlsoWatch<E>? alsoWatch) {
     145             :     return {
     146           1 :       this,
     147           3 :       for (final value in _iterable) ...?alsoWatch?.call(value),
     148             :     };
     149             :   }
     150             : 
     151           1 :   DelayedStateNotifier<DataGraphEvent> get _relationshipEventNotifier {
     152           4 :     return _adapter.graph.where((event) {
     153           2 :       return event.type.isEdge &&
     154           3 :           event.metadata == _name &&
     155           3 :           event.keys.containsFirst(_ownerKey!);
     156             :     });
     157             :   }
     158             : 
     159             :   DelayedStateNotifier<N> watch();
     160             : 
     161             :   /// This is used to make `json_serializable`'s `explicitToJson` transparent.
     162             :   ///
     163             :   /// For internal use. Does not return valid JSON.
     164           1 :   dynamic toJson() => this;
     165             : 
     166           1 :   @override
     167           4 :   List<Object?> get props => [_ownerKey, _name, _inverseName];
     168             : 
     169           1 :   @override
     170             :   String toString() {
     171             :     final keysWithoutId =
     172           8 :         keys.where((k) => _graph.getIdForKey(k) == null).map((k) => '[$k]');
     173           4 :     return '${{...ids, ...keysWithoutId}.join(', ')}';
     174             :   }
     175             : }
     176             : 
     177             : // annotation
     178             : 
     179             : class DataRelationship {
     180             :   final String? inverse;
     181             :   final bool serialize;
     182           3 :   const DataRelationship({this.inverse, this.serialize = true});
     183             : }

Generated by: LCOV version 1.15