Line data Source code
1 : part of flutter_data; 2 : 3 : /// A [Relationship] that models a to-many ownership. 4 : /// 5 : /// Example: An author who has many books 6 : /// ``` 7 : /// class Author with DataModel<Author> { 8 : /// @override 9 : /// final int id; 10 : /// final String name; 11 : /// final HasMany<Book> books; 12 : /// 13 : /// Todo({this.id, this.name, this.books}); 14 : /// } 15 : ///``` 16 : class HasMany<E extends DataModel<E>> extends Relationship<E, Set<E>> { 17 : /// Creates a [HasMany] relationship, with an optional initial [Set<E>]. 18 : /// 19 : /// Example: 20 : /// ``` 21 : /// final book = Book(title: 'Harry Potter'); 22 : /// final author = Author(id: 1, name: 'JK Rowling', books: HasMany({book})); 23 : /// ``` 24 : /// 25 : /// See also: [IterableRelationshipExtension<E>.asHasMany] 26 22 : HasMany([Set<E>? models]) : super(models); 27 : 28 16 : HasMany._(Set<String>? keys) : super._(keys); 29 : 30 2 : HasMany.remove() : super._remove(); 31 : 32 : /// For internal use with `json_serializable`. 33 8 : factory HasMany.fromJson(final Map<String, dynamic> map) { 34 16 : if (map['_'] == null) return HasMany._(null); 35 8 : return HasMany._({...map['_']}); 36 : } 37 : 38 : /// Add a [value] to this [Relationship] 39 : /// 40 : /// Attempting to add an existing [value] has no effect as this is a [Set] 41 4 : bool add(E value, {bool notify = true}) { 42 4 : return _add(value, notify: notify); 43 : } 44 : 45 1 : bool contains(Object? element) { 46 1 : return _contains(element); 47 : } 48 : 49 : /// Removes a [value] from this [Relationship] 50 3 : bool remove(Object? value, {bool notify = true}) { 51 3 : return _remove(value, notify: notify); 52 : } 53 : 54 : /// Returns keys in this relationship. 55 20 : Set<String> get keys => _keys; 56 : 57 : /// Returns IDs in this relationship. 58 4 : Set<Object> get ids => _ids; 59 : 60 : // iterable utils 61 : 62 15 : Set<E> toSet() => _iterable.toSet(); 63 : 64 12 : List<E> toList() => _iterable.toList(); 65 : 66 15 : int get length => _iterable.length; 67 : 68 9 : E get first => _iterable.first; 69 : 70 6 : bool get isEmpty => _iterable.isEmpty; 71 : 72 0 : bool get isNotEmpty => _iterable.isNotEmpty; 73 : 74 3 : Iterable<E> where(bool Function(E) test) => _iterable.where(test); 75 : 76 3 : Iterable<T> map<T>(T Function(E) f) => _iterable.map(f); 77 : 78 : // 79 : 80 : /// Returns a [StateNotifier] which emits the latest [Set<E>] representing 81 : /// this [HasMany] relationship. 82 1 : @override 83 : DelayedStateNotifier<Set<E>> watch() { 84 4 : return _relationshipEventNotifier.map((e) => toSet()); 85 : } 86 : 87 2 : @override 88 4 : String toString() => 'HasMany<$E>(${super.toString()})'; 89 : } 90 : 91 : extension IterableRelationshipExtension<T extends DataModel<T>> on Set<T> { 92 : /// Converts a [Set<T>] into a [HasMany<T>]. 93 : /// 94 : /// Equivalent to using the constructor as `HasMany(set)`. 95 12 : HasMany<T> get asHasMany => HasMany<T>(this); 96 : }