usergrid-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From mru...@apache.org
Subject [46/51] [partial] usergrid-swift git commit: Initial commit of Usergrid Swift SDK.
Date Thu, 01 Sep 2016 23:52:07 GMT
http://git-wip-us.apache.org/repos/asf/usergrid-swift/blob/8283a6dd/Source/UsergridEnums.swift
----------------------------------------------------------------------
diff --git a/Source/UsergridEnums.swift b/Source/UsergridEnums.swift
new file mode 100644
index 0000000..fd0b625
--- /dev/null
+++ b/Source/UsergridEnums.swift
@@ -0,0 +1,417 @@
+//
+//  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 use for authorization.
+*/
+@objc public enum UsergridAuthMode : Int {
+
+    // MARK: - Values -
+
+    /**
+    If the API call fails, the activity is treated as a failure with an appropriate HTTP status code.
+    */
+    case None
+
+    /**
+     If a non-expired `UsergridUserAuth` 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 authMode=.None).
+     */
+    case User
+
+    /**
+    If a non-expired `UsergridAppAuth` exists in `UsergridClient.appAuth`, 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 authMode=.None).
+    */
+    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 = "deviceOSVersion"
+
+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-swift/blob/8283a6dd/Source/UsergridExtensions.swift
----------------------------------------------------------------------
diff --git a/Source/UsergridExtensions.swift b/Source/UsergridExtensions.swift
new file mode 100644
index 0000000..30ff3a7
--- /dev/null
+++ b/Source/UsergridExtensions.swift
@@ -0,0 +1,112 @@
+//
+//  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
+
+private let kUsergrid_Milliseconds_Per_Second = 1000
+
+/// Extension methods to help create and manipulate `NSDate` objects returned by Usergrid.
+public extension NSDate {
+    /**
+     Creates a new `NSDate` object with the given milliseconds.
+
+     - parameter milliseconds: the milliseconds
+
+     - returns: A new `NSDate` object.
+     */
+    public convenience init(milliseconds: String) {
+        self.init(timeIntervalSince1970: (milliseconds as NSString).doubleValue / Double(kUsergrid_Milliseconds_Per_Second) )
+    }
+    /**
+     Converts the `NSDate` object to milliseconds.
+
+     - returns: The number of milliseconds corresponding to the date.
+     */
+    public func dateAsMilliseconds() -> Int {
+        return Int(self.timeIntervalSince1970 * Double(kUsergrid_Milliseconds_Per_Second))
+    }
+    /**
+     Converts the `NSDate` object to milliseconds and returns the value as a string.
+
+     - returns: The number of milliseconds corresponding to the date as a string.
+     */
+    public func dateAsMillisecondsString() -> String {
+        return NSDate.stringFromMilleseconds(self.dateAsMilliseconds())
+    }
+    /**
+     Converts the number of milliseconds to a string.
+
+     - parameter milliseconds: the milliseconds to convert
+
+     - returns: The milliseconds as a string.
+     */
+    public static func stringFromMilleseconds(milliseconds:Int) -> String {
+        return NSNumber(longLong: Int64(milliseconds)).stringValue
+    }
+    /**
+     Converts the `NSDate` object to the corresponding UNIX time stamp as a string.
+
+     - returns: The UNIX time stamp as a string.
+     */
+    public static func unixTimeStampString() -> String {
+        return NSDate.stringFromMilleseconds(NSDate.nowAsMilliseconds())
+    }
+    /**
+     Converts the `NSDate` object to the corresponding UNIX time stamp.
+
+     - returns: The UNIX time stamp.
+     */
+    public static func unixTimeStamp() -> Int {
+        return NSDate.nowAsMilliseconds()
+    }
+    /**
+     Converts the current date to milliseconds.
+
+     - returns: The milliseconds of the current date.
+     */
+    public static func nowAsMilliseconds() -> Int {
+        var tv = timeval()
+        let currentMillisecondTime = withUnsafeMutablePointer(&tv, { (t: UnsafeMutablePointer<timeval>) -> Int in
+            gettimeofday(t, nil)
+            return (Int(t.memory.tv_sec) * kUsergrid_Milliseconds_Per_Second) + (Int(t.memory.tv_usec) / kUsergrid_Milliseconds_Per_Second)
+        })
+        return currentMillisecondTime
+    }
+}
+
+internal extension String {
+    func isUuid() -> Bool {
+        return (NSUUID(UUIDString: self) != nil) ? true : false
+    }
+}
+
+internal extension Dictionary {
+    mutating func update(other:Dictionary) {
+        for (key,value) in other {
+            self.updateValue(value, forKey:key)
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/usergrid-swift/blob/8283a6dd/Source/UsergridFileMetaData.swift
----------------------------------------------------------------------
diff --git a/Source/UsergridFileMetaData.swift b/Source/UsergridFileMetaData.swift
new file mode 100644
index 0000000..4908430
--- /dev/null
+++ b/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(milliseconds: 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(milliseconds: 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-swift/blob/8283a6dd/Source/UsergridKeychainHelpers.swift
----------------------------------------------------------------------
diff --git a/Source/UsergridKeychainHelpers.swift b/Source/UsergridKeychainHelpers.swift
new file mode 100644
index 0000000..4639832
--- /dev/null
+++ b/Source/UsergridKeychainHelpers.swift
@@ -0,0 +1,196 @@
+//
+//  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 = "SharedDevice"
+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 createNewDeviceKeychainUUID() -> String {
+
+        #if os(watchOS) || os(OSX)
+            let usergridUUID = NSUUID().UUIDString
+        #elseif os(iOS) || os(tvOS)
+            let usergridUUID = UIDevice.currentDevice().identifierForVendor?.UUIDString ?? NSUUID().UUIDString
+        #endif
+
+        return usergridUUID
+    }
+
+    private static func createNewSharedDevice() -> UsergridDevice {
+        var deviceEntityDict = UsergridDevice.commonDevicePropertyDict()
+        deviceEntityDict[UsergridEntityProperties.UUID.stringValue] = UsergridDevice.createNewDeviceKeychainUUID()
+        let sharedDevice = UsergridDevice(type: UsergridDevice.DEVICE_ENTITY_TYPE, name: nil, propertyDict: deviceEntityDict)
+        return sharedDevice
+    }
+
+    static func getOrCreateSharedDeviceFromKeychain() -> UsergridDevice {
+        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 sharedDevice = NSKeyedUnarchiver.unarchiveObjectWithData(resultData) as? UsergridDevice {
+                        return sharedDevice
+                    } else {
+                        UsergridDevice.deleteSharedDeviceKeychainItem()
+                    }
+                }
+            }
+        }
+
+        let sharedDevice = UsergridDevice.createNewSharedDevice()
+        UsergridDevice.saveSharedDeviceKeychainItem(sharedDevice)
+        return sharedDevice
+    }
+
+
+    static func saveSharedDeviceKeychainItem(device:UsergridDevice) {
+        var queryAttributes = UsergridDevice.deviceKeychainItem()
+        queryAttributes[kSecReturnData as String] = kCFBooleanTrue as Bool
+        queryAttributes[kSecReturnAttributes as String] = kCFBooleanTrue as Bool
+
+        let sharedDeviceData = NSKeyedArchiver.archivedDataWithRootObject(device);
+
+        if SecItemCopyMatching(queryAttributes,nil) == errSecSuccess // Do we need to update keychain item or add a new one.
+        {
+            let attributesToUpdate = [kSecValueData as String:sharedDeviceData]
+            let updateStatus = SecItemUpdate(UsergridDevice.deviceKeychainItem(), attributesToUpdate)
+            if updateStatus != errSecSuccess {
+                print("Error updating shared device data to keychain!")
+            }
+        }
+        else
+        {
+            var keychainItem = UsergridDevice.deviceKeychainItem()
+            keychainItem[kSecValueData as String] = sharedDeviceData
+            let status = SecItemAdd(keychainItem, nil)
+            if status != errSecSuccess {
+                print("Error adding shared device data to keychain!")
+            }
+        }
+    }
+
+    static func deleteSharedDeviceKeychainItem() {
+        var queryAttributes = UsergridDevice.deviceKeychainItem()
+        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 shared device data to keychain!")
+            }
+        }
+    }
+}
+
+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-swift/blob/8283a6dd/Source/UsergridQuery.swift
----------------------------------------------------------------------
diff --git a/Source/UsergridQuery.swift b/Source/UsergridQuery.swift
new file mode 100644
index 0000000..c2a7000
--- /dev/null
+++ b/Source/UsergridQuery.swift
@@ -0,0 +1,591 @@
+//
+//  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 contains(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 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: .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: .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 )
+    }
+    
+    /**
+     Or operation for 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
+    }
+
+    /**
+     And operation for conditional queries.
+
+     - returns: `Self`
+     */
+    public func and() -> Self {
+        if !self.requirementStrings.first!.isEmpty {
+            self.requirementStrings.insert(UsergridQuery.AND, 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 collection name.
+
+     - parameter type: The new collection name.
+
+     - returns: `Self`
+     */
+    public func type(type: String) -> Self {
+        self.collectionName = type
+        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
+    }
+
+    /**
+     A special builder property that allows you to input a pre-defined query string. All builder properties will be ignored when this property is defined.
+
+     - parameter value: The pre-defined query string.
+
+     - returns: `Self`
+     */
+    public func fromString(value: String?) -> Self {
+        self.fromStringValue = 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 {
+
+        if let fromString = self.fromStringValue {
+            var requirementsString = fromString
+            if autoURLEncode {
+                if let encodedRequirementsString = fromString.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLQueryAllowedCharacterSet()) {
+                    requirementsString = encodedRequirementsString
+                }
+            }
+            return "\(UsergridQuery.QUESTION_MARK)\(UsergridQuery.QL)=\(requirementsString)"
+        }
+
+        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 = UsergridQuery.SELECT_ALL + UsergridQuery.SPACE + 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 fromStringValue: String? = nil
+    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 SELECT_ALL = "select *"
+    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-swift/blob/8283a6dd/Source/UsergridRequest.swift
----------------------------------------------------------------------
diff --git a/Source/UsergridRequest.swift b/Source/UsergridRequest.swift
new file mode 100644
index 0000000..0a651e2
--- /dev/null
+++ b/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; charset=utf-8"
+    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-swift/blob/8283a6dd/Source/UsergridRequestManager.swift
----------------------------------------------------------------------
diff --git a/Source/UsergridRequestManager.swift b/Source/UsergridRequestManager.swift
new file mode 100644
index 0000000..46a4213
--- /dev/null
+++ b/Source/UsergridRequestManager.swift
@@ -0,0 +1,176 @@
+//
+//  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:  nil)
+    }
+
+    deinit {
+        session.invalidateAndCancel()
+    }
+
+    func performRequest(request:UsergridRequest, completion:UsergridResponseCompletion?) {
+        session.dataTaskWithRequest(request.buildNSURLRequest()) { [weak self] (data, response, error) -> Void in
+            let response = UsergridResponse(client:self?.client, data: data, response: response as? NSHTTPURLResponse, error: error)
+            dispatch_async(dispatch_get_main_queue()) {
+                completion?(response: response)
+            }
+        }.resume()
+    }
+}
+
+
+// MARK: - Authentication -
+extension UsergridRequestManager {
+
+    static func getTokenAndExpiryFromResponseJSON(jsonDict:[String:AnyObject]) -> (token:String?,expiry: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: NSTimeInterval(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)
+
+            var createdUser: UsergridUser? = nil
+            var responseError: UsergridResponseError? = nil
+
+            if let jsonDict = dataAsJSON as? [String:AnyObject] {
+                let tokenAndExpiry = UsergridRequestManager.getTokenAndExpiryFromResponseJSON(jsonDict)
+                userAuth.accessToken = tokenAndExpiry.token
+                userAuth.expiry = tokenAndExpiry.expiry
+
+                if let userDict = jsonDict[UsergridUser.USER_ENTITY_TYPE] as? [String:AnyObject] {
+                    if let newUser = UsergridEntity.entity(jsonDict: userDict) as? UsergridUser {
+                        newUser.auth = userAuth
+                        createdUser = newUser
+                    }
+                }
+                if createdUser == nil {
+                    responseError = UsergridResponseError(jsonDictionary: jsonDict) ?? UsergridResponseError(errorName: "Auth Failed.", errorDescription: "Error Description: \(error?.localizedDescription).")
+                }
+            } else {
+                responseError = UsergridResponseError(errorName: "Auth Failed.", errorDescription: "Error Description: \(error?.localizedDescription).")
+            }
+
+            dispatch_async(dispatch_get_main_queue()) {
+                completion?(auth: userAuth, user: createdUser, error: responseError)
+            }
+        }.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)
+
+            var responseError: UsergridResponseError? = nil
+
+            if let jsonDict = dataAsJSON as? [String:AnyObject] {
+                let tokenAndExpiry = UsergridRequestManager.getTokenAndExpiryFromResponseJSON(jsonDict)
+                appAuth.accessToken = tokenAndExpiry.token
+                appAuth.expiry = tokenAndExpiry.expiry
+            } else {
+                responseError = UsergridResponseError(errorName: "Auth Failed.", errorDescription: "Error Description: \(error?.localizedDescription).")
+            }
+
+            dispatch_async(dispatch_get_main_queue()) {
+                completion?(auth: appAuth, error: responseError)
+            }
+        }.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
+            var asset: UsergridAsset? = nil
+            var responseError: UsergridResponseError? = nil
+
+            if let assetData = request.responseData where assetData.length > 0 {
+                asset = UsergridAsset(data: assetData, contentType: contentType)
+            } else {
+                responseError = UsergridResponseError(errorName: "Download Failed.", errorDescription: "Downloading asset failed.  No data was recieved.")
+            }
+
+            dispatch_async(dispatch_get_main_queue()) {
+                completion?(asset: asset, error: responseError)
+            }
+        }
+        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
+            let response = UsergridResponse(client: self?.client, data: request.responseData, response: request.response as? NSHTTPURLResponse, error: request.error)
+            dispatch_async(dispatch_get_main_queue()) {
+                completion?(asset: usergridRequest.asset, response: response)
+            }
+        }
+        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-swift/blob/8283a6dd/Source/UsergridResponse.swift
----------------------------------------------------------------------
diff --git a/Source/UsergridResponse.swift b/Source/UsergridResponse.swift
new file mode 100644
index 0000000..b9e58ec
--- /dev/null
+++ b/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 `UsergridResponseError.error` property 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: NSUTF8StringEncoding) 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(query.cursor(self.cursor), queryCompletion:completion)
+            } else {
+                self.client?.GET(UsergridQuery(type).cursor(self.cursor), queryCompletion: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-swift/blob/8283a6dd/Source/UsergridResponseError.swift
----------------------------------------------------------------------
diff --git a/Source/UsergridResponseError.swift b/Source/UsergridResponseError.swift
new file mode 100644
index 0000000..eda8a30
--- /dev/null
+++ b/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-swift/blob/8283a6dd/Source/UsergridSDK.h
----------------------------------------------------------------------
diff --git a/Source/UsergridSDK.h b/Source/UsergridSDK.h
new file mode 100644
index 0000000..be9da27
--- /dev/null
+++ b/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-swift/blob/8283a6dd/Source/UsergridSessionDelegate.swift
----------------------------------------------------------------------
diff --git a/Source/UsergridSessionDelegate.swift b/Source/UsergridSessionDelegate.swift
new file mode 100644
index 0000000..cb36fb7
--- /dev/null
+++ b/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


Mime
View raw message