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/10/24 13:06:19 UTC

[34/83] [abbrv] usergrid git commit: Moving older SDKs to a difference location and updating main README to link to new SDK locations.

http://git-wip-us.apache.org/repos/asf/usergrid/blob/867060fa/sdks/other/ios/UGAPI/SBJson/SBJsonStreamWriterState.h
----------------------------------------------------------------------
diff --git a/sdks/other/ios/UGAPI/SBJson/SBJsonStreamWriterState.h b/sdks/other/ios/UGAPI/SBJson/SBJsonStreamWriterState.h
new file mode 100755
index 0000000..90d442a
--- /dev/null
+++ b/sdks/other/ios/UGAPI/SBJson/SBJsonStreamWriterState.h
@@ -0,0 +1,69 @@
+/*
+ Copyright (c) 2010, Stig Brautaset.
+ All rights reserved.
+ 
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+ 
+   Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+  
+   Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+ 
+   Neither the name of the the author nor the names of its contributors
+   may be used to endorse or promote products derived from this software
+   without specific prior written permission.
+ 
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import <Foundation/Foundation.h>
+
+@class SBJsonStreamWriter;
+
+@interface SBJsonStreamWriterState : NSObject
++ (id)sharedInstance;
+- (BOOL)isInvalidState:(SBJsonStreamWriter*)writer;
+- (void)appendSeparator:(SBJsonStreamWriter*)writer;
+- (BOOL)expectingKey:(SBJsonStreamWriter*)writer;
+- (void)transitionState:(SBJsonStreamWriter*)writer;
+- (void)appendWhitespace:(SBJsonStreamWriter*)writer;
+@end
+
+@interface SBJsonStreamWriterStateObjectStart : SBJsonStreamWriterState
+@end
+
+@interface SBJsonStreamWriterStateObjectKey : SBJsonStreamWriterStateObjectStart
+@end
+
+@interface SBJsonStreamWriterStateObjectValue : SBJsonStreamWriterState
+@end
+
+@interface SBJsonStreamWriterStateArrayStart : SBJsonStreamWriterState
+@end
+
+@interface SBJsonStreamWriterStateArrayValue : SBJsonStreamWriterState
+@end
+
+@interface SBJsonStreamWriterStateStart : SBJsonStreamWriterState
+@end
+
+@interface SBJsonStreamWriterStateComplete : SBJsonStreamWriterState
+@end
+
+@interface SBJsonStreamWriterStateError : SBJsonStreamWriterState
+@end
+

http://git-wip-us.apache.org/repos/asf/usergrid/blob/867060fa/sdks/other/ios/UGAPI/SBJson/SBJsonStreamWriterState.m
----------------------------------------------------------------------
diff --git a/sdks/other/ios/UGAPI/SBJson/SBJsonStreamWriterState.m b/sdks/other/ios/UGAPI/SBJson/SBJsonStreamWriterState.m
new file mode 100755
index 0000000..9f04cac
--- /dev/null
+++ b/sdks/other/ios/UGAPI/SBJson/SBJsonStreamWriterState.m
@@ -0,0 +1,139 @@
+/*
+ Copyright (c) 2010, Stig Brautaset.
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+
+   Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+
+   Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+   Neither the name of the the author nor the names of its contributors
+   may be used to endorse or promote products derived from this software
+   without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import "SBJsonStreamWriterState.h"
+#import "SBJsonStreamWriter.h"
+
+#define SINGLETON \
++ (id)sharedInstance { \
+    static id state; \
+    if (!state) state = [[self alloc] init]; \
+    return state; \
+}
+
+
+@implementation SBJsonStreamWriterState
++ (id)sharedInstance { return nil; }
+- (BOOL)isInvalidState:(SBJsonStreamWriter*)writer { return NO; }
+- (void)appendSeparator:(SBJsonStreamWriter*)writer {}
+- (BOOL)expectingKey:(SBJsonStreamWriter*)writer { return NO; }
+- (void)transitionState:(SBJsonStreamWriter *)writer {}
+- (void)appendWhitespace:(SBJsonStreamWriter*)writer {
+	[writer appendBytes:"\n" length:1];
+	for (NSUInteger i = 0; i < writer.stateStack.count; i++)
+	    [writer appendBytes:"  " length:2];
+}
+@end
+
+@implementation SBJsonStreamWriterStateObjectStart
+
+SINGLETON
+
+- (void)transitionState:(SBJsonStreamWriter *)writer {
+	writer.state = [SBJsonStreamWriterStateObjectValue sharedInstance];
+}
+- (BOOL)expectingKey:(SBJsonStreamWriter *)writer {
+	writer.error = @"JSON object key must be string";
+	return YES;
+}
+@end
+
+@implementation SBJsonStreamWriterStateObjectKey
+
+SINGLETON
+
+- (void)appendSeparator:(SBJsonStreamWriter *)writer {
+	[writer appendBytes:"," length:1];
+}
+@end
+
+@implementation SBJsonStreamWriterStateObjectValue
+
+SINGLETON
+
+- (void)appendSeparator:(SBJsonStreamWriter *)writer {
+	[writer appendBytes:":" length:1];
+}
+- (void)transitionState:(SBJsonStreamWriter *)writer {
+    writer.state = [SBJsonStreamWriterStateObjectKey sharedInstance];
+}
+- (void)appendWhitespace:(SBJsonStreamWriter *)writer {
+	[writer appendBytes:" " length:1];
+}
+@end
+
+@implementation SBJsonStreamWriterStateArrayStart
+
+SINGLETON
+
+- (void)transitionState:(SBJsonStreamWriter *)writer {
+    writer.state = [SBJsonStreamWriterStateArrayValue sharedInstance];
+}
+@end
+
+@implementation SBJsonStreamWriterStateArrayValue
+
+SINGLETON
+
+- (void)appendSeparator:(SBJsonStreamWriter *)writer {
+	[writer appendBytes:"," length:1];
+}
+@end
+
+@implementation SBJsonStreamWriterStateStart
+
+SINGLETON
+
+
+- (void)transitionState:(SBJsonStreamWriter *)writer {
+    writer.state = [SBJsonStreamWriterStateComplete sharedInstance];
+}
+- (void)appendSeparator:(SBJsonStreamWriter *)writer {
+}
+@end
+
+@implementation SBJsonStreamWriterStateComplete
+
+SINGLETON
+
+- (BOOL)isInvalidState:(SBJsonStreamWriter*)writer {
+	writer.error = @"Stream is closed";
+	return YES;
+}
+@end
+
+@implementation SBJsonStreamWriterStateError
+
+SINGLETON
+
+@end
+

http://git-wip-us.apache.org/repos/asf/usergrid/blob/867060fa/sdks/other/ios/UGAPI/SBJson/SBJsonTokeniser.h
----------------------------------------------------------------------
diff --git a/sdks/other/ios/UGAPI/SBJson/SBJsonTokeniser.h b/sdks/other/ios/UGAPI/SBJson/SBJsonTokeniser.h
new file mode 100755
index 0000000..e484a94
--- /dev/null
+++ b/sdks/other/ios/UGAPI/SBJson/SBJsonTokeniser.h
@@ -0,0 +1,67 @@
+/*
+ Copyright (c) 2010, Stig Brautaset.
+ All rights reserved.
+ 
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+ 
+ Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 
+ Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 
+ Neither the name of the the author nor the names of its contributors
+ may be used to endorse or promote products derived from this software
+ without specific prior written permission.
+ 
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import <Foundation/Foundation.h>
+
+typedef enum {
+    sbjson_token_error = -1,
+    sbjson_token_eof,
+    
+    sbjson_token_array_start,
+    sbjson_token_array_end,
+    
+    sbjson_token_object_start,
+    sbjson_token_object_end,
+
+    sbjson_token_separator,
+    sbjson_token_keyval_separator,
+    
+    sbjson_token_number,
+    sbjson_token_string,
+    sbjson_token_true,
+    sbjson_token_false,
+    sbjson_token_null,
+    
+} sbjson_token_t;
+
+@class SBJsonUTF8Stream;
+
+@interface SBJsonTokeniser : NSObject 
+
+@property (strong) SBJsonUTF8Stream *stream;
+@property (copy) NSString *error;
+
+- (void)appendData:(NSData*)data_;
+
+- (sbjson_token_t)getToken:(NSObject**)token;
+
+@end

http://git-wip-us.apache.org/repos/asf/usergrid/blob/867060fa/sdks/other/ios/UGAPI/SBJson/SBJsonTokeniser.m
----------------------------------------------------------------------
diff --git a/sdks/other/ios/UGAPI/SBJson/SBJsonTokeniser.m b/sdks/other/ios/UGAPI/SBJson/SBJsonTokeniser.m
new file mode 100755
index 0000000..75d3268
--- /dev/null
+++ b/sdks/other/ios/UGAPI/SBJson/SBJsonTokeniser.m
@@ -0,0 +1,453 @@
+/*
+ Copyright (c) 2010-2011, Stig Brautaset. All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+
+ Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ Neither the name of the the author nor the names of its contributors
+ may be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import "SBJsonTokeniser.h"
+#import "SBJsonUTF8Stream.h"
+
+#define SBStringIsIllegalSurrogateHighCharacter(character) (((character) >= 0xD800UL) && ((character) <= 0xDFFFUL))
+#define SBStringIsSurrogateLowCharacter(character) ((character >= 0xDC00UL) && (character <= 0xDFFFUL))
+#define SBStringIsSurrogateHighCharacter(character) ((character >= 0xD800UL) && (character <= 0xDBFFUL))
+
+@implementation SBJsonTokeniser
+
+@synthesize error = _error;
+@synthesize stream = _stream;
+
+- (id)init {
+    self = [super init];
+    if (self) {
+        _stream = [[SBJsonUTF8Stream alloc] init];
+
+    }
+
+    return self;
+}
+
+
+- (void)appendData:(NSData *)data_ {
+    [_stream appendData:data_];
+}
+
+
+- (sbjson_token_t)match:(const char *)pattern length:(NSUInteger)len retval:(sbjson_token_t)token {
+    if (![_stream haveRemainingCharacters:len])
+        return sbjson_token_eof;
+
+    if ([_stream skipCharacters:pattern length:len])
+        return token;
+
+    self.error = [NSString stringWithFormat:@"Expected '%s' after initial '%.1s'", pattern, pattern];
+    return sbjson_token_error;
+}
+
+- (BOOL)decodeEscape:(unichar)ch into:(unichar*)decoded {
+    switch (ch) {
+        case '\\':
+        case '/':
+        case '"':
+            *decoded = ch;
+            break;
+
+        case 'b':
+            *decoded = '\b';
+            break;
+
+        case 'n':
+            *decoded = '\n';
+            break;
+
+        case 'r':
+            *decoded = '\r';
+            break;
+
+        case 't':
+            *decoded = '\t';
+            break;
+
+        case 'f':
+            *decoded = '\f';
+            break;
+
+        default:
+            self.error = @"Illegal escape character";
+            return NO;
+            break;
+    }
+    return YES;
+}
+
+- (BOOL)decodeHexQuad:(unichar*)quad {
+    unichar c, tmp = 0;
+
+    for (int i = 0; i < 4; i++) {
+        (void)[_stream getNextUnichar:&c];
+        tmp *= 16;
+        switch (c) {
+            case '0' ... '9':
+                tmp += c - '0';
+                break;
+
+            case 'a' ... 'f':
+                tmp += 10 + c - 'a';
+                break;
+
+            case 'A' ... 'F':
+                tmp += 10 + c - 'A';
+                break;
+
+            default:
+                return NO;
+        }
+    }
+    *quad = tmp;
+    return YES;
+}
+
+- (sbjson_token_t)getStringToken:(NSObject**)token {
+    NSMutableString *acc = nil;
+
+    for (;;) {
+        [_stream skip];
+        
+        unichar ch;
+        {
+            NSMutableString *string = nil;
+            
+            if (![_stream getStringFragment:&string])
+                return sbjson_token_eof;
+            
+            if (!string) {
+                self.error = @"Broken Unicode encoding";
+                return sbjson_token_error;
+            }
+            
+            if (![_stream getUnichar:&ch])
+                return sbjson_token_eof;
+            
+            if (acc) {
+                [acc appendString:string];
+                
+            } else if (ch == '"') {
+                *token = [string copy];
+                [_stream skip];
+                return sbjson_token_string;
+                
+            } else {
+                acc = [string mutableCopy];
+            }
+        }
+
+        
+        switch (ch) {
+            case 0 ... 0x1F:
+                self.error = [NSString stringWithFormat:@"Unescaped control character [0x%0.2X]", (int)ch];
+                return sbjson_token_error;
+                break;
+
+            case '"':
+                *token = acc;
+                [_stream skip];
+                return sbjson_token_string;
+                break;
+
+            case '\\':
+                if (![_stream getNextUnichar:&ch])
+                    return sbjson_token_eof;
+
+                if (ch == 'u') {
+                    if (![_stream haveRemainingCharacters:5])
+                        return sbjson_token_eof;
+
+                    unichar hi;
+                    if (![self decodeHexQuad:&hi]) {
+                        self.error = @"Invalid hex quad";
+                        return sbjson_token_error;
+                    }
+
+                    if (SBStringIsSurrogateHighCharacter(hi)) {
+                        unichar lo;
+
+                        if (![_stream haveRemainingCharacters:6])
+                            return sbjson_token_eof;
+
+                        (void)[_stream getNextUnichar:&ch];
+                        (void)[_stream getNextUnichar:&lo];
+                        if (ch != '\\' || lo != 'u' || ![self decodeHexQuad:&lo]) {
+                            self.error = @"Missing low character in surrogate pair";
+                            return sbjson_token_error;
+                        }
+
+                        if (!SBStringIsSurrogateLowCharacter(lo)) {
+                            self.error = @"Invalid low character in surrogate pair";
+                            return sbjson_token_error;
+                        }
+
+                        [acc appendFormat:@"%C%C", hi, lo];
+                    } else if (SBStringIsIllegalSurrogateHighCharacter(hi)) {
+                        self.error = @"Invalid high character in surrogate pair";
+                        return sbjson_token_error;
+                    } else {
+                        [acc appendFormat:@"%C", hi];
+                    }
+
+
+                } else {
+                    unichar decoded;
+                    if (![self decodeEscape:ch into:&decoded])
+                        return sbjson_token_error;
+                    [acc appendFormat:@"%C", decoded];
+                }
+
+                break;
+
+            default: {
+                self.error = [NSString stringWithFormat:@"Invalid UTF-8: '%x'", (int)ch];
+                return sbjson_token_error;
+                break;
+            }
+        }
+    }
+    return sbjson_token_eof;
+}
+
+- (sbjson_token_t)getNumberToken:(NSObject**)token {
+
+    NSUInteger numberStart = _stream.index;
+    NSCharacterSet *digits = [NSCharacterSet decimalDigitCharacterSet];
+
+    unichar ch;
+    if (![_stream getUnichar:&ch])
+        return sbjson_token_eof;
+
+    BOOL isNegative = NO;
+    if (ch == '-') {
+        isNegative = YES;
+        if (![_stream getNextUnichar:&ch])
+            return sbjson_token_eof;
+    }
+
+    unsigned long long mantissa = 0;
+    int mantissa_length = 0;
+    
+    if (ch == '0') {
+        mantissa_length++;
+        if (![_stream getNextUnichar:&ch])
+            return sbjson_token_eof;
+
+        if ([digits characterIsMember:ch]) {
+            self.error = @"Leading zero is illegal in number";
+            return sbjson_token_error;
+        }
+    }
+
+    while ([digits characterIsMember:ch]) {
+        mantissa *= 10;
+        mantissa += (ch - '0');
+        mantissa_length++;
+
+        if (![_stream getNextUnichar:&ch])
+            return sbjson_token_eof;
+    }
+
+    short exponent = 0;
+    BOOL isFloat = NO;
+
+    if (ch == '.') {
+        isFloat = YES;
+        if (![_stream getNextUnichar:&ch])
+            return sbjson_token_eof;
+
+        while ([digits characterIsMember:ch]) {
+            mantissa *= 10;
+            mantissa += (ch - '0');
+            mantissa_length++;
+            exponent--;
+
+            if (![_stream getNextUnichar:&ch])
+                return sbjson_token_eof;
+        }
+
+        if (!exponent) {
+            self.error = @"No digits after decimal point";
+            return sbjson_token_error;
+        }
+    }
+
+    BOOL hasExponent = NO;
+    if (ch == 'e' || ch == 'E') {
+        hasExponent = YES;
+
+        if (![_stream getNextUnichar:&ch])
+            return sbjson_token_eof;
+
+        BOOL expIsNegative = NO;
+        if (ch == '-') {
+            expIsNegative = YES;
+            if (![_stream getNextUnichar:&ch])
+                return sbjson_token_eof;
+
+        } else if (ch == '+') {
+            if (![_stream getNextUnichar:&ch])
+                return sbjson_token_eof;
+        }
+
+        short explicit_exponent = 0;
+        short explicit_exponent_length = 0;
+        while ([digits characterIsMember:ch]) {
+            explicit_exponent *= 10;
+            explicit_exponent += (ch - '0');
+            explicit_exponent_length++;
+
+            if (![_stream getNextUnichar:&ch])
+                return sbjson_token_eof;
+        }
+
+        if (explicit_exponent_length == 0) {
+            self.error = @"No digits in exponent";
+            return sbjson_token_error;
+        }
+
+        if (expIsNegative)
+            exponent -= explicit_exponent;
+        else
+            exponent += explicit_exponent;
+    }
+
+    if (!mantissa_length && isNegative) {
+        self.error = @"No digits after initial minus";
+        return sbjson_token_error;
+
+    } else if (mantissa_length >= 19) {
+        
+        NSString *number = [_stream stringWithRange:NSMakeRange(numberStart, _stream.index - numberStart)];
+        *token = [NSDecimalNumber decimalNumberWithString:number];
+
+    } else if (!isFloat && !hasExponent) {
+        if (!isNegative)
+            *token = [NSNumber numberWithUnsignedLongLong:mantissa];
+        else
+            *token = [NSNumber numberWithLongLong:-mantissa];
+    } else {
+        *token = [NSDecimalNumber decimalNumberWithMantissa:mantissa
+                                                   exponent:exponent
+                                                 isNegative:isNegative];
+    }
+
+    return sbjson_token_number;
+}
+
+- (sbjson_token_t)getToken:(NSObject **)token {
+
+    [_stream skipWhitespace];
+
+    unichar ch;
+    if (![_stream getUnichar:&ch])
+        return sbjson_token_eof;
+
+    NSUInteger oldIndexLocation = _stream.index;
+    sbjson_token_t tok;
+
+    switch (ch) {
+        case '[':
+            tok = sbjson_token_array_start;
+            [_stream skip];
+            break;
+
+        case ']':
+            tok = sbjson_token_array_end;
+            [_stream skip];
+            break;
+
+        case '{':
+            tok = sbjson_token_object_start;
+            [_stream skip];
+            break;
+
+        case ':':
+            tok = sbjson_token_keyval_separator;
+            [_stream skip];
+            break;
+
+        case '}':
+            tok = sbjson_token_object_end;
+            [_stream skip];
+            break;
+
+        case ',':
+            tok = sbjson_token_separator;
+            [_stream skip];
+            break;
+
+        case 'n':
+            tok = [self match:"null" length:4 retval:sbjson_token_null];
+            break;
+
+        case 't':
+            tok = [self match:"true" length:4 retval:sbjson_token_true];
+            break;
+
+        case 'f':
+            tok = [self match:"false" length:5 retval:sbjson_token_false];
+            break;
+
+        case '"':
+            tok = [self getStringToken:token];
+            break;
+
+        case '0' ... '9':
+        case '-':
+            tok = [self getNumberToken:token];
+            break;
+
+        case '+':
+            self.error = @"Leading + is illegal in number";
+            tok = sbjson_token_error;
+            break;
+
+        default:
+            self.error = [NSString stringWithFormat:@"Illegal start of token [%c]", ch];
+            tok = sbjson_token_error;
+            break;
+    }
+
+    if (tok == sbjson_token_eof) {
+        // We ran out of bytes in the middle of a token.
+        // We don't know how to restart in mid-flight, so
+        // rewind to the start of the token for next attempt.
+        // Hopefully we'll have more data then.
+        _stream.index = oldIndexLocation;
+    }
+
+    return tok;
+}
+
+
+@end

http://git-wip-us.apache.org/repos/asf/usergrid/blob/867060fa/sdks/other/ios/UGAPI/SBJson/SBJsonUTF8Stream.h
----------------------------------------------------------------------
diff --git a/sdks/other/ios/UGAPI/SBJson/SBJsonUTF8Stream.h b/sdks/other/ios/UGAPI/SBJson/SBJsonUTF8Stream.h
new file mode 100755
index 0000000..a26f032
--- /dev/null
+++ b/sdks/other/ios/UGAPI/SBJson/SBJsonUTF8Stream.h
@@ -0,0 +1,58 @@
+/*
+ Copyright (c) 2011, Stig Brautaset. All rights reserved.
+ 
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+ 
+ Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 
+ Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 
+ Neither the name of the the author nor the names of its contributors
+ may be used to endorse or promote products derived from this software
+ without specific prior written permission.
+ 
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import <Foundation/Foundation.h>
+
+
+@interface SBJsonUTF8Stream : NSObject {
+@private
+    const char *_bytes;
+    NSMutableData *_data;
+    NSUInteger _length;
+}
+
+@property (assign) NSUInteger index;
+
+- (void)appendData:(NSData*)data_;
+
+- (BOOL)haveRemainingCharacters:(NSUInteger)chars;
+
+- (void)skip;
+- (void)skipWhitespace;
+- (BOOL)skipCharacters:(const char *)chars length:(NSUInteger)len;
+
+- (BOOL)getUnichar:(unichar*)ch;
+- (BOOL)getNextUnichar:(unichar*)ch;
+- (BOOL)getStringFragment:(NSString**)string;
+
+- (NSString*)stringWithRange:(NSRange)range;
+
+@end

http://git-wip-us.apache.org/repos/asf/usergrid/blob/867060fa/sdks/other/ios/UGAPI/SBJson/SBJsonUTF8Stream.m
----------------------------------------------------------------------
diff --git a/sdks/other/ios/UGAPI/SBJson/SBJsonUTF8Stream.m b/sdks/other/ios/UGAPI/SBJson/SBJsonUTF8Stream.m
new file mode 100755
index 0000000..f57015d
--- /dev/null
+++ b/sdks/other/ios/UGAPI/SBJson/SBJsonUTF8Stream.m
@@ -0,0 +1,141 @@
+/*
+ Copyright (c) 2011, Stig Brautaset. All rights reserved.
+ 
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+ 
+ Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 
+ Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 
+ Neither the name of the the author nor the names of its contributors
+ may be used to endorse or promote products derived from this software
+ without specific prior written permission.
+ 
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import "SBJsonUTF8Stream.h"
+
+
+@implementation SBJsonUTF8Stream
+
+@synthesize index = _index;
+
+- (id)init {
+    self = [super init];
+    if (self) {
+        _data = [[NSMutableData alloc] initWithCapacity:4096u];
+    }
+    return self;
+}
+
+
+- (void)appendData:(NSData *)data_ {
+    
+    if (_index) {
+        // Discard data we've already parsed
+		[_data replaceBytesInRange:NSMakeRange(0, _index) withBytes:"" length:0];
+        
+        // Reset index to point to current position
+		_index = 0;
+	}
+    
+    [_data appendData:data_];
+    
+    // This is an optimisation. 
+    _bytes = (const char*)[_data bytes];
+    _length = [_data length];
+}
+
+
+- (BOOL)getUnichar:(unichar*)ch {
+    if (_index < _length) {
+        *ch = (unichar)_bytes[_index];
+        return YES;
+    }
+    return NO;
+}
+
+- (BOOL)getNextUnichar:(unichar*)ch {
+    if (++_index < _length) {
+        *ch = (unichar)_bytes[_index];
+        return YES;
+    }
+    return NO;
+}
+
+- (BOOL)getStringFragment:(NSString **)string {
+    NSUInteger start = _index;
+    while (_index < _length) {
+        switch (_bytes[_index]) {
+            case '"':
+            case '\\':
+            case 0 ... 0x1f:
+                *string = [[NSString alloc] initWithBytes:(_bytes + start)
+                                                   length:(_index - start)
+                                                 encoding:NSUTF8StringEncoding];
+                return YES;
+                break;
+            default:
+                _index++;
+                break;
+        }
+    }
+    return NO;
+}
+
+- (void)skip {
+    _index++;
+}
+
+- (void)skipWhitespace {
+    while (_index < _length) {
+        switch (_bytes[_index]) {
+            case ' ':
+            case '\t':
+            case '\r':
+            case '\n':
+                _index++;
+                break;
+            default:
+                return;
+                break;
+        }
+    }
+}
+
+- (BOOL)haveRemainingCharacters:(NSUInteger)chars {
+    return [_data length] - _index >= chars;
+}
+
+- (BOOL)skipCharacters:(const char *)chars length:(NSUInteger)len {
+    const void *bytes = ((const char*)[_data bytes]) + _index;
+    if (!memcmp(bytes, chars, len)) {
+        _index += len;
+        return YES;
+    }
+    return NO;
+}
+
+- (NSString*)stringWithRange:(NSRange)range {
+    return [[NSString alloc] initWithBytes:_bytes + range.location length:range.length encoding:NSUTF8StringEncoding];
+    
+}
+
+
+@end

http://git-wip-us.apache.org/repos/asf/usergrid/blob/867060fa/sdks/other/ios/UGAPI/SBJson/SBJsonWriter.h
----------------------------------------------------------------------
diff --git a/sdks/other/ios/UGAPI/SBJson/SBJsonWriter.h b/sdks/other/ios/UGAPI/SBJson/SBJsonWriter.h
new file mode 100755
index 0000000..640816c
--- /dev/null
+++ b/sdks/other/ios/UGAPI/SBJson/SBJsonWriter.h
@@ -0,0 +1,117 @@
+/*
+ Copyright (C) 2009 Stig Brautaset. All rights reserved.
+ 
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+ 
+ * Redistributions of source code must retain the above copyright notice, this
+   list of conditions and the following disclaimer.
+ 
+ * Redistributions in binary form must reproduce the above copyright notice,
+   this list of conditions and the following disclaimer in the documentation
+   and/or other materials provided with the distribution.
+ 
+ * Neither the name of the author nor the names of its contributors may be used
+   to endorse or promote products derived from this software without specific
+   prior written permission.
+ 
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import <Foundation/Foundation.h>
+
+/**
+ @brief The JSON writer class.
+ 
+ This uses SBJsonStreamWriter internally.
+ 
+ @see @ref json2objc
+ */
+
+@interface SBJsonWriter : NSObject
+
+/**
+ @brief The maximum recursing depth.
+ 
+ Defaults to 32. If the input is nested deeper than this the input will be deemed to be
+ malicious and the parser returns nil, signalling an error. ("Nested too deep".) You can
+ turn off this security feature by setting the maxDepth value to 0.
+ */
+@property NSUInteger maxDepth;
+
+/**
+ @brief Return an error trace, or nil if there was no errors.
+ 
+ Note that this method returns the trace of the last method that failed.
+ You need to check the return value of the call you're making to figure out
+ if the call actually failed, before you know call this method.
+ */
+@property (readonly, copy) NSString *error;
+
+/**
+ @brief Whether we are generating human-readable (multiline) JSON.
+ 
+ Set whether or not to generate human-readable JSON. The default is NO, which produces
+ JSON without any whitespace. (Except inside strings.) If set to YES, generates human-readable
+ JSON with linebreaks after each array value and dictionary key/value pair, indented two
+ spaces per nesting level.
+ */
+@property BOOL humanReadable;
+
+/**
+ @brief Whether or not to sort the dictionary keys in the output.
+ 
+ If this is set to YES, the dictionary keys in the JSON output will be in sorted order.
+ (This is useful if you need to compare two structures, for example.) The default is NO.
+ */
+@property BOOL sortKeys;
+
+/**
+ @brief An optional comparator to be used if sortKeys is YES.
+ 
+ If this is nil, sorting will be done via @selector(compare:).
+ */
+@property (copy) NSComparator sortKeysComparator;
+
+/**
+ @brief Return JSON representation for the given object.
+ 
+ Returns a string containing JSON representation of the passed in value, or nil on error.
+ If nil is returned and @p error is not NULL, @p *error can be interrogated to find the cause of the error.
+ 
+ @param value any instance that can be represented as JSON text.
+ */
+- (NSString*)stringWithObject:(id)value;
+
+/**
+ @brief Return JSON representation for the given object.
+ 
+ Returns an NSData object containing JSON represented as UTF8 text, or nil on error.
+ 
+ @param value any instance that can be represented as JSON text.
+ */
+- (NSData*)dataWithObject:(id)value;
+
+/**
+ @brief Return JSON representation (or fragment) for the given object.
+ 
+ Returns a string containing JSON representation of the passed in value, or nil on error.
+ If nil is returned and @p error is not NULL, @p *error can be interrogated to find the cause of the error.
+ 
+ @param value any instance that can be represented as a JSON fragment
+ @param error pointer to object to be populated with NSError on failure
+ 
+ */- (NSString*)stringWithObject:(id)value
+                           error:(NSError**)error;
+
+
+@end

http://git-wip-us.apache.org/repos/asf/usergrid/blob/867060fa/sdks/other/ios/UGAPI/SBJson/SBJsonWriter.m
----------------------------------------------------------------------
diff --git a/sdks/other/ios/UGAPI/SBJson/SBJsonWriter.m b/sdks/other/ios/UGAPI/SBJson/SBJsonWriter.m
new file mode 100755
index 0000000..d200f9c
--- /dev/null
+++ b/sdks/other/ios/UGAPI/SBJson/SBJsonWriter.m
@@ -0,0 +1,112 @@
+/*
+ Copyright (C) 2009 Stig Brautaset. All rights reserved.
+ 
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+ 
+ * Redistributions of source code must retain the above copyright notice, this
+   list of conditions and the following disclaimer.
+ 
+ * Redistributions in binary form must reproduce the above copyright notice,
+   this list of conditions and the following disclaimer in the documentation
+   and/or other materials provided with the distribution.
+ 
+ * Neither the name of the author nor the names of its contributors may be used
+   to endorse or promote products derived from this software without specific
+   prior written permission.
+ 
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import "SBJsonWriter.h"
+#import "SBJsonStreamWriter.h"
+#import "SBJsonStreamWriterAccumulator.h"
+
+
+@interface SBJsonWriter ()
+@property (copy) NSString *error;
+@end
+
+@implementation SBJsonWriter
+
+@synthesize sortKeys;
+@synthesize humanReadable;
+
+@synthesize error;
+@synthesize maxDepth;
+
+@synthesize sortKeysComparator;
+
+- (id)init {
+    self = [super init];
+    if (self) {
+        self.maxDepth = 32u;        
+    }
+    return self;
+}
+
+
+- (NSString*)stringWithObject:(id)value {
+	NSData *data = [self dataWithObject:value];
+	if (data)
+		return [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
+	return nil;
+}	
+
+- (NSString*)stringWithObject:(id)value error:(NSError**)error_ {
+    NSString *tmp = [self stringWithObject:value];
+    if (tmp)
+        return tmp;
+    
+    if (error_) {
+		NSDictionary *ui = [NSDictionary dictionaryWithObjectsAndKeys:error, NSLocalizedDescriptionKey, nil];
+        *error_ = [NSError errorWithDomain:@"org.brautaset.SBJsonWriter.ErrorDomain" code:0 userInfo:ui];
+	}
+	
+    return nil;
+}
+
+- (NSData*)dataWithObject:(id)object {	
+    self.error = nil;
+
+    SBJsonStreamWriterAccumulator *accumulator = [[SBJsonStreamWriterAccumulator alloc] init];
+    
+	SBJsonStreamWriter *streamWriter = [[SBJsonStreamWriter alloc] init];
+	streamWriter.sortKeys = self.sortKeys;
+	streamWriter.maxDepth = self.maxDepth;
+	streamWriter.sortKeysComparator = self.sortKeysComparator;
+	streamWriter.humanReadable = self.humanReadable;
+    streamWriter.delegate = accumulator;
+	
+	BOOL ok = NO;
+	if ([object isKindOfClass:[NSDictionary class]])
+		ok = [streamWriter writeObject:object];
+	
+	else if ([object isKindOfClass:[NSArray class]])
+		ok = [streamWriter writeArray:object];
+		
+	else if ([object respondsToSelector:@selector(proxyForJson)])
+		return [self dataWithObject:[object proxyForJson]];
+	else {
+		self.error = @"Not valid type for JSON";
+		return nil;
+	}
+	
+	if (ok)
+		return accumulator.data;
+	
+	self.error = streamWriter.error;
+	return nil;	
+}
+	
+	
+@end

http://git-wip-us.apache.org/repos/asf/usergrid/blob/867060fa/sdks/other/ios/UGAPI/SSKeychain.h
----------------------------------------------------------------------
diff --git a/sdks/other/ios/UGAPI/SSKeychain.h b/sdks/other/ios/UGAPI/SSKeychain.h
new file mode 100644
index 0000000..23093b6
--- /dev/null
+++ b/sdks/other/ios/UGAPI/SSKeychain.h
@@ -0,0 +1,357 @@
+//
+//  SSKeychain.h
+//  SSToolkit
+//
+//  Created by Sam Soffes on 5/19/10.
+//  Copyright (c) 2009-2011 Sam Soffes. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+#import <Security/Security.h>
+
+/** Error codes that can be returned in NSError objects. */
+typedef enum {
+	/** No error. */
+	SSKeychainErrorNone = noErr,
+	
+	/** Some of the arguments were invalid. */
+	SSKeychainErrorBadArguments = -1001,
+	
+	/** There was no password. */
+	SSKeychainErrorNoPassword = -1002,
+	
+	/** One or more parameters passed internally were not valid. */
+	SSKeychainErrorInvalidParameter = errSecParam,
+	
+	/** Failed to allocate memory. */
+	SSKeychainErrorFailedToAllocated = errSecAllocate,
+	
+	/** No trust results are available. */
+	SSKeychainErrorNotAvailable = errSecNotAvailable,
+	
+	/** Authorization/Authentication failed. */
+	SSKeychainErrorAuthorizationFailed = errSecAuthFailed,
+	
+	/** The item already exists. */
+	SSKeychainErrorDuplicatedItem = errSecDuplicateItem,
+	
+	/** The item cannot be found.*/
+	SSKeychainErrorNotFound = errSecItemNotFound,
+	
+	/** Interaction with the Security Server is not allowed. */
+	SSKeychainErrorInteractionNotAllowed = errSecInteractionNotAllowed,
+	
+	/** Unable to decode the provided data. */
+	SSKeychainErrorFailedToDecode = errSecDecode
+} SSKeychainErrorCode;
+
+extern NSString *const kSSKeychainErrorDomain;
+
+/** Account name. */
+extern NSString *const kSSKeychainAccountKey;
+
+/**
+ Time the item was created.
+ 
+ The value will be a string.
+ */
+extern NSString *const kSSKeychainCreatedAtKey;
+
+/** Item class. */
+extern NSString *const kSSKeychainClassKey;
+
+/** Item description. */
+extern NSString *const kSSKeychainDescriptionKey;
+
+/** Item label. */
+extern NSString *const kSSKeychainLabelKey;
+
+/** Time the item was last modified.
+ 
+ The value will be a string.
+ */
+extern NSString *const kSSKeychainLastModifiedKey;
+
+/** Where the item was created. */
+extern NSString *const kSSKeychainWhereKey;
+
+/**
+ Simple wrapper for accessing accounts, getting passwords, setting passwords, and deleting passwords using the system
+ Keychain on Mac OS X and iOS.
+ 
+ This was originally inspired by EMKeychain and SDKeychain (both of which are now gone). Thanks to the authors.
+ SSKeychain has since switched to a simpler implementation that was abstracted from [SSToolkit](http://sstoolk.it).
+ */
+@interface SSKeychain : NSObject
+
+///-----------------------
+/// @name Getting Accounts
+///-----------------------
+
+/**
+ Returns an array containing the Keychain's accounts, or `nil` if the Keychain has no accounts.
+ 
+ See the `NSString` constants declared in SSKeychain.h for a list of keys that can be used when accessing the
+ dictionaries returned by this method.
+ 
+ @return An array of dictionaries containing the Keychain's accounts, or `nil` if the Keychain doesn't have any
+ accounts. The order of the objects in the array isn't defined.
+ 
+ @see allAccounts:
+ */
++ (NSArray *)allAccounts;
+
+/**
+ Returns an array containing the Keychain's accounts, or `nil` if the Keychain doesn't have any
+ accounts.
+ 
+ See the `NSString` constants declared in SSKeychain.h for a list of keys that can be used when accessing the
+ dictionaries returned by this method.
+ 
+ @param error If accessing the accounts fails, upon return contains an error that describes the problem.
+ 
+ @return An array of dictionaries containing the Keychain's accounts, or `nil` if the Keychain doesn't have any
+ accounts. The order of the objects in the array isn't defined.
+ 
+ @see allAccounts
+ */
++ (NSArray *)allAccounts:(NSError **)error;
+
+/**
+ Returns an array containing the Keychain's accounts for a given service, or `nil` if the Keychain doesn't have any
+ accounts for the given service.
+ 
+ See the `NSString` constants declared in SSKeychain.h for a list of keys that can be used when accessing the
+ dictionaries returned by this method.
+ 
+ @param serviceName The service for which to return the corresponding accounts.
+ 
+ @return An array of dictionaries containing the Keychain's accountsfor a given `serviceName`, or `nil` if the Keychain
+ doesn't have any accounts for the given `serviceName`. The order of the objects in the array isn't defined.
+ 
+ @see accountsForService:error:
+ */
++ (NSArray *)accountsForService:(NSString *)serviceName;
+
+/**
+ Returns an array containing the Keychain's accounts for a given service, or `nil` if the Keychain doesn't have any
+ accounts for the given service.
+ 
+ @param serviceName The service for which to return the corresponding accounts.
+ 
+ @param error If accessing the accounts fails, upon return contains an error that describes the problem.
+ 
+ @return An array of dictionaries containing the Keychain's accountsfor a given `serviceName`, or `nil` if the Keychain
+ doesn't have any accounts for the given `serviceName`. The order of the objects in the array isn't defined.
+ 
+ @see accountsForService:
+ */
++ (NSArray *)accountsForService:(NSString *)serviceName error:(NSError **)error;
+
+
+///------------------------
+/// @name Getting Passwords
+///------------------------
+
+/**
+ Returns a string containing the password for a given account and service, or `nil` if the Keychain doesn't have a
+ password for the given parameters.
+ 
+ @param serviceName The service for which to return the corresponding password.
+ 
+ @param account The account for which to return the corresponding password.
+ 
+ @return Returns a string containing the password for a given account and service, or `nil` if the Keychain doesn't
+ have a password for the given parameters.
+ 
+ @see passwordForService:account:error:
+ */
++ (NSString *)passwordForService:(NSString *)serviceName account:(NSString *)account;
+
+/**
+ Returns a string containing the password for a given account and service, or `nil` if the Keychain doesn't have a
+ password for the given parameters.
+ 
+ @param serviceName The service for which to return the corresponding password.
+ 
+ @param account The account for which to return the corresponding password.
+ 
+ @param error If accessing the password fails, upon return contains an error that describes the problem.
+ 
+ @return Returns a string containing the password for a given account and service, or `nil` if the Keychain doesn't
+ have a password for the given parameters.
+ 
+ @see passwordForService:account:
+ */
++ (NSString *)passwordForService:(NSString *)serviceName account:(NSString *)account error:(NSError **)error;
+
+/**
+ Returns the password data for a given account and service, or `nil` if the Keychain doesn't have data
+ for the given parameters.
+ 
+ @param serviceName The service for which to return the corresponding password.
+ 
+ @param account The account for which to return the corresponding password.
+ 
+ @param error If accessing the password fails, upon return contains an error that describes the problem.
+ 
+ @return Returns a the password data for the given account and service, or `nil` if the Keychain doesn't
+ have data for the given parameters.
+ 
+ @see passwordDataForService:account:error:
+ */
++ (NSData *)passwordDataForService:(NSString *)serviceName account:(NSString *)account;
+
+/**
+ Returns the password data for a given account and service, or `nil` if the Keychain doesn't have data
+ for the given parameters.
+ 
+ @param serviceName The service for which to return the corresponding password.
+ 
+ @param account The account for which to return the corresponding password.
+ 
+ @param error If accessing the password fails, upon return contains an error that describes the problem.
+ 
+ @return Returns a the password data for the given account and service, or `nil` if the Keychain doesn't
+ have a password for the given parameters.
+ 
+ @see passwordDataForService:account:
+ */
++ (NSData *)passwordDataForService:(NSString *)serviceName account:(NSString *)account error:(NSError **)error;
+
+
+///-------------------------
+/// @name Deleting Passwords
+///-------------------------
+
+/**
+ Deletes a password from the Keychain.
+ 
+ @param serviceName The service for which to delete the corresponding password.
+ 
+ @param account The account for which to delete the corresponding password.
+ 
+ @return Returns `YES` on success, or `NO` on failure.
+ 
+ @see deletePasswordForService:account:error:
+ */
++ (BOOL)deletePasswordForService:(NSString *)serviceName account:(NSString *)account;
+
+/**
+ Deletes a password from the Keychain.
+ 
+ @param serviceName The service for which to delete the corresponding password.
+ 
+ @param account The account for which to delete the corresponding password.
+ 
+ @param error If deleting the password fails, upon return contains an error that describes the problem.
+ 
+ @return Returns `YES` on success, or `NO` on failure.
+ 
+ @see deletePasswordForService:account:
+ */
++ (BOOL)deletePasswordForService:(NSString *)serviceName account:(NSString *)account error:(NSError **)error;
+
+
+///------------------------
+/// @name Setting Passwords
+///------------------------
+
+/**
+ Sets a password in the Keychain.
+ 
+ @param password The password to store in the Keychain.
+ 
+ @param serviceName The service for which to set the corresponding password.
+ 
+ @param account The account for which to set the corresponding password.
+ 
+ @return Returns `YES` on success, or `NO` on failure.
+ 
+ @see setPassword:forService:account:error:
+ */
++ (BOOL)setPassword:(NSString *)password forService:(NSString *)serviceName account:(NSString *)account;
+
+/**
+ Sets a password in the Keychain.
+ 
+ @param password The password to store in the Keychain.
+ 
+ @param serviceName The service for which to set the corresponding password.
+ 
+ @param account The account for which to set the corresponding password.
+ 
+ @param error If setting the password fails, upon return contains an error that describes the problem.
+ 
+ @return Returns `YES` on success, or `NO` on failure.
+ 
+ @see setPassword:forService:account:
+ */
++ (BOOL)setPassword:(NSString *)password forService:(NSString *)serviceName account:(NSString *)account error:(NSError **)error;
+
+/**
+ Sets arbirary data in the Keychain.
+ 
+ @param password The data to store in the Keychain.
+ 
+ @param serviceName The service for which to set the corresponding password.
+ 
+ @param account The account for which to set the corresponding password.
+ 
+ @param error If setting the password fails, upon return contains an error that describes the problem.
+ 
+ @return Returns `YES` on success, or `NO` on failure.
+ 
+ @see setPasswordData:forService:account:error:
+ */
++ (BOOL)setPasswordData:(NSData *)password forService:(NSString *)serviceName account:(NSString *)account;
+
+/**
+ Sets arbirary data in the Keychain.
+ 
+ @param password The data to store in the Keychain.
+ 
+ @param serviceName The service for which to set the corresponding password.
+ 
+ @param account The account for which to set the corresponding password.
+ 
+ @param error If setting the password fails, upon return contains an error that describes the problem.
+ 
+ @return Returns `YES` on success, or `NO` on failure.
+ 
+ @see setPasswordData:forService:account:
+ */
++ (BOOL)setPasswordData:(NSData *)password forService:(NSString *)serviceName account:(NSString *)account error:(NSError **)error;
+
+
+///--------------------
+/// @name Configuration
+///--------------------
+
+#if __IPHONE_4_0 && TARGET_OS_IPHONE
+/**
+ Returns the accessibility type for all future passwords saved to the Keychain.
+ 
+ @return Returns the accessibility type.
+ 
+ The return value will be `NULL` or one of the "Keychain Item Accessibility Constants" used for determining when a
+ keychain item should be readable.
+ 
+ @see accessibilityType
+ */
++ (CFTypeRef)accessibilityType;
+
+/**
+ Sets the accessibility type for all future passwords saved to the Keychain.
+ 
+ @param accessibilityType One of the "Keychain Item Accessibility Constants" used for determining when a keychain item
+ should be readable.
+ 
+ If the value is `NULL` (the default), the Keychain default will be used.
+ 
+ @see accessibilityType
+ */
++ (void)setAccessibilityType:(CFTypeRef)accessibilityType;
+#endif
+
+@end
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/usergrid/blob/867060fa/sdks/other/ios/UGAPI/SSKeychain.m
----------------------------------------------------------------------
diff --git a/sdks/other/ios/UGAPI/SSKeychain.m b/sdks/other/ios/UGAPI/SSKeychain.m
new file mode 100644
index 0000000..1267b5e
--- /dev/null
+++ b/sdks/other/ios/UGAPI/SSKeychain.m
@@ -0,0 +1,262 @@
+//
+//  SSKeychain.m
+//  SSToolkit
+//
+//  Created by Sam Soffes on 5/19/10.
+//  Copyright (c) 2009-2011 Sam Soffes. All rights reserved.
+//
+
+#import "SSKeychain.h"
+
+NSString *const kSSKeychainErrorDomain = @"com.samsoffes.sskeychain";
+
+NSString *const kSSKeychainAccountKey = @"acct";
+NSString *const kSSKeychainCreatedAtKey = @"cdat";
+NSString *const kSSKeychainClassKey = @"labl";
+NSString *const kSSKeychainDescriptionKey = @"desc";
+NSString *const kSSKeychainLabelKey = @"labl";
+NSString *const kSSKeychainLastModifiedKey = @"mdat";
+NSString *const kSSKeychainWhereKey = @"svce";
+
+#if __IPHONE_4_0 && TARGET_OS_IPHONE
+CFTypeRef SSKeychainAccessibilityType = NULL;
+#endif
+
+@interface SSKeychain ()
++ (NSMutableDictionary *)_queryForService:(NSString *)service account:(NSString *)account;
+@end
+
+@implementation SSKeychain
+
+#pragma mark - Getting Accounts
+
++ (NSArray *)allAccounts {
+    return [self accountsForService:nil error:nil];
+}
+
+
++ (NSArray *)allAccounts:(NSError **)error {
+    return [self accountsForService:nil error:error];
+}
+
+
++ (NSArray *)accountsForService:(NSString *)service {
+    return [self accountsForService:service error:nil];
+}
+
+
++ (NSArray *)accountsForService:(NSString *)service error:(NSError **)error {
+    OSStatus status = SSKeychainErrorBadArguments;
+    NSMutableDictionary *query = [self _queryForService:service account:nil];
+#if __has_feature(objc_arc)
+	[query setObject:(__bridge id)kCFBooleanTrue forKey:(__bridge id)kSecReturnAttributes];
+    [query setObject:(__bridge id)kSecMatchLimitAll forKey:(__bridge id)kSecMatchLimit];
+#else
+    [query setObject:(id)kCFBooleanTrue forKey:(id)kSecReturnAttributes];
+    [query setObject:(id)kSecMatchLimitAll forKey:(id)kSecMatchLimit];
+#endif
+	
+	CFTypeRef result = NULL;
+#if __has_feature(objc_arc)
+    status = SecItemCopyMatching((__bridge CFDictionaryRef)query, &result);
+#else
+	status = SecItemCopyMatching((CFDictionaryRef)query, &result);
+#endif
+    if (status != noErr && error != NULL) {
+		*error = [NSError errorWithDomain:kSSKeychainErrorDomain code:status userInfo:nil];
+		return nil;
+	}
+	
+#if __has_feature(objc_arc)
+	return (__bridge_transfer NSArray *)result;
+#else
+    return [(NSArray *)result autorelease];
+#endif
+}
+
+
+#pragma mark - Getting Passwords
+
++ (NSString *)passwordForService:(NSString *)service account:(NSString *)account {
+	return [self passwordForService:service account:account error:nil];
+}
+
+
++ (NSString *)passwordForService:(NSString *)service account:(NSString *)account error:(NSError **)error {
+    NSData *data = [self passwordDataForService:service account:account error:error];
+	if (data.length > 0) {
+		NSString *string = [[NSString alloc] initWithData:(NSData *)data encoding:NSUTF8StringEncoding];
+#if !__has_feature(objc_arc)
+		[string autorelease];
+#endif
+		return string;
+	}
+	
+	return nil;
+}
+
+
++ (NSData *)passwordDataForService:(NSString *)service account:(NSString *)account {
+    return [self passwordDataForService:service account:account error:nil];
+}
+
+
++ (NSData *)passwordDataForService:(NSString *)service account:(NSString *)account error:(NSError **)error {
+    OSStatus status = SSKeychainErrorBadArguments;
+	if (!service || !account) {
+		if (error) {
+			*error = [NSError errorWithDomain:kSSKeychainErrorDomain code:status userInfo:nil];
+		}
+		return nil;
+	}
+	
+	CFTypeRef result = NULL;
+	NSMutableDictionary *query = [self _queryForService:service account:account];
+#if __has_feature(objc_arc)
+	[query setObject:(__bridge id)kCFBooleanTrue forKey:(__bridge id)kSecReturnData];
+	[query setObject:(__bridge id)kSecMatchLimitOne forKey:(__bridge id)kSecMatchLimit];
+	status = SecItemCopyMatching((__bridge CFDictionaryRef)query, &result);
+#else
+	[query setObject:(id)kCFBooleanTrue forKey:(id)kSecReturnData];
+	[query setObject:(id)kSecMatchLimitOne forKey:(id)kSecMatchLimit];
+	status = SecItemCopyMatching((CFDictionaryRef)query, &result);
+#endif
+	
+	if (status != noErr && error != NULL) {
+		*error = [NSError errorWithDomain:kSSKeychainErrorDomain code:status userInfo:nil];
+		return nil;
+	}
+	
+#if __has_feature(objc_arc)
+	return (__bridge_transfer NSData *)result;
+#else
+    return [(NSData *)result autorelease];
+#endif
+}
+
+
+#pragma mark - Deleting Passwords
+
++ (BOOL)deletePasswordForService:(NSString *)service account:(NSString *)account {
+	return [self deletePasswordForService:service account:account error:nil];
+}
+
+
++ (BOOL)deletePasswordForService:(NSString *)service account:(NSString *)account error:(NSError **)error {
+	OSStatus status = SSKeychainErrorBadArguments;
+	if (service && account) {
+		NSMutableDictionary *query = [self _queryForService:service account:account];
+#if __has_feature(objc_arc)
+		status = SecItemDelete((__bridge CFDictionaryRef)query);
+#else
+		status = SecItemDelete((CFDictionaryRef)query);
+#endif
+	}
+	if (status != noErr && error != NULL) {
+		*error = [NSError errorWithDomain:kSSKeychainErrorDomain code:status userInfo:nil];
+	}
+	return (status == noErr);
+    
+}
+
+
+#pragma mark - Setting Passwords
+
++ (BOOL)setPassword:(NSString *)password forService:(NSString *)service account:(NSString *)account {
+	return [self setPassword:password forService:service account:account error:nil];
+}
+
+
++ (BOOL)setPassword:(NSString *)password forService:(NSString *)service account:(NSString *)account error:(NSError **)error {
+    NSData *data = [password dataUsingEncoding:NSUTF8StringEncoding];
+    return [self setPasswordData:data forService:service account:account error:error];
+}
+
+
++ (BOOL)setPasswordData:(NSData *)password forService:(NSString *)service account:(NSString *)account {
+    return [self setPasswordData:password forService:service account:account error:nil];
+}
+
+
++ (BOOL)setPasswordData:(NSData *)password forService:(NSString *)service account:(NSString *)account error:(NSError **)error {
+    OSStatus status = SSKeychainErrorBadArguments;
+	if (password && service && account) {
+        [self deletePasswordForService:service account:account];
+        NSMutableDictionary *query = [self _queryForService:service account:account];
+#if __has_feature(objc_arc)
+		[query setObject:password forKey:(__bridge id)kSecValueData];
+#else
+		[query setObject:password forKey:(id)kSecValueData];
+#endif
+		
+#if __IPHONE_4_0 && TARGET_OS_IPHONE
+		if (SSKeychainAccessibilityType) {
+#if __has_feature(objc_arc)
+			[query setObject:(id)[self accessibilityType] forKey:(__bridge id)kSecAttrAccessible];
+#else
+			[query setObject:(id)[self accessibilityType] forKey:(id)kSecAttrAccessible];
+#endif
+		}
+#endif
+		
+#if __has_feature(objc_arc)
+        status = SecItemAdd((__bridge CFDictionaryRef)query, NULL);
+#else
+		status = SecItemAdd((CFDictionaryRef)query, NULL);
+#endif
+	}
+	if (status != noErr && error != NULL) {
+		*error = [NSError errorWithDomain:kSSKeychainErrorDomain code:status userInfo:nil];
+	}
+	return (status == noErr);
+}
+
+
+#pragma mark - Configuration
+
+#if __IPHONE_4_0 && TARGET_OS_IPHONE
++ (CFTypeRef)accessibilityType {
+	return SSKeychainAccessibilityType;
+}
+
+
++ (void)setAccessibilityType:(CFTypeRef)accessibilityType {
+	CFRetain(accessibilityType);
+	if (SSKeychainAccessibilityType) {
+		CFRelease(SSKeychainAccessibilityType);
+	}
+	SSKeychainAccessibilityType = accessibilityType;
+}
+#endif
+
+
+#pragma mark - Private
+
++ (NSMutableDictionary *)_queryForService:(NSString *)service account:(NSString *)account {
+    NSMutableDictionary *dictionary = [NSMutableDictionary dictionaryWithCapacity:3];
+#if __has_feature(objc_arc)
+    [dictionary setObject:(__bridge id)kSecClassGenericPassword forKey:(__bridge id)kSecClass];
+#else
+	[dictionary setObject:(id)kSecClassGenericPassword forKey:(id)kSecClass];
+#endif
+	
+    if (service) {
+#if __has_feature(objc_arc)
+		[dictionary setObject:service forKey:(__bridge id)kSecAttrService];
+#else
+		[dictionary setObject:service forKey:(id)kSecAttrService];
+#endif
+	}
+	
+    if (account) {
+#if __has_feature(objc_arc)
+		[dictionary setObject:account forKey:(__bridge id)kSecAttrAccount];
+#else
+		[dictionary setObject:account forKey:(id)kSecAttrAccount];
+#endif
+	}
+	
+    return dictionary;
+}
+
+@end
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/usergrid/blob/867060fa/sdks/other/ios/UGAPI/UGActivity.h
----------------------------------------------------------------------
diff --git a/sdks/other/ios/UGAPI/UGActivity.h b/sdks/other/ios/UGAPI/UGActivity.h
new file mode 100755
index 0000000..1139518
--- /dev/null
+++ b/sdks/other/ios/UGAPI/UGActivity.h
@@ -0,0 +1,64 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * 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.
+ */
+
+#import <Foundation/Foundation.h>
+
+@interface UGActivity : NSObject
+
+// In order for an activity to be valid, you must call setBasics and one of the setActor functions. 
+// In all cases, the return value will be YES if the function succeeded and NO if there
+// was a problem with the set. A response of NO will usually mean you sent nil for a required field.
+
+// these are the basics of the activity.
+// verb: the action being taken
+// category: The type of activity it is
+// content: The content of this activity. The format is defined by the category
+// title: The title of this category.
+-(BOOL) setBasics: (NSString *)verb category:(NSString *)category content:(NSString *)content title:(NSString *)title;
+
+// actorUserName: The username of the entity doing this activity
+// actorDisplayName: The visible name of the entity doing this activity
+// actorUUID: The UUID of the entity doing this activity
+-(BOOL) setActorInfo: (NSString *)actorUserName actorDisplayName:(NSString *)actorDisplayName actorUUID:(NSString *)actorUUID;
+
+// actorUserName: The username of the entity doing this activity
+// actorDisplayName: The visible name of the entity doing this activity
+// actorUUID: The UUID of the entity doing this activity
+-(BOOL) setActorInfo: (NSString *)actorUserName actorDisplayName:(NSString *)actorDisplayName actorEmail:(NSString *)actorEmail;
+
+// Associating an object with the Activity is optional. You don't have to supply an object at all.
+
+// objectType: the type of the object associated with this activity
+// displayName: The visible name of the object associated with this activity
+// entityType: the entity type of this object within UserGrid. The actual type that it is stored under
+// entityUUID: The uuid of the object associated with this activity
+-(BOOL)setObjectInfo: (NSString *)objectType displayName:(NSString *)displayName entityType:(NSString *)entityType entityUUID:(NSString *)entityUUID;
+
+// similar to the function above, but it takes an arbitrary object content (which can be new and unique) instead of an already-defined object
+-(BOOL)setObjectInfo: (NSString *)objectType displayName:(NSString *)displayName objectContent:(NSString *)objectContent;
+
+// similar to the other two functions, but simply has the type and displayName. In this case, the 
+// "content" value supplied in setBasics will be used as the object content.
+-(BOOL)setObjectInfo: (NSString *)objectType displayName:(NSString *)displayName;
+
+// returns YES if this is properly set up. NO if it has not been properly set up
+-(BOOL)isValid;
+
+// turn this object in to an NSDictionary. Used internally by UGClient
+-(NSDictionary *)toNSDictionary;
+
+@end

http://git-wip-us.apache.org/repos/asf/usergrid/blob/867060fa/sdks/other/ios/UGAPI/UGActivity.m
----------------------------------------------------------------------
diff --git a/sdks/other/ios/UGAPI/UGActivity.m b/sdks/other/ios/UGAPI/UGActivity.m
new file mode 100755
index 0000000..3eaea00
--- /dev/null
+++ b/sdks/other/ios/UGAPI/UGActivity.m
@@ -0,0 +1,263 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * 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.
+ */
+
+#import "UGActivity.h"
+
+// the way they have set up the object info
+enum
+{
+    kUGActivityNoObject = 0,
+    kUGActivityObjectEntity = 1,
+    kUGActivityObjectContent = 2,
+    kUGActivityObjectNameOnly = 3
+};
+
+@implementation UGActivity
+{
+    // basic stats
+    NSString *m_verb;
+    NSString *m_category;
+    NSString *m_content;
+    NSString *m_title;
+    
+    // stats related to the actor
+    NSString *m_actorUserName;
+    NSString *m_actorDisplayName;
+    NSString *m_actorUUID;
+    NSString *m_actorEmail;
+    
+    // stats related to the object
+    NSString *m_objectType;
+    NSString *m_objectDisplayName;
+    
+    // for the object, either these must be set...
+    NSString *m_entityType;
+    NSString *m_entityUUID;
+    
+    // ...or this must be set
+    NSString *m_objectContent;
+    
+    // or it will use the content field as the content for the object
+    
+    // tracking how the object is currently set up
+    int m_objectDataType;
+}
+
+-(id)init
+{
+    self = [super init];
+    if ( self )
+    {
+        m_objectDataType = kUGActivityNoObject;
+    }
+    return self;
+}
+
+-(BOOL) setBasics: (NSString *)verb category:(NSString *)category content:(NSString *)content title:(NSString *)title
+{
+    // input validation
+    if ( !verb || !category || !content || !title ) return NO;
+    
+    m_verb = verb;
+    m_category = category;
+    m_content = content;
+    m_title = title;
+
+    return YES;
+}
+
+-(BOOL) setActorInfo: (NSString *)actorUserName actorDisplayName:(NSString *)actorDisplayName actorUUID:(NSString *)actorUUID
+{
+    // input validation
+    if ( !actorUserName || !actorDisplayName || !actorUUID ) return NO;
+    
+    m_actorUserName = actorUserName;
+    m_actorDisplayName = actorDisplayName;
+    m_actorUUID = actorUUID;
+    m_actorEmail = nil;
+    
+    return YES;
+}
+
+-(BOOL) setActorInfo: (NSString *)actorUserName actorDisplayName:(NSString *)actorDisplayName actorEmail:(NSString *)actorEmail
+{
+    // input validation
+    if ( !actorUserName || !actorDisplayName || !actorEmail ) return NO;
+    
+    m_actorUserName = actorUserName;
+    m_actorDisplayName = actorDisplayName;
+    m_actorEmail = actorEmail;
+    m_actorUUID = nil;
+    
+    return YES;
+}
+
+-(BOOL)setObjectInfo: (NSString *)objectType displayName:(NSString *)displayName entityType:(NSString *)entityType entityUUID:(NSString *)entityUUID
+{
+    // input validation
+    if ( !objectType || !displayName || !entityType || !entityUUID ) return NO;
+    
+    m_objectType = objectType;
+    m_objectDisplayName = displayName;
+    m_entityType = entityType;
+    m_entityUUID = entityUUID;
+    m_objectDataType = kUGActivityObjectEntity;
+    
+    // clear out the unused value
+    m_objectContent = nil;
+    
+    return YES;
+}
+
+-(BOOL)setObjectInfo: (NSString *)objectType displayName:(NSString *)displayName objectContent:(NSString *)objectContent
+{
+    // input validation
+    if ( !objectType || !displayName || !objectContent ) return NO;
+    
+    m_objectType = objectType;
+    m_objectDisplayName = displayName;
+    m_objectContent = objectContent;
+    m_objectDataType = kUGActivityObjectContent;
+    
+    // clear out the unused values
+    m_entityType = nil;
+    m_entityUUID = nil;
+    
+    return YES;
+}
+
+-(BOOL)setObjectInfo: (NSString *)objectType displayName:(NSString *)displayName
+{
+    // input validation
+    if ( !objectType || !displayName ) return NO;
+    
+    m_objectType = objectType;
+    m_objectDisplayName = displayName;
+    m_objectDataType = kUGActivityObjectNameOnly;
+    
+    // we'll use m_content when the time comes. But we don't want to 
+    // assume they've set it yet. They can call the setup functions in any order.
+    m_objectContent = nil; 
+    m_entityType = nil;
+    m_entityUUID = nil;
+    
+    return YES;
+}
+
+-(BOOL)isValid
+{
+    // if any of the required values are nil, it's not valid
+    if ( !m_verb || !m_category || !m_content || !m_title || !m_actorUserName || !m_actorDisplayName )
+    {
+        return NO;
+    }
+    
+    // either the uuid or the email of the user must be valid
+    if ( !m_actorUUID && !m_actorEmail )
+    {
+        return NO;
+    }
+    
+    // the object data requirements are based on the object setup
+    switch ( m_objectDataType )
+    {
+        case kUGActivityObjectEntity:
+        {
+            if ( !m_objectType || !m_objectDisplayName || !m_entityType || !m_entityUUID ) return NO;
+        }
+        break;
+            
+        case kUGActivityObjectContent:
+        {
+            if ( !m_objectType || !m_objectDisplayName || !m_objectContent ) return NO;
+        }
+            break;
+            
+        case kUGActivityObjectNameOnly:
+        {
+            if ( !m_objectType || !m_objectDisplayName ) return NO;
+        }
+        break;
+            
+        // kUGActivityNoObject has no requirements.
+    }
+    
+    // if we're here, we're valid.
+    return YES;
+}
+
+-(NSDictionary *)toNSDictionary
+{
+    NSMutableDictionary *ret = [NSMutableDictionary new];
+    
+    // add all the fields in
+    [ret setObject:@"activity" forKey:@"type"];
+    [ret setObject:m_verb forKey:@"verb"];
+    [ret setObject:m_category forKey:@"category"];
+    [ret setObject:m_content forKey:@"content"];
+    [ret setObject:m_title forKey:@"title"];
+    
+    // make the actor's subdictionary
+    NSMutableDictionary *actor = [NSMutableDictionary new];
+    [actor setObject:@"person" forKey:@"type"];
+    [actor setObject:@"user" forKey:@"entityType"];
+    [actor setObject:m_actorDisplayName forKey:@"displayName"];
+    
+    if ( m_actorUUID )
+    {
+        [actor setObject:m_actorUUID forKey:@"uuid"];
+    }
+    if ( m_actorEmail )
+    {
+        [actor setObject:m_actorEmail forKey:@"email"];
+    }
+    
+    // add the actor to the main dict
+    [ret setObject:actor forKey:@"actor"];
+    
+    if ( m_objectDataType != kUGActivityNoObject )
+    {
+        // there is an associated object. Prep a dict for it
+        NSMutableDictionary *object = [NSMutableDictionary new];
+        
+        // these fields are involved in all cases
+        [object setObject:m_objectType forKey:@"type"];
+        [object setObject:m_objectDisplayName forKey:@"displayName"];
+        
+        if ( m_objectDataType == kUGActivityObjectContent )
+        {
+            [object setObject:m_objectContent forKey:@"content"];
+        }
+        else if ( m_objectDataType == kUGActivityObjectNameOnly )
+        {
+            [object setObject:m_content forKey:@"content"];
+        }
+        else if ( m_objectDataType == kUGActivityObjectEntity )
+        {
+            [object setObject:m_entityType forKey:@"entityType"];
+            [object setObject:m_entityUUID forKey:@"entityUUID"];
+        }
+        
+        // add to the dict
+        [ret setObject:object forKey:@"object"];
+    }
+    
+    // done with the assembly
+    return ret;
+}
+
+@end