Getting Resource Delta

To get resource delta, create the HHFWDeltaStream application, which uses framework methods:

Method name Brief description
initWithCredentials (_: host: environment: project: application: device:) The method initializes the framework.
auth (_: password:) The method authenticates the user by login and password.
openBase (_: key:) The method opens connection with database at the specified path.
resources (_: handler:) The method gets schemes of available resources and automatically creates corresponding tables in the database.
deltaStream (_: deltaStreamCallParams: handler:) The method loads delta to local database.
getTablesName (_: resourceName: requestParams: tableName:) The method returns table name in local database.
query (_: query:) The method sends SQL query to local database.

Auxiliary methods:

Method name Brief description
getURL (for:) The method returns URL for the file with the specified name in the Documents folder.
Type of returned data: URL
getRecords (from:) The method returns value of the "records" key from JSON result of SQL query to local database.
Type of returned data: [[String: Any]]?
getTableNames (from:) The method returns the array of values for "name" keys from results of the getRecords method.
Type of returned data: [String]
parseServerJSONResponse (json:) The method returns the result of converting JSON string into a dictionary.
Type of returned data: [String: Any]?
getResponseStatus (from:) The method returns value for the "status" key from JSON result of the query.
Type of returned data: String?
getTableNamesInDatabase (_: forResource: originalTableName:) The method returns the array of table names that satisfy the specified parameters: database location in application directory, resource name, searched table name.
Type of returned data: [String]

The HHFWDeltaStream application includes one screen, the UITextView text view, and UIButton buttons:

NOTE. When the application is initialized, authentication is executed, the buttons are not available. If the authentication is executed successfully, the buttons are available, and the text box displays the text "Authentication and resources load success".

To execute the example:

  1. Click the Perform DeltaStream button.

Clicking the button requests delta for the specified resource. Query execution result is automatically written to local database.

  1. Click the Perform SELECT button.

Clicking the button executes the SQL query SELECT * FROM table_name to local database.

Application code:

import UIKit
 
class ViewController: UIViewController {
 
    //MARK: - Outlets
    @IBOutlet weak var resultTextView: UITextView!
    @IBOutlet weak var deltaStreamButton: UIButton!
    @IBOutlet weak var queryButton: UIButton!
 
    //MARK: - View life cycle
    override func viewDidLoad() {
        super.viewDidLoad()
        self.deactivateButtons()
        self.initializeFramework()
        self.auth {
            self.activateButtons()
            self.resultTextView.text = "Authentication success"
        }
    }
 
    //MARK: - Actions
    @IBAction func deltaStreamPressed(_ sender: UIButton) {
        let databaseName = "database.sqlite"
        if self.openDatabase(databaseName) {
            self.loadResourcesScheme(databaseName) {
                self.loadDelta(databaseName) { (jsonResult) in
                    self.resultTextView.text = String(format: "%@", jsonResult)
                }
            }
        }
    }
 
    @IBAction func selectFromTablePressed(_ sender: UIButton) {
        let databaseName = "database.sqlite"
        self.performSelect(databaseName) { (jsonResult) in
            self.resultTextView.text = jsonResult
        }
    }
 
    //MARK: - HHFW - Framework initialization
    private func initializeFramework() {
        let apiVersion: String = "v1"
        let host: String = "http://testmasterfmp.fsight.cloud/"
        let environment: String = "Leonid_environment"
        let project: String = "Leonid_project"
        let application: String = "app"
        let device: String = (UIDevice.current.identifierForVendor?.uuidString)!
        HHFWController.sharedInstance().initWithCredentials(
            apiVersion,
            host: host,
            environment: environment,
            project: project,
            application: application,
            device: device
        )
    }
 
    //MARK: - HHFW - Authentication
    private func auth(completion: @escaping ()->()) {
        let username: String = "Leonid"
        let password: String = "123123"
        HHFWController.sharedInstance().auth(username, password: password){ (jsonResult) in
            if let jsonDict = jsonResult as? NSDictionary,
                let status = jsonDict["status"] as? String, status == "ok" {
                print("Auth success")
                completion()
            } else {
                print("Auth error")
            }
        }
    }
 
    //MARK: - HHFW - Open/create database
    private func openDatabase(_ databaseName: String) -> Bool {
        let fullDatabaseURL = self.getURL(for: databaseName)
        return HHFWController.sharedInstance().openBase(fullDatabaseURL.path, key: "")
    }
 
    //MARK: - HHFW - Load resource's scheme
    private func loadResourcesScheme(_ databaseName: String, completion: @escaping ()->()) {
        HHFWController.sharedInstance().resources(databaseName) { (jsonResult) in
            if let jsonDict = jsonResult as? NSDictionary,
                let status = jsonDict["status"] as? String, status == "ok" {
                print("Load resources success")
                completion()
            } else {
                print("Load resources error")
            }
        }
    }
 
    //MARK: - HHFW - DeltaStream request
    private func loadDelta(_ databaseName: String, completion: @escaping (NSDictionary)->()) {
        let resourceName = "study"
        let deltaStreamCallParams = DeltaStreamCallParams(defaultProperty: ())
        let fullDatabaseURL = self.getURL(for: databaseName)
        deltaStreamCallParams?.dataBasePath = fullDatabaseURL.path
        HHFWController.sharedInstance().deltaStream(resourceName, deltaStreamCallParams: deltaStreamCallParams) { (jsonResult) in
            if let jsonDict = jsonResult as? NSDictionary,
                let status = jsonDict["status"] as? String, status == "ok" {
                print("Load delta success")
                completion(jsonDict)
            } else {
                print("Load delta error")
            }
        }
    }
 
    //MARK: - HHFW - Performing SELECT * FROM table
    private func performSelect(_ databaseName: String, completion: (String?) -> ()) {
        let resourceName = "study"
        let tableName = "ET_TAB1"
 
        if let databaseTableName = self.getTableNamesInDatabase(databaseName, forResource: resourceName, originalTableName: tableName).first {
            let query = "SELECT * FROM `\(databaseTableName)`"
            let jsonResult = HHFWController.sharedInstance().query("/Documents/\(databaseName)", query: query)
            completion(jsonResult)
        }
    }
 
    //MARK: - HHFW - Get table names in local database
    private func getTableNamesInDatabase(_ databaseName: String, forResource resourceName: String, originalTableName tableName: String) -> [String] {
         let tableNames = HHFWController.sharedInstance().getTablesName("/Documents/\(databaseName)", resourceName: resourceName, requestParams: "", tableName: tableName)
        return self.getTableNames(from: tableNames)
    }
 
    //MARK: - View methods
    private func deactivateButtons() {
        self.deltaStreamButton.isEnabled = false
        self.queryButton.isEnabled = false
    }
 
    private func activateButtons() {
        self.deltaStreamButton.isEnabled = true
        self.queryButton.isEnabled = true
    }
 
    //MARK: - Helper methods
    private func getURL(for fileName: String) -> URL {
        let paths: [URL] = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
        let fileURL: URL = paths[0].appendingPathComponent(fileName)
        return fileURL
    }
 
    private func getRecords(from json: String?) -> [[String: Any]]? {
        var resultRecords: [[String: Any]]? = nil
        if let jsonString = json {
            let jsonDict = parseServerJSONResponse(json: jsonString)
            if self.getResponseStatus(from: jsonDict) == "ok" {
                if let result = jsonDict?["result"] as? [String: Any],
                    let database = result["database"] as? [String:Any],
                    let records = database["records"] as? [[String: Any]] {
                    resultRecords = records
                }
            }
        }
        return resultRecords
    }
 
    private func getTableNames(from json: String?) -> [String] {
        var resultTableNames: [String] = []
        if let records = getRecords(from: json) {
            for record in records {
                if let tableName = record["name"] as? String {
                    resultTableNames.append(tableName)
                }
            }
        }
        return resultTableNames
    }
 
    private func parseServerJSONResponse(json: String) -> [String: Any]? {
        guard let responseData = json.data(using: .utf8) else { return nil }
        return try? JSONSerialization.jsonObject(with: responseData, options: []) as! [String: Any]
    }
 
    func getResponseStatus(from json: [String: Any]?) -> String? {
        return json?["status"] as? String
    }
}

Getting Resource Delta (Asynchronous)

To get resource delta, create the HHFWDeltaStreamAsync application, which uses framework methods:

Method name Brief description
initWithCredentials (_: host: environment: project: application: device:) The method initializes the framework 
auth (_: password:) The method authenticates the user by login and password
openBase (_: key:) The method opens connection with database at the specified path
resources (_: handler:) The method gets schemes of available resources and automatically creates corresponding tables in the database.
deltaStreamAsync (_: withCache: deltaStreamCallParams: handler:) The method loads delta to local database
getTablesName (_: resourceName: requestParams: tableName:) The method returns table name in local database
query (_: query:) The method sends SQL query to local database.

Auxiliary methods of asynchronous getting resource delta are identical to auxiliary methods of getting resource delta.

The HHFWDeltaStreamAsync application includes one screen, the UITextView text view, and UIButton buttons:

NOTE. When the application is initialized, authentication is executed, the buttons are not available. If the authentication is executed successfully, the buttons are available, and the text box displays the text "Authentication and resources load success".

To execute the example:

  1. Click the Perform DeltaStream Async button.

Clicking the button asynchronously requests delta for the specified resource. Query execution result is automatically written to local database.

  1. Click the Perform SELECT button.

Clicking the button executes the SQL query SELECT * FROM table_name to local database.

Application code:

import UIKit
class ViewController: UIViewController {
    //MARK: - Outlets
    @IBOutlet weak var resultTextView: UITextView!
    @IBOutlet weak var deltaStreamButton: UIButton!
    @IBOutlet weak var queryButton: UIButton!
 
    //MARK: - View life cycle
    override func viewDidLoad() {
        super.viewDidLoad()
        self.deactivateButtons()
        self.initializeFramework()
        self.auth {
            self.activateButtons()
            self.resultTextView.text = "Authentication success"
        }
    }
    //MARK: - Actions
    @IBAction func deltaStreamPressed(_ sender: UIButton) {
        let databaseName = "database.sqlite"
        if self.openDatabase(databaseName) {
            self.loadResourcesScheme(databaseName) {
                self.loadDelta(databaseName) { (jsonResult) in
                    self.resultTextView.text = String(format: "%@", jsonResult)
                }
            }
        }
    }
    @IBAction func selectFromTablePressed(_ sender: UIButton) {
        let databaseName = "database.sqlite"
        self.performSelect(databaseName) { (jsonResult) in
            self.resultTextView.text = jsonResult
        }
    }
 
    //MARK: - HHFW - Framework initialization
    private func initializeFramework() {
        let apiVersion: String = "v1"
        let host: String = "http://testmasterfmp.fsight.cloud/"
        let environment: String = "DocumentationExampleEnv"
        let project: String = "DocumentationExampleProj"
        let application: String = "app"
        let device: String = (UIDevice.current.identifierForVendor?.uuidString)!
        HHFWController.sharedInstance().initWithCredentials(
            apiVersion,
            host: host,
            environment: environment,
            project: project,
            application: application,
            device: device
        )
    }
    //MARK: - HHFW - Authentication
    private func auth(completion: @escaping ()->()) {
        let username: String = "test"
        let password: String = "test123"
        HHFWController.sharedInstance().auth(username, password: password){ (jsonResult) in
            if let jsonDict = jsonResult as? NSDictionary,
                let status = jsonDict["status"] as? String, status == "ok" {
                print("Auth success")
                completion()
            } else {
                print("Auth error")
            }
        }
    }
 
    //MARK: - HHFW - Open/create database
    private func openDatabase(_ databaseName: String) -> Bool {
        let fullDatabaseURL = self.getURL(for: databaseName)
        return HHFWController.sharedInstance().openBase(fullDatabaseURL.path, key: "")
    }
 
    //MARK: - HHFW - Load resource's scheme
    private func loadResourcesScheme(_ databaseName: String, completion: @escaping ()->()) {
        HHFWController.sharedInstance().resources(databaseName) { (jsonResult) in
            if let jsonDict = jsonResult as? NSDictionary,
                let status = jsonDict["status"] as? String, status == "ok" {
                print("Load resources success")
                completion()
            } else {
                print("Load resources error")
            }
        }
    }
    //MARK: - HHFW - DeltaStream request
    private func loadDelta(_ databaseName: String, completion: @escaping (NSDictionary)->()) {
        let resourceName = "FRUITS"
        let deltaStreamCallParams = DeltaStreamCallParams(defaultDb: ())
        let fullDatabaseURL = self.getURL(for: databaseName)
        deltaStreamCallParams?.dataBasePath = fullDatabaseURL.path
        HHFWController.sharedInstance().deltaStreamAsync(resourceName, withCache: true, deltaStreamCallParams: deltaStreamCallParams) { (jsonResult) in
            if let jsonDict = jsonResult as? NSDictionary,
                let status = jsonDict["status"] as? String, status == "ok" {
                print("Load delta success")
                completion(jsonDict)
            } else {
                print("Load delta error")
            }
        }
    }
    //MARK: - HHFW - Performing SELECT * FROM table
    private func performSelect(_ databaseName: String, completion: (String?) -> ()) {
        let resourceName = "FRUITS"
        let tableName = "output_table"
        if let databaseTableName = self.getTableNamesInDatabase(databaseName, forResource: resourceName, originalTableName: tableName).first {
            let query = "SELECT * FROM `\(databaseTableName)`"
            let jsonResult = HHFWController.sharedInstance().query("/Documents/\(databaseName)", query: query)
            completion(jsonResult)
        }
    }
    //MARK: - HHFW - Get table names in local database
    private func getTableNamesInDatabase(_ databaseName: String, forResource resourceName: String, originalTableName tableName: String) -> [String] {
        let tableNames = HHFWController.sharedInstance().getTablesName("/Documents/\(databaseName)", resourceName: resourceName, requestParams: "", tableName: tableName)
        return self.getTableNames(from: tableNames)
    }
    //MARK: - View methods
    private func deactivateButtons() {
        self.deltaStreamButton.isEnabled = false
        self.queryButton.isEnabled = false
    }
    private func activateButtons() {
        self.deltaStreamButton.isEnabled = true
        self.queryButton.isEnabled = true
    }
    //MARK: - Helper methods
    private func getURL(for fileName: String) -> URL {
        let paths: [URL] = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
        let fileURL: URL = paths[0].appendingPathComponent(fileName)
        return fileURL
    }
    private func getRecords(from json: String?) -> [[String: Any]]? {
        var resultRecords: [[String: Any]]? = nil
        if let jsonString = json {
            let jsonDict = parseServerJSONResponse(json: jsonString)
            if self.getResponseStatus(from: jsonDict) == "ok" {
                if let result = jsonDict?["result"] as? [String: Any],
                    let database = result["database"] as? [String:Any],
                    let records = database["records"] as? [[String: Any]] {
                    resultRecords = records
                }
            }
        }
        return resultRecords
    }
    private func getTableNames(from json: String?) -> [String] {
        var resultTableNames: [String] = []
        if let records = getRecords(from: json) {
            for record in records {
                if let tableName = record["name"] as? String {
                    resultTableNames.append(tableName)
                }
            }
        }
        return resultTableNames
    }
    private func parseServerJSONResponse(json: String) -> [String: Any]? {
        guard let responseData = json.data(using: .utf8) else { return nil }
        return try? JSONSerialization.jsonObject(with: responseData, options: []) as! [String: Any]
    }
    func getResponseStatus(from json: [String: Any]?) -> String? {
        return json?["status"] as? String
    }
}

See also:

Examples of iOS Framework Use | Examples of Working with Resources