diff --git a/C8oSDKiOS.xcodeproj/project.pbxproj b/C8oSDKiOS.xcodeproj/project.pbxproj index 99eb315..a1d8c03 100644 --- a/C8oSDKiOS.xcodeproj/project.pbxproj +++ b/C8oSDKiOS.xcodeproj/project.pbxproj @@ -26,7 +26,6 @@ 623C740B1C7C932900E691B0 /* C8oFullSyncCbl.swift in Sources */ = {isa = PBXBuildFile; fileRef = 623C740A1C7C932900E691B0 /* C8oFullSyncCbl.swift */; }; 623C740E1C7C94E900E691B0 /* C8oFullSyncDatabase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 623C740D1C7C94E900E691B0 /* C8oFullSyncDatabase.swift */; }; 623C74101C7CD02100E691B0 /* C8oLogger.swift in Sources */ = {isa = PBXBuildFile; fileRef = 623C740F1C7CD02100E691B0 /* C8oLogger.swift */; }; - 626CC7BF1CE4CAD6002ED698 /* libCBLJSViewCompiler.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 626CC7941CE4C5B4002ED698 /* libCBLJSViewCompiler.a */; }; 62CD2A571C6207AD009E9F7E /* C8oSDKiOSTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62CD2A561C6207AD009E9F7E /* C8oSDKiOSTests.swift */; }; 62DE2D181CB6B4130026C3B1 /* C8oLocalCacheResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62DE2D171CB6B4130026C3B1 /* C8oLocalCacheResponse.swift */; }; 62E4B45C1EF02595004C84AB /* .travis.yml in Resources */ = {isa = PBXBuildFile; fileRef = 62E4B45B1EF02595004C84AB /* .travis.yml */; }; @@ -90,8 +89,6 @@ 623C740A1C7C932900E691B0 /* C8oFullSyncCbl.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = C8oFullSyncCbl.swift; sourceTree = ""; }; 623C740D1C7C94E900E691B0 /* C8oFullSyncDatabase.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = C8oFullSyncDatabase.swift; sourceTree = ""; }; 623C740F1C7CD02100E691B0 /* C8oLogger.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = C8oLogger.swift; sourceTree = ""; }; - 626CC7931CE4C5B4002ED698 /* CBLRegisterJSViewCompiler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CBLRegisterJSViewCompiler.h; path = ../ObjC/CBLRegisterJSViewCompiler.h; sourceTree = ""; }; - 626CC7941CE4C5B4002ED698 /* libCBLJSViewCompiler.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libCBLJSViewCompiler.a; path = ../ObjC/libCBLJSViewCompiler.a; sourceTree = ""; }; 627259C31ED31C38004A3769 /* C8o.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = C8o.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 627259C41ED31C38004A3769 /* C8oSDKiOSTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = C8oSDKiOSTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 62CD2A4C1C6207AD009E9F7E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; @@ -133,7 +130,6 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 626CC7BF1CE4CAD6002ED698 /* libCBLJSViewCompiler.a in Frameworks */, D1E67029367412270B12DFA4 /* Pods_C8oSDKiOS.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; @@ -244,8 +240,6 @@ 620F6D151C776E0500683D0F /* C8oTranslator.swift */, 620F6D171C7771B300683D0F /* C8oUtils.swift */, 37F523B31C9ABE19007952C3 /* C8oCookieStorage.swift */, - 626CC7931CE4C5B4002ED698 /* CBLRegisterJSViewCompiler.h */, - 626CC7941CE4C5B4002ED698 /* libCBLJSViewCompiler.a */, ); name = Internal; sourceTree = ""; @@ -649,7 +643,6 @@ ENABLE_BITCODE = YES; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", - "$(PROJECT_DIR)/build/Debug-iphoneos", "$(PROJECT_DIR)/Pods/couchbase-lite-ios", ); INFOPLIST_FILE = C8oSDKiOS/Info.plist; @@ -657,9 +650,8 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; LIBRARY_SEARCH_PATHS = ( "$(inherited)", - "$(PROJECT_DIR)/C8oSDKiOS", - "$(PROJECT_DIR)/ObjC", "$(PROJECT_DIR)/Pods/couchbase-lite-ios/Extras", + "$(PROJECT_DIR)/C8oSDKiOS", ); MODULEMAP_FILE = ""; OTHER_LDFLAGS = ( @@ -701,7 +693,6 @@ ENABLE_TESTABILITY = YES; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", - "$(PROJECT_DIR)/build/Debug-iphoneos", "$(PROJECT_DIR)/Pods/couchbase-lite-ios", ); INFOPLIST_FILE = C8oSDKiOS/Info.plist; @@ -710,7 +701,6 @@ LIBRARY_SEARCH_PATHS = ( "$(inherited)", "$(PROJECT_DIR)/C8oSDKiOS", - "$(PROJECT_DIR)/ObjC", "$(PROJECT_DIR)/Pods/couchbase-lite-ios/Extras", ); MODULEMAP_FILE = ""; @@ -746,7 +736,7 @@ PRODUCT_BUNDLE_IDENTIFIER = com.convertigo.C8oSDKiOSTests; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; - SWIFT_SWIFT3_OBJC_INFERENCE = On; + SWIFT_SWIFT3_OBJC_INFERENCE = Default; SWIFT_VERSION = 4.0; }; name = Debug; @@ -764,7 +754,7 @@ PRODUCT_BUNDLE_IDENTIFIER = com.convertigo.C8oSDKiOSTests; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; - SWIFT_SWIFT3_OBJC_INFERENCE = On; + SWIFT_SWIFT3_OBJC_INFERENCE = Default; SWIFT_VERSION = 4.0; }; name = Release; diff --git a/C8oSDKiOS/C8o.swift b/C8oSDKiOS/C8o.swift index 9029b68..c98d201 100644 --- a/C8oSDKiOS/C8o.swift +++ b/C8oSDKiOS/C8o.swift @@ -13,84 +13,84 @@ import AEXML // FIXME: comparison operators with optionals were removed from the Swift Standard Libary. // Consider refactoring the code to use the non-optional operators. fileprivate func < (lhs: T?, rhs: T?) -> Bool { - switch (lhs, rhs) { - case let (l?, r?): - return l < r - case (nil, _?): - return true - default: - return false - } + switch (lhs, rhs) { + case let (l?, r?): + return l < r + case (nil, _?): + return true + default: + return false + } } /** Allows to send requests to a Convertigo Server (or Studio), these requests are called c8o calls. - + C8o calls are done thanks to a HTTP request or a CouchbaseLite usage. - + An instance of C8o is connected to only one Convertigo and can't change it. - + To use it, you have to first initialize the C8o instance with the Convertigo endpoint, then use call methods with Convertigo variables as parameter. */ open class C8o: C8oBase { - - /* Regular Expression */ - fileprivate static let RE_REQUESTABLE: NSRegularExpression = try! NSRegularExpression(pattern: "^([^.]*)\\.(?:([^.]+)|(?:([^.]+)\\.([^.]+)))$", options: []) - - fileprivate static let RE_ENDPOINT: NSRegularExpression = try! NSRegularExpression(pattern: "^(http(s)?://([^:/]+)(:[0-9]+)?/?.*?)/projects/([^/]+)$", options: []) - - /* Engine reserved parameters */ - internal static var ENGINE_PARAMETER_PROJECT: String = "__project" - internal static var ENGINE_PARAMETER_SEQUENCE: String = "__sequence" - internal static var ENGINE_PARAMETER_CONNECTOR: String = "__connector" - internal static var ENGINE_PARAMETER_TRANSACTION: String = "__transaction" - internal static var ENGINE_PARAMETER_ENCODED: String = "__encoded" - internal static var ENGINE_PARAMETER_DEVICE_UUID: String = "__uuid" + + /* Regular Expression */ + fileprivate static let RE_REQUESTABLE: NSRegularExpression = try! NSRegularExpression(pattern: "^([^.]*)\\.(?:([^.]+)|(?:([^.]+)\\.([^.]+)))$", options: []) + + fileprivate static let RE_ENDPOINT: NSRegularExpression = try! NSRegularExpression(pattern: "^(http(s)?://([^:/]+)(:[0-9]+)?/?.*?)/projects/([^/]+)$", options: []) + + /* Engine reserved parameters */ + internal static var ENGINE_PARAMETER_PROJECT: String = "__project" + internal static var ENGINE_PARAMETER_SEQUENCE: String = "__sequence" + internal static var ENGINE_PARAMETER_CONNECTOR: String = "__connector" + internal static var ENGINE_PARAMETER_TRANSACTION: String = "__transaction" + internal static var ENGINE_PARAMETER_ENCODED: String = "__encoded" + internal static var ENGINE_PARAMETER_DEVICE_UUID: String = "__uuid" internal static var ENGINE_PARAMETER_PROGRESS: String = "__progress" internal static var ENGINE_PARAMETER_FROM_LIVE: String = "__fromLive" - - /* FULLSYNC parameters */ - - /** - Constant to use as a parameter for a Call of "fs://.post" and must be followed by a FS_POLICY_* constant. - - c8o.callJson("fs://.post", parameters: - C8o.FS_POLICY, C8o.FS_POLICY_MERGE, - "docid", myid, - "mykey", myvalue - ).sync(); - */ - open static var FS_POLICY: String = "_use_policy" - /** - Use it with "fs://.post" and C8o.FS_POLICY. - - This is the default post policy that don't alter the document before the CouchbaseLite's insertion. - */ - open static var FS_POLICY_NONE: String = "none" - /** - Use it with "fs://.post" and C8o.FS_POLICY. - - This post policy remove the "_id" and "_rev" of the document before the CouchbaseLite's insertion. - */ - open static var FS_POLICY_CREATE: String = "create" - /** - Use it with "fs://.post" and C8o.FS_POLICY. - - This post policy inserts the document in CouchbaseLite even if a document with the same "_id" already exists. - */ - open static var FS_POLICY_OVERRIDE: String = "override" - /** - Use it with "fs://.post" and C8o.FS_POLICY. - - This post policy merge the document with an existing document with the same "_id" before the CouchbaseLite's insertion. - */ - open static var FS_POLICY_MERGE: String = "merge" - /** - Use it with "fs://.post". Default value is ".". - - This key allow to override the sub key separator in case of document depth modification. - */ + + /* FULLSYNC parameters */ + + /** + Constant to use as a parameter for a Call of "fs://.post" and must be followed by a FS_POLICY_* constant. + + c8o.callJson("fs://.post", parameters: + C8o.FS_POLICY, C8o.FS_POLICY_MERGE, + "docid", myid, + "mykey", myvalue + ).sync(); + */ + open static var FS_POLICY: String = "_use_policy" + /** + Use it with "fs://.post" and C8o.FS_POLICY. + + This is the default post policy that don't alter the document before the CouchbaseLite's insertion. + */ + open static var FS_POLICY_NONE: String = "none" + /** + Use it with "fs://.post" and C8o.FS_POLICY. + + This post policy remove the "_id" and "_rev" of the document before the CouchbaseLite's insertion. + */ + open static var FS_POLICY_CREATE: String = "create" + /** + Use it with "fs://.post" and C8o.FS_POLICY. + + This post policy inserts the document in CouchbaseLite even if a document with the same "_id" already exists. + */ + open static var FS_POLICY_OVERRIDE: String = "override" + /** + Use it with "fs://.post" and C8o.FS_POLICY. + + This post policy merge the document with an existing document with the same "_id" before the CouchbaseLite's insertion. + */ + open static var FS_POLICY_MERGE: String = "merge" + /** + Use it with "fs://.post". Default value is ".". + + This key allow to override the sub key separator in case of document depth modification. + */ open static var FS_SUBKEY_SEPARATOR: String = "_use_subkey_separator" /** Use it with "c8oSettings.setFullSyncStorageEngine" to choose the SQL fullsync storage engine. @@ -107,246 +107,246 @@ open class C8o: C8oBase { A live request automatically recall the then or thenUI handler when the database changed. */ open static var FS_LIVE: String = "__live" - - /* Local cache keys */ - - internal static var LOCAL_CACHE_DOCUMENT_KEY_RESPONSE: String = "response" - internal static var LOCAL_CACHE_DOCUMENT_KEY_RESPONSE_TYPE: String = "responseType" - internal static var LOCAL_CACHE_DOCUMENT_KEY_EXPIRATION_DATE: String = "expirationDate" - - internal static var LOCAL_CACHE_DATABASE_NAME: String = "c8olocalcache" - - /* Response type */ - - internal static var RESPONSE_TYPE_XML: String = "pxml" - internal static var RESPONSE_TYPE_JSON: String = "json" - - /* Static configuration */ - internal static var defaultUiDispatcher: Any?// ACTION? - internal static var deviceUUID: String = UIDevice.current.identifierForVendor!.uuidString - - /** - Returns the current version of the SDK as "x.y.z". - - returns: Current version of the SDK as "x.y.z". - */ - open static func getSdkVersion() -> String { - return "2.2.4" - } - - /* Attributes */ - - fileprivate var _endpoint: String? - fileprivate var _endpointConvertigo: String? - fileprivate var _endpointIsSecure: Bool? - fileprivate var _endpointHost: String? - fileprivate var _endpointPort: String? - fileprivate var _endpointProject: String? - - /* Used to run HTTP requests.*/ - internal var httpInterface: C8oHttpInterface? - - /* Allows to log locally and remotely to the Convertigo server.*/ - internal var c8oLogger: C8oLogger? - - /* Allows to make fullSync calls. */ - internal var c8oFullSync: C8oFullSync? + + /* Local cache keys */ + + internal static var LOCAL_CACHE_DOCUMENT_KEY_RESPONSE: String = "response" + internal static var LOCAL_CACHE_DOCUMENT_KEY_RESPONSE_TYPE: String = "responseType" + internal static var LOCAL_CACHE_DOCUMENT_KEY_EXPIRATION_DATE: String = "expirationDate" + + internal static var LOCAL_CACHE_DATABASE_NAME: String = "c8olocalcache" + + /* Response type */ + + internal static var RESPONSE_TYPE_XML: String = "pxml" + internal static var RESPONSE_TYPE_JSON: String = "json" + + /* Static configuration */ + internal static var defaultUiDispatcher: Any?// ACTION? + internal static var deviceUUID: String = UIDevice.current.identifierForVendor!.uuidString + + /** + Returns the current version of the SDK as "x.y.z". + - returns: Current version of the SDK as "x.y.z". + */ + open static func getSdkVersion() -> String { + return "2.2.4" + } + + /* Attributes */ + + fileprivate var _endpoint: String? + fileprivate var _endpointConvertigo: String? + fileprivate var _endpointIsSecure: Bool? + fileprivate var _endpointHost: String? + fileprivate var _endpointPort: String? + fileprivate var _endpointProject: String? + + /* Used to run HTTP requests.*/ + internal var httpInterface: C8oHttpInterface? + + /* Allows to log locally and remotely to the Convertigo server.*/ + internal var c8oLogger: C8oLogger? + + /* Allows to make fullSync calls. */ + internal var c8oFullSync: C8oFullSync? var lives = Dictionary() var livesDb = Dictionary() var handleFullSyncLive: C8oFullSyncChangeListener? - - /* Constructors */ - /** - This is the base object representing a Convertigo Server end point. This object should be instanciated when the apps starts and be accessible from any class of the app. Although this is not common, you may have several C8o objects instantiated in your app. - - - parameter endpoint : The Convertigo endpoint, syntax : {protocol}://{server}:{port}/{Convertigo web app path}/projects/{project name} - Example : http://computerName:18080/convertigo/projects/MyProject - - parameter c8oSettings : Initialization options. Example : new C8oSettings().setLogRemote(false).setDefaultDatabaseName("sample") - */ - public init(endpoint: String, c8oSettings: C8oSettings? = nil) throws { - super.init() - // Checks the URL validity - if (!C8oUtils.isValidUrl(endpoint)) { - // throw NSC8oError(domain: NSURLC8oErrorDomain, code: NSURLC8oErrorCannotOpenFile, userInfo: nil) - throw C8oException(message: C8oExceptionMessage.InvalidArgumentInvalidURL(endpoint)) - } - - // Checks the endpoint validty - let regexV = C8o.RE_ENDPOINT.matches(in: endpoint, options: [], range: NSMakeRange(0, endpoint.characters.count)) - - if (regexV.first == nil) { - throw C8oException(message: C8oExceptionMessage.InvalidArgumentInvalidEndpoint(endpoint)) - } - - _endpoint = endpoint + + /* Constructors */ + /** + This is the base object representing a Convertigo Server end point. This object should be instanciated when the apps starts and be accessible from any class of the app. Although this is not common, you may have several C8o objects instantiated in your app. + + - parameter endpoint : The Convertigo endpoint, syntax : {protocol}://{server}:{port}/{Convertigo web app path}/projects/{project name} + Example : http://computerName:18080/convertigo/projects/MyProject + - parameter c8oSettings : Initialization options. Example : new C8oSettings().setLogRemote(false).setDefaultDatabaseName("sample") + */ + @objc public init(endpoint: String, c8oSettings: C8oSettings? = nil) throws { + super.init() + // Checks the URL validity + if (!C8oUtils.isValidUrl(endpoint)) { + // throw NSC8oError(domain: NSURLC8oErrorDomain, code: NSURLC8oErrorCannotOpenFile, userInfo: nil) + throw C8oException(message: C8oExceptionMessage.InvalidArgumentInvalidURL(endpoint)) + } + + // Checks the endpoint validty + let regexV = C8o.RE_ENDPOINT.matches(in: endpoint, options: [], range: NSMakeRange(0, endpoint.count)) + + if (regexV.first == nil) { + throw C8oException(message: C8oExceptionMessage.InvalidArgumentInvalidEndpoint(endpoint)) + } + + _endpoint = endpoint _endpointConvertigo = (endpoint as NSString).substring(with: regexV[0].range(at: 1)) - + if (regexV[0].range(at: 2).location != NSNotFound) { _endpointIsSecure = !(endpoint as NSString?)!.substring(with: regexV[0].range(at: 2)).isEmpty - } else { - _endpointIsSecure = false - } + } else { + _endpointIsSecure = false + } _endpointHost = (endpoint as NSString).substring(with: regexV[0].range(at: 3)) if (regexV[0].range(at: 4).location != NSNotFound) { _endpointPort = (endpoint as NSString).substring(with: regexV[0].range(at: 4)) - } + } _endpointProject = (endpoint as NSString).substring(with: regexV[0].range(at: 5)) - - if (c8oSettings != nil) { - copyProperties(c8oSettings!) - } - - self.httpInterface = C8oHttpInterface(c8o: self) - self.c8oLogger = C8oLogger(c8o: self) - self.c8oLogger!.logMethodCall("C8o constructor") + + if (c8oSettings != nil) { + copyProperties(c8oSettings!) + } + + self.httpInterface = C8oHttpInterface(c8o: self) + self.c8oLogger = C8oLogger(c8o: self) + self.c8oLogger!.logMethodCall("C8o constructor") self.c8oFullSync = C8oFullSyncCbl(c8o: self) self.handleFullSyncLive = C8oFullSyncChangeListener(handler: {(changes: JSON) -> () in for task in self.lives.values { task.executeFromLive() } }) - } - - /** - This calls a Convertigo requestable. - Example usage: - @code - myc8o = C8o() - myC8o.call(requestable, parameters, c8oResponseXmlListener, c8oExceptionListener) - @endcode - @see http://www.convertigo.com/document/convertigo-client-sdk/programming-guide/ for more information. - */ - open func call(_ requestable: String?, parameters: Dictionary? = nil, c8oResponseListener: C8oResponseListener, c8oExceptionListener: C8oExceptionListener) -> Void { - var parameters = parameters - do { - if (requestable == nil) { - throw C8oException(message: C8oExceptionMessage.InvalidArgumentNullParameter("requestable")) - } - - // Checks parameters validity - if (parameters == nil) { - parameters = Dictionary() - } else { - // Clone parameters in order to modify them - parameters = Dictionary?(parameters!) - } - - // Use the requestable string to add parameters corresponding to the c8o project, sequence, connector and transaction (. or ..) - let regex: NSRegularExpression = C8o.RE_REQUESTABLE - let regexV = regex.matches(in: requestable!, options: [], range: NSMakeRange(0, requestable!.characters.count)) - - if (regexV.first == nil) { - throw C8oException(message: C8oExceptionMessage.InvalidArgumentInvalidEndpoint(_endpoint!)) // Exception(C8oExceptionMessage.InvalidArgumentInvalidEndpoint(endpoint)) - } - - // If the project name is specified + } + + /** + This calls a Convertigo requestable. + Example usage: + @code + myc8o = C8o() + myC8o.call(requestable, parameters, c8oResponseXmlListener, c8oExceptionListener) + @endcode + @see http://www.convertigo.com/document/convertigo-client-sdk/programming-guide/ for more information. + */ + @objc open func call(_ requestable: String?, parameters: Dictionary? = nil, c8oResponseListener: C8oResponseListener, c8oExceptionListener: C8oExceptionListener? = nil) -> Void { + var parameters = parameters + do { + if (requestable == nil) { + throw C8oException(message: C8oExceptionMessage.InvalidArgumentNullParameter("requestable")) + } + + // Checks parameters validity + if (parameters == nil) { + parameters = Dictionary() + } else { + // Clone parameters in order to modify them + parameters = Dictionary?(parameters!) + } + + // Use the requestable string to add parameters corresponding to the c8o project, sequence, connector and transaction (. or ..) + let regex: NSRegularExpression = C8o.RE_REQUESTABLE + let regexV = regex.matches(in: requestable!, options: [], range: NSMakeRange(0, requestable!.count)) + + if (regexV.first == nil) { + throw C8oException(message: C8oExceptionMessage.InvalidArgumentInvalidEndpoint(_endpoint!)) // Exception(C8oExceptionMessage.InvalidArgumentInvalidEndpoint(endpoint)) + } + + // If the project name is specified if ((requestable! as NSString).substring(with: regexV[0].range(at: 1)) != "") { parameters![C8o.ENGINE_PARAMETER_PROJECT] = (requestable! as NSString).substring(with: regexV[0].range(at: 1)) as Any - } - - // If the C8o call use a sequence + } + + // If the C8o call use a sequence let rangeLenght = regexV[0].range(at: 2).length - 1 - let requestableLenght = (requestable! as NSString?)?.length - if (rangeLenght < requestableLenght && rangeLenght > 0) { - + let requestableLenght = (requestable! as NSString?)?.length + if (rangeLenght < requestableLenght && rangeLenght > 0) { + if (((requestable! as NSString?)!.substring(with: regexV[0].range(at: 2)) as String?) != "") { parameters![C8o.ENGINE_PARAMETER_SEQUENCE] = (requestable! as NSString).substring(with: regexV[0].range(at: 2)) as Any - } else { + } else { parameters![C8o.ENGINE_PARAMETER_CONNECTOR] = (requestable! as NSString).substring(with: regexV[0].range(at: 3)) as Any - + parameters![C8o.ENGINE_PARAMETER_TRANSACTION] = (requestable! as NSString).substring(with: regexV[0].range(at: 4)) as Any - - } - - } else { + + } + + } else { parameters![C8o.ENGINE_PARAMETER_CONNECTOR] = (requestable! as NSString).substring(with: regexV[0].range(at: 3)) as Any - + parameters![C8o.ENGINE_PARAMETER_TRANSACTION] = (requestable! as NSString).substring(with: regexV[0].range(at: 4)) as Any - } - - try! call(parameters, c8oResponseListener: c8oResponseListener, c8oExceptionListener: c8oExceptionListener) - } - catch let e as C8oException { - handleCallException(c8oExceptionListener, requestParameters: parameters!, exception: e) - } - catch { - let _: String - } - } - - open func call(_ parameters: Dictionary? = nil, c8oResponseListener: C8oResponseListener? = nil, c8oExceptionListener: C8oExceptionListener? = nil) throws { - var parameters = parameters - // IMPORTANT : all c8o calls have to end here ! - - c8oLogger!.logMethodCall("Call", parameters: parameters! as NSObject) - - // Checks parameters validity - if (parameters == nil) { - parameters = Dictionary() - } else { - // Clones parameters in order to modify them - // parameters = parameters - parameters = Dictionary?(parameters!) - } - - // Creates a async task running on another thread - // Exceptions have to be handled by the C8oExceptionListener - let task = C8oCallTask(c8o: self, parameters: parameters!, c8oResponseListener: c8oResponseListener!, c8oExceptionListener: c8oExceptionListener!) - task.execute() - - } - - /** - Call a Convertigo Server backend service and return data in a JSON Object. - CallJSON will asynchrously call a "requestable" (Sequence, transaction or FullSync database) and return a C8oPromise object. - Example usage: - @code - myc8o = C8o() - myC8o.callJson(requestable, parameters) - @endcode - @see http://www.convertigo.com/document/convertigo-client-sdk/programming-guide/ for more information. - @param requestable : String - A "requestable" object of this form : - - project.sequence to call a Sequence in the convertigo server. If project is not specified explicitly here, - (.sequence) the default project specified in the enpoint will be used. - - project.connector.transaction to call a transaction in the convertigo server. if project is not specified explicitly here, - (.connector.transaction) the default project specified in the enpoint will be used. If - connector is not specified (..transaction) the default connector will be used. - fs://database.fullsync_verb to call the local NoSQL database for quering, updating and syncing according to the full_sync - verb used. See FullSync documentation for a list of verbs and parameters. - - @return A C8oPromise object on which you can chain other requests to get the data with the Then(), ThenUI() methods or - use the Async() to wait for the server response without blocking the request thread. You can also use the .Fail() and - FailUI() methods to handle C8oErrors. - - */ - open func callJson (_ requestable: String, parametersDict: Dictionary?) -> C8oPromise { - let promise = C8oPromise(c8o: self) - - call(requestable, - parameters: parametersDict, - c8oResponseListener: C8oResponseJsonListener(onJsonResponse: { - (response, requestParameters) -> () in - - if (response == nil) { - if (requestParameters!.keys.contains(C8o.ENGINE_PARAMETER_PROGRESS) == true) { - - promise.onProgress((((requestParameters! as Dictionary?)![C8o.ENGINE_PARAMETER_PROGRESS]) as? C8oProgress)!) - } - } else { - promise.onResponse(response, parameters: requestParameters) - } - - }), - c8oExceptionListener: C8oExceptionListener(onException: { - (params: Pair?>?) -> () in - - promise.onFailure(params?.key as C8oException?, parameters: params?.value) - })) - return promise + } + + try call(parameters, c8oResponseListener: c8oResponseListener, c8oExceptionListener: c8oExceptionListener) + } + catch let e as C8oException { + handleCallException(c8oExceptionListener, requestParameters: parameters!, exception: e) + } + catch { + let _: String + } + } + + @objc open func call(_ parameters: Dictionary? = nil, c8oResponseListener: C8oResponseListener? = nil, c8oExceptionListener: C8oExceptionListener? = nil) throws { + var parameters = parameters + // IMPORTANT : all c8o calls have to end here ! + + c8oLogger!.logMethodCall("Call", parameters: parameters! as NSObject) + + // Checks parameters validity + if (parameters == nil) { + parameters = Dictionary() + } else { + // Clones parameters in order to modify them + // parameters = parameters + parameters = Dictionary?(parameters!) + } + + // Creates a async task running on another thread + // Exceptions have to be handled by the C8oExceptionListener + let task = C8oCallTask(c8o: self, parameters: parameters!, c8oResponseListener: c8oResponseListener!, c8oExceptionListener: c8oExceptionListener!) + task.execute() + + } + + /** + Call a Convertigo Server backend service and return data in a JSON Object. + CallJSON will asynchrously call a "requestable" (Sequence, transaction or FullSync database) and return a C8oPromise object. + Example usage: + @code + myc8o = C8o() + myC8o.callJson(requestable, parameters) + @endcode + @see http://www.convertigo.com/document/convertigo-client-sdk/programming-guide/ for more information. + @param requestable : String + A "requestable" object of this form : + + project.sequence to call a Sequence in the convertigo server. If project is not specified explicitly here, + (.sequence) the default project specified in the enpoint will be used. + + project.connector.transaction to call a transaction in the convertigo server. if project is not specified explicitly here, + (.connector.transaction) the default project specified in the enpoint will be used. If + connector is not specified (..transaction) the default connector will be used. + fs://database.fullsync_verb to call the local NoSQL database for quering, updating and syncing according to the full_sync + verb used. See FullSync documentation for a list of verbs and parameters. + + @return A C8oPromise object on which you can chain other requests to get the data with the Then(), ThenUI() methods or + use the Async() to wait for the server response without blocking the request thread. You can also use the .Fail() and + FailUI() methods to handle C8oErrors. + + */ + open func callJson (_ requestable: String, parametersDict: Dictionary?) -> C8oPromise { + let promise = C8oPromise(c8o: self) + + call(requestable, + parameters: parametersDict, + c8oResponseListener: C8oResponseJsonListener(onJsonResponse: { + (response, requestParameters) -> () in + + if (response!.isEqual(NSNull())) { + if (requestParameters!.keys.contains(C8o.ENGINE_PARAMETER_PROGRESS) == true) { + + promise.onProgress((((requestParameters! as Dictionary?)![C8o.ENGINE_PARAMETER_PROGRESS]) as? C8oProgress)!) + } + } else { + promise.onResponse(JSON(response as Any), parameters: requestParameters) + } + + }), + c8oExceptionListener: C8oExceptionListener(onException: { + (exep: C8oException, params: Dictionary?) -> () in + + promise.onFailure(exep, parameters: params) + })) + return promise } /** @@ -407,7 +407,7 @@ open class C8o: C8oBase { FailUI() methods to handle C8oErrors. */ - open func callJson(_ requestable: String, parameters: Any?...) -> C8oPromise { + open func callJson(_ requestable: String, parameters: Any?...) -> C8oPromise { let parametersUp: [AnyObject]? = parameters as [AnyObject]? let dictionnary: Dictionary? if(parametersUp?.count != 0){ @@ -416,9 +416,9 @@ open class C8o: C8oBase { else{ dictionnary = Dictionary() } - return try! callJson(requestable, parametersDict: dictionnary) - - } + return callJson(requestable, parametersDict: dictionnary) + + } /** @@ -447,34 +447,32 @@ open class C8o: C8oBase { failUI() methods to handle C8oErrors. */ - open func callXml(_ requestable: String, parametersDict: Dictionary) -> C8oPromise { - - let promise = C8oPromise(c8o: self) - - call(requestable, - parameters: parametersDict, - c8oResponseListener: C8oResponseXmlListener(onXmlResponse: { - (response, requestParameters) -> () in - - if (response == nil) { - if (requestParameters!.keys.contains(C8o.ENGINE_PARAMETER_PROGRESS) == true) { - - promise.onProgress((((requestParameters! as Dictionary?)![C8o.ENGINE_PARAMETER_PROGRESS]) as? C8oProgress)!) - } - } else { - promise.onResponse(response as? AEXMLDocument, parameters: requestParameters) - } - - }) - , c8oExceptionListener: C8oExceptionListener(onException: { - (params: Pair?>?) -> () in - - promise.onFailure((params?.key) as C8oException?, parameters: params?.value) - - })) - return promise - - } + open func callXml(_ requestable: String, parametersDict: Dictionary) -> C8oPromise { + + let promise = C8oPromise(c8o: self) + + call(requestable, + parameters: parametersDict, + c8oResponseListener: C8oResponseXmlListener(onXmlResponse: { + (response, requestParameters) -> () in + if (response == nil) { + if (requestParameters!.keys.contains(C8o.ENGINE_PARAMETER_PROGRESS) == true) { + promise.onProgress((((requestParameters! as Dictionary?)![C8o.ENGINE_PARAMETER_PROGRESS]) as? C8oProgress)!) + } + } else { + promise.onResponse(response! as? AEXMLDocument, parameters: requestParameters) + } + + }) + , c8oExceptionListener: C8oExceptionListener(onException: { + (exep: C8oException, params: Dictionary?) -> () in + + promise.onFailure(exep, parameters: params) + + })) + return promise + + } /** Call a Convertigo Server backend service and return data in a XML Document. @@ -502,140 +500,132 @@ open class C8o: C8oBase { failUI() methods to handle C8oErrors. */ - open func callXml(_ requestable: String, parameters: Any?...) -> C8oPromise { - let parametersUp: [AnyObject]? = parameters as [AnyObject]? - let dictionnary: Dictionary? - if(parametersUp?.count != 0){ - dictionnary = try! C8o.toParameters(parametersUp) - } - else{ - dictionnary = Dictionary() - } - return try! callXml(requestable, parametersDict: C8o.toParameters(parameters as [AnyObject])) - } - - /** - Add a cookie to the cookie store.
- Automatically set the domain and secure flag using the c8o endpoint. - Example usage: - @see http://www.convertigo.com/document/convertigo-client-sdk/programming-guide/ for more information. - @param name : String - @param value : String - - */ - open func addCookie(_ name: String, value: String) -> Void { - httpInterface!.addCookie(name, value: value) - } - + open func callXml(_ requestable: String, parameters: Any?...) -> C8oPromise { + return try! callXml(requestable, parametersDict: C8o.toParameters(parameters as [AnyObject])) + } + + /** + Add a cookie to the cookie store.
+ Automatically set the domain and secure flag using the c8o endpoint. + Example usage: + @see http://www.convertigo.com/document/convertigo-client-sdk/programming-guide/ for more information. + @param name : String + @param value : String + + */ + open func addCookie(_ name: String, value: String) -> Void { + _ = httpInterface!.addCookie(name, value: value) + } + /** Enable the internal SDK log.
Add to the application log (generated using the c8o.log object) the logs generated internally by the SDK. Useful for debugging the SDK. */ - open override var logC8o: Bool { - get { return _logC8o! } - set(value) { _logC8o = value } - } - + open override var logC8o: Bool { + get { return _logC8o! } + set(value) { _logC8o = value } + } + /** Sets a value indicating if logs are sent to the Convertigo server.
Default is true. */ - open override var logRemote: Bool { - get { return _logRemote! } - set(value) { _logRemote = value } - } - - open override var logLevelLocal: C8oLogLevel { - get { return _logLevelLocal } - set(value) { _logLevelLocal = value } - } - + open override var logRemote: Bool { + get { return _logRemote! } + set(value) { _logRemote = value } + } + + open override var logLevelLocal: C8oLogLevel { + get { return _logLevelLocal } + set(value) { _logLevelLocal = value } + } + /** Set the storage engine for local FullSync databases. Use C8o.FS_STORAGE_SQL or C8o.FS_STORAGE_FORESTDB. */ - open override var fullSyncStorageEngine: String { - get { return _fullSyncStorageEngine } - set(value) { - if (C8o.FS_STORAGE_SQL == value || C8o.FS_STORAGE_FORESTDB == value) { - _fullSyncStorageEngine = value - } - } - } - + open override var fullSyncStorageEngine: String { + get { return _fullSyncStorageEngine } + set(value) { + if (C8o.FS_STORAGE_SQL == value || C8o.FS_STORAGE_FORESTDB == value) { + _fullSyncStorageEngine = value + } + } + } + /** Set the encryption key for local FullSync databases encryption. */ - open override var fullSyncEncryptionKey: String? { - get { return _fullSyncEncryptionKey } - set(value) { _fullSyncEncryptionKey = value } - } - - open var log: C8oLogger { - get { return c8oLogger! } - } + open override var fullSyncEncryptionKey: String? { + get { return _fullSyncEncryptionKey } + set(value) { _fullSyncEncryptionKey = value } + } + + open var log: C8oLogger { + get { return c8oLogger! } + } /** Is the current thread is the UI thread. */ - open func isUI () -> Bool { - return Thread.isMainThread - } - + open func isUI () -> Bool { + return Thread.isMainThread + } + /** Run a block of code in the UI Thread.
Run the code directly if already in the UI thread. */ - open func runUI (_ block: DispatchWorkItem) { - DispatchQueue.main.async(execute: block) - - } + open func runUI (_ block: DispatchWorkItem) { + DispatchQueue.main.async(execute: block) + + } /** Run a block of code in a background Thread. */ - open func runBG (_ block: DispatchWorkItem) { - DispatchQueue.global(qos: .userInitiated).async(execute: block) - } - - open override var description: String { - get { - return "C8o[" + _endpoint! + "] " + super.description - } - } - - open var endpoint: String { - get { return _endpoint! } - } - - open var endpointConvertigo: String { - get { return _endpointConvertigo! } - } - - open var endpointIsSecure: Bool { - get { return _endpointIsSecure! } - } - - open var endpointHost: String { - get { return _endpointHost! } - } - - open var endpointPort: String { - get { return _endpointPort! } - } - - open var endpointProject: String { - get { return _endpointProject! } - } - - open var deviceUUID: String { - get { return C8o.deviceUUID } - } - - open var cookieStore: C8oCookieStorage { - get { return httpInterface!.cookieStore! } - } - + open func runBG (_ block: DispatchWorkItem) { + DispatchQueue.global(qos: .userInitiated).async(execute: block) + } + + open override var description: String { + get { + return "C8o[" + _endpoint! + "] " + super.description + } + } + + open var endpoint: String { + get { return _endpoint! } + } + + open var endpointConvertigo: String { + get { return _endpointConvertigo! } + } + + open var endpointIsSecure: Bool { + get { return _endpointIsSecure! } + } + + open var endpointHost: String { + get { return _endpointHost! } + } + + open var endpointPort: String { + get { return _endpointPort! } + } + + open var endpointProject: String { + get { return _endpointProject! } + } + + open var deviceUUID: String { + get { return C8o.deviceUUID } + } + + open var cookieStore: C8oCookieStorage { + get { return httpInterface!.cookieStore! } + } + /** Add a listener to monitor all changes of the 'db'. @@ -678,26 +668,25 @@ open class C8o: C8oBase { lives.removeValue(forKey: liveid) } - fileprivate static func toParameters(_ parameters: [AnyObject]?) throws -> Dictionary { - if (parameters!.count % 2 != 0) { - throw C8oException(message: C8oExceptionMessage.invalidParameterValue("parameters", details: "needs pairs of values")) - } - - var newParameters = Dictionary() - - for i in stride(from: 0, to: parameters!.count, by: 2) { - newParameters[String(describing: parameters![i])] = parameters![i + 1] - } - - return newParameters - } - - internal func handleCallException(_ c8oExceptionListener: C8oExceptionListener?, requestParameters: Dictionary, exception: C8oException) { - c8oLogger!._warn("Handle a call exception", exceptions: exception) - - if (c8oExceptionListener != nil) { - c8oExceptionListener!.onException(Pair?>(key: exception, value: requestParameters)) - } + fileprivate static func toParameters(_ parameters: [AnyObject]?) throws -> Dictionary { + if (parameters!.count % 2 != 0) { + throw C8oException(message: C8oExceptionMessage.invalidParameterValue("parameters", details: "needs pairs of values")) + } + + var newParameters = Dictionary() + + for i in stride(from: 0, to: parameters!.count, by: 2) { + newParameters[String(describing: parameters![i])] = parameters![i + 1] + } + + return newParameters + } + + internal func handleCallException(_ c8oExceptionListener: C8oExceptionListener?, requestParameters: Dictionary, exception: C8oException) { + c8oLogger!._warn("Handle a call exception", exceptions: exception) + + if (c8oExceptionListener != nil) { + c8oExceptionListener!.onException(exception, requestParameters) + } } } - diff --git a/C8oSDKiOS/C8oCallTask.swift b/C8oSDKiOS/C8oCallTask.swift index a962a06..867f066 100644 --- a/C8oSDKiOS/C8oCallTask.swift +++ b/C8oSDKiOS/C8oCallTask.swift @@ -13,226 +13,216 @@ import SwiftyJSON import AEXML internal class C8oCallTask { - fileprivate var c8o: C8o - fileprivate var parameters: Dictionary - fileprivate var c8oResponseListener: C8oResponseListener? - fileprivate var c8oExceptionListener: C8oExceptionListener - fileprivate var c8oCallUrl: String? - - internal init(c8o: C8o, parameters: Dictionary, c8oResponseListener: C8oResponseListener, c8oExceptionListener: C8oExceptionListener) { - self.c8o = c8o - self.parameters = parameters - - self.c8oResponseListener = c8oResponseListener - self.c8oExceptionListener = c8oExceptionListener - self.c8oCallUrl = nil - - c8o.c8oLogger!.logMethodCall("C8oCallTask", parameters: parameters as NSObject) - } - - internal func execute() -> Void { + fileprivate var c8o: C8o + fileprivate var parameters: Dictionary + fileprivate var c8oResponseListener: C8oResponseListener? + fileprivate var c8oExceptionListener: C8oExceptionListener + fileprivate var c8oCallUrl: String? + + internal init(c8o: C8o, parameters: Dictionary, c8oResponseListener: C8oResponseListener, c8oExceptionListener: C8oExceptionListener) { + self.c8o = c8o + self.parameters = parameters + + self.c8oResponseListener = c8oResponseListener + self.c8oExceptionListener = c8oExceptionListener + self.c8oCallUrl = nil + + c8o.c8oLogger!.logMethodCall("C8oCallTask", parameters: parameters as NSObject) + } + + internal func execute() -> Void { c8o.runBG(DispatchWorkItem{ - self.doInBackground() - }); - } + self.doInBackground() + }); + } internal func executeFromLive() { parameters.removeValue(forKey: C8o.FS_LIVE) parameters[C8o.ENGINE_PARAMETER_FROM_LIVE] = true as Any execute() } - - fileprivate func doInBackground() -> Void { - do { - let response = try handleRequest() - handleResponse(response!) - } - catch let e as C8oException { - c8oExceptionListener.onException(Pair?>(key: e, value: parameters)) - } - catch { - } - - } - - fileprivate func handleRequest() throws -> Any? { - let isFullSyncRequest: Bool = C8oFullSync.isFullSyncRequest(parameters) - - if (isFullSyncRequest) { - c8o.log._debug("Is FullSync request", exceptions: nil) + + fileprivate func doInBackground() -> Void { + do { + let response = try handleRequest() + handleResponse(response!) + } + catch let e as C8oException { + c8oExceptionListener.onException(e, parameters) + } + catch { + } + + } + + fileprivate func handleRequest() throws -> Any? { + let isFullSyncRequest: Bool = C8oFullSync.isFullSyncRequest(parameters) + + if (isFullSyncRequest) { + c8o.log._debug("Is FullSync request", exceptions: nil) let liveid = C8oUtils.getParameterStringValue(parameters, name: C8o.FS_LIVE) if (liveid != nil) { - let dbName = C8oUtils.getParameterStringValue(parameters, name: C8o.ENGINE_PARAMETER_PROJECT)?.substring(from: C8oFullSync.FULL_SYNC_PROJECT.endIndex) - try c8o.addLive(liveid!, db: dbName!, task: self) + let dbName = C8oUtils.getParameterStringValue(parameters, name: C8o.ENGINE_PARAMETER_PROJECT)![C8oFullSync.FULL_SYNC_PROJECT.endIndex...] + try c8o.addLive(liveid!, db: String(dbName), task: self) + } + // The result cannot be handled here because it can be different depending to the platform + // But it can be useful bor debug + var fullSyncResult: Any? = nil + do { + fullSyncResult = try self.c8o.c8oFullSync!.handleFullSyncRequest(self.parameters, listener: self.c8oResponseListener!) + return fullSyncResult + } + catch let e as C8oException { + throw e + } + catch let e as NSError { + print("err2") + throw C8oException(message: C8oExceptionMessage.FullSyncRequestFail(), exception: e) + } + } else { + var responseType: String = "" + if (c8oResponseListener == nil || c8oResponseListener is C8oResponseXmlListener) { + responseType = C8o.RESPONSE_TYPE_XML + } else if (c8oResponseListener is C8oResponseJsonListener) { + responseType = C8o.RESPONSE_TYPE_JSON + } else { + throw C8oError.c8oException("Wrong listener") + } + + /** Local cache */ + + var c8oCallRequestIdentifier: String? = nil + + // Allows to enable or disable the local cache on a Convertigo requestable, default value is true + let localCache: C8oLocalCache? = (C8oUtils.getParameterObjectValue(parameters, name: C8oLocalCache.PARAM, useName: false) as! C8oLocalCache?) + var localCacheEnabled: Bool = false + + // If the engine parameter for local cache is specified + if (localCache != nil) { + + // Removes local cache parameters and build the c8o call request identifier + parameters.removeValue(forKey: C8oLocalCache.PARAM) + + localCacheEnabled = localCache!.enabled + if (localCacheEnabled) { + c8oCallRequestIdentifier = C8oUtils.identifyC8oCallRequest(parameters, responseType: responseType) + + if (localCache!.priority!.isAvailable(c8o)) { + do { + let localCacheResponse: C8oLocalCacheResponse = try (c8o.c8oFullSync as! C8oFullSyncCbl).getResponseFromLocalCache(c8oCallRequestIdentifier!)! + if (!localCacheResponse.isExpired()) { + if (responseType == C8o.RESPONSE_TYPE_XML) { + return try C8oTranslator.stringToXml(localCacheResponse.getResponse()) + } else if (responseType == C8o.RESPONSE_TYPE_JSON) { + let myJson: C8oJSON = C8oJSON() + myJson.myJSON = C8oTranslator.stringToJson(localCacheResponse.getResponse()) + return myJson + } + } + } catch { + // no entry + } + } + } + } + + /** Get response */ + + parameters[C8o.ENGINE_PARAMETER_DEVICE_UUID] = c8o.deviceUUID as Any + + // Build the c8o call URL + c8oCallUrl = c8o.endpoint + "/." + responseType + + let httpResponse: Data? + var httpResponseDataError: (data: Data?, error: NSError?) + + do { + httpResponseDataError = (c8o.httpInterface?.handleRequest(c8oCallUrl!, parameters: parameters))! + if (httpResponseDataError.error != nil) { + if (localCacheEnabled) { + do { + let localCacheResponse: C8oLocalCacheResponse = try (c8o.c8oFullSync as! C8oFullSyncCbl).getResponseFromLocalCache(c8oCallRequestIdentifier!)! + if (!localCacheResponse.isExpired()) { + if (responseType == C8o.RESPONSE_TYPE_XML) { + return try C8oTranslator.stringToXml(localCacheResponse.getResponse()) + } else if (responseType == C8o.RESPONSE_TYPE_JSON) { + let myJson: C8oJSON = C8oJSON() + myJson.myJSON = C8oTranslator.stringToJson(localCacheResponse.getResponse()) + return myJson + } + } + } + catch _ as C8oUnavailableLocalCacheException { + // no entry + } + } + httpResponse = httpResponseDataError.data + return C8oException(message: C8oExceptionMessage.handleC8oCallRequest(), exception: httpResponseDataError.error!) + + } else { + httpResponse = httpResponseDataError.data + } + + } + + var response: Any? = nil + var responseString: String? = nil + if (c8oResponseListener is C8oResponseXmlListener) { + + response = C8oTranslator.dataToXml(httpResponse!)! + if (localCacheEnabled) { + responseString = (response as! AEXMLDocument).xml + } + + } else if (c8oResponseListener is C8oResponseJsonListener) { + let myc8 = C8oJSON() + myc8.myJSON = C8oTranslator.dataToJson(httpResponse! as NSData)! + response = myc8 + responseString = C8oTranslator.jsonToString(myc8.myJSON!) + } else { + return C8oException(message: "wrong listener") + } + + if (localCacheEnabled) { + var expirationDate: Double = -1 + if (localCache!.ttl > 0) { + expirationDate = Double(localCache!.ttl) + C8oUtils.getUnixEpochTime()! + } + let localCacheResponse = C8oLocalCacheResponse(response: responseString!, responseType: responseType, expirationDate: expirationDate) + try! (c8o.c8oFullSync as! C8oFullSyncCbl).saveResponseToLocalCache(c8oCallRequestIdentifier!, localCacheResponse: localCacheResponse) } - // The result cannot be handled here because it can be different depending to the platform - // But it can be useful bor debug - var fullSyncResult: Any? = nil - do { - fullSyncResult = try self.c8o.c8oFullSync!.handleFullSyncRequest(self.parameters, listener: self.c8oResponseListener!) - - return fullSyncResult - } - catch let e as C8oException { - throw e - } - catch let e as NSError { - throw C8oException(message: C8oExceptionMessage.FullSyncRequestFail(), exception: e) - } - } else { - var responseType: String = "" - if (c8oResponseListener == nil || c8oResponseListener is C8oResponseXmlListener) { - responseType = C8o.RESPONSE_TYPE_XML - } else if (c8oResponseListener is C8oResponseJsonListener) { - responseType = C8o.RESPONSE_TYPE_JSON - } else { - throw C8oError.c8oException("Wrong listener") - } - - /** Local cache */ - - var c8oCallRequestIdentifier: String? = nil - - // Allows to enable or disable the local cache on a Convertigo requestable, default value is true - let localCache: C8oLocalCache? = (C8oUtils.getParameterObjectValue(parameters, name: C8oLocalCache.PARAM, useName: false) as! C8oLocalCache?) - var localCacheEnabled: Bool = false - - // If the engine parameter for local cache is specified - if (localCache != nil) { - - // Removes local cache parameters and build the c8o call request identifier - parameters.removeValue(forKey: C8oLocalCache.PARAM) - - localCacheEnabled = localCache!.enabled - if (localCacheEnabled) { - c8oCallRequestIdentifier = C8oUtils.identifyC8oCallRequest(parameters, responseType: responseType) - - if (localCache!.priority!.isAvailable(c8o)) { - do { - let localCacheResponse: C8oLocalCacheResponse = try (c8o.c8oFullSync as! C8oFullSyncCbl).getResponseFromLocalCache(c8oCallRequestIdentifier!)! - if (!localCacheResponse.isExpired()) { - if (responseType == C8o.RESPONSE_TYPE_XML) { - return try C8oTranslator.stringToXml(localCacheResponse.getResponse()) - } else if (responseType == C8o.RESPONSE_TYPE_JSON) { - let myJson: C8oJSON = C8oJSON() - myJson.myJSON = C8oTranslator.stringToJson(localCacheResponse.getResponse()) - return myJson - } - } - } catch { - // no entry - } - } - } - } - - /** Get response */ - - parameters[C8o.ENGINE_PARAMETER_DEVICE_UUID] = c8o.deviceUUID as Any - - // Build the c8o call URL - c8oCallUrl = c8o.endpoint + "/." + responseType - - let httpResponse: Data? - var httpResponseDataError: (data: Data?, error: NSError?) - - do { - httpResponseDataError = (c8o.httpInterface?.handleRequest(c8oCallUrl!, parameters: parameters))! - if (httpResponseDataError.error != nil) { - if (localCacheEnabled) { - do { - let localCacheResponse: C8oLocalCacheResponse = try (c8o.c8oFullSync as! C8oFullSyncCbl).getResponseFromLocalCache(c8oCallRequestIdentifier!)! - if (!localCacheResponse.isExpired()) { - if (responseType == C8o.RESPONSE_TYPE_XML) { - return try C8oTranslator.stringToXml(localCacheResponse.getResponse()) - } else if (responseType == C8o.RESPONSE_TYPE_JSON) { - let myJson: C8oJSON = C8oJSON() - myJson.myJSON = C8oTranslator.stringToJson(localCacheResponse.getResponse()) - return myJson - } - } - } - catch _ as C8oUnavailableLocalCacheException { - // no entry - } - } - httpResponse = httpResponseDataError.data - return C8oException(message: C8oExceptionMessage.handleC8oCallRequest(), exception: httpResponseDataError.error!) - - } else { - httpResponse = httpResponseDataError.data - } - - } - - var response: Any? = nil - var responseString: String? = nil - if (c8oResponseListener is C8oResponseXmlListener) { - - response = C8oTranslator.dataToXml(httpResponse!)! - if (localCacheEnabled) { - responseString = (response as! AEXMLDocument).xml - } - - } else if (c8oResponseListener is C8oResponseJsonListener) { - let myc8 = C8oJSON() - myc8.myJSON = C8oTranslator.dataToJson(httpResponse! as NSData)! - response = myc8 - responseString = C8oTranslator.jsonToString(myc8.myJSON!) - } else { - return C8oException(message: "wrong listener") - } - - if (localCacheEnabled) { - // let responseString = C8oTranslator.StreamToString(responseStream) - var expirationDate: Double = -1 - if (localCache!.ttl > 0) { - expirationDate = Double(localCache!.ttl) + C8oUtils.getUnixEpochTime()! - } - let localCacheResponse = C8oLocalCacheResponse(response: responseString!, responseType: responseType, expirationDate: expirationDate) - try! (c8o.c8oFullSync as! C8oFullSyncCbl).saveResponseToLocalCache(c8oCallRequestIdentifier!, localCacheResponse: localCacheResponse) - } - - return response - - } - } - - internal func handleResponse(_ result: Any?) -> Void { - do { - - if (result == nil) { - return - } - if (c8oResponseListener == nil) { - return - } - if (result is JSON) { - - } - if (result is AEXMLDocument) { - - c8o.c8oLogger!.logC8oCallXMLResponse(result as! AEXMLDocument, url: c8oCallUrl, parameters: self.parameters) - (c8oResponseListener as! C8oResponseXmlListener).onXmlResponse(result!, parameters) - } else { - if (result is C8oJSON) { - c8o.c8oLogger!.logC8oCallJSONResponse((result as!C8oJSON).myJSON!, url: c8oCallUrl, parameters: parameters) - (c8oResponseListener as! C8oResponseJsonListener).onJsonResponse((result as!C8oJSON).myJSON!, parameters) - } else { - if result is C8oException { - c8o.handleCallException(c8oExceptionListener, requestParameters: self.parameters, exception: result as! C8oException) - } else { - /*c8o.HandleCallException(c8oExceptionListener, requestParameters: parameters, exception: C8oSDKiOS.C8oError.C8oException(C8oExceptionMessage.wrongResult(result!)))*/ - } - } - } - - } - /*catch //(Exception e) - { - //c8o.HandleCallException(c8oExceptionListener, parameters, e) - }*/ - } - + return response + + } + } + + internal func handleResponse(_ result: Any?) -> Void { + if (result == nil) { + return + } + if (c8oResponseListener == nil) { + return + } + if (result is JSON) { + + } + if (result is AEXMLDocument) { + + c8o.c8oLogger!.logC8oCallXMLResponse(result as! AEXMLDocument, url: c8oCallUrl, parameters: self.parameters) + (c8oResponseListener as! C8oResponseXmlListener).onXmlResponse(result!, parameters) + } else { + if (result is C8oJSON) { + c8o.c8oLogger!.logC8oCallJSONResponse((result as!C8oJSON).myJSON!, url: c8oCallUrl, parameters: parameters) + (c8oResponseListener as! C8oResponseJsonListener).onJsonResponse((result as!C8oJSON).myJSON!.dictionaryObject! as AnyObject, parameters) + } else { + if result is C8oException { + c8o.handleCallException(c8oExceptionListener, requestParameters: self.parameters, exception: result as! C8oException) + } else { + c8o.handleCallException(c8oExceptionListener, requestParameters: parameters, exception: C8oError.c8oException(C8oExceptionMessage.wrongResult(result!)) as! C8oException) + } + } + } + } + } diff --git a/C8oSDKiOS/C8oExceptionListener.swift b/C8oSDKiOS/C8oExceptionListener.swift index c24d469..e2f3a94 100644 --- a/C8oSDKiOS/C8oExceptionListener.swift +++ b/C8oSDKiOS/C8oExceptionListener.swift @@ -8,10 +8,10 @@ import Foundation -open class C8oExceptionListener { - open var onException: (Pair?>?) -> () - - init(onException: @escaping (_ params: Pair?>?) -> ()) { - self.onException = onException; - } +@objc open class C8oExceptionListener: NSObject { + open var onException: (_ exep:C8oException, _ params:Dictionary?) -> () + + @objc public init(onException: @escaping (_ exep:C8oException, _ params:Dictionary?) -> ()) { + self.onException = onException; + } } diff --git a/C8oSDKiOS/C8oFileTransfer.swift b/C8oSDKiOS/C8oFileTransfer.swift index fc74994..d3c68b0 100644 --- a/C8oSDKiOS/C8oFileTransfer.swift +++ b/C8oSDKiOS/C8oFileTransfer.swift @@ -168,7 +168,7 @@ open class C8oFileTransfer: C8oFileTransferBase { fileprivate func checkTaskDb() throws { if (!tasksDbCreated) { - try c8oTask.callJson("fs://.create").sync() + _ = try c8oTask.callJson("fs://.create").sync() tasksDbCreated = true } } @@ -182,7 +182,7 @@ open class C8oFileTransfer: C8oFileTransferBase { */ open func downloadFile(_ uuid: String, filePath: String) throws { try checkTaskDb() - c8oTask.callJson("fs://.post", + _ = c8oTask.callJson("fs://.post", parameters: "_id" as Any, uuid as Any, "filePath" as Any, filePath, @@ -242,11 +242,11 @@ open class C8oFileTransfer: C8oFileTransferBase { var locker: Bool let expireTransfer = Date(timeIntervalSinceNow: maxDurationForTransferAttempt) locker = false - try c8o!.callJson("fs://" + fsConnector! + ".create").sync()! + _ = try c8o!.callJson("fs://" + fsConnector! + ".create").sync()! needRemoveSession = true let condition: NSCondition = NSCondition() - c8o!.callJson("fs://" + fsConnector! + ".replicate_pull").then({ (response, parameters) -> (C8oPromise?) in + _ = c8o!.callJson("fs://" + fsConnector! + ".replicate_pull").then({ (response, parameters) -> (C8oPromise?) in condition.lock() locker = true condition.signal() @@ -277,7 +277,7 @@ open class C8oFileTransfer: C8oFileTransferBase { var all = try c8o?.callJson("fs://" + fsConnector! + ".all", parametersDict: allOptions).sync() let rows = all!["rows"] - if (rows != nil) { + if (rows != JSON.null) { let current: Int = rows.count if (current != transferStatus.current) { transferStatus.current = current @@ -291,7 +291,7 @@ open class C8oFileTransfer: C8oFileTransferBase { } } - try c8o?.callJson("fs://" + fsConnector! + ".replicate_pull", parameters: "cancel", true).sync() + _ = try c8o?.callJson("fs://" + fsConnector! + ".replicate_pull", parameters: "cancel", true).sync() if (!canceledTasks.contains(uuid)) { if (transferStatus.current < transferStatus.total) { @@ -383,7 +383,7 @@ open class C8oFileTransfer: C8oFileTransferBase { } if (needRemoveSession && c8o != nil) { - c8o!.callJson(".RemoveSession") + _ = c8o!.callJson(".RemoveSession") } tasks?.removeValue(forKey: uuid) @@ -450,7 +450,7 @@ open class C8oFileTransfer: C8oFileTransferBase { let uuid: String = NSUUID().uuidString.lowercased() - c8oTask.callJson("fs://.post", parameters: + _ = c8oTask.callJson("fs://.post", parameters: "_id", uuid, "filePath", fileName, "splitted", false, @@ -477,7 +477,7 @@ open class C8oFileTransfer: C8oFileTransferBase { __maxRunning = __maxRunning - 1 __maxRunning__.unlock() - var res: JSON = nil + var res: JSON = JSON.null var locker: Bool = false let fileName: String = transferStatus.filepath @@ -485,7 +485,7 @@ open class C8oFileTransfer: C8oFileTransferBase { let c8o: C8o = try C8o(endpoint: c8oTask.endpoint, c8oSettings: C8oSettings(c8oSettings: c8oTask).setFullSyncLocalSuffix("_" + uuid).setDefaultDatabaseName("c8ofiletransfer")) // Creates the local db - try c8o.callJson("fs://.create").sync() + _ = try c8o.callJson("fs://.create").sync() // If the file is not already splitted and stored in the local database if (!task["splitted"].boolValue && !canceledTasks.contains(uuid)) { @@ -498,9 +498,9 @@ open class C8oFileTransfer: C8oFileTransferBase { } else { // Removes the local database - try c8o.callJson("fs://.reset").sync() + _ = try c8o.callJson("fs://.reset").sync() // Removes the task doc - try c8oTask.callJson("fs://.delete", parameters: "docid", uuid).sync() + _ = try c8oTask.callJson("fs://.delete", parameters: "docid", uuid).sync() throw C8oException(message: "The file '" + task["filePath"].stringValue + "' can't be upload because it was stopped before the file content was handled") } @@ -521,7 +521,7 @@ open class C8oFileTransfer: C8oFileTransferBase { countTot += 1 read = fileStream!.read(&buffer, maxLength: buffer.count) let docid: String = uuid + "_" + countTot.description - try c8o.callJson("fs://.post", parameters: + _ = try c8o.callJson("fs://.post", parameters: "_id", docid, "fileName", fileName, "type", "chunk", @@ -529,7 +529,7 @@ open class C8oFileTransfer: C8oFileTransferBase { ).sync() let data = Data(bytes: &buffer, count: read) - try c8o.callJson("fs://.put_attachment", parameters: + _ = try c8o.callJson("fs://.put_attachment", parameters: "docid", docid, "name", "chunk", "content_type", "application/octet-stream", @@ -571,7 +571,7 @@ open class C8oFileTransfer: C8oFileTransferBase { locker = false - c8o.callJson("fs://.replicate_push") + _ = c8o.callJson("fs://.replicate_push") .then({ (response, parameters) -> (C8oPromise?) in self.condition.lock() locker = true @@ -594,7 +594,7 @@ open class C8oFileTransfer: C8oFileTransferBase { ).sync()! let rows = json["document"]["couchdb_output"]["rows"] - if (rows != nil) { + if (rows != JSON.null) { let current: Int = rows[0]["value"].intValue if (current != transferStatus.current) { transferStatus.current = current @@ -603,7 +603,7 @@ open class C8oFileTransfer: C8oFileTransferBase { } } - try c8o.callJson("fs://.replicate_push", parameters: "cancel", true).sync() + _ = try c8o.callJson("fs://.replicate_push", parameters: "cancel", true).sync() if (!canceledTasks.contains(uuid)) { // Updates the state document in the task database @@ -628,10 +628,10 @@ open class C8oFileTransfer: C8oFileTransferBase { // DispatchQueue.global(qos: .default).async {[task] in // copies val var task = task - c8o.callJson("fs://.reset") + _ = c8o.callJson("fs://.reset") .then({ (response, parameters) -> (C8oPromise?) in task["localDeleted"] = true - self.c8oTask.callJson("fs://.post", parameters: + _ = self.c8oTask.callJson("fs://.post", parameters: C8o.FS_POLICY, C8o.FS_POLICY_MERGE, "_id", task["_id"].stringValue, "localDeleted", task["localDeleted"].boolValue @@ -667,7 +667,7 @@ open class C8oFileTransfer: C8oFileTransferBase { ).sync()! let document: JSON = res["document"] - if (document["serverFilePath"] == nil) { + if (document["serverFilePath"] == JSON.null) { throw C8oException(message: "Can't find the serverFilePath in JSON response : " + res.description) } let serverFilePath: String = document["serverFilePath"].stringValue diff --git a/C8oSDKiOS/C8oFileTransferStatus.swift b/C8oSDKiOS/C8oFileTransferStatus.swift index dafc4f4..276efcf 100644 --- a/C8oSDKiOS/C8oFileTransferStatus.swift +++ b/C8oSDKiOS/C8oFileTransferStatus.swift @@ -121,9 +121,9 @@ open class C8oFileTransferStatus { } func tot() { let range2: Range = uuid.range(of: "-", options: .backwards)! - var start_index: Int = uuid.characters.distance(from: uuid.startIndex, to: range2.lowerBound) + var start_index: Int = uuid.distance(from: uuid.startIndex, to: range2.lowerBound) start_index += 1 - self.total = Int(uuid.substring(with: Range(uuid.characters.index(uuid.startIndex, offsetBy: start_index).. FullSyncDefaultResponse? { (c8o!.c8oFullSync as! C8oFullSyncCbl).performOnCblThread { - try self.handleDestroyDatabaseRequest(databaseName) + _ = try self.handleDestroyDatabaseRequest(databaseName) } return try handleCreateDatabaseRequest(databaseName) } @@ -732,7 +732,7 @@ class C8oFullSyncCbl: C8oFullSync { var propertiesMutable = properties let currentRevision: CBLSavedRevision? = document.currentRevision if (currentRevision != nil) { - propertiesMutable[C8oFullSync.FULL_SYNC__REV] = currentRevision?.revisionID as! NSObject + propertiesMutable[C8oFullSync.FULL_SYNC__REV] = (currentRevision?.revisionID! as NSObject?) } do { @@ -814,7 +814,7 @@ class C8oFullSyncCbl: C8oFullSync { } let currentRevision: CBLSavedRevision? = localCacheDocument!.currentRevision if (currentRevision != nil) { - properties[C8oFullSyncCbl.FULL_SYNC__REV] = currentRevision?.revisionID as! NSObject + properties[C8oFullSyncCbl.FULL_SYNC__REV] = currentRevision?.revisionID! as NSObject? } // do { diff --git a/C8oSDKiOS/C8oFullSyncTranslator.swift b/C8oSDKiOS/C8oFullSyncTranslator.swift index da365db..e43c24e 100644 --- a/C8oSDKiOS/C8oFullSyncTranslator.swift +++ b/C8oSDKiOS/C8oFullSyncTranslator.swift @@ -124,8 +124,8 @@ internal class C8oFullSyncTranslator { if (dict.count > 0) { - let desiredLength = str.characters.index(str.startIndex, offsetBy: ((str.characters.count) - 2)) - str = str.substring(to: desiredLength) + let desiredLength = str.index(str.startIndex, offsetBy: ((str.count) - 2)) + str = String(str[.. 0) { - let desiredLength = str.characters.index(str.startIndex, offsetBy: ((str.characters.count) - 2)) - str = str.substring(to: desiredLength) + let desiredLength = str.index(str.startIndex, offsetBy: ((str.count) - 2)) + str = String(str[.. 0) { for child in mirror.children { return toAnyObject(obj: child.value) } } return NSNull() + */ } } diff --git a/C8oSDKiOS/C8oHttpInterface.swift b/C8oSDKiOS/C8oHttpInterface.swift index b03c888..ea6abd3 100644 --- a/C8oSDKiOS/C8oHttpInterface.swift +++ b/C8oSDKiOS/C8oHttpInterface.swift @@ -34,7 +34,7 @@ internal class C8oHttpInterface { if (c8o.cookies != nil) { for a in c8o.cookies! { - addCookie(a.0, value: a.1) + _ = addCookie(a.0, value: a.1) } } } @@ -56,29 +56,29 @@ internal class C8oHttpInterface { firstCallMutex.lock() if (firstCall) { //let request = alamofire.upload(.POST, url, headers: headers, data: data!) - let request = alamofire.upload(data!, to: url, method: .post, headers: headers) + _ = alamofire.upload(data!, to: url, method: .post, headers: headers) .response(queue:queue, completionHandler:{ response in - myResponse = (response.data, response.error as! NSError?) + myResponse = (response.data, response.error as NSError?) semaphore.signal() }) - semaphore.wait(timeout: DispatchTime.distantFuture) + _ = semaphore.wait(timeout: DispatchTime.distantFuture) firstCall = false firstCallMutex.unlock() return myResponse } firstCallMutex.unlock() - let request = alamofire.upload(data!, to: url, method: .post, headers: headers) + _ = alamofire.upload(data!, to: url, method: .post, headers: headers) .response(queue:queue, completionHandler:{ response in myResponse = (response.data, response.error as NSError?) semaphore.signal() }) - semaphore.wait(timeout: DispatchTime.distantFuture) + _ = semaphore.wait(timeout: DispatchTime.distantFuture) return myResponse } @@ -124,7 +124,7 @@ internal class C8oHttpInterface { } } - postData = String(postData.characters.dropLast(1)) + postData = String(postData.dropLast(1)) return postData.data(using: String.Encoding.utf8) diff --git a/C8oSDKiOS/C8oLogger.swift b/C8oSDKiOS/C8oLogger.swift index 2f6af5f..5fb0b6f 100644 --- a/C8oSDKiOS/C8oLogger.swift +++ b/C8oSDKiOS/C8oLogger.swift @@ -12,310 +12,306 @@ import SwiftyJSON import AEXML open class C8oLogger: NSObject { - fileprivate let RE_FORMAT_TIME: NSRegularExpression = try! NSRegularExpression(pattern: "(\\d*?)(?:,|.)(\\d{3}).*", options: []) - // *** Constants ***// - - fileprivate static var LOG_TAG: String = "c8o" - fileprivate static var LOG_INTERNAL_PREFIX: String = "[c8o] " - - static let REMOTE_LOG_LIMIT: Int = 100 - - fileprivate static var JSON_KEY_REMOTE_LOG_LEVEL: String = "remoteLogLevel" - fileprivate static var JSON_KEY_TIME: String = "time" - fileprivate static var JSON_KEY_LEVEL: String = "level" - fileprivate static var JSON_KEY_MESSAGE: String = "msg" - fileprivate static var JSON_KEY_LOGS: String = "logs" - fileprivate static var JSON_KEY_ENV: String = "env" - - /** Attributes */ - - fileprivate var remoteLogUrl: String? - fileprivate var remoteLogs: Queue? - fileprivate var alreadyRemoteLogging: [Bool]? - fileprivate var remoteLogLevel: C8oLogLevel? - fileprivate var uidRemoteLogs: String? - fileprivate var startTimeRemoteLog: Date? - - fileprivate var c8o: C8o - - fileprivate var env: String - - internal init(c8o: C8o) { - self.c8o = c8o - - remoteLogUrl = c8o.endpointConvertigo + "/admin/services/logs.Add" - remoteLogs = Queue() - alreadyRemoteLogging = [Bool]() - alreadyRemoteLogging?.append(false) - - remoteLogLevel = C8oLogLevel.trace - - let currentTime = Date() - startTimeRemoteLog = currentTime - uidRemoteLogs = C8oTranslator.doubleToHexString(C8oUtils.getUnixEpochTime()!) - let envJSON: JSON = ["uid": uidRemoteLogs!, "uuid": c8o.deviceUUID, "project": c8o.endpointProject] - env = String(describing: envJSON) - } - - fileprivate func isLoggableRemote(_ logLevel: C8oLogLevel?) -> Bool { - return c8o.logRemote && logLevel != nil && C8oLogLevel.trace.rawValue <= remoteLogLevel!.rawValue && remoteLogLevel!.rawValue <= logLevel!.rawValue - } - - fileprivate func isLoggableConsole(_ logLevel: C8oLogLevel?) -> Bool { - return logLevel != nil && C8oLogLevel.trace.rawValue <= c8o.logLevelLocal.rawValue && c8o.logLevelLocal.rawValue <= logLevel!.rawValue - } - - /** Basics log */ - open func canLog(_ logLevel: C8oLogLevel) -> Bool { - return isLoggableConsole(logLevel) || isLoggableRemote(logLevel) - } - - open var isFatal: Bool { - get { return canLog(C8oLogLevel.fatal) } - } - - open var isError: Bool { - get { return canLog(C8oLogLevel.error) } - } - - open var isWarn: Bool { - get { return canLog(C8oLogLevel.warn) } - } - - open var isInfo: Bool { - get { return canLog(C8oLogLevel.info) } - } - - open var isDebug: Bool { - get { return canLog(C8oLogLevel.debug) } - } - - open var isTrace: Bool { - get { return canLog(C8oLogLevel.trace) } - } - - internal func log(_ logLevel: C8oLogLevel, message: String, exception: C8oException?! = nil) -> Void { - var message = message - let isLogConsole: Bool = isLoggableConsole(logLevel) - let isLogRemote: Bool = isLoggableRemote(logLevel) - - if (isLogConsole || isLogRemote) { - if (exception != nil) { - message += "\n" + String(describing: exception) - } - - let time: String = String(Date().timeIntervalSince(startTimeRemoteLog!)) - // let stringLevel : String = remoteLogLevel[logLevel] - - if (isLogRemote) { - remoteLogs!.enqueue(JSON( - [C8oLogger.JSON_KEY_TIME: time, - C8oLogger.JSON_KEY_LEVEL: logLevel.name(), - C8oLogger.JSON_KEY_MESSAGE: message - ])) - logRemote() - } - - if (isLogConsole) { - debugPrint("(" + time + ") [" + logLevel.name() + "] " + message) - - } - } - } - - open func fatal(_ message: String, exceptions: C8oException? = nil) -> Void { - log(C8oLogLevel.fatal, message: message, exception: exceptions) - } - - open func error(_ message: String, exceptions: C8oException? = nil) -> Void { - log(C8oLogLevel.error, message: message, exception: exceptions) - } - - open func warn(_ message: String, exceptions: C8oException? = nil) -> Void { - log(C8oLogLevel.warn, message: message, exception: exceptions) - } - - open func info(_ message: String, exceptions: C8oException? = nil) -> Void { - log(C8oLogLevel.info, message: message, exception: exceptions) - } - - open func debug(_ message: String, exceptions: C8oException? = nil) -> Void { - log(C8oLogLevel.debug, message: message, exception: exceptions) - } - - open func trace(_ message: String, exceptions: C8oException? = nil) -> Void { - log(C8oLogLevel.trace, message: message, exception: exceptions) - } - - internal func _log(_ logLevel: C8oLogLevel, messages: String, exceptions: C8oException?) -> Void { - if (c8o.logC8o) { - log(logLevel, message: C8oLogger.LOG_INTERNAL_PREFIX + messages, exception: exceptions) - } - } - - internal func _fatal(_ message: String, exceptions: C8oException? = nil) -> Void { - _log(C8oLogLevel.fatal, messages: message, exceptions: exceptions) - } - - internal func _error(_ message: String, exceptions: C8oException? = nil) -> Void { - _log(C8oLogLevel.error, messages: message, exceptions: exceptions) - } - - internal func _warn(_ message: String, exceptions: C8oException? = nil) -> Void { - _log(C8oLogLevel.warn, messages: message, exceptions: exceptions) - } - - internal func _info(_ message: String, exceptions: C8oException? = nil) -> Void { - _log(C8oLogLevel.info, messages: message, exceptions: exceptions) - } - - internal func _debug(_ message: String, exceptions: C8oException? = nil) -> Void { - _log(C8oLogLevel.debug, messages: message, exceptions: exceptions) - } - - internal func _trace(_ message: String, exceptions: C8oException? = nil) -> Void { - _log(C8oLogLevel.trace, messages: message, exceptions: exceptions) - } - - internal func logRemote() -> Void { - var canLog: Bool = false - let condition: NSCondition = NSCondition() - - condition.lock() - - // If there is no another thread already logging AND there is at least one log - canLog = !alreadyRemoteLogging![0] && remoteLogs!.Count() > 0 - if (canLog) { - alreadyRemoteLogging![0] = true - } - - condition.unlock() - - if (canLog) { - let priority = DispatchQoS.QoSClass.default + fileprivate let RE_FORMAT_TIME: NSRegularExpression = try! NSRegularExpression(pattern: "(\\d*?)(?:,|.)(\\d{3}).*", options: []) + // *** Constants ***// + + fileprivate static var LOG_TAG: String = "c8o" + fileprivate static var LOG_INTERNAL_PREFIX: String = "[c8o] " + + static let REMOTE_LOG_LIMIT: Int = 100 + + fileprivate static var JSON_KEY_REMOTE_LOG_LEVEL: String = "remoteLogLevel" + fileprivate static var JSON_KEY_TIME: String = "time" + fileprivate static var JSON_KEY_LEVEL: String = "level" + fileprivate static var JSON_KEY_MESSAGE: String = "msg" + fileprivate static var JSON_KEY_LOGS: String = "logs" + fileprivate static var JSON_KEY_ENV: String = "env" + + /** Attributes */ + + fileprivate var remoteLogUrl: String? + fileprivate var remoteLogs: Queue? + fileprivate var alreadyRemoteLogging: [Bool]? + fileprivate var remoteLogLevel: C8oLogLevel? + fileprivate var uidRemoteLogs: String? + fileprivate var startTimeRemoteLog: Date? + + fileprivate var c8o: C8o + + fileprivate var env: String + + internal init(c8o: C8o) { + self.c8o = c8o + + remoteLogUrl = c8o.endpointConvertigo + "/admin/services/logs.Add" + remoteLogs = Queue() + alreadyRemoteLogging = [Bool]() + alreadyRemoteLogging?.append(false) + + remoteLogLevel = C8oLogLevel.trace + + let currentTime = Date() + startTimeRemoteLog = currentTime + uidRemoteLogs = C8oTranslator.doubleToHexString(C8oUtils.getUnixEpochTime()!) + let envJSON: JSON = ["uid": uidRemoteLogs!, "uuid": c8o.deviceUUID, "project": c8o.endpointProject] + env = String(describing: envJSON) + } + + fileprivate func isLoggableRemote(_ logLevel: C8oLogLevel?) -> Bool { + return c8o.logRemote && logLevel != nil && C8oLogLevel.trace.rawValue <= remoteLogLevel!.rawValue && remoteLogLevel!.rawValue <= logLevel!.rawValue + } + + fileprivate func isLoggableConsole(_ logLevel: C8oLogLevel?) -> Bool { + return logLevel != nil && C8oLogLevel.trace.rawValue <= c8o.logLevelLocal.rawValue && c8o.logLevelLocal.rawValue <= logLevel!.rawValue + } + + /** Basics log */ + open func canLog(_ logLevel: C8oLogLevel) -> Bool { + return isLoggableConsole(logLevel) || isLoggableRemote(logLevel) + } + + open var isFatal: Bool { + get { return canLog(C8oLogLevel.fatal) } + } + + open var isError: Bool { + get { return canLog(C8oLogLevel.error) } + } + + open var isWarn: Bool { + get { return canLog(C8oLogLevel.warn) } + } + + open var isInfo: Bool { + get { return canLog(C8oLogLevel.info) } + } + + open var isDebug: Bool { + get { return canLog(C8oLogLevel.debug) } + } + + open var isTrace: Bool { + get { return canLog(C8oLogLevel.trace) } + } + + internal func log(_ logLevel: C8oLogLevel, message: String, exception: C8oException?! = nil) -> Void { + var message = message + let isLogConsole: Bool = isLoggableConsole(logLevel) + let isLogRemote: Bool = isLoggableRemote(logLevel) + + if (isLogConsole || isLogRemote) { + if (exception != nil) { + message += "\n" + String(describing: exception) + } + + let time: String = String(Date().timeIntervalSince(startTimeRemoteLog!)) + // let stringLevel : String = remoteLogLevel[logLevel] + + if (isLogRemote) { + remoteLogs!.enqueue(JSON( + [C8oLogger.JSON_KEY_TIME: time, + C8oLogger.JSON_KEY_LEVEL: logLevel.name(), + C8oLogger.JSON_KEY_MESSAGE: message + ])) + logRemote() + } + + if (isLogConsole) { + debugPrint("(" + time + ") [" + logLevel.name() + "] " + message) + + } + } + } + + open func fatal(_ message: String, exceptions: C8oException? = nil) -> Void { + log(C8oLogLevel.fatal, message: message, exception: exceptions) + } + + open func error(_ message: String, exceptions: C8oException? = nil) -> Void { + log(C8oLogLevel.error, message: message, exception: exceptions) + } + + open func warn(_ message: String, exceptions: C8oException? = nil) -> Void { + log(C8oLogLevel.warn, message: message, exception: exceptions) + } + + open func info(_ message: String, exceptions: C8oException? = nil) -> Void { + log(C8oLogLevel.info, message: message, exception: exceptions) + } + + open func debug(_ message: String, exceptions: C8oException? = nil) -> Void { + log(C8oLogLevel.debug, message: message, exception: exceptions) + } + + open func trace(_ message: String, exceptions: C8oException? = nil) -> Void { + log(C8oLogLevel.trace, message: message, exception: exceptions) + } + + internal func _log(_ logLevel: C8oLogLevel, messages: String, exceptions: C8oException?) -> Void { + if (c8o.logC8o) { + log(logLevel, message: C8oLogger.LOG_INTERNAL_PREFIX + messages, exception: exceptions) + } + } + + internal func _fatal(_ message: String, exceptions: C8oException? = nil) -> Void { + _log(C8oLogLevel.fatal, messages: message, exceptions: exceptions) + } + + internal func _error(_ message: String, exceptions: C8oException? = nil) -> Void { + _log(C8oLogLevel.error, messages: message, exceptions: exceptions) + } + + internal func _warn(_ message: String, exceptions: C8oException? = nil) -> Void { + _log(C8oLogLevel.warn, messages: message, exceptions: exceptions) + } + + internal func _info(_ message: String, exceptions: C8oException? = nil) -> Void { + _log(C8oLogLevel.info, messages: message, exceptions: exceptions) + } + + internal func _debug(_ message: String, exceptions: C8oException? = nil) -> Void { + _log(C8oLogLevel.debug, messages: message, exceptions: exceptions) + } + + internal func _trace(_ message: String, exceptions: C8oException? = nil) -> Void { + _log(C8oLogLevel.trace, messages: message, exceptions: exceptions) + } + + internal func logRemote() -> Void { + var canLog: Bool = false + let condition: NSCondition = NSCondition() + + condition.lock() + + // If there is no another thread already logging AND there is at least one log + canLog = !alreadyRemoteLogging![0] && remoteLogs!.Count() > 0 + if (canLog) { + alreadyRemoteLogging![0] = true + } + + condition.unlock() + + if (canLog) { + let priority = DispatchQoS.QoSClass.default DispatchQueue.global(qos: priority).async { - - // Take logs in the queue and add it to a json array - var count: Int = 0 - let listSize: Int = self.remoteLogs!.Count() - var logsArray = Array() - - while (count < listSize && count < C8oLogger.REMOTE_LOG_LIMIT) { + + // Take logs in the queue and add it to a json array + var count: Int = 0 + let listSize: Int = self.remoteLogs!.Count() + var logsArray = Array() + + while (count < listSize && count < C8oLogger.REMOTE_LOG_LIMIT) { let log = self.remoteLogs!.dequeue() if (log != nil) { logsArray.append(log!) } - count = count + 1 - } - - // Initializes request paramters - var uidS: String = "{\"uid\":\"" - uidS += self.uidRemoteLogs! - uidS += "\"}" - var parameters = Dictionary() - parameters = - [C8oLogger.JSON_KEY_LOGS: String(describing: logsArray) as NSObject, - C8oLogger.JSON_KEY_ENV: self.env as NSObject, - C8o.ENGINE_PARAMETER_DEVICE_UUID: self.c8o.deviceUUID as NSObject] - - var jsonResponse: JSON - do { - let webResponse: (data: Data?, error: NSError?) = self.c8o.httpInterface!.handleRequest(self.remoteLogUrl!, parameters: parameters) - if (webResponse.error != nil) { - self.c8o.logRemote = false - if (self.c8o.logOnFail != nil) { - self.c8o.logOnFail!(C8oException(message: C8oExceptionMessage.RemoteLogFail(), exception: webResponse.error!), nil) - } - return - } else { - jsonResponse = C8oTranslator.dataToJson(webResponse.data! as NSData)! - } - - } - /*catch _ as NSError - { - - }*/ - - var logLevelResponse = jsonResponse[C8oLogger.JSON_KEY_REMOTE_LOG_LEVEL] - - if (logLevelResponse != nil) { - let logLevelResponseStr: String = logLevelResponse.stringValue - let c8oLogLevel = C8oLogLevel.getC8oLogLevel(logLevelResponseStr) - - if (c8oLogLevel != nil) { - self.remoteLogLevel = c8oLogLevel! - } - - condition.lock() - self.alreadyRemoteLogging![0] = false - condition.unlock() - self.logRemote() - - } - } - - /*dispatch_async(dispatch_get_main_queue()){ - - }*/ - } - } - /** Others log */ - - internal func logMethodCall(_ methodName: String, parameters: NSObject...) -> Void { - if (c8o.logC8o && isDebug) { - var methodCallLogMessage: String = "Method call : " + methodName - if (isTrace && parameters.count > 0) { - methodCallLogMessage += "\n" + String(describing: parameters) - _trace(methodCallLogMessage, exceptions: nil) - - } else { - _debug(methodCallLogMessage, exceptions: nil) - } - } - } - - internal func logC8oCall(_ url: String, parameters: Dictionary) -> Void { - if (c8o.logC8o && isDebug) { - var c8oCallLogMessage: String = "C8o call : " + url - - if (parameters.count > 0) { - c8oCallLogMessage += "\n" + String(describing: parameters) - } - - _debug(c8oCallLogMessage, exceptions: nil) - } - } - - internal func logC8oCallXMLResponse(_ response: AEXMLDocument, url: String?, parameters: Dictionary) -> Void { - logC8oCallResponse(C8oTranslator.xmlToString(response)!, responseType: "XML", url: url, parameters: parameters) - } - - internal func logC8oCallJSONResponse(_ response: JSON, url: String?, parameters: Dictionary) -> Void { - logC8oCallResponse(C8oTranslator.jsonToString(response)!, responseType: "JSON", url: url, parameters: parameters) - } - - internal func logC8oCallResponse(_ responseStr: String, responseType: String, url: String?, parameters: Dictionary) -> Void { - if (c8o.logC8o && isTrace) { - var c8oCallResponseLogMessage: String - if (url == nil) { - c8oCallResponseLogMessage = "C8o call " + responseType + " response : " - } else { - c8oCallResponseLogMessage = "C8o call " + responseType + " response : " + url! - } - - if (parameters.count > 0) { - c8oCallResponseLogMessage += "\n" + parameters.description - } - - c8oCallResponseLogMessage += "\n" + responseStr - - _trace(c8oCallResponseLogMessage, exceptions: nil) - } - } + count = count + 1 + } + + // Initializes request paramters + var uidS: String = "{\"uid\":\"" + uidS += self.uidRemoteLogs! + uidS += "\"}" + var parameters = Dictionary() + parameters = + [C8oLogger.JSON_KEY_LOGS: String(describing: logsArray) as NSObject, + C8oLogger.JSON_KEY_ENV: self.env as NSObject, + C8o.ENGINE_PARAMETER_DEVICE_UUID: self.c8o.deviceUUID as NSObject] + + var jsonResponse: JSON + do { + let webResponse: (data: Data?, error: NSError?) = self.c8o.httpInterface!.handleRequest(self.remoteLogUrl!, parameters: parameters) + if (webResponse.error != nil) { + self.c8o.logRemote = false + if (self.c8o.logOnFail != nil) { + self.c8o.logOnFail!(C8oException(message: C8oExceptionMessage.RemoteLogFail(), exception: webResponse.error!), nil) + } + return + } else { + jsonResponse = C8oTranslator.dataToJson(webResponse.data! as NSData)! + } + + } + + var logLevelResponse = jsonResponse[C8oLogger.JSON_KEY_REMOTE_LOG_LEVEL] + + if (logLevelResponse != JSON.null) { + let logLevelResponseStr: String = logLevelResponse.stringValue + let c8oLogLevel = C8oLogLevel.getC8oLogLevel(logLevelResponseStr) + + if (c8oLogLevel != nil) { + self.remoteLogLevel = c8oLogLevel! + } + + condition.lock() + self.alreadyRemoteLogging![0] = false + condition.unlock() + self.logRemote() + + } + } + + /*dispatch_async(dispatch_get_main_queue()){ + + }*/ + } + } + /** Others log */ + + internal func logMethodCall(_ methodName: String, parameters: NSObject...) -> Void { + if (c8o.logC8o && isDebug) { + var methodCallLogMessage: String = "Method call : " + methodName + if (isTrace && parameters.count > 0) { + methodCallLogMessage += "\n" + String(describing: parameters) + _trace(methodCallLogMessage, exceptions: nil) + + } else { + _debug(methodCallLogMessage, exceptions: nil) + } + } + } + + internal func logC8oCall(_ url: String, parameters: Dictionary) -> Void { + if (c8o.logC8o && isDebug) { + var c8oCallLogMessage: String = "C8o call : " + url + + if (parameters.count > 0) { + c8oCallLogMessage += "\n" + String(describing: parameters) + } + + _debug(c8oCallLogMessage, exceptions: nil) + } + } + + internal func logC8oCallXMLResponse(_ response: AEXMLDocument, url: String?, parameters: Dictionary) -> Void { + logC8oCallResponse(C8oTranslator.xmlToString(response)!, responseType: "XML", url: url, parameters: parameters) + } + + internal func logC8oCallJSONResponse(_ response: JSON, url: String?, parameters: Dictionary) -> Void { + logC8oCallResponse(C8oTranslator.jsonToString(response)!, responseType: "JSON", url: url, parameters: parameters) + } + + internal func logC8oCallResponse(_ responseStr: String, responseType: String, url: String?, parameters: Dictionary) -> Void { + if (c8o.logC8o && isTrace) { + var c8oCallResponseLogMessage: String + if (url == nil) { + c8oCallResponseLogMessage = "C8o call " + responseType + " response : " + } else { + c8oCallResponseLogMessage = "C8o call " + responseType + " response : " + url! + } + + if (parameters.count > 0) { + c8oCallResponseLogMessage += "\n" + parameters.description + } + + c8oCallResponseLogMessage += "\n" + responseStr + + _trace(c8oCallResponseLogMessage, exceptions: nil) + } + } } -public enum C8oLogLevel : UInt { +@objc public enum C8oLogLevel : UInt { case null, none, trace, debug, info, warn, error, fatal internal static func getC8oLogLevel(_ name: String) -> C8oLogLevel? { @@ -340,8 +336,29 @@ public enum C8oLogLevel : UInt { return nil } } - + internal func getC8oLogLevelDescription(_ number: Int) -> String { + switch number { + case 0: + return "NULL" + case 1: + return "NONE" + case 2: + return "TRACE" + case 3: + return "DEBUG" + case 4: + return "INFO" + case 5: + return "WARN" + case 6: + return "ERROR" + case 7: + return "FATAL" + default: + return "DEBUG" + } + } public func name()->String{ - return String(describing: self) + return self.getC8oLogLevelDescription(self.hashValue) } } diff --git a/C8oSDKiOS/C8oProgress.swift b/C8oSDKiOS/C8oProgress.swift index d3dd28f..a040061 100644 --- a/C8oSDKiOS/C8oProgress.swift +++ b/C8oSDKiOS/C8oProgress.swift @@ -8,166 +8,172 @@ import Foundation -open class C8oProgress: NSObject { - fileprivate var _changed: Bool? = false - fileprivate var _continuous: Bool? = false - fileprivate var _finished: Bool? = false - fileprivate var _pull: Bool? = true - fileprivate var _current: Int? = -1 - fileprivate var _total: Int? = -1 - fileprivate var _status: String? = "" - fileprivate var _taskInfo: String? = "" - fileprivate var _raw: NSObject? - - internal override init() { - super.init() - self._raw = nil - - } - - internal init(progress: C8oProgress) { - super.init() - _continuous = progress._continuous - _finished = progress._finished - _pull = progress._pull - _current = progress._current - _total = progress._total - _status = progress._status - _taskInfo = progress._taskInfo - _raw = progress._raw - } - - internal var changed: Bool { - get { - return _changed! - } - - set(value) { - _changed = value - } - } - - open override var description: String { - var ch: String = direction + ": " + String(current) + "/" + String(total) + " (" - ch += (finished ? (continuous ? "live" : "done") : "running") + ")" - return ch - } - - open var continuous: Bool { - get { - return _continuous! - } - - set(value) { - if (value != _continuous) { - _changed = true - _continuous = value - } - } - } - - open var finished: Bool { - get { - return _finished! - } - - set(value) { - if (value != _finished) { - _changed = true - _finished = value - } - } - } - - open var pull: Bool { - get { - return _pull! - } - - set(value) { - if (value != _pull) { - _changed = true - _pull = value - } - } - } - - open var push: Bool { - get { - return !_pull! - } - } - - open var current: Int { - get { - return _current! - } - - set(value) { - if (value != _current) { - _changed = true - _current = value - } - } - } - - open var total: Int { - get { - return _total! - } - - set(value) { - if (value != _total) { - _changed = true - _total = value - } - } - } - - open var direction: String { - get { - return _pull! ? - C8oFullSyncTranslator.FULL_SYNC_RESPONSE_VALUE_DIRECTION_PULL : - C8oFullSyncTranslator.FULL_SYNC_RESPONSE_VALUE_DIRECTION_PUSH - } - } - - open var status: String { - get { - return _status! - } - - set (value) { - if (value != _status) { - _changed = true - _status = value - } - } - } - - open var taskInfo: String { - get { - return _taskInfo! - } - - set(value) { - if (value != _taskInfo) { - _changed = true - _taskInfo = value - } - } - } - - open var raw: NSObject { - get { - return _raw! - } - - set(value) { - if (value != _raw) { - _changed = true - _raw = value - } - } - } +@objc open class C8oProgress: NSObject { + fileprivate var _changed: Bool? = false + fileprivate var _continuous: Bool? = false + fileprivate var _finished: Bool? = false + fileprivate var _pull: Bool? = true + fileprivate var _current: Int? = -1 + fileprivate var _total: Int? = -1 + fileprivate var _status: String? = "" + fileprivate var _taskInfo: String? = "" + fileprivate var _raw: NSObject? + + internal override init() { + super.init() + self._raw = nil + + } + + internal init(progress: C8oProgress) { + super.init() + _continuous = progress._continuous + _finished = progress._finished + _pull = progress._pull + _current = progress._current + _total = progress._total + _status = progress._status + _taskInfo = progress._taskInfo + _raw = progress._raw + } + + internal var changed: Bool { + get { + return _changed! + } + + set(value) { + _changed = value + } + } + + @objc open override var description: String { + var ch: String = direction + ": " + String(current) + "/" + String(total) + " (" + ch += (finished ? (continuous ? "live" : "done") : "running") + ")" + return ch + } + + @objc open var dictionary: NSDictionary { + let di = ["continuous": continuous, "finished": finished, "pull": pull, "current": current, "total": total, "status": status, "taskInfo": taskInfo, "raw": raw] as [String : Any]; + let nsDi = di as NSDictionary + return nsDi + } + + open var continuous: Bool { + get { + return _continuous! + } + + set(value) { + if (value != _continuous) { + _changed = true + _continuous = value + } + } + } + + open var finished: Bool { + get { + return _finished! + } + + set(value) { + if (value != _finished) { + _changed = true + _finished = value + } + } + } + + open var pull: Bool { + get { + return _pull! + } + + set(value) { + if (value != _pull) { + _changed = true + _pull = value + } + } + } + + open var push: Bool { + get { + return !_pull! + } + } + + open var current: Int { + get { + return _current! + } + + set(value) { + if (value != _current) { + _changed = true + _current = value + } + } + } + + open var total: Int { + get { + return _total! + } + + set(value) { + if (value != _total) { + _changed = true + _total = value + } + } + } + + open var direction: String { + get { + return _pull! ? + C8oFullSyncTranslator.FULL_SYNC_RESPONSE_VALUE_DIRECTION_PULL : + C8oFullSyncTranslator.FULL_SYNC_RESPONSE_VALUE_DIRECTION_PUSH + } + } + + open var status: String { + get { + return _status! + } + + set (value) { + if (value != _status) { + _changed = true + _status = value + } + } + } + + open var taskInfo: String { + get { + return _taskInfo! + } + + set(value) { + if (value != _taskInfo) { + _changed = true + _taskInfo = value + } + } + } + + open var raw: NSObject { + get { + return _raw! + } + + set(value) { + if (value != _raw) { + _changed = true + _raw = value + } + } + } } diff --git a/C8oSDKiOS/C8oPromise.swift b/C8oSDKiOS/C8oPromise.swift index 52e3247..88b364c 100644 --- a/C8oSDKiOS/C8oPromise.swift +++ b/C8oSDKiOS/C8oPromise.swift @@ -124,7 +124,7 @@ open class C8oPromise: C8oPromiseFailSync { syncMutex.append(false) let condition: NSCondition = NSCondition() condition.lock() - then { response, parameters in + _ = then { response, parameters in if (thread == Thread.current) { syncMutex[0] = true self.lastResponse = response diff --git a/C8oSDKiOS/C8oPromiseSync.swift b/C8oSDKiOS/C8oPromiseSync.swift index fa11068..b11122a 100644 --- a/C8oSDKiOS/C8oPromiseSync.swift +++ b/C8oSDKiOS/C8oPromiseSync.swift @@ -8,8 +8,8 @@ import Foundation -open class C8oPromiseSync { - func sync() throws -> T? { - return nil as T? - } +open class C8oPromiseSync : NSObject{ + func sync() throws -> T? { + return nil as T? + } } diff --git a/C8oSDKiOS/C8oResponseJsonListener.swift b/C8oSDKiOS/C8oResponseJsonListener.swift index b44e36e..2096f74 100644 --- a/C8oSDKiOS/C8oResponseJsonListener.swift +++ b/C8oSDKiOS/C8oResponseJsonListener.swift @@ -5,14 +5,13 @@ // Created by Charles Grimont on 18/02/2016. // Copyright © 2016 Convertigo. All rights reserved. // - import Foundation import SwiftyJSON -open class C8oResponseJsonListener: C8oResponseListener { - open var onJsonResponse: (JSON?, Dictionary?) -> () - - public init(onJsonResponse: @escaping (JSON?, Dictionary?) -> ()) { - self.onJsonResponse = onJsonResponse - } +@objc open class C8oResponseJsonListener: NSObject, C8oResponseListener { + open var onJsonResponse: (AnyObject?, Dictionary?) -> () + + @objc public init(onJsonResponse: @escaping (AnyObject?, Dictionary?) -> ()) { + self.onJsonResponse = onJsonResponse + } } diff --git a/C8oSDKiOS/C8oResponseListener.swift b/C8oSDKiOS/C8oResponseListener.swift index e265d76..987e321 100644 --- a/C8oSDKiOS/C8oResponseListener.swift +++ b/C8oSDKiOS/C8oResponseListener.swift @@ -5,9 +5,8 @@ // Created by Charles Grimont on 18/02/2016. // Copyright © 2016 Convertigo. All rights reserved. // - import Foundation -public protocol C8oResponseListener { - -} \ No newline at end of file +@objc public protocol C8oResponseListener { + +} diff --git a/C8oSDKiOS/C8oResponseProgressListener.swift b/C8oSDKiOS/C8oResponseProgressListener.swift index f2b363e..44ac4c7 100644 --- a/C8oSDKiOS/C8oResponseProgressListener.swift +++ b/C8oSDKiOS/C8oResponseProgressListener.swift @@ -5,14 +5,13 @@ // Created by Charles Grimont on 18/02/2016. // Copyright © 2016 Convertigo. All rights reserved. // - import Foundation -internal class C8oResponseProgressListener: C8oResponseListener { - internal var onProgressResponse: (C8oProgress, Dictionary) -> () - - internal init(onProgressResponse: @escaping (C8oProgress, Dictionary) -> ()) { - self.onProgressResponse = onProgressResponse; - } - +@objc internal class C8oResponseProgressListener: NSObject,C8oResponseListener { + internal var onProgressResponse: (C8oProgress, Dictionary) -> () + + internal init(onProgressResponse: @escaping (C8oProgress, Dictionary) -> ()) { + self.onProgressResponse = onProgressResponse; + } + } diff --git a/C8oSDKiOS/C8oSettings.swift b/C8oSDKiOS/C8oSettings.swift index d31a81d..c437da9 100644 --- a/C8oSDKiOS/C8oSettings.swift +++ b/C8oSDKiOS/C8oSettings.swift @@ -10,168 +10,159 @@ import Foundation import Alamofire import SwiftyJSON -open class C8oSettings: C8oBase { - public override init() { - } - - public init(c8oSettings: C8oBase) { - super.init() - copyProperties(c8oSettings) - } - - open func clone() -> C8oSettings { - return C8oSettings(c8oSettings: self) - } - - /** - Sets the connection timeout to Convertigo in milliseconds. A value of zero means the timeout is not used.
- Default is 0. - Example usage: - C8oSettings().setTimeout(100) - @see http://www.convertigo.com/document/convertigo-client-sdk/programming-guide/ for more information. - @param timeout : Int - @return The current C8oSettings, for chaining. - - */ - open func setTimeout(_ timeout: Int) -> C8oSettings { - var timeout = timeout - if (timeout <= 0) { - timeout = -1 - } - _timeout = timeout - return self - } - - /** - Sets a value indicating whether https calls trust all certificates or not.
- Default is false. - Example usage: - C8oSettings().setTrustAllCertificates(true) - @see http://www.convertigo.com/document/convertigo-client-sdk/programming-guide/ for more information. - @param trustAllCertificates : Bool - @return The current C8oSettings, for chaining. - - */ - open func setTrustAllCertificates(_ trustAllCertificates: Bool) -> C8oSettings { - _trustAllCertificates = trustAllCertificates - return self - } - - open func addClientCertificate(_ certificate: Byte, password: String) -> C8oSettings { - if (_clientCertificateBinaries == nil) { - //_clientCertificateBinaries = Dictionary?(certificate , password) - } - // clientCertificateBinaries = [certificate! as NSObject: password] - - return self - } - - open func addClientCertificate(_ certificatePath: String, password: String) -> C8oSettings { - if (_clientCertificateFiles == nil) { - _clientCertificateFiles = Dictionary() - } - _clientCertificateFiles = [certificatePath: password] - - return self - } - - /** - Add a new cookie to the initial cookies send to the Convertigo server. - Example usage: - C8oSettings().setTrustAllCertificates("username", value : "Convertigo") - @see http://www.convertigo.com/document/convertigo-client-sdk/programming-guide/ for more information. - @param name : String - @param value : String - @return The current C8oSettings, for chaining. - - */ - open func addCookie(_ name: String, value: String) -> C8oSettings { - - if (_cookies == nil) { - _cookies = Dictionary() - } - _cookies = [name: value] - - return self - } - - /** - Add a new cookie to the initial cookies send to the Convertigo server. - Example usage: - C8oSettings().setTrustAllCertificates("username", value : "Convertigo") - @see http://www.convertigo.com/document/convertigo-client-sdk/programming-guide/ for more information. - @param name : String - @param value : String - @return The current C8oSettings, for chaining. - - */ - open func setLogRemote(_ logRemote: Bool) -> C8oSettings { - _logRemote = logRemote - return self - } - - open func setLogLevelLocal(_ logLevelLocal: C8oLogLevel) -> C8oSettings { - _logLevelLocal = logLevelLocal - return self - } - - open func setLogC8o(_ logC8o: Bool) -> C8oSettings { - _logC8o = logC8o - return self - } - - open func setLogOnFail(_ logOnFail: ((_ exception: C8oException, _ parameters: Dictionary?) -> (Void))?) -> C8oSettings { - _logOnFail = logOnFail - return self - } - /** - pecify the default FullSync database name. Must match a Convertigo Server - FullSync connector name - */ - open func setDefaultDatabaseName(_ defaultDatabaseName: String) -> C8oSettings { - _defaultDatabaseName = defaultDatabaseName - return self - } - - open func setAuthenticationCookieValue(_ authenticationCookieValue: String) -> C8oSettings { - _authenticationCookieValue = authenticationCookieValue - return self - } - - open func setFullSyncServerUrl(_ fullSyncServerUrl: String) -> C8oSettings { - _fullSyncServerUrl = fullSyncServerUrl - return self - } - - open func setFullSyncUsername(_ fullSyncUsername: String) -> C8oSettings { - _fullSyncUsername = fullSyncUsername - return self - } - - open func setFullSyncPassword(_ fullSyncPassword: String) -> C8oSettings { - _fullSyncPassword = fullSyncPassword - return self - } - - open func setFullSyncLocalSuffix(_ fullSyncLocalSuffix: String) -> C8oSettings { - _fullSyncLocalSuffix = fullSyncLocalSuffix - return self - } - - open func setFullSyncStorageEngine(_ fullSyncStorageEngine: String) -> C8oSettings { +@objc open class C8oSettings: C8oBase { + @objc public override init() { + } + + @objc public init(c8oSettings: C8oBase) { + super.init() + copyProperties(c8oSettings) + } + + @objc open func clone() -> C8oSettings { + return C8oSettings(c8oSettings: self) + } + + /** + Sets the connection timeout to Convertigo in milliseconds. A value of zero means the timeout is not used.
+ Default is 0. + Example usage: + C8oSettings().setTimeout(100) + @see http://www.convertigo.com/document/convertigo-client-sdk/programming-guide/ for more information. + @param timeout : Int + @return The current C8oSettings, for chaining. + + */ + @objc open func setTimeout(_ timeout: Int) -> C8oSettings { + var timeout = timeout + if (timeout <= 0) { + timeout = -1 + } + _timeout = timeout + return self + } + + /** + Sets a value indicating whether https calls trust all certificates or not.
+ Default is false. + Example usage: + C8oSettings().setTrustAllCertificates(true) + @see http://www.convertigo.com/document/convertigo-client-sdk/programming-guide/ for more information. + @param trustAllCertificates : Bool + @return The current C8oSettings, for chaining. + + */ + @objc open func setTrustAllCertificates(_ trustAllCertificates: Bool) -> C8oSettings { + _trustAllCertificates = trustAllCertificates + return self + } + + @objc open func addClientCertificate(_ certificatePath: String, password: String) -> C8oSettings { + if (_clientCertificateFiles == nil) { + _clientCertificateFiles = Dictionary() + } + _clientCertificateFiles = [certificatePath: password] + + return self + } + + /** + Add a new cookie to the initial cookies send to the Convertigo server. + Example usage: + C8oSettings().setTrustAllCertificates("username", value : "Convertigo") + @see http://www.convertigo.com/document/convertigo-client-sdk/programming-guide/ for more information. + @param name : String + @param value : String + @return The current C8oSettings, for chaining. + + */ + @objc open func addCookie(_ name: String, value: String) -> C8oSettings { + + if (_cookies == nil) { + _cookies = Dictionary() + } + _cookies = [name: value] + + return self + } + + /** + Add a new cookie to the initial cookies send to the Convertigo server. + Example usage: + C8oSettings().setTrustAllCertificates("username", value : "Convertigo") + @see http://www.convertigo.com/document/convertigo-client-sdk/programming-guide/ for more information. + @param name : String + @param value : String + @return The current C8oSettings, for chaining. + + */ + @objc open func setLogRemote(_ logRemote: Bool) -> C8oSettings { + _logRemote = logRemote + return self + } + + @objc open func setLogLevelLocal(_ logLevelLocal: C8oLogLevel) -> C8oSettings { + _logLevelLocal = logLevelLocal + return self + } + + @objc open func setLogC8o(_ logC8o: Bool) -> C8oSettings { + _logC8o = logC8o + return self + } + + @objc open func setLogOnFail(_ logOnFail: ((_ exception: C8oException, _ parameters: Dictionary?) -> (Void))?) -> C8oSettings { + _logOnFail = logOnFail + return self + } + /** + pecify the default FullSync database name. Must match a Convertigo Server + FullSync connector name + */ + @objc open func setDefaultDatabaseName(_ defaultDatabaseName: String) -> C8oSettings { + _defaultDatabaseName = defaultDatabaseName + return self + } + + @objc open func setAuthenticationCookieValue(_ authenticationCookieValue: String) -> C8oSettings { + _authenticationCookieValue = authenticationCookieValue + return self + } + + @objc open func setFullSyncServerUrl(_ fullSyncServerUrl: String) -> C8oSettings { + _fullSyncServerUrl = fullSyncServerUrl + return self + } + + @objc open func setFullSyncUsername(_ fullSyncUsername: String) -> C8oSettings { + _fullSyncUsername = fullSyncUsername + return self + } + + @objc open func setFullSyncPassword(_ fullSyncPassword: String) -> C8oSettings { + _fullSyncPassword = fullSyncPassword + return self + } + + @objc open func setFullSyncLocalSuffix(_ fullSyncLocalSuffix: String) -> C8oSettings { + _fullSyncLocalSuffix = fullSyncLocalSuffix + return self + } + + @objc open func setFullSyncStorageEngine(_ fullSyncStorageEngine: String) -> C8oSettings { if (C8o.FS_STORAGE_SQL == fullSyncStorageEngine || C8o.FS_STORAGE_FORESTDB == fullSyncStorageEngine) { _fullSyncStorageEngine = fullSyncStorageEngine } return self } - open func setFullSyncEncryptionKey(_ fullSyncEncryptionKey: String) -> C8oSettings { + @objc open func setFullSyncEncryptionKey(_ fullSyncEncryptionKey: String) -> C8oSettings { _fullSyncEncryptionKey = fullSyncEncryptionKey return self } - - open func setUseEncryption(_ useEncryption: Bool) -> C8oSettings { - _useEncryption = useEncryption - return self - } + + @objc open func setUseEncryption(_ useEncryption: Bool) -> C8oSettings { + _useEncryption = useEncryption + return self + } } diff --git a/C8oSDKiOS/Exceptions.swift b/C8oSDKiOS/Exceptions.swift index 057f0ba..66c0f5b 100644 --- a/C8oSDKiOS/Exceptions.swift +++ b/C8oSDKiOS/Exceptions.swift @@ -8,107 +8,106 @@ import Foundation -open class C8oException: NSError { - open static let NSC8oErrorDomain: String = "com.convertigo.clientsdk.exception.C8oException" - open var message: String? - - public init(message: String, exception: NSError?) { - self.message = message - super.init(domain: C8oException.NSC8oErrorDomain, code: exception!.code, userInfo: [NSLocalizedFailureReasonErrorKey: message]) - - } - - public init(message: String) { - self.message = message - super.init(domain: C8oException.NSC8oErrorDomain, code: 1, userInfo: [NSLocalizedFailureReasonErrorKey: message]) - - } - - required public init?(coder aDecoder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - fileprivate static func filterMessage(_ message: String, exception: NSError) -> String { - var message = message - if (exception is C8oException) { - message = String(describing: exception) + " | " + message - } - return message - } - - fileprivate static func filterException(_ exception: NSError) -> NSError { - /*if (exception is C8oException) - { - return null - }*/ - return exception - } +@objc open class C8oException: NSError { + open static let NSC8oErrorDomain: String = "com.convertigo.clientsdk.exception.C8oException" + @objc open var message: String? + + public init(message: String, exception: NSError?) { + self.message = message + super.init(domain: C8oException.NSC8oErrorDomain, code: exception!.code, userInfo: [NSLocalizedFailureReasonErrorKey: message]) + + } + + public init(message: String) { + self.message = message + super.init(domain: C8oException.NSC8oErrorDomain, code: 1, userInfo: [NSLocalizedFailureReasonErrorKey: message]) + + } + + required public init?(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + fileprivate static func filterMessage(_ message: String, exception: NSError) -> String { + var message = message + if (exception is C8oException) { + message = String(describing: exception) + " | " + message + } + return message + } + + fileprivate static func filterException(_ exception: NSError) -> NSError { + /*if (exception is C8oException) + { + return null + }*/ + return exception + } } open class C8oHttpException: NSError { - public init(message: String, innerException: NSError) { - super.init(domain: "com.convertigo.C8o.Error", code: C8oCode.c8oHttpException.rawValue as Int, userInfo: [NSLocalizedFailureReasonErrorKey: message]) - } - - required public init?(coder aDecoder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } + public init(message: String, innerException: NSError) { + super.init(domain: "com.convertigo.C8o.Error", code: C8oCode.c8oHttpException.rawValue as Int, userInfo: [NSLocalizedFailureReasonErrorKey: message]) + } + + required public init?(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } } open class C8oRessourceNotFoundException: C8oException { - public override init(message: String, exception: NSError?) { - super.init(message: message, exception: exception) - } - - public override init(message: String) { - super.init(message: message) - } - - required public init?(coder aDecoder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } + public override init(message: String, exception: NSError?) { + super.init(message: message, exception: exception) + } + + public override init(message: String) { + super.init(message: message) + } + + required public init?(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } } open class c8oCouchbaseLiteException: C8oException { - public override init(message: String, exception: NSError?) { - super.init(message: message, exception: exception) - } - - public override init(message: String) { - super.init(message: message) - } - - required public init?(coder aDecoder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } + public override init(message: String, exception: NSError?) { + super.init(message: message, exception: exception) + } + + public override init(message: String) { + super.init(message: message) + } + + required public init?(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } } open class C8oUnavailableLocalCacheException: NSError { - - public init(message: String) { - super.init(domain: "com.convertigo.C8o.Error", code: C8oCode.c8oUnavailableLocalCacheException.rawValue as Int, userInfo: [NSLocalizedFailureReasonErrorKey: message]) - } - - required public init?(coder aDecoder: NSCoder) { - fatalError("init(coder:) has not been implemented") -} } + + public init(message: String) { + super.init(domain: "com.convertigo.C8o.Error", code: C8oCode.c8oUnavailableLocalCacheException.rawValue as Int, userInfo: [NSLocalizedFailureReasonErrorKey: message]) + } + + required public init?(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } } public enum C8oError: Error { - - case invalidArgument(String) - case argumentException(String) - case c8oException(String) - case argumentNilException(String) - + + case invalidArgument(String) + case argumentException(String) + case c8oException(String) + case argumentNilException(String) + } public enum C8oCode: Int { - case c8oUnavailableLocalCacheException = -6000 - case c8oRessourceNotFoundException = -6001 - case c8oHttpException = -6002 - case invalidArgument = -6003 - case argumentException = -6004 - case c8oException = -6005 - + case c8oUnavailableLocalCacheException = -6000 + case c8oRessourceNotFoundException = -6001 + case c8oHttpException = -6002 + case invalidArgument = -6003 + case argumentException = -6004 + case c8oException = -6005 + } - diff --git a/C8oSDKiOS/FullSyncEnum.swift b/C8oSDKiOS/FullSyncEnum.swift index 6e55b80..afa0031 100644 --- a/C8oSDKiOS/FullSyncEnum.swift +++ b/C8oSDKiOS/FullSyncEnum.swift @@ -12,418 +12,418 @@ import AEXML import CouchbaseLite.All internal class FullSyncRequestable { - internal static var GET: FullSyncRequestable = FullSyncRequestable(value: "get", handleFullSyncrequestOp: { (c8oFullSync, databaseName, parameters, c8oResponseListener) throws -> (Any) in - - let docid: String = try! C8oUtils.peekParameterStringValue(parameters, name: FullSyncGetDocumentParameter.DOCID.name, exceptionIfMissing: true)! - return try c8oFullSync.handleGetDocumentRequest(databaseName, docid: docid, parameters: parameters) as (Any) - }) - - internal static var DELETE: FullSyncRequestable = FullSyncRequestable(value: "delete", handleFullSyncrequestOp: { (c8oFullSync, databaseName, parameters, c8oResponseListener) throws -> (Any) in - - let docid: String = try! C8oUtils.peekParameterStringValue(parameters, name: FullSyncGetDocumentParameter.DOCID.name, exceptionIfMissing: true)! - do { - return try c8oFullSync.handleDeleteDocumentRequest(databaseName, docid: docid, parameters: parameters)! - } - catch let e as NSError { - throw e - } - - }) - - internal static var POST: FullSyncRequestable = FullSyncRequestable(value: "post", handleFullSyncrequestOp: { (c8oFullSync, databaseName, parameters, c8oResponseListener) -> (Any) in - - // Gets the policy parameter - let fullSyncPolicyParameter: String? = try! C8oUtils.peekParameterStringValue(parameters, name: FullSyncPostDocumentParameter.POLICY.name, exceptionIfMissing: false) - - // Finds the policy corresponding to the parameter value if it exists - let fullSyncPolicy: FullSyncPolicy = FullSyncPolicy.getFullSyncPolicy(fullSyncPolicyParameter) - - return try c8oFullSync.handlePostDocumentRequest(databaseName, fullSyncPolicy: fullSyncPolicy, parameters: parameters)! - }) - - internal static var PUT_ATTACHMENT: FullSyncRequestable = FullSyncRequestable(value: "put_attachment") { (c8oFullSync, databaseName, parameters, c8oResponseListener) -> (Any) in - - // Gets the docid parameter - let docid: String? = C8oUtils.getParameterStringValue(parameters, name: FullSyncAttachmentParameter.DOCID.name, useName: false) - - // Gets the attachment name parameter - let name: String? = C8oUtils.getParameterStringValue(parameters, name: FullSyncAttachmentParameter.NAME.name, useName: false) - - // Gets the attachment content_type parameter - let contentType: String? = C8oUtils.getParameterStringValue(parameters, name: FullSyncAttachmentParameter.CONTENT_TYPE.name, useName: false) - - // Gets the attachment content parameter - let a = C8oUtils.getParameterObjectValue(parameters, name: FullSyncAttachmentParameter.CONTENT.name, useName: false) - let content: Data? = C8oUtils.getParameterObjectValue(parameters, name: FullSyncAttachmentParameter.CONTENT.name, useName: false) as! Data? - - return try c8oFullSync.handlePutAttachmentRequest(databaseName, docid: docid!, attachmentName: name!, attachmentType: contentType!, attachmentContent: content!) - } - internal static var DELETE_ATTACHMENT: FullSyncRequestable = FullSyncRequestable(value: "delete_attachment") { (c8oFullSync, databaseName, parameters, c8oResponseListener) -> (Any) in - - // Gets the docid parameter - let docid: String = C8oUtils.getParameterStringValue(parameters, name: FullSyncAttachmentParameter.DOCID.name, useName: false)! - - // Gets the attachment name parameter - let name: String = C8oUtils.getParameterStringValue(parameters, name: FullSyncAttachmentParameter.NAME.name, useName: false)! - - return try c8oFullSync.handleDeleteAttachmentRequest(databaseName, docid: docid, attachmentName: name) - - } - - internal static var ALL: FullSyncRequestable = FullSyncRequestable(value: "all", handleFullSyncrequestOp: { (c8oFullSync, databaseName, parameters, c8oResponseListener) -> (Any) in - - return try! c8oFullSync.handleAllDocumentsRequest(databaseName, parameters: parameters)! - }) - - internal static var VIEW: FullSyncRequestable = FullSyncRequestable(value: "view", handleFullSyncrequestOp: { (c8oFullSync, databaseName, parameters, c8oResponseListener) throws -> (Any) in - - // Gets the design doc parameter value - let ddoc: String = try! C8oUtils.peekParameterStringValue(parameters, name: FullSyncGetViewParameter.DDOC.name, exceptionIfMissing: false)! - // Gets the view name parameter value - let view: String = try! C8oUtils.peekParameterStringValue(parameters, name: FullSyncGetViewParameter.VIEW.name, exceptionIfMissing: false)! - - return try c8oFullSync.handleGetViewRequest(databaseName, ddocName: ddoc, viewName: view, parameters: parameters)! - }) - - internal static var SYNC: FullSyncRequestable = FullSyncRequestable(value: "sync", handleFullSyncrequestOp: { (c8oFullSync, databaseName, parameters, c8oResponseListener) -> (Any) in - let thread: Thread = Thread.current - var mutex: Bool = false - var pullFinish: Bool = false - var pushFinish: Bool = false - let condition: NSCondition = NSCondition() - condition.lock() - - try! c8oFullSync.handleSyncRequest(databaseName, parameters: parameters, c8oResponseListener: C8oResponseProgressListener(onProgressResponse: { (progress, param) -> () in - - if (!mutex) { - if (!pullFinish && progress.pull && progress.finished) { - pullFinish = true - c8oFullSync.c8o!.log._debug("handleFullSyncRequest pullFinish = true: " + progress.description) - } - - if (!pushFinish && progress.push && progress.finished) { - pushFinish = true - c8oFullSync.c8o!.log._debug("handleFullSyncRequest pushFinish = true: " + progress.description) - } - } - - if (progress.total != -1) { - if (c8oResponseListener is C8oResponseJsonListener) { - c8oFullSync.c8o!.log._debug("handleFullSyncRequest onJsonResponse: " + progress.description) - let varNil: C8oJSON? = nil - (c8oResponseListener as! C8oResponseJsonListener).onJsonResponse(varNil?.myJSON, param) - } else if (c8oResponseListener is C8oResponseXmlListener) { - let varNil: AEXMLDocument? = nil - (c8oResponseListener as! C8oResponseXmlListener).onXmlResponse(varNil, param) - } - } - - if (!mutex && pullFinish && pushFinish) { - if (Thread.current == thread) { - mutex = true - } else { - condition.lock() - mutex = true - c8oFullSync.c8o!.log._debug("handleFullSyncRequest notify: " + progress.description) - condition.signal() - condition.unlock() - } - } - })) - if (!mutex) { - condition.wait() - } - c8oFullSync.c8o!.log._debug("handleFullSyncRequest after wait") - let myjson: C8oJSON = C8oJSON() - let json: JSON = ["ok": true] - myjson.myJSON = json - condition.unlock() - return myjson - }) - - internal static var REPLICATE_PULL: FullSyncRequestable = FullSyncRequestable(value: "replicate_pull", handleFullSyncrequestOp: { (c8oFullSync, databaseName, parameters, c8oResponseListener) -> (Any) in - - let condition: NSCondition = NSCondition() - let thread: Thread = Thread.current - var syncMutex: [Bool] = [Bool]() - syncMutex.append(false) - condition.lock() - try! c8oFullSync.handleReplicatePullRequest(databaseName, parameters: parameters, c8oResponseListener: C8oResponseProgressListener(onProgressResponse: { (progress, param) -> () in - - if (progress.finished) { - if (Thread.current == thread) { - syncMutex[0] = true - } else { - syncMutex[0] = true - // condition.lock() - condition.signal() - // condition.unlock() - } - } - - if (progress.total != -1) { - if (c8oResponseListener is C8oResponseJsonListener) { - let varNil: C8oJSON? = nil - (c8oResponseListener as! C8oResponseJsonListener).onJsonResponse(varNil?.myJSON, param) - } else if (c8oResponseListener is C8oResponseXmlListener) { - let varNil: AEXMLDocument? = nil - (c8oResponseListener as! C8oResponseXmlListener).onXmlResponse(varNil, param) - } - } - - })) - if (!syncMutex[0]) { - condition.wait() - } - let myjson: C8oJSON = C8oJSON() - let json: JSON = ["ok": true] - myjson.myJSON = json - - condition.unlock() - return myjson - }) - - internal static var REPLICATE_PUSH: FullSyncRequestable = FullSyncRequestable(value: "replicate_push", handleFullSyncrequestOp: { (c8oFullSync, databaseName, parameters, c8oResponseListener) -> (Any) in - - let condition: NSCondition = NSCondition() - let thread: Thread = Thread.current - var syncMutex: [Bool] = [Bool]() - syncMutex.append(false) - condition.lock() - - try! c8oFullSync.handleReplicatePushRequest(databaseName, parameters: parameters, c8oResponseListener: C8oResponseProgressListener(onProgressResponse: { (progress, param) -> () in - - if (progress.finished) { - if (Thread.current == thread) { - syncMutex[0] = true - } else { - syncMutex[0] = true - // condition.lock() - condition.signal() - // condition.unlock() - } - } - - if (progress.total != -1) { - if (c8oResponseListener is C8oResponseJsonListener) { - let varNil: C8oJSON? = nil - (c8oResponseListener as! C8oResponseJsonListener).onJsonResponse(varNil?.myJSON, param) - } else if (c8oResponseListener is C8oResponseXmlListener) { - let varNil: AEXMLDocument? = nil - (c8oResponseListener as! C8oResponseXmlListener).onXmlResponse(varNil, param) - } - } - })) - if (!syncMutex[0]) { - condition.wait() - } - let myjson: C8oJSON = C8oJSON() - let json: JSON = ["ok": true] - myjson.myJSON = json - - condition.unlock() - return myjson - }) - - internal static var RESET: FullSyncRequestable = FullSyncRequestable(value: "reset", handleFullSyncrequestOp: { (c8oFullSync, databaseName, parameters, c8oResponseListener) -> (NSObject) in - - return try! c8oFullSync.handleResetDatabaseRequest(databaseName)! - }) - - internal static var CREATE: FullSyncRequestable = FullSyncRequestable(value: "create", handleFullSyncrequestOp: { (c8oFullSync, databaseName, parameters, c8oResponseListener) -> (NSObject) in - - return try c8oFullSync.handleCreateDatabaseRequest(databaseName)! - }) - - internal static var DESTROY: FullSyncRequestable = FullSyncRequestable(value: "destroy", handleFullSyncrequestOp: { (c8oFullSync, databaseName, parameters, c8oResponseListener) -> (NSObject) in - return try! c8oFullSync.handleDestroyDatabaseRequest(databaseName)! // HandleDestroyDatabaseRequest(databaseName)! - }) - - internal var value: String - fileprivate var handleFullSyncrequestOp: (C8oFullSyncCbl, String, Dictionary, C8oResponseListener) throws -> (Any) - - fileprivate init(value: String, handleFullSyncrequestOp: @escaping (C8oFullSyncCbl, String, Dictionary, C8oResponseListener) throws -> (Any)) { - self.value = value - self.handleFullSyncrequestOp = handleFullSyncrequestOp - } - - internal func handleFullSyncRequest(_ c8oFullSync: C8oFullSyncCbl, databaseNameName: String, parameters: Dictionary, c8oResponseListner: C8oResponseListener) throws -> Any { - do { - return try handleFullSyncrequestOp(c8oFullSync, databaseNameName, parameters, c8oResponseListner) - } - catch let e as NSError { - throw e - } - - } - - internal static func getFullSyncRequestable(_ value: String) -> FullSyncRequestable? { - let fullSyncRequestableValues: [FullSyncRequestable] = FullSyncRequestable.values() - for fullSyncRequestable in fullSyncRequestableValues { - if (fullSyncRequestable.value == value) { - return fullSyncRequestable - } - } - return nil - } - - internal static func values() -> [FullSyncRequestable] { - let array: [FullSyncRequestable] = [GET, DELETE, POST, ALL, VIEW, SYNC, REPLICATE_PULL, REPLICATE_PUSH, RESET, CREATE, DESTROY, PUT_ATTACHMENT, DELETE_ATTACHMENT] - return array - } + internal static var GET: FullSyncRequestable = FullSyncRequestable(value: "get", handleFullSyncrequestOp: { (c8oFullSync, databaseName, parameters, c8oResponseListener) throws -> (Any) in + + let docid: String = try! C8oUtils.peekParameterStringValue(parameters, name: FullSyncGetDocumentParameter.DOCID.name, exceptionIfMissing: true)! + return try c8oFullSync.handleGetDocumentRequest(databaseName, docid: docid, parameters: parameters) as (Any) + }) + + internal static var DELETE: FullSyncRequestable = FullSyncRequestable(value: "delete", handleFullSyncrequestOp: { (c8oFullSync, databaseName, parameters, c8oResponseListener) throws -> (Any) in + + let docid: String = try! C8oUtils.peekParameterStringValue(parameters, name: FullSyncGetDocumentParameter.DOCID.name, exceptionIfMissing: true)! + do { + return try c8oFullSync.handleDeleteDocumentRequest(databaseName, docid: docid, parameters: parameters)! + } + catch let e as NSError { + throw e + } + + }) + + internal static var POST: FullSyncRequestable = FullSyncRequestable(value: "post", handleFullSyncrequestOp: { (c8oFullSync, databaseName, parameters, c8oResponseListener) -> (Any) in + + // Gets the policy parameter + let fullSyncPolicyParameter: String? = try! C8oUtils.peekParameterStringValue(parameters, name: FullSyncPostDocumentParameter.POLICY.name, exceptionIfMissing: false) + + // Finds the policy corresponding to the parameter value if it exists + let fullSyncPolicy: FullSyncPolicy = FullSyncPolicy.getFullSyncPolicy(fullSyncPolicyParameter) + + return try c8oFullSync.handlePostDocumentRequest(databaseName, fullSyncPolicy: fullSyncPolicy, parameters: parameters)! + }) + + internal static var PUT_ATTACHMENT: FullSyncRequestable = FullSyncRequestable(value: "put_attachment") { (c8oFullSync, databaseName, parameters, c8oResponseListener) -> (Any) in + + // Gets the docid parameter + let docid: String? = C8oUtils.getParameterStringValue(parameters, name: FullSyncAttachmentParameter.DOCID.name, useName: false) + + // Gets the attachment name parameter + let name: String? = C8oUtils.getParameterStringValue(parameters, name: FullSyncAttachmentParameter.NAME.name, useName: false) + + // Gets the attachment content_type parameter + let contentType: String? = C8oUtils.getParameterStringValue(parameters, name: FullSyncAttachmentParameter.CONTENT_TYPE.name, useName: false) + + // Gets the attachment content parameter + let a = C8oUtils.getParameterObjectValue(parameters, name: FullSyncAttachmentParameter.CONTENT.name, useName: false) + let content: Data? = C8oUtils.getParameterObjectValue(parameters, name: FullSyncAttachmentParameter.CONTENT.name, useName: false) as! Data? + + return try c8oFullSync.handlePutAttachmentRequest(databaseName, docid: docid!, attachmentName: name!, attachmentType: contentType!, attachmentContent: content!) + } + internal static var DELETE_ATTACHMENT: FullSyncRequestable = FullSyncRequestable(value: "delete_attachment") { (c8oFullSync, databaseName, parameters, c8oResponseListener) -> (Any) in + + // Gets the docid parameter + let docid: String = C8oUtils.getParameterStringValue(parameters, name: FullSyncAttachmentParameter.DOCID.name, useName: false)! + + // Gets the attachment name parameter + let name: String = C8oUtils.getParameterStringValue(parameters, name: FullSyncAttachmentParameter.NAME.name, useName: false)! + + return try c8oFullSync.handleDeleteAttachmentRequest(databaseName, docid: docid, attachmentName: name) + + } + + internal static var ALL: FullSyncRequestable = FullSyncRequestable(value: "all", handleFullSyncrequestOp: { (c8oFullSync, databaseName, parameters, c8oResponseListener) -> (Any) in + + return try! c8oFullSync.handleAllDocumentsRequest(databaseName, parameters: parameters)! + }) + + internal static var VIEW: FullSyncRequestable = FullSyncRequestable(value: "view", handleFullSyncrequestOp: { (c8oFullSync, databaseName, parameters, c8oResponseListener) throws -> (Any) in + + // Gets the design doc parameter value + let ddoc: String = try! C8oUtils.peekParameterStringValue(parameters, name: FullSyncGetViewParameter.DDOC.name, exceptionIfMissing: false)! + // Gets the view name parameter value + let view: String = try! C8oUtils.peekParameterStringValue(parameters, name: FullSyncGetViewParameter.VIEW.name, exceptionIfMissing: false)! + + return try c8oFullSync.handleGetViewRequest(databaseName, ddocName: ddoc, viewName: view, parameters: parameters)! + }) + + internal static var SYNC: FullSyncRequestable = FullSyncRequestable(value: "sync", handleFullSyncrequestOp: { (c8oFullSync, databaseName, parameters, c8oResponseListener) -> (Any) in + let thread: Thread = Thread.current + var mutex: Bool = false + var pullFinish: Bool = false + var pushFinish: Bool = false + let condition: NSCondition = NSCondition() + condition.lock() + + _ = try! c8oFullSync.handleSyncRequest(databaseName, parameters: parameters, c8oResponseListener: C8oResponseProgressListener(onProgressResponse: { (progress, param) -> () in + + if (!mutex) { + if (!pullFinish && progress.pull && progress.finished) { + pullFinish = true + c8oFullSync.c8o!.log._debug("handleFullSyncRequest pullFinish = true: " + progress.description) + } + + if (!pushFinish && progress.push && progress.finished) { + pushFinish = true + c8oFullSync.c8o!.log._debug("handleFullSyncRequest pushFinish = true: " + progress.description) + } + } + + if (progress.total != -1) { + if (c8oResponseListener is C8oResponseJsonListener) { + c8oFullSync.c8o!.log._debug("handleFullSyncRequest onJsonResponse: " + progress.description) + let varNil: C8oJSON? = nil + (c8oResponseListener as! C8oResponseJsonListener).onJsonResponse(varNil?.myJSON as AnyObject, param) + } else if (c8oResponseListener is C8oResponseXmlListener) { + let varNil: AEXMLDocument? = nil + (c8oResponseListener as! C8oResponseXmlListener).onXmlResponse(varNil, param) + } + } + + if (!mutex && pullFinish && pushFinish) { + if (Thread.current == thread) { + mutex = true + } else { + condition.lock() + mutex = true + c8oFullSync.c8o!.log._debug("handleFullSyncRequest notify: " + progress.description) + condition.signal() + condition.unlock() + } + } + })) + if (!mutex) { + condition.wait() + } + c8oFullSync.c8o!.log._debug("handleFullSyncRequest after wait") + let myjson: C8oJSON = C8oJSON() + let json: JSON = ["ok": true] + myjson.myJSON = json + condition.unlock() + return myjson + }) + + internal static var REPLICATE_PULL: FullSyncRequestable = FullSyncRequestable(value: "replicate_pull", handleFullSyncrequestOp: { (c8oFullSync, databaseName, parameters, c8oResponseListener) -> (Any) in + + let condition: NSCondition = NSCondition() + let thread: Thread = Thread.current + var syncMutex: [Bool] = [Bool]() + syncMutex.append(false) + condition.lock() + _ = try! c8oFullSync.handleReplicatePullRequest(databaseName, parameters: parameters, c8oResponseListener: C8oResponseProgressListener(onProgressResponse: { (progress, param) -> () in + + if (progress.finished) { + if (Thread.current == thread) { + syncMutex[0] = true + } else { + syncMutex[0] = true + // condition.lock() + condition.signal() + // condition.unlock() + } + } + + if (progress.total != -1) { + if (c8oResponseListener is C8oResponseJsonListener) { + let varNil: C8oJSON? = nil + (c8oResponseListener as! C8oResponseJsonListener).onJsonResponse(varNil?.myJSON as AnyObject, param) + } else if (c8oResponseListener is C8oResponseXmlListener) { + let varNil: AEXMLDocument? = nil + (c8oResponseListener as! C8oResponseXmlListener).onXmlResponse(varNil, param) + } + } + + })) + if (!syncMutex[0]) { + condition.wait() + } + let myjson: C8oJSON = C8oJSON() + let json: JSON = ["ok": true] + myjson.myJSON = json + + condition.unlock() + return myjson + }) + + internal static var REPLICATE_PUSH: FullSyncRequestable = FullSyncRequestable(value: "replicate_push", handleFullSyncrequestOp: { (c8oFullSync, databaseName, parameters, c8oResponseListener) -> (Any) in + + let condition: NSCondition = NSCondition() + let thread: Thread = Thread.current + var syncMutex: [Bool] = [Bool]() + syncMutex.append(false) + condition.lock() + + _ = try! c8oFullSync.handleReplicatePushRequest(databaseName, parameters: parameters, c8oResponseListener: C8oResponseProgressListener(onProgressResponse: { (progress, param) -> () in + + if (progress.finished) { + if (Thread.current == thread) { + syncMutex[0] = true + } else { + syncMutex[0] = true + // condition.lock() + condition.signal() + // condition.unlock() + } + } + + if (progress.total != -1) { + if (c8oResponseListener is C8oResponseJsonListener) { + let varNil: C8oJSON? = nil + (c8oResponseListener as! C8oResponseJsonListener).onJsonResponse(varNil?.myJSON as AnyObject, param) + } else if (c8oResponseListener is C8oResponseXmlListener) { + let varNil: AEXMLDocument? = nil + (c8oResponseListener as! C8oResponseXmlListener).onXmlResponse(varNil, param) + } + } + })) + if (!syncMutex[0]) { + condition.wait() + } + let myjson: C8oJSON = C8oJSON() + let json: JSON = ["ok": true] + myjson.myJSON = json + + condition.unlock() + return myjson + }) + + internal static var RESET: FullSyncRequestable = FullSyncRequestable(value: "reset", handleFullSyncrequestOp: { (c8oFullSync, databaseName, parameters, c8oResponseListener) -> (NSObject) in + + return try! c8oFullSync.handleResetDatabaseRequest(databaseName)! + }) + + internal static var CREATE: FullSyncRequestable = FullSyncRequestable(value: "create", handleFullSyncrequestOp: { (c8oFullSync, databaseName, parameters, c8oResponseListener) -> (NSObject) in + + return try c8oFullSync.handleCreateDatabaseRequest(databaseName)! + }) + + internal static var DESTROY: FullSyncRequestable = FullSyncRequestable(value: "destroy", handleFullSyncrequestOp: { (c8oFullSync, databaseName, parameters, c8oResponseListener) -> (NSObject) in + return try! c8oFullSync.handleDestroyDatabaseRequest(databaseName)! // HandleDestroyDatabaseRequest(databaseName)! + }) + + internal var value: String + fileprivate var handleFullSyncrequestOp: (C8oFullSyncCbl, String, Dictionary, C8oResponseListener) throws -> (Any) + + fileprivate init(value: String, handleFullSyncrequestOp: @escaping (C8oFullSyncCbl, String, Dictionary, C8oResponseListener) throws -> (Any)) { + self.value = value + self.handleFullSyncrequestOp = handleFullSyncrequestOp + } + + internal func handleFullSyncRequest(_ c8oFullSync: C8oFullSyncCbl, databaseNameName: String, parameters: Dictionary, c8oResponseListner: C8oResponseListener) throws -> Any { + do { + return try handleFullSyncrequestOp(c8oFullSync, databaseNameName, parameters, c8oResponseListner) + } + catch let e as NSError { + throw e + } + + } + + internal static func getFullSyncRequestable(_ value: String) -> FullSyncRequestable? { + let fullSyncRequestableValues: [FullSyncRequestable] = FullSyncRequestable.values() + for fullSyncRequestable in fullSyncRequestableValues { + if (fullSyncRequestable.value == value) { + return fullSyncRequestable + } + } + return nil + } + + internal static func values() -> [FullSyncRequestable] { + let array: [FullSyncRequestable] = [GET, DELETE, POST, ALL, VIEW, SYNC, REPLICATE_PULL, REPLICATE_PUSH, RESET, CREATE, DESTROY, PUT_ATTACHMENT, DELETE_ATTACHMENT] + return array + } } //*** Common parameters ***// open class FullSyncRequestParameter { - open static let DESCENDING: FullSyncRequestParameter = FullSyncRequestParameter(name: "descending", isJson: true, action: { query, value in - query.descending = value as! Bool - }) - open static let ENDKEY: FullSyncRequestParameter = FullSyncRequestParameter(name: "endkey", isJson: true, action: { query, value in - query.endKey = value - }) - open static let ENDKEY_DOCID: FullSyncRequestParameter = FullSyncRequestParameter(name: "endkey_docid", action: { query, value in - query.endKeyDocID = value as! String - }) - open static let GROUP_LEVEL: FullSyncRequestParameter = FullSyncRequestParameter(name: "group_level", isJson: true, action: { query, value in - query.groupLevel = value as! UInt - }) - open static let INCLUDE_DELETED: FullSyncRequestParameter = FullSyncRequestParameter(name: "include_deleted", isJson: true, action: { query, value in - fatalError("must be done") - // query.allDocsMode. //= value as! Bool - }) - open static let INDEX_UPDATE_MODE: FullSyncRequestParameter = FullSyncRequestParameter(name: "index_update_mode", action: { query, value in - fatalError("must be done") - /*let valueStr : String = value as! String - var indexUpdateModeValues = CBLIndexUpdateMode() - var indexUpdateModeEnumerator =*/ - }) - open static let KEY: FullSyncRequestParameter = FullSyncRequestParameter(name: "keys", isJson: true, action: { query, value in - query.keys = [value] - }) - open static let KEYS: FullSyncRequestParameter = FullSyncRequestParameter(name: "keys", isJson: true, action: { query, value in - query.keys = value as? [Any] - }) - open static let LIMIT: FullSyncRequestParameter = FullSyncRequestParameter(name: "limit", isJson: true, action: { query, value in - var valUint : UInt = UInt(value as! NSNumber) - query.limit = valUint - }) - open static let INCLUDE_DOCS: FullSyncRequestParameter = FullSyncRequestParameter(name: "include_docs", isJson: true, action: { query, value in - query.prefetch = value as! Bool - }) - open static let REDUCE: FullSyncRequestParameter = FullSyncRequestParameter(name: "reduce", isJson: true, action: { query, value in - query.mapOnly = !(value as! Bool) - }) - open static let GROUP: FullSyncRequestParameter = FullSyncRequestParameter(name: "group", isJson: true, action: { query, value in - query.groupLevel = (value as! Bool) ? 99 : 0 - }) - open static let SKIP: FullSyncRequestParameter = FullSyncRequestParameter(name: "skip", isJson: true, action: { query, value in - var valUint : UInt = UInt(value as! NSNumber) + open static let DESCENDING: FullSyncRequestParameter = FullSyncRequestParameter(name: "descending", isJson: true, action: { query, value in + query.descending = value as! Bool + }) + open static let ENDKEY: FullSyncRequestParameter = FullSyncRequestParameter(name: "endkey", isJson: true, action: { query, value in + query.endKey = value + }) + open static let ENDKEY_DOCID: FullSyncRequestParameter = FullSyncRequestParameter(name: "endkey_docid", action: { query, value in + query.endKeyDocID = (value as! String) + }) + open static let GROUP_LEVEL: FullSyncRequestParameter = FullSyncRequestParameter(name: "group_level", isJson: true, action: { query, value in + query.groupLevel = value as! UInt + }) + open static let INCLUDE_DELETED: FullSyncRequestParameter = FullSyncRequestParameter(name: "include_deleted", isJson: true, action: { query, value in + fatalError("must be done") + // query.allDocsMode. //= value as! Bool + }) + open static let INDEX_UPDATE_MODE: FullSyncRequestParameter = FullSyncRequestParameter(name: "index_update_mode", action: { query, value in + fatalError("must be done") + /*let valueStr : String = value as! String + var indexUpdateModeValues = CBLIndexUpdateMode() + var indexUpdateModeEnumerator =*/ + }) + open static let KEY: FullSyncRequestParameter = FullSyncRequestParameter(name: "keys", isJson: true, action: { query, value in + query.keys = [value] + }) + open static let KEYS: FullSyncRequestParameter = FullSyncRequestParameter(name: "keys", isJson: true, action: { query, value in + query.keys = value as? [Any] + }) + open static let LIMIT: FullSyncRequestParameter = FullSyncRequestParameter(name: "limit", isJson: true, action: { query, value in + var valUint : UInt = UInt(truncating: value as! NSNumber) + query.limit = valUint + }) + open static let INCLUDE_DOCS: FullSyncRequestParameter = FullSyncRequestParameter(name: "include_docs", isJson: true, action: { query, value in + query.prefetch = value as! Bool + }) + open static let REDUCE: FullSyncRequestParameter = FullSyncRequestParameter(name: "reduce", isJson: true, action: { query, value in + query.mapOnly = !(value as! Bool) + }) + open static let GROUP: FullSyncRequestParameter = FullSyncRequestParameter(name: "group", isJson: true, action: { query, value in + query.groupLevel = (value as! Bool) ? 99 : 0 + }) + open static let SKIP: FullSyncRequestParameter = FullSyncRequestParameter(name: "skip", isJson: true, action: { query, value in + var valUint : UInt = UInt(truncating: value as! NSNumber) query.skip = valUint - }) - open static let STARTKEY: FullSyncRequestParameter = FullSyncRequestParameter(name: "startkey", isJson: true, action: { query, value in - query.startKey = value - }) - open static let STARTKEY_DOCID: FullSyncRequestParameter = FullSyncRequestParameter(name: "startkey_docid", action: { query, value in - query.startKeyDocID = value as? String - }) - - open var name: String - open var isJson: Bool - open var action: (CBLQuery, AnyObject) -> () - - fileprivate init(name: String, action: @escaping (CBLQuery, AnyObject) -> ()) { - self.name = name - self.isJson = false - self.action = action - } - - fileprivate init(name: String, isJson: Bool, action: @escaping (CBLQuery, AnyObject) -> ()) { - self.name = name - self.isJson = isJson - self.action = action - } - - open static func values() -> [FullSyncRequestParameter] { - let array: [FullSyncRequestParameter] = [DESCENDING, ENDKEY, ENDKEY_DOCID, GROUP_LEVEL, INCLUDE_DELETED, INDEX_UPDATE_MODE, KEYS, LIMIT, REDUCE, GROUP, SKIP, STARTKEY, STARTKEY_DOCID, INCLUDE_DOCS] - return array - } - - open static func getFullSyncRequestParameter(_ name: String?) -> FullSyncRequestParameter? { - if (name != nil) { - for fullSyncRequestParameter in FullSyncRequestParameter.values() { - if (name == fullSyncRequestParameter.name) { - return fullSyncRequestParameter - } - } - } - return nil - } - + }) + open static let STARTKEY: FullSyncRequestParameter = FullSyncRequestParameter(name: "startkey", isJson: true, action: { query, value in + query.startKey = value + }) + open static let STARTKEY_DOCID: FullSyncRequestParameter = FullSyncRequestParameter(name: "startkey_docid", action: { query, value in + query.startKeyDocID = value as? String + }) + + open var name: String + open var isJson: Bool + open var action: (CBLQuery, AnyObject) -> () + + fileprivate init(name: String, action: @escaping (CBLQuery, AnyObject) -> ()) { + self.name = name + self.isJson = false + self.action = action + } + + fileprivate init(name: String, isJson: Bool, action: @escaping (CBLQuery, AnyObject) -> ()) { + self.name = name + self.isJson = isJson + self.action = action + } + + open static func values() -> [FullSyncRequestParameter] { + let array: [FullSyncRequestParameter] = [DESCENDING, ENDKEY, ENDKEY_DOCID, GROUP_LEVEL, INCLUDE_DELETED, INDEX_UPDATE_MODE, KEYS, LIMIT, REDUCE, GROUP, SKIP, STARTKEY, STARTKEY_DOCID, INCLUDE_DOCS] + return array + } + + open static func getFullSyncRequestParameter(_ name: String?) -> FullSyncRequestParameter? { + if (name != nil) { + for fullSyncRequestParameter in FullSyncRequestParameter.values() { + if (name == fullSyncRequestParameter.name) { + return fullSyncRequestParameter + } + } + } + return nil + } + } //*** Specific parameters ***// open class FullSyncGetViewParameter { - open static let VIEW: FullSyncGetViewParameter = FullSyncGetViewParameter(name: "view") - open static let DDOC: FullSyncGetViewParameter = FullSyncGetViewParameter(name: "ddoc") - - open var name: String - - fileprivate init(name: String) { - self.name = name - } + open static let VIEW: FullSyncGetViewParameter = FullSyncGetViewParameter(name: "view") + open static let DDOC: FullSyncGetViewParameter = FullSyncGetViewParameter(name: "ddoc") + + open var name: String + + fileprivate init(name: String) { + self.name = name + } } open class FullSyncGetDocumentParameter { - open static let DOCID: FullSyncGetDocumentParameter = FullSyncGetDocumentParameter(name: "docid") - - open var name: String - - fileprivate init(name: String) { - self.name = name - } - + open static let DOCID: FullSyncGetDocumentParameter = FullSyncGetDocumentParameter(name: "docid") + + open var name: String + + fileprivate init(name: String) { + self.name = name + } + } open class FullSyncDeleteDocumentParameter { - open static let DOCID: FullSyncDeleteDocumentParameter = FullSyncDeleteDocumentParameter(name: "docid") - open static let REV: FullSyncDeleteDocumentParameter = FullSyncDeleteDocumentParameter(name: "rev") - - open var name: String - - fileprivate init(name: String) { - self.name = name - } + open static let DOCID: FullSyncDeleteDocumentParameter = FullSyncDeleteDocumentParameter(name: "docid") + open static let REV: FullSyncDeleteDocumentParameter = FullSyncDeleteDocumentParameter(name: "rev") + + open var name: String + + fileprivate init(name: String) { + self.name = name + } } open class FullSyncAttachmentParameter { - open static let DOCID: FullSyncAttachmentParameter = FullSyncAttachmentParameter(name: "docid") - open static let NAME: FullSyncAttachmentParameter = FullSyncAttachmentParameter(name: "name") - open static let CONTENT_TYPE: FullSyncAttachmentParameter = FullSyncAttachmentParameter(name: "content_type") - open static let CONTENT: FullSyncAttachmentParameter = FullSyncAttachmentParameter(name: "content") - - open var name: String - - fileprivate init(name: String) { - self.name = name - } + open static let DOCID: FullSyncAttachmentParameter = FullSyncAttachmentParameter(name: "docid") + open static let NAME: FullSyncAttachmentParameter = FullSyncAttachmentParameter(name: "name") + open static let CONTENT_TYPE: FullSyncAttachmentParameter = FullSyncAttachmentParameter(name: "content_type") + open static let CONTENT: FullSyncAttachmentParameter = FullSyncAttachmentParameter(name: "content") + + open var name: String + + fileprivate init(name: String) { + self.name = name + } } open class FullSyncPostDocumentParameter { - open static let POLICY: FullSyncPostDocumentParameter = FullSyncPostDocumentParameter(name: C8o.FS_POLICY) - open static let SUBKEY_SEPARATOR: FullSyncPostDocumentParameter = FullSyncPostDocumentParameter(name: C8o.FS_SUBKEY_SEPARATOR) - - open var name: String - - fileprivate init(name: String) { - self.name = name - } - - open static func values() -> [FullSyncPostDocumentParameter] { - let array: [FullSyncPostDocumentParameter] = [POLICY, SUBKEY_SEPARATOR] - return array - } - + open static let POLICY: FullSyncPostDocumentParameter = FullSyncPostDocumentParameter(name: C8o.FS_POLICY) + open static let SUBKEY_SEPARATOR: FullSyncPostDocumentParameter = FullSyncPostDocumentParameter(name: C8o.FS_SUBKEY_SEPARATOR) + + open var name: String + + fileprivate init(name: String) { + self.name = name + } + + open static func values() -> [FullSyncPostDocumentParameter] { + let array: [FullSyncPostDocumentParameter] = [POLICY, SUBKEY_SEPARATOR] + return array + } + } /** @@ -432,32 +432,32 @@ open class FullSyncPostDocumentParameter { //TODO... add types open class FullSyncReplicationParameter { - open static let CANCEL: FullSyncReplicationParameter = FullSyncReplicationParameter(name: "cancel", action: { replication, value in - - }) // , type: NSObject.self) - open static let LIVE: FullSyncReplicationParameter = FullSyncReplicationParameter(name: "live", action: { replication, value in - replication.continuous = value as! Bool - }) // , Boolean.Type) - open static let DOCIDS: FullSyncReplicationParameter = FullSyncReplicationParameter(name: "docids", action: { replication, value in - replication.documentIDs = value as? [String] - }) // , Array[String])) - - open var name: String - // public var type : type - open var action: (CBLReplication, Any) -> () - - fileprivate init(name: String, action: @escaping (CBLReplication, Any) -> ()) { - self.name = name - self.action = action - - // self.type = type - - } - - open static func values() -> [FullSyncReplicationParameter] { - let array: [FullSyncReplicationParameter] = [CANCEL, LIVE, DOCIDS] - return array - } + open static let CANCEL: FullSyncReplicationParameter = FullSyncReplicationParameter(name: "cancel", action: { replication, value in + + }) // , type: NSObject.self) + open static let LIVE: FullSyncReplicationParameter = FullSyncReplicationParameter(name: "live", action: { replication, value in + replication.continuous = value as! Bool + }) // , Boolean.Type) + open static let DOCIDS: FullSyncReplicationParameter = FullSyncReplicationParameter(name: "docids", action: { replication, value in + replication.documentIDs = value as? [String] + }) // , Array[String])) + + open var name: String + // public var type : type + open var action: (CBLReplication, Any) -> () + + fileprivate init(name: String, action: @escaping (CBLReplication, Any) -> ()) { + self.name = name + self.action = action + + // self.type = type + + } + + open static func values() -> [FullSyncReplicationParameter] { + let array: [FullSyncReplicationParameter] = [CANCEL, LIVE, DOCIDS] + return array + } } //*** Policy ***// @@ -466,125 +466,125 @@ open class FullSyncReplicationParameter { The policies of the fullSync's postDocument request. */ open class FullSyncPolicy { - /*private var c8o : Queue? = Queue() - public func setC8o(c8o : C8o){ - self.c8o?.enqueue(c8o) - } - public func getC8o()->C8o{ - return self.c8o!.dequeue()! - }*/ - - open static let NONE: FullSyncPolicy = FullSyncPolicy(value: C8o.FS_POLICY_NONE, action: { database, newProperties in - var createdDocument: CBLDocument + /*private var c8o : Queue? = Queue() + public func setC8o(c8o : C8o){ + self.c8o?.enqueue(c8o) + } + public func getC8o()->C8o{ + return self.c8o!.dequeue()! + }*/ + + open static let NONE: FullSyncPolicy = FullSyncPolicy(value: C8o.FS_POLICY_NONE, action: { database, newProperties in + var createdDocument: CBLDocument + var newPropertiesMutable = newProperties + do { + var documentId = C8oUtils.getParameterStringValue(newPropertiesMutable, name: C8oFullSync.FULL_SYNC__ID, useName: false) + + newPropertiesMutable.removeValue(forKey: C8oFullSync.FULL_SYNC__ID) + if (documentId == "") { + documentId = nil + } + + createdDocument = (documentId == nil) ? database.createDocument() : database.document(withID: documentId!)! + + try createdDocument.putProperties(newPropertiesMutable) + + } + catch let e as NSError { + throw c8oCouchbaseLiteException(message: C8oExceptionMessage.fullSyncPutProperties(newProperties), exception: e) + } + return createdDocument + }) + open static let CREATE: FullSyncPolicy = FullSyncPolicy(value: C8o.FS_POLICY_CREATE, action: { database, newProperties in + var createdDocument: CBLDocument var newPropertiesMutable = newProperties - do { - var documentId = C8oUtils.getParameterStringValue(newPropertiesMutable, name: C8oFullSync.FULL_SYNC__ID, useName: false) - - newPropertiesMutable.removeValue(forKey: C8oFullSync.FULL_SYNC__ID) - if (documentId == "") { - documentId = nil - } - - createdDocument = (documentId == nil) ? database.createDocument() : database.document(withID: documentId!)! + do { + newPropertiesMutable.removeValue(forKey: C8oFullSync.FULL_SYNC__ID) + newPropertiesMutable.removeValue(forKey: C8oFullSync.FULL_SYNC__REV) + createdDocument = database.createDocument() + try createdDocument.putProperties(newPropertiesMutable) + } + catch let e as NSError { + throw c8oCouchbaseLiteException(message: C8oExceptionMessage.fullSyncPutProperties(newProperties), exception: e) + } + + return createdDocument + }) + open static let OVERRIDE: FullSyncPolicy = FullSyncPolicy(value: C8o.FS_POLICY_OVERRIDE, action: { database, newProperties in + var createdDocument: CBLDocument + var newPropertiesMutable = newProperties + do { + let documentId: String? = C8oUtils.getParameterStringValue(newPropertiesMutable, name: C8oFullSync.FULL_SYNC__ID, useName: false)! + newPropertiesMutable.removeValue(forKey: C8oFullSync.FULL_SYNC__ID) + newPropertiesMutable.removeValue(forKey: C8oFullSync.FULL_SYNC__REV) + + if (documentId == nil) { + createdDocument = database.createDocument() + } else { + createdDocument = database.document(withID: documentId!)! + var currentRevision = createdDocument.currentRevision + if (currentRevision != nil) { + newPropertiesMutable[C8oFullSync.FULL_SYNC__REV] = currentRevision?.revisionID as Any + } + } + try createdDocument.putProperties(newPropertiesMutable) + } + catch let e as NSError { + throw c8oCouchbaseLiteException(message: C8oExceptionMessage.fullSyncPutProperties(newProperties), exception: e) + } + + return createdDocument + }) + open static let MERGE: FullSyncPolicy = FullSyncPolicy(value: C8o.FS_POLICY_MERGE, action: { database, newProperties in + var createdDocument: CBLDocument + var newPropertiesMutable = newProperties + do { + let documentId: String? = C8oUtils.getParameterStringValue(newPropertiesMutable, name: C8oFullSync.FULL_SYNC__ID, useName: false)! + newPropertiesMutable.removeValue(forKey: C8oFullSync.FULL_SYNC__ID) + newPropertiesMutable.removeValue(forKey: C8oFullSync.FULL_SYNC__REV) + if (documentId == nil) { + createdDocument = database.createDocument() + } else { + createdDocument = database.document(withID: documentId!)! + } + var oldProperties = createdDocument.properties + if (oldProperties != nil) { + C8oFullSyncCbl.mergeProperties(&newPropertiesMutable, oldProperties: oldProperties! as Dictionary) + } try createdDocument.putProperties(newPropertiesMutable) - - } - catch let e as NSError { - throw c8oCouchbaseLiteException(message: C8oExceptionMessage.fullSyncPutProperties(newProperties), exception: e) - } - return createdDocument - }) - open static let CREATE: FullSyncPolicy = FullSyncPolicy(value: C8o.FS_POLICY_CREATE, action: { database, newProperties in - var createdDocument: CBLDocument - var newPropertiesMutable = newProperties - do { - newPropertiesMutable.removeValue(forKey: C8oFullSync.FULL_SYNC__ID) - newPropertiesMutable.removeValue(forKey: C8oFullSync.FULL_SYNC__REV) - createdDocument = database.createDocument() - try createdDocument.putProperties(newPropertiesMutable) - } - catch let e as NSError { - throw c8oCouchbaseLiteException(message: C8oExceptionMessage.fullSyncPutProperties(newProperties), exception: e) - } - - return createdDocument - }) - open static let OVERRIDE: FullSyncPolicy = FullSyncPolicy(value: C8o.FS_POLICY_OVERRIDE, action: { database, newProperties in - var createdDocument: CBLDocument - var newPropertiesMutable = newProperties - do { - let documentId: String? = C8oUtils.getParameterStringValue(newPropertiesMutable, name: C8oFullSync.FULL_SYNC__ID, useName: false)! - newPropertiesMutable.removeValue(forKey: C8oFullSync.FULL_SYNC__ID) - newPropertiesMutable.removeValue(forKey: C8oFullSync.FULL_SYNC__REV) - - if (documentId == nil) { - createdDocument = database.createDocument() - } else { - createdDocument = database.document(withID: documentId!)! - var currentRevision = createdDocument.currentRevision - if (currentRevision != nil) { - newPropertiesMutable[C8oFullSync.FULL_SYNC__REV] = currentRevision?.revisionID as Any - } - } - try createdDocument.putProperties(newPropertiesMutable) - } - catch let e as NSError { - throw c8oCouchbaseLiteException(message: C8oExceptionMessage.fullSyncPutProperties(newProperties), exception: e) - } - - return createdDocument - }) - open static let MERGE: FullSyncPolicy = FullSyncPolicy(value: C8o.FS_POLICY_MERGE, action: { database, newProperties in - var createdDocument: CBLDocument - var newPropertiesMutable = newProperties - do { - let documentId: String? = C8oUtils.getParameterStringValue(newPropertiesMutable, name: C8oFullSync.FULL_SYNC__ID, useName: false)! - newPropertiesMutable.removeValue(forKey: C8oFullSync.FULL_SYNC__ID) - newPropertiesMutable.removeValue(forKey: C8oFullSync.FULL_SYNC__REV) - - if (documentId == nil) { - createdDocument = database.createDocument() - } else { - createdDocument = database.document(withID: documentId!)! - } - var oldProperties = createdDocument.properties - if (oldProperties != nil) { - C8oFullSyncCbl.mergeProperties(&newPropertiesMutable, oldProperties: oldProperties! as Dictionary) - } - try createdDocument.putProperties(newPropertiesMutable) - } - catch let e as NSError { - throw c8oCouchbaseLiteException(message: C8oExceptionMessage.fullSyncPutProperties(newProperties), exception: e) - } - return createdDocument - }) - - open var value: String? - open var action: (CBLDatabase, Dictionary) throws -> (CBLDocument) - + } + catch let e as NSError { + throw c8oCouchbaseLiteException(message: C8oExceptionMessage.fullSyncPutProperties(newProperties), exception: e) + } + return createdDocument + }) + + open var value: String? + open var action: (CBLDatabase, Dictionary) throws -> (CBLDocument) + fileprivate init(value: String?, action: @escaping (CBLDatabase, [String: Any]) throws -> (CBLDocument)) { - self.value = value - self.action = action - - // abstract void setReplication(Replication replication, Object parameterValue) - } - - open static func values() -> [FullSyncPolicy] { - let array: [FullSyncPolicy] = [NONE, CREATE, OVERRIDE, MERGE] - return array - } - - open static func getFullSyncPolicy(_ value: String?) -> FullSyncPolicy { - if (value != nil) { - let fullSyncPolicyValues: [FullSyncPolicy] = FullSyncPolicy.values() - for fullSyncPolicy in fullSyncPolicyValues { - - if (fullSyncPolicy.value == value) { - return fullSyncPolicy - } - } - } - return NONE - } + self.value = value + self.action = action + + // abstract void setReplication(Replication replication, Object parameterValue) + } + + open static func values() -> [FullSyncPolicy] { + let array: [FullSyncPolicy] = [NONE, CREATE, OVERRIDE, MERGE] + return array + } + + open static func getFullSyncPolicy(_ value: String?) -> FullSyncPolicy { + if (value != nil) { + let fullSyncPolicyValues: [FullSyncPolicy] = FullSyncPolicy.values() + for fullSyncPolicy in fullSyncPolicyValues { + + if (fullSyncPolicy.value == value) { + return fullSyncPolicy + } + } + } + return NONE + } } diff --git a/C8oSDKiOS/FullSyncResponse.swift b/C8oSDKiOS/FullSyncResponse.swift index ca94d22..1b148cf 100644 --- a/C8oSDKiOS/FullSyncResponse.swift +++ b/C8oSDKiOS/FullSyncResponse.swift @@ -29,7 +29,7 @@ open class FullSyncAbstractResponse: NSObject { func getProperties() -> Dictionary { var properties: Dictionary = Dictionary() - properties[FullSyncResponse.RESPONSE_KEY_OK] = self.operationStatus as! NSObject + properties[FullSyncResponse.RESPONSE_KEY_OK] = self.operationStatus! as NSObject return properties } @@ -53,8 +53,8 @@ internal class FullSyncDocumentOperationResponse: FullSyncAbstractResponse { override internal func getProperties() -> Dictionary { var properties: Dictionary = super.getProperties() - properties[FullSyncResponse.RESPONSE_KEY_DOCUMENT_ID] = self.documentId as! NSObject - properties[FullSyncResponse.RESPONSE_KEY_DOCUMENT_REVISION] = self.documentRevision as! NSObject + properties[FullSyncResponse.RESPONSE_KEY_DOCUMENT_ID] = self.documentId! as NSObject + properties[FullSyncResponse.RESPONSE_KEY_DOCUMENT_REVISION] = self.documentRevision! as NSObject return properties } diff --git a/C8oSDKiOS/Queue.swift b/C8oSDKiOS/Queue.swift index abc7fdf..8bc1451 100644 --- a/C8oSDKiOS/Queue.swift +++ b/C8oSDKiOS/Queue.swift @@ -44,7 +44,7 @@ extension String { extension String { var length: Int { - return characters.count + return count } } @@ -107,7 +107,7 @@ extension String { func indexOf(_ target: String) -> Int? { if let range = self.range(of: target) { - return characters.distance(from: startIndex, to: range.lowerBound) + return distance(from: startIndex, to: range.lowerBound) } else { return nil } @@ -115,7 +115,7 @@ extension String { func lastIndexOf(_ target: String) -> Int? { if let range = self.range(of: target, options: .backwards) { - return characters.distance(from: startIndex, to: range.lowerBound) + return distance(from: startIndex, to: range.lowerBound) } else { return nil } diff --git a/C8oSDKiOSTests/C8oSDKiOSTests.swift b/C8oSDKiOSTests/C8oSDKiOSTests.swift index 49a3c75..0aa5ff1 100644 --- a/C8oSDKiOSTests/C8oSDKiOSTests.swift +++ b/C8oSDKiOSTests/C8oSDKiOSTests.swift @@ -27,58 +27,58 @@ class C8oSDKiOSTests: XCTestCase { enum Stuff { case c8O, c8O_BIS, c8O_FS, c8O_FS_PULL, c8O_FS_PUSH, c8O_LC, setGetInSession } - func get(_ enu: Stuff) throws -> C8o { - switch (enu) { - case .c8O: - let c8o = try C8o(endpoint: PREFIX + HOST + PORT + PROJECT_PATH, c8oSettings: C8oSettings().setLogRemote(false).setLogLevelLocal(C8oLogLevel.error)) - // c8o.logLevelLocal = C8oLogLevel.ERROR - return c8o - - case .c8O_BIS: - let c8o = try C8o(endpoint: PREFIX + HOST + PORT + PROJECT_PATH, c8oSettings: C8oSettings().setLogRemote(false).setLogLevelLocal(C8oLogLevel.error)) - // c8o.logLevelLocal = C8oLogLevel.ERROR - return c8o - - case .c8O_FS: - let c8o = try C8o(endpoint: PREFIX + HOST + PORT + PROJECT_PATH, c8oSettings: C8oSettings().setDefaultDatabaseName("clientsdktesting").setLogRemote(false).setLogLevelLocal(C8oLogLevel.error)) - // c8o.logRemote = false - // c8o.logLevelLocal = C8oLogLevel.ERROR - return c8o - - case .c8O_FS_PULL: - let c8o = try C8o(endpoint: PREFIX + HOST + PORT + PROJECT_PATH, c8oSettings: C8oSettings().setDefaultDatabaseName("qa_fs_pull").setLogRemote(false).setLogLevelLocal(C8oLogLevel.error)) - // c8o.logRemote = false - // c8o.logLevelLocal = C8oLogLevel.ERROR - let json = try! c8o.callJson(".InitFsPull").sync() - XCTAssertTrue(json!["document"]["ok"].boolValue) - return c8o - - case .c8O_FS_PUSH: - let c8o = try C8o(endpoint: PREFIX + HOST + PORT + PROJECT_PATH, c8oSettings: C8oSettings().setDefaultDatabaseName("qa_fs_push").setLogRemote(false).setLogLevelLocal(C8oLogLevel.error)) - // c8o.logRemote = false - // c8o.logLevelLocal = C8oLogLevel.ERROR - let json = try! c8o.callJson(".InitFsPush").sync() - XCTAssertTrue(json!["document"]["ok"].boolValue) - return c8o - - case .c8O_LC: - let c8o = try C8o(endpoint: PREFIX + HOST + PORT + PROJECT_PATH, c8oSettings: C8oSettings().setLogRemote(false).setLogLevelLocal(C8oLogLevel.error)) - // c8o.logRemote = false - // c8o.logLevelLocal = C8oLogLevel.ERROR - return c8o - - case .setGetInSession: - let c8o = try get(.c8O_BIS) - let ts: String = String(NSTimeIntervalSince1970 * 1000) - let doc = try c8o.callXml(".SetInSession", parameters: "ts", ts).sync() - var newTs = doc?.root["pong"]["ts"].string - XCTAssertEqual(ts, newTs) - let doc2 = try c8o.callXml(".GetFromSession").sync() - newTs = doc2?.root["session"]["expression"].string - XCTAssertEqual(ts, newTs) - return c8o - } - } + func get(_ enu: Stuff) throws -> C8o { + switch (enu) { + case .c8O: + let c8o = try C8o(endpoint: PREFIX + HOST + PORT + PROJECT_PATH, c8oSettings: C8oSettings().setLogRemote(false).setLogLevelLocal(C8oLogLevel.error)) + // c8o.logLevelLocal = C8oLogLevel.ERROR + return c8o + + case .c8O_BIS: + let c8o = try C8o(endpoint: PREFIX + HOST + PORT + PROJECT_PATH, c8oSettings: C8oSettings().setLogRemote(false).setLogLevelLocal(C8oLogLevel.error)) + // c8o.logLevelLocal = C8oLogLevel.ERROR + return c8o + + case .c8O_FS: + let c8o = try C8o(endpoint: PREFIX + HOST + PORT + PROJECT_PATH, c8oSettings: C8oSettings().setDefaultDatabaseName("clientsdktesting").setLogRemote(false).setLogLevelLocal(C8oLogLevel.error)) + // c8o.logRemote = false + // c8o.logLevelLocal = C8oLogLevel.ERROR + return c8o + + case .c8O_FS_PULL: + let c8o = try C8o(endpoint: PREFIX + HOST + PORT + PROJECT_PATH, c8oSettings: C8oSettings().setDefaultDatabaseName("qa_fs_pull").setLogRemote(false).setLogLevelLocal(C8oLogLevel.error)) + // c8o.logRemote = false + // c8o.logLevelLocal = C8oLogLevel.ERROR + let json = try! c8o.callJson(".InitFsPull").sync() + XCTAssertTrue(json!["document"]["ok"].boolValue) + return c8o + + case .c8O_FS_PUSH: + let c8o = try C8o(endpoint: PREFIX + HOST + PORT + PROJECT_PATH, c8oSettings: C8oSettings().setDefaultDatabaseName("qa_fs_push").setLogRemote(false).setLogLevelLocal(C8oLogLevel.error)) + // c8o.logRemote = false + // c8o.logLevelLocal = C8oLogLevel.ERROR + let json = try! c8o.callJson(".InitFsPush").sync() + XCTAssertTrue(json!["document"]["ok"].boolValue) + return c8o + + case .c8O_LC: + let c8o = try C8o(endpoint: PREFIX + HOST + PORT + PROJECT_PATH, c8oSettings: C8oSettings().setLogRemote(false).setLogLevelLocal(C8oLogLevel.error)) + // c8o.logRemote = false + // c8o.logLevelLocal = C8oLogLevel.ERROR + return c8o + + case .setGetInSession: + let c8o = try get(.c8O_BIS) + let ts: String = String(NSTimeIntervalSince1970 * 1000) + let doc = try c8o.callXml(".SetInSession", parameters: "ts", ts).sync() + var newTs = doc?.root["pong"]["ts"].string + XCTAssertEqual(ts, newTs) + let doc2 = try c8o.callXml(".GetFromSession").sync() + newTs = doc2?.root["session"]["expression"].string + XCTAssertEqual(ts, newTs) + return c8o + } + } override func setUp() { super.setUp() @@ -161,7 +161,7 @@ class C8oSDKiOSTests: XCTestCase { }) let C8oP: C8oPromise = c8o.callXml(".Ping") Thread.sleep(forTimeInterval: 3) - try C8oP.sync() + _ = try C8oP.sync() } catch let ex as C8oException { exception = ex @@ -180,7 +180,7 @@ class C8oSDKiOSTests: XCTestCase { let c8o = try C8o(endpoint: PREFIX + HOST + "ee:28080" + PROJECT_PATH, c8oSettings: nil) let promise: C8oPromise = c8o.callXml(".Ping") Thread.sleep(forTimeInterval: 0.5) - try promise.sync() + _ = try promise.sync() } catch let ex as C8oException { exception = ex @@ -298,17 +298,17 @@ class C8oSDKiOSTests: XCTestCase { catch is C8oException{ print("error") } - catch is Error{ + catch { } } func testsetGetInSession() { - try! get(.setGetInSession) + _ = try! get(.setGetInSession) } func testCheckNoMixSession() { - try! get(.setGetInSession) + _ = try! get(.setGetInSession) let c8o = try! get(.c8O) let doc = try! c8o.callXml(".GetFromSession").sync() let expression = doc?.root["session"]["expression"].count @@ -322,20 +322,13 @@ class C8oSDKiOSTests: XCTestCase { XCTAssertTrue(!sLine.isEmpty, "[" + lvl + "] sLine='" + sLine + "'") let line = try! JSON(data: sLine.data(using: String.Encoding.utf8)!) XCTAssertEqual(lvl, line[2].string) - var newMsg = line[4].string - let start = newMsg!.range(of:"logID=")!.lowerBound - let end = newMsg!.endIndex - let range = start.. (C8oPromise?) in + _ = c8o.callXml(".Ping", parameters: "var1", "step 1").then { (doc, param) -> (C8oPromise?) in xdoc.append(doc) xthread.append(Thread.current) xparam.append(param as [String : AnyObject]) @@ -389,7 +382,7 @@ class C8oSDKiOSTests: XCTestCase { var xjson: [JSON] = [JSON]() let condition: NSCondition = NSCondition() condition.lock() - c8o.callJson(".Ping", parameters: "var1", "step 1") + _ = c8o.callJson(".Ping", parameters: "var1", "step 1") .then { (json, param) -> (C8oPromise?) in xjson.append(json) return c8o.callJson(".Ping", parameters: "var1", "step 2") @@ -425,7 +418,7 @@ class C8oSDKiOSTests: XCTestCase { var xthread: [Thread] = [Thread]() let condition: NSCondition = NSCondition() condition.lock() - c8o.callJson(".Ping", parameters: "var1", "step 1").thenUI({ (json, param) -> (C8oPromise?) in + _ = c8o.callJson(".Ping", parameters: "var1", "step 1").thenUI({ (json, param) -> (C8oPromise?) in xjson.append(json) xthread.append(Thread.current) return c8o.callJson(".Ping", parameters: "var1", "step 2") @@ -467,13 +460,13 @@ class C8oSDKiOSTests: XCTestCase { var xparam: [Dictionary] = [Dictionary]() let condition: NSCondition = NSCondition() condition.lock() - c8o.callJson(".Ping", parameters: "var1", "step 1") + _ = c8o.callJson(".Ping", parameters: "var1", "step 1") .then({ (json, param) -> (C8oPromise?) in xjson[0] = json return c8o.callJson(".Ping", parameters: "var1", "step 2") }).then({ (json, param) -> (C8oPromise?) in xjson[1] = json - if (json != nil) { + if (json != JSON.null) { throw C8oException(message: "random failure") } return c8o.callJson("Ping", parameters: "var1", "step 3") @@ -513,13 +506,13 @@ class C8oSDKiOSTests: XCTestCase { var xthread: [Thread] = [Thread]() let condition: NSCondition = NSCondition() condition.lock() - c8o.callJson(".Ping", parameters: "var1", "step 1") + _ = c8o.callJson(".Ping", parameters: "var1", "step 1") .then({ (json, param) -> (C8oPromise?) in xjson[0] = json return c8o.callJson(".Ping", parameters: "var1", "step 2") }).then({ (json, param) -> (C8oPromise?) in xjson[1] = json - if (json != nil) { + if (json != JSON.null) { throw C8oException(message: "random failure") } return c8o.callJson("Ping", parameters: "var1", "step 3") @@ -576,7 +569,7 @@ class C8oSDKiOSTests: XCTestCase { do { xjson[1] = try c8o.callJson(".Ping", parameters: "var1", "step 1").then({ (json, param) -> (C8oPromise?) in xjson[0] = json - if (json != nil) { + if (json != JSON.null) { throw C8oException(message: "random failure") } return c8o.callJson(".Ping", parameters: "var1", "step 2") @@ -682,11 +675,11 @@ class C8oSDKiOSTests: XCTestCase { let c8o = try! self.get(.c8O) var xjson: [JSON?] = [JSON?](repeating: nil, count: 3) let promise = c8o.callJson(".Ping", parameters: "var1", "step 1") - promise.then({ (json, param) -> (C8oPromise?) in + _ = promise.then({ (json, param) -> (C8oPromise?) in xjson[0] = json return c8o.callJson(".Ping", parameters: "var1", "step 2") }) - promise.then({ (json, param) -> (C8oPromise?) in + _ = promise.then({ (json, param) -> (C8oPromise?) in xjson[1] = json return c8o.callJson(".Ping", parameters: "var1", "step 3") }) @@ -704,12 +697,12 @@ class C8oSDKiOSTests: XCTestCase { var xjson: [JSON?] = [JSON?](repeating: nil, count: 3) let promise = c8o.callJson(".Ping", parameters: "var1", "step 1") Thread.sleep(forTimeInterval: 0.5) - promise.then({ (json, param) -> (C8oPromise?) in + _ = promise.then({ (json, param) -> (C8oPromise?) in xjson[0] = json return c8o.callJson(".Ping", parameters: "var1", "step 2") }) Thread.sleep(forTimeInterval: 0.5) - promise.then({ (json, param) -> (C8oPromise?) in + _ = promise.then({ (json, param) -> (C8oPromise?) in xjson[1] = json return c8o.callJson(".Ping", parameters: "var1", "step 3") }) @@ -763,7 +756,7 @@ class C8oSDKiOSTests: XCTestCase { json = try! c8o.callJson("fs://.delete", parameters: "docid", id).sync() XCTAssertTrue(json!["ok"].boolValue) do { - try c8o.callJson("fs://.get", parameters: "docid", id).sync() + _ = try c8o.callJson("fs://.get", parameters: "docid", id).sync() XCTAssertTrue(false, "not possible") } catch _ as C8oRessourceNotFoundException { @@ -785,7 +778,7 @@ class C8oSDKiOSTests: XCTestCase { XCTAssertTrue(json!["ok"].boolValue) let rev: String = json!["rev"].string! do { - try c8o.callJson("fs://.delete", parameters: "docid", id, "rev", "1-123456").sync() + _ = try c8o.callJson("fs://.delete", parameters: "docid", id, "rev", "1-123456").sync() XCTAssertTrue(false, "not possible") } catch _ as C8oRessourceNotFoundException { @@ -802,7 +795,7 @@ class C8oSDKiOSTests: XCTestCase { } XCTAssertTrue(json!["ok"].boolValue) do { - try c8o.callJson("fs://.get", parameters: "docid", id).sync() + _ = try c8o.callJson("fs://.get", parameters: "docid", id).sync() XCTAssertTrue(false, "not possible") } catch _ as C8oRessourceNotFoundException { @@ -840,7 +833,7 @@ class C8oSDKiOSTests: XCTestCase { json = try! c8o.callJson("fs://.create").sync()! XCTAssertTrue(json["ok"].boolValue) do { - try c8o.callJson("fs://.get", parameters: "docid", id ?? "").sync() + _ = try c8o.callJson("fs://.get", parameters: "docid", id ?? "").sync() XCTAssertTrue(false, "not possible") } catch _ as C8oRessourceNotFoundException { @@ -866,7 +859,7 @@ class C8oSDKiOSTests: XCTestCase { json = try! c8o.callJson("fs://.reset").sync()! XCTAssertTrue(json["ok"].boolValue) do { - try c8o.callJson("fs://.get", parameters: "docid", id).sync() + _ = try c8o.callJson("fs://.get", parameters: "docid", id).sync() XCTAssertTrue(false, "not possible") } catch _ as C8oRessourceNotFoundException { @@ -890,7 +883,7 @@ class C8oSDKiOSTests: XCTestCase { XCTAssertTrue(json["ok"].boolValue) let id: String = json["id"].string! do { - try c8o.callJson("fs://.post", parameters: "_id", id).sync() + _ = try c8o.callJson("fs://.post", parameters: "_id", id).sync() XCTAssertTrue(false, "not possible") } catch _ as c8oCouchbaseLiteException { XCTAssertTrue(true) @@ -911,7 +904,7 @@ class C8oSDKiOSTests: XCTestCase { XCTAssertTrue(json["ok"].boolValue) let id: String = json["id"].string! do { - try c8o.callJson("fs://.post", + _ = try c8o.callJson("fs://.post", parameters: C8o.FS_POLICY, C8o.FS_POLICY_NONE, "_id", id ).sync() @@ -1154,7 +1147,7 @@ class C8oSDKiOSTests: XCTestCase { json = try! c8o.callJson("fs://.post", parameters: "_id", myId).sync()! XCTAssertTrue(json["ok"].boolValue) do { - try c8o.callJson("fs://notdefault.get", parameters: "docid", myId).sync() + _ = try c8o.callJson("fs://notdefault.get", parameters: "docid", myId).sync() XCTAssertTrue(false, "not possible") } catch _ as C8oRessourceNotFoundException { @@ -1198,7 +1191,7 @@ class C8oSDKiOSTests: XCTestCase { var json: JSON = try! c8o.callJson("fs://.reset").sync()! XCTAssertTrue(json["ok"].boolValue) do { - try c8o.callJson("fs://.get", parameters: "docid", "258").sync() + _ = try c8o.callJson("fs://.get", parameters: "docid", "258").sync() XCTAssertTrue(false, "not possible") } catch _ as C8oRessourceNotFoundException { @@ -1207,13 +1200,16 @@ class C8oSDKiOSTests: XCTestCase { catch { XCTAssertTrue(false) } - json = try! c8o.callJson("fs://.replicate_pull").sync()! + json = try! c8o.callJson("fs://.replicate_pull").progress({ (prog) in + print(prog.description) + }).sync()! + print(json["ok"].boolValue) XCTAssertTrue(json["ok"].boolValue) json = try! c8o.callJson("fs://.get", parameters: "docid", "258").sync()! var value: String = json["data"].string! XCTAssertEqual("258", value) do { - try c8o.callJson("fs://.get", parameters: "docid", "456").sync() + _ = try c8o.callJson("fs://.get", parameters: "docid", "456").sync() XCTAssertTrue(false, "not possible") } catch _ as C8oRessourceNotFoundException { @@ -1234,7 +1230,7 @@ class C8oSDKiOSTests: XCTestCase { } - try! c8o.callJson(".LogoutTesting").sync() + _ = try! c8o.callJson(".LogoutTesting").sync() } func testC8oFsReplicatePullProgress() { @@ -1275,7 +1271,7 @@ class C8oSDKiOSTests: XCTestCase { XCTAssertTrue(count[0] > 2, "count > 5") } - try! c8o.callJson(".LogoutTesting").sync()! + _ = try! c8o.callJson(".LogoutTesting").sync()! } @@ -1326,7 +1322,7 @@ class C8oSDKiOSTests: XCTestCase { catch let e as NSError { XCTFail(e.description) } - try! c8o.callJson(".LogoutTesting").sync()! + _ = try! c8o.callJson(".LogoutTesting").sync()! } @@ -1395,7 +1391,7 @@ class C8oSDKiOSTests: XCTestCase { } - try! c8o.callJson(".LogoutTesting").sync()! + _ = try! c8o.callJson(".LogoutTesting").sync()! } func testC8oFsViewArrayKey() { @@ -1414,7 +1410,7 @@ class C8oSDKiOSTests: XCTestCase { "startkey", "[\"1\"]" ).sync()! } - try! c8o.callJson(".LogoutTesting").sync()! + _ = try! c8o.callJson(".LogoutTesting").sync()! } func testC8oFsReplicatePullGetAll() { @@ -1459,10 +1455,10 @@ class C8oSDKiOSTests: XCTestCase { XCTAssertEqual("doc", json["rows"][1]["doc"]["type"].string) } catch let e as NSError { - try! c8o.callJson(".LogoutTesting").sync()! + _ = try! c8o.callJson(".LogoutTesting").sync()! XCTFail(e.description) } - try! c8o.callJson(".LogoutTesting").sync()! + _ = try! c8o.callJson(".LogoutTesting").sync()! } func testC8oFsReplicatePushAuth() { @@ -1496,10 +1492,10 @@ class C8oSDKiOSTests: XCTestCase { } catch let e as NSError { - try! c8o.callJson(".LogoutTesting").sync()! + _ = try! c8o.callJson(".LogoutTesting").sync()! XCTFail(e.description) } - try! c8o.callJson(".LogoutTesting").sync()! + _ = try! c8o.callJson(".LogoutTesting").sync()! } @@ -1560,10 +1556,10 @@ class C8oSDKiOSTests: XCTestCase { } catch let e as NSError { - try! c8o.callJson(".LogoutTesting").sync()! + _ = try! c8o.callJson(".LogoutTesting").sync()! XCTFail(e.description) } - try! c8o.callJson(".LogoutTesting").sync()! + _ = try! c8o.callJson(".LogoutTesting").sync()! } @@ -1638,11 +1634,11 @@ class C8oSDKiOSTests: XCTestCase { XCTAssertTrue(json["ok"].boolValue) XCTAssertEqual(firstPush[0], "push: 0/0 (running)") - var range = NSMakeRange(0, (lastPush[0] as String!).characters.count) + var range = NSMakeRange(0, (lastPush[0]! as String).count) var regexV = try! NSRegularExpression(pattern: "push: \\d+/\\d+ \\(done\\)", options: []).matches(in: lastPush[0]!, options: [], range: range) XCTAssertTrue(regexV.first != nil, "push: \\d+/\\d+ \\(done\\) for " + lastPush[0]!) XCTAssertEqual(firstPull[0], "pull: 0/0 (running)") - range = NSMakeRange(0, (lastPull[0] as String!).characters.count) + range = NSMakeRange(0, (lastPull[0]! as String).count) regexV = try! NSRegularExpression(pattern: "pull: \\d+/\\d+ \\(done\\)", options: []).matches(in: lastPull[0]!, options: [], range: range) XCTAssertTrue(regexV.first != nil, "pull: \\d+/\\d+ \\(done\\) for " + lastPull[0]!) @@ -1673,18 +1669,18 @@ class C8oSDKiOSTests: XCTestCase { json = try! c8o.callJson(".qa_fs_push.GetDocument", parameters: "_use_docid", "def").sync()! value = json["document"]["couchdb_output"]["custom"].string as AnyObject XCTAssertEqual(id, value as? String) - range = NSMakeRange(0, (livePull[0] as String!).characters.count) + range = NSMakeRange(0, (livePull[0]! as String).count) regexV = try! NSRegularExpression(pattern: "pull: \\d+/\\d+ \\(live\\)", options: []).matches(in: livePull[0]!, options: [], range: range) XCTAssertTrue(regexV.first != nil, "pull: \\d+/\\d+ \\(live\\) for " + livePull[0]!) - range = NSMakeRange(0, (livePush[0] as String!).characters.count) + range = NSMakeRange(0, (livePush[0]! as String).count) regexV = try! NSRegularExpression(pattern: "push: \\d+/\\d+ \\(live\\)", options: []).matches(in: livePush[0]!, options: [], range: range) XCTAssertTrue(regexV.first != nil, "push: \\d+/\\d+ \\(live\\) for " + livePush[0]!) } catch let e as NSError { - try! c8o.callJson(".LogoutTesting").sync()! + _ = try! c8o.callJson(".LogoutTesting").sync()! XCTFail(e.description) } - try! c8o.callJson(".LogoutTesting").sync()! + _ = try! c8o.callJson(".LogoutTesting").sync()! } func testC8oFsReplicateCancel() { @@ -1782,14 +1778,14 @@ class C8oSDKiOSTests: XCTestCase { XCTAssertNotEqual(signature, signature2) } - /*func testC8oFileTransferDownloadSimple() { + func testC8oFileTransferDownloadSimple() throws { let c8o = try! get(.c8O) let ft = try! C8oFileTransfer(c8o: c8o, c8oFileTransferSettings: C8oFileTransferSettings()) - try! c8o.callJson("fs://" + ft.taskDb + ".destroy").sync() + _ = try! c8o.callJson("fs://" + ft.taskDb + ".destroy").sync() var status: [C8oFileTransferStatus?] = [nil] let __status: NSCondition = NSCondition() var error: [NSError?] = [nil] - ft.raiseTransferStatus({ (source, event) in + _ = ft.raiseTransferStatus({ (source, event) in if (event.state == C8oFileTransferStatus.StateFinished) { __status.lock() status[0] = event @@ -1797,7 +1793,7 @@ class C8oSDKiOSTests: XCTestCase { __status.unlock() } }) - ft.raiseException({ (source, event) in + _ = ft.raiseException({ (source, event) in __status.lock() error[0] = event __status.signal() @@ -1814,7 +1810,7 @@ class C8oSDKiOSTests: XCTestCase { do { __status.lock() try ft.downloadFile(uuid, filePath: file) - __status.wait(until: NSDate(timeIntervalSinceNow: 20.0) as Date) + __status.wait() __status.unlock() if (error[0] != nil) { throw error[0]! @@ -1833,14 +1829,14 @@ class C8oSDKiOSTests: XCTestCase { } } - func testC8oFileTransferUploadSimple() { + func testC8oFileTransferUploadSimple() throws { let c8o = try! get(.c8O) let ft = try! C8oFileTransfer(c8o: c8o, c8oFileTransferSettings: C8oFileTransferSettings()) - try! c8o.callJson("fs://" + ft.taskDb + ".destroy").sync() + _ = try! c8o.callJson("fs://" + ft.taskDb + ".destroy").sync() var status: [C8oFileTransferStatus?] = [nil] let __status: NSCondition = NSCondition() var error: [NSError?] = [nil] - ft.raiseTransferStatus({ (source, event) in + _ = ft.raiseTransferStatus({ (source, event) in if (event.state == C8oFileTransferStatus.StateFinished) { __status.lock() status[0] = event @@ -1848,7 +1844,7 @@ class C8oSDKiOSTests: XCTestCase { __status.unlock() } }) - ft.raiseException({ (source, event) in + _ = ft.raiseException({ (source, event) in __status.lock() error[0] = event __status.signal() @@ -1862,8 +1858,7 @@ class C8oSDKiOSTests: XCTestCase { __status.wait(until: NSDate(timeIntervalSinceNow: 500.0) as Date) __status.unlock() if (error[0] != nil) { - print(error) - //throw error[0]! + throw error[0]! } XCTAssertNotNil(status[0]) let filepath = status[0]?.serverFilepath @@ -1871,7 +1866,7 @@ class C8oSDKiOSTests: XCTestCase { let length = lengthC8o!["document"]["length"].string XCTAssertEqual("5120000", length) } - */ + func disable_testC8oFsLiveChanges() { let c8o = try! get(.c8O_FS_PUSH) var lastChanges: JSON? = nil @@ -1893,7 +1888,7 @@ class C8oSDKiOSTests: XCTestCase { XCTAssertTrue(json["ok"].boolValue) var cptlive: Int = 0 let _cptlive = NSCondition() - try! c8o.callJson("fs://.get", parameters: "docid", "abc", C8o.FS_LIVE, "getabc").then({ (response, parameters) -> (C8oPromise?) in + _ = try! c8o.callJson("fs://.get", parameters: "docid", "abc", C8o.FS_LIVE, "getabc").then({ (response, parameters) -> (C8oPromise?) in _cptlive.lock() if (response["_id"].string == "abc") { cptlive = cptlive + 1 @@ -2001,7 +1996,7 @@ class C8oSDKiOSTests: XCTestCase { } func XCTAssertEqualsJsonChild(expectedObject: JSON, actualObject: JSON) { - if(expectedObject != nil){ + if(expectedObject != JSON.null){ if (expectedObject.dictionary != nil) { XCTAssertNotNil(actualObject, "must not be null") XCTAssertEquals(expected: expectedObject, actual: actualObject) @@ -2022,30 +2017,26 @@ class C8oSDKiOSTests: XCTestCase { } func XCTAssertEquals(expected: JSON, actual: JSON) { - do { - if (expected.dictionary != nil) { // || expected.array?.count >= 0 ){ - let expectedD = expected.dictionary - let actualD = actual.dictionary - let expectedNames = expectedD?.keys - let actualNames = actualD?.keys - XCTAssertEqual(expectedNames!.count, actualNames!.count, "missing keys: " + expectedNames.debugDescription + " and " + actualNames.debugDescription) - for (key, _) in expectedD! { - XCTAssertTrue(actualD![key] != nil, "missing key: " + key) - XCTAssertEqualsJsonChild(expectedObject: expectedD![key]!, actualObject: actualD![key]!) - } - } - else if (expected.array != nil) { - XCTAssertEqual(expected.array!, actual.array!, "array") - } - else if (expected.int != nil) { - XCTAssertEqual(expected, actual, "int equals") - } - else if (expected.string != nil) { - XCTAssertEqual(expected, actual, "string equals") - } - } catch let t as NSError { - XCTAssertTrue(false, "exception: " + t.description) - } + if (expected.dictionary != nil) { // || expected.array?.count >= 0 ){ + let expectedD = expected.dictionary + let actualD = actual.dictionary + let expectedNames = expectedD?.keys + let actualNames = actualD?.keys + XCTAssertEqual(expectedNames!.count, actualNames!.count, "missing keys: " + expectedNames.debugDescription + " and " + actualNames.debugDescription) + for (key, _) in expectedD! { + XCTAssertTrue(actualD![key] != nil, "missing key: " + key) + XCTAssertEqualsJsonChild(expectedObject: expectedD![key]!, actualObject: actualD![key]!) + } + } + else if (expected.array != nil) { + XCTAssertEqual(expected.array!, actual.array!, "array") + } + else if (expected.int != nil) { + XCTAssertEqual(expected, actual, "int equals") + } + else if (expected.string != nil) { + XCTAssertEqual(expected, actual, "string equals") + } } } diff --git a/PodFile b/PodFile index 76a9121..d0bedc1 100644 --- a/PodFile +++ b/PodFile @@ -5,7 +5,7 @@ target 'C8oSDKiOS' do pod 'SwiftyJSON', '4.0.0' pod 'Alamofire', '4.7.2' - pod 'AEXML', '4.2.2' + pod 'AEXML', '4.3.0' pod 'couchbase-lite-ios', '1.4.1' pod 'couchbase-lite-ios/ForestDB', '1.4.1'