You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@usergrid.apache.org by sn...@apache.org on 2016/02/16 14:15:25 UTC
[33/75] [partial] usergrid git commit: Initial commit of the Swift
SDK.
http://git-wip-us.apache.org/repos/asf/usergrid/blob/7442c881/sdks/swift/Source/UsergridEnums.swift
----------------------------------------------------------------------
diff --git a/sdks/swift/Source/UsergridEnums.swift b/sdks/swift/Source/UsergridEnums.swift
new file mode 100644
index 0000000..1cc0c9c
--- /dev/null
+++ b/sdks/swift/Source/UsergridEnums.swift
@@ -0,0 +1,415 @@
+//
+// UsergridEnums.swift
+// UsergridSDK
+//
+// Created by Robert Walsh on 10/21/15.
+//
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. The ASF licenses this file to You
+ * under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License. For additional information regarding
+ * copyright in this work, please see the NOTICE file in the top level
+ * directory of this distribution.
+ *
+ */
+
+import Foundation
+
+/**
+An enumeration that is used to determine what the `UsergridClient` will fallback to depending on certain authorization conditions.
+*/
+@objc public enum UsergridAuthFallback : Int {
+
+ // MARK: - Values -
+
+ /**
+ If a non-expired user auth token exists in `UsergridClient.currentUser`, this token is used to authenticate all API calls.
+
+ If the API call fails, the activity is treated as a failure with an appropriate HTTP status code.
+
+ If a non-expired user auth token does not exist, all API calls will be made unauthenticated.
+ */
+ case None
+ /**
+ If a non-expired user auth token exists in `UsergridClient.currentUser`, this token is used to authenticate all API calls.
+
+ If the API call fails, the activity is treated as a failure with an appropriate HTTP status code (This behavior is identical to authFallback=.None).
+
+ If a non-expired user auth does not exist, all API calls will be made using stored app auth.
+ */
+ case App
+}
+
+/**
+`UsergridEntity` specific properties keys. Note that trying to mutate the values of these properties will not be allowed in most cases.
+*/
+@objc public enum UsergridEntityProperties : Int {
+
+ // MARK: - Values -
+
+ /// Corresponds to the property 'type'
+ case EntityType
+ /// Corresponds to the property 'uuid'
+ case UUID
+ /// Corresponds to the property 'name'
+ case Name
+ /// Corresponds to the property 'created'
+ case Created
+ /// Corresponds to the property 'modified'
+ case Modified
+ /// Corresponds to the property 'location'
+ case Location
+
+ // MARK: - Methods -
+
+ /**
+ Gets the corresponding `UsergridEntityProperties` from a string if it's valid.
+
+ - parameter stringValue: The string value to convert.
+
+ - returns: The corresponding `UsergridEntityProperties` or nil.
+ */
+ public static func fromString(stringValue: String) -> UsergridEntityProperties? {
+ switch stringValue.lowercaseString {
+ case ENTITY_TYPE: return .EntityType
+ case ENTITY_UUID: return .UUID
+ case ENTITY_NAME: return .Name
+ case ENTITY_CREATED: return .Created
+ case ENTITY_MODIFIED: return .Modified
+ case ENTITY_LOCATION: return .Location
+ default: return nil
+ }
+ }
+
+ /// Returns the string value.
+ public var stringValue: String {
+ switch self {
+ case .EntityType: return ENTITY_TYPE
+ case .UUID: return ENTITY_UUID
+ case .Name: return ENTITY_NAME
+ case .Created: return ENTITY_CREATED
+ case .Modified: return ENTITY_MODIFIED
+ case .Location: return ENTITY_LOCATION
+ }
+ }
+
+ /**
+ Determines if the `UsergridEntityProperties` is mutable for the given entity.
+
+ - parameter entity: The entity to check.
+
+ - returns: If the `UsergridEntityProperties` is mutable for the given entity
+ */
+ public func isMutableForEntity(entity:UsergridEntity) -> Bool {
+ switch self {
+ case .EntityType,.UUID,.Created,.Modified: return false
+ case .Location: return true
+ case .Name: return entity.isUser
+ }
+ }
+}
+
+/**
+`UsergridDeviceProperties` specific properties keys. Note that trying to mutate the values of these properties will not be allowed in most cases.
+*/
+@objc public enum UsergridDeviceProperties : Int {
+
+ // MARK: - Values -
+
+ /// Corresponds to the property 'deviceModel'
+ case Model
+ /// Corresponds to the property 'devicePlatform'
+ case Platform
+ /// Corresponds to the property 'deviceOSVersion'
+ case OSVersion
+
+ // MARK: - Methods -
+
+ /**
+ Gets the corresponding `UsergridDeviceProperties` from a string if it's valid.
+
+ - parameter stringValue: The string value to convert.
+
+ - returns: The corresponding `UsergridDeviceProperties` or nil.
+ */
+ public static func fromString(stringValue: String) -> UsergridDeviceProperties? {
+ switch stringValue.lowercaseString {
+ case DEVICE_MODEL: return .Model
+ case DEVICE_PLATFORM: return .Platform
+ case DEVICE_OSVERSION: return .OSVersion
+ default: return nil
+ }
+ }
+
+ /// Returns the string value.
+ public var stringValue: String {
+ switch self {
+ case .Model: return DEVICE_MODEL
+ case .Platform: return DEVICE_PLATFORM
+ case .OSVersion: return DEVICE_OSVERSION
+ }
+ }
+}
+
+/**
+`UsergridUser` specific properties keys.
+*/
+@objc public enum UsergridUserProperties: Int {
+
+ // MARK: - Values -
+
+ /// Corresponds to the property 'name'
+ case Name
+ /// Corresponds to the property 'username'
+ case Username
+ /// Corresponds to the property 'password'
+ case Password
+ /// Corresponds to the property 'email'
+ case Email
+ /// Corresponds to the property 'age'
+ case Age
+ /// Corresponds to the property 'activated'
+ case Activated
+ /// Corresponds to the property 'disabled'
+ case Disabled
+ /// Corresponds to the property 'picture'
+ case Picture
+
+ // MARK: - Methods -
+
+ /**
+ Gets the corresponding `UsergridUserProperties` from a string if it's valid.
+
+ - parameter stringValue: The string value to convert.
+
+ - returns: The corresponding `UsergridUserProperties` or nil.
+ */
+ public static func fromString(stringValue: String) -> UsergridUserProperties? {
+ switch stringValue.lowercaseString {
+ case ENTITY_NAME: return .Name
+ case USER_USERNAME: return .Username
+ case USER_PASSWORD: return .Password
+ case USER_EMAIL: return .Email
+ case USER_AGE: return .Age
+ case USER_ACTIVATED: return .Activated
+ case USER_DISABLED: return .Disabled
+ case USER_PICTURE: return .Picture
+ default: return nil
+ }
+ }
+
+ /// Returns the string value.
+ public var stringValue: String {
+ switch self {
+ case .Name: return ENTITY_NAME
+ case .Username: return USER_USERNAME
+ case .Password: return USER_PASSWORD
+ case .Email: return USER_EMAIL
+ case .Age: return USER_AGE
+ case .Activated: return USER_ACTIVATED
+ case .Disabled: return USER_DISABLED
+ case .Picture: return USER_PICTURE
+ }
+ }
+}
+
+/**
+`UsergridQuery` specific operators.
+*/
+@objc public enum UsergridQueryOperator: Int {
+
+ // MARK: - Values -
+
+ /// '='
+ case Equal
+ /// '>'
+ case GreaterThan
+ /// '>='
+ case GreaterThanEqualTo
+ /// '<'
+ case LessThan
+ /// '<='
+ case LessThanEqualTo
+
+ // MARK: - Methods -
+
+ /**
+ Gets the corresponding `UsergridQueryOperator` from a string if it's valid.
+
+ - parameter stringValue: The string value to convert.
+
+ - returns: The corresponding `UsergridQueryOperator` or nil.
+ */
+ public static func fromString(stringValue: String) -> UsergridQueryOperator? {
+ switch stringValue.lowercaseString {
+ case UsergridQuery.EQUAL: return .Equal
+ case UsergridQuery.GREATER_THAN: return .GreaterThan
+ case UsergridQuery.GREATER_THAN_EQUAL_TO: return .GreaterThanEqualTo
+ case UsergridQuery.LESS_THAN: return .LessThan
+ case UsergridQuery.LESS_THAN_EQUAL_TO: return .LessThanEqualTo
+ default: return nil
+ }
+ }
+
+ /// Returns the string value.
+ public var stringValue: String {
+ switch self {
+ case .Equal: return UsergridQuery.EQUAL
+ case .GreaterThan: return UsergridQuery.GREATER_THAN
+ case .GreaterThanEqualTo: return UsergridQuery.GREATER_THAN_EQUAL_TO
+ case .LessThan: return UsergridQuery.LESS_THAN
+ case .LessThanEqualTo: return UsergridQuery.LESS_THAN_EQUAL_TO
+ }
+ }
+}
+
+/**
+`UsergridQuery` specific sort orders.
+*/
+@objc public enum UsergridQuerySortOrder: Int {
+
+ // MARK: - Values -
+
+ /// Sort order is ascending.
+ case Asc
+ /// Sort order is descending.
+ case Desc
+
+ // MARK: - Methods -
+
+ /**
+ Gets the corresponding `UsergridQuerySortOrder` from a string if it's valid.
+
+ - parameter stringValue: The string value to convert.
+
+ - returns: The corresponding `UsergridQuerySortOrder` or nil.
+ */
+ public static func fromString(stringValue: String) -> UsergridQuerySortOrder? {
+ switch stringValue.lowercaseString {
+ case UsergridQuery.ASC: return .Asc
+ case UsergridQuery.DESC: return .Desc
+ default: return nil
+ }
+ }
+
+ /// Returns the string value.
+ public var stringValue: String {
+ switch self {
+ case .Asc: return UsergridQuery.ASC
+ case .Desc: return UsergridQuery.DESC
+ }
+ }
+}
+
+/**
+`UsergridAsset` image specific content types.
+*/
+@objc public enum UsergridImageContentType : Int {
+
+ // MARK: - Values -
+
+ /// Content type: 'image/png'
+ case Png
+ /// Content type: 'image/jpeg'
+ case Jpeg
+
+ // MARK: - Methods -
+
+ /// Returns the string value.
+ public var stringValue: String {
+ switch self {
+ case .Png: return ASSET_IMAGE_PNG
+ case .Jpeg: return ASSET_IMAGE_JPEG
+ }
+ }
+}
+
+/**
+ An enumeration that is used when getting connections to entity objects. Used to determine which the direction of the connection is wanted.
+ */
+@objc public enum UsergridDirection : Int {
+
+ // MARK: - Values -
+
+ /// To get the entities that have created a connection to an entity. aka `connecting`
+ case In
+
+ /// To get the entities an entity has connected to. aka `connections`
+ case Out
+
+ // MARK: - Methods -
+
+ /// Returns the connection value.
+ public var connectionValue: String {
+ switch self {
+ case .In: return CONNECTION_TYPE_IN
+ case .Out: return CONNECTION_TYPE_OUT
+ }
+ }
+}
+
+/**
+ An enumeration for defining the HTTP methods used by Usergrid.
+ */
+@objc public enum UsergridHttpMethod : Int {
+
+ /// GET
+ case Get
+
+ /// PUT
+ case Put
+
+ /// POST
+ case Post
+
+ /// DELETE
+ case Delete
+
+ /// Returns the string value.
+ public var stringValue: String {
+ switch self {
+ case .Get: return "GET"
+ case .Put: return "PUT"
+ case .Post: return "POST"
+ case .Delete: return "DELETE"
+ }
+ }
+}
+
+let ENTITY_TYPE = "type"
+let ENTITY_UUID = "uuid"
+let ENTITY_NAME = "name"
+let ENTITY_CREATED = "created"
+let ENTITY_MODIFIED = "modified"
+let ENTITY_LOCATION = "location"
+let ENTITY_LATITUDE = "latitude"
+let ENTITY_LONGITUDE = "longitude"
+
+let USER_USERNAME = "username"
+let USER_PASSWORD = "password"
+let USER_EMAIL = "email"
+let USER_AGE = "age"
+let USER_ACTIVATED = "activated"
+let USER_DISABLED = "disabled"
+let USER_PICTURE = "picture"
+
+let DEVICE_MODEL = "deviceModel"
+let DEVICE_PLATFORM = "devicePlatform"
+let DEVICE_OSVERSION = "devicePlatform"
+
+let ASSET_IMAGE_PNG = "image/png"
+let ASSET_IMAGE_JPEG = "image/jpeg"
+
+let CONNECTION_TYPE_IN = "connecting"
+let CONNECTION_TYPE_OUT = "connections"
http://git-wip-us.apache.org/repos/asf/usergrid/blob/7442c881/sdks/swift/Source/UsergridExtensions.swift
----------------------------------------------------------------------
diff --git a/sdks/swift/Source/UsergridExtensions.swift b/sdks/swift/Source/UsergridExtensions.swift
new file mode 100644
index 0000000..050145c
--- /dev/null
+++ b/sdks/swift/Source/UsergridExtensions.swift
@@ -0,0 +1,42 @@
+//
+// UsergridExtensions.swift
+// UsergridSDK
+//
+// Created by Robert Walsh on 10/6/15.
+//
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. The ASF licenses this file to You
+ * under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License. For additional information regarding
+ * copyright in this work, please see the NOTICE file in the top level
+ * directory of this distribution.
+ *
+ */
+
+import Foundation
+
+internal extension NSDate {
+ convenience init(utcTimeStamp: String) {
+ self.init(timeIntervalSince1970: (utcTimeStamp as NSString).doubleValue / 1000 )
+ }
+ func utcTimeStamp() -> Int {
+ return Int(self.timeIntervalSince1970 * 1000)
+ }
+}
+
+internal extension String {
+ func isUuid() -> Bool {
+ return (NSUUID(UUIDString: self) != nil) ? true : false
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/usergrid/blob/7442c881/sdks/swift/Source/UsergridFileMetaData.swift
----------------------------------------------------------------------
diff --git a/sdks/swift/Source/UsergridFileMetaData.swift b/sdks/swift/Source/UsergridFileMetaData.swift
new file mode 100644
index 0000000..c3e7f52
--- /dev/null
+++ b/sdks/swift/Source/UsergridFileMetaData.swift
@@ -0,0 +1,114 @@
+//
+// UsergridFileMetaData.swift
+// UsergridSDK
+//
+// Created by Robert Walsh on 10/6/15.
+//
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. The ASF licenses this file to You
+ * under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License. For additional information regarding
+ * copyright in this work, please see the NOTICE file in the top level
+ * directory of this distribution.
+ *
+ */
+
+import Foundation
+
+/**
+`UsergridFileMetaData` is a helper class for dealing with reading `UsergridEntity` file meta data.
+*/
+public class UsergridFileMetaData : NSObject,NSCoding {
+
+ internal static let FILE_METADATA = "file-metadata"
+
+ // MARK: - Instance Properties -
+
+ /// The eTag.
+ public let eTag: String?
+
+ /// The check sum.
+ public let checkSum: String?
+
+ /// The content type associated with the file data.
+ public let contentType: String?
+
+ /// The content length of the file data.
+ public let contentLength: Int
+
+ /// The last modified time stamp.
+ public let lastModifiedTimeStamp: Int
+
+ /// The `NSDate` object corresponding to the last modified time stamp.
+ public let lastModifiedDate: NSDate?
+
+ // MARK: - Initialization -
+
+ /**
+ Designated initializer for `UsergridFileMetaData` objects.
+
+ - parameter fileMetaDataJSON: The file meta data JSON dictionary.
+
+ - returns: A new instance of `UsergridFileMetaData`.
+ */
+ public init(fileMetaDataJSON:[String:AnyObject]) {
+ self.eTag = fileMetaDataJSON["etag"] as? String
+ self.checkSum = fileMetaDataJSON["checksum"] as? String
+ self.contentType = fileMetaDataJSON["content-type"] as? String
+ self.contentLength = fileMetaDataJSON["content-length"] as? Int ?? 0
+ self.lastModifiedTimeStamp = fileMetaDataJSON["last-modified"] as? Int ?? 0
+
+ if self.lastModifiedTimeStamp > 0 {
+ self.lastModifiedDate = NSDate(utcTimeStamp: self.lastModifiedTimeStamp.description)
+ } else {
+ self.lastModifiedDate = nil
+ }
+ }
+
+ // MARK: - NSCoding -
+
+ /**
+ NSCoding protocol initializer.
+
+ - parameter aDecoder: The decoder.
+
+ - returns: A decoded `UsergridUser` object.
+ */
+ required public init?(coder aDecoder: NSCoder) {
+ self.eTag = aDecoder.decodeObjectForKey("etag") as? String
+ self.checkSum = aDecoder.decodeObjectForKey("checksum") as? String
+ self.contentType = aDecoder.decodeObjectForKey("content-type") as? String
+ self.contentLength = aDecoder.decodeIntegerForKey("content-length") ?? 0
+ self.lastModifiedTimeStamp = aDecoder.decodeIntegerForKey("last-modified") ?? 0
+
+ if self.lastModifiedTimeStamp > 0 {
+ self.lastModifiedDate = NSDate(utcTimeStamp: self.lastModifiedTimeStamp.description)
+ } else {
+ self.lastModifiedDate = nil
+ }
+ }
+
+ /**
+ NSCoding protocol encoder.
+
+ - parameter aCoder: The encoder.
+ */
+ public func encodeWithCoder(aCoder: NSCoder) {
+ aCoder.encodeObject(self.eTag, forKey: "etag")
+ aCoder.encodeObject(self.checkSum, forKey: "checksum")
+ aCoder.encodeObject(self.contentType, forKey: "content-type")
+ aCoder.encodeInteger(self.contentLength, forKey: "content-length")
+ aCoder.encodeInteger(self.lastModifiedTimeStamp, forKey: "last-modified")
+ }
+}
http://git-wip-us.apache.org/repos/asf/usergrid/blob/7442c881/sdks/swift/Source/UsergridKeychainHelpers.swift
----------------------------------------------------------------------
diff --git a/sdks/swift/Source/UsergridKeychainHelpers.swift b/sdks/swift/Source/UsergridKeychainHelpers.swift
new file mode 100644
index 0000000..2d7dee6
--- /dev/null
+++ b/sdks/swift/Source/UsergridKeychainHelpers.swift
@@ -0,0 +1,148 @@
+//
+// UsergridKeychainHelpers.swift
+// UsergridSDK
+//
+// Created by Robert Walsh on 12/21/15.
+//
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. The ASF licenses this file to You
+ * under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License. For additional information regarding
+ * copyright in this work, please see the NOTICE file in the top level
+ * directory of this distribution.
+ *
+ */
+
+import Foundation
+
+#if os(iOS) || os(tvOS) || os(watchOS)
+import UIKit
+#endif
+
+private let USERGRID_KEYCHAIN_NAME = "Usergrid"
+private let USERGRID_DEVICE_KEYCHAIN_SERVICE = "DeviceUUID"
+private let USERGRID_CURRENT_USER_KEYCHAIN_SERVICE = "CurrentUser"
+
+private func usergridGenericKeychainItem() -> [String:AnyObject] {
+ var keychainItem: [String:AnyObject] = [:]
+ keychainItem[kSecClass as String] = kSecClassGenericPassword as String
+ keychainItem[kSecAttrAccessible as String] = kSecAttrAccessibleAlways as String
+ keychainItem[kSecAttrAccount as String] = USERGRID_KEYCHAIN_NAME
+ return keychainItem
+}
+
+internal extension UsergridDevice {
+
+ static func deviceKeychainItem() -> [String:AnyObject] {
+ var keychainItem = usergridGenericKeychainItem()
+ keychainItem[kSecAttrService as String] = USERGRID_DEVICE_KEYCHAIN_SERVICE
+ return keychainItem
+ }
+
+ static func createNewUsergridKeychainUUID() -> String {
+
+ #if os(watchOS) || os(OSX)
+ let usergridUUID = NSUUID().UUIDString
+ #elseif os(iOS) || os(tvOS)
+ let usergridUUID = UIDevice.currentDevice().identifierForVendor?.UUIDString ?? NSUUID().UUIDString
+ #endif
+
+ var keychainItem = UsergridDevice.deviceKeychainItem()
+ keychainItem[kSecValueData as String] = (usergridUUID as NSString).dataUsingEncoding(NSUTF8StringEncoding)
+ SecItemAdd(keychainItem, nil)
+ return usergridUUID
+ }
+
+ static func usergridDeviceUUID() -> String {
+ var queryAttributes = UsergridDevice.deviceKeychainItem()
+ queryAttributes[kSecReturnData as String] = kCFBooleanTrue as Bool
+ queryAttributes[kSecReturnAttributes as String] = kCFBooleanTrue as Bool
+ var result: AnyObject?
+ let status = withUnsafeMutablePointer(&result) { SecItemCopyMatching(queryAttributes, UnsafeMutablePointer($0)) }
+ if status == errSecSuccess {
+ if let resultDictionary = result as? NSDictionary {
+ if let resultData = resultDictionary[kSecValueData as String] as? NSData {
+ if let keychainUUID = String(data: resultData, encoding: NSUTF8StringEncoding) {
+ return keychainUUID
+ }
+ }
+ }
+ }
+ return UsergridDevice.createNewUsergridKeychainUUID()
+ }
+}
+
+internal extension UsergridUser {
+
+ static func userKeychainItem(client:UsergridClient) -> [String:AnyObject] {
+ var keychainItem = usergridGenericKeychainItem()
+ keychainItem[kSecAttrService as String] = USERGRID_CURRENT_USER_KEYCHAIN_SERVICE + "." + client.appId + "." + client.orgId
+ return keychainItem
+ }
+
+ static func getCurrentUserFromKeychain(client:UsergridClient) -> UsergridUser? {
+ var queryAttributes = UsergridUser.userKeychainItem(client)
+ queryAttributes[kSecReturnData as String] = kCFBooleanTrue as Bool
+ queryAttributes[kSecReturnAttributes as String] = kCFBooleanTrue as Bool
+
+ var result: AnyObject?
+ let status = withUnsafeMutablePointer(&result) { SecItemCopyMatching(queryAttributes, UnsafeMutablePointer($0)) }
+ if status == errSecSuccess {
+ if let resultDictionary = result as? NSDictionary {
+ if let resultData = resultDictionary[kSecValueData as String] as? NSData {
+ if let currentUser = NSKeyedUnarchiver.unarchiveObjectWithData(resultData) as? UsergridUser {
+ return currentUser
+ }
+ }
+ }
+ }
+ return nil
+ }
+
+ static func saveCurrentUserKeychainItem(client:UsergridClient, currentUser:UsergridUser) {
+ var queryAttributes = UsergridUser.userKeychainItem(client)
+ queryAttributes[kSecReturnData as String] = kCFBooleanTrue as Bool
+ queryAttributes[kSecReturnAttributes as String] = kCFBooleanTrue as Bool
+
+ if SecItemCopyMatching(queryAttributes,nil) == errSecSuccess // Do we need to update keychain item or add a new one.
+ {
+ let attributesToUpdate = [kSecValueData as String:NSKeyedArchiver.archivedDataWithRootObject(currentUser)]
+ let updateStatus = SecItemUpdate(UsergridUser.userKeychainItem(client), attributesToUpdate)
+ if updateStatus != errSecSuccess {
+ print("Error updating current user data to keychain!")
+ }
+ }
+ else
+ {
+ var keychainItem = UsergridUser.userKeychainItem(client)
+ keychainItem[kSecValueData as String] = NSKeyedArchiver.archivedDataWithRootObject(currentUser)
+ let status = SecItemAdd(keychainItem, nil)
+ if status != errSecSuccess {
+ print("Error adding current user data to keychain!")
+ }
+ }
+ }
+
+ static func deleteCurrentUserKeychainItem(client:UsergridClient) {
+ var queryAttributes = UsergridUser.userKeychainItem(client)
+ queryAttributes[kSecReturnData as String] = kCFBooleanFalse as Bool
+ queryAttributes[kSecReturnAttributes as String] = kCFBooleanFalse as Bool
+ if SecItemCopyMatching(queryAttributes,nil) == errSecSuccess {
+ let deleteStatus = SecItemDelete(queryAttributes)
+ if deleteStatus != errSecSuccess {
+ print("Error deleting current user data to keychain!")
+ }
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/usergrid/blob/7442c881/sdks/swift/Source/UsergridQuery.swift
----------------------------------------------------------------------
diff --git a/sdks/swift/Source/UsergridQuery.swift b/sdks/swift/Source/UsergridQuery.swift
new file mode 100644
index 0000000..9dfd10a
--- /dev/null
+++ b/sdks/swift/Source/UsergridQuery.swift
@@ -0,0 +1,530 @@
+//
+// UsergridQuery.swift
+// UsergridSDK
+//
+// Created by Robert Walsh on 7/22/15.
+//
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. The ASF licenses this file to You
+ * under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License. For additional information regarding
+ * copyright in this work, please see the NOTICE file in the top level
+ * directory of this distribution.
+ *
+ */
+
+import Foundation
+
+/**
+ `UsergridQuery` is builder class used to construct filtered requests to Usergrid.
+
+ `UsergridQuery` objects are then passed to `UsergridClient` or `Usergrid` methods which support `UsergridQuery` as a parameter are .GET(), .PUT(), and .DELETE().
+ */
+public class UsergridQuery : NSObject,NSCopying {
+
+ // MARK: - Initialization -
+
+ /**
+ Desingated initializer for `UsergridQuery` objects.
+
+ - parameter collectionName: The collection name or `type` of entities you want to query.
+
+ - returns: A new instance of `UsergridQuery`.
+ */
+ public init(_ collectionName: String? = nil) {
+ self.collectionName = collectionName
+ }
+
+ // MARK: - NSCopying -
+
+ /**
+ See the NSCopying protocol.
+
+ - parameter zone: Ignored
+
+ - returns: Returns a new instance that’s a copy of the receiver.
+ */
+ public func copyWithZone(zone: NSZone) -> AnyObject {
+ let queryCopy = UsergridQuery(self.collectionName)
+ queryCopy.requirementStrings = NSArray(array:self.requirementStrings, copyItems: true) as! [String]
+ queryCopy.urlTerms = NSArray(array:self.urlTerms, copyItems: true) as! [String]
+ for (key,value) in self.orderClauses {
+ queryCopy.orderClauses[key] = value
+ }
+ queryCopy.limit = self.limit
+ queryCopy.cursor = self.cursor
+ return queryCopy
+ }
+
+ // MARK: - Building -
+
+ /**
+ Constructs the string that should be appeneded to the end of the URL as a query.
+
+ - parameter autoURLEncode: Automatically encode the constructed string.
+
+ - returns: The constructed URL query sting.
+ */
+ public func build(autoURLEncode: Bool = true) -> String {
+ return self.constructURLAppend(autoURLEncode)
+ }
+
+ // MARK: - Builder Methods -
+
+ /**
+ Contains. Query: where term contains 'val%'.
+
+ - parameter term: The term.
+ - parameter value: The value.
+
+ - returns: `Self`
+ */
+ public func containsString(term: String, value: String) -> Self { return self.containsWord(term, value: value) }
+
+ /**
+ Contains. Query: where term contains 'val%'.
+
+ - parameter term: The term.
+ - parameter value: The value.
+
+ - returns: `Self`
+ */
+ public func containsWord(term: String, value: String) -> Self { return self.addRequirement(term + UsergridQuery.SPACE + UsergridQuery.CONTAINS + UsergridQuery.SPACE + ((value.isUuid()) ? UsergridQuery.EMPTY_STRING : UsergridQuery.APOSTROPHE) + value + ((value.isUuid()) ? UsergridQuery.EMPTY_STRING : UsergridQuery.APOSTROPHE)) }
+
+ /**
+ Sort ascending. Query:. order by term asc.
+
+ - parameter term: The term.
+
+ - returns: `Self`
+ */
+ public func ascending(term: String) -> Self { return self.asc(term) }
+
+ /**
+ Sort ascending. Query:. order by term asc.
+
+ - parameter term: The term.
+
+ - returns: `Self`
+ */
+ public func asc(term: String) -> Self { return self.sort(term, sortOrder: UsergridQuerySortOrder.Asc) }
+
+ /**
+ Sort descending. Query: order by term desc
+
+ - parameter term: The term.
+
+ - returns: `Self`
+ */
+ public func descending(term: String) -> Self { return self.desc(term) }
+
+ /**
+ Sort descending. Query: order by term desc
+
+ - parameter term: The term.
+
+ - returns: `Self`
+ */
+ public func desc(term: String) -> Self { return self.sort(term, sortOrder: UsergridQuerySortOrder.Desc) }
+
+ /**
+ Filter (or Equal-to). Query: where term = 'value'.
+
+ - parameter term: The term.
+ - parameter value: The value.
+
+ - returns: `Self`
+ */
+ public func filter(term: String, value: AnyObject) -> Self { return self.eq(term, value: value) }
+
+ /**
+ Equal-to. Query: where term = 'value'.
+
+ - parameter term: The term.
+ - parameter value: The value.
+
+ - returns: `Self`
+ */
+ public func equals(term: String, value: AnyObject) -> Self { return self.eq(term, value: value) }
+
+ /**
+ Equal-to. Query: where term = 'value'.
+
+ - parameter term: The term.
+ - parameter value: The value.
+
+ - returns: `Self`
+ */
+ public func eq(term: String, value: AnyObject) -> Self { return self.addOperationRequirement(term, operation:.Equal, value: value) }
+
+ /**
+ Greater-than. Query: where term > 'value'.
+
+ - parameter term: The term.
+ - parameter value: The value.
+
+ - returns: `Self`
+ */
+ public func greaterThan(term: String, value: AnyObject) -> Self { return self.gt(term, value: value) }
+
+ /**
+ Greater-than. Query: where term > 'value'.
+
+ - parameter term: The term.
+ - parameter value: The value.
+
+ - returns: `Self`
+ */
+ public func gt(term: String, value: AnyObject) -> Self { return self.addOperationRequirement(term, operation:.GreaterThan, value: value) }
+
+ /**
+ Greater-than-or-equal-to. Query: where term >= 'value'.
+
+ - parameter term: The term.
+ - parameter value: The value.
+
+ - returns: `Self`
+ */
+ public func greaterThanOrEqual(term: String, value: AnyObject) -> Self { return self.gte(term, value: value) }
+
+ /**
+ Greater-than-or-equal-to. Query: where term >= 'value'.
+
+ - parameter term: The term.
+ - parameter value: The value.
+
+ - returns: `Self`
+ */
+ public func gte(term: String, value: AnyObject) -> Self { return self.addOperationRequirement(term, operation:.GreaterThanEqualTo, value: value) }
+
+ /**
+ Less-than. Query: where term < 'value'.
+
+ - parameter term: The term.
+ - parameter value: The value.
+
+ - returns: `Self`
+ */
+ public func lessThan(term: String, value: AnyObject) -> Self { return self.lt(term, value: value) }
+
+ /**
+ Less-than. Query: where term < 'value'.
+
+ - parameter term: The term.
+ - parameter value: The value.
+
+ - returns: `Self`
+ */
+ public func lt(term: String, value: AnyObject) -> Self { return self.addOperationRequirement(term, operation:.LessThan, value: value) }
+
+ /**
+ Less-than-or-equal-to. Query: where term <= 'value'.
+
+ - parameter term: The term.
+ - parameter value: The value.
+
+ - returns: `Self`
+ */
+ public func lessThanOrEqual(term: String, value: AnyObject) -> Self { return self.lte(term, value: value) }
+
+ /**
+ Less-than-or-equal-to. Query: where term <= 'value'.
+
+ - parameter term: The term.
+ - parameter value: The value.
+
+ - returns: `Self`
+ */
+ public func lte(term: String, value: AnyObject) -> Self { return self.addOperationRequirement(term, operation:.LessThanEqualTo, value: value) }
+
+ /**
+ Contains. Query: location within val of lat, long.
+
+ - parameter distance: The distance from the latitude and longitude.
+ - parameter latitude: The latitude.
+ - parameter longitude: The longitude.
+
+ - returns: `Self`
+ */
+ public func locationWithin(distance: Float, latitude: Float, longitude: Float) -> Self {
+ return self.addRequirement(UsergridQuery.LOCATION + UsergridQuery.SPACE + UsergridQuery.WITHIN + UsergridQuery.SPACE + distance.description + UsergridQuery.SPACE + UsergridQuery.OF + UsergridQuery.SPACE + latitude.description + UsergridQuery.COMMA + longitude.description )
+ }
+
+ /**
+ Joining operation to combine conditional queries.
+
+ - returns: `Self`
+ */
+ public func or() -> Self {
+ if !self.requirementStrings.first!.isEmpty {
+ self.requirementStrings.insert(UsergridQuery.OR, atIndex: 0)
+ self.requirementStrings.insert(UsergridQuery.EMPTY_STRING, atIndex: 0)
+ }
+ return self
+ }
+
+ /**
+ Not operation for conditional queries.
+
+ - returns: `Self`
+ */
+ public func not() -> Self {
+ if !self.requirementStrings.first!.isEmpty {
+ self.requirementStrings.insert(UsergridQuery.NOT, atIndex: 0)
+ self.requirementStrings.insert(UsergridQuery.EMPTY_STRING, atIndex: 0)
+ }
+ return self
+ }
+
+ /**
+ Sort. Query: order by term `sortOrder`
+
+ - parameter term: The term.
+ - parameter sortOrder: The order.
+
+ - returns: `Self`
+ */
+ public func sort(term: String, sortOrder: UsergridQuerySortOrder) -> Self {
+ self.orderClauses[term] = sortOrder
+ return self
+ }
+
+ /**
+ Sets the collection name.
+
+ - parameter collectionName: The new collection name.
+
+ - returns: `Self`
+ */
+ public func collection(collectionName: String) -> Self {
+ self.collectionName = collectionName
+ return self
+ }
+
+ /**
+ Sets the limit on the query. Default limit is 10.
+
+ - parameter limit: The limit.
+
+ - returns: `Self`
+ */
+ public func limit(limit: Int) -> Self {
+ self.limit = limit
+ return self
+ }
+
+ /**
+ Adds a preconstructed query string as a requirement onto the query.
+
+ - parameter value: The query string.
+
+ - returns: `Self`
+ */
+ public func ql(value: String) -> Self {
+ return self.addRequirement(value)
+ }
+
+ /**
+ Sets the cursor of the query used internally by Usergrid's APIs.
+
+ - parameter value: The cursor.
+
+ - returns: `Self`
+ */
+ public func cursor(value: String?) -> Self {
+ self.cursor = value
+ return self
+ }
+
+ /**
+ Adds a URL term that will be added next to the query string when constructing the URL append.
+
+ - parameter term: The term.
+ - parameter equalsValue: The value.
+
+ - returns: `Self`
+ */
+ public func urlTerm(term: String, equalsValue: String) -> Self {
+ if (term as NSString).isEqualToString(UsergridQuery.QL) {
+ self.ql(equalsValue)
+ } else {
+ self.urlTerms.append(term + UsergridQueryOperator.Equal.stringValue + equalsValue)
+ }
+ return self
+ }
+
+ /**
+ Adds a string requirement to the query.
+
+ - parameter term: The term.
+ - parameter operation: The operation.
+ - parameter stringValue: The string value.
+
+ - returns: `Self`
+ */
+ public func addOperationRequirement(term: String, operation: UsergridQueryOperator, stringValue: String) -> Self {
+ return self.addOperationRequirement(term,operation:operation,value:stringValue)
+ }
+
+ /**
+ Adds a integer requirement to the query.
+
+ - parameter term: The term.
+ - parameter operation: The operation.
+ - parameter intValue: The integer value.
+
+ - returns: `Self`
+ */
+ public func addOperationRequirement(term: String, operation: UsergridQueryOperator, intValue: Int) -> Self {
+ return self.addOperationRequirement(term,operation:operation,value:intValue)
+ }
+
+ private func addRequirement(requirement: String) -> Self {
+ var requirementString: String = self.requirementStrings.removeAtIndex(0)
+ if !requirementString.isEmpty {
+ requirementString += UsergridQuery.SPACE + UsergridQuery.AND + UsergridQuery.SPACE
+ }
+ requirementString += requirement
+ self.requirementStrings.insert(requirementString, atIndex: 0)
+ return self
+ }
+
+ private func addOperationRequirement(term: String, operation: UsergridQueryOperator, value: AnyObject) -> Self {
+ if value is String {
+ return self.addRequirement(term + UsergridQuery.SPACE + operation.stringValue + UsergridQuery.SPACE + ((value.description.isUuid()) ? UsergridQuery.EMPTY_STRING : UsergridQuery.APOSTROPHE) + value.description + ((value.description.isUuid()) ? UsergridQuery.EMPTY_STRING : UsergridQuery.APOSTROPHE) )
+ } else {
+ return self.addRequirement(term + UsergridQuery.SPACE + operation.stringValue + UsergridQuery.SPACE + value.description)
+ }
+ }
+
+ private func constructOrderByString() -> String {
+ var orderByString = UsergridQuery.EMPTY_STRING
+ if !self.orderClauses.isEmpty {
+ var combinedClausesArray: [String] = []
+ for (key,value) in self.orderClauses {
+ combinedClausesArray.append(key + UsergridQuery.SPACE + value.stringValue)
+ }
+ for index in 0..<combinedClausesArray.count {
+ if index > 0 {
+ orderByString += UsergridQuery.COMMA
+ }
+ orderByString += combinedClausesArray[index]
+ }
+ if !orderByString.isEmpty {
+ orderByString = UsergridQuery.SPACE + UsergridQuery.ORDER_BY + UsergridQuery.SPACE + orderByString
+ }
+ }
+ return orderByString
+ }
+
+ private func constructURLTermsString() -> String {
+ return (self.urlTerms as NSArray).componentsJoinedByString(UsergridQuery.AMPERSAND)
+ }
+
+ private func constructRequirementString() -> String {
+ var requirementsString = UsergridQuery.EMPTY_STRING
+ var requirementStrings = self.requirementStrings
+
+ // If the first requirement is empty lets remove it.
+ if let firstRequirement = requirementStrings.first where firstRequirement.isEmpty {
+ requirementStrings.removeFirst()
+ }
+
+ // If the first requirement now is a conditional separator then we should remove it so its not placed at the end of the constructed string.
+ if let firstRequirement = requirementStrings.first where firstRequirement == UsergridQuery.OR || firstRequirement == UsergridQuery.NOT {
+ requirementStrings.removeFirst()
+ }
+
+ requirementsString = (requirementStrings.reverse() as NSArray).componentsJoinedByString(UsergridQuery.SPACE)
+ return requirementsString
+ }
+
+ private func constructURLAppend(autoURLEncode: Bool = true) -> String {
+ var urlAppend = UsergridQuery.EMPTY_STRING
+ if self.limit != UsergridQuery.LIMIT_DEFAULT {
+ urlAppend += "\(UsergridQuery.LIMIT)=\(self.limit.description)"
+ }
+ let urlTermsString = self.constructURLTermsString()
+ if !urlTermsString.isEmpty {
+ if !urlAppend.isEmpty {
+ urlAppend += UsergridQuery.AMPERSAND
+ }
+ urlAppend += urlTermsString
+ }
+ if let cursorString = self.cursor where !cursorString.isEmpty {
+ if !urlAppend.isEmpty {
+ urlAppend += UsergridQuery.AMPERSAND
+ }
+ urlAppend += "\(UsergridQuery.CURSOR)=\(cursorString)"
+ }
+
+ var requirementsString = self.constructRequirementString()
+ let orderByString = self.constructOrderByString()
+ if !orderByString.isEmpty {
+ requirementsString += orderByString
+ }
+ if !requirementsString.isEmpty {
+ if autoURLEncode {
+ if let encodedRequirementsString = requirementsString.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLQueryAllowedCharacterSet()) {
+ requirementsString = encodedRequirementsString
+ }
+ }
+ if !urlAppend.isEmpty {
+ urlAppend += UsergridQuery.AMPERSAND
+ }
+ urlAppend += "\(UsergridQuery.QL)=\(requirementsString)"
+ }
+
+ if !urlAppend.isEmpty {
+ urlAppend = "\(UsergridQuery.QUESTION_MARK)\(urlAppend)"
+ }
+ return urlAppend
+ }
+
+ private(set) var collectionName: String? = nil
+ private(set) var cursor: String? = nil
+ private(set) var limit: Int = UsergridQuery.LIMIT_DEFAULT
+
+ private(set) var requirementStrings: [String] = [UsergridQuery.EMPTY_STRING]
+ private(set) var orderClauses: [String:UsergridQuerySortOrder] = [:]
+ private(set) var urlTerms: [String] = []
+
+ private static let LIMIT_DEFAULT = 10
+ private static let AMPERSAND = "&"
+ private static let AND = "and"
+ private static let APOSTROPHE = "'"
+ private static let COMMA = ","
+ private static let CONTAINS = "contains"
+ private static let CURSOR = "cursor"
+ private static let EMPTY_STRING = ""
+ private static let IN = "in"
+ private static let LIMIT = "limit"
+ private static let LOCATION = "location";
+ private static let NOT = "not"
+ private static let OF = "of"
+ private static let OR = "or"
+ private static let ORDER_BY = "order by"
+ private static let QL = "ql"
+ private static let QUESTION_MARK = "?"
+ private static let SPACE = " "
+ private static let WITHIN = "within"
+
+ internal static let ASC = "asc"
+ internal static let DESC = "desc"
+ internal static let EQUAL = "="
+ internal static let GREATER_THAN = ">"
+ internal static let GREATER_THAN_EQUAL_TO = ">="
+ internal static let LESS_THAN = "<"
+ internal static let LESS_THAN_EQUAL_TO = "<="
+}
http://git-wip-us.apache.org/repos/asf/usergrid/blob/7442c881/sdks/swift/Source/UsergridRequest.swift
----------------------------------------------------------------------
diff --git a/sdks/swift/Source/UsergridRequest.swift b/sdks/swift/Source/UsergridRequest.swift
new file mode 100644
index 0000000..dd1f561
--- /dev/null
+++ b/sdks/swift/Source/UsergridRequest.swift
@@ -0,0 +1,245 @@
+//
+// UsergridRequest.swift
+// UsergridSDK
+//
+// Created by Robert Walsh on 1/12/16.
+//
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. The ASF licenses this file to You
+ * under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License. For additional information regarding
+ * copyright in this work, please see the NOTICE file in the top level
+ * directory of this distribution.
+ *
+ */
+
+import Foundation
+
+/**
+ The UsergridRequest class incapsulates the properties that all requests made by the SDK have in common.
+
+ This class is also functions to create `NSURLRequest` objects based on the properties of the class.
+*/
+public class UsergridRequest : NSObject {
+
+ // MARK: - Instance Properties -
+
+ /// The HTTP method.
+ public let method: UsergridHttpMethod
+
+ /// The base URL.
+ public let baseUrl: String
+
+ /// The paths to append to the base URL.
+ public let paths: [String]?
+
+ /// The query to append to the URL.
+ public let query: UsergridQuery?
+
+ /// The auth that will be used.
+ public let auth: UsergridAuth?
+
+ /// The headers to add to the request.
+ public let headers: [String:String]?
+
+ /// The JSON body that will be set on the request. Can be either a valid JSON object or NSData.
+ public let jsonBody: AnyObject?
+
+ /// The query params that will be set on the request.
+ public let queryParams: [String:String]?
+
+ // MARK: - Initialization -
+
+ /**
+ The designated initializer for `UsergridRequest` objects.
+
+ - parameter method: The HTTP method.
+ - parameter baseUrl: The base URL.
+ - parameter paths: The optional paths to append to the base URL.
+ - parameter query: The optional query to append to the URL.
+ - parameter auth: The optional `UsergridAuth` that will be used in the Authorization header.
+ - parameter headers: The optional headers.
+ - parameter jsonBody: The optional JSON body. Can be either a valid JSON object or NSData.
+ - parameter queryParams: The optional query params to be appended to the request url.
+
+ - returns: A new instance of `UsergridRequest`.
+ */
+ public init(method:UsergridHttpMethod,
+ baseUrl:String,
+ paths:[String]? = nil,
+ query:UsergridQuery? = nil,
+ auth:UsergridAuth? = nil,
+ headers:[String:String]? = nil,
+ jsonBody:AnyObject? = nil,
+ queryParams:[String:String]? = nil) {
+ self.method = method
+ self.baseUrl = baseUrl
+ self.paths = paths
+ self.auth = auth
+ self.headers = headers
+ self.query = query
+ self.queryParams = queryParams
+ if let body = jsonBody where (body is NSData || NSJSONSerialization.isValidJSONObject(body)) {
+ self.jsonBody = body
+ } else {
+ self.jsonBody = nil
+ }
+ }
+
+ // MARK: - Instance Methods -
+
+ /**
+ Constructs a `NSURLRequest` object with this objects instance properties.
+
+ - returns: An initialized and configured `NSURLRequest` object.
+ */
+ public func buildNSURLRequest() -> NSURLRequest {
+ let request = NSMutableURLRequest(URL: self.buildURL())
+ request.HTTPMethod = self.method.stringValue
+ self.applyHeaders(request)
+ self.applyBody(request)
+ self.applyAuth(request)
+ return request
+ }
+
+ private func buildURL() -> NSURL {
+ var constructedURLString = self.baseUrl
+ if let appendingPaths = self.paths {
+ for pathToAppend in appendingPaths {
+ if let encodedPath = pathToAppend.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLPathAllowedCharacterSet()) {
+ constructedURLString = "\(constructedURLString)\(UsergridRequest.FORWARD_SLASH)\(encodedPath)"
+ }
+ }
+ }
+ if let queryToAppend = self.query {
+ let appendFromQuery = queryToAppend.build()
+ if !appendFromQuery.isEmpty {
+ constructedURLString = "\(constructedURLString)\(UsergridRequest.FORWARD_SLASH)\(appendFromQuery)"
+ }
+ }
+ if let queryParams = self.queryParams {
+ if let components = NSURLComponents(string: constructedURLString) {
+ components.queryItems = components.queryItems ?? []
+ for (key, value) in queryParams {
+ let q: NSURLQueryItem = NSURLQueryItem(name: key, value: value)
+ components.queryItems!.append(q)
+ }
+ constructedURLString = components.string!
+ }
+ }
+ return NSURL(string:constructedURLString)!
+ }
+
+ private func applyHeaders(request:NSMutableURLRequest) {
+ if let httpHeaders = self.headers {
+ for (key,value) in httpHeaders {
+ request.setValue(value, forHTTPHeaderField: key)
+ }
+ }
+ }
+
+ private func applyBody(request:NSMutableURLRequest) {
+ if let jsonBody = self.jsonBody, httpBody = UsergridRequest.jsonBodyToData(jsonBody) {
+ request.HTTPBody = httpBody
+ request.setValue(String(format: "%lu", httpBody.length), forHTTPHeaderField: UsergridRequest.CONTENT_LENGTH)
+ }
+ }
+
+ private func applyAuth(request:NSMutableURLRequest) {
+ if let usergridAuth = self.auth {
+ if usergridAuth.isValid, let accessToken = usergridAuth.accessToken {
+ request.setValue("\(UsergridRequest.BEARER) \(accessToken)", forHTTPHeaderField: UsergridRequest.AUTHORIZATION)
+ }
+ }
+ }
+
+ private static func jsonBodyToData(jsonBody:AnyObject) -> NSData? {
+ if let jsonBodyAsNSData = jsonBody as? NSData {
+ return jsonBodyAsNSData
+ } else {
+ var jsonBodyAsNSData: NSData? = nil
+ do { jsonBodyAsNSData = try NSJSONSerialization.dataWithJSONObject(jsonBody, options: NSJSONWritingOptions(rawValue: 0)) }
+ catch { print(error) }
+ return jsonBodyAsNSData
+ }
+ }
+
+ private static let AUTHORIZATION = "Authorization"
+ private static let ACCESS_TOKEN = "access_token"
+ private static let APPLICATION_JSON = "application/json"
+ private static let BEARER = "Bearer"
+ private static let CONTENT_LENGTH = "Content-Length"
+ private static let CONTENT_TYPE = "Content-Type"
+ private static let FORWARD_SLASH = "/"
+
+ static let JSON_CONTENT_TYPE_HEADER = [UsergridRequest.CONTENT_TYPE:UsergridRequest.APPLICATION_JSON]
+}
+
+/**
+ The `UsergridRequest` sub class which is used for uploading assets.
+ */
+public class UsergridAssetUploadRequest: UsergridRequest {
+
+ // MARK: - Instance Properties -
+
+ /// The asset to use for uploading.
+ public let asset: UsergridAsset
+
+ /// A constructed multipart http body for requests to upload.
+ public var multiPartHTTPBody: NSData {
+ let httpBodyString = UsergridAssetUploadRequest.MULTIPART_START +
+ "\(UsergridAssetUploadRequest.CONTENT_DISPOSITION):\(UsergridAssetUploadRequest.FORM_DATA); name=file; filename=\(self.asset.filename)\r\n" +
+ "\(UsergridRequest.CONTENT_TYPE): \(self.asset.contentType)\r\n\r\n" as NSString
+
+ let httpBody = NSMutableData()
+ httpBody.appendData(httpBodyString.dataUsingEncoding(NSUTF8StringEncoding)!)
+ httpBody.appendData(self.asset.data)
+ httpBody.appendData(UsergridAssetUploadRequest.MULTIPART_END.dataUsingEncoding(NSUTF8StringEncoding)!)
+
+ return httpBody
+ }
+
+ // MARK: - Initialization -
+
+ /**
+ The designated initializer for `UsergridAssetUploadRequest` objects.
+
+ - parameter baseUrl: The base URL.
+ - parameter paths: The optional paths to append to the base URL.
+ - parameter auth: The optional `UsergridAuth` that will be used in the Authorization header.
+ - parameter asset: The asset to upload.
+
+ - returns: A new instance of `UsergridRequest`.
+ */
+ public init(baseUrl:String,
+ paths:[String]? = nil,
+ auth:UsergridAuth? = nil,
+ asset:UsergridAsset) {
+ self.asset = asset
+ super.init(method: .Put, baseUrl: baseUrl, paths: paths, auth: auth)
+ }
+
+ private override func applyHeaders(request: NSMutableURLRequest) {
+ super.applyHeaders(request)
+ request.setValue(UsergridAssetUploadRequest.ASSET_UPLOAD_CONTENT_HEADER, forHTTPHeaderField: UsergridRequest.CONTENT_TYPE)
+ request.setValue(String(format: "%lu", self.multiPartHTTPBody.length), forHTTPHeaderField: UsergridRequest.CONTENT_LENGTH)
+ }
+
+ private static let ASSET_UPLOAD_BOUNDARY = "usergrid-asset-upload-boundary"
+ private static let ASSET_UPLOAD_CONTENT_HEADER = "multipart/form-data; boundary=\(UsergridAssetUploadRequest.ASSET_UPLOAD_BOUNDARY)"
+ private static let CONTENT_DISPOSITION = "Content-Disposition"
+ private static let MULTIPART_START = "--\(UsergridAssetUploadRequest.ASSET_UPLOAD_BOUNDARY)\r\n"
+ private static let MULTIPART_END = "\r\n--\(UsergridAssetUploadRequest.ASSET_UPLOAD_BOUNDARY)--\r\n" as NSString
+ private static let FORM_DATA = "form-data"
+}
http://git-wip-us.apache.org/repos/asf/usergrid/blob/7442c881/sdks/swift/Source/UsergridRequestManager.swift
----------------------------------------------------------------------
diff --git a/sdks/swift/Source/UsergridRequestManager.swift b/sdks/swift/Source/UsergridRequestManager.swift
new file mode 100644
index 0000000..ccd41e5
--- /dev/null
+++ b/sdks/swift/Source/UsergridRequestManager.swift
@@ -0,0 +1,156 @@
+//
+// UsergridRequestManager.swift
+// UsergridSDK
+//
+// Created by Robert Walsh on 9/22/15.
+//
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. The ASF licenses this file to You
+ * under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License. For additional information regarding
+ * copyright in this work, please see the NOTICE file in the top level
+ * directory of this distribution.
+ *
+ */
+
+import Foundation
+
+final class UsergridRequestManager {
+
+ unowned let client: UsergridClient
+
+ let session: NSURLSession
+
+ var sessionDelegate : UsergridSessionDelegate {
+ return session.delegate as! UsergridSessionDelegate
+ }
+
+ init(client:UsergridClient) {
+ self.client = client
+
+ let config = NSURLSessionConfiguration.defaultSessionConfiguration()
+
+ #if os(tvOS)
+ config.HTTPAdditionalHeaders = ["User-Agent": "usergrid-tvOS/v\(UsergridSDKVersion)"]
+ #elseif os(iOS)
+ config.HTTPAdditionalHeaders = ["User-Agent": "usergrid-ios/v\(UsergridSDKVersion)"]
+ #elseif os(watchOS)
+ config.HTTPAdditionalHeaders = ["User-Agent": "usergrid-watchOS/v\(UsergridSDKVersion)"]
+ #elseif os(OSX)
+ config.HTTPAdditionalHeaders = ["User-Agent": "usergrid-osx/v\(UsergridSDKVersion)"]
+ #endif
+
+ self.session = NSURLSession(configuration: config,
+ delegate: UsergridSessionDelegate(),
+ delegateQueue: NSOperationQueue.mainQueue())
+ }
+
+ deinit {
+ session.invalidateAndCancel()
+ }
+
+ func performRequest(request:UsergridRequest, completion:UsergridResponseCompletion?) {
+ session.dataTaskWithRequest(request.buildNSURLRequest()) { [weak self] (data, response, error) -> Void in
+ completion?(response: UsergridResponse(client:self?.client, data: data, response: response as? NSHTTPURLResponse, error: error))
+ }.resume()
+ }
+}
+
+
+// MARK: - Authentication -
+extension UsergridRequestManager {
+
+ static func getTokenAndExpiryFromResponseJSON(jsonDict:[String:AnyObject]) -> (String?,NSDate?) {
+ var token: String? = nil
+ var expiry: NSDate? = nil
+ if let accessToken = jsonDict["access_token"] as? String {
+ token = accessToken
+ }
+ if let expiresIn = jsonDict["expires_in"] as? Int {
+ let expiresInAdjusted = expiresIn - 5000
+ expiry = NSDate(timeIntervalSinceNow: Double(expiresInAdjusted))
+ }
+ return (token,expiry)
+ }
+
+ func performUserAuthRequest(userAuth:UsergridUserAuth, request:UsergridRequest, completion:UsergridUserAuthCompletionBlock?) {
+ session.dataTaskWithRequest(request.buildNSURLRequest()) { (data, response, error) -> Void in
+ let dataAsJSON = try! NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.MutableContainers)
+ if let jsonDict = dataAsJSON as? [String:AnyObject] {
+ let tokenAndExpiry = UsergridRequestManager.getTokenAndExpiryFromResponseJSON(jsonDict)
+ userAuth.accessToken = tokenAndExpiry.0
+ userAuth.expiry = tokenAndExpiry.1
+
+ var user: UsergridUser?
+ if let userDict = jsonDict[UsergridUser.USER_ENTITY_TYPE] as? [String:AnyObject] {
+ if let createdUser = UsergridEntity.entity(jsonDict: userDict) as? UsergridUser {
+ createdUser.auth = userAuth
+ user = createdUser
+ }
+ }
+ if let createdUser = user {
+ completion?(auth: userAuth, user:createdUser, error: nil)
+ } else {
+ let error = UsergridResponseError(jsonDictionary: jsonDict) ?? UsergridResponseError(errorName: "Auth Failed.", errorDescription: "Error Description: \(error?.localizedDescription).")
+ completion?(auth: userAuth, user:nil, error:error)
+ }
+ } else {
+ let error = UsergridResponseError(errorName: "Auth Failed.", errorDescription: "Error Description: \(error?.localizedDescription).")
+ completion?(auth: userAuth, user:nil, error: error)
+ }
+ }.resume()
+ }
+
+ func performAppAuthRequest(appAuth: UsergridAppAuth, request: UsergridRequest, completion: UsergridAppAuthCompletionBlock?) {
+ session.dataTaskWithRequest(request.buildNSURLRequest()) { (data, response, error) -> Void in
+ let dataAsJSON = try! NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.MutableContainers)
+ if let jsonDict = dataAsJSON as? [String:AnyObject] {
+ let tokenAndExpiry = UsergridRequestManager.getTokenAndExpiryFromResponseJSON(jsonDict)
+ appAuth.accessToken = tokenAndExpiry.0
+ appAuth.expiry = tokenAndExpiry.1
+ completion?(auth: appAuth, error: nil)
+ } else {
+ let error = UsergridResponseError(errorName: "Auth Failed.", errorDescription: "Error Description: \(error?.localizedDescription).")
+ completion?(auth: nil, error: error)
+ }
+ }.resume()
+ }
+}
+
+// MARK: - Asset Management -
+extension UsergridRequestManager {
+
+ func performAssetDownload(contentType:String, usergridRequest:UsergridRequest, progress: UsergridAssetRequestProgress? = nil, completion:UsergridAssetDownloadCompletion? = nil) {
+ let downloadTask = session.downloadTaskWithRequest(usergridRequest.buildNSURLRequest())
+ let requestWrapper = UsergridAssetRequestWrapper(session: self.session, sessionTask: downloadTask, progress: progress) { (request) -> Void in
+ if let assetData = request.responseData where assetData.length > 0 {
+ let asset = UsergridAsset(data: assetData, contentType: contentType)
+ completion?(asset: asset, error:nil)
+ } else {
+ completion?(asset: nil, error: "Downloading asset failed. No data was recieved.")
+ }
+ }
+ self.sessionDelegate.addRequestDelegate(requestWrapper.sessionTask, requestWrapper:requestWrapper)
+ requestWrapper.sessionTask.resume()
+ }
+
+ func performAssetUpload(usergridRequest:UsergridAssetUploadRequest, progress:UsergridAssetRequestProgress? = nil, completion: UsergridAssetUploadCompletion? = nil) {
+ let uploadTask = session.uploadTaskWithRequest(usergridRequest.buildNSURLRequest(), fromData: usergridRequest.multiPartHTTPBody)
+ let requestWrapper = UsergridAssetRequestWrapper(session: self.session, sessionTask: uploadTask, progress: progress) { [weak self] (request) -> Void in
+ completion?(response: UsergridResponse(client: self?.client, data: request.responseData, response: request.response as? NSHTTPURLResponse, error: request.error),asset:usergridRequest.asset,error:nil)
+ }
+ self.sessionDelegate.addRequestDelegate(requestWrapper.sessionTask, requestWrapper:requestWrapper)
+ requestWrapper.sessionTask.resume()
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/usergrid/blob/7442c881/sdks/swift/Source/UsergridResponse.swift
----------------------------------------------------------------------
diff --git a/sdks/swift/Source/UsergridResponse.swift b/sdks/swift/Source/UsergridResponse.swift
new file mode 100644
index 0000000..012c82f
--- /dev/null
+++ b/sdks/swift/Source/UsergridResponse.swift
@@ -0,0 +1,203 @@
+//
+// UsergridResponse.swift
+// UsergridSDK
+//
+// Created by Robert Walsh on 9/2/15.
+//
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. The ASF licenses this file to You
+ * under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License. For additional information regarding
+ * copyright in this work, please see the NOTICE file in the top level
+ * directory of this distribution.
+ *
+ */
+
+import Foundation
+
+/// The completion block used in for most `UsergridClient` requests.
+public typealias UsergridResponseCompletion = (response: UsergridResponse) -> Void
+
+/**
+`UsergridResponse` is the core class that handles both successful and unsuccessful HTTP responses from Usergrid.
+
+If a request is successful, any entities returned in the response will be automatically parsed into `UsergridEntity` objects and pushed to the `entities` property.
+
+If a request fails, the `errorName` and `errorDescription` will contain information about the problem encountered.
+*/
+public class UsergridResponse: NSObject {
+
+ // MARK: - Instance Properties -
+
+ /// The client that was responsible for the request.
+ public weak var client: UsergridClient?
+
+ /// The raw response JSON.
+ internal(set) public var responseJSON: [String:AnyObject]?
+
+ /// The query used on the request.
+ internal(set) public var query: UsergridQuery?
+
+ /// The cursor from the response.
+ internal(set) public var cursor: String?
+
+ /// The entities created from the response JSON.
+ internal(set) public var entities: [UsergridEntity]?
+
+ /// The response headers.
+ internal(set) public var headers: [String:String]?
+
+ /// The response status code.
+ internal(set) public var statusCode: Int?
+
+ /// The error object containing error information if one occurred.
+ internal(set) public var error: UsergridResponseError?
+
+ /// Returns true if the HTTP status code from the response is less than 400.
+ public var ok : Bool {
+ var isOk = false
+ if let statusCode = self.statusCode {
+ isOk = (statusCode < 400)
+ }
+ return isOk
+ }
+
+ /// The count of `entities`.
+ public var count: Int { return self.entities?.count ?? 0 }
+
+ /// The first entity in `entities`.
+ public var first: UsergridEntity? { return self.entities?.first }
+
+ /// The last entity in `entities`.
+ public var last: UsergridEntity? { return self.entities?.last }
+
+ /// The first entity in `entities`.
+ public var entity: UsergridEntity? { return self.first }
+
+ /// The `UsergridUser` entity.
+ public var user: UsergridUser? { return self.entities?.first as? UsergridUser }
+
+ /// An array of `UsergridUser` entities.
+ public var users: [UsergridUser]? { return self.entities as? [UsergridUser] }
+
+ /// Does the response have a cursor.
+ public var hasNextPage: Bool { return self.cursor != nil }
+
+ /// The string value.
+ public var stringValue : String? {
+ if let responseJSON = self.responseJSON {
+ return NSString(data: try! NSJSONSerialization.dataWithJSONObject(responseJSON, options: .PrettyPrinted), encoding: NSASCIIStringEncoding) as? String
+ } else {
+ return error?.description
+ }
+ }
+
+ /// The description.
+ public override var description : String {
+ return "Response Description: \(stringValue)."
+ }
+
+ /// The debug description.
+ public override var debugDescription : String {
+ return "Properties of Entity: \(stringValue)."
+ }
+
+ // MARK: - Initialization -
+
+ /**
+ Designated initializer for `UsergridResponse` objects that contain errors.
+
+ These types of responses are usually created because request conditions are not met.
+
+ - parameter client: The client responsible for the request.
+ - parameter errorName: The error name.
+ - parameter errorDescription: The error description.
+
+ - returns: A new instance of `UsergridResponse`.
+ */
+ public init(client: UsergridClient?, errorName: String, errorDescription: String) {
+ self.client = client
+ self.error = UsergridResponseError(errorName: errorName, errorDescription: errorDescription, exception: nil)
+ }
+
+ /**
+ Designated initializer for `UsergridResponse` objects finished but still may contain errors.
+
+ - parameter client: The client responsible for the request.
+ - parameter data: The response data.
+ - parameter response: The `NSHTTPURLResponse` object.
+ - parameter error: The `NSError` object.
+ - parameter query: The query when making the request.
+
+ - returns: A new instance of `UsergridResponse`.
+ */
+ public init(client:UsergridClient?, data:NSData?, response:NSHTTPURLResponse?, error:NSError?, query:UsergridQuery? = nil) {
+ self.client = client
+ self.statusCode = response?.statusCode
+ self.headers = response?.allHeaderFields as? [String:String]
+
+ if let sessionError = error {
+ self.error = UsergridResponseError(errorName: sessionError.domain, errorDescription: sessionError.localizedDescription)
+ }
+
+ if let responseQuery = query {
+ self.query = responseQuery.copy() as? UsergridQuery
+ }
+
+ if let jsonData = data {
+ do {
+ let dataAsJSON = try NSJSONSerialization.JSONObjectWithData(jsonData, options: NSJSONReadingOptions.MutableContainers)
+ if let jsonDict = dataAsJSON as? [String:AnyObject] {
+ self.responseJSON = jsonDict
+ if let responseError = UsergridResponseError(jsonDictionary: jsonDict) {
+ self.error = responseError
+ } else {
+ if let entitiesJSONArray = jsonDict[UsergridResponse.ENTITIES] as? [[String:AnyObject]] where entitiesJSONArray.count > 0 {
+ self.entities = UsergridEntity.entities(jsonArray: entitiesJSONArray)
+ }
+ if let cursor = jsonDict[UsergridResponse.CURSOR] as? String where !cursor.isEmpty {
+ self.cursor = cursor
+ }
+ }
+ }
+ } catch {
+ print(error)
+ }
+ }
+ }
+
+ // MARK: - Instance Methods -
+
+ /**
+ Attempts to load the next page of `UsergridEntity` objects.
+
+ This requires a `cursor` to be valid as well as a `path` key within the response JSON.
+
+ - parameter completion: The completion block that is called once the request for the next page has finished.
+ */
+ public func loadNextPage(completion: UsergridResponseCompletion) {
+ if self.hasNextPage, let type = (self.responseJSON?["path"] as? NSString)?.lastPathComponent {
+ if let query = self.query?.copy() as? UsergridQuery {
+ self.client?.GET(type, query: query.cursor(self.cursor), completion:completion)
+ } else {
+ self.client?.GET(type, query: UsergridQuery(type).cursor(self.cursor), completion:completion)
+ }
+ } else {
+ completion(response: UsergridResponse(client: self.client, errorName: "No next page.", errorDescription: "No next page was found."))
+ }
+ }
+
+ static let CURSOR = "cursor"
+ static let ENTITIES = "entities"
+}
http://git-wip-us.apache.org/repos/asf/usergrid/blob/7442c881/sdks/swift/Source/UsergridResponseError.swift
----------------------------------------------------------------------
diff --git a/sdks/swift/Source/UsergridResponseError.swift b/sdks/swift/Source/UsergridResponseError.swift
new file mode 100644
index 0000000..eda8a30
--- /dev/null
+++ b/sdks/swift/Source/UsergridResponseError.swift
@@ -0,0 +1,90 @@
+//
+// UsergridResponseError.swift
+// UsergridSDK
+//
+// Created by Robert Walsh on 1/8/16.
+//
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. The ASF licenses this file to You
+ * under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License. For additional information regarding
+ * copyright in this work, please see the NOTICE file in the top level
+ * directory of this distribution.
+ *
+ */
+
+import Foundation
+
+/// A standard error object that contains details about a request failure.
+public class UsergridResponseError: NSObject {
+
+ // MARK: - Instance Properties -
+
+ /// The error's name.
+ public let errorName : String
+
+ /// The error's description.
+ public let errorDescription: String
+
+ /// The exception.
+ public var exception: String?
+
+ /// The description.
+ public override var description : String {
+ return "Error Name: \(errorName). Error Description: \(errorDescription). Exception: \(exception)."
+ }
+
+ /// The debug description.
+ public override var debugDescription : String {
+ return "Error Name: \(errorName). Error Description: \(errorDescription). Exception: \(exception)."
+ }
+
+ // MARK: - Initialization -
+
+ /**
+ Designated initializer for `UsergridResponseError`.
+
+ - parameter errorName: The error's name.
+ - parameter errorDescription: The error's description.
+ - parameter exception: The exception.
+
+ - returns: A new instance of `UsergridResponseError`
+ */
+ public init(errorName:String, errorDescription:String, exception:String? = nil) {
+ self.errorName = errorName
+ self.errorDescription = errorDescription
+ self.exception = exception
+ }
+
+ /**
+ Convenience initializer for `UsergridResponseError` that determines if the given `jsonDictionary` contains an error.
+
+ - parameter jsonDictionary: The JSON dictionary that may contain error information.
+
+ - returns: A new instance of `UsergridResponseError` if the JSON dictionary did indeed contain error information.
+ */
+ public convenience init?(jsonDictionary:[String:AnyObject]) {
+ if let errorName = jsonDictionary[USERGRID_ERROR] as? String,
+ errorDescription = jsonDictionary[USERGRID_ERROR_DESCRIPTION] as? String {
+ self.init(errorName:errorName,errorDescription:errorDescription,exception:jsonDictionary[USERGRID_EXCEPTION] as? String)
+ } else {
+ self.init(errorName:"",errorDescription:"")
+ return nil
+ }
+ }
+}
+
+let USERGRID_ERROR = "error"
+let USERGRID_ERROR_DESCRIPTION = "error_description"
+let USERGRID_EXCEPTION = "exception"
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/usergrid/blob/7442c881/sdks/swift/Source/UsergridSDK.h
----------------------------------------------------------------------
diff --git a/sdks/swift/Source/UsergridSDK.h b/sdks/swift/Source/UsergridSDK.h
new file mode 100644
index 0000000..be9da27
--- /dev/null
+++ b/sdks/swift/Source/UsergridSDK.h
@@ -0,0 +1,37 @@
+//
+// UsergridSDK.h
+// UsergridSDK
+//
+// Created by Robert Walsh on 9/30/15.
+//
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. The ASF licenses this file to You
+ * under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License. For additional information regarding
+ * copyright in this work, please see the NOTICE file in the top level
+ * directory of this distribution.
+ *
+ */
+
+#import <UIKit/UIKit.h>
+
+//! Project version number for UsergridSDK.
+FOUNDATION_EXPORT double UsergridSDKVersionNumber;
+
+//! Project version string for UsergridSDK.
+FOUNDATION_EXPORT const unsigned char UsergridSDKVersionString[];
+
+// In this header, you should import all the public headers of your framework using statements like #import <UsergridSDK/PublicHeader.h>
+
+
http://git-wip-us.apache.org/repos/asf/usergrid/blob/7442c881/sdks/swift/Source/UsergridSessionDelegate.swift
----------------------------------------------------------------------
diff --git a/sdks/swift/Source/UsergridSessionDelegate.swift b/sdks/swift/Source/UsergridSessionDelegate.swift
new file mode 100644
index 0000000..cb36fb7
--- /dev/null
+++ b/sdks/swift/Source/UsergridSessionDelegate.swift
@@ -0,0 +1,90 @@
+//
+// UsergridSessionDelegate.swift
+// UsergridSDK
+//
+// Created by Robert Walsh on 9/30/15.
+//
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. The ASF licenses this file to You
+ * under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License. For additional information regarding
+ * copyright in this work, please see the NOTICE file in the top level
+ * directory of this distribution.
+ *
+ */
+
+import Foundation
+
+final class UsergridSessionDelegate: NSObject {
+
+ private var requestDelegates: [Int:UsergridAssetRequestWrapper] = [:]
+
+ func addRequestDelegate(task:NSURLSessionTask,requestWrapper:UsergridAssetRequestWrapper) {
+ requestDelegates[task.taskIdentifier] = requestWrapper
+ }
+
+ func removeRequestDelegate(task:NSURLSessionTask) {
+ requestDelegates[task.taskIdentifier] = nil
+ }
+}
+
+extension UsergridSessionDelegate : NSURLSessionTaskDelegate {
+
+ func URLSession(session: NSURLSession, task: NSURLSessionTask, didSendBodyData bytesSent: Int64, totalBytesSent: Int64, totalBytesExpectedToSend: Int64) {
+ if let progressBlock = requestDelegates[task.taskIdentifier]?.progress {
+ progressBlock(bytesFinished:totalBytesSent, bytesExpected: totalBytesExpectedToSend)
+ }
+ }
+
+ func URLSession(session: NSURLSession, task: NSURLSessionTask, didCompleteWithError error: NSError?) {
+ if let requestWrapper = requestDelegates[task.taskIdentifier] {
+ requestWrapper.error = error
+ requestWrapper.completion(requestWrapper: requestWrapper)
+ }
+ self.removeRequestDelegate(task)
+ }
+}
+
+extension UsergridSessionDelegate : NSURLSessionDataDelegate {
+
+ func URLSession(session: NSURLSession, dataTask: NSURLSessionDataTask, didReceiveResponse response: NSURLResponse, completionHandler: (NSURLSessionResponseDisposition) -> Void) {
+ if let requestWrapper = requestDelegates[dataTask.taskIdentifier] {
+ requestWrapper.response = response
+ }
+ completionHandler(NSURLSessionResponseDisposition.Allow)
+ }
+
+ func URLSession(session: NSURLSession, dataTask: NSURLSessionDataTask, didReceiveData data: NSData) {
+ if let requestWrapper = requestDelegates[dataTask.taskIdentifier] {
+ let mutableData = requestWrapper.responseData != nil ? NSMutableData(data: requestWrapper.responseData!) : NSMutableData()
+ mutableData.appendData(data)
+ requestWrapper.responseData = mutableData
+ }
+ }
+}
+
+extension UsergridSessionDelegate : NSURLSessionDownloadDelegate {
+
+ func URLSession(session: NSURLSession, downloadTask: NSURLSessionDownloadTask, didWriteData bytesWritten: Int64, totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64) {
+ if let progressBlock = requestDelegates[downloadTask.taskIdentifier]?.progress {
+ progressBlock(bytesFinished:totalBytesWritten, bytesExpected: totalBytesExpectedToWrite)
+ }
+ }
+
+ func URLSession(session: NSURLSession, downloadTask: NSURLSessionDownloadTask, didFinishDownloadingToURL location: NSURL) {
+ if let requestWrapper = requestDelegates[downloadTask.taskIdentifier] {
+ requestWrapper.responseData = NSData(contentsOfURL: location)!
+ }
+ }
+}
\ No newline at end of file