From 8ebe047c0909db30684cf0d1732eda38f421cf47 Mon Sep 17 00:00:00 2001 From: Joan Martin Date: Wed, 27 Jun 2018 15:07:12 +0200 Subject: [PATCH] creating data source ensamblers --- .../Core/DI/InteractorAssembly.swift | 1 + .../MJSwiftCore/Core/DI/NetworkAssembly.swift | 2 +- .../Core/DI/RepositoryAssembly.swift | 4 +- .../Network/ItemNetworkDataSource.swift | 23 +-- Example/Pods/Pods.xcodeproj/project.pbxproj | 8 ++ .../Classes/Common/Repository/CoreError.swift | 11 +- .../Common/Repository/DataSource.swift | 52 ++++++- .../Repository/DataSourceEnsambler.swift | 133 ++++++++++++++++++ .../Repository/DataSourceRepository.swift | 38 +++-- .../Common/Repository/Repository.swift | 55 +++++++- .../Repository/RepositoryEnsambler.swift | 133 ++++++++++++++++++ 11 files changed, 421 insertions(+), 39 deletions(-) create mode 100644 MJSwiftCore/Classes/Common/Repository/DataSourceEnsambler.swift create mode 100644 MJSwiftCore/Classes/Common/Repository/RepositoryEnsambler.swift diff --git a/Example/MJSwiftCore/Core/DI/InteractorAssembly.swift b/Example/MJSwiftCore/Core/DI/InteractorAssembly.swift index bf35743c..7876d149 100644 --- a/Example/MJSwiftCore/Core/DI/InteractorAssembly.swift +++ b/Example/MJSwiftCore/Core/DI/InteractorAssembly.swift @@ -14,6 +14,7 @@ import MJSwiftCore class InteractorAssembly: Assembly { func assemble(container: Container) { + // Executor container.register(Executor.self, name: "GetItems") { r in DispatchQueueExecutor() }.inObjectScope(.container) diff --git a/Example/MJSwiftCore/Core/DI/NetworkAssembly.swift b/Example/MJSwiftCore/Core/DI/NetworkAssembly.swift index f9c865d0..cbe2c7dd 100644 --- a/Example/MJSwiftCore/Core/DI/NetworkAssembly.swift +++ b/Example/MJSwiftCore/Core/DI/NetworkAssembly.swift @@ -52,7 +52,7 @@ class NetworkAssembly: Assembly { } // Network Clients - container.register(AnyDataSource.self, name: Names.networkRepository) { r in ItemNetworkDataSource(r.resolve(SessionManager.self)!).asAnyDataSource() + container.register(AnyGetDataSource.self, name: Names.networkRepository) { r in ItemNetworkDataSource(r.resolve(SessionManager.self)!).asAnyGetDataSource() } } } diff --git a/Example/MJSwiftCore/Core/DI/RepositoryAssembly.swift b/Example/MJSwiftCore/Core/DI/RepositoryAssembly.swift index ee9faa46..a5018095 100644 --- a/Example/MJSwiftCore/Core/DI/RepositoryAssembly.swift +++ b/Example/MJSwiftCore/Core/DI/RepositoryAssembly.swift @@ -35,8 +35,8 @@ class RepositoryAssembly: Assembly { let storageDataSource = r.resolve(AnyDataSource.self, name: StorageAssembly.Names.storageRepository)! let storageValidationDataSource = DataSourceValidator(dataSource: storageDataSource, validator: r.resolve(ObjectValidation.self, name: Names.storageValidation)!) - let networkDataSource = r.resolve(AnyDataSource.self, name: NetworkAssembly.Names.networkRepository)! - let networkStorageRepo = NetworkStorageRepository(network: networkDataSource, + let networkDataSource = r.resolve(AnyGetDataSource.self, name: NetworkAssembly.Names.networkRepository)! + let networkStorageRepo = NetworkStorageRepository(network: DataSourceEnsambler(get: networkDataSource), storage: storageValidationDataSource) return RepositoryMapper(repository: networkStorageRepo, diff --git a/Example/MJSwiftCore/Core/Repository/Network/ItemNetworkDataSource.swift b/Example/MJSwiftCore/Core/Repository/Network/ItemNetworkDataSource.swift index bf4f9192..fbc941de 100644 --- a/Example/MJSwiftCore/Core/Repository/Network/ItemNetworkDataSource.swift +++ b/Example/MJSwiftCore/Core/Repository/Network/ItemNetworkDataSource.swift @@ -7,7 +7,6 @@ import Foundation import Alamofire import MJSwiftCore -import MJCocoaCore extension ItemEntity { fileprivate static var fromNetworkMap : [String : String] { @@ -19,7 +18,7 @@ extension ItemEntity { } } -class ItemNetworkDataSource : AlamofireDataSource { +class ItemNetworkDataSource : GetDataSource { typealias T = ItemEntity @@ -48,26 +47,6 @@ class ItemNetworkDataSource : AlamofireDataSource { query.fatalError(.getAll, self) } } - - func putAll(_ array: [ItemEntity], in query: Query) -> Future<[ItemEntity]> { - // Protocol-refactoring: NEEDS-IMPLEMENTATION OR ONLY CONFORMING TO GetDataSource - query.fatalError(.putAll, self) - } - - func put(_ value: ItemEntity?, in query: Query) -> Future { - // Protocol-refactoring: NEEDS-IMPLEMENTATION OR ONLY CONFORMING TO GetDataSource - query.fatalError(.put, self) - } - - func deleteAll(_ query: Query) -> Future { - // Protocol-refactoring: NEEDS-IMPLEMENTATION OR ONLY CONFORMING TO GetDataSource - query.fatalError(.deleteAll, self) - } - - func delete(_ query: Query) -> Future { - // Protocol-refactoring: NEEDS-IMPLEMENTATION OR ONLY CONFORMING TO GetDataSource - query.fatalError(.delete, self) - } } private extension ItemNetworkDataSource { diff --git a/Example/Pods/Pods.xcodeproj/project.pbxproj b/Example/Pods/Pods.xcodeproj/project.pbxproj index f2c0c143..204f30ba 100644 --- a/Example/Pods/Pods.xcodeproj/project.pbxproj +++ b/Example/Pods/Pods.xcodeproj/project.pbxproj @@ -431,6 +431,8 @@ D27CFF6A20E383030036392E /* AnyGetDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = D27CFF6720E383020036392E /* AnyGetDataSource.swift */; }; D27CFF6B20E383030036392E /* AnyPutDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = D27CFF6820E383030036392E /* AnyPutDataSource.swift */; }; D27CFF6D20E3838E0036392E /* Interactor.swift in Sources */ = {isa = PBXBuildFile; fileRef = D27CFF6C20E3838E0036392E /* Interactor.swift */; }; + D27CFF7120E3BABC0036392E /* DataSourceEnsambler.swift in Sources */ = {isa = PBXBuildFile; fileRef = D27CFF7020E3BABC0036392E /* DataSourceEnsambler.swift */; }; + D27CFF7320E3C2B40036392E /* RepositoryEnsambler.swift in Sources */ = {isa = PBXBuildFile; fileRef = D27CFF7220E3C2B40036392E /* RepositoryEnsambler.swift */; }; D290E01120B4097900D7C0D6 /* RetryDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = D290E01020B4097900D7C0D6 /* RetryDataSource.swift */; }; D29B2DAA40680D393BE3B29760F932EB /* MJSecureKey.m in Sources */ = {isa = PBXBuildFile; fileRef = 8F2F8D327B1D3930A8D7E644FCBD0DE0 /* MJSecureKey.m */; }; D2A179B820A5C04A00AC588B /* MJFuture+Throws.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2A179B720A5C04A00AC588B /* MJFuture+Throws.swift */; }; @@ -1190,6 +1192,8 @@ D27CFF6720E383020036392E /* AnyGetDataSource.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AnyGetDataSource.swift; sourceTree = ""; }; D27CFF6820E383030036392E /* AnyPutDataSource.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AnyPutDataSource.swift; sourceTree = ""; }; D27CFF6C20E3838E0036392E /* Interactor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Interactor.swift; sourceTree = ""; }; + D27CFF7020E3BABC0036392E /* DataSourceEnsambler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DataSourceEnsambler.swift; sourceTree = ""; }; + D27CFF7220E3C2B40036392E /* RepositoryEnsambler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RepositoryEnsambler.swift; sourceTree = ""; }; D290E01020B4097900D7C0D6 /* RetryDataSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RetryDataSource.swift; sourceTree = ""; }; D2A179B720A5C04A00AC588B /* MJFuture+Throws.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = "MJFuture+Throws.swift"; path = "MJSwiftCore/Classes/MJCocoaCore/MJFuture+Throws.swift"; sourceTree = ""; }; D2B7EB7420B802F00014A9DA /* Observable+MJFuture.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = "Observable+MJFuture.swift"; path = "MJSwiftCore/Classes/MJCocoaCore/Observable+MJFuture.swift"; sourceTree = ""; }; @@ -1884,6 +1888,7 @@ children = ( D252EBD220AAB80F000188A2 /* CoreError.swift */, 290287706A57A33D8B8D581891D4ADA5 /* DataSource.swift */, + D27CFF7020E3BABC0036392E /* DataSourceEnsambler.swift */, D2EDF60D20DA94B00063DB89 /* AnyDataSource.swift */, D27CFF6620E383020036392E /* AnyDeleteDataSource.swift */, D27CFF6720E383020036392E /* AnyGetDataSource.swift */, @@ -1895,6 +1900,7 @@ 12334A2FE64C881EC750BF933EE04D72 /* NetworkStorageRepository.swift */, 2911624EB2A68EC349EC0295A6955F86 /* Query+KeyValue.swift */, F0704F9FC8B9518C7E555C81E3F79640 /* Repository.swift */, + D27CFF7220E3C2B40036392E /* RepositoryEnsambler.swift */, 0067933C20DA39E700E7001F /* AnyRepository.swift */, D27CFF6120E37E190036392E /* AnyGetRepository.swift */, D27CFF6220E37E1A0036392E /* AnyPutRepository.swift */, @@ -3028,6 +3034,7 @@ 5532277E1F5C5FC042E8EB30713E10FA /* Future+Extensions.swift in Sources */, 076947D7AD725CA34C411FB73BAE19CD /* Future+Functional.swift in Sources */, BC69339E483340C87361D2D75027FCB9 /* Future+MJFuture.swift in Sources */, + D27CFF7320E3C2B40036392E /* RepositoryEnsambler.swift in Sources */, 2449DF79C7245BFD648545A0681FD2AF /* Future+Operators.swift in Sources */, C6477C4F63C9A874A341BC5062454A6C /* Future+Optionals.swift in Sources */, C0AED0EFE4986028A026363B2705E658 /* Future+Time.swift in Sources */, @@ -3070,6 +3077,7 @@ 6187BA6A8B614E71394BEF724C41E06C /* RealmDataSource.swift in Sources */, D94AE1A82EF11AABEB7DE8E912FECB9B /* RealmFactory.swift in Sources */, D27CFF6420E37E1A0036392E /* AnyGetRepository.swift in Sources */, + D27CFF7120E3BABC0036392E /* DataSourceEnsambler.swift in Sources */, D252EBDD20AC0D1B000188A2 /* ClassError.swift in Sources */, D454C3B9C2D6E3D546A34B7EDA5E91C3 /* RealmHandler+Future.swift in Sources */, DDC260200B674FB82DE7CEDFA5440147 /* RealmHandler.swift in Sources */, diff --git a/MJSwiftCore/Classes/Common/Repository/CoreError.swift b/MJSwiftCore/Classes/Common/Repository/CoreError.swift index 51bbb516..053fda55 100644 --- a/MJSwiftCore/Classes/Common/Repository/CoreError.swift +++ b/MJSwiftCore/Classes/Common/Repository/CoreError.swift @@ -51,17 +51,24 @@ public struct CoreError { } } + /// Illegal argument error + public class NotImplemented : ClassError { + public init(_ description: String = "Not Implemented") { + super.init(domain:CoreError.domain, code: 3, description: description) + } + } + /// Not valid error public class NotValid : ClassError { public init(_ description: String = "Object is not valid") { - super.init(domain:CoreError.domain, code: 3, description: description) + super.init(domain:CoreError.domain, code: 4, description: description) } } /// Failed error public class Failed : ClassError { public init(_ description: String = "Action failed") { - super.init(domain:CoreError.domain, code: 4, description: description) + super.init(domain:CoreError.domain, code: 5, description: description) } } } diff --git a/MJSwiftCore/Classes/Common/Repository/DataSource.swift b/MJSwiftCore/Classes/Common/Repository/DataSource.swift index 05749770..d9be92e6 100644 --- a/MJSwiftCore/Classes/Common/Repository/DataSource.swift +++ b/MJSwiftCore/Classes/Common/Repository/DataSource.swift @@ -164,10 +164,60 @@ extension DeleteDataSource { return deleteAll(IdQuery(id)) } } - /// /// Abstract definition of a DataSource /// public protocol DataSource : GetDataSource, PutDataSource, DeleteDataSource { } +/// +/// Blank data source superclass implementation +/// +public class BlankDataSourceBase : TypedDataSource { + private let crash : Bool + public init(crash : Bool = true) { self.crash = crash } + + internal func crashOrError(_ query: Query) -> Error { + if crash { + query.fatalError(.get, self) + } else { + return CoreError.NotImplemented() + } + } +} + +/// +/// Blank get data source implementation +/// +public class BlankGetDataSource : BlankDataSourceBase, GetDataSource { + public func get(_ query: Query) -> Future { return Future(crashOrError(query)) } + public func getAll(_ query: Query) -> Future<[T]> { return Future(crashOrError(query)) } +} + +/// +/// Blank put data source implementation +/// +public class BlankPutDataSource : BlankDataSourceBase, PutDataSource { + public func put(_ value: T?, in query: Query) -> Future { return Future(crashOrError(query)) } + public func putAll(_ array: [T], in query: Query) -> Future<[T]> { return Future(crashOrError(query)) } +} + +/// +/// Blank delete data source implementation +/// +public class BlankDeleteDataSource : BlankDataSourceBase, DeleteDataSource { + public func delete(_ query: Query) -> Future { return Future(crashOrError(query)) } + public func deleteAll(_ query: Query) -> Future { return Future(crashOrError(query)) } +} + +/// +/// Blank data source implementation +/// +public class BlankDataSource : BlankDataSourceBase, DataSource { + public func get(_ query: Query) -> Future { return Future(crashOrError(query)) } + public func getAll(_ query: Query) -> Future<[T]> { return Future(crashOrError(query)) } + public func put(_ value: T?, in query: Query) -> Future { return Future(crashOrError(query)) } + public func putAll(_ array: [T], in query: Query) -> Future<[T]> { return Future(crashOrError(query)) } + public func delete(_ query: Query) -> Future { return Future(crashOrError(query)) } + public func deleteAll(_ query: Query) -> Future { return Future(crashOrError(query)) } +} diff --git a/MJSwiftCore/Classes/Common/Repository/DataSourceEnsambler.swift b/MJSwiftCore/Classes/Common/Repository/DataSourceEnsambler.swift new file mode 100644 index 00000000..19882485 --- /dev/null +++ b/MJSwiftCore/Classes/Common/Repository/DataSourceEnsambler.swift @@ -0,0 +1,133 @@ +// +// Copyright 2018 Mobile Jazz SL +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import Foundation + +/// +/// Ensambles a CRUD data source into a single data source object +/// +public class DataSourceEnsambler : DataSource where Get.T == T, Put.T == T, Delete.T == T { + + private let getDataSource : Get + private let putDataSource : Put + private let deleteDataSource : Delete + + /// Main initializer + /// + /// - Parameters: + /// - getDataSource: The get data source + /// - putDataSource: The put data source + /// - deleteDataSource: The delete data source + public init(get getDataSource: Get, put putDataSource: Put, delete deleteDataSource: Delete) { + self.getDataSource = getDataSource + self.putDataSource = putDataSource + self.deleteDataSource = deleteDataSource + } + + public func get(_ query: Query) -> Future { + return getDataSource.get(query) + } + + public func getAll(_ query: Query) -> Future<[T]> { + return getDataSource.getAll(query) + } + + @discardableResult + public func put(_ value: T?, in query: Query) -> Future { + return putDataSource.put(value, in: query) + } + + @discardableResult + public func putAll(_ array: [T], in query: Query) -> Future<[T]> { + return putDataSource.putAll(array, in: query) + } + + @discardableResult + public func delete(_ query: Query) -> Future { + return deleteDataSource.delete(query) + } + + @discardableResult + public func deleteAll(_ query: Query) -> Future { + return deleteDataSource.deleteAll(query) + } +} + +extension DataSourceEnsambler where Get == Put, Get == Delete { + /// Initializer for a single DataSource + /// + /// - Parameter dataSource: The data source + public convenience init(_ dataSource: Get) { + self.init(get: dataSource, put: dataSource, delete: dataSource) + } +} + +extension DataSourceEnsambler where Put == BlankPutDataSource, Delete == BlankDeleteDataSource { + /// Initializer for a single DataSource + /// + /// - Parameter getDataSource: The data source + public convenience init(get getDataSource: Get) { + self.init(get: getDataSource, put: BlankPutDataSource(), delete: BlankDeleteDataSource()) + } +} + +extension DataSourceEnsambler where Get == BlankGetDataSource, Delete == BlankDeleteDataSource { + /// Initializer for a single DataSource + /// + /// - Parameter putDataSource: The data source + public convenience init(put putDataSource: Put) { + self.init(get: BlankGetDataSource(), put: putDataSource, delete: BlankDeleteDataSource()) + } +} + +extension DataSourceEnsambler where Get == BlankGetDataSource, Put == BlankPutDataSource { + /// Initializer for a single DataSource + /// + /// - Parameter deleteDataSource: The data source + public convenience init(delete deleteDataSource: Delete) { + self.init(get: BlankGetDataSource(), put: BlankPutDataSource(), delete: deleteDataSource) + } +} + +extension DataSourceEnsambler where Get == BlankGetDataSource { + /// Initializer for a single DataSource + /// + /// - Parameter putDataSource: The data source + /// - Parameter deleteDataSource: The data source + public convenience init(put putDataSource: Put, delete deleteDataSource: Delete) { + self.init(get: BlankGetDataSource(), put: putDataSource, delete: deleteDataSource) + } +} + +extension DataSourceEnsambler where Put == BlankPutDataSource { + /// Initializer for a single DataSource + /// + /// - Parameter getDataSource: The data source + /// - Parameter deleteDataSource: The data source + public convenience init(get getDataSource: Get, delete deleteDataSource: Delete) { + self.init(get: getDataSource, put: BlankPutDataSource(), delete: deleteDataSource) + } +} + +extension DataSourceEnsambler where Delete == BlankDeleteDataSource { + /// Initializer for a single DataSource + /// + /// - Parameter getDataSource: The data source + /// - Parameter putDataSource: The data source + public convenience init(get getDataSource: Get, put putDataSource: Put) { + self.init(get: getDataSource, put: putDataSource, delete: BlankDeleteDataSource()) + } +} diff --git a/MJSwiftCore/Classes/Common/Repository/DataSourceRepository.swift b/MJSwiftCore/Classes/Common/Repository/DataSourceRepository.swift index 8a442ebf..ac0cd2b3 100644 --- a/MJSwiftCore/Classes/Common/Repository/DataSourceRepository.swift +++ b/MJSwiftCore/Classes/Common/Repository/DataSourceRepository.swift @@ -132,9 +132,9 @@ extension DeleteDataSource { /// public class DataSourceRepository : Repository where Get.T == T, Put.T == T, Delete.T == T { - private let getDataSource : Get - private let putDataSource : Put - private let deleteDataSource : Delete + private let getDataSource : Get? + private let putDataSource : Put? + private let deleteDataSource : Delete? /// Main initializer /// @@ -142,38 +142,56 @@ public class DataSourceRepository Future { - return getDataSource.get(query) + guard let dataSource = getDataSource else { + fatalError() + } + return dataSource.get(query) } public func getAll(_ query: Query, operation: Operation = BlankOperation()) -> Future<[T]> { - return getDataSource.getAll(query) + guard let dataSource = getDataSource else { + fatalError() + } + return dataSource.getAll(query) } @discardableResult public func put(_ value: T?, in query: Query, operation: Operation = BlankOperation()) -> Future { - return putDataSource.put(value, in: query) + guard let dataSource = putDataSource else { + fatalError() + } + return dataSource.put(value, in: query) } @discardableResult public func putAll(_ array: [T], in query: Query, operation: Operation = BlankOperation()) -> Future<[T]> { - return putDataSource.putAll(array, in: query) + guard let dataSource = putDataSource else { + fatalError() + } + return dataSource.putAll(array, in: query) } @discardableResult public func delete(_ query: Query, operation: Operation = BlankOperation()) -> Future { - return deleteDataSource.delete(query) + guard let dataSource = deleteDataSource else { + fatalError() + } + return dataSource.delete(query) } @discardableResult public func deleteAll(_ query: Query, operation: Operation = BlankOperation()) -> Future { - return deleteDataSource.deleteAll(query) + guard let dataSource = deleteDataSource else { + fatalError() + } + return dataSource.deleteAll(query) } } diff --git a/MJSwiftCore/Classes/Common/Repository/Repository.swift b/MJSwiftCore/Classes/Common/Repository/Repository.swift index 2835c908..f9f589f4 100644 --- a/MJSwiftCore/Classes/Common/Repository/Repository.swift +++ b/MJSwiftCore/Classes/Common/Repository/Repository.swift @@ -44,7 +44,7 @@ public enum RepositoryCRUD : CustomStringConvertible { public protocol Operation { } extension Operation { - public func fatalError(_ method: RepositoryCRUD, _ origin: R) -> Never where R : Repository { + public func fatalError(_ method: RepositoryCRUD, _ origin: R) -> Never where R : TypedRepository { Swift.fatalError("Undefined operation \(String(describing: self)) for method \(method) on \(String(describing: type(of: origin)))") } } @@ -146,3 +146,56 @@ extension DeleteRepository { /// from the Repository superclass and forward the query to the desired DataSource. /// public protocol Repository : GetRepository, PutRepository, DeleteRepository { } + +/// +/// Blank repository superclass implementation +/// +public class BlankRepositoryBase : TypedRepository { + private let crash : Bool + public init(crash : Bool = true) { self.crash = crash } + + internal func crashOrError(_ operation: Operation) -> Error { + if crash { + operation.fatalError(.get, self) + } else { + return CoreError.NotImplemented() + } + } +} + +/// +/// Blank get repository implementation +/// +public class BlankGetRepository : BlankRepositoryBase, GetRepository { + public func get(_ query: Query, operation: Operation) -> Future { return Future(crashOrError(operation)) } + public func getAll(_ query: Query, operation: Operation) -> Future<[T]> { return Future(crashOrError(operation)) } +} + +/// +/// Blank put repository implementation +/// +public class BlankPutRepository : BlankRepositoryBase, PutRepository { + public func put(_ value: T?, in query: Query, operation: Operation) -> Future { return Future(crashOrError(operation)) } + public func putAll(_ array: [T], in query: Query, operation: Operation) -> Future<[T]> { return Future(crashOrError(operation)) } +} + +/// +/// Blank delete repository implementation +/// +public class BlankDeleteRepository : BlankRepositoryBase, DeleteRepository { + public func delete(_ query: Query, operation: Operation) -> Future { return Future(crashOrError(operation)) } + public func deleteAll(_ query: Query, operation: Operation) -> Future { return Future(crashOrError(operation)) } +} + +/// +/// Blank repository implementation +/// +public class BlankRepository : BlankRepositoryBase, Repository { + public func get(_ query: Query, operation: Operation) -> Future { return Future(crashOrError(operation)) } + public func getAll(_ query: Query, operation: Operation) -> Future<[T]> { return Future(crashOrError(operation)) } + public func put(_ value: T?, in query: Query, operation: Operation) -> Future { return Future(crashOrError(operation)) } + public func putAll(_ array: [T], in query: Query, operation: Operation) -> Future<[T]> { return Future(crashOrError(operation)) } + public func delete(_ query: Query, operation: Operation) -> Future { return Future(crashOrError(operation)) } + public func deleteAll(_ query: Query, operation: Operation) -> Future { return Future(crashOrError(operation)) } +} + diff --git a/MJSwiftCore/Classes/Common/Repository/RepositoryEnsambler.swift b/MJSwiftCore/Classes/Common/Repository/RepositoryEnsambler.swift new file mode 100644 index 00000000..7c083da8 --- /dev/null +++ b/MJSwiftCore/Classes/Common/Repository/RepositoryEnsambler.swift @@ -0,0 +1,133 @@ +// +// Copyright 2018 Mobile Jazz SL +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import Foundation + +/// +/// Ensambles a CRUD repository into a single repository object +/// +public class RepositoryEnsambler : Repository where Get.T == T, Put.T == T, Delete.T == T { + + private let getRepository : Get + private let putRepository : Put + private let deleteRepository : Delete + + /// Main initializer + /// + /// - Parameters: + /// - getRepository: The get repository + /// - putRepository: The put repository + /// - deleteRepository: The delete repository + public init(get getRepository: Get, put putRepository: Put, delete deleteRepository: Delete) { + self.getRepository = getRepository + self.putRepository = putRepository + self.deleteRepository = deleteRepository + } + + public func get(_ query: Query, operation: Operation) -> Future { + return getRepository.get(query, operation: operation) + } + + public func getAll(_ query: Query, operation: Operation) -> Future<[T]> { + return getRepository.getAll(query, operation: operation) + } + + @discardableResult + public func put(_ value: T?, in query: Query, operation: Operation) -> Future { + return putRepository.put(value, in: query, operation: operation) + } + + @discardableResult + public func putAll(_ array: [T], in query: Query, operation: Operation) -> Future<[T]> { + return putRepository.putAll(array, in: query, operation: operation) + } + + @discardableResult + public func delete(_ query: Query, operation: Operation) -> Future { + return deleteRepository.delete(query, operation: operation) + } + + @discardableResult + public func deleteAll(_ query: Query, operation: Operation) -> Future { + return deleteRepository.deleteAll(query, operation: operation) + } +} + +extension RepositoryEnsambler where Get == Put, Get == Delete { + /// Initializer for a single Repository + /// + /// - Parameter repository: The repository + public convenience init(_ repository: Get) { + self.init(get: repository, put: repository, delete: repository) + } +} + +extension RepositoryEnsambler where Put == BlankPutRepository, Delete == BlankDeleteRepository { + /// Initializer for a single Repository + /// + /// - Parameter getRepository: The repository + public convenience init(get getRepository: Get) { + self.init(get: getRepository, put: BlankPutRepository(), delete: BlankDeleteRepository()) + } +} + +extension RepositoryEnsambler where Get == BlankGetRepository, Delete == BlankDeleteRepository { + /// Initializer for a single Repository + /// + /// - Parameter putRepository: The repository + public convenience init(put putRepository: Put) { + self.init(get: BlankGetRepository(), put: putRepository, delete: BlankDeleteRepository()) + } +} + +extension RepositoryEnsambler where Get == BlankGetRepository, Put == BlankPutRepository { + /// Initializer for a single Repository + /// + /// - Parameter deleteRepository: The repository + public convenience init(delete deleteRepository: Delete) { + self.init(get: BlankGetRepository(), put: BlankPutRepository(), delete: deleteRepository) + } +} + +extension RepositoryEnsambler where Get == BlankGetRepository { + /// Initializer for a single Repository + /// + /// - Parameter putRepository: The repository + /// - Parameter deleteRepository: The repository + public convenience init(put putRepository: Put, delete deleteRepository: Delete) { + self.init(get: BlankGetRepository(), put: putRepository, delete: deleteRepository) + } +} + +extension RepositoryEnsambler where Put == BlankPutRepository { + /// Initializer for a single Repository + /// + /// - Parameter getRepository: The repository + /// - Parameter deleteRepository: The repository + public convenience init(get getRepository: Get, delete deleteRepository: Delete) { + self.init(get: getRepository, put: BlankPutRepository(), delete: deleteRepository) + } +} + +extension RepositoryEnsambler where Delete == BlankDeleteRepository { + /// Initializer for a single Repository + /// + /// - Parameter getRepository: The repository + /// - Parameter putRepository: The repository + public convenience init(get getRepository: Get, put putRepository: Put) { + self.init(get: getRepository, put: putRepository, delete: BlankDeleteRepository()) + } +}