DataSource

A DataSource is an interace for those classes responsible of fetching and managing raw data. This data can be manipulated in many ways as for example being stored in a local database, being sent via a network or socket interface or any third party services (sending emails via Sengrid or SMS via another service).

Usage

// Swift
let dataSource = MyCustomGetDataSource()
dataSource.get(IdQuery("myKey")).then { value in
    print("Success: \(value)")
}.fail { error in 
    print("Failure: \(error)")
}
// Kotlin
val dataSource = MyCustomGetDataSource()
dataSource.get(ByIdentifierQuery("myKey")).onComplete(onSuccess = {
    println(it)
}, onFailure = {
    println(it.localizedMessage)
})

Query

A Query object itself defines intrinsically how data must be manipulated, containing inside all parameters required to execute the action.

For more information, read the Query reference.

API

All actions handled by a DataSource are grouped in a simple CRUD.

Get

Fetch related functions.

// Swift
public protocol GetDataSource : DataSource {
    associatedtype T
    func get(_ query: Query) -> Future<T>
    func getAll(_ query: Query) -> Future<[T]>
}
// Kotlin
interface GetDataSource<V> : DataSource {
    fun get(query: Query): Future<V>
    fun getAll(query: Query): Future<List<V>>
}

Put

Actions related functions. PUT methods will be responsible of editing, modifying, sending or any other action related method.

Note that in the put function, the value is optional. This happens becasue it is not always required to have an actual value to perform the action defined by the Query. In the case of putAll, an empty array can be passed.

// Swift
public protocol PutDataSource : DataSource {
    associatedtype T
    func put(_ value: T?, in query: Query) -> Future<T>
    func putAll(_ array: [T], in query: Query) -> Future<[T]>
}
// Kotlin
interface PutDataSource<V> : DataSource {
    fun put(query: Query, value: V?): Future<V>
    fun putAll(query: Query, value: List<V>? = emptyList()): Future<List<V>>
}

Delete

Deletion related functions.

Note that only a Query is required and no value is returned rather than a Future encapsulating the output error.

// Swift
public protocol DeleteDataSource : DataSource {
    func delete(_ query: Query) -> Future<Void>
    func deleteAll(_ query: Query) -> Future<Void>
}
// Kotlin
interface DeleteDataSource : DataSource {
    fun delete(query: Query): Future<Unit>
    fun deleteAll(query: Query): Future<Unit>
}

IdQuery CRUD extensions

All GetDataSource, PutDataSource and DeleteDataSource interfaces are extended with methods to access the CRUD functions by an Id:

// Swift
extension GetDataSource {
    public func get<K>(_ id: K) -> Future<T> where K:Hashable { ... }
    public func getAll<K>(_ id: K) -> Future<[T]> where K:Hashable { ... }
}

extension PutDataSource {
    public func put<K>(_ value: T?, forId id: K) -> Future<T> where K:Hashable { ... }
    public func putAll<K>(_ array: [T], forId id: K) -> Future<[T]> where K:Hashable { ... }
}

extension DeleteDataSource {
    public func delete<K>(_ id: K) -> Future<Void> where K:Hashable { ... }
    public func deleteAll<K>(_ id: K) -> Future<Void> where K:Hashable { ... }
}
// TODO

This way, code that originally looked like this:

// Swift
dataSource.get(IdQuery("myKey"))
dataSource.put(myObject, in:IdQuery("myKey"))
dataSource.delete(IdQuery("myKey"))
// Kotlin
dataSource.get(ByIdentifierQuery("myKey"))
dataSource.put(ByIdentifierQuery("myKey"), myObject)
dataSource.delete(ByIdentifierQuery("myKey"))

can be written as follows:

// Swift
dataSource.get("myKey")
dataSource.put(myObject, forId:"myKey")
dataSource.delete("myKey")
// Kotlin
dataSource.get("myKey")
dataSource.put("myKey", myObject)
dataSource.delete("myKey")

DataSource Implementations

Swift exclusive implementations

  • TimedCacheDataSource<T>: A TLRU cache over a data source.
  • RealmDataSource<E,O>: Realm based data source. Available at the MJSWiftCore/Realm pod subspec.
  • KeychainDataSource<T>: Keychain based data source. Available at the MJSwiftCore/Security pod subspec.
  • DataSourceAssembler<T>: Combines three data sources (get, put, delete) into a single object.
  • AnyDataSource<T>: Type erasing for any get+put+delete data source.
  • AnyGetDataSource<T>: Type erasing for a get data source.
  • AnyPutDataSource<T>: Type erasing for a put data source.
  • RetryDataSource<T>: Encapsulates another data source and retries a call when an error happens.

Swift Notes

DataSource base protocol

In order to have a generic type, all GetDataSource, PutDataSource and DeleteDataSource extends from the following base protocol:

public protocol DataSource { }

Kotlin Notes

DataSource base interface

interface DataSource