Compare commits
	
		
			6 Commits
		
	
	
		
			b033b97917
			...
			37d9ab748d
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | 37d9ab748d | ||
|   | 3e533a5427 | ||
|   | 02ea266c43 | ||
|   | 2467bc306a | ||
|   | c2f375de6f | ||
|   | 18b1daa922 | 
| @ -7,7 +7,7 @@ | |||||||
|  * the Free Software Foundation, either version 3 of the License, or |  * the Free Software Foundation, either version 3 of the License, or | ||||||
|  * any later version. |  * any later version. | ||||||
| 
 | 
 | ||||||
|  * This program is distributed in the hope that it will be useful,  |  * This program is distributed in the hope that it will be useful, | ||||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of |  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||||||
|  * GNU General Public License for more details. |  * GNU General Public License for more details. | ||||||
| @ -31,10 +31,10 @@ The Wyatt Architecture for Flutter. | |||||||
| 
 | 
 | ||||||
| ## Features | ## Features | ||||||
| 
 | 
 | ||||||
| * Usecase | - Usecase | ||||||
| * Repository | - Repository | ||||||
| * DataSource | - DataSource | ||||||
| * Entity | - Entity | ||||||
| 
 | 
 | ||||||
| ## Usage | ## Usage | ||||||
| 
 | 
 | ||||||
| @ -73,19 +73,20 @@ abstract class PhotoRepository extends BaseRepository { | |||||||
| } | } | ||||||
| ``` | ``` | ||||||
| 
 | 
 | ||||||
| > Here the repository is just a proxy of the data sources with result type (to have beautiful  error handling). | > Here the repository is just a proxy of the data sources with result type (to have beautiful error handling). | ||||||
| 
 | 
 | ||||||
| And finaly create your different usecases by using `UseCase<Parameters, ReturnType>` : | And finaly create your different usecases : | ||||||
|  | 
 | ||||||
|  | Several use cases are supported : | ||||||
|  | 
 | ||||||
|  | - Classic usecase : | ||||||
| 
 | 
 | ||||||
| ```dart | ```dart | ||||||
| class RetrieveAllPhoto extends UseCase<QueryParameters, List<Photo>> { | class Test extends AsyncUseCase<QueryParameters, List<Photo>>> { | ||||||
|   final PhotoRepository _photoRepository; |  | ||||||
| 
 |  | ||||||
|   RetrieveAllPhotos(this._photoRepository); |  | ||||||
| 
 | 
 | ||||||
|   @override |   @override | ||||||
|   FutureResult<List<Photo>> call(QueryParameters params) { |   FuturOrResult<List<Photo>>> call(QueryParameters? params) { | ||||||
|     final photos = _photoRepository.getAllPhotos( |      final photos = _photoRepository.getAllPhotos( | ||||||
|       start: params.start, |       start: params.start, | ||||||
|       limit: params.limit, |       limit: params.limit, | ||||||
|     ); |     ); | ||||||
| @ -94,6 +95,54 @@ class RetrieveAllPhoto extends UseCase<QueryParameters, List<Photo>> { | |||||||
| } | } | ||||||
| ``` | ``` | ||||||
| 
 | 
 | ||||||
|  | You can add alternatve scenarios and check pre/post conditions using our extensions : | ||||||
|  | 
 | ||||||
|  | ```dart | ||||||
|  | class SearchPhotos extends AsyncUseCase<QueryParameters, List<Photo>>> { | ||||||
|  | 
 | ||||||
|  |   @override | ||||||
|  |   FutureOrResult<List<Photo>>> call(QueryParameters? params) { | ||||||
|  |      final photos = _photoRepository.getAllPhotos( | ||||||
|  |       start: params.start, | ||||||
|  |       limit: params.limit, | ||||||
|  |     ); | ||||||
|  |     return photos; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |   @override | ||||||
|  |   FutureOr<void> onStart(QueryParameters? params) { | ||||||
|  |     if(params.start == null || params.limit == null){ | ||||||
|  |       throw ClientException('Préconndition non valides'); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | You can implement error scenarios overriding `onError`, or check postconditions by overriding `onComplete` . | ||||||
|  | 
 | ||||||
|  | - Stream usecase : | ||||||
|  | 
 | ||||||
|  | ```dart | ||||||
|  | class SearchPhotos extends StreamUseCase<QueryParameters, List<Photo>>> { | ||||||
|  | 
 | ||||||
|  |   @override | ||||||
|  |   FutureOrResult<Stream<List<Photo>>>> call(QueryParameters? params) { | ||||||
|  |      final photos = _photoRepository.getAllPhotos( | ||||||
|  |       start: params.start, | ||||||
|  |       limit: params.limit, | ||||||
|  |     ); | ||||||
|  |     return photos; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | On this case, observers allow you to add alternative scénarios when data changed, overriding `onData` or `onDone`. | ||||||
|  | 
 | ||||||
|  | Please note that to use handlers, call `execute` methodes instead of `call`. | ||||||
|  | 
 | ||||||
| > In fact, here we need a new parameter object, so let's create it: | > In fact, here we need a new parameter object, so let's create it: | ||||||
| 
 | 
 | ||||||
| ```dart | ```dart | ||||||
| @ -171,4 +220,4 @@ class PhotoRepositoryImpl extends PhotoRepository { | |||||||
| } | } | ||||||
| ``` | ``` | ||||||
| 
 | 
 | ||||||
| That's all. | That's all. | ||||||
|  | |||||||
| @ -35,46 +35,47 @@ class PhotoRepositoryImpl extends PhotoRepository { | |||||||
|   ); |   ); | ||||||
| 
 | 
 | ||||||
|   @override |   @override | ||||||
|   FutureResult<void> addPhotoToFavorites(Photo photo) => Result.tryCatchAsync( |   FutureOrResult<void> addPhotoToFavorites(Photo photo) => Result.tryCatchAsync( | ||||||
|         () => _favoriteLocalDataSource.addPhotoToFavorites(photo), |         () => _favoriteLocalDataSource.addPhotoToFavorites(photo), | ||||||
|         (error) => ClientException('Cannot add photo to favorites.'), |         (error) => ClientException('Cannot add photo to favorites.'), | ||||||
|       ); |       ); | ||||||
| 
 | 
 | ||||||
|   @override |   @override | ||||||
|   FutureResult<bool> checkIfPhotoIsInFavorites(int id) => Result.tryCatchAsync( |   FutureOrResult<bool> checkIfPhotoIsInFavorites(int id) => | ||||||
|  |       Result.tryCatchAsync( | ||||||
|         () => _favoriteLocalDataSource.checkIfPhotoIsInFavorites(id), |         () => _favoriteLocalDataSource.checkIfPhotoIsInFavorites(id), | ||||||
|         (error) => |         (error) => | ||||||
|             ClientException('Cannot check if photo `$id` is in favorites.'), |             ClientException('Cannot check if photo `$id` is in favorites.'), | ||||||
|       ); |       ); | ||||||
| 
 | 
 | ||||||
|   @override |   @override | ||||||
|   FutureResult<void> deletePhotoFromFavorites(int id) => Result.tryCatchAsync( |   FutureOrResult<void> deletePhotoFromFavorites(int id) => Result.tryCatchAsync( | ||||||
|         () => _favoriteLocalDataSource.deletePhotoFromFavorites(id), |         () => _favoriteLocalDataSource.deletePhotoFromFavorites(id), | ||||||
|         (error) => ClientException('Cannot delete photo `$id` from favorites.'), |         (error) => ClientException('Cannot delete photo `$id` from favorites.'), | ||||||
|       ); |       ); | ||||||
| 
 | 
 | ||||||
|   @override |   @override | ||||||
|   FutureResult<Album> getAlbum(int id) => Result.tryCatchAsync( |   FutureOrResult<Album> getAlbum(int id) => Result.tryCatchAsync( | ||||||
|         () => _albumRemoteDataSource.getAlbum(id), |         () => _albumRemoteDataSource.getAlbum(id), | ||||||
|         (error) => ServerException('Cannot retrieve album $id.'), |         (error) => ServerException('Cannot retrieve album $id.'), | ||||||
|       ); |       ); | ||||||
| 
 | 
 | ||||||
|   @override |   @override | ||||||
|   FutureResult<List<Album>> getAllAlbums({int? start, int? limit}) => |   FutureOrResult<List<Album>> getAllAlbums({int? start, int? limit}) => | ||||||
|       Result.tryCatchAsync( |       Result.tryCatchAsync( | ||||||
|         () => _albumRemoteDataSource.getAllAlbums(start: start, limit: limit), |         () => _albumRemoteDataSource.getAllAlbums(start: start, limit: limit), | ||||||
|         (error) => ServerException('Cannot retrieve all albums.'), |         (error) => ServerException('Cannot retrieve all albums.'), | ||||||
|       ); |       ); | ||||||
| 
 | 
 | ||||||
|   @override |   @override | ||||||
|   FutureResult<List<Photo>> getAllPhotos({int? start, int? limit}) async => |   FutureOrResult<List<Photo>> getAllPhotos({int? start, int? limit}) async => | ||||||
|       Result.tryCatchAsync( |       Result.tryCatchAsync( | ||||||
|         () => _photoRemoteDataSource.getAllPhotos(start: start, limit: limit), |         () => _photoRemoteDataSource.getAllPhotos(start: start, limit: limit), | ||||||
|         (error) => ServerException('Cannot retrieve all photos.'), |         (error) => ServerException('Cannot retrieve all photos.'), | ||||||
|       ); |       ); | ||||||
| 
 | 
 | ||||||
|   @override |   @override | ||||||
|   FutureResult<List<Photo>> getAllPhotosFromFavorites() async { |   FutureOrResult<List<Photo>> getAllPhotosFromFavorites() async { | ||||||
|     try { |     try { | ||||||
|       final response = <Photo>[]; |       final response = <Photo>[]; | ||||||
|       final favorites = |       final favorites = | ||||||
| @ -95,13 +96,13 @@ class PhotoRepositoryImpl extends PhotoRepository { | |||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   @override |   @override | ||||||
|   FutureResult<Photo> getPhoto(int id) => Result.tryCatchAsync( |   FutureOrResult<Photo> getPhoto(int id) => Result.tryCatchAsync( | ||||||
|         () => _photoRemoteDataSource.getPhoto(id), |         () => _photoRemoteDataSource.getPhoto(id), | ||||||
|         (error) => ServerException('Cannot retrieve photo $id.'), |         (error) => ServerException('Cannot retrieve photo $id.'), | ||||||
|       ); |       ); | ||||||
| 
 | 
 | ||||||
|   @override |   @override | ||||||
|   FutureResult<List<Photo>> getPhotosFromAlbum( |   FutureOrResult<List<Photo>> getPhotosFromAlbum( | ||||||
|     int albumId, { |     int albumId, { | ||||||
|     int? start, |     int? start, | ||||||
|     int? limit, |     int? limit, | ||||||
|  | |||||||
| @ -19,17 +19,17 @@ import 'package:architecture_example/domain/entities/photo.dart'; | |||||||
| import 'package:wyatt_architecture/wyatt_architecture.dart'; | import 'package:wyatt_architecture/wyatt_architecture.dart'; | ||||||
| 
 | 
 | ||||||
| abstract class PhotoRepository extends BaseRepository { | abstract class PhotoRepository extends BaseRepository { | ||||||
|   FutureResult<Album> getAlbum(int id); |   FutureOrResult<Album> getAlbum(int id); | ||||||
|   FutureResult<List<Album>> getAllAlbums({int? start, int? limit}); |   FutureOrResult<List<Album>> getAllAlbums({int? start, int? limit}); | ||||||
|   FutureResult<Photo> getPhoto(int id); |   FutureOrResult<Photo> getPhoto(int id); | ||||||
|   FutureResult<List<Photo>> getAllPhotos({int? start, int? limit}); |   FutureOrResult<List<Photo>> getAllPhotos({int? start, int? limit}); | ||||||
|   FutureResult<List<Photo>> getPhotosFromAlbum( |   FutureOrResult<List<Photo>> getPhotosFromAlbum( | ||||||
|     int albumId, { |     int albumId, { | ||||||
|     int? start, |     int? start, | ||||||
|     int? limit, |     int? limit, | ||||||
|   }); |   }); | ||||||
|   FutureResult<void> addPhotoToFavorites(Photo photo); |   FutureOrResult<void> addPhotoToFavorites(Photo photo); | ||||||
|   FutureResult<void> deletePhotoFromFavorites(int id); |   FutureOrResult<void> deletePhotoFromFavorites(int id); | ||||||
|   FutureResult<List<Photo>> getAllPhotosFromFavorites(); |   FutureOrResult<List<Photo>> getAllPhotosFromFavorites(); | ||||||
|   FutureResult<bool> checkIfPhotoIsInFavorites(int id); |   FutureOrResult<bool> checkIfPhotoIsInFavorites(int id); | ||||||
| } | } | ||||||
|  | |||||||
| @ -1,31 +1,40 @@ | |||||||
| // Copyright (C) 2022 WYATT GROUP | // Copyright (C) 2022 WYATT GROUP | ||||||
| // Please see the AUTHORS file for details. | // Please see the AUTHORS file for details. | ||||||
| //  | // | ||||||
| // This program is free software: you can redistribute it and/or modify | // This program is free software: you can redistribute it and/or modify | ||||||
| // it under the terms of the GNU General Public License as published by | // it under the terms of the GNU General Public License as published by | ||||||
| // the Free Software Foundation, either version 3 of the License, or | // the Free Software Foundation, either version 3 of the License, or | ||||||
| // any later version. | // any later version. | ||||||
| //  | // | ||||||
| // This program is distributed in the hope that it will be useful, | // This program is distributed in the hope that it will be useful, | ||||||
| // but WITHOUT ANY WARRANTY; without even the implied warranty of | // but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
| // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||||||
| // GNU General Public License for more details. | // GNU General Public License for more details. | ||||||
| //  | // | ||||||
| // You should have received a copy of the GNU General Public License | // You should have received a copy of the GNU General Public License | ||||||
| // along with this program. If not, see <https://www.gnu.org/licenses/>. | // along with this program. If not, see <https://www.gnu.org/licenses/>. | ||||||
| 
 | 
 | ||||||
|  | import 'dart:async'; | ||||||
|  | 
 | ||||||
| import 'package:architecture_example/domain/entities/photo.dart'; | import 'package:architecture_example/domain/entities/photo.dart'; | ||||||
| import 'package:architecture_example/domain/repositories/photo_repository.dart'; | import 'package:architecture_example/domain/repositories/photo_repository.dart'; | ||||||
| import 'package:wyatt_architecture/wyatt_architecture.dart'; | import 'package:wyatt_architecture/wyatt_architecture.dart'; | ||||||
| 
 | 
 | ||||||
| class AddPhotoToFavorites extends UseCase<Photo, List<Photo>> { | class AddPhotoToFavorites extends AsyncUseCase<Photo, List<Photo>> { | ||||||
|   final PhotoRepository _photoRepository; |   final PhotoRepository _photoRepository; | ||||||
| 
 | 
 | ||||||
|   AddPhotoToFavorites(this._photoRepository); |   AddPhotoToFavorites(this._photoRepository); | ||||||
| 
 | 
 | ||||||
|   @override |   @override | ||||||
|   FutureResult<List<Photo>> call(Photo params) async { |   FutureOrResult<List<Photo>> call(Photo? params) async { | ||||||
|     await _photoRepository.addPhotoToFavorites(params); |     await _photoRepository.addPhotoToFavorites(params!); | ||||||
|     return _photoRepository.getAllPhotosFromFavorites(); |     return _photoRepository.getAllPhotosFromFavorites(); | ||||||
|   } |   } | ||||||
|  | 
 | ||||||
|  |   @override | ||||||
|  |   FutureOr<void> onStart(Photo? params) { | ||||||
|  |     if (params == null) { | ||||||
|  |       throw ClientException('Photo cannot be null'); | ||||||
|  |     } | ||||||
|  |   } | ||||||
| } | } | ||||||
|  | |||||||
| @ -14,15 +14,24 @@ | |||||||
| // You should have received a copy of the GNU General Public License | // You should have received a copy of the GNU General Public License | ||||||
| // along with this program. If not, see <https://www.gnu.org/licenses/>. | // along with this program. If not, see <https://www.gnu.org/licenses/>. | ||||||
| 
 | 
 | ||||||
|  | import 'dart:async'; | ||||||
|  | 
 | ||||||
| import 'package:architecture_example/domain/repositories/photo_repository.dart'; | import 'package:architecture_example/domain/repositories/photo_repository.dart'; | ||||||
| import 'package:wyatt_architecture/wyatt_architecture.dart'; | import 'package:wyatt_architecture/wyatt_architecture.dart'; | ||||||
| 
 | 
 | ||||||
| class CheckIfPhotoIsInFavorites extends UseCase<int, bool> { | class CheckIfPhotoIsInFavorites extends AsyncUseCase<int, bool> { | ||||||
|   final PhotoRepository _photoRepository; |   final PhotoRepository _photoRepository; | ||||||
| 
 | 
 | ||||||
|   CheckIfPhotoIsInFavorites(this._photoRepository); |   CheckIfPhotoIsInFavorites(this._photoRepository); | ||||||
| 
 | 
 | ||||||
|   @override |   @override | ||||||
|   FutureResult<bool> call(int params) async => |   FutureOrResult<bool> call(int? params) async => | ||||||
|       _photoRepository.checkIfPhotoIsInFavorites(params); |       _photoRepository.checkIfPhotoIsInFavorites(params!); | ||||||
|  | 
 | ||||||
|  |   @override | ||||||
|  |   FutureOr<void> onStart(int? params) { | ||||||
|  |     if (params == null) { | ||||||
|  |       throw ClientException('id cannot be null'); | ||||||
|  |     } | ||||||
|  |   } | ||||||
| } | } | ||||||
|  | |||||||
| @ -1,16 +1,16 @@ | |||||||
| // Copyright (C) 2022 WYATT GROUP | // Copyright (C) 2022 WYATT GROUP | ||||||
| // Please see the AUTHORS file for details. | // Please see the AUTHORS file for details. | ||||||
| //  | // | ||||||
| // This program is free software: you can redistribute it and/or modify | // This program is free software: you can redistribute it and/or modify | ||||||
| // it under the terms of the GNU General Public License as published by | // it under the terms of the GNU General Public License as published by | ||||||
| // the Free Software Foundation, either version 3 of the License, or | // the Free Software Foundation, either version 3 of the License, or | ||||||
| // any later version. | // any later version. | ||||||
| //  | // | ||||||
| // This program is distributed in the hope that it will be useful, | // This program is distributed in the hope that it will be useful, | ||||||
| // but WITHOUT ANY WARRANTY; without even the implied warranty of | // but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
| // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||||||
| // GNU General Public License for more details. | // GNU General Public License for more details. | ||||||
| //  | // | ||||||
| // You should have received a copy of the GNU General Public License | // You should have received a copy of the GNU General Public License | ||||||
| // along with this program. If not, see <https://www.gnu.org/licenses/>. | // along with this program. If not, see <https://www.gnu.org/licenses/>. | ||||||
| 
 | 
 | ||||||
| @ -18,13 +18,13 @@ import 'package:architecture_example/domain/entities/photo.dart'; | |||||||
| import 'package:architecture_example/domain/repositories/photo_repository.dart'; | import 'package:architecture_example/domain/repositories/photo_repository.dart'; | ||||||
| import 'package:wyatt_architecture/wyatt_architecture.dart'; | import 'package:wyatt_architecture/wyatt_architecture.dart'; | ||||||
| 
 | 
 | ||||||
| class DisplayFavorites extends UseCase<void, List<Photo>> { | class DisplayFavorites extends AsyncUseCase<NoParam, List<Photo>> { | ||||||
|   final PhotoRepository _photoRepository; |   final PhotoRepository _photoRepository; | ||||||
| 
 | 
 | ||||||
|   DisplayFavorites(this._photoRepository); |   DisplayFavorites(this._photoRepository); | ||||||
| 
 | 
 | ||||||
|   @override |   @override | ||||||
|   FutureResult<List<Photo>> call(void params) { |   FutureOrResult<List<Photo>> call(void params) { | ||||||
|     final photos = _photoRepository.getAllPhotosFromFavorites(); |     final photos = _photoRepository.getAllPhotosFromFavorites(); | ||||||
|     return photos; |     return photos; | ||||||
|   } |   } | ||||||
|  | |||||||
| @ -14,18 +14,27 @@ | |||||||
| // You should have received a copy of the GNU General Public License | // You should have received a copy of the GNU General Public License | ||||||
| // along with this program. If not, see <https://www.gnu.org/licenses/>. | // along with this program. If not, see <https://www.gnu.org/licenses/>. | ||||||
| 
 | 
 | ||||||
|  | import 'dart:async'; | ||||||
|  | 
 | ||||||
| import 'package:architecture_example/domain/entities/photo.dart'; | import 'package:architecture_example/domain/entities/photo.dart'; | ||||||
| import 'package:architecture_example/domain/repositories/photo_repository.dart'; | import 'package:architecture_example/domain/repositories/photo_repository.dart'; | ||||||
| import 'package:wyatt_architecture/wyatt_architecture.dart'; | import 'package:wyatt_architecture/wyatt_architecture.dart'; | ||||||
| 
 | 
 | ||||||
| class DisplayPhoto extends UseCase<int, Photo> { | class DisplayPhoto extends AsyncUseCase<int, Photo> { | ||||||
|   final PhotoRepository _photoRepository; |   final PhotoRepository _photoRepository; | ||||||
| 
 | 
 | ||||||
|   DisplayPhoto(this._photoRepository); |   DisplayPhoto(this._photoRepository); | ||||||
| 
 | 
 | ||||||
|   @override |   @override | ||||||
|   FutureResult<Photo> call(int params) { |   FutureOrResult<Photo> call(int? params) { | ||||||
|     final photo = _photoRepository.getPhoto(params); |     final photo = _photoRepository.getPhoto(params!); | ||||||
|     return photo; |     return photo; | ||||||
|   } |   } | ||||||
|  | 
 | ||||||
|  |   @override | ||||||
|  |   FutureOr<void> onStart(int? params) { | ||||||
|  |     if (params == null) { | ||||||
|  |       throw ClientException('id cannot be null'); | ||||||
|  |     } | ||||||
|  |   } | ||||||
| } | } | ||||||
|  | |||||||
| @ -14,24 +14,33 @@ | |||||||
| // You should have received a copy of the GNU General Public License | // You should have received a copy of the GNU General Public License | ||||||
| // along with this program. If not, see <https://www.gnu.org/licenses/>. | // along with this program. If not, see <https://www.gnu.org/licenses/>. | ||||||
| 
 | 
 | ||||||
|  | import 'dart:async'; | ||||||
|  | 
 | ||||||
| import 'package:architecture_example/domain/entities/photo.dart'; | import 'package:architecture_example/domain/entities/photo.dart'; | ||||||
| import 'package:architecture_example/domain/repositories/photo_repository.dart'; | import 'package:architecture_example/domain/repositories/photo_repository.dart'; | ||||||
| import 'package:architecture_example/domain/usecases/photos/params/query_parameters.dart'; | import 'package:architecture_example/domain/usecases/photos/params/query_parameters.dart'; | ||||||
| import 'package:wyatt_architecture/wyatt_architecture.dart'; | import 'package:wyatt_architecture/wyatt_architecture.dart'; | ||||||
| 
 | 
 | ||||||
| class OpenAlbum extends UseCase<QueryParameters, List<Photo>> { | class OpenAlbum extends AsyncUseCase<QueryParameters, List<Photo>> { | ||||||
|   final PhotoRepository _photoRepository; |   final PhotoRepository _photoRepository; | ||||||
| 
 | 
 | ||||||
|   OpenAlbum(this._photoRepository); |   OpenAlbum(this._photoRepository); | ||||||
| 
 | 
 | ||||||
|   @override |   @override | ||||||
|   FutureResult<List<Photo>> call(QueryParameters params) { |   FutureOrResult<List<Photo>> call(QueryParameters? params) { | ||||||
|     final photos = _photoRepository.getPhotosFromAlbum( |     final photos = _photoRepository.getPhotosFromAlbum( | ||||||
|       params.albumId, |       params!.albumId, | ||||||
|       start: params.start, |       start: params.start, | ||||||
|       limit: params.limit, |       limit: params.limit, | ||||||
|     ); |     ); | ||||||
| 
 | 
 | ||||||
|     return photos; |     return photos; | ||||||
|   } |   } | ||||||
|  | 
 | ||||||
|  |   @override | ||||||
|  |   FutureOr<void> onStart(QueryParameters? params) { | ||||||
|  |     if (params == null) { | ||||||
|  |       throw ClientException('params cannot be null'); | ||||||
|  |     } | ||||||
|  |   } | ||||||
| } | } | ||||||
|  | |||||||
| @ -14,18 +14,27 @@ | |||||||
| // You should have received a copy of the GNU General Public License | // You should have received a copy of the GNU General Public License | ||||||
| // along with this program. If not, see <https://www.gnu.org/licenses/>. | // along with this program. If not, see <https://www.gnu.org/licenses/>. | ||||||
| 
 | 
 | ||||||
|  | import 'dart:async'; | ||||||
|  | 
 | ||||||
| import 'package:architecture_example/domain/entities/photo.dart'; | import 'package:architecture_example/domain/entities/photo.dart'; | ||||||
| import 'package:architecture_example/domain/repositories/photo_repository.dart'; | import 'package:architecture_example/domain/repositories/photo_repository.dart'; | ||||||
| import 'package:wyatt_architecture/wyatt_architecture.dart'; | import 'package:wyatt_architecture/wyatt_architecture.dart'; | ||||||
| 
 | 
 | ||||||
| class RemovePhotoFromFavorites extends UseCase<int, List<Photo>> { | class RemovePhotoFromFavorites extends AsyncUseCase<int, List<Photo>> { | ||||||
|   final PhotoRepository _photoRepository; |   final PhotoRepository _photoRepository; | ||||||
| 
 | 
 | ||||||
|   RemovePhotoFromFavorites(this._photoRepository); |   RemovePhotoFromFavorites(this._photoRepository); | ||||||
| 
 | 
 | ||||||
|   @override |   @override | ||||||
|   FutureResult<List<Photo>> call(int params) async { |   FutureOrResult<List<Photo>> call(int? params) async { | ||||||
|     await _photoRepository.deletePhotoFromFavorites(params); |     await _photoRepository.deletePhotoFromFavorites(params!); | ||||||
|     return _photoRepository.getAllPhotosFromFavorites(); |     return _photoRepository.getAllPhotosFromFavorites(); | ||||||
|   } |   } | ||||||
|  | 
 | ||||||
|  |   @override | ||||||
|  |   FutureOr<void> onStart(int? params) { | ||||||
|  |     if (params == null) { | ||||||
|  |       throw ClientException('id cannot be null'); | ||||||
|  |     } | ||||||
|  |   } | ||||||
| } | } | ||||||
|  | |||||||
| @ -14,22 +14,31 @@ | |||||||
| // You should have received a copy of the GNU General Public License | // You should have received a copy of the GNU General Public License | ||||||
| // along with this program. If not, see <https://www.gnu.org/licenses/>. | // along with this program. If not, see <https://www.gnu.org/licenses/>. | ||||||
| 
 | 
 | ||||||
|  | import 'dart:async'; | ||||||
|  | 
 | ||||||
| import 'package:architecture_example/domain/entities/album.dart'; | import 'package:architecture_example/domain/entities/album.dart'; | ||||||
| import 'package:architecture_example/domain/repositories/photo_repository.dart'; | import 'package:architecture_example/domain/repositories/photo_repository.dart'; | ||||||
| import 'package:architecture_example/domain/usecases/photos/params/query_parameters.dart'; | import 'package:architecture_example/domain/usecases/photos/params/query_parameters.dart'; | ||||||
| import 'package:wyatt_architecture/wyatt_architecture.dart'; | import 'package:wyatt_architecture/wyatt_architecture.dart'; | ||||||
| 
 | 
 | ||||||
| class RetrieveAllAlbums extends UseCase<QueryParameters, List<Album>> { | class RetrieveAllAlbums extends AsyncUseCase<QueryParameters, List<Album>> { | ||||||
|   final PhotoRepository _photoRepository; |   final PhotoRepository _photoRepository; | ||||||
| 
 | 
 | ||||||
|   RetrieveAllAlbums(this._photoRepository); |   RetrieveAllAlbums(this._photoRepository); | ||||||
| 
 | 
 | ||||||
|   @override |   @override | ||||||
|   FutureResult<List<Album>> call(QueryParameters params) { |   FutureOrResult<List<Album>> call(QueryParameters? params) { | ||||||
|     final albums = _photoRepository.getAllAlbums( |     final albums = _photoRepository.getAllAlbums( | ||||||
|       start: params.start, |       start: params!.start, | ||||||
|       limit: params.limit, |       limit: params.limit, | ||||||
|     ); |     ); | ||||||
|     return albums; |     return albums; | ||||||
|   } |   } | ||||||
|  | 
 | ||||||
|  |   @override | ||||||
|  |   FutureOr<void> onStart(QueryParameters? params) { | ||||||
|  |     if (params == null) { | ||||||
|  |       throw ClientException('params cannot be null'); | ||||||
|  |     } | ||||||
|  |   } | ||||||
| } | } | ||||||
|  | |||||||
| @ -0,0 +1,44 @@ | |||||||
|  | // Copyright (C) 2022 WYATT GROUP | ||||||
|  | // Please see the AUTHORS file for details. | ||||||
|  | // | ||||||
|  | // This program is free software: you can redistribute it and/or modify | ||||||
|  | // it under the terms of the GNU General Public License as published by | ||||||
|  | // the Free Software Foundation, either version 3 of the License, or | ||||||
|  | // any later version. | ||||||
|  | // | ||||||
|  | // This program is distributed in the hope that it will be useful, | ||||||
|  | // but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
|  | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||||||
|  | // GNU General Public License for more details. | ||||||
|  | // | ||||||
|  | // You should have received a copy of the GNU General Public License | ||||||
|  | // along with this program. If not, see <https://www.gnu.org/licenses/>. | ||||||
|  | 
 | ||||||
|  | import 'dart:async'; | ||||||
|  | 
 | ||||||
|  | import 'package:wyatt_architecture/wyatt_architecture.dart'; | ||||||
|  | 
 | ||||||
|  | /// Usecase observers | ||||||
|  | mixin Observer<Parameters, ReturnType> { | ||||||
|  |   /// Called before usecase is runned. | ||||||
|  |   /// Usefull to check the preconditions | ||||||
|  |   FutureOr<void> onStart(Parameters? params) {} | ||||||
|  | 
 | ||||||
|  |   /// Called when error occures during main scenario | ||||||
|  |   /// Usefull to run alternative scenario | ||||||
|  |   FutureOr<void> onError(AppException? error) {} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /// Specific observer for classic usecase | ||||||
|  | mixin AsyncObserver<ReturnType> { | ||||||
|  |   FutureOr<void> onComplete(ReturnType? data) {} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /// Specific observer for stream case usecase | ||||||
|  | mixin StreamObserver<ReturnType> { | ||||||
|  |   /// Replaces the data event handler of this subscription. | ||||||
|  |   void onDone() {} | ||||||
|  | 
 | ||||||
|  |   ///  Replaces the done event handler of this subscription. | ||||||
|  |   void onData(ReturnType? data) {} | ||||||
|  | } | ||||||
| @ -1,27 +1,83 @@ | |||||||
| // Copyright (C) 2022 WYATT GROUP | // Copyright (C) 2022 WYATT GROUP | ||||||
| // Please see the AUTHORS file for details. | // Please see the AUTHORS file for details. | ||||||
| //  | // | ||||||
| // This program is free software: you can redistribute it and/or modify | // This program is free software: you can redistribute it and/or modify | ||||||
| // it under the terms of the GNU General Public License as published by | // it under the terms of the GNU General Public License as published by | ||||||
| // the Free Software Foundation, either version 3 of the License, or | // the Free Software Foundation, either version 3 of the License, or | ||||||
| // any later version. | // any later version. | ||||||
| //  | // | ||||||
| // This program is distributed in the hope that it will be useful, | // This program is distributed in the hope that it will be useful, | ||||||
| // but WITHOUT ANY WARRANTY; without even the implied warranty of | // but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
| // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||||||
| // GNU General Public License for more details. | // GNU General Public License for more details. | ||||||
| //  | // | ||||||
| // You should have received a copy of the GNU General Public License | // You should have received a copy of the GNU General Public License | ||||||
| // along with this program. If not, see <https://www.gnu.org/licenses/>. | // along with this program. If not, see <https://www.gnu.org/licenses/>. | ||||||
| 
 | 
 | ||||||
|  | import 'dart:async'; | ||||||
|  | 
 | ||||||
| import 'package:wyatt_architecture/src/core/exceptions/exceptions.dart'; | import 'package:wyatt_architecture/src/core/exceptions/exceptions.dart'; | ||||||
|  | import 'package:wyatt_architecture/src/domain/usecases/observers.dart'; | ||||||
| import 'package:wyatt_type_utils/wyatt_type_utils.dart'; | import 'package:wyatt_type_utils/wyatt_type_utils.dart'; | ||||||
| 
 | 
 | ||||||
| typedef FutureResult<T> = Future<Result<T, AppException>>; | typedef FutureOrResult<T> = FutureOr<Result<T, AppException>>; | ||||||
| typedef StreamResult<T> = Stream<Result<T, AppException>>; | typedef StreamResult<T> = Stream<Result<T, AppException>>; | ||||||
| typedef Res<T> = Result<T, AppException>; |  | ||||||
| 
 | 
 | ||||||
| // ignore: one_member_abstracts | /// Abstract class of a use case | ||||||
| abstract class UseCase<Parameters, ReturnType> { | abstract class BaseUseCase<Parameters, ReturnType> { | ||||||
|   FutureResult<ReturnType> call(Parameters params); |   /// Run use case scenarios | ||||||
|  |   ReturnType execute(Parameters parameters); | ||||||
|  | 
 | ||||||
|  |   /// Private function to implement main scenario | ||||||
|  |   /// of your usecase. | ||||||
|  |   ReturnType call(Parameters params); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /// Abstract class of a use case that deals specifically | ||||||
|  | /// with the response and its state. | ||||||
|  | abstract class UseCase<Parameters, ReturnType> | ||||||
|  |     extends BaseUseCase<Parameters?, FutureOrResult<ReturnType>> | ||||||
|  |     with Observer<Parameters, ReturnType> { | ||||||
|  |   FutureOr<void> _onSuccess(ReturnType data); | ||||||
|  | 
 | ||||||
|  |   /// Supports the result of the main scenario and integrates | ||||||
|  |   /// some alternative scenarios if necessary. | ||||||
|  |   @override | ||||||
|  |   FutureOrResult<ReturnType> execute(Parameters? parameters) => | ||||||
|  |       Result.tryCatchAsync( | ||||||
|  |         () async { | ||||||
|  |           await onStart(parameters); | ||||||
|  |           final response = await call(parameters); | ||||||
|  |           if (response.isErr) { | ||||||
|  |             await onError(response.err); | ||||||
|  |           } else if (response.isOk && response.ok != null) { | ||||||
|  |             await _onSuccess(response.ok as ReturnType); | ||||||
|  |           } | ||||||
|  | 
 | ||||||
|  |           return response.ok!; | ||||||
|  |         }, | ||||||
|  |         (error) => ClientException( | ||||||
|  |           error.toString(), | ||||||
|  |         ), | ||||||
|  |       ); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /// Abtstract classic usecase. | ||||||
|  | abstract class AsyncUseCase<Parameters, ReturnType> | ||||||
|  |     extends UseCase<Parameters?, ReturnType> with AsyncObserver<ReturnType> { | ||||||
|  |   @override | ||||||
|  |   FutureOr<void> _onSuccess(ReturnType data) => onComplete(data); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /// Abstract specific usecase bases on streams | ||||||
|  | abstract class StreamUseCase<Parameters, ReturnType> | ||||||
|  |     extends UseCase<Parameters?, Stream<ReturnType>> | ||||||
|  |     with StreamObserver<ReturnType> { | ||||||
|  |   @override | ||||||
|  |   FutureOr<void> _onSuccess(Stream<ReturnType> data) { | ||||||
|  |     data.listen( | ||||||
|  |       onData, | ||||||
|  |       onDone: onDone, | ||||||
|  |     ); | ||||||
|  |   } | ||||||
| } | } | ||||||
|  | |||||||
| @ -15,4 +15,5 @@ | |||||||
| // along with this program. If not, see <https://www.gnu.org/licenses/>. | // along with this program. If not, see <https://www.gnu.org/licenses/>. | ||||||
| 
 | 
 | ||||||
| export 'no_param.dart'; | export 'no_param.dart'; | ||||||
|  | export 'observers.dart'; | ||||||
| export 'usecase.dart'; | export 'usecase.dart'; | ||||||
|  | |||||||
							
								
								
									
										
											BIN
										
									
								
								packages/wyatt_architecture/models/class_model.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								packages/wyatt_architecture/models/class_model.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 117 KiB | 
							
								
								
									
										86
									
								
								packages/wyatt_architecture/models/class_model.puml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										86
									
								
								packages/wyatt_architecture/models/class_model.puml
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,86 @@ | |||||||
|  | @startuml | ||||||
|  | set namespaceSeparator :: | ||||||
|  | 
 | ||||||
|  | abstract class "wyatt_architecture::src::core::exceptions::exceptions.dart::AppException" { | ||||||
|  |   +String? message | ||||||
|  |   +String toString() | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | "dart::core::Exception" <|-- "wyatt_architecture::src::core::exceptions::exceptions.dart::AppException" | ||||||
|  | 
 | ||||||
|  | class "wyatt_architecture::src::core::exceptions::exceptions.dart::ClientException" { | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | "wyatt_architecture::src::core::exceptions::exceptions.dart::AppException" <|-- "wyatt_architecture::src::core::exceptions::exceptions.dart::ClientException" | ||||||
|  | class "wyatt_architecture::src::core::exceptions::exceptions.dart::ServerException" { | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | "wyatt_architecture::src::core::exceptions::exceptions.dart::AppException" <|-- "wyatt_architecture::src::core::exceptions::exceptions.dart::ServerException" | ||||||
|  | 
 | ||||||
|  | abstract class "wyatt_architecture::src::domain::repositories::base_repository.dart::BaseRepository" { | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | abstract class "wyatt_architecture::src::domain::data_sources::local::base_local_data_source.dart::BaseLocalDataSource" { | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | "wyatt_architecture::src::domain::data_sources::base_data_source.dart::BaseDataSource" <|-- "wyatt_architecture::src::domain::data_sources::local::base_local_data_source.dart::BaseLocalDataSource" | ||||||
|  | 
 | ||||||
|  | abstract class "wyatt_architecture::src::domain::data_sources::base_data_source.dart::BaseDataSource" { | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | abstract class "wyatt_architecture::src::domain::data_sources::remote::base_remote_data_source.dart::BaseRemoteDataSource" { | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | "wyatt_architecture::src::domain::data_sources::base_data_source.dart::BaseDataSource" <|-- "wyatt_architecture::src::domain::data_sources::remote::base_remote_data_source.dart::BaseRemoteDataSource" | ||||||
|  | 
 | ||||||
|  | class "wyatt_architecture::src::domain::usecases::no_param.dart::NoParam" { | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | "wyatt_architecture::src::domain::entities::entity.dart::Entity" <|-- "wyatt_architecture::src::domain::usecases::no_param.dart::NoParam" | ||||||
|  | 
 | ||||||
|  | abstract class "wyatt_architecture::src::domain::usecases::observers.dart::Observer" { | ||||||
|  |   +FutureOr<void> onStart() | ||||||
|  |   +FutureOr<void> onError() | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | abstract class "wyatt_architecture::src::domain::usecases::observers.dart::AsyncObserver" { | ||||||
|  |   +FutureOr<void> onComplete() | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | abstract class "wyatt_architecture::src::domain::usecases::observers.dart::StreamObserver" { | ||||||
|  |   +void onDone() | ||||||
|  |   +void onData() | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | abstract class "wyatt_architecture::src::domain::usecases::usecase.dart::BaseUseCase" { | ||||||
|  |   +ReturnType execute() | ||||||
|  |   +ReturnType call() | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | abstract class "wyatt_architecture::src::domain::usecases::usecase.dart::UseCase" { | ||||||
|  |   -FutureOr<void> _onSuccess() | ||||||
|  |   +FutureOr<Result<ReturnType, AppException>> execute() | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | "wyatt_architecture::src::domain::usecases::usecase.dart::BaseUseCase" <|-- "wyatt_architecture::src::domain::usecases::usecase.dart::UseCase" | ||||||
|  | "wyatt_architecture::src::domain::usecases::observers.dart::Observer" <|-- "wyatt_architecture::src::domain::usecases::usecase.dart::UseCase" | ||||||
|  | 
 | ||||||
|  | abstract class "wyatt_architecture::src::domain::usecases::usecase.dart::AsyncUseCase" { | ||||||
|  |   -FutureOr<void> _onSuccess() | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | "wyatt_architecture::src::domain::usecases::usecase.dart::UseCase" <|-- "wyatt_architecture::src::domain::usecases::usecase.dart::AsyncUseCase" | ||||||
|  | "wyatt_architecture::src::domain::usecases::observers.dart::AsyncObserver" <|-- "wyatt_architecture::src::domain::usecases::usecase.dart::AsyncUseCase" | ||||||
|  | 
 | ||||||
|  | abstract class "wyatt_architecture::src::domain::usecases::usecase.dart::StreamUseCase" { | ||||||
|  |   -FutureOr<void> _onSuccess() | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | "wyatt_architecture::src::domain::usecases::usecase.dart::UseCase" <|-- "wyatt_architecture::src::domain::usecases::usecase.dart::StreamUseCase" | ||||||
|  | "wyatt_architecture::src::domain::usecases::observers.dart::StreamObserver" <|-- "wyatt_architecture::src::domain::usecases::usecase.dart::StreamUseCase" | ||||||
|  | 
 | ||||||
|  | abstract class "wyatt_architecture::src::domain::entities::entity.dart::Entity" { | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | @enduml | ||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user