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 2014/04/10 17:20:58 UTC

[01/12] git commit: Refactored Group module methods to execute callbacks with the [err, response, self] format

Repository: incubator-usergrid
Updated Branches:
  refs/heads/master 594b9fad5 -> d8221a196
  refs/pull/96/merge [deleted] c40bec1ef


Refactored Group module methods to execute callbacks with the [err, response, self] format


Project: http://git-wip-us.apache.org/repos/asf/incubator-usergrid/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-usergrid/commit/39fac0df
Tree: http://git-wip-us.apache.org/repos/asf/incubator-usergrid/tree/39fac0df
Diff: http://git-wip-us.apache.org/repos/asf/incubator-usergrid/diff/39fac0df

Branch: refs/heads/master
Commit: 39fac0dfb6a13fa89decf23afcda221ef5084741
Parents: e5f2acf
Author: ryan bridges <rb...@apigee.com>
Authored: Tue Mar 25 12:17:01 2014 -0400
Committer: ryan bridges <rb...@apigee.com>
Committed: Tue Mar 25 12:17:01 2014 -0400

----------------------------------------------------------------------
 sdks/html5-javascript/lib/modules/Group.js | 118 +++++++++++-------------
 1 file changed, 56 insertions(+), 62 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/39fac0df/sdks/html5-javascript/lib/modules/Group.js
----------------------------------------------------------------------
diff --git a/sdks/html5-javascript/lib/modules/Group.js b/sdks/html5-javascript/lib/modules/Group.js
index a479c80..cdbef60 100644
--- a/sdks/html5-javascript/lib/modules/Group.js
+++ b/sdks/html5-javascript/lib/modules/Group.js
@@ -43,41 +43,33 @@ Usergrid.Group.prototype.fetch = function(callback) {
     endpoint:memberEndpoint
   }
 
-  this._client.request(groupOptions, function(err, data){
+  this._client.request(groupOptions, function(err, response){
     if(err) {
       if(self._client.logging) {
         console.log('error getting group');
       }
-      doCallback(callback, [err, data], self);
+      doCallback(callback, [err, response], self);
     } else {
-      if(data.entities && data.entities.length) {
-        var groupData = data.entities[0];
-        self._data = groupData || {};
-        self._client.request(memberOptions, function(err, data) {
+      var entities = response.getEntities();
+      if(entities && entities.length) {
+        var groupresponse = entities.shift();
+        //self._response = groupresponse || {};
+        self._client.request(memberOptions, function(err, response) {
           if(err && self._client.logging) {
             console.log('error getting group users');
           } else {
-            if(data.entities) {
-              var count = data.entities.length;
-              self._list = [];
-              for (var i = 0; i < count; i++) {
-                var uuid = data.entities[i].uuid;
-                if(uuid) {
-                  var entityData = data.entities[i] || {};
-                  var entityOptions = {
-                    type: entityData.type,
+            self._list = response.getEntities();
+              .filter(function(entity){return isUUID(entity.uuid)})
+              .map(function(entity){
+                  return new Usergrid.Entity({
+                    type: entity.type,
                     client: self._client,
-                    uuid:uuid,
-                    data:entityData
-                  };
-                  var entity = new Usergrid.Entity(entityOptions);
-                  self._list.push(entity);
-                }
-
-              }
-            }
+                    uuid:entity.uuid,
+                    response:entity //TODO: deprecate this property
+                  });
+              })            
           }
-          doCallback(callback, [err, data, self._list], self);
+          doCallback(callback, [err, response, self], self);
         });
       }
     }
@@ -93,11 +85,12 @@ Usergrid.Group.prototype.fetch = function(callback) {
  *  @return {function} callback(err, data);
  */
 Usergrid.Group.prototype.members = function(callback) {
-  doCallback(callback, [null, this._list], this);
+  //doCallback(callback, [null, this._list, this], this);
+  return this._list;
 };
 
 /*
- *  Adds a user to the group, and refreshes the group object.
+ *  Adds an existing user to the group, and refreshes the group object.
  *
  *  Options object: {user: user_entity}
  *
@@ -109,18 +102,21 @@ Usergrid.Group.prototype.members = function(callback) {
  */
 Usergrid.Group.prototype.add = function(options, callback) {
   var self = this;
-  var options = {
-    method:"POST",
-    endpoint:"groups/"+this._path+"/users/"+options.user.get('username')
-  }
-
-  this._client.request(options, function(error, data){
-    if(error) {
-      doCallback(callback, [error, data, data.entities], self);
-    } else {
-      self.fetch(callback);
+  if(options.user){
+    var options = {
+      method:"POST",
+      endpoint:"groups/"+this._path+"/users/"+options.user.get('username')
     }
-  });
+    this._client.request(options, function(error, response){
+      if(error) {
+        doCallback(callback, [error, response, self], self);
+      } else {
+        self.fetch(callback);
+      }
+    });
+  }else{
+    doCallback(callback, ["no user specified"], this);
+  }
 }
 
 /*
@@ -136,19 +132,21 @@ Usergrid.Group.prototype.add = function(options, callback) {
  */
 Usergrid.Group.prototype.remove = function(options, callback) {
   var self = this;
-
-  var options = {
-    method:"DELETE",
-    endpoint:"groups/"+this._path+"/users/"+options.user.get('username')
-  }
-
-  this._client.request(options, function(error, data){
-    if(error) {
-      doCallback(callback, [error, data], self);
-    } else {
-      self.fetch(callback);
+  if(options.user){
+    var options = {
+      method:"DELETE",
+      endpoint:"groups/"+this._path+"/users/"+options.user.get('username')
     }
-  });
+    this._client.request(options, function(error, response){
+      if(error) {
+        doCallback(callback, [error, response, self], self);
+      } else {
+        self.fetch(callback);
+      }
+    });
+  }else{
+    doCallback(callback, ["no user specified"], this);
+  }
 }
 
 /*
@@ -161,19 +159,16 @@ Usergrid.Group.prototype.remove = function(options, callback) {
  */
 Usergrid.Group.prototype.feed = function(callback) {
   var self = this;
-
-  var endpoint = "groups/"+this._path+"/feed";
-
   var options = {
     method:"GET",
-    endpoint:endpoint
+    endpoint:"groups/"+this._path+"/feed"
   }
 
-  this._client.request(options, function(err, data){
+  this._client.request(options, function(err, response){
     if (err && self.logging) {
       console.log('error trying to log user in');
     }
-    doCallback(callback, [err, data, data.entities], self);
+    doCallback(callback, [err, response, self], self);
   });
 }
 
@@ -189,8 +184,9 @@ Usergrid.Group.prototype.feed = function(callback) {
  * @returns {callback} callback(err, entity)
  */
 Usergrid.Group.prototype.createGroupActivity = function(options, callback){
+  var self = this;
   var user = options.user;
-  options = {
+  var entity = new Usergrid.Entity({
     client: this._client,
     data: {
       actor: {
@@ -210,10 +206,8 @@ Usergrid.Group.prototype.createGroupActivity = function(options, callback){
       "content": options.content,
       "type": 'groups/' + this._path + '/activities'
     }
-  }
-
-  var entity = new Usergrid.Entity(options);
-  entity.save(function(err, data) {
-    doCallback(callback, [err, entity]);
+  });
+  entity.save(function(err, response, entity) {
+    doCallback(callback, [err, response, self]);
   });
 };


[10/12] git commit: Updated examples and fixed issues where encountered. Updated changelog

Posted by sn...@apache.org.
Updated examples and fixed issues where encountered. Updated changelog


Project: http://git-wip-us.apache.org/repos/asf/incubator-usergrid/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-usergrid/commit/39f0ebeb
Tree: http://git-wip-us.apache.org/repos/asf/incubator-usergrid/tree/39f0ebeb
Diff: http://git-wip-us.apache.org/repos/asf/incubator-usergrid/diff/39f0ebeb

Branch: refs/heads/master
Commit: 39f0ebeb1883df9bdedfbc5f4e4684a99dc9efad
Parents: 3c47925
Author: ryan bridges <rb...@apigee.com>
Authored: Tue Apr 1 16:40:09 2014 -0400
Committer: ryan bridges <rb...@apigee.com>
Committed: Tue Apr 1 16:40:09 2014 -0400

----------------------------------------------------------------------
 sdks/html5-javascript/changelog.md          | 13 ++++++-
 sdks/html5-javascript/examples/dogs/app.js  |  6 ++--
 sdks/html5-javascript/examples/test/test.js | 46 ++++++++++++------------
 sdks/html5-javascript/index.html            | 12 +++----
 sdks/html5-javascript/lib/modules/Client.js | 21 +++++------
 sdks/html5-javascript/lib/modules/Entity.js | 18 +++++-----
 sdks/html5-javascript/usergrid.js           | 32 ++++++++---------
 sdks/html5-javascript/usergrid.min.js       |  2 +-
 8 files changed, 80 insertions(+), 70 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/39f0ebeb/sdks/html5-javascript/changelog.md
----------------------------------------------------------------------
diff --git a/sdks/html5-javascript/changelog.md b/sdks/html5-javascript/changelog.md
index a2435cb..692a1a4 100644
--- a/sdks/html5-javascript/changelog.md
+++ b/sdks/html5-javascript/changelog.md
@@ -1,7 +1,18 @@
 ##Change log
 ###0.11.0
 - Removed 'getOnExist' flag from createEntity and createGroup. Handling of duplicate entity errors is now the responsibility of the client.
-
+- Usergrid.Group.prototype.fetch returns self instead of group list
+- Usergrid.Client.prototype.createGroup updated to new callback format
+- Usergrid.Client.prototype.createEntity updated to new callback format
+- Usergrid.Client.prototype.getEntity updated to new callback format
+- Usergrid.Collection instantiation no longer fetches the collection automatically, this no longer takes a callback
+- Usergrid.Entity.prototype.save no longer handles password changes
+- Usergrid.Entity.prototype.changePassword added to handle password requests
+- Usergrid.Counter no longer needs a callback
+- Usergrid.Asset.prototype.download sets appropriate mime type for content
+- Usergrid.Asset.prototype.upload implemented retry interval to mitigate errors when an asset has not fully propagated
+ 
+ 
 ###0.10.8
 - Added support for Events and Counters
 - Added support for Folders and Assets

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/39f0ebeb/sdks/html5-javascript/examples/dogs/app.js
----------------------------------------------------------------------
diff --git a/sdks/html5-javascript/examples/dogs/app.js b/sdks/html5-javascript/examples/dogs/app.js
index 17289f3..55b0e17 100755
--- a/sdks/html5-javascript/examples/dogs/app.js
+++ b/sdks/html5-javascript/examples/dogs/app.js
@@ -44,11 +44,11 @@ $(document).ready(function () {
 
   var dogs;
 
-  client.createCollection(options, function (err, dogs) {
+  client.createCollection(options, function (err, response, collection) {
     if (err) {
       $('#mydoglist').html('could not load dogs');
     } else {
-
+      dogs=collection;
       //bind the next button to the proper method in the collection object
       $('#next-button').bind('click', function() {
         $('#message').html('');
@@ -174,4 +174,4 @@ $(document).ready(function () {
     }
   });
 
-});
\ No newline at end of file
+});

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/39f0ebeb/sdks/html5-javascript/examples/test/test.js
----------------------------------------------------------------------
diff --git a/sdks/html5-javascript/examples/test/test.js b/sdks/html5-javascript/examples/test/test.js
index ff9dc82..fb65d98 100755
--- a/sdks/html5-javascript/examples/test/test.js
+++ b/sdks/html5-javascript/examples/test/test.js
@@ -303,7 +303,7 @@ function makeNewDog(step) {
 		name:'Ralph'+_unique
 	}
 
-	client.createEntity(options, function (err, dog) {
+	client.createEntity(options, function (err, response, dog) {
 		if (err) {
 			error('dog not created');
 		} else {
@@ -414,7 +414,7 @@ function testDogsCollection(step) {
 		qs:{ql:'order by index'}
 	}
 
-	client.createCollection(options, function (err, dogs) {
+	client.createCollection(options, function (err, response, dogs) {
 		if (err) {
 			error('could not make collection');
 		} else {
@@ -519,7 +519,7 @@ function cleanupAllDogs(step){
 		qs:{limit:50} //limit statement set to 50
 	}
 
-	client.createCollection(options, function (err, dogs) {
+	client.createCollection(options, function (err, response, dogs) {
 		if (err) {
 			error('could not get all dogs');
 		} else {
@@ -574,7 +574,7 @@ function prepareDatabaseForNewUser(step) {
 
 function createUser(step) {
 	client.signup(_username, _password, _email, 'Marty McFly',
-		function (err, marty) {
+		function (err, response, marty) {
 			if (err){
 				error('user not created');
 				runner(step, marty);
@@ -608,7 +608,7 @@ function getExistingUser(step, marty) {
 		type:'users',
 		username:_username
 	}
-	client.getEntity(options, function(err, existingUser){
+	client.getEntity(options, function(err, response, existingUser){
 		if (err){
 			error('existing user not retrieved');
 		} else {
@@ -644,7 +644,7 @@ function loginUser(step, marty) {
 	username = _username;
 	password = _password;
 	client.login(username, password,
-		function (err) {
+		function (err, response, user) {
 			if (err) {
 				error('could not log user in');
 			} else {
@@ -659,6 +659,7 @@ function loginUser(step, marty) {
 				//Then make calls against the API.  For example, you can
 				//get the user entity this way:
 				client.getLoggedInUser(function(err, data, user) {
+					console.error(err, data, user);
 					if(err) {
 						error('could not get logged in user');
 					} else {
@@ -680,8 +681,9 @@ function loginUser(step, marty) {
 function changeUsersPassword(step, marty) {
 
 	marty.set('oldpassword', _password);
+	marty.set('password', _newpassword);
 	marty.set('newpassword', _newpassword);
-	marty.save(function(err){
+	marty.changePassword(function(err, response){
 		if (err){
 			error('user password not updated');
 		} else {
@@ -712,13 +714,13 @@ function reloginUser(step, marty) {
 	username = _username
 	password = _newpassword;
 	client.login(username, password,
-		function (err) {
-		if (err) {
-			error('could not relog user in');
-		} else {
-			success('user has been re-logged in');
-			runner(step, marty);
-		}
+		function (err, response, marty) {
+			if (err) {
+				error('could not relog user in');
+			} else {
+				success('user has been re-logged in');
+				runner(step, marty);
+			}
 		}
 	);
 }
@@ -741,7 +743,7 @@ function createDog(step, marty) {
 		breed:'mutt'
 	}
 
-	client.createEntity(options, function (err, dog) {
+	client.createEntity(options, function (err, response, dog) {
 		if (err) {
 			error('POST new dog by logged in user failed');
 		} else {
@@ -754,14 +756,14 @@ function createDog(step, marty) {
 
 function userLikesDog(step, marty, dog) {
 
-	marty.connect('likes', dog, function (err, data) {
+	marty.connect('likes', dog, function (err, response, data) {
 		if (err) {
 			error('connection not created');
 			runner(step, marty);
 		} else {
 
 			//call succeeded, so pull the connections back down
-			marty.getConnections('likes', function (err, data) {
+			marty.getConnections('likes', function (err, response, data) {
 				if (err) {
 						error('could not get connections');
 				} else {
@@ -842,7 +844,7 @@ function createExistingEntity(step, marty) {
 		name:'einstein'
 	}
 
-	client.createEntity(options, function (err, dog) {
+	client.createEntity(options, function (err, response, dog) {
 		if (err) {
 			error('Create new entity to use for existing entity failed');
 		} else {
@@ -858,7 +860,7 @@ function createExistingEntity(step, marty) {
 				name:'einstein',
 				breed:'mutt'
 			}
-			client.createEntity(options, function (err, newdog) {
+			client.createEntity(options, function (err, response, newdog) {
 				if (err) {
 					success('Create new entity to use for existing entity failed');
 				} else {
@@ -887,7 +889,7 @@ function createNewEntityNoName(step, marty) {
    othervalue:"something else"
 	}
 
-	client.createEntity(options, function (err, entity) {
+	client.createEntity(options, function (err, response, entity) {
 		if (err) {
 			error('Create new entity with no name failed');
 		} else {
@@ -907,7 +909,7 @@ function cleanUpUsers(step){
     qs:{limit:50} //limit statement set to 50
   }
 
-  client.createCollection(options, function (err, users) {
+  client.createCollection(options, function (err, response, users) {
     if (err) {
       error('could not get all users');
     } else {
@@ -940,7 +942,7 @@ function cleanUpDogs(step){
       qs:{limit:50} //limit statement set to 50
     }
 
-    client.createCollection(options, function (err, dogs) {
+    client.createCollection(options, function (err, response, dogs) {
       if (err) {
         error('could not get all dogs');
       } else {

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/39f0ebeb/sdks/html5-javascript/index.html
----------------------------------------------------------------------
diff --git a/sdks/html5-javascript/index.html b/sdks/html5-javascript/index.html
index 359e8c8..2019b6c 100755
--- a/sdks/html5-javascript/index.html
+++ b/sdks/html5-javascript/index.html
@@ -8,22 +8,22 @@
    </head>
    <body>
       <div class="header">
-         <img src="examples/resources/images/apigee.png"> App Services (Usergrid) Javascript SDK
+         <img src="examples/resources/images/apigee.png"> Usergrid Javascript SDK
       </div>
       <div id="main" class="main">
          <br/>
          <h2>Javascript SDK</h2>
-         This SDK is designed to enable you to connect your apps to the App Services (Usergrid) API.
+         This SDK is designed to enable you to connect your apps to the Usergrid API.
          <br/>
          <br/>
          <h2>Read me</h2>
          View the read me file for the SDK:
-         <a href="https://github.com/apigee/usergrid-javascript-sdk/blob/master/README.md">https://github.com/apigee/usergrid-javascript-sdk/blob/master/README.md</a>.
+         <a href="https://github.com/usergrid/usergrid/blob/master/sdks/html5-javascript/README.md">https://github.com/usergrid/usergrid/blob/master/sdks/html5-javascript/README.md</a>.
          <br/>
          <br/>
          <h2>API documentation</h2>
-         For more information on App Services, see our docs:
-         <a href="http://apigee.com/docs/app_services">http://apigee.com/docs/app_service</a>
+         For more information on Usergrid, see the Apache docs:
+         <a href="http://usergrid.incubator.apache.org/">http://usergrid.incubator.apache.org/</a>
          <br/>
          <br/>
 
@@ -41,7 +41,7 @@
          <br/>
          <a href="examples/facebook/facebook.html" style="font-size: 20px;">Facebook Login Example</a>
          <br/>
-         This app shows you how to use Facebook to log into App Services (Usergrid).
+         This app shows you how to use Facebook to log into Usergrid.
          <br/>
          <br/>
          <a href="examples/test/test.html" style="font-size: 20px;">Tests for examples in readme file</a>

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/39f0ebeb/sdks/html5-javascript/lib/modules/Client.js
----------------------------------------------------------------------
diff --git a/sdks/html5-javascript/lib/modules/Client.js b/sdks/html5-javascript/lib/modules/Client.js
index a87c935..bc6f39a 100644
--- a/sdks/html5-javascript/lib/modules/Client.js
+++ b/sdks/html5-javascript/lib/modules/Client.js
@@ -519,19 +519,19 @@
         grant_type: 'password'
       }
     };
-    self.request(options, function(err, data) {
+    self.request(options, function(err, response) {
       var user = {};
       if (err) {
         if (self.logging) console.log('error trying to log user in');
       } else {
         var options = {
           client: self,
-          data: data.user
+          data: response.user
         };
         user = new Usergrid.Entity(options);
-        self.setToken(data.access_token);
+        self.setToken(response.access_token);
       }
-      doCallback(callback, [err, data, user]);
+      doCallback(callback, [err, response, user]);
     });
   };
 
@@ -665,27 +665,28 @@
    *  @return {callback} callback(err, data)
    */
   Usergrid.Client.prototype.getLoggedInUser = function(callback) {
+    var self = this;
     if (!this.getToken()) {
-      callback(true, null, null);
+        doCallback(callback, [new UsergridError("Access Token not set"), null, self], self);
     } else {
-      var self = this;
       var options = {
         method: 'GET',
         endpoint: 'users/me'
       };
-      this.request(options, function(err, data) {
+      this.request(options, function(err, response) {
         if (err) {
           if (self.logging) {
             console.log('error trying to log user in');
           }
-          doCallback(callback, [err, data, null], self);
+          console.error(err, response);
+          doCallback(callback, [err, response, self], self);
         } else {
           var options = {
             client: self,
-            data: data.entities[0]
+            data: response.getEntity()
           };
           var user = new Usergrid.Entity(options);
-          doCallback(callback, [null, data, user], self);
+          doCallback(callback, [null, response, user], self);
         }
       });
     }

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/39f0ebeb/sdks/html5-javascript/lib/modules/Entity.js
----------------------------------------------------------------------
diff --git a/sdks/html5-javascript/lib/modules/Entity.js b/sdks/html5-javascript/lib/modules/Entity.js
index d5dc3ec..48d9e1e 100644
--- a/sdks/html5-javascript/lib/modules/Entity.js
+++ b/sdks/html5-javascript/lib/modules/Entity.js
@@ -351,17 +351,15 @@ Usergrid.Entity.prototype.addOrRemoveConnection = function(method, connection, e
  *
  */
 Usergrid.Entity.prototype.getEntityId = function(entity) {
-  var id = false;
-  if (isUUID(entity.get('uuid'))) {
-    id = entity.get('uuid');
-  } else {
-    if (this.get("type") === 'users') {
-      id = entity.get('username');
-    } else if (entity.get('name')) {
-      id = entity.get('name');
+    var id;
+    if (isUUID(entity.get("uuid"))) {
+        id = entity.get("uuid");
+    } else if (this.get("type") === "users") {
+        id = entity.get("username");
+    } else  {
+        id = entity.get("name");
     }
-  }
-  return id;
+    return id;
 };
 
 /*

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/39f0ebeb/sdks/html5-javascript/usergrid.js
----------------------------------------------------------------------
diff --git a/sdks/html5-javascript/usergrid.js b/sdks/html5-javascript/usergrid.js
index 79ab355..2c4efd7 100644
--- a/sdks/html5-javascript/usergrid.js
+++ b/sdks/html5-javascript/usergrid.js
@@ -1040,19 +1040,19 @@ function doCallback(callback, params, context) {
                 grant_type: "password"
             }
         };
-        self.request(options, function(err, data) {
+        self.request(options, function(err, response) {
             var user = {};
             if (err) {
                 if (self.logging) console.log("error trying to log user in");
             } else {
                 var options = {
                     client: self,
-                    data: data.user
+                    data: response.user
                 };
                 user = new Usergrid.Entity(options);
-                self.setToken(data.access_token);
+                self.setToken(response.access_token);
             }
-            doCallback(callback, [ err, data, user ]);
+            doCallback(callback, [ err, response, user ]);
         });
     };
     Usergrid.Client.prototype.reAuthenticateLite = function(callback) {
@@ -1171,27 +1171,28 @@ function doCallback(callback, params, context) {
    *  @return {callback} callback(err, data)
    */
     Usergrid.Client.prototype.getLoggedInUser = function(callback) {
+        var self = this;
         if (!this.getToken()) {
-            callback(true, null, null);
+            doCallback(callback, [ new UsergridError("Access Token not set"), null, self ], self);
         } else {
-            var self = this;
             var options = {
                 method: "GET",
                 endpoint: "users/me"
             };
-            this.request(options, function(err, data) {
+            this.request(options, function(err, response) {
                 if (err) {
                     if (self.logging) {
                         console.log("error trying to log user in");
                     }
-                    doCallback(callback, [ err, data, null ], self);
+                    console.error(err, response);
+                    doCallback(callback, [ err, response, self ], self);
                 } else {
                     var options = {
                         client: self,
-                        data: data.entities[0]
+                        data: response.getEntity()
                     };
                     var user = new Usergrid.Entity(options);
-                    doCallback(callback, [ null, data, user ], self);
+                    doCallback(callback, [ null, response, user ], self);
                 }
             });
         }
@@ -1671,15 +1672,13 @@ Usergrid.Entity.prototype.addOrRemoveConnection = function(method, connection, e
  *
  */
 Usergrid.Entity.prototype.getEntityId = function(entity) {
-    var id = false;
+    var id;
     if (isUUID(entity.get("uuid"))) {
         id = entity.get("uuid");
+    } else if (this.get("type") === "users") {
+        id = entity.get("username");
     } else {
-        if (this.get("type") === "users") {
-            id = entity.get("username");
-        } else if (entity.get("name")) {
-            id = entity.get("name");
-        }
+        id = entity.get("name");
     }
     return id;
 };
@@ -3006,7 +3005,6 @@ Usergrid.Asset.prototype.upload = function(data, callback) {
     fr.onload = function() {
         var binary = fr.result;
         xhr.overrideMimeType("application/octet-stream");
-        // setTimeout(function() {
         xhr.sendAsBinary(binary);
     };
     fr.readAsBinaryString(data);


[07/12] Added convenience methods for createAsset and createCounter

Posted by sn...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/3c47925e/sdks/html5-javascript/usergrid.min.js
----------------------------------------------------------------------
diff --git a/sdks/html5-javascript/usergrid.min.js b/sdks/html5-javascript/usergrid.min.js
index ccec845..14a8078 100644
--- a/sdks/html5-javascript/usergrid.min.js
+++ b/sdks/html5-javascript/usergrid.min.js
@@ -1,3 +1,3 @@
 /*! usergrid@0.11.0 2014-04-01 */
-function extend(subClass,superClass){var F=function(){};return F.prototype=superClass.prototype,subClass.prototype=new F,subClass.prototype.constructor=subClass,subClass.superclass=superClass.prototype,superClass.prototype.constructor==Object.prototype.constructor&&(superClass.prototype.constructor=superClass),subClass}function propCopy(from,to){for(var prop in from)from.hasOwnProperty(prop)&&(to[prop]="object"==typeof from[prop]&&"object"==typeof to[prop]?propCopy(from[prop],to[prop]):from[prop]);return to}function NOOP(){}function isValidUrl(url){if(!url)return!1;var doc,base,anchor,isValid=!1;try{doc=document.implementation.createHTMLDocument(""),base=doc.createElement("base"),base.href=base||window.lo,doc.head.appendChild(base),anchor=doc.createElement("a"),anchor.href=url,doc.body.appendChild(anchor),isValid=!(""===anchor.href)}catch(e){console.error(e)}finally{return doc.head.removeChild(base),doc.body.removeChild(anchor),base=null,anchor=null,doc=null,isValid}}function isUUID
 (uuid){return uuid?uuidValueRegex.test(uuid):!1}function encodeParams(params){var queryString;return params&&Object.keys(params)&&(queryString=[].slice.call(arguments).reduce(function(a,b){return a.concat(b instanceof Array?b:[b])},[]).filter(function(c){return"object"==typeof c}).reduce(function(p,c){return c instanceof Array?p.push(c):p=p.concat(Object.keys(c).map(function(key){return[key,c[key]]})),p},[]).reduce(function(p,c){return 2===c.length?p.push(c):p=p.concat(c),p},[]).reduce(function(p,c){return c[1]instanceof Array?c[1].forEach(function(v){p.push([c[0],v])}):p.push(c),p},[]).map(function(c){return c[1]=encodeURIComponent(c[1]),c.join("=")}).join("&")),queryString}function isFunction(f){return f&&null!==f&&"function"==typeof f}function doCallback(callback,params,context){var returnValue;return isFunction(callback)&&(params||(params=[]),context||(context=this),params.push(context),returnValue=callback.apply(context,params)),returnValue}function getSafeTime(prop){var time;s
 witch(typeof prop){case"undefined":time=Date.now();break;case"number":time=prop;break;case"string":time=isNaN(prop)?Date.parse(prop):parseInt(prop);break;default:time=Date.parse(prop.toString())}return time}var UsergridEventable=function(){throw Error("'UsergridEventable' is not intended to be invoked directly")};UsergridEventable.prototype={bind:function(event,fn){this._events=this._events||{},this._events[event]=this._events[event]||[],this._events[event].push(fn)},unbind:function(event,fn){this._events=this._events||{},event in this._events!=!1&&this._events[event].splice(this._events[event].indexOf(fn),1)},trigger:function(event){if(this._events=this._events||{},event in this._events!=!1)for(var i=0;i<this._events[event].length;i++)this._events[event][i].apply(this,Array.prototype.slice.call(arguments,1))}},UsergridEventable.mixin=function(destObject){for(var props=["bind","unbind","trigger"],i=0;i<props.length;i++)props[i]in destObject.prototype&&(console.warn("overwriting '"+p
 rops[i]+"' on '"+destObject.name+"'."),console.warn("the previous version can be found at '_"+props[i]+"' on '"+destObject.name+"'."),destObject.prototype["_"+props[i]]=destObject.prototype[props[i]]),destObject.prototype[props[i]]=UsergridEventable.prototype[props[i]]},function(){function Logger(name){this.logEnabled=!0,this.init(name,!0)}var name="Logger",global=this,overwrittenName=global[name];return Logger.METHODS=["log","error","warn","info","debug","assert","clear","count","dir","dirxml","exception","group","groupCollapsed","groupEnd","profile","profileEnd","table","time","timeEnd","trace"],Logger.prototype.init=function(name,logEnabled){this.name=name||"UNKNOWN",this.logEnabled=logEnabled||!0;var addMethod=function(method){this[method]=this.createLogMethod(method)}.bind(this);Logger.METHODS.forEach(addMethod)},Logger.prototype.createLogMethod=function(method){return Logger.prototype.log.bind(this,method)},Logger.prototype.prefix=function(method,args){var prepend="["+method.t
 oUpperCase()+"]["+name+"]:	";return-1!==["log","error","warn","info"].indexOf(method)&&("string"==typeof args[0]?args[0]=prepend+args[0]:args.unshift(prepend)),args},Logger.prototype.log=function(){var args=[].slice.call(arguments);method=args.shift(),-1===Logger.METHODS.indexOf(method)&&(method="log"),this.logEnabled&&console&&console[method]&&(args=this.prefix(method,args),console[method].apply(console,args))},Logger.prototype.setLogEnabled=function(logEnabled){this.logEnabled=logEnabled||!0},Logger.mixin=function(destObject){destObject.__logger=new Logger(destObject.name||"UNKNOWN");var addMethod=function(method){method in destObject.prototype&&(console.warn("overwriting '"+method+"' on '"+destObject.name+"'."),console.warn("the previous version can be found at '_"+method+"' on '"+destObject.name+"'."),destObject.prototype["_"+method]=destObject.prototype[method]),destObject.prototype[method]=destObject.__logger.createLogMethod(method)};Logger.METHODS.forEach(addMethod)},global[n
 ame]=Logger,global[name].noConflict=function(){return overwrittenName&&(global[name]=overwrittenName),Logger},global[name]}(),function(global){function Promise(){this.complete=!1,this.error=null,this.result=null,this.callbacks=[]}var name="Promise",overwrittenName=global[name];return Promise.prototype.then=function(callback,context){var f=function(){return callback.apply(context,arguments)};this.complete?f(this.error,this.result):this.callbacks.push(f)},Promise.prototype.done=function(error,result){if(this.complete=!0,this.error=error,this.result=result,this.callbacks){for(var i=0;i<this.callbacks.length;i++)this.callbacks[i](error,result);this.callbacks.length=0}},Promise.join=function(promises){function notifier(i){return function(error,result){completed+=1,errors[i]=error,results[i]=result,completed===total&&p.done(errors,results)}}for(var p=new Promise,total=promises.length,completed=0,errors=[],results=[],i=0;total>i;i++)promises[i]().then(notifier(i));return p},Promise.chain=f
 unction(promises,error,result){var p=new Promise;return null===promises||0===promises.length?p.done(error,result):promises[0](error,result).then(function(res,err){promises.splice(0,1),promises?Promise.chain(promises,res,err).then(function(r,e){p.done(r,e)}):p.done(res,err)}),p},global[name]=Promise,global[name].noConflict=function(){return overwrittenName&&(global[name]=overwrittenName),Promise},global[name]}(this),function(){function partial(){var args=Array.prototype.slice.call(arguments),fn=args.shift();return fn.bind(this,args)}function Ajax(){function encode(data){var result="";if("string"==typeof data)result=data;else{var e=encodeURIComponent;for(var i in data)data.hasOwnProperty(i)&&(result+="&"+e(i)+"="+e(data[i]))}return result}function request(m,u,d){var timeout,p=new Promise;return self.logger.time(m+" "+u),function(xhr){xhr.onreadystatechange=function(){4===this.readyState&&(self.logger.timeEnd(m+" "+u),clearTimeout(timeout),p.done(null,this))},xhr.onerror=function(respo
 nse){clearTimeout(timeout),p.done(response,null)},xhr.oncomplete=function(){clearTimeout(timeout),self.logger.timeEnd(m+" "+u),self.info("%s request to %s returned %s",m,u,this.status)},xhr.open(m,u),d&&("object"==typeof d&&(d=JSON.stringify(d)),xhr.setRequestHeader("Content-Type","application/json"),xhr.setRequestHeader("Accept","application/json")),timeout=setTimeout(function(){xhr.abort(),p.done("API Call timed out.",null)},3e4),xhr.send(encode(d))}(new XMLHttpRequest),p}this.logger=new global.Logger(name);var self=this;this.request=request,this.get=partial(request,"GET"),this.post=partial(request,"POST"),this.put=partial(request,"PUT"),this.delete=partial(request,"DELETE")}var exports,name="Ajax",global=this,overwrittenName=global[name];return global[name]=new Ajax,global[name].noConflict=function(){return overwrittenName&&(global[name]=overwrittenName),exports},global[name]}(),window.console=window.console||{},window.console.log=window.console.log||function(){};var uuidValueReg
 ex=/^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/;!function(global){function Usergrid(){this.logger=new Logger(name)}var name="Usergrid",overwrittenName=global[name],VALID_REQUEST_METHODS=["GET","POST","PUT","DELETE"];return Usergrid.isValidEndpoint=function(){return!0},Usergrid.Request=function(method,endpoint,query_params,data,callback){var p=new Promise;if(this.logger=new global.Logger("Usergrid.Request"),this.logger.time("process request "+method+" "+endpoint),this.endpoint=endpoint+"?"+encodeParams(query_params),this.method=method.toUpperCase(),this.data="object"==typeof data?JSON.stringify(data):data,-1===VALID_REQUEST_METHODS.indexOf(this.method))throw new UsergridInvalidHTTPMethodError("invalid request method '"+this.method+"'");if(!isValidUrl(this.endpoint))throw this.logger.error(endpoint,this.endpoint,/^https:\/\//.test(endpoint)),new UsergridInvalidURIError("The provided endpoint is not valid: "+this.endpoint);var request=function(){retur
 n Ajax.request(this.method,this.endpoint,this.data)}.bind(this),response=function(err,request){return new Usergrid.Response(err,request)}.bind(this),oncomplete=function(err,response){p.done(err,response),this.logger.info("REQUEST",err,response),doCallback(callback,[err,response]),this.logger.timeEnd("process request "+method+" "+endpoint)}.bind(this);return Promise.chain([request,response]).then(oncomplete),p},Usergrid.Response=function(err,response){var p=new Promise,data=null;try{data=JSON.parse(response.responseText)}catch(e){data={}}switch(Object.keys(data).forEach(function(key){Object.defineProperty(this,key,{value:data[key],enumerable:!0})}.bind(this)),Object.defineProperty(this,"logger",{enumerable:!1,configurable:!1,writable:!1,value:new global.Logger(name)}),Object.defineProperty(this,"success",{enumerable:!1,configurable:!1,writable:!0,value:!0}),Object.defineProperty(this,"err",{enumerable:!1,configurable:!1,writable:!0,value:err}),Object.defineProperty(this,"status",{enu
 merable:!1,configurable:!1,writable:!0,value:parseInt(response.status)}),Object.defineProperty(this,"statusGroup",{enumerable:!1,configurable:!1,writable:!0,value:this.status-this.status%100}),this.statusGroup){case 200:this.success=!0;break;case 400:case 500:case 300:case 100:default:this.success=!1}return this.success?p.done(null,this):p.done(UsergridError.fromResponse(data),this),p},Usergrid.Response.prototype.getEntities=function(){var entities;return this.success&&(entities=this.data?this.data.entities:this.entities),entities||[]},Usergrid.Response.prototype.getEntity=function(){var entities=this.getEntities();return entities[0]},Usergrid.VERSION=Usergrid.USERGRID_SDK_VERSION="0.11.0",global[name]=Usergrid,global[name].noConflict=function(){return overwrittenName&&(global[name]=overwrittenName),Usergrid},global[name]}(this),function(){var exports,name="Client",global=this,overwrittenName=global[name];return Usergrid.Client=function(options){this.URI=options.URI||"https://api.us
 ergrid.com",options.orgName&&this.set("orgName",options.orgName),options.appName&&this.set("appName",options.appName),options.qs&&this.setObject("default_qs",options.qs),this.buildCurl=options.buildCurl||!1,this.logging=options.logging||!1},Usergrid.Client.prototype.request=function(options,callback){var uri,method=options.method||"GET",endpoint=options.endpoint,body=options.body||{},qs=options.qs||{},mQuery=options.mQuery||!1,orgName=this.get("orgName"),appName=this.get("appName"),default_qs=this.getObject("default_qs");if(!mQuery&&!orgName&&!appName)return logoutCallback();uri=mQuery?this.URI+"/"+endpoint:this.URI+"/"+orgName+"/"+appName+"/"+endpoint,this.getToken()&&(qs.access_token=this.getToken()),default_qs&&(qs=propCopy(qs,default_qs));{var self=this;new Usergrid.Request(method,uri,qs,body,function(err,response){err?doCallback(callback,[err,response,self],self):doCallback(callback,[null,response,self],self)})}},Usergrid.Client.prototype.buildAssetURL=function(uuid){var self=t
 his,qs={},assetURL=this.URI+"/"+this.orgName+"/"+this.appName+"/assets/"+uuid+"/data";self.getToken()&&(qs.access_token=self.getToken());var encoded_params=encodeParams(qs);return encoded_params&&(assetURL+="?"+encoded_params),assetURL},Usergrid.Client.prototype.createGroup=function(options,callback){var group=new Usergrid.Group({path:options.path,client:this,data:options});group.save(function(err,response){doCallback(callback,[err,response,group],group)})},Usergrid.Client.prototype.createEntity=function(options,callback){var entity=new Usergrid.Entity({client:this,data:options});entity.save(function(err,response){doCallback(callback,[err,response,entity],entity)})},Usergrid.Client.prototype.getEntity=function(options,callback){var entity=new Usergrid.Entity({client:this,data:options});entity.fetch(function(err,response){doCallback(callback,[err,response,entity],entity)})},Usergrid.Client.prototype.restoreEntity=function(serializedObject){var data=JSON.parse(serializedObject),option
 s={client:this,data:data},entity=new Usergrid.Entity(options);return entity},Usergrid.Client.prototype.createCollection=function(options,callback){options.client=this;var collection=new Usergrid.Collection(options);collection.fetch(function(err,response,collection){doCallback(callback,[err,response,collection],this)})},Usergrid.Client.prototype.restoreCollection=function(serializedObject){var data=JSON.parse(serializedObject);data.client=this;var collection=new Usergrid.Collection(data);return collection},Usergrid.Client.prototype.getFeedForUser=function(username,callback){var options={method:"GET",endpoint:"users/"+username+"/feed"};this.request(options,function(err,data){err?doCallback(callback,[err]):doCallback(callback,[err,data,data.getEntities()])})},Usergrid.Client.prototype.createUserActivity=function(user,options,callback){options.type="users/"+user+"/activities",options={client:this,data:options};var entity=new Usergrid.Entity(options);entity.save(function(err,data){doCall
 back(callback,[err,data,entity])})},Usergrid.Client.prototype.createUserActivityWithEntity=function(user,content,callback){var username=user.get("username"),options={actor:{displayName:username,uuid:user.get("uuid"),username:username,email:user.get("email"),picture:user.get("picture"),image:{duration:0,height:80,url:user.get("picture"),width:80}},verb:"post",content:content};this.createUserActivity(username,options,callback)},Usergrid.Client.prototype.calcTimeDiff=function(){var seconds=0,time=this._end-this._start;try{seconds=(time/10/60).toFixed(2)}catch(e){return 0}return seconds},Usergrid.Client.prototype.setToken=function(token){this.set("token",token)},Usergrid.Client.prototype.getToken=function(){return this.get("token")},Usergrid.Client.prototype.setObject=function(key,value){value&&(value=JSON.stringify(value)),this.set(key,value)},Usergrid.Client.prototype.set=function(key,value){var keyStore="apigee_"+key;this[key]=value,"undefined"!=typeof Storage&&(value?localStorage.se
 tItem(keyStore,value):localStorage.removeItem(keyStore))},Usergrid.Client.prototype.getObject=function(key){return JSON.parse(this.get(key))},Usergrid.Client.prototype.get=function(key){var keyStore="apigee_"+key,value=null;return this[key]?value=this[key]:"undefined"!=typeof Storage&&(value=localStorage.getItem(keyStore)),value},Usergrid.Client.prototype.signup=function(username,password,email,name,callback){var options={type:"users",username:username,password:password,email:email,name:name};this.createEntity(options,callback)},Usergrid.Client.prototype.login=function(username,password,callback){var self=this,options={method:"POST",endpoint:"token",body:{username:username,password:password,grant_type:"password"}};self.request(options,function(err,data){var user={};if(err)self.logging&&console.log("error trying to log user in");else{var options={client:self,data:data.user};user=new Usergrid.Entity(options),self.setToken(data.access_token)}doCallback(callback,[err,data,user])})},User
 grid.Client.prototype.reAuthenticateLite=function(callback){var self=this,options={method:"GET",endpoint:"management/me",mQuery:!0};this.request(options,function(err,response){err&&self.logging?console.log("error trying to re-authenticate user"):self.setToken(response.data.access_token),doCallback(callback,[err])})},Usergrid.Client.prototype.reAuthenticate=function(email,callback){var self=this,options={method:"GET",endpoint:"management/users/"+email,mQuery:!0};this.request(options,function(err,response){var data,organizations={},applications={},user={};if(err&&self.logging)console.log("error trying to full authenticate user");else{data=response.data,self.setToken(data.token),self.set("email",data.email),localStorage.setItem("accessToken",data.token),localStorage.setItem("userUUID",data.uuid),localStorage.setItem("userEmail",data.email);var userData={username:data.username,email:data.email,name:data.name,uuid:data.uuid},options={client:self,data:userData};user=new Usergrid.Entity(op
 tions),organizations=data.organizations;var org="";try{var existingOrg=self.get("orgName");org=organizations[existingOrg]?organizations[existingOrg]:organizations[Object.keys(organizations)[0]],self.set("orgName",org.name)}catch(e){err=!0,self.logging&&console.log("error selecting org")}applications=self.parseApplicationsArray(org),self.selectFirstApp(applications),self.setObject("organizations",organizations),self.setObject("applications",applications)}doCallback(callback,[err,data,user,organizations,applications],self)})},Usergrid.Client.prototype.loginFacebook=function(facebookToken,callback){var self=this,options={method:"GET",endpoint:"auth/facebook",qs:{fb_access_token:facebookToken}};this.request(options,function(err,data){var user={};if(err&&self.logging)console.log("error trying to log user in");else{var options={client:self,data:data.user};user=new Usergrid.Entity(options),self.setToken(data.access_token)}doCallback(callback,[err,data,user],self)})},Usergrid.Client.prototy
 pe.getLoggedInUser=function(callback){if(this.getToken()){var self=this,options={method:"GET",endpoint:"users/me"};this.request(options,function(err,data){if(err)self.logging&&console.log("error trying to log user in"),doCallback(callback,[err,data,null],self);else{var options={client:self,data:data.entities[0]},user=new Usergrid.Entity(options);doCallback(callback,[null,data,user],self)}})}else callback(!0,null,null)},Usergrid.Client.prototype.isLoggedIn=function(){var token=this.getToken();return"undefined"!=typeof token&&null!==token},Usergrid.Client.prototype.logout=function(){this.setToken()},Usergrid.Client.prototype.destroyToken=function(username,token,revokeAll,callback){var options={client:self,method:"PUT"};options.endpoint=revokeAll===!0?"users/"+username+"/revoketokens":null===token?"users/"+username+"/revoketoken?token="+this.getToken():"users/"+username+"/revoketoken?token="+token,this.request(options,function(err,data){err?(self.logging&&console.log("error destroying 
 access token"),doCallback(callback,[err,data,null],self)):(console.log(revokeAll===!0?"all user tokens invalidated":"token invalidated"),doCallback(callback,[err,data,null],self))})},Usergrid.Client.prototype.logoutAndDestroyToken=function(username,token,revokeAll,callback){null===username?console.log("username required to revoke tokens"):(this.destroyToken(username,token,revokeAll,callback),(revokeAll===!0||token===this.getToken()||null===token)&&this.setToken(null))},Usergrid.Client.prototype.buildCurlCall=function(options){var curl=["curl"],method=(options.method||"GET").toUpperCase(),body=options.body,uri=options.uri;return curl.push("-X"),curl.push(["POST","PUT","DELETE"].indexOf(method)>=0?method:"GET"),curl.push(uri),"object"==typeof body&&Object.keys(body).length>0&&-1!==["POST","PUT"].indexOf(method)&&(curl.push("-d"),curl.push("'"+JSON.stringify(body)+"'")),curl=curl.join(" "),console.log(curl),curl},Usergrid.Client.prototype.getDisplayImage=function(email,picture,size){si
 ze=size||50;var image="https://apigee.com/usergrid/images/user_profile.png";try{picture?image=picture:email.length&&(image="https://secure.gravatar.com/avatar/"+MD5(email)+"?s="+size+encodeURI("&d=https://apigee.com/usergrid/images/user_profile.png"))}catch(e){}finally{return image}},global[name]=Usergrid.Client,global[name].noConflict=function(){return overwrittenName&&(global[name]=overwrittenName),exports},global[name]}();var ENTITY_SYSTEM_PROPERTIES=["metadata","created","modified","oldpassword","newpassword","type","activated","uuid"];Usergrid.Entity=function(options){this._data={},this._client=void 0,options&&(this.set(options.data||{}),this._client=options.client||{})},Usergrid.Entity.isEntity=function(obj){return obj&&obj instanceof Usergrid.Entity},Usergrid.Entity.isPersistedEntity=function(obj){return isEntity(obj)&&isUUID(obj.get("uuid"))},Usergrid.Entity.prototype.serialize=function(){return JSON.stringify(this._data)},Usergrid.Entity.prototype.get=function(key){var valu
 e;if(0===arguments.length?value=this._data:arguments.length>1&&(key=[].slice.call(arguments).reduce(function(p,c){return c instanceof Array?p=p.concat(c):p.push(c),p},[])),key instanceof Array){var self=this;value=key.map(function(k){return self.get(k)})}else"undefined"!=typeof key&&(value=this._data[key]);return value},Usergrid.Entity.prototype.set=function(key,value){if("object"==typeof key)for(var field in key)this._data[field]=key[field];else"string"==typeof key?null===value?delete this._data[key]:this._data[key]=value:this._data={}},Usergrid.Entity.prototype.getEndpoint=function(){var name,type=this.get("type"),nameProperties=["uuid","name"];if(void 0===type)throw new UsergridError("cannot fetch entity, no entity type specified","no_type_specified");return/^users?$/.test(type)&&nameProperties.unshift("username"),name=this.get(nameProperties).filter(function(x){return null!==x&&"undefined"!=typeof x}).shift(),name?[type,name].join("/"):type},Usergrid.Entity.prototype.save=functi
 on(callback){var self=this,type=this.get("type"),method="POST",entityId=this.get("uuid"),entityData=this.get(),options={method:method,endpoint:type};entityId&&(options.method="PUT",options.endpoint+="/"+entityId),options.body=Object.keys(entityData).filter(function(key){return-1===ENTITY_SYSTEM_PROPERTIES.indexOf(key)}).reduce(function(data,key){return data[key]=entityData[key],data},{}),self._client.request(options,function(err,response){var entity=response.getEntity();entity&&(self.set(entity),self.set("type",/^\//.test(response.path)?response.path.substring(1):response.path)),err&&self._client.logging&&console.log("could not save entity"),doCallback(callback,[err,response,self],self)})},Usergrid.Entity.prototype.changePassword=function(oldpassword,password,newpassword,callback){var self=this;if("function"==typeof oldpassword&&void 0===callback&&(callback=oldpassword,oldpassword=self.get("oldpassword"),password=self.get("password"),newpassword=self.get("newpassword")),self.set({pa
 ssword:null,oldpassword:null,newpassword:null}),!(/^users?$/.test(self.get("type"))&&oldpassword&&newpassword))throw new UsergridInvalidArgumentError("Invalid arguments passed to 'changePassword'");var options={method:"PUT",endpoint:"users/"+self.get("uuid")+"/password",body:{uuid:self.get("uuid"),username:self.get("username"),password:password,oldpassword:oldpassword,newpassword:newpassword}};self._client.request(options,function(err,response){err&&self._client.logging&&console.log("could not update user"),doCallback(callback,[err,response,self],self)})},Usergrid.Entity.prototype.fetch=function(callback){var endpoint,self=this;endpoint=this.getEndpoint();var options={method:"GET",endpoint:endpoint};this._client.request(options,function(err,response){var entity=response.getEntity();entity&&self.set(entity),doCallback(callback,[err,response,self],self)})},Usergrid.Entity.prototype.destroy=function(callback){var self=this,endpoint=this.getEndpoint(),options={method:"DELETE",endpoint:e
 ndpoint};this._client.request(options,function(err,response){err||self.set(null),doCallback(callback,[err,response,self],self)})},Usergrid.Entity.prototype.connect=function(connection,entity,callback){this.addOrRemoveConnection("POST",connection,entity,callback)},Usergrid.Entity.prototype.disconnect=function(connection,entity,callback){this.addOrRemoveConnection("DELETE",connection,entity,callback)},Usergrid.Entity.prototype.addOrRemoveConnection=function(method,connection,entity,callback){var self=this;if(-1==["POST","DELETE"].indexOf(method.toUpperCase()))throw new UsergridInvalidArgumentError("invalid method for connection call. must be 'POST' or 'DELETE'");var connecteeType=entity.get("type"),connectee=this.getEntityId(entity);if(!connectee)throw new UsergridInvalidArgumentError("connectee could not be identified");var connectorType=this.get("type"),connector=this.getEntityId(this);if(!connector)throw new UsergridInvalidArgumentError("connector could not be identified");var endp
 oint=[connectorType,connector,connection,connecteeType,connectee].join("/"),options={method:method,endpoint:endpoint};this._client.request(options,function(err,response){err&&self._client.logging&&console.log("There was an error with the connection call"),doCallback(callback,[err,response,self],self)})},Usergrid.Entity.prototype.getEntityId=function(entity){var id=!1;return isUUID(entity.get("uuid"))?id=entity.get("uuid"):"users"===this.get("type")?id=entity.get("username"):entity.get("name")&&(id=entity.get("name")),id},Usergrid.Entity.prototype.getConnections=function(connection,callback){var self=this,connectorType=this.get("type"),connector=this.getEntityId(this);if(connector){var endpoint=connectorType+"/"+connector+"/"+connection+"/",options={method:"GET",endpoint:endpoint};this._client.request(options,function(err,data){err&&self._client.logging&&console.log("entity could not be connected"),self[connection]={};for(var length=data&&data.entities?data.entities.length:0,i=0;leng
 th>i;i++)"user"===data.entities[i].type?self[connection][data.entities[i].username]=data.entities[i]:self[connection][data.entities[i].name]=data.entities[i];doCallback(callback,[err,data,data.entities],self)})}else if("function"==typeof callback){var error="Error in getConnections - no uuid specified.";self._client.logging&&console.log(error),doCallback(callback,[!0,error],self)}},Usergrid.Entity.prototype.getGroups=function(callback){var self=this,endpoint="users/"+this.get("uuid")+"/groups",options={method:"GET",endpoint:endpoint};this._client.request(options,function(err,data){err&&self._client.logging&&console.log("entity could not be connected"),self.groups=data.entities,doCallback(callback,[err,data,data.entities],self)})},Usergrid.Entity.prototype.getActivities=function(callback){var self=this,endpoint=this.get("type")+"/"+this.get("uuid")+"/activities",options={method:"GET",endpoint:endpoint};this._client.request(options,function(err,data){err&&self._client.logging&&console
 .log("entity could not be connected");for(var entity in data.entities)data.entities[entity].createdDate=new Date(data.entities[entity].created).toUTCString();self.activities=data.entities,doCallback(callback,[err,data,data.entities],self)})},Usergrid.Entity.prototype.getFollowing=function(callback){var self=this,endpoint="users/"+this.get("uuid")+"/following",options={method:"GET",endpoint:endpoint};this._client.request(options,function(err,data){err&&self._client.logging&&console.log("could not get user following");for(var entity in data.entities){data.entities[entity].createdDate=new Date(data.entities[entity].created).toUTCString();var image=self._client.getDisplayImage(data.entities[entity].email,data.entities[entity].picture);data.entities[entity]._portal_image_icon=image}self.following=data.entities,doCallback(callback,[err,data,data.entities],self)})},Usergrid.Entity.prototype.getFollowers=function(callback){var self=this,endpoint="users/"+this.get("uuid")+"/followers",option
 s={method:"GET",endpoint:endpoint};this._client.request(options,function(err,data){err&&self._client.logging&&console.log("could not get user followers");for(var entity in data.entities){data.entities[entity].createdDate=new Date(data.entities[entity].created).toUTCString();var image=self._client.getDisplayImage(data.entities[entity].email,data.entities[entity].picture);data.entities[entity]._portal_image_icon=image}self.followers=data.entities,doCallback(callback,[err,data,data.entities],self)})},Usergrid.Entity.prototype.getRoles=function(callback){var self=this,endpoint=this.get("type")+"/"+this.get("uuid")+"/roles",options={method:"GET",endpoint:endpoint};this._client.request(options,function(err,data){err&&self._client.logging&&console.log("could not get user roles"),self.roles=data.entities,doCallback(callback,[err,data,data.entities],self)})},Usergrid.Entity.prototype.getPermissions=function(callback){var self=this,endpoint=this.get("type")+"/"+this.get("uuid")+"/permissions"
 ,options={method:"GET",endpoint:endpoint};this._client.request(options,function(err,data){err&&self._client.logging&&console.log("could not get user permissions");var permissions=[];if(data.data){var perms=data.data,count=0;for(var i in perms){count++;var perm=perms[i],parts=perm.split(":"),ops_part="",path_part=parts[0];parts.length>1&&(ops_part=parts[0],path_part=parts[1]),ops_part=ops_part.replace("*","get,post,put,delete");var ops=ops_part.split(","),ops_object={};ops_object.get="no",ops_object.post="no",ops_object.put="no",ops_object.delete="no";for(var j in ops)ops_object[ops[j]]="yes";permissions.push({operations:ops_object,path:path_part,perm:perm})}}self.permissions=permissions,doCallback(callback,[err,data,data.entities],self)})},Usergrid.Collection=function(options){if(options&&(this._client=options.client,this._type=options.type,this.qs=options.qs||{},this._list=options.list||[],this._iterator=options.iterator||-1,this._previous=options.previous||[],this._next=options.ne
 xt||null,this._cursor=options.cursor||null,options.list))for(var count=options.list.length,i=0;count>i;i++){var entity=this._client.restoreEntity(options.list[i]);this._list[i]=entity}},Usergrid.isCollection=function(obj){return obj&&obj instanceof Usergrid.Collection},Usergrid.Collection.prototype.serialize=function(){var data={};data.type=this._type,data.qs=this.qs,data.iterator=this._iterator,data.previous=this._previous,data.next=this._next,data.cursor=this._cursor,this.resetEntityPointer();var i=0;for(data.list=[];this.hasNextEntity();){var entity=this.getNextEntity();data.list[i]=entity.serialize(),i++}return data=JSON.stringify(data)},Usergrid.Collection.prototype.fetch=function(callback){var self=this,qs=this.qs;this._cursor?qs.cursor=this._cursor:delete qs.cursor;var options={method:"GET",endpoint:this._type,qs:this.qs};this._client.request(options,function(err,response){err&&self._client.logging?console.log("error getting collection"):(self.saveCursor(response.cursor||null
 ),self.resetEntityPointer(),self._list=response.getEntities().filter(function(entity){return isUUID(entity.uuid)}).map(function(entity){var ent=new Usergrid.Entity({client:self._client});return ent.set(entity),ent.type=self._type,ent})),doCallback(callback,[err,response,self],self)})},Usergrid.Collection.prototype.addEntity=function(entityObject,callback){var self=this;entityObject.type=this._type,this._client.createEntity(entityObject,function(err,response,entity){err||self.addExistingEntity(entity),doCallback(callback,[err,response,self],self)})},Usergrid.Collection.prototype.addExistingEntity=function(entity){var count=this._list.length;this._list[count]=entity},Usergrid.Collection.prototype.destroyEntity=function(entity,callback){var self=this;entity.destroy(function(err,response){err?(self._client.logging&&console.log("could not destroy entity"),doCallback(callback,[err,response,self],self)):self.fetch(callback),self.removeEntity(entity)})},Usergrid.Collection.prototype.getEnti
 tiesByCriteria=function(criteria){return this._list.filter(criteria)},Usergrid.Collection.prototype.getEntityByCriteria=function(criteria){return this.getEntitiesByCriteria(criteria).shift()
-},Usergrid.Collection.prototype.removeEntity=function(entity){var removedEntity=this.getEntityByCriteria(function(item){return entity.uuid===item.get("uuid")});return delete this._list[this._list.indexOf(removedEntity)],removedEntity},Usergrid.Collection.prototype.getEntityByUUID=function(uuid,callback){var entity=this.getEntityByCriteria(function(item){return item.get("uuid")===uuid});if(entity)doCallback(callback,[null,entity,entity],this);else{var options={data:{type:this._type,uuid:uuid},client:this._client};entity=new Usergrid.Entity(options),entity.fetch(callback)}},Usergrid.Collection.prototype.getFirstEntity=function(){var count=this._list.length;return count>0?this._list[0]:null},Usergrid.Collection.prototype.getLastEntity=function(){var count=this._list.length;return count>0?this._list[count-1]:null},Usergrid.Collection.prototype.hasNextEntity=function(){var next=this._iterator+1,hasNextElement=next>=0&&next<this._list.length;return hasNextElement?!0:!1},Usergrid.Collectio
 n.prototype.getNextEntity=function(){this._iterator++;var hasNextElement=this._iterator>=0&&this._iterator<=this._list.length;return hasNextElement?this._list[this._iterator]:!1},Usergrid.Collection.prototype.hasPrevEntity=function(){var previous=this._iterator-1,hasPreviousElement=previous>=0&&previous<this._list.length;return hasPreviousElement?!0:!1},Usergrid.Collection.prototype.getPrevEntity=function(){this._iterator--;var hasPreviousElement=this._iterator>=0&&this._iterator<=this._list.length;return hasPreviousElement?this._list[this._iterator]:!1},Usergrid.Collection.prototype.resetEntityPointer=function(){this._iterator=-1},Usergrid.Collection.prototype.saveCursor=function(cursor){this._next!==cursor&&(this._next=cursor)},Usergrid.Collection.prototype.resetPaging=function(){this._previous=[],this._next=null,this._cursor=null},Usergrid.Collection.prototype.hasNextPage=function(){return this._next},Usergrid.Collection.prototype.getNextPage=function(callback){this.hasNextPage()
 &&(this._previous.push(this._cursor),this._cursor=this._next,this._list=[],this.fetch(callback))},Usergrid.Collection.prototype.hasPreviousPage=function(){return this._previous.length>0},Usergrid.Collection.prototype.getPreviousPage=function(callback){this.hasPreviousPage()&&(this._next=null,this._cursor=this._previous.pop(),this._list=[],this.fetch(callback))},Usergrid.Group=function(options){this._path=options.path,this._list=[],this._client=options.client,this._data=options.data||{},this._data.type="groups"},Usergrid.Group.prototype=new Usergrid.Entity,Usergrid.Group.prototype.fetch=function(callback){var self=this,groupEndpoint="groups/"+this._path,memberEndpoint="groups/"+this._path+"/users",groupOptions={method:"GET",endpoint:groupEndpoint},memberOptions={method:"GET",endpoint:memberEndpoint};this._client.request(groupOptions,function(err,response){if(err)self._client.logging&&console.log("error getting group"),doCallback(callback,[err,response],self);else{var entities=respons
 e.getEntities();if(entities&&entities.length){{entities.shift()}self._client.request(memberOptions,function(err,response){err&&self._client.logging?console.log("error getting group users"):self._list=response.getEntities().filter(function(entity){return isUUID(entity.uuid)}).map(function(entity){return new Usergrid.Entity({type:entity.type,client:self._client,uuid:entity.uuid,response:entity})}),doCallback(callback,[err,response,self],self)})}}})},Usergrid.Group.prototype.members=function(){return this._list},Usergrid.Group.prototype.add=function(options,callback){var self=this;options.user?(options={method:"POST",endpoint:"groups/"+this._path+"/users/"+options.user.get("username")},this._client.request(options,function(error,response){error?doCallback(callback,[error,response,self],self):self.fetch(callback)})):doCallback(callback,[new UsergridError("no user specified","no_user_specified"),null,this],this)},Usergrid.Group.prototype.remove=function(options,callback){var self=this;op
 tions.user?(options={method:"DELETE",endpoint:"groups/"+this._path+"/users/"+options.user.get("username")},this._client.request(options,function(error,response){error?doCallback(callback,[error,response,self],self):self.fetch(callback)})):doCallback(callback,[new UsergridError("no user specified","no_user_specified"),null,this],this)},Usergrid.Group.prototype.feed=function(callback){var self=this,options={method:"GET",endpoint:"groups/"+this._path+"/feed"};this._client.request(options,function(err,response){doCallback(callback,[err,response,self],self)})},Usergrid.Group.prototype.createGroupActivity=function(options,callback){var self=this,user=options.user,entity=new Usergrid.Entity({client:this._client,data:{actor:{displayName:user.get("username"),uuid:user.get("uuid"),username:user.get("username"),email:user.get("email"),picture:user.get("picture"),image:{duration:0,height:80,url:user.get("picture"),width:80}},verb:"post",content:options.content,type:"groups/"+this._path+"/activi
 ties"}});entity.save(function(err,response){doCallback(callback,[err,response,self])})},Usergrid.Counter=function(options,callback){this._client=options.client,this._data=options.data||{},this._data.category=options.category||"UNKNOWN",this._data.timestamp=options.timestamp||0,this._data.type="events",this._data.counters=options.counters||{},doCallback(callback,[!1,this],this)};var COUNTER_RESOLUTIONS=["all","minute","five_minutes","half_hour","hour","six_day","day","week","month"];Usergrid.Counter.prototype=new Usergrid.Entity,Usergrid.Counter.prototype.fetch=function(callback){this.getData({},callback)},Usergrid.Counter.prototype.increment=function(options,callback){var self=this,name=options.name,value=options.value;return name?isNaN(value)?doCallback(callback,[new UsergridInvalidArgumentError("'value' for increment, decrement must be a number"),null,self],self):(self._data.counters[name]=parseInt(value)||1,self.save(callback)):doCallback(callback,[new UsergridInvalidArgumentErro
 r("'name' for increment, decrement must be a number"),null,self],self)},Usergrid.Counter.prototype.decrement=function(options,callback){var self=this,name=options.name,value=options.value;self.increment({name:name,value:-(parseInt(value)||1)},callback)},Usergrid.Counter.prototype.reset=function(options,callback){var self=this,name=options.name;self.increment({name:name,value:0},callback)},Usergrid.Counter.prototype.getData=function(options,callback){var start_time,end_time,start=options.start||0,end=options.end||Date.now(),resolution=(options.resolution||"all").toLowerCase(),counters=options.counters||Object.keys(this._data.counters),res=(resolution||"all").toLowerCase();-1===COUNTER_RESOLUTIONS.indexOf(res)&&(res="all"),start_time=getSafeTime(start),end_time=getSafeTime(end);var self=this,params=Object.keys(counters).map(function(counter){return["counter",encodeURIComponent(counters[counter])].join("=")});params.push("resolution="+res),params.push("start_time="+String(start_time)),
 params.push("end_time="+String(end_time));var endpoint="counters?"+params.join("&");this._client.request({endpoint:endpoint},function(err,data){return data.counters&&data.counters.length&&data.counters.forEach(function(counter){self._data.counters[counter.name]=counter.value||counter.values}),doCallback(callback,[err,data,self],self)})},Usergrid.Folder=function(options,callback){var self=this;console.log("FOLDER OPTIONS",options),self._client=options.client,self._data=options.data||{},self._data.type="folders";var missingData=["name","owner","path"].some(function(required){return!(required in self._data)});return missingData?doCallback(callback,[new UsergridInvalidArgumentError("Invalid asset data: 'name', 'owner', and 'path' are required properties."),null,self],self):void self.save(function(err,response){err?doCallback(callback,[new UsergridError(response),response,self],self):(response&&response.entities&&response.entities.length&&self.set(response.entities[0]),doCallback(callbac
 k,[null,response,self],self))})},Usergrid.Folder.prototype=new Usergrid.Entity,Usergrid.Folder.prototype.fetch=function(callback){var self=this;Usergrid.Entity.prototype.fetch.call(self,function(err,data){console.log("self",self.get()),console.log("data",data),err?doCallback(callback,[null,data,self],self):self.getAssets(function(err,response){err?doCallback(callback,[new UsergridError(response),resonse,self],self):doCallback(callback,[null,self],self)})})},Usergrid.Folder.prototype.addAsset=function(options,callback){var self=this;if("asset"in options){var asset=null;switch(typeof options.asset){case"object":asset=options.asset,asset instanceof Usergrid.Entity||(asset=new Usergrid.Asset(asset));break;case"string":isUUID(options.asset)&&(asset=new Usergrid.Asset({client:self._client,data:{uuid:options.asset,type:"assets"}}))}asset&&asset instanceof Usergrid.Entity&&asset.fetch(function(err,data){if(err)doCallback(callback,[new UsergridError(data),data,self],self);else{var endpoint=[
 "folders",self.get("uuid"),"assets",asset.get("uuid")].join("/"),options={method:"POST",endpoint:endpoint};self._client.request(options,callback)}})}else doCallback(callback,[new UsergridInvalidArgumentError("No asset specified"),null,self],self)},Usergrid.Folder.prototype.removeAsset=function(options,callback){var self=this;if("asset"in options){var asset=null;switch(typeof options.asset){case"object":asset=options.asset;break;case"string":isUUID(options.asset)&&(asset=new Usergrid.Asset({client:self._client,data:{uuid:options.asset,type:"assets"}}))}if(asset&&null!==asset){var endpoint=["folders",self.get("uuid"),"assets",asset.get("uuid")].join("/");self._client.request({method:"DELETE",endpoint:endpoint},function(err,response){err?doCallback(callback,[new UsergridError(response),response,self],self):doCallback(callback,[null,response,self],self)})}}else doCallback(callback,[new UsergridInvalidArgumentError("No asset specified"),null,self],self)},Usergrid.Folder.prototype.getAsse
 ts=function(callback){return this.getConnections("assets",callback)},XMLHttpRequest.prototype.sendAsBinary||(XMLHttpRequest.prototype.sendAsBinary=function(sData){for(var nBytes=sData.length,ui8Data=new Uint8Array(nBytes),nIdx=0;nBytes>nIdx;nIdx++)ui8Data[nIdx]=255&sData.charCodeAt(nIdx);this.send(ui8Data)}),Usergrid.Asset=function(options,callback){var self=this;self._client=options.client,self._data=options.data||{},self._data.type="assets";var missingData=["name","owner","path"].some(function(required){return!(required in self._data)});missingData?doCallback(callback,[new UsergridError("Invalid asset data: 'name', 'owner', and 'path' are required properties."),null,self],self):self.save(function(err,data){err?doCallback(callback,[new UsergridError(data),data,self],self):(data&&data.entities&&data.entities.length&&self.set(data.entities[0]),doCallback(callback,[null,data,self],self))})},Usergrid.Asset.prototype=new Usergrid.Entity,Usergrid.Asset.prototype.addToFolder=function(opti
 ons,callback){var self=this;if("folder"in options&&isUUID(options.folder)){Usergrid.Folder({uuid:options.folder},function(err,folder){if(err)doCallback(callback,[UsergridError.fromResponse(folder),folder,self],self);else{var endpoint=["folders",folder.get("uuid"),"assets",self.get("uuid")].join("/"),options={method:"POST",endpoint:endpoint};this._client.request(options,function(err,response){err?doCallback(callback,[UsergridError.fromResponse(folder),response,self],self):doCallback(callback,[null,folder,self],self)})}})}else doCallback(callback,[new UsergridError("folder not specified"),null,self],self)},Usergrid.Asset.prototype.upload=function(data,callback){if(!(window.File&&window.FileReader&&window.FileList&&window.Blob))return void doCallback(callback,[new UsergridError("The File APIs are not fully supported by your browser."),null,this],this);var self=this,endpoint=[this._client.URI,this._client.orgName,this._client.appName,"assets",self.get("uuid"),"data"].join("/"),xhr=new X
 MLHttpRequest;xhr.open("POST",endpoint,!0),xhr.onerror=function(){doCallback(callback,[!0,new UsergridError("The File APIs are not fully supported by your browser.")],self)},xhr.onload=function(){xhr.status>=300?doCallback(callback,[new UsergridError(JSON.parse(xhr.responseText)),null,self],self):doCallback(callback,[null,xhr,self],self)};var fr=new FileReader;fr.onload=function(){var binary=fr.result;xhr.overrideMimeType("application/octet-stream"),setTimeout(function(){xhr.sendAsBinary(binary)},1e3)},fr.readAsBinaryString(data)},Usergrid.Asset.prototype.download=function(callback){var self=this,endpoint=[this._client.URI,this._client.orgName,this._client.appName,"assets",self.get("uuid"),"data"].join("/"),xhr=new XMLHttpRequest;xhr.open("GET",endpoint,!0),xhr.responseType="blob",xhr.onload=function(){var blob=xhr.response;doCallback(callback,[null,blob,self],self)},xhr.onerror=function(err){callback(!0,err),doCallback(callback,[new UsergridError(err),err,self],self)},xhr.send()},f
 unction(global){function UsergridError(message,name,timestamp,duration,exception){this.message=message,this.name=name,this.timestamp=timestamp||Date.now(),this.duration=duration||0,this.exception=exception}function UsergridHTTPResponseError(message,name,timestamp,duration,exception){this.message=message,this.name=name,this.timestamp=timestamp||Date.now(),this.duration=duration||0,this.exception=exception}function UsergridInvalidHTTPMethodError(message,name,timestamp,duration,exception){this.message=message,this.name=name||"invalid_http_method",this.timestamp=timestamp||Date.now(),this.duration=duration||0,this.exception=exception}function UsergridInvalidURIError(message,name,timestamp,duration,exception){this.message=message,this.name=name||"invalid_uri",this.timestamp=timestamp||Date.now(),this.duration=duration||0,this.exception=exception}function UsergridInvalidArgumentError(message,name,timestamp,duration,exception){this.message=message,this.name=name||"invalid_argument",this.ti
 mestamp=timestamp||Date.now(),this.duration=duration||0,this.exception=exception}function UsergridKeystoreDatabaseUpgradeNeededError(message,name,timestamp,duration,exception){this.message=message,this.name=name,this.timestamp=timestamp||Date.now(),this.duration=duration||0,this.exception=exception}var short,name="UsergridError",_name=global[name],_short=short&&void 0!==short?global[short]:void 0;return UsergridError.prototype=new Error,UsergridError.prototype.constructor=UsergridError,UsergridError.fromResponse=function(response){return response&&"undefined"!=typeof response?new UsergridError(response.error_description,response.error,response.timestamp,response.duration,response.exception):new UsergridError},UsergridError.createSubClass=function(name){return name in global&&global[name]?global[name]:(global[name]=function(){},global[name].name=name,global[name].prototype=new UsergridError,global[name])},UsergridHTTPResponseError.prototype=new UsergridError,UsergridInvalidHTTPMethod
 Error.prototype=new UsergridError,UsergridInvalidURIError.prototype=new UsergridError,UsergridInvalidArgumentError.prototype=new UsergridError,UsergridKeystoreDatabaseUpgradeNeededError.prototype=new UsergridError,global.UsergridHTTPResponseError=UsergridHTTPResponseError,global.UsergridInvalidHTTPMethodError=UsergridInvalidHTTPMethodError,global.UsergridInvalidURIError=UsergridInvalidURIError,global.UsergridInvalidArgumentError=UsergridInvalidArgumentError,global.UsergridKeystoreDatabaseUpgradeNeededError=UsergridKeystoreDatabaseUpgradeNeededError,global[name]=UsergridError,void 0!==short&&(global[short]=UsergridError),global[name].noConflict=function(){return _name&&(global[name]=_name),void 0!==short&&(global[short]=_short),UsergridError},global[name]}(this);
\ No newline at end of file
+function extend(subClass,superClass){var F=function(){};return F.prototype=superClass.prototype,subClass.prototype=new F,subClass.prototype.constructor=subClass,subClass.superclass=superClass.prototype,superClass.prototype.constructor==Object.prototype.constructor&&(superClass.prototype.constructor=superClass),subClass}function propCopy(from,to){for(var prop in from)from.hasOwnProperty(prop)&&(to[prop]="object"==typeof from[prop]&&"object"==typeof to[prop]?propCopy(from[prop],to[prop]):from[prop]);return to}function NOOP(){}function isValidUrl(url){if(!url)return!1;var doc,base,anchor,isValid=!1;try{doc=document.implementation.createHTMLDocument(""),base=doc.createElement("base"),base.href=base||window.lo,doc.head.appendChild(base),anchor=doc.createElement("a"),anchor.href=url,doc.body.appendChild(anchor),isValid=!(""===anchor.href)}catch(e){console.error(e)}finally{return doc.head.removeChild(base),doc.body.removeChild(anchor),base=null,anchor=null,doc=null,isValid}}function isUUID
 (uuid){return uuid?uuidValueRegex.test(uuid):!1}function encodeParams(params){var queryString;return params&&Object.keys(params)&&(queryString=[].slice.call(arguments).reduce(function(a,b){return a.concat(b instanceof Array?b:[b])},[]).filter(function(c){return"object"==typeof c}).reduce(function(p,c){return c instanceof Array?p.push(c):p=p.concat(Object.keys(c).map(function(key){return[key,c[key]]})),p},[]).reduce(function(p,c){return 2===c.length?p.push(c):p=p.concat(c),p},[]).reduce(function(p,c){return c[1]instanceof Array?c[1].forEach(function(v){p.push([c[0],v])}):p.push(c),p},[]).map(function(c){return c[1]=encodeURIComponent(c[1]),c.join("=")}).join("&")),queryString}function isFunction(f){return f&&null!==f&&"function"==typeof f}function doCallback(callback,params,context){var returnValue;return isFunction(callback)&&(params||(params=[]),context||(context=this),params.push(context),returnValue=callback.apply(context,params)),returnValue}function getSafeTime(prop){var time;s
 witch(typeof prop){case"undefined":time=Date.now();break;case"number":time=prop;break;case"string":time=isNaN(prop)?Date.parse(prop):parseInt(prop);break;default:time=Date.parse(prop.toString())}return time}var UsergridEventable=function(){throw Error("'UsergridEventable' is not intended to be invoked directly")};UsergridEventable.prototype={bind:function(event,fn){this._events=this._events||{},this._events[event]=this._events[event]||[],this._events[event].push(fn)},unbind:function(event,fn){this._events=this._events||{},event in this._events!=!1&&this._events[event].splice(this._events[event].indexOf(fn),1)},trigger:function(event){if(this._events=this._events||{},event in this._events!=!1)for(var i=0;i<this._events[event].length;i++)this._events[event][i].apply(this,Array.prototype.slice.call(arguments,1))}},UsergridEventable.mixin=function(destObject){for(var props=["bind","unbind","trigger"],i=0;i<props.length;i++)props[i]in destObject.prototype&&(console.warn("overwriting '"+p
 rops[i]+"' on '"+destObject.name+"'."),console.warn("the previous version can be found at '_"+props[i]+"' on '"+destObject.name+"'."),destObject.prototype["_"+props[i]]=destObject.prototype[props[i]]),destObject.prototype[props[i]]=UsergridEventable.prototype[props[i]]},function(){function Logger(name){this.logEnabled=!0,this.init(name,!0)}var name="Logger",global=this,overwrittenName=global[name];return Logger.METHODS=["log","error","warn","info","debug","assert","clear","count","dir","dirxml","exception","group","groupCollapsed","groupEnd","profile","profileEnd","table","time","timeEnd","trace"],Logger.prototype.init=function(name,logEnabled){this.name=name||"UNKNOWN",this.logEnabled=logEnabled||!0;var addMethod=function(method){this[method]=this.createLogMethod(method)}.bind(this);Logger.METHODS.forEach(addMethod)},Logger.prototype.createLogMethod=function(method){return Logger.prototype.log.bind(this,method)},Logger.prototype.prefix=function(method,args){var prepend="["+method.t
 oUpperCase()+"]["+name+"]:	";return-1!==["log","error","warn","info"].indexOf(method)&&("string"==typeof args[0]?args[0]=prepend+args[0]:args.unshift(prepend)),args},Logger.prototype.log=function(){var args=[].slice.call(arguments);method=args.shift(),-1===Logger.METHODS.indexOf(method)&&(method="log"),this.logEnabled&&console&&console[method]&&(args=this.prefix(method,args),console[method].apply(console,args))},Logger.prototype.setLogEnabled=function(logEnabled){this.logEnabled=logEnabled||!0},Logger.mixin=function(destObject){destObject.__logger=new Logger(destObject.name||"UNKNOWN");var addMethod=function(method){method in destObject.prototype&&(console.warn("overwriting '"+method+"' on '"+destObject.name+"'."),console.warn("the previous version can be found at '_"+method+"' on '"+destObject.name+"'."),destObject.prototype["_"+method]=destObject.prototype[method]),destObject.prototype[method]=destObject.__logger.createLogMethod(method)};Logger.METHODS.forEach(addMethod)},global[n
 ame]=Logger,global[name].noConflict=function(){return overwrittenName&&(global[name]=overwrittenName),Logger},global[name]}(),function(global){function Promise(){this.complete=!1,this.error=null,this.result=null,this.callbacks=[]}var name="Promise",overwrittenName=global[name];return Promise.prototype.then=function(callback,context){var f=function(){return callback.apply(context,arguments)};this.complete?f(this.error,this.result):this.callbacks.push(f)},Promise.prototype.done=function(error,result){if(this.complete=!0,this.error=error,this.result=result,this.callbacks){for(var i=0;i<this.callbacks.length;i++)this.callbacks[i](error,result);this.callbacks.length=0}},Promise.join=function(promises){function notifier(i){return function(error,result){completed+=1,errors[i]=error,results[i]=result,completed===total&&p.done(errors,results)}}for(var p=new Promise,total=promises.length,completed=0,errors=[],results=[],i=0;total>i;i++)promises[i]().then(notifier(i));return p},Promise.chain=f
 unction(promises,error,result){var p=new Promise;return null===promises||0===promises.length?p.done(error,result):promises[0](error,result).then(function(res,err){promises.splice(0,1),promises?Promise.chain(promises,res,err).then(function(r,e){p.done(r,e)}):p.done(res,err)}),p},global[name]=Promise,global[name].noConflict=function(){return overwrittenName&&(global[name]=overwrittenName),Promise},global[name]}(this),function(){function partial(){var args=Array.prototype.slice.call(arguments),fn=args.shift();return fn.bind(this,args)}function Ajax(){function encode(data){var result="";if("string"==typeof data)result=data;else{var e=encodeURIComponent;for(var i in data)data.hasOwnProperty(i)&&(result+="&"+e(i)+"="+e(data[i]))}return result}function request(m,u,d){var timeout,p=new Promise;return self.logger.time(m+" "+u),function(xhr){xhr.onreadystatechange=function(){4===this.readyState&&(self.logger.timeEnd(m+" "+u),clearTimeout(timeout),p.done(null,this))},xhr.onerror=function(respo
 nse){clearTimeout(timeout),p.done(response,null)},xhr.oncomplete=function(){clearTimeout(timeout),self.logger.timeEnd(m+" "+u),self.info("%s request to %s returned %s",m,u,this.status)},xhr.open(m,u),d&&("object"==typeof d&&(d=JSON.stringify(d)),xhr.setRequestHeader("Content-Type","application/json"),xhr.setRequestHeader("Accept","application/json")),timeout=setTimeout(function(){xhr.abort(),p.done("API Call timed out.",null)},3e4),xhr.send(encode(d))}(new XMLHttpRequest),p}this.logger=new global.Logger(name);var self=this;this.request=request,this.get=partial(request,"GET"),this.post=partial(request,"POST"),this.put=partial(request,"PUT"),this.delete=partial(request,"DELETE")}var exports,name="Ajax",global=this,overwrittenName=global[name];return global[name]=new Ajax,global[name].noConflict=function(){return overwrittenName&&(global[name]=overwrittenName),exports},global[name]}(),window.console=window.console||{},window.console.log=window.console.log||function(){};var uuidValueReg
 ex=/^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/;!function(global){function Usergrid(){this.logger=new Logger(name)}var name="Usergrid",overwrittenName=global[name],VALID_REQUEST_METHODS=["GET","POST","PUT","DELETE"];return Usergrid.isValidEndpoint=function(){return!0},Usergrid.Request=function(method,endpoint,query_params,data,callback){var p=new Promise;if(this.logger=new global.Logger("Usergrid.Request"),this.logger.time("process request "+method+" "+endpoint),this.endpoint=endpoint+"?"+encodeParams(query_params),this.method=method.toUpperCase(),this.data="object"==typeof data?JSON.stringify(data):data,-1===VALID_REQUEST_METHODS.indexOf(this.method))throw new UsergridInvalidHTTPMethodError("invalid request method '"+this.method+"'");if(!isValidUrl(this.endpoint))throw this.logger.error(endpoint,this.endpoint,/^https:\/\//.test(endpoint)),new UsergridInvalidURIError("The provided endpoint is not valid: "+this.endpoint);var request=function(){retur
 n Ajax.request(this.method,this.endpoint,this.data)}.bind(this),response=function(err,request){return new Usergrid.Response(err,request)}.bind(this),oncomplete=function(err,response){p.done(err,response),this.logger.info("REQUEST",err,response),doCallback(callback,[err,response]),this.logger.timeEnd("process request "+method+" "+endpoint)}.bind(this);return Promise.chain([request,response]).then(oncomplete),p},Usergrid.Response=function(err,response){var p=new Promise,data=null;try{data=JSON.parse(response.responseText)}catch(e){data={}}switch(Object.keys(data).forEach(function(key){Object.defineProperty(this,key,{value:data[key],enumerable:!0})}.bind(this)),Object.defineProperty(this,"logger",{enumerable:!1,configurable:!1,writable:!1,value:new global.Logger(name)}),Object.defineProperty(this,"success",{enumerable:!1,configurable:!1,writable:!0,value:!0}),Object.defineProperty(this,"err",{enumerable:!1,configurable:!1,writable:!0,value:err}),Object.defineProperty(this,"status",{enu
 merable:!1,configurable:!1,writable:!0,value:parseInt(response.status)}),Object.defineProperty(this,"statusGroup",{enumerable:!1,configurable:!1,writable:!0,value:this.status-this.status%100}),this.statusGroup){case 200:this.success=!0;break;case 400:case 500:case 300:case 100:default:this.success=!1}return this.success?p.done(null,this):p.done(UsergridError.fromResponse(data),this),p},Usergrid.Response.prototype.getEntities=function(){var entities;return this.success&&(entities=this.data?this.data.entities:this.entities),entities||[]},Usergrid.Response.prototype.getEntity=function(){var entities=this.getEntities();return entities[0]},Usergrid.VERSION=Usergrid.USERGRID_SDK_VERSION="0.11.0",global[name]=Usergrid,global[name].noConflict=function(){return overwrittenName&&(global[name]=overwrittenName),Usergrid},global[name]}(this),function(){var exports,name="Client",global=this,overwrittenName=global[name];return Usergrid.Client=function(options){this.URI=options.URI||"https://api.us
 ergrid.com",options.orgName&&this.set("orgName",options.orgName),options.appName&&this.set("appName",options.appName),options.qs&&this.setObject("default_qs",options.qs),this.buildCurl=options.buildCurl||!1,this.logging=options.logging||!1},Usergrid.Client.prototype.request=function(options,callback){var uri,method=options.method||"GET",endpoint=options.endpoint,body=options.body||{},qs=options.qs||{},mQuery=options.mQuery||!1,orgName=this.get("orgName"),appName=this.get("appName"),default_qs=this.getObject("default_qs");if(!mQuery&&!orgName&&!appName)return logoutCallback();uri=mQuery?this.URI+"/"+endpoint:this.URI+"/"+orgName+"/"+appName+"/"+endpoint,this.getToken()&&(qs.access_token=this.getToken()),default_qs&&(qs=propCopy(qs,default_qs));{var self=this;new Usergrid.Request(method,uri,qs,body,function(err,response){err?doCallback(callback,[err,response,self],self):doCallback(callback,[null,response,self],self)})}},Usergrid.Client.prototype.buildAssetURL=function(uuid){var self=t
 his,qs={},assetURL=this.URI+"/"+this.orgName+"/"+this.appName+"/assets/"+uuid+"/data";self.getToken()&&(qs.access_token=self.getToken());var encoded_params=encodeParams(qs);return encoded_params&&(assetURL+="?"+encoded_params),assetURL},Usergrid.Client.prototype.createGroup=function(options,callback){var group=new Usergrid.Group({path:options.path,client:this,data:options});group.save(function(err,response){doCallback(callback,[err,response,group],group)})},Usergrid.Client.prototype.createEntity=function(options,callback){var entity=new Usergrid.Entity({client:this,data:options});entity.save(function(err,response){doCallback(callback,[err,response,entity],entity)})},Usergrid.Client.prototype.getEntity=function(options,callback){var entity=new Usergrid.Entity({client:this,data:options});entity.fetch(function(err,response){doCallback(callback,[err,response,entity],entity)})},Usergrid.Client.prototype.restoreEntity=function(serializedObject){var data=JSON.parse(serializedObject),option
 s={client:this,data:data},entity=new Usergrid.Entity(options);return entity},Usergrid.Client.prototype.createCounter=function(options,callback){var counter=new Usergrid.Counter({client:this,data:options});counter.save(callback)},Usergrid.Client.prototype.createAsset=function(options,callback){var file=options.file;file&&(options.name=options.name||file.name,options["content-type"]=options["content-type"]||file.type,options.path=options.path||"/",delete options.file);var asset=new Usergrid.Asset({client:this,data:options});asset.save(function(err,response,asset){file&&!err?asset.upload(file,callback):doCallback(callback,[err,response,asset],asset)})},Usergrid.Client.prototype.createCollection=function(options,callback){options.client=this;var collection=new Usergrid.Collection(options);collection.fetch(function(err,response,collection){doCallback(callback,[err,response,collection],this)})},Usergrid.Client.prototype.restoreCollection=function(serializedObject){var data=JSON.parse(seri
 alizedObject);data.client=this;var collection=new Usergrid.Collection(data);return collection},Usergrid.Client.prototype.getFeedForUser=function(username,callback){var options={method:"GET",endpoint:"users/"+username+"/feed"};this.request(options,function(err,data){err?doCallback(callback,[err]):doCallback(callback,[err,data,data.getEntities()])})},Usergrid.Client.prototype.createUserActivity=function(user,options,callback){options.type="users/"+user+"/activities",options={client:this,data:options};var entity=new Usergrid.Entity(options);entity.save(function(err,data){doCallback(callback,[err,data,entity])})},Usergrid.Client.prototype.createUserActivityWithEntity=function(user,content,callback){var username=user.get("username"),options={actor:{displayName:username,uuid:user.get("uuid"),username:username,email:user.get("email"),picture:user.get("picture"),image:{duration:0,height:80,url:user.get("picture"),width:80}},verb:"post",content:content};this.createUserActivity(username,optio
 ns,callback)},Usergrid.Client.prototype.calcTimeDiff=function(){var seconds=0,time=this._end-this._start;try{seconds=(time/10/60).toFixed(2)}catch(e){return 0}return seconds},Usergrid.Client.prototype.setToken=function(token){this.set("token",token)},Usergrid.Client.prototype.getToken=function(){return this.get("token")},Usergrid.Client.prototype.setObject=function(key,value){value&&(value=JSON.stringify(value)),this.set(key,value)},Usergrid.Client.prototype.set=function(key,value){var keyStore="apigee_"+key;this[key]=value,"undefined"!=typeof Storage&&(value?localStorage.setItem(keyStore,value):localStorage.removeItem(keyStore))},Usergrid.Client.prototype.getObject=function(key){return JSON.parse(this.get(key))},Usergrid.Client.prototype.get=function(key){var keyStore="apigee_"+key,value=null;return this[key]?value=this[key]:"undefined"!=typeof Storage&&(value=localStorage.getItem(keyStore)),value},Usergrid.Client.prototype.signup=function(username,password,email,name,callback){var
  options={type:"users",username:username,password:password,email:email,name:name};this.createEntity(options,callback)},Usergrid.Client.prototype.login=function(username,password,callback){var self=this,options={method:"POST",endpoint:"token",body:{username:username,password:password,grant_type:"password"}};self.request(options,function(err,data){var user={};if(err)self.logging&&console.log("error trying to log user in");else{var options={client:self,data:data.user};user=new Usergrid.Entity(options),self.setToken(data.access_token)}doCallback(callback,[err,data,user])})},Usergrid.Client.prototype.reAuthenticateLite=function(callback){var self=this,options={method:"GET",endpoint:"management/me",mQuery:!0};this.request(options,function(err,response){err&&self.logging?console.log("error trying to re-authenticate user"):self.setToken(response.data.access_token),doCallback(callback,[err])})},Usergrid.Client.prototype.reAuthenticate=function(email,callback){var self=this,options={method:"G
 ET",endpoint:"management/users/"+email,mQuery:!0};this.request(options,function(err,response){var data,organizations={},applications={},user={};if(err&&self.logging)console.log("error trying to full authenticate user");else{data=response.data,self.setToken(data.token),self.set("email",data.email),localStorage.setItem("accessToken",data.token),localStorage.setItem("userUUID",data.uuid),localStorage.setItem("userEmail",data.email);var userData={username:data.username,email:data.email,name:data.name,uuid:data.uuid},options={client:self,data:userData};user=new Usergrid.Entity(options),organizations=data.organizations;var org="";try{var existingOrg=self.get("orgName");org=organizations[existingOrg]?organizations[existingOrg]:organizations[Object.keys(organizations)[0]],self.set("orgName",org.name)}catch(e){err=!0,self.logging&&console.log("error selecting org")}applications=self.parseApplicationsArray(org),self.selectFirstApp(applications),self.setObject("organizations",organizations),se
 lf.setObject("applications",applications)}doCallback(callback,[err,data,user,organizations,applications],self)})},Usergrid.Client.prototype.loginFacebook=function(facebookToken,callback){var self=this,options={method:"GET",endpoint:"auth/facebook",qs:{fb_access_token:facebookToken}};this.request(options,function(err,data){var user={};if(err&&self.logging)console.log("error trying to log user in");else{var options={client:self,data:data.user};user=new Usergrid.Entity(options),self.setToken(data.access_token)}doCallback(callback,[err,data,user],self)})},Usergrid.Client.prototype.getLoggedInUser=function(callback){if(this.getToken()){var self=this,options={method:"GET",endpoint:"users/me"};this.request(options,function(err,data){if(err)self.logging&&console.log("error trying to log user in"),doCallback(callback,[err,data,null],self);else{var options={client:self,data:data.entities[0]},user=new Usergrid.Entity(options);doCallback(callback,[null,data,user],self)}})}else callback(!0,null,
 null)},Usergrid.Client.prototype.isLoggedIn=function(){var token=this.getToken();return"undefined"!=typeof token&&null!==token},Usergrid.Client.prototype.logout=function(){this.setToken()},Usergrid.Client.prototype.destroyToken=function(username,token,revokeAll,callback){var options={client:self,method:"PUT"};options.endpoint=revokeAll===!0?"users/"+username+"/revoketokens":null===token?"users/"+username+"/revoketoken?token="+this.getToken():"users/"+username+"/revoketoken?token="+token,this.request(options,function(err,data){err?(self.logging&&console.log("error destroying access token"),doCallback(callback,[err,data,null],self)):(console.log(revokeAll===!0?"all user tokens invalidated":"token invalidated"),doCallback(callback,[err,data,null],self))})},Usergrid.Client.prototype.logoutAndDestroyToken=function(username,token,revokeAll,callback){null===username?console.log("username required to revoke tokens"):(this.destroyToken(username,token,revokeAll,callback),(revokeAll===!0||toke
 n===this.getToken()||null===token)&&this.setToken(null))},Usergrid.Client.prototype.buildCurlCall=function(options){var curl=["curl"],method=(options.method||"GET").toUpperCase(),body=options.body,uri=options.uri;return curl.push("-X"),curl.push(["POST","PUT","DELETE"].indexOf(method)>=0?method:"GET"),curl.push(uri),"object"==typeof body&&Object.keys(body).length>0&&-1!==["POST","PUT"].indexOf(method)&&(curl.push("-d"),curl.push("'"+JSON.stringify(body)+"'")),curl=curl.join(" "),console.log(curl),curl},Usergrid.Client.prototype.getDisplayImage=function(email,picture,size){size=size||50;var image="https://apigee.com/usergrid/images/user_profile.png";try{picture?image=picture:email.length&&(image="https://secure.gravatar.com/avatar/"+MD5(email)+"?s="+size+encodeURI("&d=https://apigee.com/usergrid/images/user_profile.png"))}catch(e){}finally{return image}},global[name]=Usergrid.Client,global[name].noConflict=function(){return overwrittenName&&(global[name]=overwrittenName),exports},glo
 bal[name]}();var ENTITY_SYSTEM_PROPERTIES=["metadata","created","modified","oldpassword","newpassword","type","activated","uuid"];Usergrid.Entity=function(options){this._data={},this._client=void 0,options&&(this.set(options.data||{}),this._client=options.client||{})},Usergrid.Entity.isEntity=function(obj){return obj&&obj instanceof Usergrid.Entity},Usergrid.Entity.isPersistedEntity=function(obj){return isEntity(obj)&&isUUID(obj.get("uuid"))},Usergrid.Entity.prototype.serialize=function(){return JSON.stringify(this._data)},Usergrid.Entity.prototype.get=function(key){var value;if(0===arguments.length?value=this._data:arguments.length>1&&(key=[].slice.call(arguments).reduce(function(p,c){return c instanceof Array?p=p.concat(c):p.push(c),p},[])),key instanceof Array){var self=this;value=key.map(function(k){return self.get(k)})}else"undefined"!=typeof key&&(value=this._data[key]);return value},Usergrid.Entity.prototype.set=function(key,value){if("object"==typeof key)for(var field in key
 )this._data[field]=key[field];else"string"==typeof key?null===value?delete this._data[key]:this._data[key]=value:this._data={}},Usergrid.Entity.prototype.getEndpoint=function(){var name,type=this.get("type"),nameProperties=["uuid","name"];if(void 0===type)throw new UsergridError("cannot fetch entity, no entity type specified","no_type_specified");return/^users?$/.test(type)&&nameProperties.unshift("username"),name=this.get(nameProperties).filter(function(x){return null!==x&&"undefined"!=typeof x}).shift(),name?[type,name].join("/"):type},Usergrid.Entity.prototype.save=function(callback){var self=this,type=this.get("type"),method="POST",entityId=this.get("uuid"),entityData=this.get(),options={method:method,endpoint:type};entityId&&(options.method="PUT",options.endpoint+="/"+entityId),options.body=Object.keys(entityData).filter(function(key){return-1===ENTITY_SYSTEM_PROPERTIES.indexOf(key)}).reduce(function(data,key){return data[key]=entityData[key],data},{}),self._client.request(opti
 ons,function(err,response){var entity=response.getEntity();entity&&(self.set(entity),self.set("type",/^\//.test(response.path)?response.path.substring(1):response.path)),err&&self._client.logging&&console.log("could not save entity"),doCallback(callback,[err,response,self],self)})},Usergrid.Entity.prototype.changePassword=function(oldpassword,password,newpassword,callback){var self=this;if("function"==typeof oldpassword&&void 0===callback&&(callback=oldpassword,oldpassword=self.get("oldpassword"),password=self.get("password"),newpassword=self.get("newpassword")),self.set({password:null,oldpassword:null,newpassword:null}),!(/^users?$/.test(self.get("type"))&&oldpassword&&newpassword))throw new UsergridInvalidArgumentError("Invalid arguments passed to 'changePassword'");var options={method:"PUT",endpoint:"users/"+self.get("uuid")+"/password",body:{uuid:self.get("uuid"),username:self.get("username"),password:password,oldpassword:oldpassword,newpassword:newpassword}};self._client.reques
 t(options,function(err,response){err&&self._client.logging&&console.log("could not update user"),doCallback(callback,[err,response,self],self)})},Usergrid.Entity.prototype.fetch=function(callback){var endpoint,self=this;endpoint=this.getEndpoint();var options={method:"GET",endpoint:endpoint};this._client.request(options,function(err,response){var entity=response.getEntity();entity&&self.set(entity),doCallback(callback,[err,response,self],self)})},Usergrid.Entity.prototype.destroy=function(callback){var self=this,endpoint=this.getEndpoint(),options={method:"DELETE",endpoint:endpoint};this._client.request(options,function(err,response){err||self.set(null),doCallback(callback,[err,response,self],self)})},Usergrid.Entity.prototype.connect=function(connection,entity,callback){this.addOrRemoveConnection("POST",connection,entity,callback)},Usergrid.Entity.prototype.disconnect=function(connection,entity,callback){this.addOrRemoveConnection("DELETE",connection,entity,callback)},Usergrid.Enti
 ty.prototype.addOrRemoveConnection=function(method,connection,entity,callback){var self=this;if(-1==["POST","DELETE"].indexOf(method.toUpperCase()))throw new UsergridInvalidArgumentError("invalid method for connection call. must be 'POST' or 'DELETE'");var connecteeType=entity.get("type"),connectee=this.getEntityId(entity);if(!connectee)throw new UsergridInvalidArgumentError("connectee could not be identified");var connectorType=this.get("type"),connector=this.getEntityId(this);if(!connector)throw new UsergridInvalidArgumentError("connector could not be identified");var endpoint=[connectorType,connector,connection,connecteeType,connectee].join("/"),options={method:method,endpoint:endpoint};this._client.request(options,function(err,response){err&&self._client.logging&&console.log("There was an error with the connection call"),doCallback(callback,[err,response,self],self)})},Usergrid.Entity.prototype.getEntityId=function(entity){var id=!1;return isUUID(entity.get("uuid"))?id=entity.ge
 t("uuid"):"users"===this.get("type")?id=entity.get("username"):entity.get("name")&&(id=entity.get("name")),id},Usergrid.Entity.prototype.getConnections=function(connection,callback){var self=this,connectorType=this.get("type"),connector=this.getEntityId(this);if(connector){var endpoint=connectorType+"/"+connector+"/"+connection+"/",options={method:"GET",endpoint:endpoint};this._client.request(options,function(err,data){err&&self._client.logging&&console.log("entity could not be connected"),self[connection]={};for(var length=data&&data.entities?data.entities.length:0,i=0;length>i;i++)"user"===data.entities[i].type?self[connection][data.entities[i].username]=data.entities[i]:self[connection][data.entities[i].name]=data.entities[i];doCallback(callback,[err,data,data.entities],self)})}else if("function"==typeof callback){var error="Error in getConnections - no uuid specified.";self._client.logging&&console.log(error),doCallback(callback,[!0,error],self)}},Usergrid.Entity.prototype.getGr
 oups=function(callback){var self=this,endpoint="users/"+this.get("uuid")+"/groups",options={method:"GET",endpoint:endpoint};this._client.request(options,function(err,data){err&&self._client.logging&&console.log("entity could not be connected"),self.groups=data.entities,doCallback(callback,[err,data,data.entities],self)})},Usergrid.Entity.prototype.getActivities=function(callback){var self=this,endpoint=this.get("type")+"/"+this.get("uuid")+"/activities",options={method:"GET",endpoint:endpoint};this._client.request(options,function(err,data){err&&self._client.logging&&console.log("entity could not be connected");for(var entity in data.entities)data.entities[entity].createdDate=new Date(data.entities[entity].created).toUTCString();self.activities=data.entities,doCallback(callback,[err,data,data.entities],self)})},Usergrid.Entity.prototype.getFollowing=function(callback){var self=this,endpoint="users/"+this.get("uuid")+"/following",options={method:"GET",endpoint:endpoint};this._client.
 request(options,function(err,data){err&&self._client.logging&&console.log("could not get user following");for(var entity in data.entities){data.entities[entity].createdDate=new Date(data.entities[entity].created).toUTCString();var image=self._client.getDisplayImage(data.entities[entity].email,data.entities[entity].picture);data.entities[entity]._portal_image_icon=image}self.following=data.entities,doCallback(callback,[err,data,data.entities],self)})},Usergrid.Entity.prototype.getFollowers=function(callback){var self=this,endpoint="users/"+this.get("uuid")+"/followers",options={method:"GET",endpoint:endpoint};this._client.request(options,function(err,data){err&&self._client.logging&&console.log("could not get user followers");for(var entity in data.entities){data.entities[entity].createdDate=new Date(data.entities[entity].created).toUTCString();var image=self._client.getDisplayImage(data.entities[entity].email,data.entities[entity].picture);data.entities[entity]._portal_image_icon=im
 age}self.followers=data.entities,doCallback(callback,[err,data,data.entities],self)})},Usergrid.Entity.prototype.getRoles=function(callback){var self=this,endpoint=this.get("type")+"/"+this.get("uuid")+"/roles",options={method:"GET",endpoint:endpoint};this._client.request(options,function(err,data){err&&self._client.logging&&console.log("could not get user roles"),self.roles=data.entities,doCallback(callback,[err,data,data.entities],self)})},Usergrid.Entity.prototype.getPermissions=function(callback){var self=this,endpoint=this.get("type")+"/"+this.get("uuid")+"/permissions",options={method:"GET",endpoint:endpoint};this._client.request(options,function(err,data){err&&self._client.logging&&console.log("could not get user permissions");var permissions=[];if(data.data){var perms=data.data,count=0;for(var i in perms){count++;var perm=perms[i],parts=perm.split(":"),ops_part="",path_part=parts[0];parts.length>1&&(ops_part=parts[0],path_part=parts[1]),ops_part=ops_part.replace("*","get,pos
 t,put,delete");var ops=ops_part.split(","),ops_object={};ops_object.get="no",ops_object.post="no",ops_object.put="no",ops_object.delete="no";for(var j in ops)ops_object[ops[j]]="yes";permissions.push({operations:ops_object,path:path_part,perm:perm})}}self.permissions=permissions,doCallback(callback,[err,data,data.entities],self)})},Usergrid.Collection=function(options){if(options&&(this._client=options.client,this._type=options.type,this.qs=options.qs||{},this._list=options.list||[],this._iterator=options.iterator||-1,this._previous=options.previous||[],this._next=options.next||null,this._cursor=options.cursor||null,options.list))for(var count=options.list.length,i=0;count>i;i++){var entity=this._client.restoreEntity(options.list[i]);this._list[i]=entity}},Usergrid.isCollection=function(obj){return obj&&obj instanceof Usergrid.Collection},Usergrid.Collection.prototype.serialize=function(){var data={};data.type=this._type,data.qs=this.qs,data.iterator=this._iterator,data.previous=thi
 s._previous,data.next=this._next,data.cursor=this._cursor,this.resetEntityPointer();var i=0;for(data.list=[];this.hasNextEntity();){var entity=this.getNextEntity();data.list[i]=entity.serialize(),i++}return data=JSON.stringify(data)},Usergrid.Collection.prototype.fetch=function(callback){var self=this,qs=this.qs;this._cursor?qs.cursor=this._cursor:delete qs.cursor;var options={method:"GET",endpoint:this._type,qs:this.qs};this._client.request(options,function(err,response){err&&self._client.logging?console.log("error getting collection"):(self.saveCursor(response.cursor||null),self.resetEntityPointer(),self._list=response.getEntities().filter(function(entity){return isUUID(entity.uuid)}).map(function(entity){var ent=new Usergrid.Entity({client:self._client});return ent.set(entity),ent.type=self._type,ent})),doCallback(callback,[err,response,self],self)})},Usergrid.Collection.prototype.addEntity=function(entityObject,callback){var self=this;entityObject.type=this._type,this._client.cr
 eateEntity(entityObject,function(err,response,entity){err||self.addExistingEntity(entity),doCallback(callback,[err,response,self],self)
+})},Usergrid.Collection.prototype.addExistingEntity=function(entity){var count=this._list.length;this._list[count]=entity},Usergrid.Collection.prototype.destroyEntity=function(entity,callback){var self=this;entity.destroy(function(err,response){err?(self._client.logging&&console.log("could not destroy entity"),doCallback(callback,[err,response,self],self)):self.fetch(callback),self.removeEntity(entity)})},Usergrid.Collection.prototype.getEntitiesByCriteria=function(criteria){return this._list.filter(criteria)},Usergrid.Collection.prototype.getEntityByCriteria=function(criteria){return this.getEntitiesByCriteria(criteria).shift()},Usergrid.Collection.prototype.removeEntity=function(entity){var removedEntity=this.getEntityByCriteria(function(item){return entity.uuid===item.get("uuid")});return delete this._list[this._list.indexOf(removedEntity)],removedEntity},Usergrid.Collection.prototype.getEntityByUUID=function(uuid,callback){var entity=this.getEntityByCriteria(function(item){retur
 n item.get("uuid")===uuid});if(entity)doCallback(callback,[null,entity,entity],this);else{var options={data:{type:this._type,uuid:uuid},client:this._client};entity=new Usergrid.Entity(options),entity.fetch(callback)}},Usergrid.Collection.prototype.getFirstEntity=function(){var count=this._list.length;return count>0?this._list[0]:null},Usergrid.Collection.prototype.getLastEntity=function(){var count=this._list.length;return count>0?this._list[count-1]:null},Usergrid.Collection.prototype.hasNextEntity=function(){var next=this._iterator+1,hasNextElement=next>=0&&next<this._list.length;return hasNextElement?!0:!1},Usergrid.Collection.prototype.getNextEntity=function(){this._iterator++;var hasNextElement=this._iterator>=0&&this._iterator<=this._list.length;return hasNextElement?this._list[this._iterator]:!1},Usergrid.Collection.prototype.hasPrevEntity=function(){var previous=this._iterator-1,hasPreviousElement=previous>=0&&previous<this._list.length;return hasPreviousElement?!0:!1},Userg
 rid.Collection.prototype.getPrevEntity=function(){this._iterator--;var hasPreviousElement=this._iterator>=0&&this._iterator<=this._list.length;return hasPreviousElement?this._list[this._iterator]:!1},Usergrid.Collection.prototype.resetEntityPointer=function(){this._iterator=-1},Usergrid.Collection.prototype.saveCursor=function(cursor){this._next!==cursor&&(this._next=cursor)},Usergrid.Collection.prototype.resetPaging=function(){this._previous=[],this._next=null,this._cursor=null},Usergrid.Collection.prototype.hasNextPage=function(){return this._next},Usergrid.Collection.prototype.getNextPage=function(callback){this.hasNextPage()&&(this._previous.push(this._cursor),this._cursor=this._next,this._list=[],this.fetch(callback))},Usergrid.Collection.prototype.hasPreviousPage=function(){return this._previous.length>0},Usergrid.Collection.prototype.getPreviousPage=function(callback){this.hasPreviousPage()&&(this._next=null,this._cursor=this._previous.pop(),this._list=[],this.fetch(callback)
 )},Usergrid.Group=function(options){this._path=options.path,this._list=[],this._client=options.client,this._data=options.data||{},this._data.type="groups"},Usergrid.Group.prototype=new Usergrid.Entity,Usergrid.Group.prototype.fetch=function(callback){var self=this,groupEndpoint="groups/"+this._path,memberEndpoint="groups/"+this._path+"/users",groupOptions={method:"GET",endpoint:groupEndpoint},memberOptions={method:"GET",endpoint:memberEndpoint};this._client.request(groupOptions,function(err,response){if(err)self._client.logging&&console.log("error getting group"),doCallback(callback,[err,response],self);else{var entities=response.getEntities();if(entities&&entities.length){{entities.shift()}self._client.request(memberOptions,function(err,response){err&&self._client.logging?console.log("error getting group users"):self._list=response.getEntities().filter(function(entity){return isUUID(entity.uuid)}).map(function(entity){return new Usergrid.Entity({type:entity.type,client:self._client
 ,uuid:entity.uuid,response:entity})}),doCallback(callback,[err,response,self],self)})}}})},Usergrid.Group.prototype.members=function(){return this._list},Usergrid.Group.prototype.add=function(options,callback){var self=this;options.user?(options={method:"POST",endpoint:"groups/"+this._path+"/users/"+options.user.get("username")},this._client.request(options,function(error,response){error?doCallback(callback,[error,response,self],self):self.fetch(callback)})):doCallback(callback,[new UsergridError("no user specified","no_user_specified"),null,this],this)},Usergrid.Group.prototype.remove=function(options,callback){var self=this;options.user?(options={method:"DELETE",endpoint:"groups/"+this._path+"/users/"+options.user.get("username")},this._client.request(options,function(error,response){error?doCallback(callback,[error,response,self],self):self.fetch(callback)})):doCallback(callback,[new UsergridError("no user specified","no_user_specified"),null,this],this)},Usergrid.Group.prototype
 .feed=function(callback){var self=this,options={method:"GET",endpoint:"groups/"+this._path+"/feed"};this._client.request(options,function(err,response){doCallback(callback,[err,response,self],self)})},Usergrid.Group.prototype.createGroupActivity=function(options,callback){var self=this,user=options.user,entity=new Usergrid.Entity({client:this._client,data:{actor:{displayName:user.get("username"),uuid:user.get("uuid"),username:user.get("username"),email:user.get("email"),picture:user.get("picture"),image:{duration:0,height:80,url:user.get("picture"),width:80}},verb:"post",content:options.content,type:"groups/"+this._path+"/activities"}});entity.save(function(err,response){doCallback(callback,[err,response,self])})},Usergrid.Counter=function(options){this._client=options.client,this._data=options.data||{},this._data.category=options.category||"UNKNOWN",this._data.timestamp=options.timestamp||0,this._data.type="events",this._data.counters=options.counters||{}};var COUNTER_RESOLUTIONS=[
 "all","minute","five_minutes","half_hour","hour","six_day","day","week","month"];Usergrid.Counter.prototype=new Usergrid.Entity,Usergrid.Counter.prototype.fetch=function(callback){this.getData({},callback)},Usergrid.Counter.prototype.increment=function(options,callback){var self=this,name=options.name,value=options.value;return name?isNaN(value)?doCallback(callback,[new UsergridInvalidArgumentError("'value' for increment, decrement must be a number"),null,self],self):(self._data.counters[name]=parseInt(value)||1,self.save(callback)):doCallback(callback,[new UsergridInvalidArgumentError("'name' for increment, decrement must be a number"),null,self],self)},Usergrid.Counter.prototype.decrement=function(options,callback){var self=this,name=options.name,value=options.value;self.increment({name:name,value:-(parseInt(value)||1)},callback)},Usergrid.Counter.prototype.reset=function(options,callback){var self=this,name=options.name;self.increment({name:name,value:0},callback)},Usergrid.Count
 er.prototype.getData=function(options,callback){var start_time,end_time,start=options.start||0,end=options.end||Date.now(),resolution=(options.resolution||"all").toLowerCase(),counters=options.counters||Object.keys(this._data.counters),res=(resolution||"all").toLowerCase();-1===COUNTER_RESOLUTIONS.indexOf(res)&&(res="all"),start_time=getSafeTime(start),end_time=getSafeTime(end);var self=this,params=Object.keys(counters).map(function(counter){return["counter",encodeURIComponent(counters[counter])].join("=")});params.push("resolution="+res),params.push("start_time="+String(start_time)),params.push("end_time="+String(end_time));var endpoint="counters?"+params.join("&");this._client.request({endpoint:endpoint},function(err,data){return data.counters&&data.counters.length&&data.counters.forEach(function(counter){self._data.counters[counter.name]=counter.value||counter.values}),doCallback(callback,[err,data,self],self)})},Usergrid.Folder=function(options,callback){var self=this;console.lo
 g("FOLDER OPTIONS",options),self._client=options.client,self._data=options.data||{},self._data.type="folders";var missingData=["name","owner","path"].some(function(required){return!(required in self._data)});return missingData?doCallback(callback,[new UsergridInvalidArgumentError("Invalid asset data: 'name', 'owner', and 'path' are required properties."),null,self],self):void self.save(function(err,response){err?doCallback(callback,[new UsergridError(response),response,self],self):(response&&response.entities&&response.entities.length&&self.set(response.entities[0]),doCallback(callback,[null,response,self],self))})},Usergrid.Folder.prototype=new Usergrid.Entity,Usergrid.Folder.prototype.fetch=function(callback){var self=this;Usergrid.Entity.prototype.fetch.call(self,function(err,data){console.log("self",self.get()),console.log("data",data),err?doCallback(callback,[null,data,self],self):self.getAssets(function(err,response){err?doCallback(callback,[new UsergridError(response),resonse
 ,self],self):doCallback(callback,[null,self],self)})})},Usergrid.Folder.prototype.addAsset=function(options,callback){var self=this;if("asset"in options){var asset=null;switch(typ

<TRUNCATED>

[02/12] Refactored individual modules for standard callback signature and updated tests

Posted by sn...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/da8ecfff/sdks/html5-javascript/usergrid.min.js
----------------------------------------------------------------------
diff --git a/sdks/html5-javascript/usergrid.min.js b/sdks/html5-javascript/usergrid.min.js
index 52f3d82..ccec845 100644
--- a/sdks/html5-javascript/usergrid.min.js
+++ b/sdks/html5-javascript/usergrid.min.js
@@ -1,3 +1,3 @@
-/*! usergrid@0.11.0 2014-03-21 */
-function extend(subClass,superClass){var F=function(){};return F.prototype=superClass.prototype,subClass.prototype=new F,subClass.prototype.constructor=subClass,subClass.superclass=superClass.prototype,superClass.prototype.constructor==Object.prototype.constructor&&(superClass.prototype.constructor=superClass),subClass}function propCopy(from,to){for(var prop in from)from.hasOwnProperty(prop)&&(to[prop]="object"==typeof from[prop]&&"object"==typeof to[prop]?propCopy(from[prop],to[prop]):from[prop]);return to}function NOOP(){}function isValidUrl(url){if(!url)return!1;var doc,base,anchor,isValid=!1;try{doc=document.implementation.createHTMLDocument(""),base=doc.createElement("base"),base.href=base||window.lo,doc.head.appendChild(base),anchor=doc.createElement("a"),anchor.href=url,doc.body.appendChild(anchor),isValid=!(""===anchor.href)}catch(e){console.error(e)}finally{return doc.head.removeChild(base),doc.body.removeChild(anchor),base=null,anchor=null,doc=null,isValid}}function isUUID
 (uuid){return uuid?uuidValueRegex.test(uuid):!1}function encodeParams(params){var queryString;return params&&Object.keys(params)&&(queryString=[].slice.call(arguments).reduce(function(a,b){return a.concat(b instanceof Array?b:[b])},[]).filter(function(c){return"object"==typeof c}).reduce(function(p,c){return c instanceof Array?p.push(c):p=p.concat(Object.keys(c).map(function(key){return[key,c[key]]})),p},[]).reduce(function(p,c){return 2===c.length?p.push(c):p=p.concat(c),p},[]).reduce(function(p,c){return c[1]instanceof Array?c[1].forEach(function(v){p.push([c[0],v])}):p.push(c),p},[]).map(function(c){return c[1]=encodeURIComponent(c[1]),c.join("=")}).join("&")),queryString}function isFunction(f){return f&&null!==f&&"function"==typeof f}function doCallback(callback,params,context){var returnValue;return isFunction(callback)&&(params||(params=[]),context||(context=this),params.push(context),returnValue=callback.apply(context,params)),returnValue}var UsergridEventable=function(){thro
 w Error("'UsergridEventable' is not intended to be invoked directly")};UsergridEventable.prototype={bind:function(event,fn){this._events=this._events||{},this._events[event]=this._events[event]||[],this._events[event].push(fn)},unbind:function(event,fn){this._events=this._events||{},event in this._events!=!1&&this._events[event].splice(this._events[event].indexOf(fn),1)},trigger:function(event){if(this._events=this._events||{},event in this._events!=!1)for(var i=0;i<this._events[event].length;i++)this._events[event][i].apply(this,Array.prototype.slice.call(arguments,1))}},UsergridEventable.mixin=function(destObject){for(var props=["bind","unbind","trigger"],i=0;i<props.length;i++)props[i]in destObject.prototype&&(console.warn("overwriting '"+props[i]+"' on '"+destObject.name+"'."),console.warn("the previous version can be found at '_"+props[i]+"' on '"+destObject.name+"'."),destObject.prototype["_"+props[i]]=destObject.prototype[props[i]]),destObject.prototype[props[i]]=UsergridEven
 table.prototype[props[i]]},function(){function Logger(name){this.logEnabled=!0,this.init(name,!0)}var name="Logger",global=this,overwrittenName=global[name];return Logger.METHODS=["log","error","warn","info","debug","assert","clear","count","dir","dirxml","exception","group","groupCollapsed","groupEnd","profile","profileEnd","table","time","timeEnd","trace"],Logger.prototype.init=function(name,logEnabled){this.name=name||"UNKNOWN",this.logEnabled=logEnabled||!0;var addMethod=function(method){this[method]=this.createLogMethod(method)}.bind(this);Logger.METHODS.forEach(addMethod)},Logger.prototype.createLogMethod=function(method){return Logger.prototype.log.bind(this,method)},Logger.prototype.prefix=function(method,args){var prepend="["+method.toUpperCase()+"]["+name+"]:	";return-1!==["log","error","warn","info"].indexOf(method)&&("string"==typeof args[0]?args[0]=prepend+args[0]:args.unshift(prepend)),args},Logger.prototype.log=function(){var args=[].slice.call(arguments);method=args.
 shift(),-1===Logger.METHODS.indexOf(method)&&(method="log"),this.logEnabled&&console&&console[method]&&(args=this.prefix(method,args),console[method].apply(console,args))},Logger.prototype.setLogEnabled=function(logEnabled){this.logEnabled=logEnabled||!0},Logger.mixin=function(destObject){destObject.__logger=new Logger(destObject.name||"UNKNOWN");var addMethod=function(method){method in destObject.prototype&&(console.warn("overwriting '"+method+"' on '"+destObject.name+"'."),console.warn("the previous version can be found at '_"+method+"' on '"+destObject.name+"'."),destObject.prototype["_"+method]=destObject.prototype[method]),destObject.prototype[method]=destObject.__logger.createLogMethod(method)};Logger.METHODS.forEach(addMethod)},global[name]=Logger,global[name].noConflict=function(){return overwrittenName&&(global[name]=overwrittenName),Logger},global[name]}(),function(global){function Promise(){this.complete=!1,this.error=null,this.result=null,this.callbacks=[]}var name="Prom
 ise",overwrittenName=global[name];return Promise.prototype.create=function(){return new Promise},Promise.prototype.then=function(callback,context){var f=function(){return callback.apply(context,arguments)};this.complete?f(this.error,this.result):this.callbacks.push(f)},Promise.prototype.done=function(error,result){if(this.complete=!0,this.error=error,this.result=result,this.callbacks){for(var i=0;i<this.callbacks.length;i++)this.callbacks[i](error,result);this.callbacks.length=0}},Promise.join=function(promises){function notifier(i){return function(error,result){completed+=1,errors[i]=error,results[i]=result,completed===total&&p.done(errors,results)}}for(var p=new Promise,total=promises.length,completed=0,errors=[],results=[],i=0;total>i;i++)promises[i]().then(notifier(i));return p},Promise.chain=function(promises,error,result){var p=new Promise;return null===promises||0===promises.length?p.done(error,result):promises[0](error,result).then(function(res,err){promises.splice(0,1),prom
 ises?Promise.chain(promises,res,err).then(function(r,e){p.done(r,e)}):p.done(res,err)}),p},global[name]=Promise,global[name].noConflict=function(){return overwrittenName&&(global[name]=overwrittenName),Promise},global[name]}(this),function(){function partial(){var args=Array.prototype.slice.call(arguments),fn=args.shift();return fn.bind(this,args)}function Ajax(){function encode(data){var result="";if("string"==typeof data)result=data;else{var e=encodeURIComponent;for(var i in data)data.hasOwnProperty(i)&&(result+="&"+e(i)+"="+e(data[i]))}return result}function request(m,u,d){var timeout,p=new Promise;return self.logger.time(m+" "+u),function(xhr){xhr.onreadystatechange=function(){4^this.readyState||(self.logger.timeEnd(m+" "+u),clearTimeout(timeout),p.done(null,this))},xhr.onerror=function(response){clearTimeout(timeout),p.done(response,null)},xhr.oncomplete=function(){clearTimeout(timeout),self.logger.timeEnd(m+" "+u),self.info("%s request to %s returned %s",m,u,this.status)},xhr.
 open(m,u),d&&("object"==typeof d&&(d=JSON.stringify(d)),xhr.setRequestHeader("Content-Type","application/json"),xhr.setRequestHeader("Accept","application/json")),timeout=setTimeout(function(){xhr.abort(),p.done("API Call timed out.",null)},3e4),xhr.send(encode(d))}(new XMLHttpRequest),p}this.logger=new global.Logger(name);var self=this;this.request=request,this.get=partial(request,"GET"),this.post=partial(request,"POST"),this.put=partial(request,"PUT"),this.delete=partial(request,"DELETE")}var exports,name="Ajax",global=this,overwrittenName=global[name];return global[name]=new Ajax,global[name].noConflict=function(){return overwrittenName&&(global[name]=overwrittenName),exports},global[name]}(),window.console=window.console||{},window.console.log=window.console.log||function(){};var uuidValueRegex=/^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/;!function(global){function Usergrid(){this.logger=new Logger(name)}var name="Usergrid",overwrittenName=glob
 al[name];Usergrid.isValidEndpoint=function(){return!0};var VALID_REQUEST_METHODS=["GET","POST","PUT","DELETE"];return Usergrid.Request=function(method,endpoint,query_params,data,callback){var p=new Promise;if(this.logger=new global.Logger("Usergrid.Request"),this.logger.time("process request "+method+" "+endpoint),this.endpoint=endpoint+"?"+encodeParams(query_params),this.method=method.toUpperCase(),this.data="object"==typeof data?JSON.stringify(data):data,-1===VALID_REQUEST_METHODS.indexOf(this.method))throw new UsergridInvalidHTTPMethodError("invalid request method '"+this.method+"'");if(!isValidUrl(this.endpoint))throw this.logger.error(endpoint,this.endpoint,/^https:\/\//.test(endpoint)),new UsergridInvalidURIError("The provided endpoint is not valid: "+this.endpoint);var request=function(){return Ajax.request(this.method,this.endpoint,this.data)}.bind(this),response=function(err,request){return new Usergrid.Response(err,request)}.bind(this),oncomplete=function(err,response){p.d
 one(err,response),this.logger.info("REQUEST",err,response),doCallback(callback,[err,response]),this.logger.timeEnd("process request "+method+" "+endpoint)}.bind(this);return Promise.chain([request,response]).then(oncomplete),p},Usergrid.Response=function(err,response){var p=new Promise,data=null;try{data=JSON.parse(response.responseText)}catch(e){data={}}switch(Object.keys(data).forEach(function(key){Object.defineProperty(this,key,{value:data[key],enumerable:!0})}.bind(this)),Object.defineProperty(this,"logger",{enumerable:!1,configurable:!1,writable:!1,value:new global.Logger(name)}),Object.defineProperty(this,"success",{enumerable:!1,configurable:!1,writable:!0,value:!0}),Object.defineProperty(this,"err",{enumerable:!1,configurable:!1,writable:!0,value:err}),Object.defineProperty(this,"status",{enumerable:!1,configurable:!1,writable:!0,value:parseInt(response.status)}),Object.defineProperty(this,"statusGroup",{enumerable:!1,configurable:!1,writable:!0,value:this.status-this.status
 %100}),this.statusGroup){case 200:this.success=!0;break;case 400:case 500:case 300:case 100:default:this.success=!1}return this.success?p.done(null,this):p.done(UsergridError.fromResponse(data),this),p},Usergrid.Response.prototype.getEntities=function(){var entities=[];return this.success&&(entities=this.data?this.data.entities:this.entities),entities},Usergrid.Response.prototype.getEntity=function(){var entities=this.getEntities();return entities[0]},Usergrid.VERSION=Usergrid.USERGRID_SDK_VERSION="0.11.0",global[name]=Usergrid,global[name].noConflict=function(){return overwrittenName&&(global[name]=overwrittenName),Usergrid},global[name]}(this),function(){var exports,name="Client",global=this,overwrittenName=global[name];return Usergrid.Client=function(options){this.URI=options.URI||"https://api.usergrid.com",options.orgName&&this.set("orgName",options.orgName),options.appName&&this.set("appName",options.appName),options.qs&&this.setObject("default_qs",options.qs),this.buildCurl=op
 tions.buildCurl||!1,this.logging=options.logging||!1,this._callTimeout=options.callTimeout||3e4,this._callTimeoutCallback=options.callTimeoutCallback||null,this.logoutCallback=options.logoutCallback||null},Usergrid.Client.prototype.request=function(options,callback){var uri,method=options.method||"GET",endpoint=options.endpoint,body=options.body||{},qs=options.qs||{},mQuery=options.mQuery||!1,orgName=this.get("orgName"),appName=this.get("appName"),default_qs=this.getObject("default_qs"),logoutCallback=function(){return"function"==typeof this.logoutCallback?this.logoutCallback(!0,"no_org_or_app_name_specified"):void 0}.bind(this);if(!mQuery&&!orgName&&!appName)return logoutCallback();uri=mQuery?this.URI+"/"+endpoint:this.URI+"/"+orgName+"/"+appName+"/"+endpoint,this.getToken()&&(qs.access_token=this.getToken()),default_qs&&(qs=propCopy(qs,default_qs));new Usergrid.Request(method,uri,qs,body,function(err,response){return-1!==["auth_expired_session_token","auth_missing_credentials","au
 th_unverified_oath","expired_token","unauthorized","auth_invalid"].indexOf(response.error)?logoutCallback():void doCallback(callback,[err,response])})},Usergrid.Client.prototype.buildAssetURL=function(uuid){var self=this,qs={},assetURL=this.URI+"/"+this.orgName+"/"+this.appName+"/assets/"+uuid+"/data";self.getToken()&&(qs.access_token=self.getToken());var encoded_params=encodeParams(qs);return encoded_params&&(assetURL+="?"+encoded_params),assetURL},Usergrid.Client.prototype.createGroup=function(options,callback){options={path:options.path,client:this,data:options};var group=new Usergrid.Group(options);group.save(function(err,data){doCallback(callback,[err,group,data])})},Usergrid.Client.prototype.createEntity=function(options,callback){var entity_data={client:this,data:options},entity=new Usergrid.Entity(entity_data);entity.save(function(err,data){doCallback(callback,[err,entity,data])})},Usergrid.Client.prototype.getEntity=function(options,callback){var options={client:this,data:o
 ptions},entity=new Usergrid.Entity(options);entity.fetch(function(err,data){doCallback(callback,[err,entity,data])})},Usergrid.Client.prototype.restoreEntity=function(serializedObject){var data=JSON.parse(serializedObject),options={client:this,data:data},entity=new Usergrid.Entity(options);return entity},Usergrid.Client.prototype.createCollection=function(options,callback){options.client=this,new Usergrid.Collection(options,function(err,data,collection){doCallback(callback,[err,collection,data])})},Usergrid.Client.prototype.restoreCollection=function(serializedObject){var data=JSON.parse(serializedObject);data.client=this;var collection=new Usergrid.Collection(data);return collection},Usergrid.Client.prototype.getFeedForUser=function(username,callback){var options={method:"GET",endpoint:"users/"+username+"/feed"};this.request(options,function(err,data){err?doCallback(callback,[err]):doCallback(callback,[err,data,data.getEntities()])})},Usergrid.Client.prototype.createUserActivity=fu
 nction(user,options,callback){options.type="users/"+user+"/activities";var options={client:this,data:options},entity=new Usergrid.Entity(options);entity.save(function(err){doCallback(callback,[err,entity])})},Usergrid.Client.prototype.createUserActivityWithEntity=function(user,content,callback){var username=user.get("username"),options={actor:{displayName:username,uuid:user.get("uuid"),username:username,email:user.get("email"),picture:user.get("picture"),image:{duration:0,height:80,url:user.get("picture"),width:80}},verb:"post",content:content};this.createUserActivity(username,options,callback)},Usergrid.Client.prototype.calcTimeDiff=function(){var seconds=0,time=this._end-this._start;try{seconds=(time/10/60).toFixed(2)}catch(e){return 0}return seconds},Usergrid.Client.prototype.setToken=function(token){this.set("token",token)},Usergrid.Client.prototype.getToken=function(){return this.get("token")},Usergrid.Client.prototype.setObject=function(key,value){value&&(value=JSON.stringify(
 value)),this.set(key,value)},Usergrid.Client.prototype.set=function(key,value){var keyStore="apigee_"+key;this[key]=value,"undefined"!=typeof Storage&&(value?localStorage.setItem(keyStore,value):localStorage.removeItem(keyStore))},Usergrid.Client.prototype.getObject=function(key){return JSON.parse(this.get(key))},Usergrid.Client.prototype.get=function(key){var keyStore="apigee_"+key,value=null;return this[key]?value=this[key]:"undefined"!=typeof Storage&&(value=localStorage.getItem(keyStore)),value},Usergrid.Client.prototype.signup=function(username,password,email,name,callback){var options={type:"users",username:username,password:password,email:email,name:name};this.createEntity(options,callback)},Usergrid.Client.prototype.login=function(username,password,callback){var self=this,options={method:"POST",endpoint:"token",body:{username:username,password:password,grant_type:"password"}};self.request(options,function(err,data){var user={};if(err)self.logging&&console.log("error trying t
 o log user in");else{var options={client:self,data:data.user};user=new Usergrid.Entity(options),self.setToken(data.access_token)}doCallback(callback,[err,data,user])})},Usergrid.Client.prototype.reAuthenticateLite=function(callback){var self=this,options={method:"GET",endpoint:"management/me",mQuery:!0};this.request(options,function(err,response){err&&self.logging?console.log("error trying to re-authenticate user"):self.setToken(response.data.access_token),doCallback(callback,[err])})},Usergrid.Client.prototype.reAuthenticate=function(email,callback){var self=this,options={method:"GET",endpoint:"management/users/"+email,mQuery:!0};this.request(options,function(err,response){var data,organizations={},applications={},user={};if(err&&self.logging)console.log("error trying to full authenticate user");else{data=response.data,self.setToken(data.token),self.set("email",data.email),localStorage.setItem("accessToken",data.token),localStorage.setItem("userUUID",data.uuid),localStorage.setItem
 ("userEmail",data.email);var userData={username:data.username,email:data.email,name:data.name,uuid:data.uuid},options={client:self,data:userData};user=new Usergrid.Entity(options),organizations=data.organizations;var org="";try{var existingOrg=self.get("orgName");org=organizations[existingOrg]?organizations[existingOrg]:organizations[Object.keys(organizations)[0]],self.set("orgName",org.name)}catch(e){err=!0,self.logging&&console.log("error selecting org")}applications=self.parseApplicationsArray(org),self.selectFirstApp(applications),self.setObject("organizations",organizations),self.setObject("applications",applications)}doCallback(callback,[err,data,user,organizations,applications],self)})},Usergrid.Client.prototype.loginFacebook=function(facebookToken,callback){var self=this,options={method:"GET",endpoint:"auth/facebook",qs:{fb_access_token:facebookToken}};this.request(options,function(err,data){var user={};if(err&&self.logging)console.log("error trying to log user in");else{var
  options={client:self,data:data.user};user=new Usergrid.Entity(options),self.setToken(data.access_token)}doCallback(callback,[err,data,user],self)})},Usergrid.Client.prototype.getLoggedInUser=function(callback){if(this.getToken()){var self=this,options={method:"GET",endpoint:"users/me"};this.request(options,function(err,data){if(err)self.logging&&console.log("error trying to log user in"),doCallback(callback,[err,data,null],self);else{var options={client:self,data:data.entities[0]},user=new Usergrid.Entity(options);doCallback(callback,[null,data,user],self)}})}else callback(!0,null,null)},Usergrid.Client.prototype.isLoggedIn=function(){var token=this.getToken();return"undefined"!=typeof token&&null!==token},Usergrid.Client.prototype.logout=function(){this.setToken()},Usergrid.Client.prototype.destroyToken=function(username,token,revokeAll,callback){var options={client:self,method:"PUT"};options.endpoint=1==revokeAll?"users/"+username+"/revoketokens":null==token?"users/"+username+"/r
 evoketoken?token="+this.getToken():"users/"+username+"/revoketoken?token="+token,this.request(options,function(err,data){err?(self.logging&&console.log("error destroying access token"),doCallback(callback,[err,data,null],self)):(console.log(1==revokeAll?"all user tokens invalidated":"token invalidated"),doCallback(callback,[err,data,null],self))})},Usergrid.Client.prototype.logoutAndDestroyToken=function(username,token,revokeAll,callback){null==username?console.log("username required to revoke tokens"):(this.destroyToken(username,token,revokeAll,callback),(1==revokeAll||token==this.getToken()||null==token)&&this.setToken(null))},Usergrid.Client.prototype.buildCurlCall=function(options){var curl=["curl"],method=(options.method||"GET").toUpperCase(),body=options.body,uri=options.uri;return curl.push("-X"),curl.push(["POST","PUT","DELETE"].indexOf(method)>=0?method:"GET"),curl.push(uri),"object"==typeof body&&Object.keys(body).length>0&&-1!==["POST","PUT"].indexOf(method)&&(curl.push("
 -d"),curl.push("'"+JSON.stringify(body)+"'")),curl=curl.join(" "),console.log(curl),curl},Usergrid.Client.prototype.getDisplayImage=function(email,picture,size){size=size||50;var image="https://apigee.com/usergrid/images/user_profile.png";try{picture?image=picture:email.length&&(image="https://secure.gravatar.com/avatar/"+MD5(email)+"?s="+size+encodeURI("&d=https://apigee.com/usergrid/images/user_profile.png"))}catch(e){}finally{return image}},global[name]=Usergrid.Client,global[name].noConflict=function(){return overwrittenName&&(global[name]=overwrittenName),exports},global[name]}();var ENTITY_SYSTEM_PROPERTIES=["metadata","created","modified","oldpassword","newpassword","type","activated","uuid"];Usergrid.Entity=function(options){options&&(this._data=options.data||{},this._client=options.client||{})},Usergrid.Entity.isEntity=function(obj){return obj&&obj instanceof Usergrid.Entity},Usergrid.Entity.isPersistedEntity=function(obj){return isEntity(obj)&&isUUID(obj.get("uuid"))},User
 grid.Entity.prototype.serialize=function(){return JSON.stringify(this._data)},Usergrid.Entity.prototype.get=function(key){var value;if(0===arguments.length?value=this._data:arguments.length>1&&(key=[].slice.call(arguments).reduce(function(p,c){return c instanceof Array?p=p.concat(c):p.push(c),p},[])),key instanceof Array){var self=this;value=key.map(function(k){return self.get(k)})}else"undefined"!=typeof key&&(value=this._data[key]);return value},Usergrid.Entity.prototype.set=function(key,value){if("object"==typeof key)for(var field in key)this._data[field]=key[field];else"string"==typeof key?null===value?delete this._data[key]:this._data[key]=value:this._data={}},Usergrid.Entity.prototype.getEndpoint=function(){var name,type=this.get("type"),nameProperties=["uuid","name"];if(void 0===type)throw new UsergridError("cannot fetch entity, no entity type specified","no_type_specified");("users"===type||"user"===type)&&nameProperties.unshift("username");var names=this.get(nameProperties)
 .filter(function(x){return null!=x&&"undefined"!=typeof x});return 0===names.length?type:(name=names.shift(),[type,name].join("/"))},Usergrid.Entity.prototype.save=function(callback){var self=this,type=this.get("type"),method="POST",entityId=this.get("uuid"),data={},entityData=this.get(),password=this.get("password"),oldpassword=this.get("oldpassword"),newpassword=this.get("newpassword"),options={method:method,endpoint:type};entityId&&(options.method="PUT",options.endpoint+="/"+entityId),Object.keys(entityData).filter(function(key){return-1===ENTITY_SYSTEM_PROPERTIES.indexOf(key)}).forEach(function(key){data[key]=entityData[key]}),options.body=data,this._client.request(options,function(err,response){var entity=response.getEntity();if(entity&&(self.set(entity),self.set("type",/^\//.test(response.path)?response.path.substring(1):response.path)),self.set("password",null),self.set("oldpassword",null),self.set("newpassword",null),err&&self._client.logging)console.log("could not save enti
 ty"),doCallback(callback,[err,response,self]);else if(/^users?/.test(self.get("type"))&&oldpassword&&newpassword){var options={method:"PUT",endpoint:type+"/"+self.get("uuid")+"/password",body:{uuid:self.get("uuid"),username:self.get("username"),password:password,oldpassword:oldpassword,newpassword:newpassword}};self._client.request(options,function(err,data){err&&self._client.logging&&console.log("could not update user"),self.set({password:null,oldpassword:null,newpassword:null}),doCallback(callback,[err,data,self])})}else doCallback(callback,[err,response,self])})},Usergrid.Entity.prototype.fetch=function(callback){var endpoint,self=this;endpoint=this.getEndpoint();var options={method:"GET",endpoint:endpoint};this._client.request(options,function(err,response){var entity=response.getEntity();entity&&self.set(entity),doCallback(callback,[err,entity,self])})},Usergrid.Entity.prototype.destroy=function(callback){var self=this,endpoint=this.getEndpoint(),options={method:"DELETE",endpoi
 nt:endpoint};this._client.request(options,function(err,data){err||self.set(null),doCallback(callback,[err,data])})},Usergrid.Entity.prototype.connect=function(connection,entity,callback){var error,self=this,connecteeType=entity.get("type"),connectee=this.getEntityId(entity);if(!connectee)return void("function"==typeof callback&&(error="Error trying to delete object - no uuid specified.",self._client.logging&&console.log(error),doCallback(callback,[!0,error],self)));var connectorType=this.get("type"),connector=this.getEntityId(this);if(!connector)return void("function"==typeof callback&&(error="Error in connect - no uuid specified.",self._client.logging&&console.log(error),doCallback(callback,[!0,error],self)));var endpoint=connectorType+"/"+connector+"/"+connection+"/"+connecteeType+"/"+connectee,options={method:"POST",endpoint:endpoint};this._client.request(options,function(err,data){err&&self._client.logging&&console.log("entity could not be connected"),doCallback(callback,[err,da
 ta],self)})},Usergrid.Entity.prototype.getEntityId=function(entity){var id=!1;return isUUID(entity.get("uuid"))?id=entity.get("uuid"):"users"===this.get("type")?id=entity.get("username"):entity.get("name")&&(id=entity.get("name")),id},Usergrid.Entity.prototype.getConnections=function(connection,callback){var self=this,connectorType=this.get("type"),connector=this.getEntityId(this);if(connector){var endpoint=connectorType+"/"+connector+"/"+connection+"/",options={method:"GET",endpoint:endpoint};this._client.request(options,function(err,data){err&&self._client.logging&&console.log("entity could not be connected"),self[connection]={};for(var length=data&&data.entities?data.entities.length:0,i=0;length>i;i++)"user"===data.entities[i].type?self[connection][data.entities[i].username]=data.entities[i]:self[connection][data.entities[i].name]=data.entities[i];doCallback(callback,[err,data,data.entities],self)})}else if("function"==typeof callback){var error="Error in getConnections - no uuid
  specified.";self._client.logging&&console.log(error),doCallback(callback,[!0,error],self)}},Usergrid.Entity.prototype.getGroups=function(callback){var self=this,endpoint="users/"+this.get("uuid")+"/groups",options={method:"GET",endpoint:endpoint};this._client.request(options,function(err,data){err&&self._client.logging&&console.log("entity could not be connected"),self.groups=data.entities,doCallback(callback,[err,data,data.entities],self)})},Usergrid.Entity.prototype.getActivities=function(callback){var self=this,endpoint=this.get("type")+"/"+this.get("uuid")+"/activities",options={method:"GET",endpoint:endpoint};this._client.request(options,function(err,data){err&&self._client.logging&&console.log("entity could not be connected");for(var entity in data.entities)data.entities[entity].createdDate=new Date(data.entities[entity].created).toUTCString();self.activities=data.entities,doCallback(callback,[err,data,data.entities],self)})},Usergrid.Entity.prototype.getFollowing=function(ca
 llback){var self=this,endpoint="users/"+this.get("uuid")+"/following",options={method:"GET",endpoint:endpoint};this._client.request(options,function(err,data){err&&self._client.logging&&console.log("could not get user following");for(var entity in data.entities){data.entities[entity].createdDate=new Date(data.entities[entity].created).toUTCString();var image=self._client.getDisplayImage(data.entities[entity].email,data.entities[entity].picture);data.entities[entity]._portal_image_icon=image}self.following=data.entities,doCallback(callback,[err,data,data.entities],self)})},Usergrid.Entity.prototype.getFollowers=function(callback){var self=this,endpoint="users/"+this.get("uuid")+"/followers",options={method:"GET",endpoint:endpoint};this._client.request(options,function(err,data){err&&self._client.logging&&console.log("could not get user followers");for(var entity in data.entities){data.entities[entity].createdDate=new Date(data.entities[entity].created).toUTCString();var image=self._c
 lient.getDisplayImage(data.entities[entity].email,data.entities[entity].picture);data.entities[entity]._portal_image_icon=image}self.followers=data.entities,doCallback(callback,[err,data,data.entities],self)})},Usergrid.Entity.prototype.getRoles=function(callback){var self=this,endpoint=this.get("type")+"/"+this.get("uuid")+"/roles",options={method:"GET",endpoint:endpoint};this._client.request(options,function(err,data){err&&self._client.logging&&console.log("could not get user roles"),self.roles=data.entities,doCallback(callback,[err,data,data.entities],self)})},Usergrid.Entity.prototype.getPermissions=function(callback){var self=this,endpoint=this.get("type")+"/"+this.get("uuid")+"/permissions",options={method:"GET",endpoint:endpoint};this._client.request(options,function(err,data){err&&self._client.logging&&console.log("could not get user permissions");var permissions=[];if(data.data){var perms=data.data,count=0;for(var i in perms){count++;var perm=perms[i],parts=perm.split(":"),
 ops_part="",path_part=parts[0];parts.length>1&&(ops_part=parts[0],path_part=parts[1]),ops_part.replace("*","get,post,put,delete");var ops=ops_part.split(","),ops_object={};ops_object.get="no",ops_object.post="no",ops_object.put="no",ops_object.delete="no";for(var j in ops)ops_object[ops[j]]="yes";permissions.push({operations:ops_object,path:path_part,perm:perm})}}self.permissions=permissions,doCallback(callback,[err,data,data.entities],self)})},Usergrid.Entity.prototype.disconnect=function(connection,entity,callback){var error,self=this,connecteeType=entity.get("type"),connectee=this.getEntityId(entity);if(!connectee)return void("function"==typeof callback&&(error="Error trying to delete object - no uuid specified.",self._client.logging&&console.log(error),doCallback(callback,[!0,error],self)));var connectorType=this.get("type"),connector=this.getEntityId(this);if(!connector)return void("function"==typeof callback&&(error="Error in connect - no uuid specified.",self._client.logging&
 &console.log(error),doCallback(callback,[!0,error],self)));var endpoint=connectorType+"/"+connector+"/"+connection+"/"+connecteeType+"/"+connectee,options={method:"DELETE",endpoint:endpoint};this._client.request(options,function(err,data){err&&self._client.logging&&console.log("entity could not be disconnected"),doCallback(callback,[err,data],self)})},Usergrid.Collection=function(options,callback){if(options&&(this._client=options.client,this._type=options.type,this.qs=options.qs||{},this._list=options.list||[],this._iterator=options.iterator||-1,this._previous=options.previous||[],this._next=options.next||null,this._cursor=options.cursor||null,options.list))for(var count=options.list.length,i=0;count>i;i++){var entity=this._client.restoreEntity(options.list[i]);this._list[i]=entity}callback&&this.fetch(callback)},Usergrid.isCollection=function(obj){return obj&&obj instanceof Usergrid.Collection},Usergrid.Collection.prototype.serialize=function(){var data={};data.type=this._type,dat
 a.qs=this.qs,data.iterator=this._iterator,data.previous=this._previous,data.next=this._next,data.cursor=this._cursor,this.resetEntityPointer();var i=0;for(data.list=[];this.hasNextEntity();){var entity=this.getNextEntity();data.list[i]=entity.serialize(),i++}return data=JSON.stringify(data)},Usergrid.Collection.prototype.addCollection=function(collectionName,options,callback){self=this,options.client=this._client;var collection=new Usergrid.Collection(options,function(err){if("function"==typeof callback){for(collection.resetEntityPointer();collection.hasNextEntity();){var user=collection.getNextEntity(),image=(user.get("email"),self._client.getDisplayImage(user.get("email"),user.get("picture")));user._portal_image_icon=image}self[collectionName]=collection,doCallback(callback,[err,collection],self)}})},Usergrid.Collection.prototype.fetch=function(callback){var self=this,qs=this.qs;this._cursor?qs.cursor=this._cursor:delete qs.cursor;var options={method:"GET",endpoint:this._type,qs:t
 his.qs};this._client.request(options,function(err,data){if(err&&self._client.logging)console.log("error getting collection");
-else{var cursor=data.cursor||null;if(self.saveCursor(cursor),data.entities){self.resetEntityPointer();var count=data.entities.length;self._list=[];for(var i=0;count>i;i++){var uuid=data.entities[i].uuid;if(uuid){var entityData=data.entities[i]||{};self._baseType=data.entities[i].type,entityData.type=self._type;var entityOptions={type:self._type,client:self._client,uuid:uuid,data:entityData},ent=new Usergrid.Entity(entityOptions);ent._json=JSON.stringify(entityData,null,2);var ct=self._list.length;self._list[ct]=ent}}}}doCallback(callback,[err,data],self)})},Usergrid.Collection.prototype.addEntity=function(options,callback){var self=this;options.type=this._type,this._client.createEntity(options,function(err,entity){if(!err){var count=self._list.length;self._list[count]=entity}doCallback(callback,[err,entity],self)})},Usergrid.Collection.prototype.addExistingEntity=function(entity){var count=this._list.length;this._list[count]=entity},Usergrid.Collection.prototype.destroyEntity=functi
 on(entity,callback){var self=this;entity.destroy(function(err,data){err?(self._client.logging&&console.log("could not destroy entity"),doCallback(callback,[err,data],self)):self.fetch(callback)}),this.removeEntity(entity)},Usergrid.Collection.prototype.removeEntity=function(entity){var uuid=entity.get("uuid");for(var key in this._list){var listItem=this._list[key];if(listItem.get("uuid")===uuid)return this._list.splice(key,1)}return!1},Usergrid.Collection.prototype.getEntityByUUID=function(uuid,callback){for(var key in this._list){var listItem=this._list[key];if(listItem.get("uuid")===uuid)return callback(null,listItem)}var options={data:{type:this._type,uuid:uuid},client:this._client},entity=new Usergrid.Entity(options);entity.fetch(callback)},Usergrid.Collection.prototype.getFirstEntity=function(){var count=this._list.length;return count>0?this._list[0]:null},Usergrid.Collection.prototype.getLastEntity=function(){var count=this._list.length;return count>0?this._list[count-1]:null}
 ,Usergrid.Collection.prototype.hasNextEntity=function(){var next=this._iterator+1,hasNextElement=next>=0&&next<this._list.length;return hasNextElement?!0:!1},Usergrid.Collection.prototype.getNextEntity=function(){this._iterator++;var hasNextElement=this._iterator>=0&&this._iterator<=this._list.length;return hasNextElement?this._list[this._iterator]:!1},Usergrid.Collection.prototype.hasPrevEntity=function(){var previous=this._iterator-1,hasPreviousElement=previous>=0&&previous<this._list.length;return hasPreviousElement?!0:!1},Usergrid.Collection.prototype.getPrevEntity=function(){this._iterator--;var hasPreviousElement=this._iterator>=0&&this._iterator<=this._list.length;return hasPreviousElement?this._list[this._iterator]:!1},Usergrid.Collection.prototype.resetEntityPointer=function(){this._iterator=-1},Usergrid.Collection.prototype.saveCursor=function(cursor){this._next!==cursor&&(this._next=cursor)},Usergrid.Collection.prototype.resetPaging=function(){this._previous=[],this._next
 =null,this._cursor=null},Usergrid.Collection.prototype.hasNextPage=function(){return this._next},Usergrid.Collection.prototype.getNextPage=function(callback){this.hasNextPage()&&(this._previous.push(this._cursor),this._cursor=this._next,this._list=[],this.fetch(callback))},Usergrid.Collection.prototype.hasPreviousPage=function(){return this._previous.length>0},Usergrid.Collection.prototype.getPreviousPage=function(callback){this.hasPreviousPage()&&(this._next=null,this._cursor=this._previous.pop(),this._list=[],this.fetch(callback))},Usergrid.Group=function(options){this._path=options.path,this._list=[],this._client=options.client,this._data=options.data||{},this._data.type="groups"},Usergrid.Group.prototype=new Usergrid.Entity,Usergrid.Group.prototype.fetch=function(callback){var self=this,groupEndpoint="groups/"+this._path,memberEndpoint="groups/"+this._path+"/users",groupOptions={method:"GET",endpoint:groupEndpoint},memberOptions={method:"GET",endpoint:memberEndpoint};this._clien
 t.request(groupOptions,function(err,data){if(err)self._client.logging&&console.log("error getting group"),doCallback(callback,[err,data],self);else if(data.entities&&data.entities.length){var groupData=data.entities[0];self._data=groupData||{},self._client.request(memberOptions,function(err,data){if(err&&self._client.logging)console.log("error getting group users");else if(data.entities){var count=data.entities.length;self._list=[];for(var i=0;count>i;i++){var uuid=data.entities[i].uuid;if(uuid){var entityData=data.entities[i]||{},entityOptions={type:entityData.type,client:self._client,uuid:uuid,data:entityData},entity=new Usergrid.Entity(entityOptions);self._list.push(entity)}}}doCallback(callback,[err,data,self._list],self)})}})},Usergrid.Group.prototype.members=function(callback){doCallback(callback,[null,this._list],this)},Usergrid.Group.prototype.add=function(options,callback){var self=this,options={method:"POST",endpoint:"groups/"+this._path+"/users/"+options.user.get("usernam
 e")};this._client.request(options,function(error,data){error?doCallback(callback,[error,data,data.entities],self):self.fetch(callback)})},Usergrid.Group.prototype.remove=function(options,callback){var self=this,options={method:"DELETE",endpoint:"groups/"+this._path+"/users/"+options.user.get("username")};this._client.request(options,function(error,data){error?doCallback(callback,[error,data],self):self.fetch(callback)})},Usergrid.Group.prototype.feed=function(callback){var self=this,endpoint="groups/"+this._path+"/feed",options={method:"GET",endpoint:endpoint};this._client.request(options,function(err,data){err&&self.logging&&console.log("error trying to log user in"),doCallback(callback,[err,data,data.entities],self)})},Usergrid.Group.prototype.createGroupActivity=function(options,callback){var user=options.user;options={client:this._client,data:{actor:{displayName:user.get("username"),uuid:user.get("uuid"),username:user.get("username"),email:user.get("email"),picture:user.get("pic
 ture"),image:{duration:0,height:80,url:user.get("picture"),width:80}},verb:"post",content:options.content,type:"groups/"+this._path+"/activities"}};var entity=new Usergrid.Entity(options);entity.save(function(err){doCallback(callback,[err,entity])})},Usergrid.Counter=function(options,callback){var self=this;this._client=options.client,this._data=options.data||{},this._data.category=options.category||"UNKNOWN",this._data.timestamp=options.timestamp||0,this._data.type="events",this._data.counters=options.counters||{},doCallback(callback,[!1,self],self)};var COUNTER_RESOLUTIONS=["all","minute","five_minutes","half_hour","hour","six_day","day","week","month"];Usergrid.Counter.prototype=new Usergrid.Entity,Usergrid.Counter.prototype.fetch=function(callback){this.getData({},callback)},Usergrid.Counter.prototype.increment=function(options,callback){var self=this,name=options.name,value=options.value;return name?isNaN(value)?doCallback(callback,[!0,"'value' for increment, decrement must be 
 a number"],self):(self._data.counters[name]=parseInt(value)||1,self.save(callback)):doCallback(callback,[!0,"'name' for increment, decrement must be a number"],self)},Usergrid.Counter.prototype.decrement=function(options,callback){var self=this,name=options.name,value=options.value;self.increment({name:name,value:-(parseInt(value)||1)},callback)},Usergrid.Counter.prototype.reset=function(options,callback){var self=this,name=options.name;self.increment({name:name,value:0},callback)},Usergrid.Counter.prototype.getData=function(options,callback){var start_time,end_time,start=options.start||0,end=options.end||Date.now(),resolution=(options.resolution||"all").toLowerCase(),counters=options.counters||Object.keys(this._data.counters),res=(resolution||"all").toLowerCase();if(-1===COUNTER_RESOLUTIONS.indexOf(res)&&(res="all"),start)switch(typeof start){case"undefined":start_time=0;break;case"number":start_time=start;break;case"string":start_time=isNaN(start)?Date.parse(start):parseInt(start)
 ;break;default:start_time=Date.parse(start.toString())}if(end)switch(typeof end){case"undefined":end_time=Date.now();break;case"number":end_time=end;break;case"string":end_time=isNaN(end)?Date.parse(end):parseInt(end);break;default:end_time=Date.parse(end.toString())}var self=this,params=Object.keys(counters).map(function(counter){return["counter",encodeURIComponent(counters[counter])].join("=")});params.push("resolution="+res),params.push("start_time="+String(start_time)),params.push("end_time="+String(end_time));var endpoint="counters?"+params.join("&");this._client.request({endpoint:endpoint},function(err,data){return data.counters&&data.counters.length&&data.counters.forEach(function(counter){self._data.counters[counter.name]=counter.value||counter.values}),doCallback(callback,[err,data],self)})},Usergrid.Folder=function(options,callback){var self=this;console.log("FOLDER OPTIONS",options),self._client=options.client,self._data=options.data||{},self._data.type="folders";var miss
 ingData=["name","owner","path"].some(function(required){return!(required in self._data)});return missingData?doCallback(callback,[!0,new UsergridError("Invalid asset data: 'name', 'owner', and 'path' are required properties.")],self):void self.save(function(err,data){err?doCallback(callback,[!0,new UsergridError(data)],self):(data&&data.entities&&data.entities.length&&self.set(data.entities[0]),doCallback(callback,[!1,self],self))})},Usergrid.Folder.prototype=new Usergrid.Entity,Usergrid.Folder.prototype.fetch=function(callback){var self=this;Usergrid.Entity.prototype.fetch.call(self,function(err,data){console.log("self",self.get()),console.log("data",data),err?doCallback(callback,[!0,new UsergridError(data)],self):self.getAssets(function(err,data){err?doCallback(callback,[!0,new UsergridError(data)],self):doCallback(callback,[null,self],self)})})},Usergrid.Folder.prototype.addAsset=function(options,callback){var self=this;if("asset"in options){var asset=null;switch(typeof options.a
 sset){case"object":asset=options.asset,asset instanceof Usergrid.Entity||(asset=new Usergrid.Asset(asset));break;case"string":isUUID(options.asset)&&(asset=new Usergrid.Asset({client:self._client,data:{uuid:options.asset,type:"assets"}}))}asset&&asset instanceof Usergrid.Entity&&asset.fetch(function(err,data){if(err)doCallback(callback,[err,new UsergridError(data)],self);else{var endpoint=["folders",self.get("uuid"),"assets",asset.get("uuid")].join("/"),options={method:"POST",endpoint:endpoint};self._client.request(options,callback)}})}else doCallback(callback,[!0,{error_description:"No asset specified"}],self)},Usergrid.Folder.prototype.removeAsset=function(options,callback){var self=this;if("asset"in options){var asset=null;switch(typeof options.asset){case"object":asset=options.asset;break;case"string":isUUID(options.asset)&&(asset=new Usergrid.Asset({client:self._client,data:{uuid:options.asset,type:"assets"}}))}if(asset&&null!==asset){var endpoint=["folders",self.get("uuid"),"a
 ssets",asset.get("uuid")].join("/");self._client.request({method:"DELETE",endpoint:endpoint},callback)}}else doCallback(callback,[!0,{error_description:"No asset specified"}],self)},Usergrid.Folder.prototype.getAssets=function(callback){return this.getConnections("assets",callback)},XMLHttpRequest.prototype.sendAsBinary||(XMLHttpRequest.prototype.sendAsBinary=function(sData){for(var nBytes=sData.length,ui8Data=new Uint8Array(nBytes),nIdx=0;nBytes>nIdx;nIdx++)ui8Data[nIdx]=255&sData.charCodeAt(nIdx);this.send(ui8Data)}),Usergrid.Asset=function(options,callback){var self=this;self._client=options.client,self._data=options.data||{},self._data.type="assets";var missingData=["name","owner","path"].some(function(required){return!(required in self._data)});return missingData?doCallback(callback,[!0,new UsergridError("Invalid asset data: 'name', 'owner', and 'path' are required properties.")],self):void self.save(function(err,data){err?doCallback(callback,[!0,new UsergridError(data)],self):
 (data&&data.entities&&data.entities.length&&self.set(data.entities[0]),doCallback(callback,[!1,self],self))})},Usergrid.Asset.prototype=new Usergrid.Entity,Usergrid.Asset.prototype.addToFolder=function(options,callback){var self=this;if("folder"in options&&isUUID(options.folder)){Usergrid.Folder({uuid:options.folder},function(err,folder){if(err)return callback.call(self,err,folder);var endpoint=["folders",folder.get("uuid"),"assets",self.get("uuid")].join("/"),options={method:"POST",endpoint:endpoint};this._client.request(options,callback)})}else doCallback(callback,[!0,new UsergridError("folder not specified")],self)},Usergrid.Asset.prototype.upload=function(data,callback){if(!(window.File&&window.FileReader&&window.FileList&&window.Blob))return doCallback(callback,[!0,new UsergridError("The File APIs are not fully supported by your browser.")],self);var self=this,endpoint=[this._client.URI,this._client.orgName,this._client.appName,"assets",self.get("uuid"),"data"].join("/"),xhr=ne
 w XMLHttpRequest;xhr.open("POST",endpoint,!0),xhr.onerror=function(){doCallback(callback,[!0,new UsergridError("The File APIs are not fully supported by your browser.")],self)},xhr.onload=function(){xhr.status>=300?doCallback(callback,[!0,new UsergridError(JSON.parse(xhr.responseText))],self):doCallback(callback,[null,self],self)};var fr=new FileReader;fr.onload=function(){var binary=fr.result;xhr.overrideMimeType("application/octet-stream"),setTimeout(function(){xhr.sendAsBinary(binary)},1e3)},fr.readAsBinaryString(data)},Usergrid.Asset.prototype.download=function(callback){var self=this,endpoint=[this._client.URI,this._client.orgName,this._client.appName,"assets",self.get("uuid"),"data"].join("/"),xhr=new XMLHttpRequest;xhr.open("GET",endpoint,!0),xhr.responseType="blob",xhr.onload=function(){var blob=xhr.response;doCallback(callback,[!1,blob],self)},xhr.onerror=function(err){callback(!0,err),doCallback(callback,[!0,new UsergridError(err)],self)},xhr.send()},function(global){funct
 ion UsergridError(message,name,timestamp,duration,exception){this.message=message,this.name=name,this.timestamp=timestamp||Date.now(),this.duration=duration||0,this.exception=exception}function UsergridHTTPResponseError(message,name,timestamp,duration,exception){this.message=message,this.name=name,this.timestamp=timestamp||Date.now(),this.duration=duration||0,this.exception=exception}function UsergridInvalidHTTPMethodError(message,name,timestamp,duration,exception){this.message=message,this.name=name,this.timestamp=timestamp||Date.now(),this.duration=duration||0,this.exception=exception}function UsergridInvalidURIError(message,name,timestamp,duration,exception){this.message=message,this.name=name,this.timestamp=timestamp||Date.now(),this.duration=duration||0,this.exception=exception}function UsergridKeystoreDatabaseUpgradeNeededError(message,name,timestamp,duration,exception){this.message=message,this.name=name,this.timestamp=timestamp||Date.now(),this.duration=duration||0,this.exce
 ption=exception}var short,name="UsergridError",_name=global[name],_short=short&&void 0!==short?global[short]:void 0;return UsergridError.prototype=new Error,UsergridError.prototype.constructor=UsergridError,UsergridError.fromResponse=function(response){return response&&"undefined"!=typeof response?new UsergridError(response.error_description,response.error,response.timestamp,response.duration,response.exception):new UsergridError},UsergridError.createSubClass=function(name){return name in global&&global[name]?global[name]:(global[name]=function(){},global[name].name=name,global[name].prototype=new UsergridError,global[name])},UsergridHTTPResponseError.prototype=new UsergridError,UsergridInvalidHTTPMethodError.prototype=new UsergridError,UsergridInvalidURIError.prototype=new UsergridError,UsergridKeystoreDatabaseUpgradeNeededError.prototype=new UsergridError,global.UsergridHTTPResponseError=UsergridHTTPResponseError,global.UsergridInvalidHTTPMethodError=UsergridInvalidHTTPMethodError
 ,global.UsergridInvalidURIError=UsergridInvalidURIError,global.UsergridKeystoreDatabaseUpgradeNeededError=UsergridKeystoreDatabaseUpgradeNeededError,global[name]=UsergridError,void 0!==short&&(global[short]=UsergridError),global[name].noConflict=function(){return _name&&(global[name]=_name),void 0!==short&&(global[short]=_short),UsergridError},global[name]}(this);
\ No newline at end of file
+/*! usergrid@0.11.0 2014-04-01 */
+function extend(subClass,superClass){var F=function(){};return F.prototype=superClass.prototype,subClass.prototype=new F,subClass.prototype.constructor=subClass,subClass.superclass=superClass.prototype,superClass.prototype.constructor==Object.prototype.constructor&&(superClass.prototype.constructor=superClass),subClass}function propCopy(from,to){for(var prop in from)from.hasOwnProperty(prop)&&(to[prop]="object"==typeof from[prop]&&"object"==typeof to[prop]?propCopy(from[prop],to[prop]):from[prop]);return to}function NOOP(){}function isValidUrl(url){if(!url)return!1;var doc,base,anchor,isValid=!1;try{doc=document.implementation.createHTMLDocument(""),base=doc.createElement("base"),base.href=base||window.lo,doc.head.appendChild(base),anchor=doc.createElement("a"),anchor.href=url,doc.body.appendChild(anchor),isValid=!(""===anchor.href)}catch(e){console.error(e)}finally{return doc.head.removeChild(base),doc.body.removeChild(anchor),base=null,anchor=null,doc=null,isValid}}function isUUID
 (uuid){return uuid?uuidValueRegex.test(uuid):!1}function encodeParams(params){var queryString;return params&&Object.keys(params)&&(queryString=[].slice.call(arguments).reduce(function(a,b){return a.concat(b instanceof Array?b:[b])},[]).filter(function(c){return"object"==typeof c}).reduce(function(p,c){return c instanceof Array?p.push(c):p=p.concat(Object.keys(c).map(function(key){return[key,c[key]]})),p},[]).reduce(function(p,c){return 2===c.length?p.push(c):p=p.concat(c),p},[]).reduce(function(p,c){return c[1]instanceof Array?c[1].forEach(function(v){p.push([c[0],v])}):p.push(c),p},[]).map(function(c){return c[1]=encodeURIComponent(c[1]),c.join("=")}).join("&")),queryString}function isFunction(f){return f&&null!==f&&"function"==typeof f}function doCallback(callback,params,context){var returnValue;return isFunction(callback)&&(params||(params=[]),context||(context=this),params.push(context),returnValue=callback.apply(context,params)),returnValue}function getSafeTime(prop){var time;s
 witch(typeof prop){case"undefined":time=Date.now();break;case"number":time=prop;break;case"string":time=isNaN(prop)?Date.parse(prop):parseInt(prop);break;default:time=Date.parse(prop.toString())}return time}var UsergridEventable=function(){throw Error("'UsergridEventable' is not intended to be invoked directly")};UsergridEventable.prototype={bind:function(event,fn){this._events=this._events||{},this._events[event]=this._events[event]||[],this._events[event].push(fn)},unbind:function(event,fn){this._events=this._events||{},event in this._events!=!1&&this._events[event].splice(this._events[event].indexOf(fn),1)},trigger:function(event){if(this._events=this._events||{},event in this._events!=!1)for(var i=0;i<this._events[event].length;i++)this._events[event][i].apply(this,Array.prototype.slice.call(arguments,1))}},UsergridEventable.mixin=function(destObject){for(var props=["bind","unbind","trigger"],i=0;i<props.length;i++)props[i]in destObject.prototype&&(console.warn("overwriting '"+p
 rops[i]+"' on '"+destObject.name+"'."),console.warn("the previous version can be found at '_"+props[i]+"' on '"+destObject.name+"'."),destObject.prototype["_"+props[i]]=destObject.prototype[props[i]]),destObject.prototype[props[i]]=UsergridEventable.prototype[props[i]]},function(){function Logger(name){this.logEnabled=!0,this.init(name,!0)}var name="Logger",global=this,overwrittenName=global[name];return Logger.METHODS=["log","error","warn","info","debug","assert","clear","count","dir","dirxml","exception","group","groupCollapsed","groupEnd","profile","profileEnd","table","time","timeEnd","trace"],Logger.prototype.init=function(name,logEnabled){this.name=name||"UNKNOWN",this.logEnabled=logEnabled||!0;var addMethod=function(method){this[method]=this.createLogMethod(method)}.bind(this);Logger.METHODS.forEach(addMethod)},Logger.prototype.createLogMethod=function(method){return Logger.prototype.log.bind(this,method)},Logger.prototype.prefix=function(method,args){var prepend="["+method.t
 oUpperCase()+"]["+name+"]:	";return-1!==["log","error","warn","info"].indexOf(method)&&("string"==typeof args[0]?args[0]=prepend+args[0]:args.unshift(prepend)),args},Logger.prototype.log=function(){var args=[].slice.call(arguments);method=args.shift(),-1===Logger.METHODS.indexOf(method)&&(method="log"),this.logEnabled&&console&&console[method]&&(args=this.prefix(method,args),console[method].apply(console,args))},Logger.prototype.setLogEnabled=function(logEnabled){this.logEnabled=logEnabled||!0},Logger.mixin=function(destObject){destObject.__logger=new Logger(destObject.name||"UNKNOWN");var addMethod=function(method){method in destObject.prototype&&(console.warn("overwriting '"+method+"' on '"+destObject.name+"'."),console.warn("the previous version can be found at '_"+method+"' on '"+destObject.name+"'."),destObject.prototype["_"+method]=destObject.prototype[method]),destObject.prototype[method]=destObject.__logger.createLogMethod(method)};Logger.METHODS.forEach(addMethod)},global[n
 ame]=Logger,global[name].noConflict=function(){return overwrittenName&&(global[name]=overwrittenName),Logger},global[name]}(),function(global){function Promise(){this.complete=!1,this.error=null,this.result=null,this.callbacks=[]}var name="Promise",overwrittenName=global[name];return Promise.prototype.then=function(callback,context){var f=function(){return callback.apply(context,arguments)};this.complete?f(this.error,this.result):this.callbacks.push(f)},Promise.prototype.done=function(error,result){if(this.complete=!0,this.error=error,this.result=result,this.callbacks){for(var i=0;i<this.callbacks.length;i++)this.callbacks[i](error,result);this.callbacks.length=0}},Promise.join=function(promises){function notifier(i){return function(error,result){completed+=1,errors[i]=error,results[i]=result,completed===total&&p.done(errors,results)}}for(var p=new Promise,total=promises.length,completed=0,errors=[],results=[],i=0;total>i;i++)promises[i]().then(notifier(i));return p},Promise.chain=f
 unction(promises,error,result){var p=new Promise;return null===promises||0===promises.length?p.done(error,result):promises[0](error,result).then(function(res,err){promises.splice(0,1),promises?Promise.chain(promises,res,err).then(function(r,e){p.done(r,e)}):p.done(res,err)}),p},global[name]=Promise,global[name].noConflict=function(){return overwrittenName&&(global[name]=overwrittenName),Promise},global[name]}(this),function(){function partial(){var args=Array.prototype.slice.call(arguments),fn=args.shift();return fn.bind(this,args)}function Ajax(){function encode(data){var result="";if("string"==typeof data)result=data;else{var e=encodeURIComponent;for(var i in data)data.hasOwnProperty(i)&&(result+="&"+e(i)+"="+e(data[i]))}return result}function request(m,u,d){var timeout,p=new Promise;return self.logger.time(m+" "+u),function(xhr){xhr.onreadystatechange=function(){4===this.readyState&&(self.logger.timeEnd(m+" "+u),clearTimeout(timeout),p.done(null,this))},xhr.onerror=function(respo
 nse){clearTimeout(timeout),p.done(response,null)},xhr.oncomplete=function(){clearTimeout(timeout),self.logger.timeEnd(m+" "+u),self.info("%s request to %s returned %s",m,u,this.status)},xhr.open(m,u),d&&("object"==typeof d&&(d=JSON.stringify(d)),xhr.setRequestHeader("Content-Type","application/json"),xhr.setRequestHeader("Accept","application/json")),timeout=setTimeout(function(){xhr.abort(),p.done("API Call timed out.",null)},3e4),xhr.send(encode(d))}(new XMLHttpRequest),p}this.logger=new global.Logger(name);var self=this;this.request=request,this.get=partial(request,"GET"),this.post=partial(request,"POST"),this.put=partial(request,"PUT"),this.delete=partial(request,"DELETE")}var exports,name="Ajax",global=this,overwrittenName=global[name];return global[name]=new Ajax,global[name].noConflict=function(){return overwrittenName&&(global[name]=overwrittenName),exports},global[name]}(),window.console=window.console||{},window.console.log=window.console.log||function(){};var uuidValueReg
 ex=/^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/;!function(global){function Usergrid(){this.logger=new Logger(name)}var name="Usergrid",overwrittenName=global[name],VALID_REQUEST_METHODS=["GET","POST","PUT","DELETE"];return Usergrid.isValidEndpoint=function(){return!0},Usergrid.Request=function(method,endpoint,query_params,data,callback){var p=new Promise;if(this.logger=new global.Logger("Usergrid.Request"),this.logger.time("process request "+method+" "+endpoint),this.endpoint=endpoint+"?"+encodeParams(query_params),this.method=method.toUpperCase(),this.data="object"==typeof data?JSON.stringify(data):data,-1===VALID_REQUEST_METHODS.indexOf(this.method))throw new UsergridInvalidHTTPMethodError("invalid request method '"+this.method+"'");if(!isValidUrl(this.endpoint))throw this.logger.error(endpoint,this.endpoint,/^https:\/\//.test(endpoint)),new UsergridInvalidURIError("The provided endpoint is not valid: "+this.endpoint);var request=function(){retur
 n Ajax.request(this.method,this.endpoint,this.data)}.bind(this),response=function(err,request){return new Usergrid.Response(err,request)}.bind(this),oncomplete=function(err,response){p.done(err,response),this.logger.info("REQUEST",err,response),doCallback(callback,[err,response]),this.logger.timeEnd("process request "+method+" "+endpoint)}.bind(this);return Promise.chain([request,response]).then(oncomplete),p},Usergrid.Response=function(err,response){var p=new Promise,data=null;try{data=JSON.parse(response.responseText)}catch(e){data={}}switch(Object.keys(data).forEach(function(key){Object.defineProperty(this,key,{value:data[key],enumerable:!0})}.bind(this)),Object.defineProperty(this,"logger",{enumerable:!1,configurable:!1,writable:!1,value:new global.Logger(name)}),Object.defineProperty(this,"success",{enumerable:!1,configurable:!1,writable:!0,value:!0}),Object.defineProperty(this,"err",{enumerable:!1,configurable:!1,writable:!0,value:err}),Object.defineProperty(this,"status",{enu
 merable:!1,configurable:!1,writable:!0,value:parseInt(response.status)}),Object.defineProperty(this,"statusGroup",{enumerable:!1,configurable:!1,writable:!0,value:this.status-this.status%100}),this.statusGroup){case 200:this.success=!0;break;case 400:case 500:case 300:case 100:default:this.success=!1}return this.success?p.done(null,this):p.done(UsergridError.fromResponse(data),this),p},Usergrid.Response.prototype.getEntities=function(){var entities;return this.success&&(entities=this.data?this.data.entities:this.entities),entities||[]},Usergrid.Response.prototype.getEntity=function(){var entities=this.getEntities();return entities[0]},Usergrid.VERSION=Usergrid.USERGRID_SDK_VERSION="0.11.0",global[name]=Usergrid,global[name].noConflict=function(){return overwrittenName&&(global[name]=overwrittenName),Usergrid},global[name]}(this),function(){var exports,name="Client",global=this,overwrittenName=global[name];return Usergrid.Client=function(options){this.URI=options.URI||"https://api.us
 ergrid.com",options.orgName&&this.set("orgName",options.orgName),options.appName&&this.set("appName",options.appName),options.qs&&this.setObject("default_qs",options.qs),this.buildCurl=options.buildCurl||!1,this.logging=options.logging||!1},Usergrid.Client.prototype.request=function(options,callback){var uri,method=options.method||"GET",endpoint=options.endpoint,body=options.body||{},qs=options.qs||{},mQuery=options.mQuery||!1,orgName=this.get("orgName"),appName=this.get("appName"),default_qs=this.getObject("default_qs");if(!mQuery&&!orgName&&!appName)return logoutCallback();uri=mQuery?this.URI+"/"+endpoint:this.URI+"/"+orgName+"/"+appName+"/"+endpoint,this.getToken()&&(qs.access_token=this.getToken()),default_qs&&(qs=propCopy(qs,default_qs));{var self=this;new Usergrid.Request(method,uri,qs,body,function(err,response){err?doCallback(callback,[err,response,self],self):doCallback(callback,[null,response,self],self)})}},Usergrid.Client.prototype.buildAssetURL=function(uuid){var self=t
 his,qs={},assetURL=this.URI+"/"+this.orgName+"/"+this.appName+"/assets/"+uuid+"/data";self.getToken()&&(qs.access_token=self.getToken());var encoded_params=encodeParams(qs);return encoded_params&&(assetURL+="?"+encoded_params),assetURL},Usergrid.Client.prototype.createGroup=function(options,callback){var group=new Usergrid.Group({path:options.path,client:this,data:options});group.save(function(err,response){doCallback(callback,[err,response,group],group)})},Usergrid.Client.prototype.createEntity=function(options,callback){var entity=new Usergrid.Entity({client:this,data:options});entity.save(function(err,response){doCallback(callback,[err,response,entity],entity)})},Usergrid.Client.prototype.getEntity=function(options,callback){var entity=new Usergrid.Entity({client:this,data:options});entity.fetch(function(err,response){doCallback(callback,[err,response,entity],entity)})},Usergrid.Client.prototype.restoreEntity=function(serializedObject){var data=JSON.parse(serializedObject),option
 s={client:this,data:data},entity=new Usergrid.Entity(options);return entity},Usergrid.Client.prototype.createCollection=function(options,callback){options.client=this;var collection=new Usergrid.Collection(options);collection.fetch(function(err,response,collection){doCallback(callback,[err,response,collection],this)})},Usergrid.Client.prototype.restoreCollection=function(serializedObject){var data=JSON.parse(serializedObject);data.client=this;var collection=new Usergrid.Collection(data);return collection},Usergrid.Client.prototype.getFeedForUser=function(username,callback){var options={method:"GET",endpoint:"users/"+username+"/feed"};this.request(options,function(err,data){err?doCallback(callback,[err]):doCallback(callback,[err,data,data.getEntities()])})},Usergrid.Client.prototype.createUserActivity=function(user,options,callback){options.type="users/"+user+"/activities",options={client:this,data:options};var entity=new Usergrid.Entity(options);entity.save(function(err,data){doCall
 back(callback,[err,data,entity])})},Usergrid.Client.prototype.createUserActivityWithEntity=function(user,content,callback){var username=user.get("username"),options={actor:{displayName:username,uuid:user.get("uuid"),username:username,email:user.get("email"),picture:user.get("picture"),image:{duration:0,height:80,url:user.get("picture"),width:80}},verb:"post",content:content};this.createUserActivity(username,options,callback)},Usergrid.Client.prototype.calcTimeDiff=function(){var seconds=0,time=this._end-this._start;try{seconds=(time/10/60).toFixed(2)}catch(e){return 0}return seconds},Usergrid.Client.prototype.setToken=function(token){this.set("token",token)},Usergrid.Client.prototype.getToken=function(){return this.get("token")},Usergrid.Client.prototype.setObject=function(key,value){value&&(value=JSON.stringify(value)),this.set(key,value)},Usergrid.Client.prototype.set=function(key,value){var keyStore="apigee_"+key;this[key]=value,"undefined"!=typeof Storage&&(value?localStorage.se
 tItem(keyStore,value):localStorage.removeItem(keyStore))},Usergrid.Client.prototype.getObject=function(key){return JSON.parse(this.get(key))},Usergrid.Client.prototype.get=function(key){var keyStore="apigee_"+key,value=null;return this[key]?value=this[key]:"undefined"!=typeof Storage&&(value=localStorage.getItem(keyStore)),value},Usergrid.Client.prototype.signup=function(username,password,email,name,callback){var options={type:"users",username:username,password:password,email:email,name:name};this.createEntity(options,callback)},Usergrid.Client.prototype.login=function(username,password,callback){var self=this,options={method:"POST",endpoint:"token",body:{username:username,password:password,grant_type:"password"}};self.request(options,function(err,data){var user={};if(err)self.logging&&console.log("error trying to log user in");else{var options={client:self,data:data.user};user=new Usergrid.Entity(options),self.setToken(data.access_token)}doCallback(callback,[err,data,user])})},User
 grid.Client.prototype.reAuthenticateLite=function(callback){var self=this,options={method:"GET",endpoint:"management/me",mQuery:!0};this.request(options,function(err,response){err&&self.logging?console.log("error trying to re-authenticate user"):self.setToken(response.data.access_token),doCallback(callback,[err])})},Usergrid.Client.prototype.reAuthenticate=function(email,callback){var self=this,options={method:"GET",endpoint:"management/users/"+email,mQuery:!0};this.request(options,function(err,response){var data,organizations={},applications={},user={};if(err&&self.logging)console.log("error trying to full authenticate user");else{data=response.data,self.setToken(data.token),self.set("email",data.email),localStorage.setItem("accessToken",data.token),localStorage.setItem("userUUID",data.uuid),localStorage.setItem("userEmail",data.email);var userData={username:data.username,email:data.email,name:data.name,uuid:data.uuid},options={client:self,data:userData};user=new Usergrid.Entity(op
 tions),organizations=data.organizations;var org="";try{var existingOrg=self.get("orgName");org=organizations[existingOrg]?organizations[existingOrg]:organizations[Object.keys(organizations)[0]],self.set("orgName",org.name)}catch(e){err=!0,self.logging&&console.log("error selecting org")}applications=self.parseApplicationsArray(org),self.selectFirstApp(applications),self.setObject("organizations",organizations),self.setObject("applications",applications)}doCallback(callback,[err,data,user,organizations,applications],self)})},Usergrid.Client.prototype.loginFacebook=function(facebookToken,callback){var self=this,options={method:"GET",endpoint:"auth/facebook",qs:{fb_access_token:facebookToken}};this.request(options,function(err,data){var user={};if(err&&self.logging)console.log("error trying to log user in");else{var options={client:self,data:data.user};user=new Usergrid.Entity(options),self.setToken(data.access_token)}doCallback(callback,[err,data,user],self)})},Usergrid.Client.prototy
 pe.getLoggedInUser=function(callback){if(this.getToken()){var self=this,options={method:"GET",endpoint:"users/me"};this.request(options,function(err,data){if(err)self.logging&&console.log("error trying to log user in"),doCallback(callback,[err,data,null],self);else{var options={client:self,data:data.entities[0]},user=new Usergrid.Entity(options);doCallback(callback,[null,data,user],self)}})}else callback(!0,null,null)},Usergrid.Client.prototype.isLoggedIn=function(){var token=this.getToken();return"undefined"!=typeof token&&null!==token},Usergrid.Client.prototype.logout=function(){this.setToken()},Usergrid.Client.prototype.destroyToken=function(username,token,revokeAll,callback){var options={client:self,method:"PUT"};options.endpoint=revokeAll===!0?"users/"+username+"/revoketokens":null===token?"users/"+username+"/revoketoken?token="+this.getToken():"users/"+username+"/revoketoken?token="+token,this.request(options,function(err,data){err?(self.logging&&console.log("error destroying 
 access token"),doCallback(callback,[err,data,null],self)):(console.log(revokeAll===!0?"all user tokens invalidated":"token invalidated"),doCallback(callback,[err,data,null],self))})},Usergrid.Client.prototype.logoutAndDestroyToken=function(username,token,revokeAll,callback){null===username?console.log("username required to revoke tokens"):(this.destroyToken(username,token,revokeAll,callback),(revokeAll===!0||token===this.getToken()||null===token)&&this.setToken(null))},Usergrid.Client.prototype.buildCurlCall=function(options){var curl=["curl"],method=(options.method||"GET").toUpperCase(),body=options.body,uri=options.uri;return curl.push("-X"),curl.push(["POST","PUT","DELETE"].indexOf(method)>=0?method:"GET"),curl.push(uri),"object"==typeof body&&Object.keys(body).length>0&&-1!==["POST","PUT"].indexOf(method)&&(curl.push("-d"),curl.push("'"+JSON.stringify(body)+"'")),curl=curl.join(" "),console.log(curl),curl},Usergrid.Client.prototype.getDisplayImage=function(email,picture,size){si
 ze=size||50;var image="https://apigee.com/usergrid/images/user_profile.png";try{picture?image=picture:email.length&&(image="https://secure.gravatar.com/avatar/"+MD5(email)+"?s="+size+encodeURI("&d=https://apigee.com/usergrid/images/user_profile.png"))}catch(e){}finally{return image}},global[name]=Usergrid.Client,global[name].noConflict=function(){return overwrittenName&&(global[name]=overwrittenName),exports},global[name]}();var ENTITY_SYSTEM_PROPERTIES=["metadata","created","modified","oldpassword","newpassword","type","activated","uuid"];Usergrid.Entity=function(options){this._data={},this._client=void 0,options&&(this.set(options.data||{}),this._client=options.client||{})},Usergrid.Entity.isEntity=function(obj){return obj&&obj instanceof Usergrid.Entity},Usergrid.Entity.isPersistedEntity=function(obj){return isEntity(obj)&&isUUID(obj.get("uuid"))},Usergrid.Entity.prototype.serialize=function(){return JSON.stringify(this._data)},Usergrid.Entity.prototype.get=function(key){var valu
 e;if(0===arguments.length?value=this._data:arguments.length>1&&(key=[].slice.call(arguments).reduce(function(p,c){return c instanceof Array?p=p.concat(c):p.push(c),p},[])),key instanceof Array){var self=this;value=key.map(function(k){return self.get(k)})}else"undefined"!=typeof key&&(value=this._data[key]);return value},Usergrid.Entity.prototype.set=function(key,value){if("object"==typeof key)for(var field in key)this._data[field]=key[field];else"string"==typeof key?null===value?delete this._data[key]:this._data[key]=value:this._data={}},Usergrid.Entity.prototype.getEndpoint=function(){var name,type=this.get("type"),nameProperties=["uuid","name"];if(void 0===type)throw new UsergridError("cannot fetch entity, no entity type specified","no_type_specified");return/^users?$/.test(type)&&nameProperties.unshift("username"),name=this.get(nameProperties).filter(function(x){return null!==x&&"undefined"!=typeof x}).shift(),name?[type,name].join("/"):type},Usergrid.Entity.prototype.save=functi
 on(callback){var self=this,type=this.get("type"),method="POST",entityId=this.get("uuid"),entityData=this.get(),options={method:method,endpoint:type};entityId&&(options.method="PUT",options.endpoint+="/"+entityId),options.body=Object.keys(entityData).filter(function(key){return-1===ENTITY_SYSTEM_PROPERTIES.indexOf(key)}).reduce(function(data,key){return data[key]=entityData[key],data},{}),self._client.request(options,function(err,response){var entity=response.getEntity();entity&&(self.set(entity),self.set("type",/^\//.test(response.path)?response.path.substring(1):response.path)),err&&self._client.logging&&console.log("could not save entity"),doCallback(callback,[err,response,self],self)})},Usergrid.Entity.prototype.changePassword=function(oldpassword,password,newpassword,callback){var self=this;if("function"==typeof oldpassword&&void 0===callback&&(callback=oldpassword,oldpassword=self.get("oldpassword"),password=self.get("password"),newpassword=self.get("newpassword")),self.set({pa
 ssword:null,oldpassword:null,newpassword:null}),!(/^users?$/.test(self.get("type"))&&oldpassword&&newpassword))throw new UsergridInvalidArgumentError("Invalid arguments passed to 'changePassword'");var options={method:"PUT",endpoint:"users/"+self.get("uuid")+"/password",body:{uuid:self.get("uuid"),username:self.get("username"),password:password,oldpassword:oldpassword,newpassword:newpassword}};self._client.request(options,function(err,response){err&&self._client.logging&&console.log("could not update user"),doCallback(callback,[err,response,self],self)})},Usergrid.Entity.prototype.fetch=function(callback){var endpoint,self=this;endpoint=this.getEndpoint();var options={method:"GET",endpoint:endpoint};this._client.request(options,function(err,response){var entity=response.getEntity();entity&&self.set(entity),doCallback(callback,[err,response,self],self)})},Usergrid.Entity.prototype.destroy=function(callback){var self=this,endpoint=this.getEndpoint(),options={method:"DELETE",endpoint:e
 ndpoint};this._client.request(options,function(err,response){err||self.set(null),doCallback(callback,[err,response,self],self)})},Usergrid.Entity.prototype.connect=function(connection,entity,callback){this.addOrRemoveConnection("POST",connection,entity,callback)},Usergrid.Entity.prototype.disconnect=function(connection,entity,callback){this.addOrRemoveConnection("DELETE",connection,entity,callback)},Usergrid.Entity.prototype.addOrRemoveConnection=function(method,connection,entity,callback){var self=this;if(-1==["POST","DELETE"].indexOf(method.toUpperCase()))throw new UsergridInvalidArgumentError("invalid method for connection call. must be 'POST' or 'DELETE'");var connecteeType=entity.get("type"),connectee=this.getEntityId(entity);if(!connectee)throw new UsergridInvalidArgumentError("connectee could not be identified");var connectorType=this.get("type"),connector=this.getEntityId(this);if(!connector)throw new UsergridInvalidArgumentError("connector could not be identified");var endp
 oint=[connectorType,connector,connection,connecteeType,connectee].join("/"),options={method:method,endpoint:endpoint};this._client.request(options,function(err,response){err&&self._client.logging&&console.log("There was an error with the connection call"),doCallback(callback,[err,response,self],self)})},Usergrid.Entity.prototype.getEntityId=function(entity){var id=!1;return isUUID(entity.get("uuid"))?id=entity.get("uuid"):"users"===this.get("type")?id=entity.get("username"):entity.get("name")&&(id=entity.get("name")),id},Usergrid.Entity.prototype.getConnections=function(connection,callback){var self=this,connectorType=this.get("type"),connector=this.getEntityId(this);if(connector){var endpoint=connectorType+"/"+connector+"/"+connection+"/",options={method:"GET",endpoint:endpoint};this._client.request(options,function(err,data){err&&self._client.logging&&console.log("entity could not be connected"),self[connection]={};for(var length=data&&data.entities?data.entities.length:0,i=0;leng
 th>i;i++)"user"===data.entities[i].type?self[connection][data.entities[i].username]=data.entities[i]:self[connection][data.entities[i].name]=data.entities[i];doCallback(callback,[err,data,data.entities],self)})}else if("function"==typeof callback){var error="Error in getConnections - no uuid specified.";self._client.logging&&console.log(error),doCallback(callback,[!0,error],self)}},Usergrid.Entity.prototype.getGroups=function(callback){var self=this,endpoint="users/"+this.get("uuid")+"/groups",options={method:"GET",endpoint:endpoint};this._client.request(options,function(err,data){err&&self._client.logging&&console.log("entity could not be connected"),self.groups=data.entities,doCallback(callback,[err,data,data.entities],self)})},Usergrid.Entity.prototype.getActivities=function(callback){var self=this,endpoint=this.get("type")+"/"+this.get("uuid")+"/activities",options={method:"GET",endpoint:endpoint};this._client.request(options,function(err,data){err&&self._client.logging&&console
 .log("entity could not be connected");for(var entity in data.entities)data.entities[entity].createdDate=new Date(data.entities[entity].created).toUTCString();self.activities=data.entities,doCallback(callback,[err,data,data.entities],self)})},Usergrid.Entity.prototype.getFollowing=function(callback){var self=this,endpoint="users/"+this.get("uuid")+"/following",options={method:"GET",endpoint:endpoint};this._client.request(options,function(err,data){err&&self._client.logging&&console.log("could not get user following");for(var entity in data.entities){data.entities[entity].createdDate=new Date(data.entities[entity].created).toUTCString();var image=self._client.getDisplayImage(data.entities[entity].email,data.entities[entity].picture);data.entities[entity]._portal_image_icon=image}self.following=data.entities,doCallback(callback,[err,data,data.entities],self)})},Usergrid.Entity.prototype.getFollowers=function(callback){var self=this,endpoint="users/"+this.get("uuid")+"/followers",option
 s={method:"GET",endpoint:endpoint};this._client.request(options,function(err,data){err&&self._client.logging&&console.log("could not get user followers");for(var entity in data.entities){data.entities[entity].createdDate=new Date(data.entities[entity].created).toUTCString();var image=self._client.getDisplayImage(data.entities[entity].email,data.entities[entity].picture);data.entities[entity]._portal_image_icon=image}self.followers=data.entities,doCallback(callback,[err,data,data.entities],self)})},Usergrid.Entity.prototype.getRoles=function(callback){var self=this,endpoint=this.get("type")+"/"+this.get("uuid")+"/roles",options={method:"GET",endpoint:endpoint};this._client.request(options,function(err,data){err&&self._client.logging&&console.log("could not get user roles"),self.roles=data.entities,doCallback(callback,[err,data,data.entities],self)})},Usergrid.Entity.prototype.getPermissions=function(callback){var self=this,endpoint=this.get("type")+"/"+this.get("uuid")+"/permissions"
 ,options={method:"GET",endpoint:endpoint};this._client.request(options,function(err,data){err&&self._client.logging&&console.log("could not get user permissions");var permissions=[];if(data.data){var perms=data.data,count=0;for(var i in perms){count++;var perm=perms[i],parts=perm.split(":"),ops_part="",path_part=parts[0];parts.length>1&&(ops_part=parts[0],path_part=parts[1]),ops_part=ops_part.replace("*","get,post,put,delete");var ops=ops_part.split(","),ops_object={};ops_object.get="no",ops_object.post="no",ops_object.put="no",ops_object.delete="no";for(var j in ops)ops_object[ops[j]]="yes";permissions.push({operations:ops_object,path:path_part,perm:perm})}}self.permissions=permissions,doCallback(callback,[err,data,data.entities],self)})},Usergrid.Collection=function(options){if(options&&(this._client=options.client,this._type=options.type,this.qs=options.qs||{},this._list=options.list||[],this._iterator=options.iterator||-1,this._previous=options.previous||[],this._next=options.ne
 xt||null,this._cursor=options.cursor||null,options.list))for(var count=options.list.length,i=0;count>i;i++){var entity=this._client.restoreEntity(options.list[i]);this._list[i]=entity}},Usergrid.isCollection=function(obj){return obj&&obj instanceof Usergrid.Collection},Usergrid.Collection.prototype.serialize=function(){var data={};data.type=this._type,data.qs=this.qs,data.iterator=this._iterator,data.previous=this._previous,data.next=this._next,data.cursor=this._cursor,this.resetEntityPointer();var i=0;for(data.list=[];this.hasNextEntity();){var entity=this.getNextEntity();data.list[i]=entity.serialize(),i++}return data=JSON.stringify(data)},Usergrid.Collection.prototype.fetch=function(callback){var self=this,qs=this.qs;this._cursor?qs.cursor=this._cursor:delete qs.cursor;var options={method:"GET",endpoint:this._type,qs:this.qs};this._client.request(options,function(err,response){err&&self._client.logging?console.log("error getting collection"):(self.saveCursor(response.cursor||null
 ),self.resetEntityPointer(),self._list=response.getEntities().filter(function(entity){return isUUID(entity.uuid)}).map(function(entity){var ent=new Usergrid.Entity({client:self._client});return ent.set(entity),ent.type=self._type,ent})),doCallback(callback,[err,response,self],self)})},Usergrid.Collection.prototype.addEntity=function(entityObject,callback){var self=this;entityObject.type=this._type,this._client.createEntity(entityObject,function(err,response,entity){err||self.addExistingEntity(entity),doCallback(callback,[err,response,self],self)})},Usergrid.Collection.prototype.addExistingEntity=function(entity){var count=this._list.length;this._list[count]=entity},Usergrid.Collection.prototype.destroyEntity=function(entity,callback){var self=this;entity.destroy(function(err,response){err?(self._client.logging&&console.log("could not destroy entity"),doCallback(callback,[err,response,self],self)):self.fetch(callback),self.removeEntity(entity)})},Usergrid.Collection.prototype.getEnti
 tiesByCriteria=function(criteria){return this._list.filter(criteria)},Usergrid.Collection.prototype.getEntityByCriteria=function(criteria){return this.getEntitiesByCriteria(criteria).shift()
+},Usergrid.Collection.prototype.removeEntity=function(entity){var removedEntity=this.getEntityByCriteria(function(item){return entity.uuid===item.get("uuid")});return delete this._list[this._list.indexOf(removedEntity)],removedEntity},Usergrid.Collection.prototype.getEntityByUUID=function(uuid,callback){var entity=this.getEntityByCriteria(function(item){return item.get("uuid")===uuid});if(entity)doCallback(callback,[null,entity,entity],this);else{var options={data:{type:this._type,uuid:uuid},client:this._client};entity=new Usergrid.Entity(options),entity.fetch(callback)}},Usergrid.Collection.prototype.getFirstEntity=function(){var count=this._list.length;return count>0?this._list[0]:null},Usergrid.Collection.prototype.getLastEntity=function(){var count=this._list.length;return count>0?this._list[count-1]:null},Usergrid.Collection.prototype.hasNextEntity=function(){var next=this._iterator+1,hasNextElement=next>=0&&next<this._list.length;return hasNextElement?!0:!1},Usergrid.Collectio
 n.prototype.getNextEntity=function(){this._iterator++;var hasNextElement=this._iterator>=0&&this._iterator<=this._list.length;return hasNextElement?this._list[this._iterator]:!1},Usergrid.Collection.prototype.hasPrevEntity=function(){var previous=this._iterator-1,hasPreviousElement=previous>=0&&previous<this._list.length;return hasPreviousElement?!0:!1},Usergrid.Collection.prototype.getPrevEntity=function(){this._iterator--;var hasPreviousElement=this._iterator>=0&&this._iterator<=this._list.length;return hasPreviousElement?this._list[this._iterator]:!1},Usergrid.Collection.prototype.resetEntityPointer=function(){this._iterator=-1},Usergrid.Collection.prototype.saveCursor=function(cursor){this._next!==cursor&&(this._next=cursor)},Usergrid.Collection.prototype.resetPaging=function(){this._previous=[],this._next=null,this._cursor=null},Usergrid.Collection.prototype.hasNextPage=function(){return this._next},Usergrid.Collection.prototype.getNextPage=function(callback){this.hasNextPage()
 &&(this._previous.push(this._cursor),this._cursor=this._next,this._list=[],this.fetch(callback))},Usergrid.Collection.prototype.hasPreviousPage=function(){return this._previous.length>0},Usergrid.Collection.prototype.getPreviousPage=function(callback){this.hasPreviousPage()&&(this._next=null,this._cursor=this._previous.pop(),this._list=[],this.fetch(callback))},Usergrid.Group=function(options){this._path=options.path,this._list=[],this._client=options.client,this._data=options.data||{},this._data.type="groups"},Usergrid.Group.prototype=new Usergrid.Entity,Usergrid.Group.prototype.fetch=function(callback){var self=this,groupEndpoint="groups/"+this._path,memberEndpoint="groups/"+this._path+"/users",groupOptions={method:"GET",endpoint:groupEndpoint},memberOptions={method:"GET",endpoint:memberEndpoint};this._client.request(groupOptions,function(err,response){if(err)self._client.logging&&console.log("error getting group"),doCallback(callback,[err,response],self);else{var entities=respons
 e.getEntities();if(entities&&entities.length){{entities.shift()}self._client.request(memberOptions,function(err,response){err&&self._client.logging?console.log("error getting group users"):self._list=response.getEntities().filter(function(entity){return isUUID(entity.uuid)}).map(function(entity){return new Usergrid.Entity({type:entity.type,client:self._client,uuid:entity.uuid,response:entity})}),doCallback(callback,[err,response,self],self)})}}})},Usergrid.Group.prototype.members=function(){return this._list},Usergrid.Group.prototype.add=function(options,callback){var self=this;options.user?(options={method:"POST",endpoint:"groups/"+this._path+"/users/"+options.user.get("username")},this._client.request(options,function(error,response){error?doCallback(callback,[error,response,self],self):self.fetch(callback)})):doCallback(callback,[new UsergridError("no user specified","no_user_specified"),null,this],this)},Usergrid.Group.prototype.remove=function(options,callback){var self=this;op
 tions.user?(options={method:"DELETE",endpoint:"groups/"+this._path+"/users/"+options.user.get("username")},this._client.request(options,function(error,response){error?doCallback(callback,[error,response,self],self):self.fetch(callback)})):doCallback(callback,[new UsergridError("no user specified","no_user_specified"),null,this],this)},Usergrid.Group.prototype.feed=function(callback){var self=this,options={method:"GET",endpoint:"groups/"+this._path+"/feed"};this._client.request(options,function(err,response){doCallback(callback,[err,response,self],self)})},Usergrid.Group.prototype.createGroupActivity=function(options,callback){var self=this,user=options.user,entity=new Usergrid.Entity({client:this._client,data:{actor:{displayName:user.get("username"),uuid:user.get("uuid"),username:user.get("username"),email:user.get("email"),picture:user.get("picture"),image:{duration:0,height:80,url:user.get("picture"),width:80}},verb:"post",content:options.content,type:"groups/"+this._path+"/activi
 ties"}});entity.save(function(err,response){doCallback(callback,[err,response,self])})},Usergrid.Counter=function(options,callback){this._client=options.client,this._data=options.data||{},this._data.category=options.category||"UNKNOWN",this._data.timestamp=options.timestamp||0,this._data.type="events",this._data.counters=options.counters||{},doCallback(callback,[!1,this],this)};var COUNTER_RESOLUTIONS=["all","minute","five_minutes","half_hour","hour","six_day","day","week","month"];Usergrid.Counter.prototype=new Usergrid.Entity,Usergrid.Counter.prototype.fetch=function(callback){this.getData({},callback)},Usergrid.Counter.prototype.increment=function(options,callback){var self=this,name=options.name,value=options.value;return name?isNaN(value)?doCallback(callback,[new UsergridInvalidArgumentError("'value' for increment, decrement must be a number"),null,self],self):(self._data.counters[name]=parseInt(value)||1,self.save(callback)):doCallback(callback,[new UsergridInvalidArgumentErro
 r("'name' for increment, decrement must be a number"),null,self],self)},Usergrid.Counter.prototype.decrement=function(options,callback){var self=this,name=options.name,value=options.value;self.increment({name:name,value:-(parseInt(value)||1)},callback)},Usergrid.Counter.prototype.reset=function(options,callback){var self=this,name=options.name;self.increment({name:name,value:0},callback)},Usergrid.Counter.prototype.getData=function(options,callback){var start_time,end_time,start=options.start||0,end=options.end||Date.now(),resolution=(options.resolution||"all").toLowerCase(),counters=options.counters||Object.keys(this._data.counters),res=(resolution||"all").toLowerCase();-1===COUNTER_RESOLUTIONS.indexOf(res)&&(res="all"),start_time=getSafeTime(start),end_time=getSafeTime(end);var self=this,params=Object.keys(counters).map(function(counter){return["counter",encodeURIComponent(counters[counter])].join("=")});params.push("resolution="+res),params.push("start_time="+String(start_time)),
 params.push("end_time="+String(end_time));var endpoint="counters?"+params.join("&");this._client.request({endpoint:endpoint},function(err,data){return data.counters&&data.counters.length&&data.counters.forEach(function(counter){self._data.counters[counter.name]=counter.value||counter.values}),doCallback(callback,[err,data,self],self)})},Usergrid.Folder=function(options,callback){var self=this;console.log("FOLDER OPTIONS",options),self._client=options.client,self._data=options.data||{},self._data.type="folders";var missingData=["name","owner","path"].some(function(required){return!(required in self._data)});return missingData?doCallback(callback,[new UsergridInvalidArgumentError("Invalid asset data: 'name', 'owner', and 'path' are required properties."),null,self],self):void self.save(function(err,response){err?doCallback(callback,[new UsergridError(response),response,self],self):(response&&response.entities&&response.entities.length&&self.set(response.entities[0]),doCallback(callbac
 k,[null,response,self],self))})},Usergrid.Folder.prototype=new Usergrid.Entity,Usergrid.Folder.prototype.fetch=function(callback){var self=this;Usergrid.Entity.prototype.fetch.call(self,function(err,data){console.log("self",self.get()),console.log("data",data),err?doCallback(callback,[null,data,self],self):self.getAssets(function(err,response){err?doCallback(callback,[new UsergridError(response),resonse,self],self):doCallback(callback,[null,self],self)})})},Usergrid.Folder.prototype.addAsset=function(options,callback){var self=this;if("asset"in options){

<TRUNCATED>

[11/12] git commit: Merge branch 'master' of https://github.com/usergrid/usergrid into DPS-116

Posted by sn...@apache.org.
Merge branch 'master' of https://github.com/usergrid/usergrid into DPS-116


Project: http://git-wip-us.apache.org/repos/asf/incubator-usergrid/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-usergrid/commit/e576e0a3
Tree: http://git-wip-us.apache.org/repos/asf/incubator-usergrid/tree/e576e0a3
Diff: http://git-wip-us.apache.org/repos/asf/incubator-usergrid/diff/e576e0a3

Branch: refs/heads/master
Commit: e576e0a304999fe9f26c2ab9c3ab4bce8eec326a
Parents: 39f0ebe 37e5c23
Author: ryan bridges <rb...@apigee.com>
Authored: Wed Apr 2 10:08:35 2014 -0400
Committer: ryan bridges <rb...@apigee.com>
Committed: Wed Apr 2 10:08:35 2014 -0400

----------------------------------------------------------------------
 .gitignore                                      |     3 +-
 README.md                                       |    64 +-
 bower.json                                      |    39 +
 portal/Gruntfile.js                             |   212 +-
 portal/README.md                                |    88 +-
 portal/archive/index.html                       |    21 +
 portal/archive/js/app/console.js                |     4 +
 portal/bower.json                               |    27 +-
 portal/config.js                                |    42 +-
 portal/css/dash.min.css                         |     2 +-
 portal/css/main.css                             |   267 +-
 .../usergrid-portal/archive/coming_soon.html    |    31 +
 .../ui-bg_diagonals-thick_90_eeeeee_40x40.png   |   Bin 0 -> 251 bytes
 .../images/ui-bg_flat_100_deedf7_40x100.png     |   Bin 0 -> 182 bytes
 .../images/ui-bg_flat_100_e4f1fb_40x100.png     |   Bin 0 -> 213 bytes
 .../images/ui-bg_flat_100_f2f5f7_40x100.png     |   Bin 0 -> 212 bytes
 .../images/ui-bg_flat_15_cd0a0a_40x100.png      |   Bin 0 -> 181 bytes
 .../images/ui-bg_flat_50_3baae3_40x100.png      |   Bin 0 -> 182 bytes
 .../images/ui-bg_flat_80_d7ebf9_40x100.png      |   Bin 0 -> 183 bytes
 .../ui-bg_highlight-hard_70_000000_1x100.png    |   Bin 0 -> 118 bytes
 .../ui-bg_highlight-soft_25_ffef8f_1x100.png    |   Bin 0 -> 153 bytes
 .../images/ui-icons_000000_256x240.png          |   Bin 0 -> 4369 bytes
 .../images/ui-icons_2694e8_256x240.png          |   Bin 0 -> 4369 bytes
 .../images/ui-icons_2e83ff_256x240.png          |   Bin 0 -> 4369 bytes
 .../images/ui-icons_3d80b3_256x240.png          |   Bin 0 -> 4369 bytes
 .../images/ui-icons_72a7cf_256x240.png          |   Bin 0 -> 4369 bytes
 .../images/ui-icons_ffffff_256x240.png          |   Bin 0 -> 4369 bytes
 .../css/custom-theme/jquery-ui-1.8.9.custom.css |   573 +
 .../archive/css/jquery-ui-timepicker.css        |    53 +
 .../archive/css/jquery.ui.statusbar.css         |    25 +
 .../usergrid-portal/archive/css/prettify.css    |    52 +
 .../archive/css/usergrid-stripped.css           |  5199 +++
 .../usergrid-portal/archive/css/usergrid.css    |  5203 +++
 .../dist/usergrid-portal/archive/dash/README.md |     3 +
 .../archive/dash/config/testacular-e2e.conf.js  |    22 +
 .../archive/dash/config/testacular.conf.js      |    20 +
 .../archive/dash/test/e2e/runner.html           |    10 +
 .../archive/dash/test/e2e/scenarios.js          |    45 +
 .../dash/test/lib/angular/angular-mocks.js      |  1764 +
 .../dash/test/lib/angular/angular-scenario.js   | 26195 +++++++++++++
 .../archive/dash/test/lib/angular/version.txt   |     1 +
 .../archive/dash/test/unit/controllersSpec.js   |    31 +
 .../archive/dash/test/unit/directivesSpec.js    |    19 +
 .../archive/dash/test/unit/filtersSpec.js       |    19 +
 .../archive/dash/test/unit/servicesSpec.js      |    14 +
 .../archive/images/APNS_cert_upload.png         |   Bin 0 -> 33956 bytes
 .../archive/images/APNS_certification.png       |   Bin 0 -> 16855 bytes
 .../archive/images/android-notification.png     |   Bin 0 -> 41629 bytes
 .../archive/images/android-sdk-download.png     |   Bin 0 -> 4848 bytes
 .../archive/images/api-activity.gif             |   Bin 0 -> 10819 bytes
 .../archive/images/apigee-logo.png              |   Bin 0 -> 3647 bytes
 .../archive/images/apigeetopbar.png             |   Bin 0 -> 4658 bytes
 .../archive/images/background_one_col.png       |   Bin 0 -> 3126 bytes
 .../archive/images/btn-copyCurl-up.png          |   Bin 0 -> 2762 bytes
 .../archive/images/clippy-bg.png                |   Bin 0 -> 561 bytes
 .../usergrid-portal/archive/images/close.gif    |   Bin 0 -> 718 bytes
 .../archive/images/dotnet-sdk-download.png      |   Bin 0 -> 7149 bytes
 .../archive/images/down_arrow.png               |   Bin 0 -> 1285 bytes
 .../usergrid-portal/archive/images/error.png    |   Bin 0 -> 2009 bytes
 .../archive/images/faviconApigee.ico            |   Bin 0 -> 1150 bytes
 .../images/glyphicons-halflings-white.png       |   Bin 0 -> 4352 bytes
 .../archive/images/glyphicons-halflings.png     |   Bin 0 -> 4352 bytes
 .../glyphicons_halflings_135_wrench-white2.pdn  |   Bin 0 -> 5400 bytes
 .../glyphicons_halflings_135_wrench-white2.png  |   Bin 0 -> 296 bytes
 .../images/glyphicons_halflings_135_wrench.png  |   Bin 0 -> 228 bytes
 .../glyphicons_halflings_135_wrench_white.png   |   Bin 0 -> 251 bytes
 .../glyphicons_halflings_wrench_white.png       |   Bin 0 -> 1016 bytes
 .../archive/images/google_api_key.png           |   Bin 0 -> 98118 bytes
 .../archive/images/green_dot.png                |   Bin 0 -> 3472 bytes
 .../usergrid-portal/archive/images/grid.png     |   Bin 0 -> 166 bytes
 .../usergrid-portal/archive/images/icons.png    |   Bin 0 -> 13132 bytes
 .../archive/images/ios-sdk-download.png         |   Bin 0 -> 4886 bytes
 .../archive/images/iphone_message.png           |   Bin 0 -> 90307 bytes
 .../archive/images/javascript-sdk-download.png  |   Bin 0 -> 4618 bytes
 .../archive/images/left_arrow.png               |   Bin 0 -> 1257 bytes
 .../archive/images/logo-white.png               |   Bin 0 -> 2014 bytes
 .../archive/images/menuActiveTriangle.png       |   Bin 0 -> 315 bytes
 .../archive/images/nodejs-sdk-download.png      |   Bin 0 -> 5273 bytes
 .../usergrid-portal/archive/images/notice.png   |   Bin 0 -> 2112 bytes
 .../archive/images/orange-arrow.png             |   Bin 0 -> 242 bytes
 .../archive/images/push_notifications_icon.png  |   Bin 0 -> 338 bytes
 .../usergrid-portal/archive/images/red_dot.png  |   Bin 0 -> 3482 bytes
 .../archive/images/right_arrow.png              |   Bin 0 -> 1251 bytes
 .../archive/images/ruby-sdk-download.png        |   Bin 0 -> 6343 bytes
 .../usergrid-portal/archive/images/step_1.png   |   Bin 0 -> 1953 bytes
 .../usergrid-portal/archive/images/step_2.png   |   Bin 0 -> 2117 bytes
 .../usergrid-portal/archive/images/step_3.png   |   Bin 0 -> 2162 bytes
 .../usergrid-portal/archive/images/success.png  |   Bin 0 -> 1863 bytes
 .../archive/images/swish_arrow.png              |   Bin 0 -> 220 bytes
 .../archive/images/topbackground.png            |   Bin 0 -> 2890 bytes
 .../usergrid-portal/archive/images/up_arrow.png |   Bin 0 -> 1292 bytes
 .../archive/images/user-photo.png               |   Bin 0 -> 3849 bytes
 .../archive/images/user_profile.png             |   Bin 0 -> 3775 bytes
 .../archive/images/usergrid_200.png             |   Bin 0 -> 6397 bytes
 .../archive/images/usergrid_400.png             |   Bin 0 -> 8746 bytes
 .../usergrid-portal/archive/images/warning.png  |   Bin 0 -> 1179 bytes
 .../archive/images/yellow_dot.png               |   Bin 0 -> 3475 bytes
 .../archive/index-stripped2.html                |  1795 +
 portal/dist/usergrid-portal/archive/index.html  |  1931 +
 .../dist/usergrid-portal/archive/js/app/app.js  |   131 +
 .../usergrid-portal/archive/js/app/console.js   |  5397 +++
 .../usergrid-portal/archive/js/app/helpers.js   |   241 +
 .../archive/js/app/navigation.js                |   251 +
 .../usergrid-portal/archive/js/app/pages.js     |   161 +
 .../usergrid-portal/archive/js/app/params.js    |    30 +
 .../archive/js/app/quickLogin.js                |    30 +
 .../usergrid-portal/archive/js/app/session.js   |   176 +
 .../dist/usergrid-portal/archive/js/app/sso.js  |   135 +
 .../usergrid-portal/archive/js/app/status.js    |    37 +
 .../archive/js/app/ui/collections.entity.js     |   320 +
 .../archive/js/app/ui/collections.user.js       |   120 +
 .../usergrid-portal/archive/js/app/ui/ui.js     |   415 +
 .../archive/js/app/usergrid.appSDK.js           |  2097 ++
 .../archive/js/app/usergrid.appSDK.orig.js      |  2070 ++
 .../usergrid-portal/archive/js/lib/MD5.min.js   |     1 +
 .../usergrid-portal/archive/js/lib/backbone.js  |  1431 +
 .../archive/js/lib/bootstrap.min.js             |     7 +
 .../usergrid-portal/archive/js/lib/date.min.js  |     2 +
 .../archive/js/lib/jquery-1.7.2.min.js          |     4 +
 .../archive/js/lib/jquery-ui-1.8.18.min.js      |    15 +
 .../archive/js/lib/jquery.dataset.min.js        |     1 +
 .../archive/js/lib/jquery.dform-0.1.3.min.js    |    16 +
 .../archive/js/lib/jquery.jsonp-2.3.1.min.js    |     3 +
 .../archive/js/lib/jquery.tmpl.min.js           |    10 +
 .../archive/js/lib/jquery.ui.statusbar.min.js   |     1 +
 .../archive/js/lib/jquery.ui.timepicker.min.js  |     1 +
 .../usergrid-portal/archive/js/lib/prettify.js  |  1477 +
 .../archive/js/lib/underscore-min.js            |     5 +
 .../archive/js/spec/client-tests.js             |   159 +
 .../usergrid-portal/archive/js/spec/index.html  |    20 +
 .../archive/js/spec/qunit-git.css               |   238 +
 .../archive/js/spec/qunit-git.js                |  1865 +
 .../archive/js/unit-tests/appSDK-tests.js       |   255 +
 .../archive/js/unit-tests/ie-jquery-tests.js    |   191 +
 .../archive/js/unit-tests/qunit.css             |   231 +
 .../archive/js/unit-tests/qunit.js              |  1934 +
 .../dist/usergrid-portal/archive/loading.html   |     9 +
 .../dist/usergrid-portal/archive/max/index.html |     0
 .../usergrid-portal/archive/planned_outage.html |    48 +
 .../usergrid-portal/archive/push/index.html     |    34 +
 .../usergrid-portal/archive/service_down.html   |    48 +
 .../apigee.ui.activities.table_rows.html        |    14 +
 .../templates/apigee.ui.admins.table_rows.html  |     8 +
 .../apigee.ui.applications.table_rows.html      |     4 +
 .../apigee.ui.collection.table_rows.html        |    67 +
 .../apigee.ui.collections.query.indexes.html    |     5 +
 .../apigee.ui.collections.table_rows.html       |     9 +
 .../apigee.ui.collections.user.header.html      |    21 +
 .../templates/apigee.ui.curl.detail.html        |    11 +
 .../templates/apigee.ui.feed.table_rows.html    |    15 +
 .../templates/apigee.ui.groups.table_rows.html  |    14 +
 .../apigee.ui.panels.group.activities.html      |    28 +
 .../apigee.ui.panels.group.details.html         |    97 +
 .../apigee.ui.panels.group.memberships.html     |    40 +
 .../apigee.ui.panels.group.permissions.html     |    99 +
 ...pigee.ui.panels.notifications.configure.html |    14 +
 .../apigee.ui.panels.role.permissions.html      |    58 +
 .../templates/apigee.ui.panels.role.users.html  |    38 +
 .../apigee.ui.panels.user.activities.html       |    40 +
 .../templates/apigee.ui.panels.user.graph.html  |    80 +
 .../apigee.ui.panels.user.memberships.html      |    40 +
 .../apigee.ui.panels.user.permissions.html      |   105 +
 .../apigee.ui.panels.user.profile.html          |   113 +
 .../apigee.ui.role.groups.table_rows.html       |    44 +
 .../templates/apigee.ui.roles.table_rows.html   |    15 +
 .../templates/apigee.ui.users.table_rows.html   |    18 +
 .../archive/templates/test/modalForm2.html      |    32 +
 .../archive/test/autocomplete.html              |    25 +
 .../usergrid-portal/archive/test/modalForm.html |    32 +
 .../bower_components/angular-intro.js/LICENSE   |    20 +
 .../angular-intro.js/angular-intro.js           |    60 +
 .../angular-intro.js/bower.json                 |    20 +
 .../angular-intro.js/build/angular-intro.min.js |     1 +
 .../angular-intro.js/example/app.js             |    51 +
 .../angular-intro.js/lib/app.js                 |    49 +
 .../angular-intro.js/lib/intro.min.js           |    20 +
 .../angular-intro.js/lib/introjs.css            |   216 +
 .../bower_components/angular/README.md          |    48 +
 .../bower_components/angular/angular-csp.css    |    18 +
 .../bower_components/angular/angular.js         | 21734 +++++++++++
 .../bower_components/angular/angular.min.js     |   211 +
 .../angular/angular.min.js.gzip                 |   Bin 0 -> 38778 bytes
 .../bower_components/angular/angular.min.js.map |     8 +
 .../bower_components/angular/bower.json         |     7 +
 .../bower_components/angularitics/Gruntfile.js  |    62 +
 .../bower_components/angularitics/LICENSE       |    22 +
 .../bower_components/angularitics/README.md     |   115 +
 .../bower_components/angularitics/bower.json    |    12 +
 .../dist/angulartics-chartbeat.min.js           |     7 +
 .../dist/angulartics-ga-cordova.min.js          |     6 +
 .../angularitics/dist/angulartics-ga.min.js     |     7 +
 .../dist/angulartics-google-analytics.min.js    |     7 +
 .../dist/angulartics-kissmetrics.min.js         |     6 +
 .../dist/angulartics-mixpanel.min.js            |     7 +
 .../angularitics/dist/angulartics-scroll.min.js |    14 +
 .../dist/angulartics-segmentio.min.js           |     6 +
 .../angularitics/dist/angulartics.min.js        |     6 +
 .../bower_components/angularitics/karma.conf.js |    22 +
 .../bower_components/angularitics/package.json  |    43 +
 .../angularitics/samples/chartbeat.html         |    79 +
 .../angularitics/samples/google-analytics.html  |    68 +
 .../angularitics/samples/kissmetrics.html       |    75 +
 .../angularitics/samples/mixpanel.html          |    65 +
 .../angularitics/samples/partials/a.tpl.html    |     1 +
 .../angularitics/samples/partials/b.tpl.html    |     1 +
 .../angularitics/samples/partials/c.tpl.html    |     1 +
 .../angularitics/samples/partials/root.tpl.html |     1 +
 .../angularitics/samples/scroll.html            |    82 +
 .../angularitics/samples/segmentio.html         |    65 +
 .../angularitics/src/angulartics-chartbeat.js   |    29 +
 .../angularitics/src/angulartics-ga-cordova.js  |    91 +
 .../angularitics/src/angulartics-ga.js          |    32 +
 .../angularitics/src/angulartics-kissmetrics.js |    29 +
 .../angularitics/src/angulartics-mixpanel.js    |    29 +
 .../angularitics/src/angulartics-scroll.js      |    47 +
 .../angularitics/src/angulartics-segmentio.js   |    24 +
 .../angularitics/src/angulartics.js             |   132 +
 .../angularitics/test/angularticsSpec.js        |    38 +
 .../bower_components/apigee-sdk/apigee.js       |  3260 ++
 .../bower_components/apigee-sdk/apigee.min.js   |     3 +
 .../bower_components/apigee-sdk/bower.json      |    13 +
 .../samples/collections/css/apigee.min.css      |   213 +
 .../collections/css/jquery.mobile.icons.min.css |     3 +
 .../samples/collections/css/theme.min.css       |   213 +
 .../apigee-sdk/samples/collections/js/index.js  |   360 +
 .../entities/css/jquery.mobile.icons.min.css    |     3 +
 .../samples/entities/css/theme.min.css          |   213 +
 .../apigee-sdk/samples/entities/js/index.js     |   228 +
 .../geolocation/css/jquery.mobile.icons.min.css |     3 +
 .../samples/geolocation/css/theme.min.css       |   213 +
 .../apigee-sdk/samples/geolocation/js/index.js  |   133 +
 .../apigee-sdk/samples/messagee/app.js          |   634 +
 .../samples/messagee/usergrid.validation.js     |   249 +
 .../samples/push/android/AndroidManifest.xml    |    79 +
 .../samples/push/android/ant.properties         |    17 +
 .../push/android/assets/www/PushNotification.js |    65 +
 .../push/android/assets/www/cordova-2.7.0.js    |  6836 ++++
 .../push/android/assets/www/css/index.css       |   115 +
 .../push/android/assets/www/img/cordova.png     |   Bin 0 -> 19932 bytes
 .../push/android/assets/www/img/logo.png        |   Bin 0 -> 21814 bytes
 .../samples/push/android/assets/www/js/index.js |   241 +
 .../samples/push/android/assets/www/main.js     |   165 +
 .../samples/push/android/assets/www/master.css  |   116 +
 .../screen/android/screen-hdpi-landscape.png    |   Bin 0 -> 218302 bytes
 .../res/screen/android/screen-hdpi-portrait.png |   Bin 0 -> 222148 bytes
 .../screen/android/screen-ldpi-landscape.png    |   Bin 0 -> 42616 bytes
 .../res/screen/android/screen-ldpi-portrait.png |   Bin 0 -> 42034 bytes
 .../screen/android/screen-mdpi-landscape.png    |   Bin 0 -> 92347 bytes
 .../res/screen/android/screen-mdpi-portrait.png |   Bin 0 -> 90555 bytes
 .../screen/android/screen-xhdpi-landscape.png   |   Bin 0 -> 489604 bytes
 .../screen/android/screen-xhdpi-portrait.png    |   Bin 0 -> 504508 bytes
 .../samples/push/android/assets/www/spec.html   |    68 +
 .../push/android/assets/www/spec/helper.js      |    33 +
 .../push/android/assets/www/spec/index.js       |    67 +
 .../www/spec/lib/jasmine-1.2.0/MIT.LICENSE      |    20 +
 .../www/spec/lib/jasmine-1.2.0/jasmine-html.js  |   616 +
 .../www/spec/lib/jasmine-1.2.0/jasmine.css      |    81 +
 .../www/spec/lib/jasmine-1.2.0/jasmine.js       |  2529 ++
 .../apigee-sdk/samples/push/android/build.xml   |    92 +
 .../samples/push/android/cordova/appinfo.jar    |   Bin 0 -> 1574 bytes
 .../samples/push/android/cordova/build          |    24 +
 .../samples/push/android/cordova/clean          |    24 +
 .../samples/push/android/cordova/cordova        |   159 +
 .../apigee-sdk/samples/push/android/cordova/log |    24 +
 .../samples/push/android/cordova/release        |    24 +
 .../apigee-sdk/samples/push/android/cordova/run |    24 +
 .../push/android/libs/android-support-v13.jar   |   Bin 0 -> 402581 bytes
 .../samples/push/android/libs/cordova-2.7.0.jar |   Bin 0 -> 256941 bytes
 .../samples/push/android/libs/gcm.jar           |   Bin 0 -> 13662 bytes
 .../samples/push/android/proguard-project.txt   |    20 +
 .../samples/push/android/project.properties     |    14 +
 .../android/res/drawable-hdpi/ic_launcher.png   |   Bin 0 -> 9397 bytes
 .../push/android/res/drawable-hdpi/icon.png     |   Bin 0 -> 6080 bytes
 .../android/res/drawable-ldpi/ic_launcher.png   |   Bin 0 -> 2729 bytes
 .../push/android/res/drawable-ldpi/icon.png     |   Bin 0 -> 3096 bytes
 .../android/res/drawable-mdpi/ic_launcher.png   |   Bin 0 -> 5237 bytes
 .../push/android/res/drawable-mdpi/icon.png     |   Bin 0 -> 4090 bytes
 .../android/res/drawable-xhdpi/ic_launcher.png  |   Bin 0 -> 14383 bytes
 .../push/android/res/drawable-xhdpi/icon.png    |   Bin 0 -> 7685 bytes
 .../samples/push/android/res/drawable/icon.png  |   Bin 0 -> 7685 bytes
 .../samples/push/android/res/layout/main.xml    |    13 +
 .../samples/push/android/res/values/strings.xml |     4 +
 .../samples/push/android/res/xml/config.xml     |    62 +
 .../plugin/gcm/CordovaGCMBroadcastReceiver.java |    19 +
 .../src/com/plugin/gcm/GCMIntentService.java    |   163 +
 .../src/com/plugin/gcm/PushHandlerActivity.java |    66 +
 .../android/src/com/plugin/gcm/PushPlugin.java  |   216 +
 .../src/me/mdob/android/androidpush.java        |    36 +
 .../samples/push/ios/CordovaLib/Classes/CDV.h   |    57 +
 .../ios/CordovaLib/Classes/CDVAccelerometer.h   |    39 +
 .../ios/CordovaLib/Classes/CDVAccelerometer.m   |   128 +
 .../ios/CordovaLib/Classes/CDVAvailability.h    |    87 +
 .../push/ios/CordovaLib/Classes/CDVBattery.h    |    40 +
 .../push/ios/CordovaLib/Classes/CDVBattery.m    |   152 +
 .../push/ios/CordovaLib/Classes/CDVCamera.h     |    92 +
 .../push/ios/CordovaLib/Classes/CDVCamera.m     |   570 +
 .../push/ios/CordovaLib/Classes/CDVCapture.h    |   118 +
 .../push/ios/CordovaLib/Classes/CDVCapture.m    |   847 +
 .../ios/CordovaLib/Classes/CDVCommandDelegate.h |    54 +
 .../CordovaLib/Classes/CDVCommandDelegateImpl.h |    33 +
 .../CordovaLib/Classes/CDVCommandDelegateImpl.m |   145 +
 .../ios/CordovaLib/Classes/CDVCommandQueue.h    |    40 +
 .../ios/CordovaLib/Classes/CDVCommandQueue.m    |   169 +
 .../ios/CordovaLib/Classes/CDVConfigParser.h    |    28 +
 .../ios/CordovaLib/Classes/CDVConfigParser.m    |    70 +
 .../push/ios/CordovaLib/Classes/CDVConnection.h |    34 +
 .../push/ios/CordovaLib/Classes/CDVConnection.m |   132 +
 .../push/ios/CordovaLib/Classes/CDVContact.h    |   136 +
 .../push/ios/CordovaLib/Classes/CDVContact.m    |  1752 +
 .../push/ios/CordovaLib/Classes/CDVContacts.h   |   151 +
 .../push/ios/CordovaLib/Classes/CDVContacts.m   |   593 +
 .../push/ios/CordovaLib/Classes/CDVDebug.h      |    25 +
 .../ios/CordovaLib/Classes/CDVDebugConsole.h    |    28 +
 .../ios/CordovaLib/Classes/CDVDebugConsole.m    |    37 +
 .../push/ios/CordovaLib/Classes/CDVDevice.h     |    30 +
 .../push/ios/CordovaLib/Classes/CDVDevice.m     |    90 +
 .../push/ios/CordovaLib/Classes/CDVEcho.h       |    23 +
 .../push/ios/CordovaLib/Classes/CDVEcho.m       |    61 +
 .../push/ios/CordovaLib/Classes/CDVExif.h       |    43 +
 .../push/ios/CordovaLib/Classes/CDVFile.h       |   106 +
 .../push/ios/CordovaLib/Classes/CDVFile.m       |  1409 +
 .../ios/CordovaLib/Classes/CDVFileTransfer.h    |    74 +
 .../ios/CordovaLib/Classes/CDVFileTransfer.m    |   625 +
 .../ios/CordovaLib/Classes/CDVGlobalization.h   |   150 +
 .../ios/CordovaLib/Classes/CDVGlobalization.m   |   790 +
 .../ios/CordovaLib/Classes/CDVInAppBrowser.h    |    88 +
 .../ios/CordovaLib/Classes/CDVInAppBrowser.m    |   581 +
 .../CordovaLib/Classes/CDVInvokedUrlCommand.h   |    57 +
 .../CordovaLib/Classes/CDVInvokedUrlCommand.m   |   140 +
 .../push/ios/CordovaLib/Classes/CDVJSON.h       |    30 +
 .../push/ios/CordovaLib/Classes/CDVJSON.m       |    77 +
 .../CordovaLib/Classes/CDVJpegHeaderWriter.h    |    62 +
 .../CordovaLib/Classes/CDVJpegHeaderWriter.m    |   522 +
 .../ios/CordovaLib/Classes/CDVLocalStorage.h    |    50 +
 .../ios/CordovaLib/Classes/CDVLocalStorage.m    |   485 +
 .../push/ios/CordovaLib/Classes/CDVLocation.h   |   104 +
 .../push/ios/CordovaLib/Classes/CDVLocation.m   |   623 +
 .../push/ios/CordovaLib/Classes/CDVLogger.h     |    26 +
 .../push/ios/CordovaLib/Classes/CDVLogger.m     |    38 +
 .../ios/CordovaLib/Classes/CDVNotification.h    |    37 +
 .../ios/CordovaLib/Classes/CDVNotification.m    |   126 +
 .../push/ios/CordovaLib/Classes/CDVPlugin.h     |    64 +
 .../push/ios/CordovaLib/Classes/CDVPlugin.m     |   152 +
 .../ios/CordovaLib/Classes/CDVPluginResult.h    |    68 +
 .../ios/CordovaLib/Classes/CDVPluginResult.m    |   224 +
 .../ios/CordovaLib/Classes/CDVReachability.h    |    85 +
 .../ios/CordovaLib/Classes/CDVReachability.m    |   260 +
 .../Classes/CDVScreenOrientationDelegate.h      |    28 +
 .../push/ios/CordovaLib/Classes/CDVSound.h      |   116 +
 .../push/ios/CordovaLib/Classes/CDVSound.m      |   699 +
 .../ios/CordovaLib/Classes/CDVSplashScreen.h    |    33 +
 .../ios/CordovaLib/Classes/CDVSplashScreen.m    |   225 +
 .../ios/CordovaLib/Classes/CDVURLProtocol.h     |    29 +
 .../ios/CordovaLib/Classes/CDVURLProtocol.m     |   230 +
 .../ios/CordovaLib/Classes/CDVUserAgentUtil.h   |    27 +
 .../ios/CordovaLib/Classes/CDVUserAgentUtil.m   |   120 +
 .../ios/CordovaLib/Classes/CDVViewController.h  |    73 +
 .../ios/CordovaLib/Classes/CDVViewController.m  |   931 +
 .../ios/CordovaLib/Classes/CDVWebViewDelegate.h |    37 +
 .../ios/CordovaLib/Classes/CDVWebViewDelegate.m |   171 +
 .../push/ios/CordovaLib/Classes/CDVWhitelist.h  |    36 +
 .../push/ios/CordovaLib/Classes/CDVWhitelist.m  |   192 +
 .../CordovaLib/Classes/NSArray+Comparisons.h    |    26 +
 .../CordovaLib/Classes/NSArray+Comparisons.m    |    41 +
 .../push/ios/CordovaLib/Classes/NSData+Base64.h |    33 +
 .../push/ios/CordovaLib/Classes/NSData+Base64.m |   281 +
 .../Classes/NSDictionary+Extensions.h           |    35 +
 .../Classes/NSDictionary+Extensions.m           |   159 +
 .../Classes/NSMutableArray+QueueAdditions.h     |    29 +
 .../Classes/NSMutableArray+QueueAdditions.m     |    58 +
 .../CordovaLib/Classes/UIDevice+Extensions.h    |    31 +
 .../CordovaLib/Classes/UIDevice+Extensions.m    |    47 +
 .../Classes/compatibility/0.9.6/CDV.h           |    30 +
 .../Classes/compatibility/0.9.6/CDVPlugin.h     |    46 +
 .../Classes/compatibility/0.9.6/CDVPlugin.m     |    29 +
 .../Classes/compatibility/1.5.0/CDV.h           |    32 +
 .../Classes/compatibility/1.5.0/CDVPlugin.h     |    23 +
 .../CordovaLib/Classes/compatibility/README.txt |    23 +
 .../CordovaLib.xcodeproj/project.pbxproj        |   667 +
 .../push/ios/CordovaLib/CordovaLib_Prefix.pch   |    22 +
 .../samples/push/ios/CordovaLib/VERSION         |     1 +
 .../apigee-sdk/samples/push/ios/cordova/build   |    51 +
 .../apigee-sdk/samples/push/ios/cordova/emulate |    55 +
 .../apigee-sdk/samples/push/ios/cordova/log     |    23 +
 .../apigee-sdk/samples/push/ios/cordova/release |    51 +
 .../apigee-sdk/samples/push/ios/cordova/run     |    58 +
 .../push/ios/iospush.xcodeproj/project.pbxproj  |   623 +
 .../push/ios/iospush/Classes/AppDelegate.h      |    42 +
 .../push/ios/iospush/Classes/AppDelegate.m      |   122 +
 .../ios/iospush/Classes/MainViewController.h    |    40 +
 .../ios/iospush/Classes/MainViewController.m    |   174 +
 .../ios/iospush/Classes/MainViewController.xib  |   138 +
 .../iospush/Plugins/AppDelegate+notification.h  |    20 +
 .../iospush/Plugins/AppDelegate+notification.m  |   119 +
 .../push/ios/iospush/Plugins/PushPlugin.h       |    54 +
 .../push/ios/iospush/Plugins/PushPlugin.m       |   248 +
 .../samples/push/ios/iospush/Plugins/README     |    20 +
 .../Resources/Capture.bundle/controls_bg.png    |   Bin 0 -> 955 bytes
 .../Resources/Capture.bundle/controls_bg@2x.png |   Bin 0 -> 971 bytes
 .../Capture.bundle/controls_bg@2x~ipad.png      |   Bin 0 -> 2858 bytes
 .../Capture.bundle/controls_bg~ipad.png         |   Bin 0 -> 969 bytes
 .../microphone-568h@2x~iphone.png               |   Bin 0 -> 531673 bytes
 .../Resources/Capture.bundle/microphone.png     |   Bin 0 -> 72226 bytes
 .../Resources/Capture.bundle/microphone@2x.png  |   Bin 0 -> 282409 bytes
 .../Capture.bundle/microphone@2x~ipad.png       |   Bin 0 -> 911582 bytes
 .../Capture.bundle/microphone~ipad.png          |   Bin 0 -> 393975 bytes
 .../Resources/Capture.bundle/record_button.png  |   Bin 0 -> 5852 bytes
 .../Capture.bundle/record_button@2x.png         |   Bin 0 -> 13875 bytes
 .../Capture.bundle/record_button@2x~ipad.png    |   Bin 0 -> 15822 bytes
 .../Capture.bundle/record_button~ipad.png       |   Bin 0 -> 7547 bytes
 .../Resources/Capture.bundle/recording_bg.png   |   Bin 0 -> 973 bytes
 .../Capture.bundle/recording_bg@2x.png          |   Bin 0 -> 990 bytes
 .../Capture.bundle/recording_bg@2x~ipad.png     |   Bin 0 -> 1026 bytes
 .../Capture.bundle/recording_bg~ipad.png        |   Bin 0 -> 996 bytes
 .../Resources/Capture.bundle/stop_button.png    |   Bin 0 -> 5514 bytes
 .../Resources/Capture.bundle/stop_button@2x.png |   Bin 0 -> 12965 bytes
 .../Capture.bundle/stop_button@2x~ipad.png      |   Bin 0 -> 14474 bytes
 .../Capture.bundle/stop_button~ipad.png         |   Bin 0 -> 7119 bytes
 .../Resources/de.lproj/Localizable.strings      |    26 +
 .../Resources/en.lproj/Localizable.strings      |    25 +
 .../Resources/es.lproj/Localizable.strings      |    25 +
 .../ios/iospush/Resources/icons/icon-72.png     |   Bin 0 -> 4944 bytes
 .../ios/iospush/Resources/icons/icon-72@2x.png  |   Bin 0 -> 11706 bytes
 .../push/ios/iospush/Resources/icons/icon.png   |   Bin 0 -> 3902 bytes
 .../ios/iospush/Resources/icons/icon@2x.png     |   Bin 0 -> 7869 bytes
 .../Resources/se.lproj/Localizable.strings      |    26 +
 .../Resources/splash/Default-568h@2x~iphone.png |   Bin 0 -> 34225 bytes
 .../splash/Default-Landscape@2x~ipad.png        |   Bin 0 -> 77300 bytes
 .../Resources/splash/Default-Landscape~ipad.png |   Bin 0 -> 34935 bytes
 .../splash/Default-Portrait@2x~ipad.png         |   Bin 0 -> 76546 bytes
 .../Resources/splash/Default-Portrait~ipad.png  |   Bin 0 -> 34278 bytes
 .../Resources/splash/Default@2x~iphone.png      |   Bin 0 -> 29475 bytes
 .../iospush/Resources/splash/Default~iphone.png |   Bin 0 -> 10394 bytes
 .../samples/push/ios/iospush/config.xml         |    65 +
 .../samples/push/ios/iospush/iospush-Info.plist |    78 +
 .../samples/push/ios/iospush/iospush-Prefix.pch |    26 +
 .../apigee-sdk/samples/push/ios/iospush/main.m  |    35 +
 .../samples/push/ios/www/PushNotification.js    |    65 +
 .../samples/push/ios/www/cordova-2.6.0.js       |  6433 ++++
 .../samples/push/ios/www/css/index.css          |   115 +
 .../samples/push/ios/www/img/logo.png           |   Bin 0 -> 21814 bytes
 .../apigee-sdk/samples/push/ios/www/js/index.js |   217 +
 .../res/screen/ios/screen-ipad-landscape-2x.png |   Bin 0 -> 1534088 bytes
 .../res/screen/ios/screen-ipad-landscape.png    |   Bin 0 -> 407370 bytes
 .../res/screen/ios/screen-ipad-portrait-2x.png  |   Bin 0 -> 1610434 bytes
 .../www/res/screen/ios/screen-ipad-portrait.png |   Bin 0 -> 422441 bytes
 .../screen/ios/screen-iphone-landscape-2x.png   |   Bin 0 -> 339639 bytes
 .../res/screen/ios/screen-iphone-landscape.png  |   Bin 0 -> 92301 bytes
 .../screen/ios/screen-iphone-portrait-2x.png    |   Bin 0 -> 350593 bytes
 .../res/screen/ios/screen-iphone-portrait.png   |   Bin 0 -> 93897 bytes
 .../apigee-sdk/samples/push/ios/www/spec.html   |    68 +
 .../samples/push/ios/www/spec/helper.js         |    33 +
 .../samples/push/ios/www/spec/index.js          |    67 +
 .../ios/www/spec/lib/jasmine-1.2.0/MIT.LICENSE  |    20 +
 .../www/spec/lib/jasmine-1.2.0/jasmine-html.js  |   616 +
 .../ios/www/spec/lib/jasmine-1.2.0/jasmine.css  |    81 +
 .../ios/www/spec/lib/jasmine-1.2.0/jasmine.js   |  2529 ++
 .../samples/usersAndGroups/README.txt           |    22 +
 .../usersAndGroups/css/codiqa.ext.min.css       |     1 +
 .../usersAndGroups/css/images/ajax-loader.gif   |   Bin 0 -> 7825 bytes
 .../css/images/icons-18-black.png               |   Bin 0 -> 1968 bytes
 .../css/images/icons-18-white.png               |   Bin 0 -> 1988 bytes
 .../css/images/icons-36-black.png               |   Bin 0 -> 3859 bytes
 .../css/images/icons-36-white.png               |   Bin 0 -> 3861 bytes
 .../css/jquery.mobile-1.3.1.min.css             |     3 +
 .../samples/usersAndGroups/js/codiqa.ext.min.js |     6 +
 .../samples/usersAndGroups/js/index.js          |   345 +
 .../usersAndGroups/js/jquery-1.9.1.min.js       |     5 +
 .../js/jquery.mobile-1.3.1.min.js               |     7 +
 .../bower_components/apigee.max.ui/bower.json   |    19 +
 .../apigee.max.ui/dist/css/max.min.css          |     1 +
 .../apigee.max.ui/dist/img/no-data1.png         |   Bin 0 -> 45300 bytes
 .../apigee.max.ui/dist/img/phone-small.gif      |   Bin 0 -> 1300 bytes
 .../apigee.max.ui/dist/img/tablet-small.gif     |   Bin 0 -> 1390 bytes
 .../apigee.max.ui/dist/js/max-dev.min.js        |  1781 +
 .../apigee.max.ui/dist/js/max.min.js            |     4 +
 .../bower_components/intro.js/BUILD/BUILD.js    |    43 +
 .../bower_components/intro.js/Makefile          |     6 +
 .../bower_components/intro.js/README.md         |   487 +
 .../bower_components/intro.js/bower.json        |     9 +
 .../bower_components/intro.js/component.json    |    13 +
 .../bower_components/intro.js/intro.js          |   940 +
 .../bower_components/intro.js/introjs-rtl.css   |    22 +
 .../bower_components/intro.js/introjs.css       |   248 +
 .../intro.js/minified/intro.min.js              |    24 +
 .../intro.js/minified/introjs-rtl.min.css       |     1 +
 .../intro.js/minified/introjs.min.css           |     1 +
 .../bower_components/intro.js/package.json      |    17 +
 .../jquery-waypoints/CHANGELOG.md               |    92 +
 .../jquery-waypoints/README.markdown            |    47 +
 .../jquery-waypoints/bower.json                 |    19 +
 .../jquery-waypoints/licenses.txt               |    23 +
 .../jquery-waypoints/package.json               |    19 +
 .../infinite-scroll/waypoints-infinite.js       |    67 +
 .../infinite-scroll/waypoints-infinite.min.js   |     8 +
 .../sticky-elements/waypoints-sticky.js         |    55 +
 .../sticky-elements/waypoints-sticky.min.js     |     8 +
 .../jquery-waypoints/waypoints.js               |   520 +
 .../jquery-waypoints/waypoints.min.js           |     8 +
 .../bower_components/jquery/MIT-LICENSE.txt     |    21 +
 .../bower_components/jquery/bower.json          |    27 +
 .../bower_components/jquery/dist/jquery.js      |  9174 +++++
 .../bower_components/jquery/dist/jquery.min.js  |     5 +
 .../bower_components/jquery/dist/jquery.min.map |     1 +
 .../bower_components/jquery/src/ajax.js         |   806 +
 .../bower_components/jquery/src/ajax/jsonp.js   |    89 +
 .../bower_components/jquery/src/ajax/load.js    |    75 +
 .../jquery/src/ajax/parseJSON.js                |    13 +
 .../jquery/src/ajax/parseXML.js                 |    28 +
 .../bower_components/jquery/src/ajax/script.js  |    64 +
 .../jquery/src/ajax/var/nonce.js                |     5 +
 .../jquery/src/ajax/var/rquery.js               |     3 +
 .../bower_components/jquery/src/ajax/xhr.js     |   135 +
 .../bower_components/jquery/src/attributes.js   |    11 +
 .../jquery/src/attributes/attr.js               |   143 +
 .../jquery/src/attributes/classes.js            |   158 +
 .../jquery/src/attributes/prop.js               |    96 +
 .../jquery/src/attributes/support.js            |    35 +
 .../jquery/src/attributes/val.js                |   163 +
 .../bower_components/jquery/src/callbacks.js    |   205 +
 .../bower_components/jquery/src/core.js         |   498 +
 .../bower_components/jquery/src/core/access.js  |    60 +
 .../bower_components/jquery/src/core/init.js    |   123 +
 .../jquery/src/core/parseHTML.js                |    39 +
 .../bower_components/jquery/src/core/ready.js   |    97 +
 .../jquery/src/core/var/rsingleTag.js           |     4 +
 .../bower_components/jquery/src/css.js          |   451 +
 .../jquery/src/css/addGetHookIf.js              |    24 +
 .../bower_components/jquery/src/css/curCSS.js   |    57 +
 .../jquery/src/css/defaultDisplay.js            |    70 +
 .../jquery/src/css/hiddenVisibleSelectors.js    |    15 +
 .../bower_components/jquery/src/css/support.js  |    91 +
 .../bower_components/jquery/src/css/swap.js     |    28 +
 .../jquery/src/css/var/cssExpand.js             |     3 +
 .../jquery/src/css/var/getStyles.js             |     5 +
 .../jquery/src/css/var/isHidden.js              |    13 +
 .../jquery/src/css/var/rmargin.js               |     3 +
 .../jquery/src/css/var/rnumnonpx.js             |     5 +
 .../bower_components/jquery/src/data.js         |   175 +
 .../bower_components/jquery/src/data/Data.js    |   181 +
 .../bower_components/jquery/src/data/accepts.js |    20 +
 .../jquery/src/data/var/data_priv.js            |     5 +
 .../jquery/src/data/var/data_user.js            |     5 +
 .../bower_components/jquery/src/deferred.js     |   149 +
 .../bower_components/jquery/src/deprecated.js   |    13 +
 .../bower_components/jquery/src/dimensions.js   |    50 +
 .../bower_components/jquery/src/effects.js      |   647 +
 .../jquery/src/effects/Tween.js                 |   114 +
 .../jquery/src/effects/animatedSelector.js      |    13 +
 .../bower_components/jquery/src/event.js        |   868 +
 .../bower_components/jquery/src/event/alias.js  |    39 +
 .../jquery/src/event/support.js                 |     9 +
 .../bower_components/jquery/src/exports/amd.js  |    24 +
 .../jquery/src/exports/global.js                |    32 +
 .../bower_components/jquery/src/intro.js        |    44 +
 .../bower_components/jquery/src/jquery.js       |    36 +
 .../bower_components/jquery/src/manipulation.js |   582 +
 .../jquery/src/manipulation/_evalUrl.js         |    18 +
 .../jquery/src/manipulation/support.js          |    31 +
 .../src/manipulation/var/rcheckableType.js      |     3 +
 .../bower_components/jquery/src/offset.js       |   204 +
 .../bower_components/jquery/src/outro.js        |     1 +
 .../bower_components/jquery/src/queue.js        |   142 +
 .../bower_components/jquery/src/queue/delay.js  |    22 +
 .../jquery/src/selector-native.js               |   172 +
 .../jquery/src/selector-sizzle.js               |    14 +
 .../bower_components/jquery/src/selector.js     |     1 +
 .../bower_components/jquery/src/serialize.js    |   111 +
 .../jquery/src/sizzle/dist/sizzle.js            |  2034 ++
 .../jquery/src/sizzle/dist/sizzle.min.js        |     3 +
 .../jquery/src/sizzle/dist/sizzle.min.map       |     1 +
 .../bower_components/jquery/src/traversing.js   |   200 +
 .../jquery/src/traversing/findFilter.js         |   100 +
 .../jquery/src/traversing/var/rneedsContext.js  |     6 +
 .../bower_components/jquery/src/var/arr.js      |     3 +
 .../jquery/src/var/class2type.js                |     4 +
 .../bower_components/jquery/src/var/concat.js   |     5 +
 .../bower_components/jquery/src/var/hasOwn.js   |     5 +
 .../bower_components/jquery/src/var/indexOf.js  |     5 +
 .../bower_components/jquery/src/var/pnum.js     |     3 +
 .../bower_components/jquery/src/var/push.js     |     5 +
 .../jquery/src/var/rnotwhite.js                 |     3 +
 .../bower_components/jquery/src/var/slice.js    |     5 +
 .../jquery/src/var/strundefined.js              |     3 +
 .../bower_components/jquery/src/var/support.js  |     4 +
 .../bower_components/jquery/src/var/toString.js |     5 +
 .../bower_components/jquery/src/var/trim.js     |     3 +
 .../bower_components/jquery/src/wrap.js         |    78 +
 .../bower_components/sizzle/dist/sizzle.js      |  2015 +
 .../bower_components/sizzle/dist/sizzle.min.js  |     3 +
 .../bower_components/sizzle/dist/sizzle.min.map |     1 +
 .../bower_components/sizzle/tasks/commit.js     |    10 +
 .../bower_components/sizzle/tasks/compile.js    |    34 +
 .../bower_components/sizzle/tasks/dist.js       |    35 +
 .../bower_components/sizzle/tasks/release.js    |    43 +
 .../bower_components/sizzle/tasks/tag.js        |     9 +
 .../bower_components/sizzle/tasks/version.js    |    35 +
 .../bower_components/sizzle/test/data/empty.js  |     0
 .../sizzle/test/data/mixed_sort.html            |    22 +
 .../sizzle/test/data/testinit.js                |   136 +
 .../bower_components/sizzle/test/jquery.js      |  9597 +++++
 .../sizzle/test/libs/qunit/qunit.css            |   244 +
 .../sizzle/test/libs/qunit/qunit.js             |  2212 ++
 .../sizzle/test/unit/extending.js               |    95 +
 .../sizzle/test/unit/selector.js                |  1138 +
 .../sizzle/test/unit/utilities.js               |   169 +
 portal/dist/usergrid-portal/config.js           |    45 +
 .../css/apigeeGlobalNavigation.css              |   274 +
 .../css/arsmarquette/ARSMaquettePro-Light.otf   |   Bin 0 -> 184600 bytes
 .../css/arsmarquette/ARSMaquettePro-Medium.otf  |   Bin 0 -> 188020 bytes
 .../css/arsmarquette/ARSMaquettePro-Regular.otf |   Bin 0 -> 188096 bytes
 portal/dist/usergrid-portal/css/dash.min.css    |     1 +
 .../dist/usergrid-portal/css/entypo/entypo.eot  |   Bin 0 -> 35540 bytes
 .../dist/usergrid-portal/css/entypo/entypo.svg  |    13 +
 .../dist/usergrid-portal/css/entypo/entypo.ttf  |   Bin 0 -> 35392 bytes
 .../dist/usergrid-portal/css/entypo/entypo.woff |   Bin 0 -> 21916 bytes
 portal/dist/usergrid-portal/css/main.css        |  1970 +
 portal/dist/usergrid-portal/favicon.ico         |   Bin 0 -> 1150 bytes
 .../img/appswitcher/apiPlatform_lg.png          |   Bin 0 -> 2397 bytes
 .../img/appswitcher/appServices_lg.png          |   Bin 0 -> 2295 bytes
 .../img/appswitcher/console_lg.png              |   Bin 0 -> 1453 bytes
 .../usergrid-portal/img/appswitcher/home_lg.png |   Bin 0 -> 1522 bytes
 .../img/appswitcher/logo_color.png              |   Bin 0 -> 3459 bytes
 .../usergrid-portal/img/appswitcher/max_lg.png  |   Bin 0 -> 1970 bytes
 .../img/appswitcher/triangleMenuItem_right.png  |   Bin 0 -> 1158 bytes
 .../triangleMenuItem_right_hover.png            |   Bin 0 -> 1169 bytes
 portal/dist/usergrid-portal/img/blue-bars.png   |   Bin 0 -> 3635 bytes
 portal/dist/usergrid-portal/img/blue-bolt.png   |   Bin 0 -> 3942 bytes
 portal/dist/usergrid-portal/img/blue-carat.png  |   Bin 0 -> 1006 bytes
 portal/dist/usergrid-portal/img/green_dot.png   |   Bin 0 -> 3472 bytes
 .../img/introjs_arrow_step_next.png             |   Bin 0 -> 219 bytes
 .../img/introjs_arrow_step_next_disabled.png    |   Bin 0 -> 220 bytes
 .../img/introjs_arrow_step_prev.png             |   Bin 0 -> 217 bytes
 .../img/introjs_arrow_step_prev_disabled.png    |   Bin 0 -> 218 bytes
 .../dist/usergrid-portal/img/introjs_close.png  |   Bin 0 -> 274 bytes
 portal/dist/usergrid-portal/img/logo.gif        |   Bin 0 -> 2279 bytes
 portal/dist/usergrid-portal/img/nav-device.gif  |   Bin 0 -> 2184 bytes
 portal/dist/usergrid-portal/img/nav-sprites.png |   Bin 0 -> 7953 bytes
 portal/dist/usergrid-portal/img/no-data1.png    |   Bin 0 -> 45300 bytes
 portal/dist/usergrid-portal/img/phone-small.gif |   Bin 0 -> 1300 bytes
 .../img/push/APNS_cert_upload.png               |   Bin 0 -> 33956 bytes
 .../img/push/APNS_certification.png             |   Bin 0 -> 16855 bytes
 .../img/push/android-notification.png           |   Bin 0 -> 41629 bytes
 .../usergrid-portal/img/push/google_api_key.png |   Bin 0 -> 98118 bytes
 .../usergrid-portal/img/push/iphone_message.png |   Bin 0 -> 90307 bytes
 portal/dist/usergrid-portal/img/push/step_1.png |   Bin 0 -> 1953 bytes
 portal/dist/usergrid-portal/img/push/step_2.png |   Bin 0 -> 2117 bytes
 portal/dist/usergrid-portal/img/push/step_3.png |   Bin 0 -> 2162 bytes
 portal/dist/usergrid-portal/img/red_dot.png     |   Bin 0 -> 3482 bytes
 .../usergrid-portal/img/sdk-sprites-large.png   |   Bin 0 -> 14642 bytes
 portal/dist/usergrid-portal/img/sdk-sprites.png |   Bin 0 -> 5027 bytes
 .../dist/usergrid-portal/img/tablet-small.gif   |   Bin 0 -> 1390 bytes
 portal/dist/usergrid-portal/img/user-photo.png  |   Bin 0 -> 3849 bytes
 .../dist/usergrid-portal/img/user_profile.png   |   Bin 0 -> 3775 bytes
 portal/dist/usergrid-portal/img/verify.png      |   Bin 0 -> 22934 bytes
 portal/dist/usergrid-portal/img/yellow_dot.png  |   Bin 0 -> 3475 bytes
 portal/dist/usergrid-portal/index-debug.html    |   183 +
 portal/dist/usergrid-portal/index-template.html |   188 +
 portal/dist/usergrid-portal/index.html          |   183 +
 .../usergrid-portal/js/charts/highcharts.json   |   329 +
 .../js/libs/Highcharts-2.3.5/index.htm          |    79 +
 .../js/adapters/mootools-adapter.js             |    13 +
 .../js/adapters/mootools-adapter.src.js         |   328 +
 .../js/adapters/prototype-adapter.js            |    16 +
 .../js/adapters/prototype-adapter.src.js        |   385 +
 .../libs/Highcharts-2.3.5/js/highcharts-more.js |    35 +
 .../Highcharts-2.3.5/js/highcharts-more.src.js  |  1581 +
 .../js/libs/Highcharts-2.3.5/js/highcharts.js   |   250 +
 .../libs/Highcharts-2.3.5/js/highcharts.src.js  | 15281 ++++++++
 .../Highcharts-2.3.5/js/modules/canvas-tools.js |   133 +
 .../js/modules/canvas-tools.src.js              |  3113 ++
 .../js/libs/Highcharts-2.3.5/js/modules/data.js |    14 +
 .../Highcharts-2.3.5/js/modules/data.src.js     |   512 +
 .../Highcharts-2.3.5/js/modules/exporting.js    |    23 +
 .../js/modules/exporting.src.js                 |   752 +
 .../Highcharts-2.3.5/js/themes/dark-blue.js     |   263 +
 .../Highcharts-2.3.5/js/themes/dark-green.js    |   263 +
 .../js/libs/Highcharts-2.3.5/js/themes/gray.js  |   262 +
 .../js/libs/Highcharts-2.3.5/js/themes/grid.js  |    95 +
 .../js/libs/Highcharts-2.3.5/js/themes/skies.js |    89 +
 portal/dist/usergrid-portal/js/libs/MD5.min.js  |     1 +
 .../js/libs/angular-1.0.5/angular-cookies.js    |   183 +
 .../libs/angular-1.0.5/angular-cookies.min.js   |     7 +
 .../js/libs/angular-1.0.5/angular-loader.js     |   276 +
 .../js/libs/angular-1.0.5/angular-loader.min.js |     7 +
 .../js/libs/angular-1.0.5/angular-mocks.js      |  1886 +
 .../js/libs/angular-1.0.5/angular-resource.js   |   445 +
 .../libs/angular-1.0.5/angular-resource.min.js  |    10 +
 .../js/libs/angular-1.0.5/angular-sanitize.js   |   535 +
 .../libs/angular-1.0.5/angular-sanitize.min.js  |    13 +
 .../js/libs/angular-1.0.5/angular.js            | 14733 ++++++++
 .../js/libs/angular-1.0.5/angular.min.js        |   161 +
 .../js/libs/angular-1.0.5/version.txt           |     1 +
 .../js/libs/angular-1.1.5/angular-1.1.5.js      | 16876 +++++++++
 .../js/libs/angular-1.1.5/angular-merge.min.js  |     8 +
 .../angular-1.1.5/angular-resource-1.1.5.js     |   537 +
 .../js/libs/angular-1.2.5/angular-animate.js    |  1323 +
 .../libs/angular-1.2.5/angular-animate.min.js   |    23 +
 .../angular-1.2.5/angular-animate.min.js.map    |     8 +
 .../js/libs/angular-1.2.5/angular-cookies.js    |   202 +
 .../libs/angular-1.2.5/angular-cookies.min.js   |     8 +
 .../angular-1.2.5/angular-cookies.min.js.map    |     8 +
 .../js/libs/angular-1.2.5/angular-csp.css       |    24 +
 .../js/libs/angular-1.2.5/angular-loader.js     |   410 +
 .../js/libs/angular-1.2.5/angular-loader.min.js |     9 +
 .../angular-1.2.5/angular-loader.min.js.map     |     8 +
 .../js/libs/angular-1.2.5/angular-mocks.js      |  2116 ++
 .../js/libs/angular-1.2.5/angular-resource.js   |   565 +
 .../libs/angular-1.2.5/angular-resource.min.js  |    13 +
 .../angular-1.2.5/angular-resource.min.js.map   |     8 +
 .../js/libs/angular-1.2.5/angular-route.js      |   911 +
 .../js/libs/angular-1.2.5/angular-route.min.js  |    14 +
 .../libs/angular-1.2.5/angular-route.min.js.map |     8 +
 .../js/libs/angular-1.2.5/angular-sanitize.js   |   622 +
 .../libs/angular-1.2.5/angular-sanitize.min.js  |    14 +
 .../angular-1.2.5/angular-sanitize.min.js.map   |     8 +
 .../js/libs/angular-1.2.5/angular-scenario.js   | 32374 +++++++++++++++++
 .../js/libs/angular-1.2.5/angular-touch.js      |   563 +
 .../js/libs/angular-1.2.5/angular-touch.min.js  |    13 +
 .../libs/angular-1.2.5/angular-touch.min.js.map |     8 +
 .../js/libs/angular-1.2.5/angular.js            | 20369 +++++++++++
 .../js/libs/angular-1.2.5/angular.min.js        |   201 +
 .../js/libs/angular-1.2.5/angular.min.js.map    |     8 +
 .../js/libs/angular-1.2.5/errors.json           |     1 +
 .../js/libs/angular-1.2.5/version.json          |     1 +
 .../js/libs/angular-1.2.5/version.txt           |     1 +
 .../angularitics-0.8.5-google-analytics.js      |     7 +
 .../js/libs/angularitics/angularitics-0.8.5.js  |     6 +
 .../libs/bootstrap/css/bootstrap-responsive.css |  1345 +
 .../bootstrap/css/bootstrap-responsive.min.css  |  1245 +
 .../js/libs/bootstrap/css/bootstrap.css         |  6169 ++++
 .../js/libs/bootstrap/css/bootstrap.min.css     |  5469 +++
 .../js/libs/bootstrap/custom/css/bootstrap.css  |  6316 ++++
 .../libs/bootstrap/custom/css/bootstrap.min.css |     9 +
 .../custom/img/glyphicons-halflings-white.png   |   Bin 0 -> 8777 bytes
 .../custom/img/glyphicons-halflings.png         |   Bin 0 -> 12799 bytes
 .../js/libs/bootstrap/custom/js/bootstrap.js    |  2291 ++
 .../libs/bootstrap/custom/js/bootstrap.min.js   |     7 +
 .../img/glyphicons-halflings-white.png          |   Bin 0 -> 8777 bytes
 .../libs/bootstrap/img/glyphicons-halflings.png |   Bin 0 -> 12799 bytes
 .../js/libs/bootstrap/js/bootstrap.js           |  2117 ++
 .../js/libs/bootstrap/js/bootstrap.min.js       |   644 +
 .../usergrid-portal/js/libs/google-viz-api.js   |    49 +
 .../js/libs/jquery/jquery-1.9.1.min.js          |     5 +
 .../js/libs/jquery/jquery-migrate-1.1.1.min.js  |     3 +
 .../js/libs/jquery/jquery.sparkline.min.js      |     5 +
 .../js/libs/jqueryui/date.min.js                |     2 +
 .../ui-bg_diagonals-thick_90_eeeeee_40x40.png   |   Bin 0 -> 251 bytes
 .../images/ui-bg_flat_100_deedf7_40x100.png     |   Bin 0 -> 182 bytes
 .../images/ui-bg_flat_100_e4f1fb_40x100.png     |   Bin 0 -> 213 bytes
 .../images/ui-bg_flat_100_f2f5f7_40x100.png     |   Bin 0 -> 212 bytes
 .../images/ui-bg_flat_15_cd0a0a_40x100.png      |   Bin 0 -> 181 bytes
 .../images/ui-bg_flat_50_3baae3_40x100.png      |   Bin 0 -> 182 bytes
 .../images/ui-bg_flat_80_d7ebf9_40x100.png      |   Bin 0 -> 183 bytes
 .../ui-bg_highlight-hard_70_000000_1x100.png    |   Bin 0 -> 118 bytes
 .../ui-bg_highlight-soft_25_ffef8f_1x100.png    |   Bin 0 -> 153 bytes
 .../jqueryui/images/ui-icons_000000_256x240.png |   Bin 0 -> 4369 bytes
 .../jqueryui/images/ui-icons_2694e8_256x240.png |   Bin 0 -> 4369 bytes
 .../jqueryui/images/ui-icons_2e83ff_256x240.png |   Bin 0 -> 4369 bytes
 .../jqueryui/images/ui-icons_3d80b3_256x240.png |   Bin 0 -> 4369 bytes
 .../jqueryui/images/ui-icons_72a7cf_256x240.png |   Bin 0 -> 4369 bytes
 .../jqueryui/images/ui-icons_ffffff_256x240.png |   Bin 0 -> 4369 bytes
 .../js/libs/jqueryui/jquery-ui-1.8.18.min.js    |    15 +
 .../js/libs/jqueryui/jquery-ui-1.8.9.custom.css |     1 +
 .../js/libs/jqueryui/jquery-ui-timepicker.css   |     1 +
 .../libs/jqueryui/jquery.ui.timepicker.min.js   |     1 +
 .../ui-bootstrap-custom-0.3.0.min.js            |     1 +
 .../ui-bootstrap-custom-tpls-0.3.0.min.js       |     1 +
 .../js/libs/usergrid-libs.min.js                |    22 +
 .../usergrid-portal/js/libs/usergrid.sdk.js     |  2474 ++
 .../dist/usergrid-portal/js/usergrid-dev.min.js |  4939 +++
 portal/dist/usergrid-portal/js/usergrid.min.js  |     6 +
 .../dist/usergrid-portal/sdk/usergrid.0.10.4.js |  1402 +
 .../dist/usergrid-portal/sdk/usergrid.0.10.5.js |  1755 +
 .../dist/usergrid-portal/sdk/usergrid.0.10.7.js |  2265 ++
 portal/img/introjs_arrow_step_next.png          |   Bin 0 -> 219 bytes
 portal/img/introjs_arrow_step_next_disabled.png |   Bin 0 -> 220 bytes
 portal/img/introjs_arrow_step_prev.png          |   Bin 0 -> 217 bytes
 portal/img/introjs_arrow_step_prev_disabled.png |   Bin 0 -> 218 bytes
 portal/img/introjs_close.png                    |   Bin 0 -> 274 bytes
 portal/index-debug.html                         |    95 +-
 portal/index-template.html                      |    81 +-
 portal/index.html                               |    95 +-
 portal/js/app.js                                |   255 +-
 portal/js/data/shell-controller.js              |     9 -
 portal/js/global/help-service.js                |   140 +
 portal/js/global/page-controller.js             |   349 +-
 portal/js/global/page-title.js                  |    13 +-
 portal/js/global/ug-service.js                  |    20 +-
 .../js/libs/bootstrap/custom/css/bootstrap.css  |    15 +-
 .../libs/bootstrap/custom/css/bootstrap.min.css |     2 +-
 portal/js/libs/usergrid-libs.min.js             |    22 +-
 portal/js/libs/usergrid.sdk.js                  |     4 +-
 portal/js/login/login-controller.js             |    10 +-
 portal/js/login/login.html                      |     3 +-
 .../js/org-overview/org-overview-controller.js  |     4 +-
 portal/js/org-overview/org-overview.html        |   149 +-
 portal/js/org-overview/org-overview.html.orig   |   188 +
 portal/js/roles/roles.html                      |     9 +-
 portal/js/shell/shell-controller.js             |     5 +-
 portal/js/shell/shell.html                      |     1 +
 portal/js/templates.js                          |   163 +-
 portal/js/usergrid-dev.min.js                   |   174 +-
 portal/js/usergrid.min.js                       |    10 +-
 portal/package.json                             |    17 +-
 .../instrument/js/usergrid-coverage.min.js      |     6 +
 .../test/coverage/instrument/js/usergrid.min.js |     3 +
 portal/tests/protractor/applications.spec.js    |     2 +-
 .../tests/protractor/coverage/coverage.spec.js  |     7 +
 portal/tests/protractor/data.spec.js            |     2 +-
 portal/tests/protractor/forgotPassword.spec.js  |     4 +-
 portal/tests/protractor/login.spec.js           |    45 +
 portal/tests/protractor/organization.spec.js    |     2 +-
 portal/tests/protractor/profile.spec.js         |     6 +-
 portal/tests/protractor/roles.spec.js           |    40 +
 portal/tests/protractor/shell.spec.js           |   121 +
 portal/tests/protractor/users.spec.js           |    45 +-
 portal/tests/protractor/util.js                 |    81 +-
 portal/tests/protractorConf.js                  |     3 +-
 portal/tests/unit/sample.spec.js                |     1 +
 sdks/nodejs/lib/usergrid.js                     |    74 +-
 sdks/nodejs/package.json                        |     3 +-
 stack/pom.xml                                   |     1 +
 .../applications/ApplicationResource.java       |     1 -
 .../main/resources/swagger/applications.json    |    16 -
 .../src/main/resources/swagger/management.json  |    16 -
 .../src/main/resources/swagger/resources.json   |    16 -
 stack/services/pom.xml                          |     6 +-
 .../management/export/ExportServiceImpl.java    |   331 +-
 .../management/export/S3ExportImpl.java         |    10 +-
 .../cassandra/ManagementServiceIT.java          |   292 +-
 .../management/cassandra/MockS3ExportImpl.java  |     1 -
 832 files changed, 338049 insertions(+), 1145 deletions(-)
----------------------------------------------------------------------



[09/12] Updated examples and fixed issues where encountered. Updated changelog

Posted by sn...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/39f0ebeb/sdks/html5-javascript/usergrid.min.js
----------------------------------------------------------------------
diff --git a/sdks/html5-javascript/usergrid.min.js b/sdks/html5-javascript/usergrid.min.js
index 14a8078..02ad346 100644
--- a/sdks/html5-javascript/usergrid.min.js
+++ b/sdks/html5-javascript/usergrid.min.js
@@ -1,3 +1,3 @@
 /*! usergrid@0.11.0 2014-04-01 */
-function extend(subClass,superClass){var F=function(){};return F.prototype=superClass.prototype,subClass.prototype=new F,subClass.prototype.constructor=subClass,subClass.superclass=superClass.prototype,superClass.prototype.constructor==Object.prototype.constructor&&(superClass.prototype.constructor=superClass),subClass}function propCopy(from,to){for(var prop in from)from.hasOwnProperty(prop)&&(to[prop]="object"==typeof from[prop]&&"object"==typeof to[prop]?propCopy(from[prop],to[prop]):from[prop]);return to}function NOOP(){}function isValidUrl(url){if(!url)return!1;var doc,base,anchor,isValid=!1;try{doc=document.implementation.createHTMLDocument(""),base=doc.createElement("base"),base.href=base||window.lo,doc.head.appendChild(base),anchor=doc.createElement("a"),anchor.href=url,doc.body.appendChild(anchor),isValid=!(""===anchor.href)}catch(e){console.error(e)}finally{return doc.head.removeChild(base),doc.body.removeChild(anchor),base=null,anchor=null,doc=null,isValid}}function isUUID
 (uuid){return uuid?uuidValueRegex.test(uuid):!1}function encodeParams(params){var queryString;return params&&Object.keys(params)&&(queryString=[].slice.call(arguments).reduce(function(a,b){return a.concat(b instanceof Array?b:[b])},[]).filter(function(c){return"object"==typeof c}).reduce(function(p,c){return c instanceof Array?p.push(c):p=p.concat(Object.keys(c).map(function(key){return[key,c[key]]})),p},[]).reduce(function(p,c){return 2===c.length?p.push(c):p=p.concat(c),p},[]).reduce(function(p,c){return c[1]instanceof Array?c[1].forEach(function(v){p.push([c[0],v])}):p.push(c),p},[]).map(function(c){return c[1]=encodeURIComponent(c[1]),c.join("=")}).join("&")),queryString}function isFunction(f){return f&&null!==f&&"function"==typeof f}function doCallback(callback,params,context){var returnValue;return isFunction(callback)&&(params||(params=[]),context||(context=this),params.push(context),returnValue=callback.apply(context,params)),returnValue}function getSafeTime(prop){var time;s
 witch(typeof prop){case"undefined":time=Date.now();break;case"number":time=prop;break;case"string":time=isNaN(prop)?Date.parse(prop):parseInt(prop);break;default:time=Date.parse(prop.toString())}return time}var UsergridEventable=function(){throw Error("'UsergridEventable' is not intended to be invoked directly")};UsergridEventable.prototype={bind:function(event,fn){this._events=this._events||{},this._events[event]=this._events[event]||[],this._events[event].push(fn)},unbind:function(event,fn){this._events=this._events||{},event in this._events!=!1&&this._events[event].splice(this._events[event].indexOf(fn),1)},trigger:function(event){if(this._events=this._events||{},event in this._events!=!1)for(var i=0;i<this._events[event].length;i++)this._events[event][i].apply(this,Array.prototype.slice.call(arguments,1))}},UsergridEventable.mixin=function(destObject){for(var props=["bind","unbind","trigger"],i=0;i<props.length;i++)props[i]in destObject.prototype&&(console.warn("overwriting '"+p
 rops[i]+"' on '"+destObject.name+"'."),console.warn("the previous version can be found at '_"+props[i]+"' on '"+destObject.name+"'."),destObject.prototype["_"+props[i]]=destObject.prototype[props[i]]),destObject.prototype[props[i]]=UsergridEventable.prototype[props[i]]},function(){function Logger(name){this.logEnabled=!0,this.init(name,!0)}var name="Logger",global=this,overwrittenName=global[name];return Logger.METHODS=["log","error","warn","info","debug","assert","clear","count","dir","dirxml","exception","group","groupCollapsed","groupEnd","profile","profileEnd","table","time","timeEnd","trace"],Logger.prototype.init=function(name,logEnabled){this.name=name||"UNKNOWN",this.logEnabled=logEnabled||!0;var addMethod=function(method){this[method]=this.createLogMethod(method)}.bind(this);Logger.METHODS.forEach(addMethod)},Logger.prototype.createLogMethod=function(method){return Logger.prototype.log.bind(this,method)},Logger.prototype.prefix=function(method,args){var prepend="["+method.t
 oUpperCase()+"]["+name+"]:	";return-1!==["log","error","warn","info"].indexOf(method)&&("string"==typeof args[0]?args[0]=prepend+args[0]:args.unshift(prepend)),args},Logger.prototype.log=function(){var args=[].slice.call(arguments);method=args.shift(),-1===Logger.METHODS.indexOf(method)&&(method="log"),this.logEnabled&&console&&console[method]&&(args=this.prefix(method,args),console[method].apply(console,args))},Logger.prototype.setLogEnabled=function(logEnabled){this.logEnabled=logEnabled||!0},Logger.mixin=function(destObject){destObject.__logger=new Logger(destObject.name||"UNKNOWN");var addMethod=function(method){method in destObject.prototype&&(console.warn("overwriting '"+method+"' on '"+destObject.name+"'."),console.warn("the previous version can be found at '_"+method+"' on '"+destObject.name+"'."),destObject.prototype["_"+method]=destObject.prototype[method]),destObject.prototype[method]=destObject.__logger.createLogMethod(method)};Logger.METHODS.forEach(addMethod)},global[n
 ame]=Logger,global[name].noConflict=function(){return overwrittenName&&(global[name]=overwrittenName),Logger},global[name]}(),function(global){function Promise(){this.complete=!1,this.error=null,this.result=null,this.callbacks=[]}var name="Promise",overwrittenName=global[name];return Promise.prototype.then=function(callback,context){var f=function(){return callback.apply(context,arguments)};this.complete?f(this.error,this.result):this.callbacks.push(f)},Promise.prototype.done=function(error,result){if(this.complete=!0,this.error=error,this.result=result,this.callbacks){for(var i=0;i<this.callbacks.length;i++)this.callbacks[i](error,result);this.callbacks.length=0}},Promise.join=function(promises){function notifier(i){return function(error,result){completed+=1,errors[i]=error,results[i]=result,completed===total&&p.done(errors,results)}}for(var p=new Promise,total=promises.length,completed=0,errors=[],results=[],i=0;total>i;i++)promises[i]().then(notifier(i));return p},Promise.chain=f
 unction(promises,error,result){var p=new Promise;return null===promises||0===promises.length?p.done(error,result):promises[0](error,result).then(function(res,err){promises.splice(0,1),promises?Promise.chain(promises,res,err).then(function(r,e){p.done(r,e)}):p.done(res,err)}),p},global[name]=Promise,global[name].noConflict=function(){return overwrittenName&&(global[name]=overwrittenName),Promise},global[name]}(this),function(){function partial(){var args=Array.prototype.slice.call(arguments),fn=args.shift();return fn.bind(this,args)}function Ajax(){function encode(data){var result="";if("string"==typeof data)result=data;else{var e=encodeURIComponent;for(var i in data)data.hasOwnProperty(i)&&(result+="&"+e(i)+"="+e(data[i]))}return result}function request(m,u,d){var timeout,p=new Promise;return self.logger.time(m+" "+u),function(xhr){xhr.onreadystatechange=function(){4===this.readyState&&(self.logger.timeEnd(m+" "+u),clearTimeout(timeout),p.done(null,this))},xhr.onerror=function(respo
 nse){clearTimeout(timeout),p.done(response,null)},xhr.oncomplete=function(){clearTimeout(timeout),self.logger.timeEnd(m+" "+u),self.info("%s request to %s returned %s",m,u,this.status)},xhr.open(m,u),d&&("object"==typeof d&&(d=JSON.stringify(d)),xhr.setRequestHeader("Content-Type","application/json"),xhr.setRequestHeader("Accept","application/json")),timeout=setTimeout(function(){xhr.abort(),p.done("API Call timed out.",null)},3e4),xhr.send(encode(d))}(new XMLHttpRequest),p}this.logger=new global.Logger(name);var self=this;this.request=request,this.get=partial(request,"GET"),this.post=partial(request,"POST"),this.put=partial(request,"PUT"),this.delete=partial(request,"DELETE")}var exports,name="Ajax",global=this,overwrittenName=global[name];return global[name]=new Ajax,global[name].noConflict=function(){return overwrittenName&&(global[name]=overwrittenName),exports},global[name]}(),window.console=window.console||{},window.console.log=window.console.log||function(){};var uuidValueReg
 ex=/^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/;!function(global){function Usergrid(){this.logger=new Logger(name)}var name="Usergrid",overwrittenName=global[name],VALID_REQUEST_METHODS=["GET","POST","PUT","DELETE"];return Usergrid.isValidEndpoint=function(){return!0},Usergrid.Request=function(method,endpoint,query_params,data,callback){var p=new Promise;if(this.logger=new global.Logger("Usergrid.Request"),this.logger.time("process request "+method+" "+endpoint),this.endpoint=endpoint+"?"+encodeParams(query_params),this.method=method.toUpperCase(),this.data="object"==typeof data?JSON.stringify(data):data,-1===VALID_REQUEST_METHODS.indexOf(this.method))throw new UsergridInvalidHTTPMethodError("invalid request method '"+this.method+"'");if(!isValidUrl(this.endpoint))throw this.logger.error(endpoint,this.endpoint,/^https:\/\//.test(endpoint)),new UsergridInvalidURIError("The provided endpoint is not valid: "+this.endpoint);var request=function(){retur
 n Ajax.request(this.method,this.endpoint,this.data)}.bind(this),response=function(err,request){return new Usergrid.Response(err,request)}.bind(this),oncomplete=function(err,response){p.done(err,response),this.logger.info("REQUEST",err,response),doCallback(callback,[err,response]),this.logger.timeEnd("process request "+method+" "+endpoint)}.bind(this);return Promise.chain([request,response]).then(oncomplete),p},Usergrid.Response=function(err,response){var p=new Promise,data=null;try{data=JSON.parse(response.responseText)}catch(e){data={}}switch(Object.keys(data).forEach(function(key){Object.defineProperty(this,key,{value:data[key],enumerable:!0})}.bind(this)),Object.defineProperty(this,"logger",{enumerable:!1,configurable:!1,writable:!1,value:new global.Logger(name)}),Object.defineProperty(this,"success",{enumerable:!1,configurable:!1,writable:!0,value:!0}),Object.defineProperty(this,"err",{enumerable:!1,configurable:!1,writable:!0,value:err}),Object.defineProperty(this,"status",{enu
 merable:!1,configurable:!1,writable:!0,value:parseInt(response.status)}),Object.defineProperty(this,"statusGroup",{enumerable:!1,configurable:!1,writable:!0,value:this.status-this.status%100}),this.statusGroup){case 200:this.success=!0;break;case 400:case 500:case 300:case 100:default:this.success=!1}return this.success?p.done(null,this):p.done(UsergridError.fromResponse(data),this),p},Usergrid.Response.prototype.getEntities=function(){var entities;return this.success&&(entities=this.data?this.data.entities:this.entities),entities||[]},Usergrid.Response.prototype.getEntity=function(){var entities=this.getEntities();return entities[0]},Usergrid.VERSION=Usergrid.USERGRID_SDK_VERSION="0.11.0",global[name]=Usergrid,global[name].noConflict=function(){return overwrittenName&&(global[name]=overwrittenName),Usergrid},global[name]}(this),function(){var exports,name="Client",global=this,overwrittenName=global[name];return Usergrid.Client=function(options){this.URI=options.URI||"https://api.us
 ergrid.com",options.orgName&&this.set("orgName",options.orgName),options.appName&&this.set("appName",options.appName),options.qs&&this.setObject("default_qs",options.qs),this.buildCurl=options.buildCurl||!1,this.logging=options.logging||!1},Usergrid.Client.prototype.request=function(options,callback){var uri,method=options.method||"GET",endpoint=options.endpoint,body=options.body||{},qs=options.qs||{},mQuery=options.mQuery||!1,orgName=this.get("orgName"),appName=this.get("appName"),default_qs=this.getObject("default_qs");if(!mQuery&&!orgName&&!appName)return logoutCallback();uri=mQuery?this.URI+"/"+endpoint:this.URI+"/"+orgName+"/"+appName+"/"+endpoint,this.getToken()&&(qs.access_token=this.getToken()),default_qs&&(qs=propCopy(qs,default_qs));{var self=this;new Usergrid.Request(method,uri,qs,body,function(err,response){err?doCallback(callback,[err,response,self],self):doCallback(callback,[null,response,self],self)})}},Usergrid.Client.prototype.buildAssetURL=function(uuid){var self=t
 his,qs={},assetURL=this.URI+"/"+this.orgName+"/"+this.appName+"/assets/"+uuid+"/data";self.getToken()&&(qs.access_token=self.getToken());var encoded_params=encodeParams(qs);return encoded_params&&(assetURL+="?"+encoded_params),assetURL},Usergrid.Client.prototype.createGroup=function(options,callback){var group=new Usergrid.Group({path:options.path,client:this,data:options});group.save(function(err,response){doCallback(callback,[err,response,group],group)})},Usergrid.Client.prototype.createEntity=function(options,callback){var entity=new Usergrid.Entity({client:this,data:options});entity.save(function(err,response){doCallback(callback,[err,response,entity],entity)})},Usergrid.Client.prototype.getEntity=function(options,callback){var entity=new Usergrid.Entity({client:this,data:options});entity.fetch(function(err,response){doCallback(callback,[err,response,entity],entity)})},Usergrid.Client.prototype.restoreEntity=function(serializedObject){var data=JSON.parse(serializedObject),option
 s={client:this,data:data},entity=new Usergrid.Entity(options);return entity},Usergrid.Client.prototype.createCounter=function(options,callback){var counter=new Usergrid.Counter({client:this,data:options});counter.save(callback)},Usergrid.Client.prototype.createAsset=function(options,callback){var file=options.file;file&&(options.name=options.name||file.name,options["content-type"]=options["content-type"]||file.type,options.path=options.path||"/",delete options.file);var asset=new Usergrid.Asset({client:this,data:options});asset.save(function(err,response,asset){file&&!err?asset.upload(file,callback):doCallback(callback,[err,response,asset],asset)})},Usergrid.Client.prototype.createCollection=function(options,callback){options.client=this;var collection=new Usergrid.Collection(options);collection.fetch(function(err,response,collection){doCallback(callback,[err,response,collection],this)})},Usergrid.Client.prototype.restoreCollection=function(serializedObject){var data=JSON.parse(seri
 alizedObject);data.client=this;var collection=new Usergrid.Collection(data);return collection},Usergrid.Client.prototype.getFeedForUser=function(username,callback){var options={method:"GET",endpoint:"users/"+username+"/feed"};this.request(options,function(err,data){err?doCallback(callback,[err]):doCallback(callback,[err,data,data.getEntities()])})},Usergrid.Client.prototype.createUserActivity=function(user,options,callback){options.type="users/"+user+"/activities",options={client:this,data:options};var entity=new Usergrid.Entity(options);entity.save(function(err,data){doCallback(callback,[err,data,entity])})},Usergrid.Client.prototype.createUserActivityWithEntity=function(user,content,callback){var username=user.get("username"),options={actor:{displayName:username,uuid:user.get("uuid"),username:username,email:user.get("email"),picture:user.get("picture"),image:{duration:0,height:80,url:user.get("picture"),width:80}},verb:"post",content:content};this.createUserActivity(username,optio
 ns,callback)},Usergrid.Client.prototype.calcTimeDiff=function(){var seconds=0,time=this._end-this._start;try{seconds=(time/10/60).toFixed(2)}catch(e){return 0}return seconds},Usergrid.Client.prototype.setToken=function(token){this.set("token",token)},Usergrid.Client.prototype.getToken=function(){return this.get("token")},Usergrid.Client.prototype.setObject=function(key,value){value&&(value=JSON.stringify(value)),this.set(key,value)},Usergrid.Client.prototype.set=function(key,value){var keyStore="apigee_"+key;this[key]=value,"undefined"!=typeof Storage&&(value?localStorage.setItem(keyStore,value):localStorage.removeItem(keyStore))},Usergrid.Client.prototype.getObject=function(key){return JSON.parse(this.get(key))},Usergrid.Client.prototype.get=function(key){var keyStore="apigee_"+key,value=null;return this[key]?value=this[key]:"undefined"!=typeof Storage&&(value=localStorage.getItem(keyStore)),value},Usergrid.Client.prototype.signup=function(username,password,email,name,callback){var
  options={type:"users",username:username,password:password,email:email,name:name};this.createEntity(options,callback)},Usergrid.Client.prototype.login=function(username,password,callback){var self=this,options={method:"POST",endpoint:"token",body:{username:username,password:password,grant_type:"password"}};self.request(options,function(err,data){var user={};if(err)self.logging&&console.log("error trying to log user in");else{var options={client:self,data:data.user};user=new Usergrid.Entity(options),self.setToken(data.access_token)}doCallback(callback,[err,data,user])})},Usergrid.Client.prototype.reAuthenticateLite=function(callback){var self=this,options={method:"GET",endpoint:"management/me",mQuery:!0};this.request(options,function(err,response){err&&self.logging?console.log("error trying to re-authenticate user"):self.setToken(response.data.access_token),doCallback(callback,[err])})},Usergrid.Client.prototype.reAuthenticate=function(email,callback){var self=this,options={method:"G
 ET",endpoint:"management/users/"+email,mQuery:!0};this.request(options,function(err,response){var data,organizations={},applications={},user={};if(err&&self.logging)console.log("error trying to full authenticate user");else{data=response.data,self.setToken(data.token),self.set("email",data.email),localStorage.setItem("accessToken",data.token),localStorage.setItem("userUUID",data.uuid),localStorage.setItem("userEmail",data.email);var userData={username:data.username,email:data.email,name:data.name,uuid:data.uuid},options={client:self,data:userData};user=new Usergrid.Entity(options),organizations=data.organizations;var org="";try{var existingOrg=self.get("orgName");org=organizations[existingOrg]?organizations[existingOrg]:organizations[Object.keys(organizations)[0]],self.set("orgName",org.name)}catch(e){err=!0,self.logging&&console.log("error selecting org")}applications=self.parseApplicationsArray(org),self.selectFirstApp(applications),self.setObject("organizations",organizations),se
 lf.setObject("applications",applications)}doCallback(callback,[err,data,user,organizations,applications],self)})},Usergrid.Client.prototype.loginFacebook=function(facebookToken,callback){var self=this,options={method:"GET",endpoint:"auth/facebook",qs:{fb_access_token:facebookToken}};this.request(options,function(err,data){var user={};if(err&&self.logging)console.log("error trying to log user in");else{var options={client:self,data:data.user};user=new Usergrid.Entity(options),self.setToken(data.access_token)}doCallback(callback,[err,data,user],self)})},Usergrid.Client.prototype.getLoggedInUser=function(callback){if(this.getToken()){var self=this,options={method:"GET",endpoint:"users/me"};this.request(options,function(err,data){if(err)self.logging&&console.log("error trying to log user in"),doCallback(callback,[err,data,null],self);else{var options={client:self,data:data.entities[0]},user=new Usergrid.Entity(options);doCallback(callback,[null,data,user],self)}})}else callback(!0,null,
 null)},Usergrid.Client.prototype.isLoggedIn=function(){var token=this.getToken();return"undefined"!=typeof token&&null!==token},Usergrid.Client.prototype.logout=function(){this.setToken()},Usergrid.Client.prototype.destroyToken=function(username,token,revokeAll,callback){var options={client:self,method:"PUT"};options.endpoint=revokeAll===!0?"users/"+username+"/revoketokens":null===token?"users/"+username+"/revoketoken?token="+this.getToken():"users/"+username+"/revoketoken?token="+token,this.request(options,function(err,data){err?(self.logging&&console.log("error destroying access token"),doCallback(callback,[err,data,null],self)):(console.log(revokeAll===!0?"all user tokens invalidated":"token invalidated"),doCallback(callback,[err,data,null],self))})},Usergrid.Client.prototype.logoutAndDestroyToken=function(username,token,revokeAll,callback){null===username?console.log("username required to revoke tokens"):(this.destroyToken(username,token,revokeAll,callback),(revokeAll===!0||toke
 n===this.getToken()||null===token)&&this.setToken(null))},Usergrid.Client.prototype.buildCurlCall=function(options){var curl=["curl"],method=(options.method||"GET").toUpperCase(),body=options.body,uri=options.uri;return curl.push("-X"),curl.push(["POST","PUT","DELETE"].indexOf(method)>=0?method:"GET"),curl.push(uri),"object"==typeof body&&Object.keys(body).length>0&&-1!==["POST","PUT"].indexOf(method)&&(curl.push("-d"),curl.push("'"+JSON.stringify(body)+"'")),curl=curl.join(" "),console.log(curl),curl},Usergrid.Client.prototype.getDisplayImage=function(email,picture,size){size=size||50;var image="https://apigee.com/usergrid/images/user_profile.png";try{picture?image=picture:email.length&&(image="https://secure.gravatar.com/avatar/"+MD5(email)+"?s="+size+encodeURI("&d=https://apigee.com/usergrid/images/user_profile.png"))}catch(e){}finally{return image}},global[name]=Usergrid.Client,global[name].noConflict=function(){return overwrittenName&&(global[name]=overwrittenName),exports},glo
 bal[name]}();var ENTITY_SYSTEM_PROPERTIES=["metadata","created","modified","oldpassword","newpassword","type","activated","uuid"];Usergrid.Entity=function(options){this._data={},this._client=void 0,options&&(this.set(options.data||{}),this._client=options.client||{})},Usergrid.Entity.isEntity=function(obj){return obj&&obj instanceof Usergrid.Entity},Usergrid.Entity.isPersistedEntity=function(obj){return isEntity(obj)&&isUUID(obj.get("uuid"))},Usergrid.Entity.prototype.serialize=function(){return JSON.stringify(this._data)},Usergrid.Entity.prototype.get=function(key){var value;if(0===arguments.length?value=this._data:arguments.length>1&&(key=[].slice.call(arguments).reduce(function(p,c){return c instanceof Array?p=p.concat(c):p.push(c),p},[])),key instanceof Array){var self=this;value=key.map(function(k){return self.get(k)})}else"undefined"!=typeof key&&(value=this._data[key]);return value},Usergrid.Entity.prototype.set=function(key,value){if("object"==typeof key)for(var field in key
 )this._data[field]=key[field];else"string"==typeof key?null===value?delete this._data[key]:this._data[key]=value:this._data={}},Usergrid.Entity.prototype.getEndpoint=function(){var name,type=this.get("type"),nameProperties=["uuid","name"];if(void 0===type)throw new UsergridError("cannot fetch entity, no entity type specified","no_type_specified");return/^users?$/.test(type)&&nameProperties.unshift("username"),name=this.get(nameProperties).filter(function(x){return null!==x&&"undefined"!=typeof x}).shift(),name?[type,name].join("/"):type},Usergrid.Entity.prototype.save=function(callback){var self=this,type=this.get("type"),method="POST",entityId=this.get("uuid"),entityData=this.get(),options={method:method,endpoint:type};entityId&&(options.method="PUT",options.endpoint+="/"+entityId),options.body=Object.keys(entityData).filter(function(key){return-1===ENTITY_SYSTEM_PROPERTIES.indexOf(key)}).reduce(function(data,key){return data[key]=entityData[key],data},{}),self._client.request(opti
 ons,function(err,response){var entity=response.getEntity();entity&&(self.set(entity),self.set("type",/^\//.test(response.path)?response.path.substring(1):response.path)),err&&self._client.logging&&console.log("could not save entity"),doCallback(callback,[err,response,self],self)})},Usergrid.Entity.prototype.changePassword=function(oldpassword,password,newpassword,callback){var self=this;if("function"==typeof oldpassword&&void 0===callback&&(callback=oldpassword,oldpassword=self.get("oldpassword"),password=self.get("password"),newpassword=self.get("newpassword")),self.set({password:null,oldpassword:null,newpassword:null}),!(/^users?$/.test(self.get("type"))&&oldpassword&&newpassword))throw new UsergridInvalidArgumentError("Invalid arguments passed to 'changePassword'");var options={method:"PUT",endpoint:"users/"+self.get("uuid")+"/password",body:{uuid:self.get("uuid"),username:self.get("username"),password:password,oldpassword:oldpassword,newpassword:newpassword}};self._client.reques
 t(options,function(err,response){err&&self._client.logging&&console.log("could not update user"),doCallback(callback,[err,response,self],self)})},Usergrid.Entity.prototype.fetch=function(callback){var endpoint,self=this;endpoint=this.getEndpoint();var options={method:"GET",endpoint:endpoint};this._client.request(options,function(err,response){var entity=response.getEntity();entity&&self.set(entity),doCallback(callback,[err,response,self],self)})},Usergrid.Entity.prototype.destroy=function(callback){var self=this,endpoint=this.getEndpoint(),options={method:"DELETE",endpoint:endpoint};this._client.request(options,function(err,response){err||self.set(null),doCallback(callback,[err,response,self],self)})},Usergrid.Entity.prototype.connect=function(connection,entity,callback){this.addOrRemoveConnection("POST",connection,entity,callback)},Usergrid.Entity.prototype.disconnect=function(connection,entity,callback){this.addOrRemoveConnection("DELETE",connection,entity,callback)},Usergrid.Enti
 ty.prototype.addOrRemoveConnection=function(method,connection,entity,callback){var self=this;if(-1==["POST","DELETE"].indexOf(method.toUpperCase()))throw new UsergridInvalidArgumentError("invalid method for connection call. must be 'POST' or 'DELETE'");var connecteeType=entity.get("type"),connectee=this.getEntityId(entity);if(!connectee)throw new UsergridInvalidArgumentError("connectee could not be identified");var connectorType=this.get("type"),connector=this.getEntityId(this);if(!connector)throw new UsergridInvalidArgumentError("connector could not be identified");var endpoint=[connectorType,connector,connection,connecteeType,connectee].join("/"),options={method:method,endpoint:endpoint};this._client.request(options,function(err,response){err&&self._client.logging&&console.log("There was an error with the connection call"),doCallback(callback,[err,response,self],self)})},Usergrid.Entity.prototype.getEntityId=function(entity){var id=!1;return isUUID(entity.get("uuid"))?id=entity.ge
 t("uuid"):"users"===this.get("type")?id=entity.get("username"):entity.get("name")&&(id=entity.get("name")),id},Usergrid.Entity.prototype.getConnections=function(connection,callback){var self=this,connectorType=this.get("type"),connector=this.getEntityId(this);if(connector){var endpoint=connectorType+"/"+connector+"/"+connection+"/",options={method:"GET",endpoint:endpoint};this._client.request(options,function(err,data){err&&self._client.logging&&console.log("entity could not be connected"),self[connection]={};for(var length=data&&data.entities?data.entities.length:0,i=0;length>i;i++)"user"===data.entities[i].type?self[connection][data.entities[i].username]=data.entities[i]:self[connection][data.entities[i].name]=data.entities[i];doCallback(callback,[err,data,data.entities],self)})}else if("function"==typeof callback){var error="Error in getConnections - no uuid specified.";self._client.logging&&console.log(error),doCallback(callback,[!0,error],self)}},Usergrid.Entity.prototype.getGr
 oups=function(callback){var self=this,endpoint="users/"+this.get("uuid")+"/groups",options={method:"GET",endpoint:endpoint};this._client.request(options,function(err,data){err&&self._client.logging&&console.log("entity could not be connected"),self.groups=data.entities,doCallback(callback,[err,data,data.entities],self)})},Usergrid.Entity.prototype.getActivities=function(callback){var self=this,endpoint=this.get("type")+"/"+this.get("uuid")+"/activities",options={method:"GET",endpoint:endpoint};this._client.request(options,function(err,data){err&&self._client.logging&&console.log("entity could not be connected");for(var entity in data.entities)data.entities[entity].createdDate=new Date(data.entities[entity].created).toUTCString();self.activities=data.entities,doCallback(callback,[err,data,data.entities],self)})},Usergrid.Entity.prototype.getFollowing=function(callback){var self=this,endpoint="users/"+this.get("uuid")+"/following",options={method:"GET",endpoint:endpoint};this._client.
 request(options,function(err,data){err&&self._client.logging&&console.log("could not get user following");for(var entity in data.entities){data.entities[entity].createdDate=new Date(data.entities[entity].created).toUTCString();var image=self._client.getDisplayImage(data.entities[entity].email,data.entities[entity].picture);data.entities[entity]._portal_image_icon=image}self.following=data.entities,doCallback(callback,[err,data,data.entities],self)})},Usergrid.Entity.prototype.getFollowers=function(callback){var self=this,endpoint="users/"+this.get("uuid")+"/followers",options={method:"GET",endpoint:endpoint};this._client.request(options,function(err,data){err&&self._client.logging&&console.log("could not get user followers");for(var entity in data.entities){data.entities[entity].createdDate=new Date(data.entities[entity].created).toUTCString();var image=self._client.getDisplayImage(data.entities[entity].email,data.entities[entity].picture);data.entities[entity]._portal_image_icon=im
 age}self.followers=data.entities,doCallback(callback,[err,data,data.entities],self)})},Usergrid.Entity.prototype.getRoles=function(callback){var self=this,endpoint=this.get("type")+"/"+this.get("uuid")+"/roles",options={method:"GET",endpoint:endpoint};this._client.request(options,function(err,data){err&&self._client.logging&&console.log("could not get user roles"),self.roles=data.entities,doCallback(callback,[err,data,data.entities],self)})},Usergrid.Entity.prototype.getPermissions=function(callback){var self=this,endpoint=this.get("type")+"/"+this.get("uuid")+"/permissions",options={method:"GET",endpoint:endpoint};this._client.request(options,function(err,data){err&&self._client.logging&&console.log("could not get user permissions");var permissions=[];if(data.data){var perms=data.data,count=0;for(var i in perms){count++;var perm=perms[i],parts=perm.split(":"),ops_part="",path_part=parts[0];parts.length>1&&(ops_part=parts[0],path_part=parts[1]),ops_part=ops_part.replace("*","get,pos
 t,put,delete");var ops=ops_part.split(","),ops_object={};ops_object.get="no",ops_object.post="no",ops_object.put="no",ops_object.delete="no";for(var j in ops)ops_object[ops[j]]="yes";permissions.push({operations:ops_object,path:path_part,perm:perm})}}self.permissions=permissions,doCallback(callback,[err,data,data.entities],self)})},Usergrid.Collection=function(options){if(options&&(this._client=options.client,this._type=options.type,this.qs=options.qs||{},this._list=options.list||[],this._iterator=options.iterator||-1,this._previous=options.previous||[],this._next=options.next||null,this._cursor=options.cursor||null,options.list))for(var count=options.list.length,i=0;count>i;i++){var entity=this._client.restoreEntity(options.list[i]);this._list[i]=entity}},Usergrid.isCollection=function(obj){return obj&&obj instanceof Usergrid.Collection},Usergrid.Collection.prototype.serialize=function(){var data={};data.type=this._type,data.qs=this.qs,data.iterator=this._iterator,data.previous=thi
 s._previous,data.next=this._next,data.cursor=this._cursor,this.resetEntityPointer();var i=0;for(data.list=[];this.hasNextEntity();){var entity=this.getNextEntity();data.list[i]=entity.serialize(),i++}return data=JSON.stringify(data)},Usergrid.Collection.prototype.fetch=function(callback){var self=this,qs=this.qs;this._cursor?qs.cursor=this._cursor:delete qs.cursor;var options={method:"GET",endpoint:this._type,qs:this.qs};this._client.request(options,function(err,response){err&&self._client.logging?console.log("error getting collection"):(self.saveCursor(response.cursor||null),self.resetEntityPointer(),self._list=response.getEntities().filter(function(entity){return isUUID(entity.uuid)}).map(function(entity){var ent=new Usergrid.Entity({client:self._client});return ent.set(entity),ent.type=self._type,ent})),doCallback(callback,[err,response,self],self)})},Usergrid.Collection.prototype.addEntity=function(entityObject,callback){var self=this;entityObject.type=this._type,this._client.cr
 eateEntity(entityObject,function(err,response,entity){err||self.addExistingEntity(entity),doCallback(callback,[err,response,self],self)
+function extend(subClass,superClass){var F=function(){};return F.prototype=superClass.prototype,subClass.prototype=new F,subClass.prototype.constructor=subClass,subClass.superclass=superClass.prototype,superClass.prototype.constructor==Object.prototype.constructor&&(superClass.prototype.constructor=superClass),subClass}function propCopy(from,to){for(var prop in from)from.hasOwnProperty(prop)&&(to[prop]="object"==typeof from[prop]&&"object"==typeof to[prop]?propCopy(from[prop],to[prop]):from[prop]);return to}function NOOP(){}function isValidUrl(url){if(!url)return!1;var doc,base,anchor,isValid=!1;try{doc=document.implementation.createHTMLDocument(""),base=doc.createElement("base"),base.href=base||window.lo,doc.head.appendChild(base),anchor=doc.createElement("a"),anchor.href=url,doc.body.appendChild(anchor),isValid=!(""===anchor.href)}catch(e){console.error(e)}finally{return doc.head.removeChild(base),doc.body.removeChild(anchor),base=null,anchor=null,doc=null,isValid}}function isUUID
 (uuid){return uuid?uuidValueRegex.test(uuid):!1}function encodeParams(params){var queryString;return params&&Object.keys(params)&&(queryString=[].slice.call(arguments).reduce(function(a,b){return a.concat(b instanceof Array?b:[b])},[]).filter(function(c){return"object"==typeof c}).reduce(function(p,c){return c instanceof Array?p.push(c):p=p.concat(Object.keys(c).map(function(key){return[key,c[key]]})),p},[]).reduce(function(p,c){return 2===c.length?p.push(c):p=p.concat(c),p},[]).reduce(function(p,c){return c[1]instanceof Array?c[1].forEach(function(v){p.push([c[0],v])}):p.push(c),p},[]).map(function(c){return c[1]=encodeURIComponent(c[1]),c.join("=")}).join("&")),queryString}function isFunction(f){return f&&null!==f&&"function"==typeof f}function doCallback(callback,params,context){var returnValue;return isFunction(callback)&&(params||(params=[]),context||(context=this),params.push(context),returnValue=callback.apply(context,params)),returnValue}function getSafeTime(prop){var time;s
 witch(typeof prop){case"undefined":time=Date.now();break;case"number":time=prop;break;case"string":time=isNaN(prop)?Date.parse(prop):parseInt(prop);break;default:time=Date.parse(prop.toString())}return time}var UsergridEventable=function(){throw Error("'UsergridEventable' is not intended to be invoked directly")};UsergridEventable.prototype={bind:function(event,fn){this._events=this._events||{},this._events[event]=this._events[event]||[],this._events[event].push(fn)},unbind:function(event,fn){this._events=this._events||{},event in this._events!=!1&&this._events[event].splice(this._events[event].indexOf(fn),1)},trigger:function(event){if(this._events=this._events||{},event in this._events!=!1)for(var i=0;i<this._events[event].length;i++)this._events[event][i].apply(this,Array.prototype.slice.call(arguments,1))}},UsergridEventable.mixin=function(destObject){for(var props=["bind","unbind","trigger"],i=0;i<props.length;i++)props[i]in destObject.prototype&&(console.warn("overwriting '"+p
 rops[i]+"' on '"+destObject.name+"'."),console.warn("the previous version can be found at '_"+props[i]+"' on '"+destObject.name+"'."),destObject.prototype["_"+props[i]]=destObject.prototype[props[i]]),destObject.prototype[props[i]]=UsergridEventable.prototype[props[i]]},function(){function Logger(name){this.logEnabled=!0,this.init(name,!0)}var name="Logger",global=this,overwrittenName=global[name];return Logger.METHODS=["log","error","warn","info","debug","assert","clear","count","dir","dirxml","exception","group","groupCollapsed","groupEnd","profile","profileEnd","table","time","timeEnd","trace"],Logger.prototype.init=function(name,logEnabled){this.name=name||"UNKNOWN",this.logEnabled=logEnabled||!0;var addMethod=function(method){this[method]=this.createLogMethod(method)}.bind(this);Logger.METHODS.forEach(addMethod)},Logger.prototype.createLogMethod=function(method){return Logger.prototype.log.bind(this,method)},Logger.prototype.prefix=function(method,args){var prepend="["+method.t
 oUpperCase()+"]["+name+"]:	";return-1!==["log","error","warn","info"].indexOf(method)&&("string"==typeof args[0]?args[0]=prepend+args[0]:args.unshift(prepend)),args},Logger.prototype.log=function(){var args=[].slice.call(arguments);method=args.shift(),-1===Logger.METHODS.indexOf(method)&&(method="log"),this.logEnabled&&console&&console[method]&&(args=this.prefix(method,args),console[method].apply(console,args))},Logger.prototype.setLogEnabled=function(logEnabled){this.logEnabled=logEnabled||!0},Logger.mixin=function(destObject){destObject.__logger=new Logger(destObject.name||"UNKNOWN");var addMethod=function(method){method in destObject.prototype&&(console.warn("overwriting '"+method+"' on '"+destObject.name+"'."),console.warn("the previous version can be found at '_"+method+"' on '"+destObject.name+"'."),destObject.prototype["_"+method]=destObject.prototype[method]),destObject.prototype[method]=destObject.__logger.createLogMethod(method)};Logger.METHODS.forEach(addMethod)},global[n
 ame]=Logger,global[name].noConflict=function(){return overwrittenName&&(global[name]=overwrittenName),Logger},global[name]}(),function(global){function Promise(){this.complete=!1,this.error=null,this.result=null,this.callbacks=[]}var name="Promise",overwrittenName=global[name];return Promise.prototype.then=function(callback,context){var f=function(){return callback.apply(context,arguments)};this.complete?f(this.error,this.result):this.callbacks.push(f)},Promise.prototype.done=function(error,result){if(this.complete=!0,this.error=error,this.result=result,this.callbacks){for(var i=0;i<this.callbacks.length;i++)this.callbacks[i](error,result);this.callbacks.length=0}},Promise.join=function(promises){function notifier(i){return function(error,result){completed+=1,errors[i]=error,results[i]=result,completed===total&&p.done(errors,results)}}for(var p=new Promise,total=promises.length,completed=0,errors=[],results=[],i=0;total>i;i++)promises[i]().then(notifier(i));return p},Promise.chain=f
 unction(promises,error,result){var p=new Promise;return null===promises||0===promises.length?p.done(error,result):promises[0](error,result).then(function(res,err){promises.splice(0,1),promises?Promise.chain(promises,res,err).then(function(r,e){p.done(r,e)}):p.done(res,err)}),p},global[name]=Promise,global[name].noConflict=function(){return overwrittenName&&(global[name]=overwrittenName),Promise},global[name]}(this),function(){function partial(){var args=Array.prototype.slice.call(arguments),fn=args.shift();return fn.bind(this,args)}function Ajax(){function encode(data){var result="";if("string"==typeof data)result=data;else{var e=encodeURIComponent;for(var i in data)data.hasOwnProperty(i)&&(result+="&"+e(i)+"="+e(data[i]))}return result}function request(m,u,d){var timeout,p=new Promise;return self.logger.time(m+" "+u),function(xhr){xhr.onreadystatechange=function(){4===this.readyState&&(self.logger.timeEnd(m+" "+u),clearTimeout(timeout),p.done(null,this))},xhr.onerror=function(respo
 nse){clearTimeout(timeout),p.done(response,null)},xhr.oncomplete=function(){clearTimeout(timeout),self.logger.timeEnd(m+" "+u),self.info("%s request to %s returned %s",m,u,this.status)},xhr.open(m,u),d&&("object"==typeof d&&(d=JSON.stringify(d)),xhr.setRequestHeader("Content-Type","application/json"),xhr.setRequestHeader("Accept","application/json")),timeout=setTimeout(function(){xhr.abort(),p.done("API Call timed out.",null)},3e4),xhr.send(encode(d))}(new XMLHttpRequest),p}this.logger=new global.Logger(name);var self=this;this.request=request,this.get=partial(request,"GET"),this.post=partial(request,"POST"),this.put=partial(request,"PUT"),this.delete=partial(request,"DELETE")}var exports,name="Ajax",global=this,overwrittenName=global[name];return global[name]=new Ajax,global[name].noConflict=function(){return overwrittenName&&(global[name]=overwrittenName),exports},global[name]}(),window.console=window.console||{},window.console.log=window.console.log||function(){};var uuidValueReg
 ex=/^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/;!function(global){function Usergrid(){this.logger=new Logger(name)}var name="Usergrid",overwrittenName=global[name],VALID_REQUEST_METHODS=["GET","POST","PUT","DELETE"];return Usergrid.isValidEndpoint=function(){return!0},Usergrid.Request=function(method,endpoint,query_params,data,callback){var p=new Promise;if(this.logger=new global.Logger("Usergrid.Request"),this.logger.time("process request "+method+" "+endpoint),this.endpoint=endpoint+"?"+encodeParams(query_params),this.method=method.toUpperCase(),this.data="object"==typeof data?JSON.stringify(data):data,-1===VALID_REQUEST_METHODS.indexOf(this.method))throw new UsergridInvalidHTTPMethodError("invalid request method '"+this.method+"'");if(!isValidUrl(this.endpoint))throw this.logger.error(endpoint,this.endpoint,/^https:\/\//.test(endpoint)),new UsergridInvalidURIError("The provided endpoint is not valid: "+this.endpoint);var request=function(){retur
 n Ajax.request(this.method,this.endpoint,this.data)}.bind(this),response=function(err,request){return new Usergrid.Response(err,request)}.bind(this),oncomplete=function(err,response){p.done(err,response),this.logger.info("REQUEST",err,response),doCallback(callback,[err,response]),this.logger.timeEnd("process request "+method+" "+endpoint)}.bind(this);return Promise.chain([request,response]).then(oncomplete),p},Usergrid.Response=function(err,response){var p=new Promise,data=null;try{data=JSON.parse(response.responseText)}catch(e){data={}}switch(Object.keys(data).forEach(function(key){Object.defineProperty(this,key,{value:data[key],enumerable:!0})}.bind(this)),Object.defineProperty(this,"logger",{enumerable:!1,configurable:!1,writable:!1,value:new global.Logger(name)}),Object.defineProperty(this,"success",{enumerable:!1,configurable:!1,writable:!0,value:!0}),Object.defineProperty(this,"err",{enumerable:!1,configurable:!1,writable:!0,value:err}),Object.defineProperty(this,"status",{enu
 merable:!1,configurable:!1,writable:!0,value:parseInt(response.status)}),Object.defineProperty(this,"statusGroup",{enumerable:!1,configurable:!1,writable:!0,value:this.status-this.status%100}),this.statusGroup){case 200:this.success=!0;break;case 400:case 500:case 300:case 100:default:this.success=!1}return this.success?p.done(null,this):p.done(UsergridError.fromResponse(data),this),p},Usergrid.Response.prototype.getEntities=function(){var entities;return this.success&&(entities=this.data?this.data.entities:this.entities),entities||[]},Usergrid.Response.prototype.getEntity=function(){var entities=this.getEntities();return entities[0]},Usergrid.VERSION=Usergrid.USERGRID_SDK_VERSION="0.11.0",global[name]=Usergrid,global[name].noConflict=function(){return overwrittenName&&(global[name]=overwrittenName),Usergrid},global[name]}(this),function(){var exports,name="Client",global=this,overwrittenName=global[name];return Usergrid.Client=function(options){this.URI=options.URI||"https://api.us
 ergrid.com",options.orgName&&this.set("orgName",options.orgName),options.appName&&this.set("appName",options.appName),options.qs&&this.setObject("default_qs",options.qs),this.buildCurl=options.buildCurl||!1,this.logging=options.logging||!1},Usergrid.Client.prototype.request=function(options,callback){var uri,method=options.method||"GET",endpoint=options.endpoint,body=options.body||{},qs=options.qs||{},mQuery=options.mQuery||!1,orgName=this.get("orgName"),appName=this.get("appName"),default_qs=this.getObject("default_qs");if(!mQuery&&!orgName&&!appName)return logoutCallback();uri=mQuery?this.URI+"/"+endpoint:this.URI+"/"+orgName+"/"+appName+"/"+endpoint,this.getToken()&&(qs.access_token=this.getToken()),default_qs&&(qs=propCopy(qs,default_qs));{var self=this;new Usergrid.Request(method,uri,qs,body,function(err,response){err?doCallback(callback,[err,response,self],self):doCallback(callback,[null,response,self],self)})}},Usergrid.Client.prototype.buildAssetURL=function(uuid){var self=t
 his,qs={},assetURL=this.URI+"/"+this.orgName+"/"+this.appName+"/assets/"+uuid+"/data";self.getToken()&&(qs.access_token=self.getToken());var encoded_params=encodeParams(qs);return encoded_params&&(assetURL+="?"+encoded_params),assetURL},Usergrid.Client.prototype.createGroup=function(options,callback){var group=new Usergrid.Group({path:options.path,client:this,data:options});group.save(function(err,response){doCallback(callback,[err,response,group],group)})},Usergrid.Client.prototype.createEntity=function(options,callback){var entity=new Usergrid.Entity({client:this,data:options});entity.save(function(err,response){doCallback(callback,[err,response,entity],entity)})},Usergrid.Client.prototype.getEntity=function(options,callback){var entity=new Usergrid.Entity({client:this,data:options});entity.fetch(function(err,response){doCallback(callback,[err,response,entity],entity)})},Usergrid.Client.prototype.restoreEntity=function(serializedObject){var data=JSON.parse(serializedObject),option
 s={client:this,data:data},entity=new Usergrid.Entity(options);return entity},Usergrid.Client.prototype.createCounter=function(options,callback){var counter=new Usergrid.Counter({client:this,data:options});counter.save(callback)},Usergrid.Client.prototype.createAsset=function(options,callback){var file=options.file;file&&(options.name=options.name||file.name,options["content-type"]=options["content-type"]||file.type,options.path=options.path||"/",delete options.file);var asset=new Usergrid.Asset({client:this,data:options});asset.save(function(err,response,asset){file&&!err?asset.upload(file,callback):doCallback(callback,[err,response,asset],asset)})},Usergrid.Client.prototype.createCollection=function(options,callback){options.client=this;var collection=new Usergrid.Collection(options);collection.fetch(function(err,response,collection){doCallback(callback,[err,response,collection],this)})},Usergrid.Client.prototype.restoreCollection=function(serializedObject){var data=JSON.parse(seri
 alizedObject);data.client=this;var collection=new Usergrid.Collection(data);return collection},Usergrid.Client.prototype.getFeedForUser=function(username,callback){var options={method:"GET",endpoint:"users/"+username+"/feed"};this.request(options,function(err,data){err?doCallback(callback,[err]):doCallback(callback,[err,data,data.getEntities()])})},Usergrid.Client.prototype.createUserActivity=function(user,options,callback){options.type="users/"+user+"/activities",options={client:this,data:options};var entity=new Usergrid.Entity(options);entity.save(function(err,data){doCallback(callback,[err,data,entity])})},Usergrid.Client.prototype.createUserActivityWithEntity=function(user,content,callback){var username=user.get("username"),options={actor:{displayName:username,uuid:user.get("uuid"),username:username,email:user.get("email"),picture:user.get("picture"),image:{duration:0,height:80,url:user.get("picture"),width:80}},verb:"post",content:content};this.createUserActivity(username,optio
 ns,callback)},Usergrid.Client.prototype.calcTimeDiff=function(){var seconds=0,time=this._end-this._start;try{seconds=(time/10/60).toFixed(2)}catch(e){return 0}return seconds},Usergrid.Client.prototype.setToken=function(token){this.set("token",token)},Usergrid.Client.prototype.getToken=function(){return this.get("token")},Usergrid.Client.prototype.setObject=function(key,value){value&&(value=JSON.stringify(value)),this.set(key,value)},Usergrid.Client.prototype.set=function(key,value){var keyStore="apigee_"+key;this[key]=value,"undefined"!=typeof Storage&&(value?localStorage.setItem(keyStore,value):localStorage.removeItem(keyStore))},Usergrid.Client.prototype.getObject=function(key){return JSON.parse(this.get(key))},Usergrid.Client.prototype.get=function(key){var keyStore="apigee_"+key,value=null;return this[key]?value=this[key]:"undefined"!=typeof Storage&&(value=localStorage.getItem(keyStore)),value},Usergrid.Client.prototype.signup=function(username,password,email,name,callback){var
  options={type:"users",username:username,password:password,email:email,name:name};this.createEntity(options,callback)},Usergrid.Client.prototype.login=function(username,password,callback){var self=this,options={method:"POST",endpoint:"token",body:{username:username,password:password,grant_type:"password"}};self.request(options,function(err,response){var user={};if(err)self.logging&&console.log("error trying to log user in");else{var options={client:self,data:response.user};user=new Usergrid.Entity(options),self.setToken(response.access_token)}doCallback(callback,[err,response,user])})},Usergrid.Client.prototype.reAuthenticateLite=function(callback){var self=this,options={method:"GET",endpoint:"management/me",mQuery:!0};this.request(options,function(err,response){err&&self.logging?console.log("error trying to re-authenticate user"):self.setToken(response.data.access_token),doCallback(callback,[err])})},Usergrid.Client.prototype.reAuthenticate=function(email,callback){var self=this,op
 tions={method:"GET",endpoint:"management/users/"+email,mQuery:!0};this.request(options,function(err,response){var data,organizations={},applications={},user={};if(err&&self.logging)console.log("error trying to full authenticate user");else{data=response.data,self.setToken(data.token),self.set("email",data.email),localStorage.setItem("accessToken",data.token),localStorage.setItem("userUUID",data.uuid),localStorage.setItem("userEmail",data.email);var userData={username:data.username,email:data.email,name:data.name,uuid:data.uuid},options={client:self,data:userData};user=new Usergrid.Entity(options),organizations=data.organizations;var org="";try{var existingOrg=self.get("orgName");org=organizations[existingOrg]?organizations[existingOrg]:organizations[Object.keys(organizations)[0]],self.set("orgName",org.name)}catch(e){err=!0,self.logging&&console.log("error selecting org")}applications=self.parseApplicationsArray(org),self.selectFirstApp(applications),self.setObject("organizations",o
 rganizations),self.setObject("applications",applications)}doCallback(callback,[err,data,user,organizations,applications],self)})},Usergrid.Client.prototype.loginFacebook=function(facebookToken,callback){var self=this,options={method:"GET",endpoint:"auth/facebook",qs:{fb_access_token:facebookToken}};this.request(options,function(err,data){var user={};if(err&&self.logging)console.log("error trying to log user in");else{var options={client:self,data:data.user};user=new Usergrid.Entity(options),self.setToken(data.access_token)}doCallback(callback,[err,data,user],self)})},Usergrid.Client.prototype.getLoggedInUser=function(callback){var self=this;if(this.getToken()){var options={method:"GET",endpoint:"users/me"};this.request(options,function(err,response){if(err)self.logging&&console.log("error trying to log user in"),console.error(err,response),doCallback(callback,[err,response,self],self);else{var options={client:self,data:response.getEntity()},user=new Usergrid.Entity(options);doCallba
 ck(callback,[null,response,user],self)}})}else doCallback(callback,[new UsergridError("Access Token not set"),null,self],self)},Usergrid.Client.prototype.isLoggedIn=function(){var token=this.getToken();return"undefined"!=typeof token&&null!==token},Usergrid.Client.prototype.logout=function(){this.setToken()},Usergrid.Client.prototype.destroyToken=function(username,token,revokeAll,callback){var options={client:self,method:"PUT"};options.endpoint=revokeAll===!0?"users/"+username+"/revoketokens":null===token?"users/"+username+"/revoketoken?token="+this.getToken():"users/"+username+"/revoketoken?token="+token,this.request(options,function(err,data){err?(self.logging&&console.log("error destroying access token"),doCallback(callback,[err,data,null],self)):(console.log(revokeAll===!0?"all user tokens invalidated":"token invalidated"),doCallback(callback,[err,data,null],self))})},Usergrid.Client.prototype.logoutAndDestroyToken=function(username,token,revokeAll,callback){null===username?cons
 ole.log("username required to revoke tokens"):(this.destroyToken(username,token,revokeAll,callback),(revokeAll===!0||token===this.getToken()||null===token)&&this.setToken(null))},Usergrid.Client.prototype.buildCurlCall=function(options){var curl=["curl"],method=(options.method||"GET").toUpperCase(),body=options.body,uri=options.uri;return curl.push("-X"),curl.push(["POST","PUT","DELETE"].indexOf(method)>=0?method:"GET"),curl.push(uri),"object"==typeof body&&Object.keys(body).length>0&&-1!==["POST","PUT"].indexOf(method)&&(curl.push("-d"),curl.push("'"+JSON.stringify(body)+"'")),curl=curl.join(" "),console.log(curl),curl},Usergrid.Client.prototype.getDisplayImage=function(email,picture,size){size=size||50;var image="https://apigee.com/usergrid/images/user_profile.png";try{picture?image=picture:email.length&&(image="https://secure.gravatar.com/avatar/"+MD5(email)+"?s="+size+encodeURI("&d=https://apigee.com/usergrid/images/user_profile.png"))}catch(e){}finally{return image}},global[nam
 e]=Usergrid.Client,global[name].noConflict=function(){return overwrittenName&&(global[name]=overwrittenName),exports},global[name]}();var ENTITY_SYSTEM_PROPERTIES=["metadata","created","modified","oldpassword","newpassword","type","activated","uuid"];Usergrid.Entity=function(options){this._data={},this._client=void 0,options&&(this.set(options.data||{}),this._client=options.client||{})},Usergrid.Entity.isEntity=function(obj){return obj&&obj instanceof Usergrid.Entity},Usergrid.Entity.isPersistedEntity=function(obj){return isEntity(obj)&&isUUID(obj.get("uuid"))},Usergrid.Entity.prototype.serialize=function(){return JSON.stringify(this._data)},Usergrid.Entity.prototype.get=function(key){var value;if(0===arguments.length?value=this._data:arguments.length>1&&(key=[].slice.call(arguments).reduce(function(p,c){return c instanceof Array?p=p.concat(c):p.push(c),p},[])),key instanceof Array){var self=this;value=key.map(function(k){return self.get(k)})}else"undefined"!=typeof key&&(value=this
 ._data[key]);return value},Usergrid.Entity.prototype.set=function(key,value){if("object"==typeof key)for(var field in key)this._data[field]=key[field];else"string"==typeof key?null===value?delete this._data[key]:this._data[key]=value:this._data={}},Usergrid.Entity.prototype.getEndpoint=function(){var name,type=this.get("type"),nameProperties=["uuid","name"];if(void 0===type)throw new UsergridError("cannot fetch entity, no entity type specified","no_type_specified");return/^users?$/.test(type)&&nameProperties.unshift("username"),name=this.get(nameProperties).filter(function(x){return null!==x&&"undefined"!=typeof x}).shift(),name?[type,name].join("/"):type},Usergrid.Entity.prototype.save=function(callback){var self=this,type=this.get("type"),method="POST",entityId=this.get("uuid"),entityData=this.get(),options={method:method,endpoint:type};entityId&&(options.method="PUT",options.endpoint+="/"+entityId),options.body=Object.keys(entityData).filter(function(key){return-1===ENTITY_SYSTEM
 _PROPERTIES.indexOf(key)}).reduce(function(data,key){return data[key]=entityData[key],data},{}),self._client.request(options,function(err,response){var entity=response.getEntity();entity&&(self.set(entity),self.set("type",/^\//.test(response.path)?response.path.substring(1):response.path)),err&&self._client.logging&&console.log("could not save entity"),doCallback(callback,[err,response,self],self)})},Usergrid.Entity.prototype.changePassword=function(oldpassword,password,newpassword,callback){var self=this;if("function"==typeof oldpassword&&void 0===callback&&(callback=oldpassword,oldpassword=self.get("oldpassword"),password=self.get("password"),newpassword=self.get("newpassword")),self.set({password:null,oldpassword:null,newpassword:null}),!(/^users?$/.test(self.get("type"))&&oldpassword&&newpassword))throw new UsergridInvalidArgumentError("Invalid arguments passed to 'changePassword'");var options={method:"PUT",endpoint:"users/"+self.get("uuid")+"/password",body:{uuid:self.get("uui
 d"),username:self.get("username"),password:password,oldpassword:oldpassword,newpassword:newpassword}};self._client.request(options,function(err,response){err&&self._client.logging&&console.log("could not update user"),doCallback(callback,[err,response,self],self)})},Usergrid.Entity.prototype.fetch=function(callback){var endpoint,self=this;endpoint=this.getEndpoint();var options={method:"GET",endpoint:endpoint};this._client.request(options,function(err,response){var entity=response.getEntity();entity&&self.set(entity),doCallback(callback,[err,response,self],self)})},Usergrid.Entity.prototype.destroy=function(callback){var self=this,endpoint=this.getEndpoint(),options={method:"DELETE",endpoint:endpoint};this._client.request(options,function(err,response){err||self.set(null),doCallback(callback,[err,response,self],self)})},Usergrid.Entity.prototype.connect=function(connection,entity,callback){this.addOrRemoveConnection("POST",connection,entity,callback)},Usergrid.Entity.prototype.disco
 nnect=function(connection,entity,callback){this.addOrRemoveConnection("DELETE",connection,entity,callback)},Usergrid.Entity.prototype.addOrRemoveConnection=function(method,connection,entity,callback){var self=this;if(-1==["POST","DELETE"].indexOf(method.toUpperCase()))throw new UsergridInvalidArgumentError("invalid method for connection call. must be 'POST' or 'DELETE'");var connecteeType=entity.get("type"),connectee=this.getEntityId(entity);if(!connectee)throw new UsergridInvalidArgumentError("connectee could not be identified");var connectorType=this.get("type"),connector=this.getEntityId(this);if(!connector)throw new UsergridInvalidArgumentError("connector could not be identified");var endpoint=[connectorType,connector,connection,connecteeType,connectee].join("/"),options={method:method,endpoint:endpoint};this._client.request(options,function(err,response){err&&self._client.logging&&console.log("There was an error with the connection call"),doCallback(callback,[err,response,self]
 ,self)})},Usergrid.Entity.prototype.getEntityId=function(entity){var id;return id=entity.get(isUUID(entity.get("uuid"))?"uuid":"users"===this.get("type")?"username":"name")},Usergrid.Entity.prototype.getConnections=function(connection,callback){var self=this,connectorType=this.get("type"),connector=this.getEntityId(this);if(connector){var endpoint=connectorType+"/"+connector+"/"+connection+"/",options={method:"GET",endpoint:endpoint};this._client.request(options,function(err,data){err&&self._client.logging&&console.log("entity could not be connected"),self[connection]={};for(var length=data&&data.entities?data.entities.length:0,i=0;length>i;i++)"user"===data.entities[i].type?self[connection][data.entities[i].username]=data.entities[i]:self[connection][data.entities[i].name]=data.entities[i];doCallback(callback,[err,data,data.entities],self)})}else if("function"==typeof callback){var error="Error in getConnections - no uuid specified.";self._client.logging&&console.log(error),doCallb
 ack(callback,[!0,error],self)}},Usergrid.Entity.prototype.getGroups=function(callback){var self=this,endpoint="users/"+this.get("uuid")+"/groups",options={method:"GET",endpoint:endpoint};this._client.request(options,function(err,data){err&&self._client.logging&&console.log("entity could not be connected"),self.groups=data.entities,doCallback(callback,[err,data,data.entities],self)})},Usergrid.Entity.prototype.getActivities=function(callback){var self=this,endpoint=this.get("type")+"/"+this.get("uuid")+"/activities",options={method:"GET",endpoint:endpoint};this._client.request(options,function(err,data){err&&self._client.logging&&console.log("entity could not be connected");for(var entity in data.entities)data.entities[entity].createdDate=new Date(data.entities[entity].created).toUTCString();self.activities=data.entities,doCallback(callback,[err,data,data.entities],self)})},Usergrid.Entity.prototype.getFollowing=function(callback){var self=this,endpoint="users/"+this.get("uuid")+"/fo
 llowing",options={method:"GET",endpoint:endpoint};this._client.request(options,function(err,data){err&&self._client.logging&&console.log("could not get user following");for(var entity in data.entities){data.entities[entity].createdDate=new Date(data.entities[entity].created).toUTCString();var image=self._client.getDisplayImage(data.entities[entity].email,data.entities[entity].picture);data.entities[entity]._portal_image_icon=image}self.following=data.entities,doCallback(callback,[err,data,data.entities],self)})},Usergrid.Entity.prototype.getFollowers=function(callback){var self=this,endpoint="users/"+this.get("uuid")+"/followers",options={method:"GET",endpoint:endpoint};this._client.request(options,function(err,data){err&&self._client.logging&&console.log("could not get user followers");for(var entity in data.entities){data.entities[entity].createdDate=new Date(data.entities[entity].created).toUTCString();var image=self._client.getDisplayImage(data.entities[entity].email,data.entiti
 es[entity].picture);data.entities[entity]._portal_image_icon=image}self.followers=data.entities,doCallback(callback,[err,data,data.entities],self)})},Usergrid.Entity.prototype.getRoles=function(callback){var self=this,endpoint=this.get("type")+"/"+this.get("uuid")+"/roles",options={method:"GET",endpoint:endpoint};this._client.request(options,function(err,data){err&&self._client.logging&&console.log("could not get user roles"),self.roles=data.entities,doCallback(callback,[err,data,data.entities],self)})},Usergrid.Entity.prototype.getPermissions=function(callback){var self=this,endpoint=this.get("type")+"/"+this.get("uuid")+"/permissions",options={method:"GET",endpoint:endpoint};this._client.request(options,function(err,data){err&&self._client.logging&&console.log("could not get user permissions");var permissions=[];if(data.data){var perms=data.data,count=0;for(var i in perms){count++;var perm=perms[i],parts=perm.split(":"),ops_part="",path_part=parts[0];parts.length>1&&(ops_part=part
 s[0],path_part=parts[1]),ops_part=ops_part.replace("*","get,post,put,delete");var ops=ops_part.split(","),ops_object={};ops_object.get="no",ops_object.post="no",ops_object.put="no",ops_object.delete="no";for(var j in ops)ops_object[ops[j]]="yes";permissions.push({operations:ops_object,path:path_part,perm:perm})}}self.permissions=permissions,doCallback(callback,[err,data,data.entities],self)})},Usergrid.Collection=function(options){if(options&&(this._client=options.client,this._type=options.type,this.qs=options.qs||{},this._list=options.list||[],this._iterator=options.iterator||-1,this._previous=options.previous||[],this._next=options.next||null,this._cursor=options.cursor||null,options.list))for(var count=options.list.length,i=0;count>i;i++){var entity=this._client.restoreEntity(options.list[i]);this._list[i]=entity}},Usergrid.isCollection=function(obj){return obj&&obj instanceof Usergrid.Collection},Usergrid.Collection.prototype.serialize=function(){var data={};data.type=this._type
 ,data.qs=this.qs,data.iterator=this._iterator,data.previous=this._previous,data.next=this._next,data.cursor=this._cursor,this.resetEntityPointer();var i=0;for(data.list=[];this.hasNextEntity();){var entity=this.getNextEntity();data.list[i]=entity.serialize(),i++}return data=JSON.stringify(data)},Usergrid.Collection.prototype.fetch=function(callback){var self=this,qs=this.qs;this._cursor?qs.cursor=this._cursor:delete qs.cursor;var options={method:"GET",endpoint:this._type,qs:this.qs};this._client.request(options,function(err,response){err&&self._client.logging?console.log("error getting collection"):(self.saveCursor(response.cursor||null),self.resetEntityPointer(),self._list=response.getEntities().filter(function(entity){return isUUID(entity.uuid)}).map(function(entity){var ent=new Usergrid.Entity({client:self._client});return ent.set(entity),ent.type=self._type,ent})),doCallback(callback,[err,response,self],self)})},Usergrid.Collection.prototype.addEntity=function(entityObject,callb
 ack){var self=this;entityObject.type=this._type,this._client.createEntity(entityObject,function(err,response,entity){err||self.addExistingEntity(entity),doCallback(callback,[err,response,self],self)
 })},Usergrid.Collection.prototype.addExistingEntity=function(entity){var count=this._list.length;this._list[count]=entity},Usergrid.Collection.prototype.destroyEntity=function(entity,callback){var self=this;entity.destroy(function(err,response){err?(self._client.logging&&console.log("could not destroy entity"),doCallback(callback,[err,response,self],self)):self.fetch(callback),self.removeEntity(entity)})},Usergrid.Collection.prototype.getEntitiesByCriteria=function(criteria){return this._list.filter(criteria)},Usergrid.Collection.prototype.getEntityByCriteria=function(criteria){return this.getEntitiesByCriteria(criteria).shift()},Usergrid.Collection.prototype.removeEntity=function(entity){var removedEntity=this.getEntityByCriteria(function(item){return entity.uuid===item.get("uuid")});return delete this._list[this._list.indexOf(removedEntity)],removedEntity},Usergrid.Collection.prototype.getEntityByUUID=function(uuid,callback){var entity=this.getEntityByCriteria(function(item){retur
 n item.get("uuid")===uuid});if(entity)doCallback(callback,[null,entity,entity],this);else{var options={data:{type:this._type,uuid:uuid},client:this._client};entity=new Usergrid.Entity(options),entity.fetch(callback)}},Usergrid.Collection.prototype.getFirstEntity=function(){var count=this._list.length;return count>0?this._list[0]:null},Usergrid.Collection.prototype.getLastEntity=function(){var count=this._list.length;return count>0?this._list[count-1]:null},Usergrid.Collection.prototype.hasNextEntity=function(){var next=this._iterator+1,hasNextElement=next>=0&&next<this._list.length;return hasNextElement?!0:!1},Usergrid.Collection.prototype.getNextEntity=function(){this._iterator++;var hasNextElement=this._iterator>=0&&this._iterator<=this._list.length;return hasNextElement?this._list[this._iterator]:!1},Usergrid.Collection.prototype.hasPrevEntity=function(){var previous=this._iterator-1,hasPreviousElement=previous>=0&&previous<this._list.length;return hasPreviousElement?!0:!1},Userg
 rid.Collection.prototype.getPrevEntity=function(){this._iterator--;var hasPreviousElement=this._iterator>=0&&this._iterator<=this._list.length;return hasPreviousElement?this._list[this._iterator]:!1},Usergrid.Collection.prototype.resetEntityPointer=function(){this._iterator=-1},Usergrid.Collection.prototype.saveCursor=function(cursor){this._next!==cursor&&(this._next=cursor)},Usergrid.Collection.prototype.resetPaging=function(){this._previous=[],this._next=null,this._cursor=null},Usergrid.Collection.prototype.hasNextPage=function(){return this._next},Usergrid.Collection.prototype.getNextPage=function(callback){this.hasNextPage()&&(this._previous.push(this._cursor),this._cursor=this._next,this._list=[],this.fetch(callback))},Usergrid.Collection.prototype.hasPreviousPage=function(){return this._previous.length>0},Usergrid.Collection.prototype.getPreviousPage=function(callback){this.hasPreviousPage()&&(this._next=null,this._cursor=this._previous.pop(),this._list=[],this.fetch(callback)
 )},Usergrid.Group=function(options){this._path=options.path,this._list=[],this._client=options.client,this._data=options.data||{},this._data.type="groups"},Usergrid.Group.prototype=new Usergrid.Entity,Usergrid.Group.prototype.fetch=function(callback){var self=this,groupEndpoint="groups/"+this._path,memberEndpoint="groups/"+this._path+"/users",groupOptions={method:"GET",endpoint:groupEndpoint},memberOptions={method:"GET",endpoint:memberEndpoint};this._client.request(groupOptions,function(err,response){if(err)self._client.logging&&console.log("error getting group"),doCallback(callback,[err,response],self);else{var entities=response.getEntities();if(entities&&entities.length){{entities.shift()}self._client.request(memberOptions,function(err,response){err&&self._client.logging?console.log("error getting group users"):self._list=response.getEntities().filter(function(entity){return isUUID(entity.uuid)}).map(function(entity){return new Usergrid.Entity({type:entity.type,client:self._client
 ,uuid:entity.uuid,response:entity})}),doCallback(callback,[err,response,self],self)})}}})},Usergrid.Group.prototype.members=function(){return this._list},Usergrid.Group.prototype.add=function(options,callback){var self=this;options.user?(options={method:"POST",endpoint:"groups/"+this._path+"/users/"+options.user.get("username")},this._client.request(options,function(error,response){error?doCallback(callback,[error,response,self],self):self.fetch(callback)})):doCallback(callback,[new UsergridError("no user specified","no_user_specified"),null,this],this)},Usergrid.Group.prototype.remove=function(options,callback){var self=this;options.user?(options={method:"DELETE",endpoint:"groups/"+this._path+"/users/"+options.user.get("username")},this._client.request(options,function(error,response){error?doCallback(callback,[error,response,self],self):self.fetch(callback)})):doCallback(callback,[new UsergridError("no user specified","no_user_specified"),null,this],this)},Usergrid.Group.prototype
 .feed=function(callback){var self=this,options={method:"GET",endpoint:"groups/"+this._path+"/feed"};this._client.request(options,function(err,response){doCallback(callback,[err,response,self],self)})},Usergrid.Group.prototype.createGroupActivity=function(options,callback){var self=this,user=options.user,entity=new Usergrid.Entity({client:this._client,data:{actor:{displayName:user.get("username"),uuid:user.get("uuid"),username:user.get("username"),email:user.get("email"),picture:user.get("picture"),image:{duration:0,height:80,url:user.get("picture"),width:80}},verb:"post",content:options.content,type:"groups/"+this._path+"/activities"}});entity.save(function(err,response){doCallback(callback,[err,response,self])})},Usergrid.Counter=function(options){this._client=options.client,this._data=options.data||{},this._data.category=options.category||"UNKNOWN",this._data.timestamp=options.timestamp||0,this._data.type="events",this._data.counters=options.counters||{}};var COUNTER_RESOLUTIONS=[
 "all","minute","five_minutes","half_hour","hour","six_day","day","week","month"];Usergrid.Counter.prototype=new Usergrid.Entity,Usergrid.Counter.prototype.fetch=function(callback){this.getData({},callback)},Usergrid.Counter.prototype.increment=function(options,callback){var self=this,name=options.name,value=options.value;return name?isNaN(value)?doCallback(callback,[new UsergridInvalidArgumentError("'value' for increment, decrement must be a number"),null,self],self):(self._data.counters[name]=parseInt(value)||1,self.save(callback)):doCallback(callback,[new UsergridInvalidArgumentError("'name' for increment, decrement must be a number"),null,self],self)},Usergrid.Counter.prototype.decrement=function(options,callback){var self=this,name=options.name,value=options.value;self.increment({name:name,value:-(parseInt(value)||1)},callback)},Usergrid.Counter.prototype.reset=function(options,callback){var self=this,name=options.name;self.increment({name:name,value:0},callback)},Usergrid.Count
 er.prototype.getData=function(options,callback){var start_time,end_time,start=options.start||0,end=options.end||Date.now(),resolution=(options.resolution||"all").toLowerCase(),counters=options.counters||Object.keys(this._data.counters),res=(resolution||"all").toLowerCase();-1===COUNTER_RESOLUTIONS.indexOf(res)&&(res="all"),start_time=getSafeTime(start),end_time=getSafeTime(end);var self=this,params=Object.keys(counters).map(function(counter){return["counter",encodeURIComponent(counters[counter])].join("=")});params.push("resolution="+res),params.push("start_time="+String(start_time)),params.push("end_time="+String(end_time));var endpoint="counters?"+params.join("&");this._client.request({endpoint:endpoint},function(err,data){return data.counters&&data.counters.length&&data.counters.forEach(function(counter){self._data.counters[counter.name]=counter.value||counter.values}),doCallback(callback,[err,data,self],self)})},Usergrid.Folder=function(options,callback){var self=this;console.lo
 g("FOLDER OPTIONS",options),self._client=options.client,self._data=options.data||{},self._data.type="folders";var missingData=["name","owner","path"].some(function(required){return!(required in self._data)});return missingData?doCallback(callback,[new UsergridInvalidArgumentError("Invalid asset data: 'name', 'owner', and 'path' are required properties."),null,self],self):void self.save(function(err,response){err?doCallback(callback,[new UsergridError(response),response,self],self):(response&&response.entities&&response.entities.length&&self.set(response.entities[0]),doCallback(callback,[null,response,self],self))})},Usergrid.Folder.prototype=new Usergrid.Entity,Usergrid.Folder.prototype.fetch=function(callback){var self=this;Usergrid.Entity.prototype.fetch.call(self,function(err,data){console.log("self",self.get()),console.log("data",data),err?doCallback(callback,[null,data,self],self):self.getAssets(function(err,response){err?doCallback(callback,[new UsergridError(response),resonse
 ,self],self):doCallback(callback,[null,self],self)})})},Usergrid.Folder.prototype.addAsset=function(options,callback){var self=this;if("asset"in options){var asset=null;switch(typeof options.asset){case"object":asset=options.asset,asset instanceof Usergrid.Entity||(asset=new Usergrid.Asset(asset));break;case"string":isUUID(options.asset)&&(asset=new Usergrid.Asset({client:self._client,data:{uuid:options.asset,type:"assets"}}))}asset&&asset instanceof Usergrid.Entity&&asset.fetch(function(err,data){if(err)doCallback(callback,[new UsergridError(data),data,self],self);else{var endpoint=["folders",self.get("uuid"),"assets",asset.get("uuid")].join("/"),options={method:"POST",endpoint:endpoint};self._client.request(options,callback)}})}else doCallback(callback,[new UsergridInvalidArgumentError("No asset specified"),null,self],self)},Usergrid.Folder.prototype.removeAsset=function(options,callback){var self=this;if("asset"in options){var asset=null;switch(typeof options.asset){case"object":
 asset=options.asset;break;case"string":isUUID(options.asset)&&(asset=new Usergrid.Asset({client:self._client,data:{uuid:options.asset,type:"assets"}}))}if(asset&&null!==asset){var endpoint=["folders",self.get("uuid"),"assets",asset.get("uuid")].join("/");self._client.request({method:"DELETE",endpoint:endpoint},function(err,response){err?doCallback(callback,[new UsergridError(response),response,self],self):doCallback(callback,[null,response,self],self)})}}else doCallback(callback,[new UsergridInvalidArgumentError("No asset specified"),null,self],self)},Usergrid.Folder.prototype.getAssets=function(callback){return this.getConnections("assets",callback)},XMLHttpRequest.prototype.sendAsBinary||(XMLHttpRequest.prototype.sendAsBinary=function(sData){for(var nBytes=sData.length,ui8Data=new Uint8Array(nBytes),nIdx=0;nBytes>nIdx;nIdx++)ui8Data[nIdx]=255&sData.charCodeAt(nIdx);this.send(ui8Data)}),Usergrid.Asset=function(options,callback){var self=this;self._client=options.client,self._data=o
 ptions.data||{},self._data.type="assets";var missingData=["name","owner","path"].some(function(required){return!(required in self._data)});missingData?doCallback(callback,[new UsergridError("Invalid asset data: 'name', 'owner', and 'path' are required properties."),null,self],self):self.save(function(err,data){err?doCallback(callback,[new UsergridError(data),data,self],self):(data&&data.entities&&data.entities.length&&self.set(data.entities[0]),doCallback(callback,[null,data,self],self))})},Usergrid.Asset.prototype=new Usergrid.Entity,Usergrid.Asset.prototype.addToFolder=function(options,callback){var self=this;if("folder"in options&&isUUID(options.folder)){Usergrid.Folder({uuid:options.folder},function(err,folder){if(err)doCallback(callback,[UsergridError.fromResponse(folder),folder,self],self);else{var endpoint=["folders",folder.get("uuid"),"assets",self.get("uuid")].join("/"),options={method:"POST",endpoint:endpoint};this._client.request(options,function(err,response){err?doCallb
 ack(callback,[UsergridError.fromResponse(folder),response,self],self):doCallback(callback,[null,folder,self],self)})}})}else doCallback(callback,[new UsergridError("folder not specified"),null,self],self)},Usergrid.Asset.prototype.upload=function(data,callback){if(!(window.File&&window.FileReader&&window.FileList&&window.Blob))return void doCallback(callback,[new UsergridError("The File APIs are not fully supported by your browser."),null,this],this);var self=this,args=arguments,attempts=self.get("attempts");isNaN(attempts)&&(attempts=3),self.set("content-type",data.type),self.set("size",data.size);var endpoint=[this._client.URI,this._client.orgName,this._client.appName,"assets",self.get("uuid"),"data"].join("/"),xhr=new XMLHttpRequest;xhr.open("POST",endpoint,!0),xhr.onerror=function(){doCallback(callback,[new UsergridError("The File APIs are not fully supported by your browser.")],xhr,self)},xhr.onload=function(){xhr.status>=500&&attempts>0?(self.set("attempts",--attempts),setTime
 out(function(){self.upload.apply(self,args)},100)):xhr.status>=300?(self.set("attempts"),doCallback(callback,[new UsergridError(JSON.parse(xhr.responseText)),xhr,self],self)):(self.set("attempts"),doCallback(callback,[null,xhr,self],self))};var fr=new FileReader;fr.onload=function(){var binary=fr.result;xhr.overrideMimeType("application/octet-stream"),xhr.sendAsBinary(binary)},fr.readAsBinaryString(data)},Usergrid.Asset.prototype.download=function(callback){var self=this,endpoint=[this._client.URI,this._client.orgName,this._client.appName,"assets",self.get("uuid"),"data"].join("/"),xhr=new XMLHttpRequest;xhr.open("GET",endpoint,!0),xhr.responseType="blob",xhr.onload=function(){xhr.response;doCallback(callback,[null,xhr,self],self)},xhr.onerror=function(err){callback(!0,err),doCallback(callback,[new UsergridError(err),xhr,self],self)},xhr.overrideMimeType(self.get("content-type")),xhr.send()},function(global){function UsergridError(message,name,timestamp,duration,exception){this.mess
 age=message,this.name=name,this.timestamp=timestamp||Date.now(),this.duration=duration||0,this.exception=exception}function UsergridHTTPResponseError(message,name,timestamp,duration,exception){this.message=message,this.name=name,this.timestamp=timestamp||Date.now(),this.duration=duration||0,this.exception=exception}function UsergridInvalidHTTPMethodError(message,name,timestamp,duration,exception){this.message=message,this.name=name||"invalid_http_method",this.timestamp=timestamp||Date.now(),this.duration=duration||0,this.exception=exception}function UsergridInvalidURIError(message,name,timestamp,duration,exception){this.message=message,this.name=name||"invalid_uri",this.timestamp=timestamp||Date.now(),this.duration=duration||0,this.exception=exception}function UsergridInvalidArgumentError(message,name,timestamp,duration,exception){this.message=message,this.name=name||"invalid_argument",this.timestamp=timestamp||Date.now(),this.duration=duration||0,this.exception=exception}function U
 sergridKeystoreDatabaseUpgradeNeededError(message,name,timestamp,duration,exception){this.message=message,this.name=name,this.timestamp=timestamp||Date.now(),this.duration=duration||0,this.exception=exception}var short,name="UsergridError",_name=global[name],_short=short&&void 0!==short?global[short]:void 0;return UsergridError.prototype=new Error,UsergridError.prototype.constructor=UsergridError,UsergridError.fromResponse=function(response){return response&&"undefined"!=typeof response?new UsergridError(response.error_description,response.error,response.timestamp,response.duration,response.exception):new UsergridError},UsergridError.createSubClass=function(name){return name in global&&global[name]?global[name]:(global[name]=function(){},global[name].name=name,global[name].prototype=new UsergridError,global[name])},UsergridHTTPResponseError.prototype=new UsergridError,UsergridInvalidHTTPMethodError.prototype=new UsergridError,UsergridInvalidURIError.prototype=new UsergridError,Userg
 ridInvalidArgumentError.prototype=new UsergridError,UsergridKeystoreDatabaseUpgradeNeededError.prototype=new UsergridError,global.UsergridHTTPResponseError=UsergridHTTPResponseError,global.UsergridInvalidHTTPMethodError=UsergridInvalidHTTPMethodError,global.UsergridInvalidURIError=UsergridInvalidURIError,global.UsergridInvalidArgumentError=UsergridInvalidArgumentError,global.UsergridKeystoreDatabaseUpgradeNeededError=UsergridKeystoreDatabaseUpgradeNeededError,global[name]=UsergridError,void 0!==short&&(global[short]=UsergridError),global[name].noConflict=function(){return _name&&(global[name]=_name),void 0!==short&&(global[short]=_short),UsergridError},global[name]}(this);
\ No newline at end of file


[05/12] git commit: Refactored individual modules for standard callback signature and updated tests

Posted by sn...@apache.org.
Refactored individual modules for standard callback signature and updated tests


Project: http://git-wip-us.apache.org/repos/asf/incubator-usergrid/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-usergrid/commit/da8ecfff
Tree: http://git-wip-us.apache.org/repos/asf/incubator-usergrid/tree/da8ecfff
Diff: http://git-wip-us.apache.org/repos/asf/incubator-usergrid/diff/da8ecfff

Branch: refs/heads/master
Commit: da8ecfff19c930d5845a0d21a56f6529f81e9c05
Parents: 39fac0d
Author: ryan bridges <rb...@apigee.com>
Authored: Tue Apr 1 12:09:45 2014 -0400
Committer: ryan bridges <rb...@apigee.com>
Committed: Tue Apr 1 12:09:45 2014 -0400

----------------------------------------------------------------------
 sdks/html5-javascript/lib/Usergrid.js           | 171 ++--
 sdks/html5-javascript/lib/modules/Asset.js      |  71 +-
 sdks/html5-javascript/lib/modules/Client.js     | 462 +++++-----
 sdks/html5-javascript/lib/modules/Collection.js | 236 ++---
 sdks/html5-javascript/lib/modules/Counter.js    | 164 ++--
 sdks/html5-javascript/lib/modules/Entity.js     | 452 +++++-----
 sdks/html5-javascript/lib/modules/Error.js      | 112 +--
 sdks/html5-javascript/lib/modules/Folder.js     |  46 +-
 sdks/html5-javascript/lib/modules/Group.js      | 104 ++-
 sdks/html5-javascript/lib/modules/util/Ajax.js  |  16 +-
 sdks/html5-javascript/lib/modules/util/Event.js |   8 +-
 .../html5-javascript/lib/modules/util/Logger.js |  18 +-
 .../lib/modules/util/Promise.js                 |   5 +-
 sdks/html5-javascript/tests/mocha/test.js       |  77 +-
 sdks/html5-javascript/usergrid.js               | 884 +++++++++----------
 sdks/html5-javascript/usergrid.min.js           |   6 +-
 16 files changed, 1431 insertions(+), 1401 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/da8ecfff/sdks/html5-javascript/lib/Usergrid.js
----------------------------------------------------------------------
diff --git a/sdks/html5-javascript/lib/Usergrid.js b/sdks/html5-javascript/lib/Usergrid.js
index 5fb046a..5fed303 100644
--- a/sdks/html5-javascript/lib/Usergrid.js
+++ b/sdks/html5-javascript/lib/Usergrid.js
@@ -35,29 +35,31 @@ function extend(subClass, superClass) {
     subClass.prototype.constructor = subClass;
 
     subClass.superclass = superClass.prototype;
-    if(superClass.prototype.constructor == Object.prototype.constructor) {
+    if (superClass.prototype.constructor == Object.prototype.constructor) {
         superClass.prototype.constructor = superClass;
     }
     return subClass;
 }
-function propCopy(from, to){
-    for(var prop in from){
-        if(from.hasOwnProperty(prop)){
-            if("object"===typeof from[prop] && "object"===typeof to[prop]){
-                to[prop]=propCopy(from[prop], to[prop]);
-            }else{
-                to[prop]=from[prop];
+
+function propCopy(from, to) {
+    for (var prop in from) {
+        if (from.hasOwnProperty(prop)) {
+            if ("object" === typeof from[prop] && "object" === typeof to[prop]) {
+                to[prop] = propCopy(from[prop], to[prop]);
+            } else {
+                to[prop] = from[prop];
             }
         }
     }
     return to;
 }
-function NOOP(){}
+
+function NOOP() {}
 
 function isValidUrl(url) {
     if (!url) return false;
-    var doc, base, anchor, isValid=false;
-    try{
+    var doc, base, anchor, isValid = false;
+    try {
         doc = document.implementation.createHTMLDocument('');
         base = doc.createElement('base');
         base.href = base || window.lo;
@@ -65,15 +67,15 @@ function isValidUrl(url) {
         anchor = doc.createElement('a');
         anchor.href = url;
         doc.body.appendChild(anchor);
-        isValid=!(anchor.href === '')
-    }catch(e){
+        isValid = !(anchor.href === '')
+    } catch (e) {
         console.error(e);
-    }finally{
+    } finally {
         doc.head.removeChild(base);
         doc.body.removeChild(anchor);
-        base=null;
-        anchor=null;
-        doc=null;
+        base = null;
+        anchor = null;
+        doc = null;
         return isValid;
     }
 }
@@ -87,8 +89,9 @@ function isValidUrl(url) {
  * @returns {Boolean} true if string is uuid
  */
 var uuidValueRegex = /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/;
+
 function isUUID(uuid) {
-	return (!uuid)?false:uuidValueRegex.test(uuid);
+    return (!uuid) ? false : uuidValueRegex.test(uuid);
 }
 
 /*
@@ -101,14 +104,34 @@ function isUUID(uuid) {
  */
 function encodeParams(params) {
     var queryString;
-    if(params && Object.keys(params)){
+    if (params && Object.keys(params)) {
         queryString = [].slice.call(arguments)
-            .reduce(function(a, b) {return a.concat((b instanceof Array)?b:[b]);},[])
-            .filter(function(c){return "object"===typeof c})
-            .reduce(function(p,c){(!(c instanceof Array)) ? p= p.concat(Object.keys(c).map(function(key){return [key,c[key]]})): p.push(c); return p;},[])
-            .reduce(function(p,c){((c.length===2) ? p.push(c) : p= p.concat(c)); return p;},[])
-            .reduce(function(p,c){(c[1] instanceof Array) ? c[1].forEach(function(v){p.push([c[0],v])}): p.push(c); return p;},[])
-            .map(function(c){c[1]=encodeURIComponent(c[1]); return c.join('=')})
+            .reduce(function(a, b) {
+                return a.concat((b instanceof Array) ? b : [b]);
+            }, [])
+            .filter(function(c) {
+                return "object" === typeof c
+            })
+            .reduce(function(p, c) {
+                (!(c instanceof Array)) ? p = p.concat(Object.keys(c).map(function(key) {
+                    return [key, c[key]]
+                })) : p.push(c);
+                return p;
+            }, [])
+            .reduce(function(p, c) {
+                ((c.length === 2) ? p.push(c) : p = p.concat(c));
+                return p;
+            }, [])
+            .reduce(function(p, c) {
+                (c[1] instanceof Array) ? c[1].forEach(function(v) {
+                    p.push([c[0], v])
+                }) : p.push(c);
+                return p;
+            }, [])
+            .map(function(c) {
+                c[1] = encodeURIComponent(c[1]);
+                return c.join('=')
+            })
             .join('&');
     }
     return queryString;
@@ -124,7 +147,7 @@ function encodeParams(params) {
  *  @return {boolean} Returns true or false
  */
 function isFunction(f) {
-	return (f && f !== null && typeof(f) === 'function');
+    return (f && f !== null && typeof(f) === 'function');
 }
 
 /*
@@ -138,36 +161,38 @@ function isFunction(f) {
  *  @return Returns whatever would be returned by the callback. or false.
  */
 function doCallback(callback, params, context) {
-	var returnValue;
-	if (isFunction(callback)) {
-		if (!params) params = [];
-		if (!context) context = this;
-		params.push(context);
-		//try {
-			returnValue = callback.apply(context, params);
-		/*} catch (ex) {
+    var returnValue;
+    if (isFunction(callback)) {
+        if (!params) params = [];
+        if (!context) context = this;
+        params.push(context);
+        //try {
+        returnValue = callback.apply(context, params);
+        /*} catch (ex) {
 			if (console && console.error) {
 				console.error("Callback error:", ex);
 			}
 		}*/
-	}
-	return returnValue;
+    }
+    return returnValue;
 }
 
 //noinspection ThisExpressionReferencesGlobalObjectJS
 (function(global) {
-	var name = 'Usergrid', overwrittenName = global[name];
+    var name = 'Usergrid',
+        overwrittenName = global[name];
+    var VALID_REQUEST_METHODS = ['GET', 'POST', 'PUT', 'DELETE'];
 
     function Usergrid() {
         this.logger = new Logger(name);
     }
 
-    Usergrid.isValidEndpoint = function (endpoint) {
+    Usergrid.isValidEndpoint = function(endpoint) {
         //TODO actually implement this
         return true;
     };
-    var VALID_REQUEST_METHODS = ['GET', 'POST', 'PUT', 'DELETE'];
-    Usergrid.Request = function (method, endpoint, query_params, data, callback) {
+
+    Usergrid.Request = function(method, endpoint, query_params, data, callback) {
         var p = new Promise();
         /*
          Create a logger
@@ -177,7 +202,7 @@ function doCallback(callback, params, context) {
         /*
          Validate our input
          */
-        this.endpoint=endpoint+'?'+encodeParams(query_params);
+        this.endpoint = endpoint + '?' + encodeParams(query_params);
         this.method = method.toUpperCase();
         //this.query_params = query_params;
         this.data = ("object" === typeof data) ? JSON.stringify(data) : data;
@@ -194,25 +219,29 @@ function doCallback(callback, params, context) {
             throw new UsergridInvalidURIError("The provided endpoint is not valid: " + this.endpoint);
         }
         /* a callback to make the request */
-        var request=function () {return Ajax.request(this.method, this.endpoint, this.data)}.bind(this);
+        var request = function() {
+            return Ajax.request(this.method, this.endpoint, this.data)
+        }.bind(this);
         /* a callback to process the response */
-        var response=function (err, request) {return new Usergrid.Response(err, request)}.bind(this);
+        var response = function(err, request) {
+            return new Usergrid.Response(err, request)
+        }.bind(this);
         /* a callback to clean up and return data to the client */
-        var oncomplete=function (err, response) {
+        var oncomplete = function(err, response) {
             p.done(err, response);
             this.logger.info("REQUEST", err, response);
             doCallback(callback, [err, response]);
             this.logger.timeEnd("process request " + method + " " + endpoint);
         }.bind(this);
         /* and a promise to chain them all together */
-        Promise.chain([request,response]).then(oncomplete);
+        Promise.chain([request, response]).then(oncomplete);
 
         return p;
     };
     //TODO more granular handling of statusCodes
-    Usergrid.Response = function (err, response) {
+    Usergrid.Response = function(err, response) {
         var p = new Promise();
-        var data=null;
+        var data = null;
         try {
             data = JSON.parse(response.responseText);
         } catch (e) {
@@ -220,8 +249,11 @@ function doCallback(callback, params, context) {
             //this.logger.error("Caught error ", e.message);
             data = {}
         }
-        Object.keys(data).forEach(function(key){
-            Object.defineProperty(this, key, { value : data[key], enumerable:true });
+        Object.keys(data).forEach(function(key) {
+            Object.defineProperty(this, key, {
+                value: data[key],
+                enumerable: true
+            });
         }.bind(this));
         Object.defineProperty(this, "logger", {
             enumerable: false,
@@ -254,13 +286,13 @@ function doCallback(callback, params, context) {
             value: (this.status - this.status % 100)
         });
         switch (this.statusGroup) {
-            case 200:
+            case 200: //success
                 this.success = true;
                 break;
-            case 400:
-            case 500:
-            case 300:
-            case 100:
+            case 400: //user error
+            case 500: //server error
+            case 300: //cache and redirects
+            case 100: //upgrade
             default:
                 //server error
                 this.success = false;
@@ -273,28 +305,25 @@ function doCallback(callback, params, context) {
         }
         return p;
     };
-    Usergrid.Response.prototype.getEntities = function () {
-        var entities=[]
+    Usergrid.Response.prototype.getEntities = function() {
+        var entities;
         if (this.success) {
-            entities=(this.data)?this.data.entities:this.entities;
+            entities = (this.data) ? this.data.entities : this.entities;
         }
-        return entities;
+        return entities || [];
     }
-    Usergrid.Response.prototype.getEntity = function () {
-        var entities=this.getEntities();
+    Usergrid.Response.prototype.getEntity = function() {
+        var entities = this.getEntities();
         return entities[0];
     }
     Usergrid.VERSION = Usergrid.USERGRID_SDK_VERSION = '0.11.0';
 
-	global[name] =  Usergrid;
-	global[name].noConflict = function() {
-		if(overwrittenName){
-			global[name] = overwrittenName;
-		}
-		return Usergrid;
-	};
-	return global[name];
+    global[name] = Usergrid;
+    global[name].noConflict = function() {
+        if (overwrittenName) {
+            global[name] = overwrittenName;
+        }
+        return Usergrid;
+    };
+    return global[name];
 }(this));
-
-
-

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/da8ecfff/sdks/html5-javascript/lib/modules/Asset.js
----------------------------------------------------------------------
diff --git a/sdks/html5-javascript/lib/modules/Asset.js b/sdks/html5-javascript/lib/modules/Asset.js
index c368427..b5bc68a 100644
--- a/sdks/html5-javascript/lib/modules/Asset.js
+++ b/sdks/html5-javascript/lib/modules/Asset.js
@@ -30,20 +30,23 @@ Usergrid.Asset = function(options, callback) {
 	self._client = options.client;
 	self._data = options.data || {};
 	self._data.type = "assets";
-	var missingData = ["name", "owner", "path"].some(function(required) { return !(required in self._data)});
-	if(missingData){
-		return doCallback(callback, [true, new UsergridError("Invalid asset data: 'name', 'owner', and 'path' are required properties.")], self);
-	}
-	self.save(function(err, data) {
-		if (err) {
-			doCallback(callback, [true, new UsergridError(data)], self);
-		} else {
-			if (data && data.entities && data.entities.length){
-				self.set(data.entities[0]);
-			}
-			doCallback(callback, [false, self], self);
-		}
+	var missingData = ["name", "owner", "path"].some(function(required) {
+		return !(required in self._data);
 	});
+	if (missingData) {
+		doCallback(callback, [new UsergridError("Invalid asset data: 'name', 'owner', and 'path' are required properties."), null, self], self);
+	} else {
+		self.save(function(err, data) {
+			if (err) {
+				doCallback(callback, [new UsergridError(data), data, self], self);
+			} else {
+				if (data && data.entities && data.entities.length) {
+					self.set(data.entities[0]);
+				}
+				doCallback(callback, [null, data, self], self);
+			}
+		});
+	}
 };
 
 /*
@@ -69,17 +72,26 @@ Usergrid.Asset.prototype.addToFolder = function(options, callback) {
 			uuid: options.folder
 		}, function(err, folder) {
 			if (err) {
-				return callback.call(self, err, folder);
+				doCallback(callback, [UsergridError.fromResponse(folder), folder, self], self);
+			} else {
+				var endpoint = ["folders", folder.get("uuid"), "assets", self.get("uuid")].join('/');
+				var options = {
+					method: 'POST',
+					endpoint: endpoint
+				};
+				this._client.request(options, function(err, response) {
+					if (err) {
+						doCallback(callback, [UsergridError.fromResponse(folder), response, self], self);
+					} else {
+						doCallback(callback, [null, folder, self], self);
+					}
+
+
+				});
 			}
-			var endpoint = ["folders", folder.get("uuid"), "assets", self.get("uuid")].join('/');
-			var options = {
-				method: 'POST',
-				endpoint: endpoint
-			};
-			this._client.request(options, callback);
 		});
 	} else {
-		doCallback(callback, [true, new UsergridError('folder not specified')], self);
+		doCallback(callback, [new UsergridError('folder not specified'), null, self], self);
 	}
 };
 
@@ -93,7 +105,8 @@ Usergrid.Asset.prototype.addToFolder = function(options, callback) {
  */
 Usergrid.Asset.prototype.upload = function(data, callback) {
 	if (!(window.File && window.FileReader && window.FileList && window.Blob)) {
-		return doCallback(callback, [true, new UsergridError('The File APIs are not fully supported by your browser.')], self);
+		doCallback(callback, [new UsergridError('The File APIs are not fully supported by your browser.'), null, this], this);
+		return;
 	}
 	var self = this;
 	var endpoint = [this._client.URI, this._client.orgName, this._client.appName, "assets", self.get("uuid"), 'data'].join('/'); //self._client.buildAssetURL(self.get("uuid"));
@@ -102,13 +115,13 @@ Usergrid.Asset.prototype.upload = function(data, callback) {
 	xhr.open("POST", endpoint, true);
 	xhr.onerror = function(err) {
 		//callback(true, err);
-		doCallback(callback, [true, new UsergridError('The File APIs are not fully supported by your browser.')], self)
+		doCallback(callback, [true, new UsergridError('The File APIs are not fully supported by your browser.')], self);
 	};
 	xhr.onload = function(ev) {
 		if (xhr.status >= 300) {
-			doCallback(callback, [true, new UsergridError(JSON.parse(xhr.responseText))], self)
+			doCallback(callback, [new UsergridError(JSON.parse(xhr.responseText)), null, self], self);
 		} else {
-			doCallback(callback, [null, self], self)
+			doCallback(callback, [null, xhr, self], self);
 		}
 	};
 	var fr = new FileReader();
@@ -120,7 +133,7 @@ Usergrid.Asset.prototype.upload = function(data, callback) {
 		}, 1000);
 	};
 	fr.readAsBinaryString(data);
-}
+};
 
 /*
  *  Download Asset data
@@ -138,12 +151,12 @@ Usergrid.Asset.prototype.download = function(callback) {
 	xhr.onload = function(ev) {
 		var blob = xhr.response;
 		//callback(null, blob);
-		doCallback(callback, [false, blob], self)
+		doCallback(callback, [null, blob, self], self);
 	};
 	xhr.onerror = function(err) {
 		callback(true, err);
-		doCallback(callback, [true, new UsergridError(err)], self)
+		doCallback(callback, [new UsergridError(err), err, self], self);
 	};
 
 	xhr.send();
-}
+};

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/da8ecfff/sdks/html5-javascript/lib/modules/Client.js
----------------------------------------------------------------------
diff --git a/sdks/html5-javascript/lib/modules/Client.js b/sdks/html5-javascript/lib/modules/Client.js
index 655b025..d9ab1b2 100644
--- a/sdks/html5-javascript/lib/modules/Client.js
+++ b/sdks/html5-javascript/lib/modules/Client.js
@@ -1,6 +1,16 @@
 (function() {
-  var name = 'Client', global = this, overwrittenName = global[name], exports;
-
+  var name = 'Client',
+    global = this,
+    overwrittenName = global[name],
+    exports;
+  var AUTH_ERRORS = [
+    "auth_expired_session_token",
+    "auth_missing_credentials",
+    "auth_unverified_oath",
+    "expired_token",
+    "unauthorized",
+    "auth_invalid"
+  ];
   Usergrid.Client = function(options) {
     //usergrid endpoint
     this.URI = options.URI || 'https://api.usergrid.com';
@@ -12,7 +22,7 @@
     if (options.appName) {
       this.set('appName', options.appName);
     }
-    if(options.qs){
+    if (options.qs) {
       this.setObject('default_qs', options.qs);
     }
     //other options
@@ -20,9 +30,7 @@
     this.logging = options.logging || false;
 
     //timeout and callbacks
-    this._callTimeout =  options.callTimeout || 30000; //default to 30 seconds
-    this._callTimeoutCallback =  options.callTimeoutCallback || null;
-    this.logoutCallback =  options.logoutCallback || null;
+    // this.logoutCallback =  options.logoutCallback || null;
   };
 
   /*
@@ -41,8 +49,7 @@
    *  @param {function} callback
    *  @return {callback} callback(err, data)
    */
-  Usergrid.Client.prototype.request = function (options, callback) {
-    var self = this;
+  Usergrid.Client.prototype.request = function(options, callback) {
     var method = options.method || 'GET';
     var endpoint = options.endpoint;
     var body = options.body || {};
@@ -50,15 +57,15 @@
     var mQuery = options.mQuery || false; //is this a query to the management endpoint?
     var orgName = this.get('orgName');
     var appName = this.get('appName');
-    var default_qs=this.getObject('default_qs');
+    var default_qs = this.getObject('default_qs');
     var uri;
-      var logoutCallback=function(){
-          if (typeof(this.logoutCallback) === 'function') {
-              return this.logoutCallback(true, 'no_org_or_app_name_specified');
-          }
-      }.bind(this);
-    if(!mQuery && !orgName && !appName){
-        return logoutCallback();
+    /*var logoutCallback=function(){
+        if (typeof(this.logoutCallback) === 'function') {
+            return this.logoutCallback(true, 'no_org_or_app_name_specified');
+        }
+    }.bind(this);*/
+    if (!mQuery && !orgName && !appName) {
+      return logoutCallback();
     }
     if (mQuery) {
       uri = this.URI + '/' + endpoint;
@@ -67,29 +74,29 @@
     }
     if (this.getToken()) {
       qs.access_token = this.getToken();
-      /* //could also use headers for the token
+      /*
+       **NOTE** The token can also be passed as a header on the request
+
        xhr.setRequestHeader("Authorization", "Bearer " + self.getToken());
        xhr.withCredentials = true;
        */
     }
-    if(default_qs){
-      qs=propCopy(qs, default_qs);
+    if (default_qs) {
+      qs = propCopy(qs, default_qs);
     }
-      var req = new Usergrid.Request(method, uri, qs, body, function (err, response) {
-          if ([
-              "auth_expired_session_token",
-              "auth_missing_credentials",
-              "auth_unverified_oath",
-              "expired_token",
-              "unauthorized",
-              "auth_invalid"
-          ].indexOf(response.error) !== -1) {
-              return logoutCallback();
-          }
-          doCallback(callback, [err, response]);
-          //p.done(err, response);
-      });
-  }
+    var self=this;
+    var req = new Usergrid.Request(method, uri, qs, body, function(err, response) {
+      /*if (AUTH_ERRORS.indexOf(response.error) !== -1) {
+            return logoutCallback();
+        }*/
+      if(err){
+        doCallback(callback, [err, response, self], self);
+      }else{
+        doCallback(callback, [null, response, self], self);
+      }
+      //p.done(err, response);
+    });
+  };
 
   /*
    *  function for building asset urls
@@ -127,15 +134,13 @@
    *  @return {callback} callback(err, data)
    */
   Usergrid.Client.prototype.createGroup = function(options, callback) {
-    options = {
+    var group = new Usergrid.Group({
       path: options.path,
       client: this,
       data: options
-    };
-
-    var group = new Usergrid.Group(options);
-    group.save(function(err, data){
-        doCallback(callback, [err, group, data]);
+    });
+    group.save(function(err, response) {
+      doCallback(callback, [err, response, group], group);
     });
   };
 
@@ -150,17 +155,15 @@
    *  @param {function} callback
    *  @return {callback} callback(err, data)
    */
-    Usergrid.Client.prototype.createEntity = function (options, callback) {
-        var entity_data = {
-            client: this,
-            data: options
-        };
-        var entity = new Usergrid.Entity(entity_data);
-        var self = this;
-        entity.save(function (err, data) {
-            doCallback(callback, [err, entity, data]);
-        });
-    };
+  Usergrid.Client.prototype.createEntity = function(options, callback) {
+    var entity = new Usergrid.Entity({
+      client: this,
+      data: options
+    });
+    entity.save(function(err, response) {
+      doCallback(callback, [err, response, entity], entity);
+    });
+  };
   /*
    *  Main function for getting existing entities - should be called directly.
    *
@@ -175,14 +178,13 @@
    *  @param {function} callback
    *  @return {callback} callback(err, data)
    */
-  Usergrid.Client.prototype.getEntity = function (options, callback) {
-    var options = {
-      client:this,
-      data:options
-    }
-    var entity = new Usergrid.Entity(options);
-    entity.fetch(function(err, data) {
-        doCallback(callback, [err, entity, data]);
+  Usergrid.Client.prototype.getEntity = function(options, callback) {
+    var entity = new Usergrid.Entity({
+      client: this,
+      data: options
+    });
+    entity.fetch(function(err, response) {
+      doCallback(callback, [err, response, entity], entity);
     });
   };
 
@@ -196,12 +198,12 @@
    *  @param {string} serializedObject
    *  @return {object} Entity Object
    */
-  Usergrid.Client.prototype.restoreEntity = function (serializedObject) {
+  Usergrid.Client.prototype.restoreEntity = function(serializedObject) {
     var data = JSON.parse(serializedObject);
     var options = {
-      client:this,
-      data:data
-    }
+      client: this,
+      data: data
+    };
     var entity = new Usergrid.Entity(options);
     return entity;
   };
@@ -217,10 +219,11 @@
    *  @param {function} callback
    *  @return {callback} callback(err, data)
    */
-  Usergrid.Client.prototype.createCollection = function (options, callback) {
+  Usergrid.Client.prototype.createCollection = function(options, callback) {
     options.client = this;
-    new Usergrid.Collection(options, function(err, data, collection) {
-        doCallback(callback, [err, collection, data]);
+    var collection = new Usergrid.Collection(options);
+    collection.fetch(function(err, response, collection) {
+      doCallback(callback, [err, response, collection], this);
     });
   };
 
@@ -234,7 +237,7 @@
    *  @param {string} serializedObject
    *  @return {object} Collection Object
    */
-  Usergrid.Client.prototype.restoreCollection = function (serializedObject) {
+  Usergrid.Client.prototype.restoreCollection = function(serializedObject) {
     var data = JSON.parse(serializedObject);
     data.client = this;
     var collection = new Usergrid.Collection(data);
@@ -253,15 +256,15 @@
   Usergrid.Client.prototype.getFeedForUser = function(username, callback) {
     var options = {
       method: "GET",
-      endpoint: "users/"+username+"/feed"
+      endpoint: "users/" + username + "/feed"
     };
 
-    this.request(options, function(err, data){
-        if(err) {
-            doCallback(callback, [err]);
-        } else {
-            doCallback(callback, [err, data, data.getEntities()]);
-        }
+    this.request(options, function(err, data) {
+      if (err) {
+        doCallback(callback, [err]);
+      } else {
+        doCallback(callback, [err, data, data.getEntities()]);
+      }
     });
   };
 
@@ -300,15 +303,15 @@
    *  @param {function} callback
    *  @return {callback} callback(err, data)
    */
-  Usergrid.Client.prototype.createUserActivity = function (user, options, callback) {
-    options.type = 'users/'+user+'/activities';
-    var options = {
-      client:this,
-      data:options
-    }
+  Usergrid.Client.prototype.createUserActivity = function(user, options, callback) {
+    options.type = 'users/' + user + '/activities';
+    options = {
+      client: this,
+      data: options
+    };
     var entity = new Usergrid.Entity(options);
     entity.save(function(err, data) {
-        doCallback(callback, [err, entity]);
+      doCallback(callback, [err, data, entity]);
     });
   };
 
@@ -329,20 +332,20 @@
     var username = user.get("username");
     var options = {
       actor: {
-        "displayName":username,
-        "uuid":user.get("uuid"),
-        "username":username,
-        "email":user.get("email"),
-        "picture":user.get("picture"),
+        "displayName": username,
+        "uuid": user.get("uuid"),
+        "username": username,
+        "email": user.get("email"),
+        "picture": user.get("picture"),
         "image": {
-          "duration":0,
-          "height":80,
-          "url":user.get("picture"),
-          "width":80
+          "duration": 0,
+          "height": 80,
+          "url": user.get("picture"),
+          "width": 80
         }
       },
-      "verb":"post",
-      "content":content
+      "verb": "post",
+      "content": content
     };
 
     this.createUserActivity(username, options, callback);
@@ -352,12 +355,12 @@
   /*
    *  A private method to get call timing of last call
    */
-  Usergrid.Client.prototype.calcTimeDiff = function () {
+  Usergrid.Client.prototype.calcTimeDiff = function() {
     var seconds = 0;
     var time = this._end - this._start;
     try {
-      seconds = ((time/10) / 60).toFixed(2);
-    } catch(e) {
+      seconds = ((time / 10) / 60).toFixed(2);
+    } catch (e) {
       return 0;
     }
     return seconds;
@@ -371,7 +374,7 @@
    *  @params {string} token
    *  @return none
    */
-  Usergrid.Client.prototype.setToken = function (token) {
+  Usergrid.Client.prototype.setToken = function(token) {
     this.set('token', token);
   };
 
@@ -382,7 +385,7 @@
    *  @public
    *  @return {string} token
    */
-  Usergrid.Client.prototype.getToken = function () {
+  Usergrid.Client.prototype.getToken = function() {
     return this.get('token');
   };
 
@@ -393,10 +396,10 @@
     this.set(key, value);
   };
 
-  Usergrid.Client.prototype.set = function (key, value) {
-    var keyStore =  'apigee_' + key;
+  Usergrid.Client.prototype.set = function(key, value) {
+    var keyStore = 'apigee_' + key;
     this[key] = value;
-    if(typeof(Storage)!=="undefined"){
+    if (typeof(Storage) !== "undefined") {
       if (value) {
         localStorage.setItem(keyStore, value);
       } else {
@@ -409,15 +412,15 @@
     return JSON.parse(this.get(key));
   };
 
-  Usergrid.Client.prototype.get = function (key) {
+  Usergrid.Client.prototype.get = function(key) {
     var keyStore = 'apigee_' + key;
-    var value=null;
+    var value = null;
     if (this[key]) {
-      value= this[key];
-    } else if(typeof(Storage)!=="undefined") {
-      value= localStorage.getItem(keyStore);
+      value = this[key];
+    } else if (typeof(Storage) !== "undefined") {
+      value = localStorage.getItem(keyStore);
     }
-    return value  ;
+    return value;
   };
 
   /*
@@ -435,11 +438,11 @@
   Usergrid.Client.prototype.signup = function(username, password, email, name, callback) {
     var self = this;
     var options = {
-      type:"users",
-      username:username,
-      password:password,
-      email:email,
-      name:name
+      type: "users",
+      username: username,
+      password: password,
+      email: email,
+      name: name
     };
 
     this.createEntity(options, callback);
@@ -456,12 +459,12 @@
    *  @param {function} callback
    *  @return {callback} callback(err, data)
    */
-  Usergrid.Client.prototype.login = function (username, password, callback) {
+  Usergrid.Client.prototype.login = function(username, password, callback) {
     var self = this;
     var options = {
-      method:'POST',
-      endpoint:'token',
-      body:{
+      method: 'POST',
+      endpoint: 'token',
+      body: {
         username: username,
         password: password,
         grant_type: 'password'
@@ -470,11 +473,11 @@
     self.request(options, function(err, data) {
       var user = {};
       if (err) {
-        if(self.logging)console.log('error trying to log user in');
+        if (self.logging) console.log('error trying to log user in');
       } else {
         var options = {
-          client:self,
-          data:data.user
+          client: self,
+          data: data.user
         };
         user = new Usergrid.Entity(options);
         self.setToken(data.access_token);
@@ -484,12 +487,12 @@
   };
 
 
-  Usergrid.Client.prototype.reAuthenticateLite = function (callback) {
+  Usergrid.Client.prototype.reAuthenticateLite = function(callback) {
     var self = this;
     var options = {
-      method:'GET',
-      endpoint:'management/me',
-      mQuery:true
+      method: 'GET',
+      endpoint: 'management/me',
+      mQuery: true
     };
     this.request(options, function(err, response) {
       if (err && self.logging) {
@@ -497,21 +500,21 @@
       } else {
 
         //save the re-authed token and current email/username
-          self.setToken(response.data.access_token);
+        self.setToken(response.data.access_token);
 
       }
-        doCallback(callback, [err]);
+      doCallback(callback, [err]);
 
     });
   };
 
 
-  Usergrid.Client.prototype.reAuthenticate = function (email, callback) {
+  Usergrid.Client.prototype.reAuthenticate = function(email, callback) {
     var self = this;
     var options = {
-      method:'GET',
-      endpoint:'management/users/'+email,
-      mQuery:true
+      method: 'GET',
+      endpoint: 'management/users/' + email,
+      mQuery: true
     };
     this.request(options, function(err, response) {
       var organizations = {};
@@ -533,14 +536,14 @@
 
 
         var userData = {
-          "username" : data.username,
-          "email" : data.email,
-          "name" : data.name,
-          "uuid" : data.uuid
+          "username": data.username,
+          "email": data.email,
+          "name": data.name,
+          "uuid": data.uuid
         };
         var options = {
-          client:self,
-          data:userData
+          client: self,
+          data: userData
         };
         user = new Usergrid.Entity(options);
 
@@ -549,9 +552,9 @@
         try {
           //if we have an org stored, then use that one. Otherwise, use the first one.
           var existingOrg = self.get('orgName');
-          org = (organizations[existingOrg])?organizations[existingOrg]:organizations[Object.keys(organizations)[0]];
+          org = (organizations[existingOrg]) ? organizations[existingOrg] : organizations[Object.keys(organizations)[0]];
           self.set('orgName', org.name);
-        } catch(e) {
+        } catch (e) {
           err = true;
           if (self.logging) {
             console.log('error selecting org');
@@ -579,12 +582,12 @@
    *  @param {function} callback
    *  @return {callback} callback(err, data)
    */
-  Usergrid.Client.prototype.loginFacebook = function (facebookToken, callback) {
+  Usergrid.Client.prototype.loginFacebook = function(facebookToken, callback) {
     var self = this;
     var options = {
-      method:'GET',
-      endpoint:'auth/facebook',
-      qs:{
+      method: 'GET',
+      endpoint: 'auth/facebook',
+      qs: {
         fb_access_token: facebookToken
       }
     };
@@ -596,7 +599,7 @@
         var options = {
           client: self,
           data: data.user
-        }
+        };
         user = new Usergrid.Entity(options);
         self.setToken(data.access_token);
       }
@@ -612,14 +615,14 @@
    *  @param {function} callback
    *  @return {callback} callback(err, data)
    */
-  Usergrid.Client.prototype.getLoggedInUser = function (callback) {
+  Usergrid.Client.prototype.getLoggedInUser = function(callback) {
     if (!this.getToken()) {
       callback(true, null, null);
     } else {
       var self = this;
       var options = {
-        method:'GET',
-        endpoint:'users/me'
+        method: 'GET',
+        endpoint: 'users/me'
       };
       this.request(options, function(err, data) {
         if (err) {
@@ -629,8 +632,8 @@
           doCallback(callback, [err, data, null], self);
         } else {
           var options = {
-            client:self,
-            data:data.entities[0]
+            client: self,
+            data: data.entities[0]
           };
           var user = new Usergrid.Entity(options);
           doCallback(callback, [null, data, user], self);
@@ -647,9 +650,9 @@
    *  @public
    *  @return {boolean} Returns true the user is logged in (has token and uuid), false if not
    */
-  Usergrid.Client.prototype.isLoggedIn = function () {
-      var token=this.getToken();
-    return "undefined" !== typeof token && token!==null;
+  Usergrid.Client.prototype.isLoggedIn = function() {
+    var token = this.getToken();
+    return "undefined" !== typeof token && token !== null;
   };
 
   /*
@@ -659,74 +662,74 @@
    *  @public
    *  @return none
    */
-  Usergrid.Client.prototype.logout = function () {
+  Usergrid.Client.prototype.logout = function() {
     this.setToken();
   };
 
-    /*
-    *  A public method to destroy access tokens on the server
-    *
-    *  @method logout
-    *  @public    
-    *	 @param {string} username	the user associated with the token to revoke
-    *	 @param {string} token set to 'null' to revoke the token of the currently logged in user 
-    *  	 or set to token value to revoke a specific token
-    *	 @param {string} revokeAll set to 'true' to revoke all tokens for the user            
-    *  @return none
-    */
-		Usergrid.Client.prototype.destroyToken = function (username, token, revokeAll, callback) {
-      var options = {
-	        client:self,
-	        method:'PUT',	        
-				}
-				
-      if (revokeAll == true) {
-				options.endpoint = 'users/'+username+'/revoketokens';
-			} else if (token == null) {
-				options.endpoint = 'users/'+username+'/revoketoken?token='+this.getToken();
-			} else {
-				options.endpoint = 'users/'+username+'/revoketoken?token='+token;
-			}
-      this.request(options, function(err,data) {
-		    if (err) {
-	          if (self.logging) {
-	            console.log('error destroying access token');
-	          }
-	          doCallback(callback, [err, data, null], self);
-	        } else {
-	          if (revokeAll == true) {
-	            console.log('all user tokens invalidated');
-	          } else {
-							console.log('token invalidated');
-	          }
-	          doCallback(callback, [err, data, null], self);
-	        }
-      });
-	  };
-  
-    /*
-    *  A public method to log out an app user - clears all user fields from client
-    *  and destroys the access token on the server.
-    *
-    *  @method logout
-    *  @public
-    *	 @param {string} username the user associated with the token to revoke
-    *	 @param {string} token set to 'null' to revoke the token of the currently logged in user 
-    *  	 or set to token value to revoke a specific token
-    *	 @param {string} revokeAll set to 'true' to revoke all tokens for the user        
-    *  @return none
-    */
-    Usergrid.Client.prototype.logoutAndDestroyToken = function(username, token, revokeAll, callback) {
-			if (username == null) {
-				console.log('username required to revoke tokens');
-			} else {
-				this.destroyToken(username, token, revokeAll, callback);
-				if (revokeAll == true || token == this.getToken() || token == null) {
-		    	this.setToken(null);
-		    }
-		  }
+  /*
+   *  A public method to destroy access tokens on the server
+   *
+   *  @method logout
+   *  @public
+   *  @param {string} username	the user associated with the token to revoke
+   *  @param {string} token set to 'null' to revoke the token of the currently logged in user
+   *    or set to token value to revoke a specific token
+   *  @param {string} revokeAll set to 'true' to revoke all tokens for the user
+   *  @return none
+   */
+  Usergrid.Client.prototype.destroyToken = function(username, token, revokeAll, callback) {
+    var options = {
+      client: self,
+      method: 'PUT',
     };
 
+    if (revokeAll === true) {
+      options.endpoint = 'users/' + username + '/revoketokens';
+    } else if (token === null) {
+      options.endpoint = 'users/' + username + '/revoketoken?token=' + this.getToken();
+    } else {
+      options.endpoint = 'users/' + username + '/revoketoken?token=' + token;
+    }
+    this.request(options, function(err, data) {
+      if (err) {
+        if (self.logging) {
+          console.log('error destroying access token');
+        }
+        doCallback(callback, [err, data, null], self);
+      } else {
+        if (revokeAll === true) {
+          console.log('all user tokens invalidated');
+        } else {
+          console.log('token invalidated');
+        }
+        doCallback(callback, [err, data, null], self);
+      }
+    });
+  };
+
+  /*
+   *  A public method to log out an app user - clears all user fields from client
+   *  and destroys the access token on the server.
+   *
+   *  @method logout
+   *  @public
+   *  @param {string} username the user associated with the token to revoke
+   *  @param {string} token set to 'null' to revoke the token of the currently logged in user
+   *   or set to token value to revoke a specific token
+   *  @param {string} revokeAll set to 'true' to revoke all tokens for the user
+   *  @return none
+   */
+  Usergrid.Client.prototype.logoutAndDestroyToken = function(username, token, revokeAll, callback) {
+    if (username === null) {
+      console.log('username required to revoke tokens');
+    } else {
+      this.destroyToken(username, token, revokeAll, callback);
+      if (revokeAll === true || token === this.getToken() || token === null) {
+        this.setToken(null);
+      }
+    }
+  };
+
   /*
    *  A private method to build the curl call to display on the command line
    *
@@ -735,7 +738,7 @@
    *  @param {object} options
    *  @return {string} curl
    */
-  Usergrid.Client.prototype.buildCurlCall = function (options) {
+  Usergrid.Client.prototype.buildCurlCall = function(options) {
     var curl = ['curl'];
     var method = (options.method || 'GET').toUpperCase();
     var body = options.body;
@@ -743,44 +746,43 @@
 
     //curl - add the method to the command (no need to add anything for GET)
     curl.push('-X');
-    curl.push((['POST','PUT','DELETE'].indexOf(method)>=0)?method:'GET');
+    curl.push((['POST', 'PUT', 'DELETE'].indexOf(method) >= 0) ? method : 'GET');
 
     //curl - append the path
     curl.push(uri);
 
-    if("object"===typeof body && Object.keys(body).length>0 && ['POST','PUT'].indexOf(method)!==-1){
+    if ("object" === typeof body && Object.keys(body).length > 0 && ['POST', 'PUT'].indexOf(method) !== -1) {
       curl.push('-d');
-      curl.push("'"+JSON.stringify(body)+"'");
+      curl.push("'" + JSON.stringify(body) + "'");
     }
-    curl=curl.join(' ');
+    curl = curl.join(' ');
     //log the curl command to the console
     console.log(curl);
 
     return curl;
-  }
+  };
 
-  Usergrid.Client.prototype.getDisplayImage = function (email, picture, size) {
-      size = size || 50;
-      var image='https://apigee.com/usergrid/images/user_profile.png';
+  Usergrid.Client.prototype.getDisplayImage = function(email, picture, size) {
+    size = size || 50;
+    var image = 'https://apigee.com/usergrid/images/user_profile.png';
     try {
       if (picture) {
-        image= picture;
-      }else if (email.length) {
-        image= 'https://secure.gravatar.com/avatar/' + MD5(email) + '?s=' + size + encodeURI("&d=https://apigee.com/usergrid/images/user_profile.png");
+        image = picture;
+      } else if (email.length) {
+        image = 'https://secure.gravatar.com/avatar/' + MD5(email) + '?s=' + size + encodeURI("&d=https://apigee.com/usergrid/images/user_profile.png");
       }
-    } catch(e) {
+    } catch (e) {
       //TODO do something with this error?
-    }finally{
+    } finally {
       return image;
     }
-  }
-  global[name] =  Usergrid.Client;
+  };
+  global[name] = Usergrid.Client;
   global[name].noConflict = function() {
-    if(overwrittenName){
+    if (overwrittenName) {
       global[name] = overwrittenName;
     }
     return exports;
   };
   return global[name];
 }());
-

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/da8ecfff/sdks/html5-javascript/lib/modules/Collection.js
----------------------------------------------------------------------
diff --git a/sdks/html5-javascript/lib/modules/Collection.js b/sdks/html5-javascript/lib/modules/Collection.js
index 75affaa..8233863 100644
--- a/sdks/html5-javascript/lib/modules/Collection.js
+++ b/sdks/html5-javascript/lib/modules/Collection.js
@@ -1,4 +1,3 @@
-
 /*
  *  The Collection class models Usergrid Collections.  It essentially
  *  acts as a container for holding Entity objects, while providing
@@ -6,10 +5,9 @@
  *
  *  @constructor
  *  @param {string} options - configuration object
- *  @param {function} callback
- *  @return {callback} callback(err, data)
+ *  @return {Collection} collection
  */
-Usergrid.Collection = function(options, callback) {
+Usergrid.Collection = function(options) {
 
   if (options) {
     this._client = options.client;
@@ -28,17 +26,17 @@ Usergrid.Collection = function(options, callback) {
     //restore entities if available
     if (options.list) {
       var count = options.list.length;
-      for(var i=0;i<count;i++){
+      for (var i = 0; i < count; i++) {
         //make new entity with
         var entity = this._client.restoreEntity(options.list[i]);
         this._list[i] = entity;
       }
     }
   }
-  if (callback) {
+  /*if (callback) {
     //populate the collection
     this.fetch(callback);
-  }
+  }*/
 
 };
 
@@ -51,9 +49,9 @@ Usergrid.Collection = function(options, callback) {
  *  @params {any} obj - any variable
  *  @return {boolean} Returns true or false
  */
-Usergrid.isCollection = function(obj){
+Usergrid.isCollection = function(obj) {
   return (obj && obj instanceof Usergrid.Collection);
-}
+};
 
 
 /*
@@ -62,10 +60,10 @@ Usergrid.isCollection = function(obj){
  *  @method serialize
  *  @return {object} data
  */
-Usergrid.Collection.prototype.serialize = function () {
+Usergrid.Collection.prototype.serialize = function() {
 
   //pull out the state from this object and return it
-  var data = {}
+  var data = {};
   data.type = this._type;
   data.qs = this.qs;
   data.iterator = this._iterator;
@@ -74,9 +72,9 @@ Usergrid.Collection.prototype.serialize = function () {
   data.cursor = this._cursor;
 
   this.resetEntityPointer();
-  var i=0;
+  var i = 0;
   data.list = [];
-  while(this.hasNextEntity()) {
+  while (this.hasNextEntity()) {
     var entity = this.getNextEntity();
     data.list[i] = entity.serialize();
     i++;
@@ -85,8 +83,8 @@ Usergrid.Collection.prototype.serialize = function () {
   data = JSON.stringify(data);
   return data;
 };
-
-Usergrid.Collection.prototype.addCollection = function (collectionName, options, callback) {
+//addCollection is deprecated?
+/*Usergrid.Collection.prototype.addCollection = function (collectionName, options, callback) {
   self = this;
   options.client = this._client;
   var collection = new Usergrid.Collection(options, function(err, data) {
@@ -104,7 +102,7 @@ Usergrid.Collection.prototype.addCollection = function (collectionName, options,
       doCallback(callback, [err, collection], self);
     }
   });
-};
+};*/
 
 /*
  *  Populates the collection from the server
@@ -113,7 +111,7 @@ Usergrid.Collection.prototype.addCollection = function (collectionName, options,
  *  @param {function} callback
  *  @return {callback} callback(err, data)
  */
-Usergrid.Collection.prototype.fetch = function (callback) {
+Usergrid.Collection.prototype.fetch = function(callback) {
   var self = this;
   var qs = this.qs;
 
@@ -124,44 +122,33 @@ Usergrid.Collection.prototype.fetch = function (callback) {
     delete qs.cursor;
   }
   var options = {
-    method:'GET',
-    endpoint:this._type,
-    qs:this.qs
+    method: 'GET',
+    endpoint: this._type,
+    qs: this.qs
   };
-  this._client.request(options, function (err, data) {
-    if(err && self._client.logging) {
+  this._client.request(options, function(err, response) {
+    if (err && self._client.logging) {
       console.log('error getting collection');
     } else {
       //save the cursor if there is one
-      var cursor = data.cursor || null;
-      self.saveCursor(cursor);
-      if (data.entities) {
-        self.resetEntityPointer();
-        var count = data.entities.length;
-        //save entities locally
-        self._list = []; //clear the local list first
-        for (var i=0;i<count;i++) {
-          var uuid = data.entities[i].uuid;
-          if (uuid) {
-            var entityData = data.entities[i] || {};
-            self._baseType = data.entities[i].type; //store the base type in the collection
-            entityData.type = self._type;//make sure entities are same type (have same path) as parent collection.
-            var entityOptions = {
-              type:self._type,
-              client:self._client,
-              uuid:uuid,
-              data:entityData
-            };
-
-            var ent = new Usergrid.Entity(entityOptions);
-            ent._json = JSON.stringify(entityData, null, 2);
-            var ct = self._list.length;
-            self._list[ct] = ent;
-          }
-        }
-      }
+      self.saveCursor(response.cursor || null);
+      self.resetEntityPointer();
+      //save entities locally
+      self._list = response.getEntities()
+        .filter(function(entity) {
+          return isUUID(entity.uuid);
+        })
+        .map(function(entity) {
+          var ent = new Usergrid.Entity({
+            client: self._client
+          });
+          ent.set(entity);
+          ent.type = self._type;
+          //ent._json = JSON.stringify(entity, null, 2);
+          return ent;
+        });
     }
-    doCallback(callback, [err, data], self);
+    doCallback(callback, [err, response, self], self);
   });
 };
 
@@ -173,22 +160,21 @@ Usergrid.Collection.prototype.fetch = function (callback) {
  *  @param {function} callback
  *  @return {callback} callback(err, data, entity)
  */
-Usergrid.Collection.prototype.addEntity = function (options, callback) {
+Usergrid.Collection.prototype.addEntity = function(entityObject, callback) {
   var self = this;
-  options.type = this._type;
+  entityObject.type = this._type;
 
   //create the new entity
-  this._client.createEntity(options, function (err, entity) {
+  this._client.createEntity(entityObject, function(err, response, entity) {
     if (!err) {
       //then add the entity to the list
-      var count = self._list.length;
-      self._list[count] = entity;
+      self.addExistingEntity(entity);
     }
-    doCallback(callback, [err, entity], self);    
+    doCallback(callback, [err, response, self], self);
   });
 };
 
-Usergrid.Collection.prototype.addExistingEntity = function (entity) {
+Usergrid.Collection.prototype.addExistingEntity = function(entity) {
   //entity should already exist in the db, so just add it to the list
   var count = this._list.length;
   this._list[count] = entity;
@@ -202,33 +188,58 @@ Usergrid.Collection.prototype.addExistingEntity = function (entity) {
  *  @param {function} callback
  *  @return {callback} callback(err, data)
  */
-Usergrid.Collection.prototype.destroyEntity = function (entity, callback) {
+Usergrid.Collection.prototype.destroyEntity = function(entity, callback) {
   var self = this;
-  entity.destroy(function(err, data) {
+  entity.destroy(function(err, response) {
     if (err) {
       if (self._client.logging) {
         console.log('could not destroy entity');
       }
-      doCallback(callback, [err, data], self);
+      doCallback(callback, [err, response, self], self);
     } else {
-        //destroy was good, so repopulate the collection
-        self.fetch(callback);
+      //destroy was good, so repopulate the collection
+      self.fetch(callback);
     }
-  });
     //remove entity from the local store
-    this.removeEntity(entity);
+    self.removeEntity(entity);
+  });
 };
 
-
-Usergrid.Collection.prototype.removeEntity = function (entity) {
-  var uuid = entity.get('uuid');
-  for (var key in this._list) {
-    var listItem = this._list[key];
-    if (listItem.get('uuid') === uuid) {
-      return this._list.splice(key, 1);
-    }
-  }
-  return false;
+/*
+ * Filters the list of entities based on the supplied criteria function
+ * works like Array.prototype.filter
+ *
+ *  @method getEntitiesByCriteria
+ *  @param {function} criteria  A function that takes each entity as an argument and returns true or false
+ *  @return {Entity[]} returns a list of entities that caused the criteria function to return true
+ */
+Usergrid.Collection.prototype.getEntitiesByCriteria = function(criteria) {
+  return this._list.filter(criteria);
+};
+/*
+ * Returns the first entity from the list of entities based on the supplied criteria function
+ * works like Array.prototype.filter
+ *
+ *  @method getEntitiesByCriteria
+ *  @param {function} criteria  A function that takes each entity as an argument and returns true or false
+ *  @return {Entity[]} returns a list of entities that caused the criteria function to return true
+ */
+Usergrid.Collection.prototype.getEntityByCriteria = function(criteria) {
+  return this.getEntitiesByCriteria(criteria).shift();
+};
+/*
+ * Removed an entity from the collection without destroying it on the server
+ *
+ *  @method removeEntity
+ *  @param {object} entity
+ *  @return {Entity} returns the removed entity or undefined if it was not found
+ */
+Usergrid.Collection.prototype.removeEntity = function(entity) {
+  var removedEntity = this.getEntityByCriteria(function(item) {
+    return entity.uuid === item.get('uuid');
+  });
+  delete this._list[this._list.indexOf(removedEntity)];
+  return removedEntity;
 };
 
 /*
@@ -239,25 +250,24 @@ Usergrid.Collection.prototype.removeEntity = function (entity) {
  *  @param {function} callback
  *  @return {callback} callback(err, data, entity)
  */
-Usergrid.Collection.prototype.getEntityByUUID = function (uuid, callback) {
-
-  for (var key in this._list) {
-    var listItem = this._list[key];
-    if (listItem.get('uuid') === uuid) {
-        return callback(null, listItem);
-    }
-  }
-
-  //get the entity from the database
-  var options = {
-    data: {
-      type: this._type,
-      uuid:uuid
-    },
-    client: this._client
+Usergrid.Collection.prototype.getEntityByUUID = function(uuid, callback) {
+  var entity = this.getEntityByCriteria(function(item) {
+    return item.get('uuid') === uuid;
+  });
+  if (entity) {
+    doCallback(callback, [null, entity, entity], this);
+  } else {
+    //get the entity from the database
+    var options = {
+      data: {
+        type: this._type,
+        uuid: uuid
+      },
+      client: this._client
+    };
+    entity = new Usergrid.Entity(options);
+    entity.fetch(callback);
   }
-  var entity = new Usergrid.Entity(options);
-  entity.fetch(callback);
 };
 
 /*
@@ -266,7 +276,7 @@ Usergrid.Collection.prototype.getEntityByUUID = function (uuid, callback) {
  *  @method getFirstEntity
  *  @return {object} returns an entity object
  */
-Usergrid.Collection.prototype.getFirstEntity = function () {
+Usergrid.Collection.prototype.getFirstEntity = function() {
   var count = this._list.length;
   if (count > 0) {
     return this._list[0];
@@ -280,10 +290,10 @@ Usergrid.Collection.prototype.getFirstEntity = function () {
  *  @method getLastEntity
  *  @return {object} returns an entity object
  */
-Usergrid.Collection.prototype.getLastEntity = function () {
+Usergrid.Collection.prototype.getLastEntity = function() {
   var count = this._list.length;
   if (count > 0) {
-    return this._list[count-1];
+    return this._list[count - 1];
   }
   return null;
 };
@@ -297,10 +307,10 @@ Usergrid.Collection.prototype.getLastEntity = function () {
  *  @method hasNextEntity
  *  @return {boolean} true if there is a next entity, false if not
  */
-Usergrid.Collection.prototype.hasNextEntity = function () {
+Usergrid.Collection.prototype.hasNextEntity = function() {
   var next = this._iterator + 1;
-  var hasNextElement = (next >=0 && next < this._list.length);
-  if(hasNextElement) {
+  var hasNextElement = (next >= 0 && next < this._list.length);
+  if (hasNextElement) {
     return true;
   }
   return false;
@@ -315,10 +325,10 @@ Usergrid.Collection.prototype.hasNextEntity = function () {
  *  @method hasNextEntity
  *  @return {object} entity
  */
-Usergrid.Collection.prototype.getNextEntity = function () {
+Usergrid.Collection.prototype.getNextEntity = function() {
   this._iterator++;
   var hasNextElement = (this._iterator >= 0 && this._iterator <= this._list.length);
-  if(hasNextElement) {
+  if (hasNextElement) {
     return this._list[this._iterator];
   }
   return false;
@@ -331,10 +341,10 @@ Usergrid.Collection.prototype.getNextEntity = function () {
  *  @method hasPrevEntity
  *  @return {boolean} true if there is a previous entity, false if not
  */
-Usergrid.Collection.prototype.hasPrevEntity = function () {
+Usergrid.Collection.prototype.hasPrevEntity = function() {
   var previous = this._iterator - 1;
-  var hasPreviousElement = (previous >=0 && previous < this._list.length);
-  if(hasPreviousElement) {
+  var hasPreviousElement = (previous >= 0 && previous < this._list.length);
+  if (hasPreviousElement) {
     return true;
   }
   return false;
@@ -346,10 +356,10 @@ Usergrid.Collection.prototype.hasPrevEntity = function () {
  *  @method getPrevEntity
  *  @return {object} entity
  */
-Usergrid.Collection.prototype.getPrevEntity = function () {
+Usergrid.Collection.prototype.getPrevEntity = function() {
   this._iterator--;
   var hasPreviousElement = (this._iterator >= 0 && this._iterator <= this._list.length);
-  if(hasPreviousElement) {
+  if (hasPreviousElement) {
     return this._list[this._iterator];
   }
   return false;
@@ -362,8 +372,8 @@ Usergrid.Collection.prototype.getPrevEntity = function () {
  *  @method resetEntityPointer
  *  @return none
  */
-Usergrid.Collection.prototype.resetEntityPointer = function () {
-  this._iterator  = -1;
+Usergrid.Collection.prototype.resetEntityPointer = function() {
+  this._iterator = -1;
 };
 
 /*
@@ -399,7 +409,7 @@ Usergrid.Collection.prototype.resetPaging = function() {
  *  @method hasNextPage
  *  @return {boolean} returns true if there is a next page of data, false otherwise
  */
-Usergrid.Collection.prototype.hasNextPage = function () {
+Usergrid.Collection.prototype.hasNextPage = function() {
   return (this._next);
 };
 
@@ -412,7 +422,7 @@ Usergrid.Collection.prototype.hasNextPage = function () {
  *  @param {function} callback
  *  @return {callback} callback(err, data)
  */
-Usergrid.Collection.prototype.getNextPage = function (callback) {
+Usergrid.Collection.prototype.getNextPage = function(callback) {
   if (this.hasNextPage()) {
     //set the cursor to the next page of data
     this._previous.push(this._cursor);
@@ -421,7 +431,7 @@ Usergrid.Collection.prototype.getNextPage = function (callback) {
     this._list = [];
     this.fetch(callback);
   }
-}
+};
 
 /*
  *  Paging -  checks to see if there is a previous page od data
@@ -429,7 +439,7 @@ Usergrid.Collection.prototype.getNextPage = function (callback) {
  *  @method hasPreviousPage
  *  @return {boolean} returns true if there is a previous page of data, false otherwise
  */
-Usergrid.Collection.prototype.hasPreviousPage = function () {
+Usergrid.Collection.prototype.hasPreviousPage = function() {
   return (this._previous.length > 0);
 };
 
@@ -442,9 +452,9 @@ Usergrid.Collection.prototype.hasPreviousPage = function () {
  *  @param {function} callback
  *  @return {callback} callback(err, data)
  */
-Usergrid.Collection.prototype.getPreviousPage = function (callback) {
+Usergrid.Collection.prototype.getPreviousPage = function(callback) {
   if (this.hasPreviousPage()) {
-    this._next=null; //clear out next so the comparison will find the next item
+    this._next = null; //clear out next so the comparison will find the next item
     this._cursor = this._previous.pop();
     //empty the list
     this._list = [];

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/da8ecfff/sdks/html5-javascript/lib/modules/Counter.js
----------------------------------------------------------------------
diff --git a/sdks/html5-javascript/lib/modules/Counter.js b/sdks/html5-javascript/lib/modules/Counter.js
index b6d211f..5de76c8 100644
--- a/sdks/html5-javascript/lib/modules/Counter.js
+++ b/sdks/html5-javascript/lib/modules/Counter.js
@@ -6,17 +6,17 @@
  *  @returns {callback} callback(err, event)
  */
 Usergrid.Counter = function(options, callback) {
-  var self=this;
+  // var self=this;
   this._client = options.client;
   this._data = options.data || {};
-  this._data.category = options.category||"UNKNOWN";
-  this._data.timestamp = options.timestamp||0;
+  this._data.category = options.category || "UNKNOWN";
+  this._data.timestamp = options.timestamp || 0;
   this._data.type = "events";
-  this._data.counters=options.counters||{};
-  doCallback(callback, [false, self], self);
+  this._data.counters = options.counters || {};
+  doCallback(callback, [false, this], this);
   //this.save(callback);
 };
-var COUNTER_RESOLUTIONS=[
+var COUNTER_RESOLUTIONS = [
   'all', 'minute', 'five_minutes', 'half_hour',
   'hour', 'six_day', 'day', 'week', 'month'
 ];
@@ -36,9 +36,9 @@ Usergrid.Counter.prototype = new Usergrid.Entity();
  * @param {function} callback
  * @returns {callback} callback(err, event)
  */
-Usergrid.Counter.prototype.fetch=function(callback){
+Usergrid.Counter.prototype.fetch = function(callback) {
   this.getData({}, callback);
-}
+};
 /*
  * increments the counter for a specific event
  *
@@ -50,16 +50,16 @@ Usergrid.Counter.prototype.fetch=function(callback){
  * @param {function} callback
  * @returns {callback} callback(err, event)
  */
-Usergrid.Counter.prototype.increment=function(options, callback){
-  var self=this,
-    name=options.name,
-    value=options.value;
-  if(!name){
-    return doCallback(callback, [true, "'name' for increment, decrement must be a number"], self);
-  }else if(isNaN(value)){
-    return doCallback(callback, [true, "'value' for increment, decrement must be a number"], self);
-  }else{
-    self._data.counters[name]=(parseInt(value))||1;
+Usergrid.Counter.prototype.increment = function(options, callback) {
+  var self = this,
+    name = options.name,
+    value = options.value;
+  if (!name) {
+    return doCallback(callback, [new UsergridInvalidArgumentError("'name' for increment, decrement must be a number"), null, self], self);
+  } else if (isNaN(value)) {
+    return doCallback(callback, [new UsergridInvalidArgumentError("'value' for increment, decrement must be a number"), null, self], self);
+  } else {
+    self._data.counters[name] = (parseInt(value)) || 1;
     return self.save(callback);
   }
 };
@@ -75,11 +75,14 @@ Usergrid.Counter.prototype.increment=function(options, callback){
  * @returns {callback} callback(err, event)
  */
 
-Usergrid.Counter.prototype.decrement=function(options, callback){
-  var self=this,
-    name=options.name,
-    value=options.value;
-  self.increment({name:name, value:-((parseInt(value))||1)}, callback);
+Usergrid.Counter.prototype.decrement = function(options, callback) {
+  var self = this,
+    name = options.name,
+    value = options.value;
+  self.increment({
+    name: name,
+    value: -((parseInt(value)) || 1)
+  }, callback);
 };
 /*
  * resets the counter for a specific event
@@ -93,10 +96,13 @@ Usergrid.Counter.prototype.decrement=function(options, callback){
  * @returns {callback} callback(err, event)
  */
 
-Usergrid.Counter.prototype.reset=function(options, callback){
-  var self=this,
-    name=options.name;
-  self.increment({name:name, value:0}, callback);
+Usergrid.Counter.prototype.reset = function(options, callback) {
+  var self = this,
+    name = options.name;
+  self.increment({
+    name: name,
+    value: 0
+  }, callback);
 };
 
 /*
@@ -116,63 +122,55 @@ Usergrid.Counter.prototype.reset=function(options, callback){
  * @param {function} callback
  * @returns {callback} callback(err, event)
  */
-Usergrid.Counter.prototype.getData=function(options, callback){
-  var start_time, 
-      end_time,
-      start=options.start||0,
-      end=options.end||Date.now(),
-      resolution=(options.resolution||'all').toLowerCase(),
-      counters=options.counters||Object.keys(this._data.counters),
-      res=(resolution||'all').toLowerCase();
-  if(COUNTER_RESOLUTIONS.indexOf(res)===-1){
-    res='all';
-  }
-  if(start){
-    switch(typeof start){
-      case "undefined":
-        start_time=0;
-        break;
-      case "number":
-        start_time=start;
-        break;
-      case "string":
-        start_time=(isNaN(start))?Date.parse(start):parseInt(start);
-        break;
-      default:
-        start_time=Date.parse(start.toString());
-    }
-  }
-  if(end){
-    switch(typeof end){
-      case "undefined":
-        end_time=Date.now();
-        break;
-      case "number":
-        end_time=end;
-        break;
-      case "string":
-        end_time=(isNaN(end))?Date.parse(end):parseInt(end);
-        break;
-      default:
-        end_time=Date.parse(end.toString());
-    }
+Usergrid.Counter.prototype.getData = function(options, callback) {
+  var start_time,
+    end_time,
+    start = options.start || 0,
+    end = options.end || Date.now(),
+    resolution = (options.resolution || 'all').toLowerCase(),
+    counters = options.counters || Object.keys(this._data.counters),
+    res = (resolution || 'all').toLowerCase();
+  if (COUNTER_RESOLUTIONS.indexOf(res) === -1) {
+    res = 'all';
   }
-  var self=this;
+  start_time = getSafeTime(start);
+  end_time = getSafeTime(end);
+  var self = this;
   //https://api.usergrid.com/yourorgname/sandbox/counters?counter=test_counter
-  var params=Object.keys(counters).map(function(counter){
-      return ["counter", encodeURIComponent(counters[counter])].join('=');
-    });
-  params.push('resolution='+res)
-  params.push('start_time='+String(start_time))
-  params.push('end_time='+String(end_time))
-    
-  var endpoint="counters?"+params.join('&');
-  this._client.request({endpoint:endpoint}, function(err, data){
-    if(data.counters && data.counters.length){
-      data.counters.forEach(function(counter){
-        self._data.counters[counter.name]=counter.value||counter.values;
-      })
+  var params = Object.keys(counters).map(function(counter) {
+    return ["counter", encodeURIComponent(counters[counter])].join('=');
+  });
+  params.push('resolution=' + res);
+  params.push('start_time=' + String(start_time));
+  params.push('end_time=' + String(end_time));
+
+  var endpoint = "counters?" + params.join('&');
+  this._client.request({
+    endpoint: endpoint
+  }, function(err, data) {
+    if (data.counters && data.counters.length) {
+      data.counters.forEach(function(counter) {
+        self._data.counters[counter.name] = counter.value || counter.values;
+      });
     }
-    return doCallback(callback, [err, data], self);
-  })
+    return doCallback(callback, [err, data, self], self);
+  });
 };
+
+function getSafeTime(prop) {
+  var time;
+  switch (typeof prop) {
+    case "undefined":
+      time = Date.now();
+      break;
+    case "number":
+      time = prop;
+      break;
+    case "string":
+      time = (isNaN(prop)) ? Date.parse(prop) : parseInt(prop);
+      break;
+    default:
+      time = Date.parse(prop.toString());
+  }
+  return time;
+}


[08/12] git commit: Added convenience methods for createAsset and createCounter

Posted by sn...@apache.org.
Added convenience methods for createAsset and createCounter


Project: http://git-wip-us.apache.org/repos/asf/incubator-usergrid/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-usergrid/commit/3c47925e
Tree: http://git-wip-us.apache.org/repos/asf/incubator-usergrid/tree/3c47925e
Diff: http://git-wip-us.apache.org/repos/asf/incubator-usergrid/diff/3c47925e

Branch: refs/heads/master
Commit: 3c47925e72db0dc06a09f1175634248b1057b92a
Parents: bc03fb8
Author: ryan bridges <rb...@apigee.com>
Authored: Tue Apr 1 14:18:37 2014 -0400
Committer: ryan bridges <rb...@apigee.com>
Committed: Tue Apr 1 14:18:37 2014 -0400

----------------------------------------------------------------------
 sdks/html5-javascript/lib/modules/Client.js  | 49 +++++++++++++
 sdks/html5-javascript/lib/modules/Counter.js |  4 +-
 sdks/html5-javascript/tests/mocha/test.js    | 42 +++++++-----
 sdks/html5-javascript/usergrid.js            | 83 ++++++++++++++++++++---
 sdks/html5-javascript/usergrid.min.js        |  4 +-
 5 files changed, 149 insertions(+), 33 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/3c47925e/sdks/html5-javascript/lib/modules/Client.js
----------------------------------------------------------------------
diff --git a/sdks/html5-javascript/lib/modules/Client.js b/sdks/html5-javascript/lib/modules/Client.js
index d9ab1b2..a87c935 100644
--- a/sdks/html5-javascript/lib/modules/Client.js
+++ b/sdks/html5-javascript/lib/modules/Client.js
@@ -207,6 +207,55 @@
     var entity = new Usergrid.Entity(options);
     return entity;
   };
+  /*
+   *  Main function for creating new counters - should be called directly.
+   *
+   *  options object: options {timestamp:0, category:'value', counters:{name : value}}
+   *
+   *  @method createCounter
+   *  @public
+   *  @params {object} options
+   *  @param {function} callback
+   *  @return {callback} callback(err, response, counter)
+   */
+  Usergrid.Client.prototype.createCounter = function(options, callback) {
+    var counter = new Usergrid.Counter({
+      client: this,
+      data: options
+    });
+    counter.save(callback);
+  };
+  /*
+   *  Main function for creating new assets - should be called directly.
+   *
+   *  options object: options {name:"photo.jpg", path:"/user/uploads", "content-type":"image/jpeg", owner:"F01DE600-0000-0000-0000-000000000000", file: FileOrBlobObject }
+   *
+   *  @method createCounter
+   *  @public
+   *  @params {object} options
+   *  @param {function} callback
+   *  @return {callback} callback(err, response, counter)
+   */
+  Usergrid.Client.prototype.createAsset = function(options, callback) {
+    var file=options.file;
+    if(file){
+      options.name=options.name||file.name;
+      options['content-type']=options['content-type']||file.type;
+      options.path=options.path||'/';
+      delete options.file;
+    }
+    var asset = new Usergrid.Asset({
+      client: this,
+      data: options
+    });
+    asset.save(function(err, response, asset){
+      if(file && !err){
+        asset.upload(file, callback);
+      }else{
+        doCallback(callback, [err, response, asset], asset);
+      }
+    });
+  };
 
   /*
    *  Main function for creating new collections - should be called directly.

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/3c47925e/sdks/html5-javascript/lib/modules/Counter.js
----------------------------------------------------------------------
diff --git a/sdks/html5-javascript/lib/modules/Counter.js b/sdks/html5-javascript/lib/modules/Counter.js
index 5de76c8..03953f5 100644
--- a/sdks/html5-javascript/lib/modules/Counter.js
+++ b/sdks/html5-javascript/lib/modules/Counter.js
@@ -5,7 +5,7 @@
  *  @param {object} options {timestamp:0, category:'value', counters:{name : value}}
  *  @returns {callback} callback(err, event)
  */
-Usergrid.Counter = function(options, callback) {
+Usergrid.Counter = function(options) {
   // var self=this;
   this._client = options.client;
   this._data = options.data || {};
@@ -13,7 +13,7 @@ Usergrid.Counter = function(options, callback) {
   this._data.timestamp = options.timestamp || 0;
   this._data.type = "events";
   this._data.counters = options.counters || {};
-  doCallback(callback, [false, this], this);
+  // doCallback(callback, [false, this], this);
   //this.save(callback);
 };
 var COUNTER_RESOLUTIONS = [

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/3c47925e/sdks/html5-javascript/tests/mocha/test.js
----------------------------------------------------------------------
diff --git a/sdks/html5-javascript/tests/mocha/test.js b/sdks/html5-javascript/tests/mocha/test.js
index d27949c..a00ff6e 100644
--- a/sdks/html5-javascript/tests/mocha/test.js
+++ b/sdks/html5-javascript/tests/mocha/test.js
@@ -800,11 +800,9 @@ describe('Usergrid', function(){
                         test_counter: 0
                     }
                 }
-            }, function(err, data) {
-                assert(!err, data.error_description);
-                console.log(data);
-                done();
             });
+            assert(counter, "Counter not created");
+            done();
         });
         it('should save a counter', function(done) {
             counter.save(function(err, data) {
@@ -902,7 +900,6 @@ describe('Usergrid', function(){
             req.onload = function() {
                 test_image = req.response;
                 image_type = req.getResponseHeader('Content-Type');
-                console.log(test_image, image_type);
                 done();
             }
             req.onerror = function(err) {
@@ -1011,24 +1008,33 @@ describe('Usergrid', function(){
                 done();
             });
         });
+        it('should RETRIEVE an asset', function(done) {
+            asset.fetch(function(err, response, entity){
+                if(err){
+                    assert(false, err);
+                }else{
+                    asset=entity;
+                }
+                done();
+            })
+        });
         it('should upload asset data', function(done) {
-            this.timeout(15000);
-            setTimeout(function() {
-                asset.upload(test_image, function(err, response, asset) {
-                    if(err){
-                        assert(false, err.error_description);
-                    }
-                    done();
-                });
-            }, 10000);
+            this.timeout(5000);
+            asset.upload(test_image, function(err, response, asset) {
+                if(err){
+                    assert(false, err.error_description);
+                }
+                done();
+            });
         });
         it('should retrieve asset data', function(done) {
+            this.timeout(5000);
             asset.download(function(err, response, asset) {
                 if(err){
                     assert(false, err.error_description);
                 }
-                assert(asset.type == test_image.type, "MIME types don't match");
-                assert(asset.size == test_image.size, "sizes don't match");
+                assert(asset.get('content-type') == test_image.type, "MIME types don't match");
+                assert(asset.get('size') == test_image.size, "sizes don't match");
                 done();
             });
         });
@@ -1063,7 +1069,7 @@ describe('Usergrid', function(){
                 done();
             })
         });
-        it('should DELETE the asset', function(done) {
+        after(function(done) {
             asset.destroy(function(err, data) {
                 if(err){
                     assert(false, err.error_description);
@@ -1072,7 +1078,7 @@ describe('Usergrid', function(){
                 done();
             })
         });
-        it('should DELETE the folder', function(done) {
+        after(function(done) {
             folder.destroy(function(err, data) {
                 if(err){
                     assert(false, err.error_description);

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/3c47925e/sdks/html5-javascript/usergrid.js
----------------------------------------------------------------------
diff --git a/sdks/html5-javascript/usergrid.js b/sdks/html5-javascript/usergrid.js
index 98fa616..79ab355 100644
--- a/sdks/html5-javascript/usergrid.js
+++ b/sdks/html5-javascript/usergrid.js
@@ -747,6 +747,55 @@ function doCallback(callback, params, context) {
         return entity;
     };
     /*
+   *  Main function for creating new counters - should be called directly.
+   *
+   *  options object: options {timestamp:0, category:'value', counters:{name : value}}
+   *
+   *  @method createCounter
+   *  @public
+   *  @params {object} options
+   *  @param {function} callback
+   *  @return {callback} callback(err, response, counter)
+   */
+    Usergrid.Client.prototype.createCounter = function(options, callback) {
+        var counter = new Usergrid.Counter({
+            client: this,
+            data: options
+        });
+        counter.save(callback);
+    };
+    /*
+   *  Main function for creating new assets - should be called directly.
+   *
+   *  options object: options {name:"photo.jpg", path:"/user/uploads", "content-type":"image/jpeg", owner:"F01DE600-0000-0000-0000-000000000000", file: FileOrBlobObject }
+   *
+   *  @method createCounter
+   *  @public
+   *  @params {object} options
+   *  @param {function} callback
+   *  @return {callback} callback(err, response, counter)
+   */
+    Usergrid.Client.prototype.createAsset = function(options, callback) {
+        var file = options.file;
+        if (file) {
+            options.name = options.name || file.name;
+            options["content-type"] = options["content-type"] || file.type;
+            options.path = options.path || "/";
+            delete options.file;
+        }
+        var asset = new Usergrid.Asset({
+            client: this,
+            data: options
+        });
+        asset.save(function(err, response, asset) {
+            if (file && !err) {
+                asset.upload(file, callback);
+            } else {
+                doCallback(callback, [ err, response, asset ], asset);
+            }
+        });
+    };
+    /*
    *  Main function for creating new collections - should be called directly.
    *
    *  options object: options {client:client, type: type, qs:qs}
@@ -2487,7 +2536,7 @@ Usergrid.Group.prototype.createGroupActivity = function(options, callback) {
  *  @param {object} options {timestamp:0, category:'value', counters:{name : value}}
  *  @returns {callback} callback(err, event)
  */
-Usergrid.Counter = function(options, callback) {
+Usergrid.Counter = function(options) {
     // var self=this;
     this._client = options.client;
     this._data = options.data || {};
@@ -2495,7 +2544,6 @@ Usergrid.Counter = function(options, callback) {
     this._data.timestamp = options.timestamp || 0;
     this._data.type = "events";
     this._data.counters = options.counters || {};
-    doCallback(callback, [ false, this ], this);
 };
 
 var COUNTER_RESOLUTIONS = [ "all", "minute", "five_minutes", "half_hour", "hour", "six_day", "day", "week", "month" ];
@@ -2925,18 +2973,32 @@ Usergrid.Asset.prototype.upload = function(data, callback) {
         return;
     }
     var self = this;
+    var args = arguments;
+    var attempts = self.get("attempts");
+    if (isNaN(attempts)) {
+        attempts = 3;
+    }
+    self.set("content-type", data.type);
+    self.set("size", data.size);
     var endpoint = [ this._client.URI, this._client.orgName, this._client.appName, "assets", self.get("uuid"), "data" ].join("/");
     //self._client.buildAssetURL(self.get("uuid"));
     var xhr = new XMLHttpRequest();
     xhr.open("POST", endpoint, true);
     xhr.onerror = function(err) {
         //callback(true, err);
-        doCallback(callback, [ true, new UsergridError("The File APIs are not fully supported by your browser.") ], self);
+        doCallback(callback, [ new UsergridError("The File APIs are not fully supported by your browser.") ], xhr, self);
     };
     xhr.onload = function(ev) {
-        if (xhr.status >= 300) {
-            doCallback(callback, [ new UsergridError(JSON.parse(xhr.responseText)), null, self ], self);
+        if (xhr.status >= 500 && attempts > 0) {
+            self.set("attempts", --attempts);
+            setTimeout(function() {
+                self.upload.apply(self, args);
+            }, 100);
+        } else if (xhr.status >= 300) {
+            self.set("attempts");
+            doCallback(callback, [ new UsergridError(JSON.parse(xhr.responseText)), xhr, self ], self);
         } else {
+            self.set("attempts");
             doCallback(callback, [ null, xhr, self ], self);
         }
     };
@@ -2944,9 +3006,8 @@ Usergrid.Asset.prototype.upload = function(data, callback) {
     fr.onload = function() {
         var binary = fr.result;
         xhr.overrideMimeType("application/octet-stream");
-        setTimeout(function() {
-            xhr.sendAsBinary(binary);
-        }, 1e3);
+        // setTimeout(function() {
+        xhr.sendAsBinary(binary);
     };
     fr.readAsBinaryString(data);
 };
@@ -2966,13 +3027,13 @@ Usergrid.Asset.prototype.download = function(callback) {
     xhr.responseType = "blob";
     xhr.onload = function(ev) {
         var blob = xhr.response;
-        //callback(null, blob);
-        doCallback(callback, [ null, blob, self ], self);
+        doCallback(callback, [ null, xhr, self ], self);
     };
     xhr.onerror = function(err) {
         callback(true, err);
-        doCallback(callback, [ new UsergridError(err), err, self ], self);
+        doCallback(callback, [ new UsergridError(err), xhr, self ], self);
     };
+    xhr.overrideMimeType(self.get("content-type"));
     xhr.send();
 };
 


[03/12] Refactored individual modules for standard callback signature and updated tests

Posted by sn...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/da8ecfff/sdks/html5-javascript/usergrid.js
----------------------------------------------------------------------
diff --git a/sdks/html5-javascript/usergrid.js b/sdks/html5-javascript/usergrid.js
index 45696bf..98fa616 100644
--- a/sdks/html5-javascript/usergrid.js
+++ b/sdks/html5-javascript/usergrid.js
@@ -1,4 +1,4 @@
-/*! usergrid@0.11.0 2014-03-21 */
+/*! usergrid@0.11.0 2014-04-01 */
 var UsergridEventable = function() {
     throw Error("'UsergridEventable' is not intended to be invoked directly");
 };
@@ -110,9 +110,6 @@ UsergridEventable.mixin = function(destObject) {
         this.result = null;
         this.callbacks = [];
     }
-    Promise.prototype.create = function() {
-        return new Promise();
-    };
     Promise.prototype.then = function(callback, context) {
         var f = function() {
             return callback.apply(context, arguments);
@@ -208,8 +205,11 @@ UsergridEventable.mixin = function(destObject) {
             self.logger.time(m + " " + u);
             (function(xhr) {
                 xhr.onreadystatechange = function() {
-                    this.readyState ^ 4 || (self.logger.timeEnd(m + " " + u), clearTimeout(timeout), 
-                    p.done(null, this));
+                    if (this.readyState === 4) {
+                        self.logger.timeEnd(m + " " + u);
+                        clearTimeout(timeout);
+                        p.done(null, this);
+                    }
                 };
                 xhr.onerror = function(response) {
                     clearTimeout(timeout);
@@ -419,6 +419,7 @@ function doCallback(callback, params, context) {
 //noinspection ThisExpressionReferencesGlobalObjectJS
 (function(global) {
     var name = "Usergrid", overwrittenName = global[name];
+    var VALID_REQUEST_METHODS = [ "GET", "POST", "PUT", "DELETE" ];
     function Usergrid() {
         this.logger = new Logger(name);
     }
@@ -426,7 +427,6 @@ function doCallback(callback, params, context) {
         //TODO actually implement this
         return true;
     };
-    var VALID_REQUEST_METHODS = [ "GET", "POST", "PUT", "DELETE" ];
     Usergrid.Request = function(method, endpoint, query_params, data, callback) {
         var p = new Promise();
         /*
@@ -519,14 +519,19 @@ function doCallback(callback, params, context) {
         });
         switch (this.statusGroup) {
           case 200:
+            //success
             this.success = true;
             break;
 
           case 400:
-          case 500:
-          case 300:
-          case 100:
-          default:
+          //user error
+            case 500:
+          //server error
+            case 300:
+          //cache and redirects
+            case 100:
+          //upgrade
+            default:
             //server error
             this.success = false;
             break;
@@ -539,11 +544,11 @@ function doCallback(callback, params, context) {
         return p;
     };
     Usergrid.Response.prototype.getEntities = function() {
-        var entities = [];
+        var entities;
         if (this.success) {
             entities = this.data ? this.data.entities : this.entities;
         }
-        return entities;
+        return entities || [];
     };
     Usergrid.Response.prototype.getEntity = function() {
         var entities = this.getEntities();
@@ -562,6 +567,7 @@ function doCallback(callback, params, context) {
 
 (function() {
     var name = "Client", global = this, overwrittenName = global[name], exports;
+    var AUTH_ERRORS = [ "auth_expired_session_token", "auth_missing_credentials", "auth_unverified_oath", "expired_token", "unauthorized", "auth_invalid" ];
     Usergrid.Client = function(options) {
         //usergrid endpoint
         this.URI = options.URI || "https://api.usergrid.com";
@@ -578,11 +584,6 @@ function doCallback(callback, params, context) {
         //other options
         this.buildCurl = options.buildCurl || false;
         this.logging = options.logging || false;
-        //timeout and callbacks
-        this._callTimeout = options.callTimeout || 3e4;
-        //default to 30 seconds
-        this._callTimeoutCallback = options.callTimeoutCallback || null;
-        this.logoutCallback = options.logoutCallback || null;
     };
     /*
    *  Main function for making requests to the API.  Can be called directly.
@@ -601,7 +602,6 @@ function doCallback(callback, params, context) {
    *  @return {callback} callback(err, data)
    */
     Usergrid.Client.prototype.request = function(options, callback) {
-        var self = this;
         var method = options.method || "GET";
         var endpoint = options.endpoint;
         var body = options.body || {};
@@ -612,11 +612,11 @@ function doCallback(callback, params, context) {
         var appName = this.get("appName");
         var default_qs = this.getObject("default_qs");
         var uri;
-        var logoutCallback = function() {
-            if (typeof this.logoutCallback === "function") {
-                return this.logoutCallback(true, "no_org_or_app_name_specified");
-            }
-        }.bind(this);
+        /*var logoutCallback=function(){
+        if (typeof(this.logoutCallback) === 'function') {
+            return this.logoutCallback(true, 'no_org_or_app_name_specified');
+        }
+    }.bind(this);*/
         if (!mQuery && !orgName && !appName) {
             return logoutCallback();
         }
@@ -631,11 +631,16 @@ function doCallback(callback, params, context) {
         if (default_qs) {
             qs = propCopy(qs, default_qs);
         }
+        var self = this;
         var req = new Usergrid.Request(method, uri, qs, body, function(err, response) {
-            if ([ "auth_expired_session_token", "auth_missing_credentials", "auth_unverified_oath", "expired_token", "unauthorized", "auth_invalid" ].indexOf(response.error) !== -1) {
-                return logoutCallback();
+            /*if (AUTH_ERRORS.indexOf(response.error) !== -1) {
+            return logoutCallback();
+        }*/
+            if (err) {
+                doCallback(callback, [ err, response, self ], self);
+            } else {
+                doCallback(callback, [ null, response, self ], self);
             }
-            doCallback(callback, [ err, response ]);
         });
     };
     /*
@@ -670,14 +675,13 @@ function doCallback(callback, params, context) {
    *  @return {callback} callback(err, data)
    */
     Usergrid.Client.prototype.createGroup = function(options, callback) {
-        options = {
+        var group = new Usergrid.Group({
             path: options.path,
             client: this,
             data: options
-        };
-        var group = new Usergrid.Group(options);
-        group.save(function(err, data) {
-            doCallback(callback, [ err, group, data ]);
+        });
+        group.save(function(err, response) {
+            doCallback(callback, [ err, response, group ], group);
         });
     };
     /*
@@ -692,14 +696,12 @@ function doCallback(callback, params, context) {
    *  @return {callback} callback(err, data)
    */
     Usergrid.Client.prototype.createEntity = function(options, callback) {
-        var entity_data = {
+        var entity = new Usergrid.Entity({
             client: this,
             data: options
-        };
-        var entity = new Usergrid.Entity(entity_data);
-        var self = this;
-        entity.save(function(err, data) {
-            doCallback(callback, [ err, entity, data ]);
+        });
+        entity.save(function(err, response) {
+            doCallback(callback, [ err, response, entity ], entity);
         });
     };
     /*
@@ -717,13 +719,12 @@ function doCallback(callback, params, context) {
    *  @return {callback} callback(err, data)
    */
     Usergrid.Client.prototype.getEntity = function(options, callback) {
-        var options = {
+        var entity = new Usergrid.Entity({
             client: this,
             data: options
-        };
-        var entity = new Usergrid.Entity(options);
-        entity.fetch(function(err, data) {
-            doCallback(callback, [ err, entity, data ]);
+        });
+        entity.fetch(function(err, response) {
+            doCallback(callback, [ err, response, entity ], entity);
         });
     };
     /*
@@ -758,8 +759,9 @@ function doCallback(callback, params, context) {
    */
     Usergrid.Client.prototype.createCollection = function(options, callback) {
         options.client = this;
-        new Usergrid.Collection(options, function(err, data, collection) {
-            doCallback(callback, [ err, collection, data ]);
+        var collection = new Usergrid.Collection(options);
+        collection.fetch(function(err, response, collection) {
+            doCallback(callback, [ err, response, collection ], this);
         });
     };
     /*
@@ -837,13 +839,13 @@ function doCallback(callback, params, context) {
    */
     Usergrid.Client.prototype.createUserActivity = function(user, options, callback) {
         options.type = "users/" + user + "/activities";
-        var options = {
+        options = {
             client: this,
             data: options
         };
         var entity = new Usergrid.Entity(options);
         entity.save(function(err, data) {
-            doCallback(callback, [ err, entity ]);
+            doCallback(callback, [ err, data, entity ]);
         });
     };
     /*
@@ -1168,24 +1170,24 @@ function doCallback(callback, params, context) {
         this.setToken();
     };
     /*
-    *  A public method to destroy access tokens on the server
-    *
-    *  @method logout
-    *  @public    
-    *	 @param {string} username	the user associated with the token to revoke
-    *	 @param {string} token set to 'null' to revoke the token of the currently logged in user 
-    *  	 or set to token value to revoke a specific token
-    *	 @param {string} revokeAll set to 'true' to revoke all tokens for the user            
-    *  @return none
-    */
+   *  A public method to destroy access tokens on the server
+   *
+   *  @method logout
+   *  @public
+   *  @param {string} username	the user associated with the token to revoke
+   *  @param {string} token set to 'null' to revoke the token of the currently logged in user
+   *    or set to token value to revoke a specific token
+   *  @param {string} revokeAll set to 'true' to revoke all tokens for the user
+   *  @return none
+   */
     Usergrid.Client.prototype.destroyToken = function(username, token, revokeAll, callback) {
         var options = {
             client: self,
             method: "PUT"
         };
-        if (revokeAll == true) {
+        if (revokeAll === true) {
             options.endpoint = "users/" + username + "/revoketokens";
-        } else if (token == null) {
+        } else if (token === null) {
             options.endpoint = "users/" + username + "/revoketoken?token=" + this.getToken();
         } else {
             options.endpoint = "users/" + username + "/revoketoken?token=" + token;
@@ -1197,7 +1199,7 @@ function doCallback(callback, params, context) {
                 }
                 doCallback(callback, [ err, data, null ], self);
             } else {
-                if (revokeAll == true) {
+                if (revokeAll === true) {
                     console.log("all user tokens invalidated");
                 } else {
                     console.log("token invalidated");
@@ -1207,23 +1209,23 @@ function doCallback(callback, params, context) {
         });
     };
     /*
-    *  A public method to log out an app user - clears all user fields from client
-    *  and destroys the access token on the server.
-    *
-    *  @method logout
-    *  @public
-    *	 @param {string} username the user associated with the token to revoke
-    *	 @param {string} token set to 'null' to revoke the token of the currently logged in user 
-    *  	 or set to token value to revoke a specific token
-    *	 @param {string} revokeAll set to 'true' to revoke all tokens for the user        
-    *  @return none
-    */
+   *  A public method to log out an app user - clears all user fields from client
+   *  and destroys the access token on the server.
+   *
+   *  @method logout
+   *  @public
+   *  @param {string} username the user associated with the token to revoke
+   *  @param {string} token set to 'null' to revoke the token of the currently logged in user
+   *   or set to token value to revoke a specific token
+   *  @param {string} revokeAll set to 'true' to revoke all tokens for the user
+   *  @return none
+   */
     Usergrid.Client.prototype.logoutAndDestroyToken = function(username, token, revokeAll, callback) {
-        if (username == null) {
+        if (username === null) {
             console.log("username required to revoke tokens");
         } else {
             this.destroyToken(username, token, revokeAll, callback);
-            if (revokeAll == true || token == this.getToken() || token == null) {
+            if (revokeAll === true || token === this.getToken() || token === null) {
                 this.setToken(null);
             }
         }
@@ -1288,8 +1290,11 @@ var ENTITY_SYSTEM_PROPERTIES = [ "metadata", "created", "modified", "oldpassword
  *  @param {object} options {client:client, data:{'type':'collection_type', uuid:'uuid', 'key':'value'}}
  */
 Usergrid.Entity = function(options) {
+    this._data = {};
+    this._client = undefined;
     if (options) {
-        this._data = options.data || {};
+        //this._data = options.data || {};
+        this.set(options.data || {});
         this._client = options.client || {};
     }
 };
@@ -1391,22 +1396,16 @@ Usergrid.Entity.prototype.set = function(key, value) {
 };
 
 Usergrid.Entity.prototype.getEndpoint = function() {
-    var type = this.get("type"), name, endpoint;
-    var nameProperties = [ "uuid", "name" ];
+    var type = this.get("type"), nameProperties = [ "uuid", "name" ], name;
     if (type === undefined) {
         throw new UsergridError("cannot fetch entity, no entity type specified", "no_type_specified");
-    } else if (type === "users" || type === "user") {
+    } else if (/^users?$/.test(type)) {
         nameProperties.unshift("username");
     }
-    var names = this.get(nameProperties).filter(function(x) {
-        return x != null && "undefined" !== typeof x;
-    });
-    if (names.length === 0) {
-        return type;
-    } else {
-        name = names.shift();
-    }
-    return [ type, name ].join("/");
+    name = this.get(nameProperties).filter(function(x) {
+        return x !== null && "undefined" !== typeof x;
+    }).shift();
+    return name ? [ type, name ].join("/") : type;
 };
 
 /*
@@ -1415,77 +1414,83 @@ Usergrid.Entity.prototype.getEndpoint = function() {
  *  @method save
  *  @public
  *  @param {function} callback
- *  @return {callback} callback(err, data)
+ *  @return {callback} callback(err, response, self)
  */
 Usergrid.Entity.prototype.save = function(callback) {
-    var self = this, type = this.get("type"), method = "POST", entityId = this.get("uuid"), data = {}, entityData = this.get(), password = this.get("password"), oldpassword = this.get("oldpassword"), newpassword = this.get("newpassword"), options = {
+    var self = this, type = this.get("type"), method = "POST", entityId = this.get("uuid"), changePassword, entityData = this.get(), options = {
         method: method,
         endpoint: type
     };
-    //update the entity
+    //update the entity if the UUID is present
     if (entityId) {
         options.method = "PUT";
         options.endpoint += "/" + entityId;
     }
     //remove system-specific properties
-    Object.keys(entityData).filter(function(key) {
+    options.body = Object.keys(entityData).filter(function(key) {
         return ENTITY_SYSTEM_PROPERTIES.indexOf(key) === -1;
-    }).forEach(function(key) {
+    }).reduce(function(data, key) {
         data[key] = entityData[key];
-    });
-    options.body = data;
-    //save the entity first
-    this._client.request(options, function(err, response) {
+        return data;
+    }, {});
+    self._client.request(options, function(err, response) {
         var entity = response.getEntity();
         if (entity) {
             self.set(entity);
             self.set("type", /^\//.test(response.path) ? response.path.substring(1) : response.path);
         }
-        //      doCallback(callback,[err, self]);
-        /*
-        TODO move user logic to its own entity
-       */
-        //clear out pw info if present
-        self.set("password", null);
-        self.set("oldpassword", null);
-        self.set("newpassword", null);
         if (err && self._client.logging) {
             console.log("could not save entity");
-            doCallback(callback, [ err, response, self ]);
-        } else if (/^users?/.test(self.get("type")) && oldpassword && newpassword) {
-            //if this is a user, update the password if it has been specified;
-            //Note: we have a ticket in to change PUT calls to /users to accept the password change
-            //      once that is done, we will remove this call and merge it all into one
-            var options = {
-                method: "PUT",
-                endpoint: type + "/" + self.get("uuid") + "/password",
-                body: {
-                    uuid: self.get("uuid"),
-                    username: self.get("username"),
-                    password: password,
-                    oldpassword: oldpassword,
-                    newpassword: newpassword
-                }
-            };
-            self._client.request(options, function(err, data) {
-                if (err && self._client.logging) {
-                    console.log("could not update user");
-                }
-                //remove old and new password fields so they don't end up as part of the entity object
-                self.set({
-                    password: null,
-                    oldpassword: null,
-                    newpassword: null
-                });
-                doCallback(callback, [ err, data, self ]);
-            });
-        } else {
-            doCallback(callback, [ err, response, self ]);
         }
+        doCallback(callback, [ err, response, self ], self);
     });
 };
 
 /*
+ *
+ * Updates the user's password
+ */
+Usergrid.Entity.prototype.changePassword = function(oldpassword, password, newpassword, callback) {
+    //Note: we have a ticket in to change PUT calls to /users to accept the password change
+    //      once that is done, we will remove this call and merge it all into one
+    var self = this;
+    if ("function" === typeof oldpassword && callback === undefined) {
+        callback = oldpassword;
+        oldpassword = self.get("oldpassword");
+        password = self.get("password");
+        newpassword = self.get("newpassword");
+    }
+    //clear out pw info if present
+    self.set({
+        password: null,
+        oldpassword: null,
+        newpassword: null
+    });
+    if (/^users?$/.test(self.get("type")) && oldpassword && newpassword) {
+        var options = {
+            method: "PUT",
+            endpoint: "users/" + self.get("uuid") + "/password",
+            body: {
+                uuid: self.get("uuid"),
+                username: self.get("username"),
+                password: password,
+                oldpassword: oldpassword,
+                newpassword: newpassword
+            }
+        };
+        self._client.request(options, function(err, response) {
+            if (err && self._client.logging) {
+                console.log("could not update user");
+            }
+            //remove old and new password fields so they don't end up as part of the entity object
+            doCallback(callback, [ err, response, self ], self);
+        });
+    } else {
+        throw new UsergridInvalidArgumentError("Invalid arguments passed to 'changePassword'");
+    }
+};
+
+/*
  *  refreshes the entity by making a GET call back to the database
  *
  *  @method fetch
@@ -1505,7 +1510,7 @@ Usergrid.Entity.prototype.fetch = function(callback) {
         if (entity) {
             self.set(entity);
         }
-        doCallback(callback, [ err, entity, self ]);
+        doCallback(callback, [ err, response, self ], self);
     });
 };
 
@@ -1526,11 +1531,11 @@ Usergrid.Entity.prototype.destroy = function(callback) {
         method: "DELETE",
         endpoint: endpoint
     };
-    this._client.request(options, function(err, data) {
+    this._client.request(options, function(err, response) {
         if (!err) {
             self.set(null);
         }
-        doCallback(callback, [ err, data ]);
+        doCallback(callback, [ err, response, self ], self);
     });
 };
 
@@ -1546,44 +1551,63 @@ Usergrid.Entity.prototype.destroy = function(callback) {
  *
  */
 Usergrid.Entity.prototype.connect = function(connection, entity, callback) {
+    this.addOrRemoveConnection("POST", connection, entity, callback);
+};
+
+/*
+ *  disconnects one entity from another
+ *
+ *  @method disconnect
+ *  @public
+ *  @param {string} connection
+ *  @param {object} entity
+ *  @param {function} callback
+ *  @return {callback} callback(err, data)
+ *
+ */
+Usergrid.Entity.prototype.disconnect = function(connection, entity, callback) {
+    this.addOrRemoveConnection("DELETE", connection, entity, callback);
+};
+
+/*
+ *  adds or removes a connection between two entities
+ *
+ *  @method addOrRemoveConnection
+ *  @public
+ *  @param {string} method
+ *  @param {string} connection
+ *  @param {object} entity
+ *  @param {function} callback
+ *  @return {callback} callback(err, data)
+ *
+ */
+Usergrid.Entity.prototype.addOrRemoveConnection = function(method, connection, entity, callback) {
     var self = this;
-    var error;
+    if ([ "POST", "DELETE" ].indexOf(method.toUpperCase()) == -1) {
+        throw new UsergridInvalidArgumentError("invalid method for connection call. must be 'POST' or 'DELETE'");
+    }
     //connectee info
     var connecteeType = entity.get("type");
     var connectee = this.getEntityId(entity);
     if (!connectee) {
-        if (typeof callback === "function") {
-            error = "Error trying to delete object - no uuid specified.";
-            if (self._client.logging) {
-                console.log(error);
-            }
-            doCallback(callback, [ true, error ], self);
-        }
-        return;
+        throw new UsergridInvalidArgumentError("connectee could not be identified");
     }
     //connector info
     var connectorType = this.get("type");
     var connector = this.getEntityId(this);
     if (!connector) {
-        if (typeof callback === "function") {
-            error = "Error in connect - no uuid specified.";
-            if (self._client.logging) {
-                console.log(error);
-            }
-            doCallback(callback, [ true, error ], self);
-        }
-        return;
+        throw new UsergridInvalidArgumentError("connector could not be identified");
     }
-    var endpoint = connectorType + "/" + connector + "/" + connection + "/" + connecteeType + "/" + connectee;
+    var endpoint = [ connectorType, connector, connection, connecteeType, connectee ].join("/");
     var options = {
-        method: "POST",
+        method: method,
         endpoint: endpoint
     };
-    this._client.request(options, function(err, data) {
+    this._client.request(options, function(err, response) {
         if (err && self._client.logging) {
-            console.log("entity could not be connected");
+            console.log("There was an error with the connection call");
         }
-        doCallback(callback, [ err, data ], self);
+        doCallback(callback, [ err, response, self ], self);
     });
 };
 
@@ -1777,7 +1801,7 @@ Usergrid.Entity.prototype.getPermissions = function(callback) {
                     ops_part = parts[0];
                     path_part = parts[1];
                 }
-                ops_part.replace("*", "get,post,put,delete");
+                ops_part = ops_part.replace("*", "get,post,put,delete");
                 var ops = ops_part.split(",");
                 var ops_object = {};
                 ops_object.get = "no";
@@ -1800,69 +1824,15 @@ Usergrid.Entity.prototype.getPermissions = function(callback) {
 };
 
 /*
- *  disconnects one entity from another
- *
- *  @method disconnect
- *  @public
- *  @param {string} connection
- *  @param {object} entity
- *  @param {function} callback
- *  @return {callback} callback(err, data)
- *
- */
-Usergrid.Entity.prototype.disconnect = function(connection, entity, callback) {
-    var self = this;
-    var error;
-    //connectee info
-    var connecteeType = entity.get("type");
-    var connectee = this.getEntityId(entity);
-    if (!connectee) {
-        if (typeof callback === "function") {
-            error = "Error trying to delete object - no uuid specified.";
-            if (self._client.logging) {
-                console.log(error);
-            }
-            doCallback(callback, [ true, error ], self);
-        }
-        return;
-    }
-    //connector info
-    var connectorType = this.get("type");
-    var connector = this.getEntityId(this);
-    if (!connector) {
-        if (typeof callback === "function") {
-            error = "Error in connect - no uuid specified.";
-            if (self._client.logging) {
-                console.log(error);
-            }
-            doCallback(callback, [ true, error ], self);
-        }
-        return;
-    }
-    var endpoint = connectorType + "/" + connector + "/" + connection + "/" + connecteeType + "/" + connectee;
-    var options = {
-        method: "DELETE",
-        endpoint: endpoint
-    };
-    this._client.request(options, function(err, data) {
-        if (err && self._client.logging) {
-            console.log("entity could not be disconnected");
-        }
-        doCallback(callback, [ err, data ], self);
-    });
-};
-
-/*
  *  The Collection class models Usergrid Collections.  It essentially
  *  acts as a container for holding Entity objects, while providing
  *  additional funcitonality such as paging, and saving
  *
  *  @constructor
  *  @param {string} options - configuration object
- *  @param {function} callback
- *  @return {callback} callback(err, data)
+ *  @return {Collection} collection
  */
-Usergrid.Collection = function(options, callback) {
+Usergrid.Collection = function(options) {
     if (options) {
         this._client = options.client;
         this._type = options.type;
@@ -1885,10 +1855,6 @@ Usergrid.Collection = function(options, callback) {
             }
         }
     }
-    if (callback) {
-        //populate the collection
-        this.fetch(callback);
-    }
 };
 
 /*
@@ -1930,24 +1896,26 @@ Usergrid.Collection.prototype.serialize = function() {
     return data;
 };
 
-Usergrid.Collection.prototype.addCollection = function(collectionName, options, callback) {
-    self = this;
-    options.client = this._client;
-    var collection = new Usergrid.Collection(options, function(err, data) {
-        if (typeof callback === "function") {
-            collection.resetEntityPointer();
-            while (collection.hasNextEntity()) {
-                var user = collection.getNextEntity();
-                var email = user.get("email");
-                var image = self._client.getDisplayImage(user.get("email"), user.get("picture"));
-                user._portal_image_icon = image;
-            }
-            self[collectionName] = collection;
-            doCallback(callback, [ err, collection ], self);
-        }
-    });
-};
+//addCollection is deprecated?
+/*Usergrid.Collection.prototype.addCollection = function (collectionName, options, callback) {
+  self = this;
+  options.client = this._client;
+  var collection = new Usergrid.Collection(options, function(err, data) {
+    if (typeof(callback) === 'function') {
+
+      collection.resetEntityPointer();
+      while(collection.hasNextEntity()) {
+        var user = collection.getNextEntity();
+        var email = user.get('email');
+        var image = self._client.getDisplayImage(user.get('email'), user.get('picture'));
+        user._portal_image_icon = image;
+      }
 
+      self[collectionName] = collection;
+      doCallback(callback, [err, collection], self);
+    }
+  });
+};*/
 /*
  *  Populates the collection from the server
  *
@@ -1969,42 +1937,27 @@ Usergrid.Collection.prototype.fetch = function(callback) {
         endpoint: this._type,
         qs: this.qs
     };
-    this._client.request(options, function(err, data) {
+    this._client.request(options, function(err, response) {
         if (err && self._client.logging) {
             console.log("error getting collection");
         } else {
             //save the cursor if there is one
-            var cursor = data.cursor || null;
-            self.saveCursor(cursor);
-            if (data.entities) {
-                self.resetEntityPointer();
-                var count = data.entities.length;
-                //save entities locally
-                self._list = [];
-                //clear the local list first
-                for (var i = 0; i < count; i++) {
-                    var uuid = data.entities[i].uuid;
-                    if (uuid) {
-                        var entityData = data.entities[i] || {};
-                        self._baseType = data.entities[i].type;
-                        //store the base type in the collection
-                        entityData.type = self._type;
-                        //make sure entities are same type (have same path) as parent collection.
-                        var entityOptions = {
-                            type: self._type,
-                            client: self._client,
-                            uuid: uuid,
-                            data: entityData
-                        };
-                        var ent = new Usergrid.Entity(entityOptions);
-                        ent._json = JSON.stringify(entityData, null, 2);
-                        var ct = self._list.length;
-                        self._list[ct] = ent;
-                    }
-                }
-            }
+            self.saveCursor(response.cursor || null);
+            self.resetEntityPointer();
+            //save entities locally
+            self._list = response.getEntities().filter(function(entity) {
+                return isUUID(entity.uuid);
+            }).map(function(entity) {
+                var ent = new Usergrid.Entity({
+                    client: self._client
+                });
+                ent.set(entity);
+                ent.type = self._type;
+                //ent._json = JSON.stringify(entity, null, 2);
+                return ent;
+            });
         }
-        doCallback(callback, [ err, data ], self);
+        doCallback(callback, [ err, response, self ], self);
     });
 };
 
@@ -2016,17 +1969,16 @@ Usergrid.Collection.prototype.fetch = function(callback) {
  *  @param {function} callback
  *  @return {callback} callback(err, data, entity)
  */
-Usergrid.Collection.prototype.addEntity = function(options, callback) {
+Usergrid.Collection.prototype.addEntity = function(entityObject, callback) {
     var self = this;
-    options.type = this._type;
+    entityObject.type = this._type;
     //create the new entity
-    this._client.createEntity(options, function(err, entity) {
+    this._client.createEntity(entityObject, function(err, response, entity) {
         if (!err) {
             //then add the entity to the list
-            var count = self._list.length;
-            self._list[count] = entity;
+            self.addExistingEntity(entity);
         }
-        doCallback(callback, [ err, entity ], self);
+        doCallback(callback, [ err, response, self ], self);
     });
 };
 
@@ -2046,30 +1998,58 @@ Usergrid.Collection.prototype.addExistingEntity = function(entity) {
  */
 Usergrid.Collection.prototype.destroyEntity = function(entity, callback) {
     var self = this;
-    entity.destroy(function(err, data) {
+    entity.destroy(function(err, response) {
         if (err) {
             if (self._client.logging) {
                 console.log("could not destroy entity");
             }
-            doCallback(callback, [ err, data ], self);
+            doCallback(callback, [ err, response, self ], self);
         } else {
             //destroy was good, so repopulate the collection
             self.fetch(callback);
         }
+        //remove entity from the local store
+        self.removeEntity(entity);
     });
-    //remove entity from the local store
-    this.removeEntity(entity);
 };
 
+/*
+ * Filters the list of entities based on the supplied criteria function
+ * works like Array.prototype.filter
+ *
+ *  @method getEntitiesByCriteria
+ *  @param {function} criteria  A function that takes each entity as an argument and returns true or false
+ *  @return {Entity[]} returns a list of entities that caused the criteria function to return true
+ */
+Usergrid.Collection.prototype.getEntitiesByCriteria = function(criteria) {
+    return this._list.filter(criteria);
+};
+
+/*
+ * Returns the first entity from the list of entities based on the supplied criteria function
+ * works like Array.prototype.filter
+ *
+ *  @method getEntitiesByCriteria
+ *  @param {function} criteria  A function that takes each entity as an argument and returns true or false
+ *  @return {Entity[]} returns a list of entities that caused the criteria function to return true
+ */
+Usergrid.Collection.prototype.getEntityByCriteria = function(criteria) {
+    return this.getEntitiesByCriteria(criteria).shift();
+};
+
+/*
+ * Removed an entity from the collection without destroying it on the server
+ *
+ *  @method removeEntity
+ *  @param {object} entity
+ *  @return {Entity} returns the removed entity or undefined if it was not found
+ */
 Usergrid.Collection.prototype.removeEntity = function(entity) {
-    var uuid = entity.get("uuid");
-    for (var key in this._list) {
-        var listItem = this._list[key];
-        if (listItem.get("uuid") === uuid) {
-            return this._list.splice(key, 1);
-        }
-    }
-    return false;
+    var removedEntity = this.getEntityByCriteria(function(item) {
+        return entity.uuid === item.get("uuid");
+    });
+    delete this._list[this._list.indexOf(removedEntity)];
+    return removedEntity;
 };
 
 /*
@@ -2081,22 +2061,23 @@ Usergrid.Collection.prototype.removeEntity = function(entity) {
  *  @return {callback} callback(err, data, entity)
  */
 Usergrid.Collection.prototype.getEntityByUUID = function(uuid, callback) {
-    for (var key in this._list) {
-        var listItem = this._list[key];
-        if (listItem.get("uuid") === uuid) {
-            return callback(null, listItem);
-        }
+    var entity = this.getEntityByCriteria(function(item) {
+        return item.get("uuid") === uuid;
+    });
+    if (entity) {
+        doCallback(callback, [ null, entity, entity ], this);
+    } else {
+        //get the entity from the database
+        var options = {
+            data: {
+                type: this._type,
+                uuid: uuid
+            },
+            client: this._client
+        };
+        entity = new Usergrid.Entity(options);
+        entity.fetch(callback);
     }
-    //get the entity from the database
-    var options = {
-        data: {
-            type: this._type,
-            uuid: uuid
-        },
-        client: this._client
-    };
-    var entity = new Usergrid.Entity(options);
-    entity.fetch(callback);
 };
 
 /*
@@ -2334,40 +2315,33 @@ Usergrid.Group.prototype.fetch = function(callback) {
         method: "GET",
         endpoint: memberEndpoint
     };
-    this._client.request(groupOptions, function(err, data) {
+    this._client.request(groupOptions, function(err, response) {
         if (err) {
             if (self._client.logging) {
                 console.log("error getting group");
             }
-            doCallback(callback, [ err, data ], self);
+            doCallback(callback, [ err, response ], self);
         } else {
-            if (data.entities && data.entities.length) {
-                var groupData = data.entities[0];
-                self._data = groupData || {};
-                self._client.request(memberOptions, function(err, data) {
+            var entities = response.getEntities();
+            if (entities && entities.length) {
+                var groupresponse = entities.shift();
+                //self._response = groupresponse || {};
+                self._client.request(memberOptions, function(err, response) {
                     if (err && self._client.logging) {
                         console.log("error getting group users");
                     } else {
-                        if (data.entities) {
-                            var count = data.entities.length;
-                            self._list = [];
-                            for (var i = 0; i < count; i++) {
-                                var uuid = data.entities[i].uuid;
-                                if (uuid) {
-                                    var entityData = data.entities[i] || {};
-                                    var entityOptions = {
-                                        type: entityData.type,
-                                        client: self._client,
-                                        uuid: uuid,
-                                        data: entityData
-                                    };
-                                    var entity = new Usergrid.Entity(entityOptions);
-                                    self._list.push(entity);
-                                }
-                            }
-                        }
+                        self._list = response.getEntities().filter(function(entity) {
+                            return isUUID(entity.uuid);
+                        }).map(function(entity) {
+                            return new Usergrid.Entity({
+                                type: entity.type,
+                                client: self._client,
+                                uuid: entity.uuid,
+                                response: entity
+                            });
+                        });
                     }
-                    doCallback(callback, [ err, data, self._list ], self);
+                    doCallback(callback, [ err, response, self ], self);
                 });
             }
         }
@@ -2383,11 +2357,12 @@ Usergrid.Group.prototype.fetch = function(callback) {
  *  @return {function} callback(err, data);
  */
 Usergrid.Group.prototype.members = function(callback) {
-    doCallback(callback, [ null, this._list ], this);
+    //doCallback(callback, [null, this._list, this], this);
+    return this._list;
 };
 
 /*
- *  Adds a user to the group, and refreshes the group object.
+ *  Adds an existing user to the group, and refreshes the group object.
  *
  *  Options object: {user: user_entity}
  *
@@ -2399,17 +2374,21 @@ Usergrid.Group.prototype.members = function(callback) {
  */
 Usergrid.Group.prototype.add = function(options, callback) {
     var self = this;
-    var options = {
-        method: "POST",
-        endpoint: "groups/" + this._path + "/users/" + options.user.get("username")
-    };
-    this._client.request(options, function(error, data) {
-        if (error) {
-            doCallback(callback, [ error, data, data.entities ], self);
-        } else {
-            self.fetch(callback);
-        }
-    });
+    if (options.user) {
+        options = {
+            method: "POST",
+            endpoint: "groups/" + this._path + "/users/" + options.user.get("username")
+        };
+        this._client.request(options, function(error, response) {
+            if (error) {
+                doCallback(callback, [ error, response, self ], self);
+            } else {
+                self.fetch(callback);
+            }
+        });
+    } else {
+        doCallback(callback, [ new UsergridError("no user specified", "no_user_specified"), null, this ], this);
+    }
 };
 
 /*
@@ -2425,17 +2404,21 @@ Usergrid.Group.prototype.add = function(options, callback) {
  */
 Usergrid.Group.prototype.remove = function(options, callback) {
     var self = this;
-    var options = {
-        method: "DELETE",
-        endpoint: "groups/" + this._path + "/users/" + options.user.get("username")
-    };
-    this._client.request(options, function(error, data) {
-        if (error) {
-            doCallback(callback, [ error, data ], self);
-        } else {
-            self.fetch(callback);
-        }
-    });
+    if (options.user) {
+        options = {
+            method: "DELETE",
+            endpoint: "groups/" + this._path + "/users/" + options.user.get("username")
+        };
+        this._client.request(options, function(error, response) {
+            if (error) {
+                doCallback(callback, [ error, response, self ], self);
+            } else {
+                self.fetch(callback);
+            }
+        });
+    } else {
+        doCallback(callback, [ new UsergridError("no user specified", "no_user_specified"), null, this ], this);
+    }
 };
 
 /*
@@ -2448,16 +2431,12 @@ Usergrid.Group.prototype.remove = function(options, callback) {
  */
 Usergrid.Group.prototype.feed = function(callback) {
     var self = this;
-    var endpoint = "groups/" + this._path + "/feed";
     var options = {
         method: "GET",
-        endpoint: endpoint
+        endpoint: "groups/" + this._path + "/feed"
     };
-    this._client.request(options, function(err, data) {
-        if (err && self.logging) {
-            console.log("error trying to log user in");
-        }
-        doCallback(callback, [ err, data, data.entities ], self);
+    this._client.request(options, function(err, response) {
+        doCallback(callback, [ err, response, self ], self);
     });
 };
 
@@ -2473,8 +2452,9 @@ Usergrid.Group.prototype.feed = function(callback) {
  * @returns {callback} callback(err, entity)
  */
 Usergrid.Group.prototype.createGroupActivity = function(options, callback) {
+    var self = this;
     var user = options.user;
-    options = {
+    var entity = new Usergrid.Entity({
         client: this._client,
         data: {
             actor: {
@@ -2494,10 +2474,9 @@ Usergrid.Group.prototype.createGroupActivity = function(options, callback) {
             content: options.content,
             type: "groups/" + this._path + "/activities"
         }
-    };
-    var entity = new Usergrid.Entity(options);
-    entity.save(function(err, data) {
-        doCallback(callback, [ err, entity ]);
+    });
+    entity.save(function(err, response, entity) {
+        doCallback(callback, [ err, response, self ]);
     });
 };
 
@@ -2509,14 +2488,14 @@ Usergrid.Group.prototype.createGroupActivity = function(options, callback) {
  *  @returns {callback} callback(err, event)
  */
 Usergrid.Counter = function(options, callback) {
-    var self = this;
+    // var self=this;
     this._client = options.client;
     this._data = options.data || {};
     this._data.category = options.category || "UNKNOWN";
     this._data.timestamp = options.timestamp || 0;
     this._data.type = "events";
     this._data.counters = options.counters || {};
-    doCallback(callback, [ false, self ], self);
+    doCallback(callback, [ false, this ], this);
 };
 
 var COUNTER_RESOLUTIONS = [ "all", "minute", "five_minutes", "half_hour", "hour", "six_day", "day", "week", "month" ];
@@ -2555,9 +2534,9 @@ Usergrid.Counter.prototype.fetch = function(callback) {
 Usergrid.Counter.prototype.increment = function(options, callback) {
     var self = this, name = options.name, value = options.value;
     if (!name) {
-        return doCallback(callback, [ true, "'name' for increment, decrement must be a number" ], self);
+        return doCallback(callback, [ new UsergridInvalidArgumentError("'name' for increment, decrement must be a number"), null, self ], self);
     } else if (isNaN(value)) {
-        return doCallback(callback, [ true, "'value' for increment, decrement must be a number" ], self);
+        return doCallback(callback, [ new UsergridInvalidArgumentError("'value' for increment, decrement must be a number"), null, self ], self);
     } else {
         self._data.counters[name] = parseInt(value) || 1;
         return self.save(callback);
@@ -2624,42 +2603,8 @@ Usergrid.Counter.prototype.getData = function(options, callback) {
     if (COUNTER_RESOLUTIONS.indexOf(res) === -1) {
         res = "all";
     }
-    if (start) {
-        switch (typeof start) {
-          case "undefined":
-            start_time = 0;
-            break;
-
-          case "number":
-            start_time = start;
-            break;
-
-          case "string":
-            start_time = isNaN(start) ? Date.parse(start) : parseInt(start);
-            break;
-
-          default:
-            start_time = Date.parse(start.toString());
-        }
-    }
-    if (end) {
-        switch (typeof end) {
-          case "undefined":
-            end_time = Date.now();
-            break;
-
-          case "number":
-            end_time = end;
-            break;
-
-          case "string":
-            end_time = isNaN(end) ? Date.parse(end) : parseInt(end);
-            break;
-
-          default:
-            end_time = Date.parse(end.toString());
-        }
-    }
+    start_time = getSafeTime(start);
+    end_time = getSafeTime(end);
     var self = this;
     //https://api.usergrid.com/yourorgname/sandbox/counters?counter=test_counter
     var params = Object.keys(counters).map(function(counter) {
@@ -2677,10 +2622,31 @@ Usergrid.Counter.prototype.getData = function(options, callback) {
                 self._data.counters[counter.name] = counter.value || counter.values;
             });
         }
-        return doCallback(callback, [ err, data ], self);
+        return doCallback(callback, [ err, data, self ], self);
     });
 };
 
+function getSafeTime(prop) {
+    var time;
+    switch (typeof prop) {
+      case "undefined":
+        time = Date.now();
+        break;
+
+      case "number":
+        time = prop;
+        break;
+
+      case "string":
+        time = isNaN(prop) ? Date.parse(prop) : parseInt(prop);
+        break;
+
+      default:
+        time = Date.parse(prop.toString());
+    }
+    return time;
+}
+
 /*
  *  A class to model a Usergrid folder.
  *
@@ -2698,16 +2664,16 @@ Usergrid.Folder = function(options, callback) {
         return !(required in self._data);
     });
     if (missingData) {
-        return doCallback(callback, [ true, new UsergridError("Invalid asset data: 'name', 'owner', and 'path' are required properties.") ], self);
+        return doCallback(callback, [ new UsergridInvalidArgumentError("Invalid asset data: 'name', 'owner', and 'path' are required properties."), null, self ], self);
     }
-    self.save(function(err, data) {
+    self.save(function(err, response) {
         if (err) {
-            doCallback(callback, [ true, new UsergridError(data) ], self);
+            doCallback(callback, [ new UsergridError(response), response, self ], self);
         } else {
-            if (data && data.entities && data.entities.length) {
-                self.set(data.entities[0]);
+            if (response && response.entities && response.entities.length) {
+                self.set(response.entities[0]);
             }
-            doCallback(callback, [ false, self ], self);
+            doCallback(callback, [ null, response, self ], self);
         }
     });
 };
@@ -2731,15 +2697,15 @@ Usergrid.Folder.prototype.fetch = function(callback) {
         console.log("self", self.get());
         console.log("data", data);
         if (!err) {
-            self.getAssets(function(err, data) {
+            self.getAssets(function(err, response) {
                 if (err) {
-                    doCallback(callback, [ true, new UsergridError(data) ], self);
+                    doCallback(callback, [ new UsergridError(response), resonse, self ], self);
                 } else {
                     doCallback(callback, [ null, self ], self);
                 }
             });
         } else {
-            doCallback(callback, [ true, new UsergridError(data) ], self);
+            doCallback(callback, [ null, data, self ], self);
         }
     });
 };
@@ -2779,7 +2745,7 @@ Usergrid.Folder.prototype.addAsset = function(options, callback) {
         if (asset && asset instanceof Usergrid.Entity) {
             asset.fetch(function(err, data) {
                 if (err) {
-                    doCallback(callback, [ err, new UsergridError(data) ], self);
+                    doCallback(callback, [ new UsergridError(data), data, self ], self);
                 } else {
                     var endpoint = [ "folders", self.get("uuid"), "assets", asset.get("uuid") ].join("/");
                     var options = {
@@ -2792,9 +2758,7 @@ Usergrid.Folder.prototype.addAsset = function(options, callback) {
         }
     } else {
         //nothing to add
-        doCallback(callback, [ true, {
-            error_description: "No asset specified"
-        } ], self);
+        doCallback(callback, [ new UsergridInvalidArgumentError("No asset specified"), null, self ], self);
     }
 };
 
@@ -2832,13 +2796,17 @@ Usergrid.Folder.prototype.removeAsset = function(options, callback) {
             self._client.request({
                 method: "DELETE",
                 endpoint: endpoint
-            }, callback);
+            }, function(err, response) {
+                if (err) {
+                    doCallback(callback, [ new UsergridError(response), response, self ], self);
+                } else {
+                    doCallback(callback, [ null, response, self ], self);
+                }
+            });
         }
     } else {
         //nothing to add
-        doCallback(callback, [ true, {
-            error_description: "No asset specified"
-        } ], self);
+        doCallback(callback, [ new UsergridInvalidArgumentError("No asset specified"), null, self ], self);
     }
 };
 
@@ -2886,18 +2854,19 @@ Usergrid.Asset = function(options, callback) {
         return !(required in self._data);
     });
     if (missingData) {
-        return doCallback(callback, [ true, new UsergridError("Invalid asset data: 'name', 'owner', and 'path' are required properties.") ], self);
-    }
-    self.save(function(err, data) {
-        if (err) {
-            doCallback(callback, [ true, new UsergridError(data) ], self);
-        } else {
-            if (data && data.entities && data.entities.length) {
-                self.set(data.entities[0]);
+        doCallback(callback, [ new UsergridError("Invalid asset data: 'name', 'owner', and 'path' are required properties."), null, self ], self);
+    } else {
+        self.save(function(err, data) {
+            if (err) {
+                doCallback(callback, [ new UsergridError(data), data, self ], self);
+            } else {
+                if (data && data.entities && data.entities.length) {
+                    self.set(data.entities[0]);
+                }
+                doCallback(callback, [ null, data, self ], self);
             }
-            doCallback(callback, [ false, self ], self);
-        }
-    });
+        });
+    }
 };
 
 /*
@@ -2921,17 +2890,24 @@ Usergrid.Asset.prototype.addToFolder = function(options, callback) {
             uuid: options.folder
         }, function(err, folder) {
             if (err) {
-                return callback.call(self, err, folder);
+                doCallback(callback, [ UsergridError.fromResponse(folder), folder, self ], self);
+            } else {
+                var endpoint = [ "folders", folder.get("uuid"), "assets", self.get("uuid") ].join("/");
+                var options = {
+                    method: "POST",
+                    endpoint: endpoint
+                };
+                this._client.request(options, function(err, response) {
+                    if (err) {
+                        doCallback(callback, [ UsergridError.fromResponse(folder), response, self ], self);
+                    } else {
+                        doCallback(callback, [ null, folder, self ], self);
+                    }
+                });
             }
-            var endpoint = [ "folders", folder.get("uuid"), "assets", self.get("uuid") ].join("/");
-            var options = {
-                method: "POST",
-                endpoint: endpoint
-            };
-            this._client.request(options, callback);
         });
     } else {
-        doCallback(callback, [ true, new UsergridError("folder not specified") ], self);
+        doCallback(callback, [ new UsergridError("folder not specified"), null, self ], self);
     }
 };
 
@@ -2945,7 +2921,8 @@ Usergrid.Asset.prototype.addToFolder = function(options, callback) {
  */
 Usergrid.Asset.prototype.upload = function(data, callback) {
     if (!(window.File && window.FileReader && window.FileList && window.Blob)) {
-        return doCallback(callback, [ true, new UsergridError("The File APIs are not fully supported by your browser.") ], self);
+        doCallback(callback, [ new UsergridError("The File APIs are not fully supported by your browser."), null, this ], this);
+        return;
     }
     var self = this;
     var endpoint = [ this._client.URI, this._client.orgName, this._client.appName, "assets", self.get("uuid"), "data" ].join("/");
@@ -2958,9 +2935,9 @@ Usergrid.Asset.prototype.upload = function(data, callback) {
     };
     xhr.onload = function(ev) {
         if (xhr.status >= 300) {
-            doCallback(callback, [ true, new UsergridError(JSON.parse(xhr.responseText)) ], self);
+            doCallback(callback, [ new UsergridError(JSON.parse(xhr.responseText)), null, self ], self);
         } else {
-            doCallback(callback, [ null, self ], self);
+            doCallback(callback, [ null, xhr, self ], self);
         }
     };
     var fr = new FileReader();
@@ -2990,11 +2967,11 @@ Usergrid.Asset.prototype.download = function(callback) {
     xhr.onload = function(ev) {
         var blob = xhr.response;
         //callback(null, blob);
-        doCallback(callback, [ false, blob ], self);
+        doCallback(callback, [ null, blob, self ], self);
     };
     xhr.onerror = function(err) {
         callback(true, err);
-        doCallback(callback, [ true, new UsergridError(err) ], self);
+        doCallback(callback, [ new UsergridError(err), err, self ], self);
     };
     xhr.send();
 };
@@ -3072,7 +3049,7 @@ Usergrid.Asset.prototype.download = function(callback) {
     UsergridHTTPResponseError.prototype = new UsergridError();
     function UsergridInvalidHTTPMethodError(message, name, timestamp, duration, exception) {
         this.message = message;
-        this.name = name;
+        this.name = name || "invalid_http_method";
         this.timestamp = timestamp || Date.now();
         this.duration = duration || 0;
         this.exception = exception;
@@ -3080,12 +3057,20 @@ Usergrid.Asset.prototype.download = function(callback) {
     UsergridInvalidHTTPMethodError.prototype = new UsergridError();
     function UsergridInvalidURIError(message, name, timestamp, duration, exception) {
         this.message = message;
-        this.name = name;
+        this.name = name || "invalid_uri";
         this.timestamp = timestamp || Date.now();
         this.duration = duration || 0;
         this.exception = exception;
     }
     UsergridInvalidURIError.prototype = new UsergridError();
+    function UsergridInvalidArgumentError(message, name, timestamp, duration, exception) {
+        this.message = message;
+        this.name = name || "invalid_argument";
+        this.timestamp = timestamp || Date.now();
+        this.duration = duration || 0;
+        this.exception = exception;
+    }
+    UsergridInvalidArgumentError.prototype = new UsergridError();
     function UsergridKeystoreDatabaseUpgradeNeededError(message, name, timestamp, duration, exception) {
         this.message = message;
         this.name = name;
@@ -3094,10 +3079,11 @@ Usergrid.Asset.prototype.download = function(callback) {
         this.exception = exception;
     }
     UsergridKeystoreDatabaseUpgradeNeededError.prototype = new UsergridError();
-    global["UsergridHTTPResponseError"] = UsergridHTTPResponseError;
-    global["UsergridInvalidHTTPMethodError"] = UsergridInvalidHTTPMethodError;
-    global["UsergridInvalidURIError"] = UsergridInvalidURIError;
-    global["UsergridKeystoreDatabaseUpgradeNeededError"] = UsergridKeystoreDatabaseUpgradeNeededError;
+    global.UsergridHTTPResponseError = UsergridHTTPResponseError;
+    global.UsergridInvalidHTTPMethodError = UsergridInvalidHTTPMethodError;
+    global.UsergridInvalidURIError = UsergridInvalidURIError;
+    global.UsergridInvalidArgumentError = UsergridInvalidArgumentError;
+    global.UsergridKeystoreDatabaseUpgradeNeededError = UsergridKeystoreDatabaseUpgradeNeededError;
     global[name] = UsergridError;
     if (short !== undefined) {
         //noinspection JSUnusedAssignment


[12/12] git commit: Merge pull request #96 from r3b/DPS-116

Posted by sn...@apache.org.
Merge pull request #96 from r3b/DPS-116

Javascript SDK Refactoring

Project: http://git-wip-us.apache.org/repos/asf/incubator-usergrid/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-usergrid/commit/d8221a19
Tree: http://git-wip-us.apache.org/repos/asf/incubator-usergrid/tree/d8221a19
Diff: http://git-wip-us.apache.org/repos/asf/incubator-usergrid/diff/d8221a19

Branch: refs/heads/master
Commit: d8221a196ec4961715ff4941c39a85dcc71e03aa
Parents: 594b9fa e576e0a
Author: Rod Simpson <ro...@rodsimpson.com>
Authored: Thu Apr 10 08:42:39 2014 -0600
Committer: Rod Simpson <ro...@rodsimpson.com>
Committed: Thu Apr 10 08:42:39 2014 -0600

----------------------------------------------------------------------
 sdks/html5-javascript/changelog.md              |  13 +-
 sdks/html5-javascript/examples/dogs/app.js      |   6 +-
 sdks/html5-javascript/examples/test/test.js     |  46 +-
 sdks/html5-javascript/index.html                |  12 +-
 sdks/html5-javascript/lib/Usergrid.js           | 171 ++--
 sdks/html5-javascript/lib/modules/Asset.js      |  93 +-
 sdks/html5-javascript/lib/modules/Client.js     | 528 +++++-----
 sdks/html5-javascript/lib/modules/Collection.js | 236 ++---
 sdks/html5-javascript/lib/modules/Counter.js    | 166 ++--
 sdks/html5-javascript/lib/modules/Entity.js     | 470 ++++-----
 sdks/html5-javascript/lib/modules/Error.js      | 112 ++-
 sdks/html5-javascript/lib/modules/Folder.js     |  46 +-
 sdks/html5-javascript/lib/modules/Group.js      | 160 ++-
 sdks/html5-javascript/lib/modules/util/Ajax.js  |  16 +-
 sdks/html5-javascript/lib/modules/util/Event.js |   8 +-
 .../html5-javascript/lib/modules/util/Logger.js |  18 +-
 .../lib/modules/util/Promise.js                 |   5 +-
 sdks/html5-javascript/tests/mocha/test.js       | 107 +-
 sdks/html5-javascript/usergrid.js               | 989 ++++++++++---------
 sdks/html5-javascript/usergrid.min.js           |   6 +-
 20 files changed, 1684 insertions(+), 1524 deletions(-)
----------------------------------------------------------------------



[06/12] git commit: Removed call delay for upload and implemented a retry on failure. MUCH faster and MUCH, MUCH more reliable.

Posted by sn...@apache.org.
Removed call delay for upload and implemented a retry on failure. MUCH faster and MUCH, MUCH more reliable.


Project: http://git-wip-us.apache.org/repos/asf/incubator-usergrid/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-usergrid/commit/bc03fb82
Tree: http://git-wip-us.apache.org/repos/asf/incubator-usergrid/tree/bc03fb82
Diff: http://git-wip-us.apache.org/repos/asf/incubator-usergrid/diff/bc03fb82

Branch: refs/heads/master
Commit: bc03fb8296d3dc9b608c0441550c929986ae76cd
Parents: da8ecff
Author: ryan bridges <rb...@apigee.com>
Authored: Tue Apr 1 14:17:35 2014 -0400
Committer: ryan bridges <rb...@apigee.com>
Committed: Tue Apr 1 14:17:35 2014 -0400

----------------------------------------------------------------------
 sdks/html5-javascript/lib/modules/Asset.js | 30 ++++++++++++++++---------
 1 file changed, 20 insertions(+), 10 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/bc03fb82/sdks/html5-javascript/lib/modules/Asset.js
----------------------------------------------------------------------
diff --git a/sdks/html5-javascript/lib/modules/Asset.js b/sdks/html5-javascript/lib/modules/Asset.js
index b5bc68a..52cfd96 100644
--- a/sdks/html5-javascript/lib/modules/Asset.js
+++ b/sdks/html5-javascript/lib/modules/Asset.js
@@ -109,18 +109,30 @@ Usergrid.Asset.prototype.upload = function(data, callback) {
 		return;
 	}
 	var self = this;
+	var args=arguments;
+	var attempts=self.get("attempts");
+	if(isNaN(attempts)){
+		attempts=3;
+	}
+	self.set('content-type', data.type);
+	self.set('size', data.size);
 	var endpoint = [this._client.URI, this._client.orgName, this._client.appName, "assets", self.get("uuid"), 'data'].join('/'); //self._client.buildAssetURL(self.get("uuid"));
 
 	var xhr = new XMLHttpRequest();
 	xhr.open("POST", endpoint, true);
 	xhr.onerror = function(err) {
 		//callback(true, err);
-		doCallback(callback, [true, new UsergridError('The File APIs are not fully supported by your browser.')], self);
+		doCallback(callback, [new UsergridError('The File APIs are not fully supported by your browser.')], xhr, self);
 	};
 	xhr.onload = function(ev) {
-		if (xhr.status >= 300) {
-			doCallback(callback, [new UsergridError(JSON.parse(xhr.responseText)), null, self], self);
+		if(xhr.status >= 500 && attempts>0){
+			self.set('attempts', --attempts);
+			setTimeout(function(){self.upload.apply(self, args);}, 100);
+		}else if (xhr.status >= 300) {
+			self.set('attempts')
+			doCallback(callback, [new UsergridError(JSON.parse(xhr.responseText)), xhr, self], self);
 		} else {
+			self.set('attempts')
 			doCallback(callback, [null, xhr, self], self);
 		}
 	};
@@ -128,9 +140,7 @@ Usergrid.Asset.prototype.upload = function(data, callback) {
 	fr.onload = function() {
 		var binary = fr.result;
 		xhr.overrideMimeType('application/octet-stream');
-		setTimeout(function() {
-			xhr.sendAsBinary(binary);
-		}, 1000);
+		xhr.sendAsBinary(binary);
 	};
 	fr.readAsBinaryString(data);
 };
@@ -146,17 +156,17 @@ Usergrid.Asset.prototype.download = function(callback) {
 	var self = this;
 	var endpoint = [this._client.URI, this._client.orgName, this._client.appName, "assets", self.get("uuid"), 'data'].join('/');
 	var xhr = new XMLHttpRequest();
+
 	xhr.open("GET", endpoint, true);
 	xhr.responseType = "blob";
 	xhr.onload = function(ev) {
 		var blob = xhr.response;
-		//callback(null, blob);
-		doCallback(callback, [null, blob, self], self);
+		doCallback(callback, [null, xhr, self], self);
 	};
 	xhr.onerror = function(err) {
 		callback(true, err);
-		doCallback(callback, [new UsergridError(err), err, self], self);
+		doCallback(callback, [new UsergridError(err), xhr, self], self);
 	};
-
+	xhr.overrideMimeType(self.get('content-type'));
 	xhr.send();
 };


[04/12] Refactored individual modules for standard callback signature and updated tests

Posted by sn...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/da8ecfff/sdks/html5-javascript/lib/modules/Entity.js
----------------------------------------------------------------------
diff --git a/sdks/html5-javascript/lib/modules/Entity.js b/sdks/html5-javascript/lib/modules/Entity.js
index 32c12db..d5dc3ec 100644
--- a/sdks/html5-javascript/lib/modules/Entity.js
+++ b/sdks/html5-javascript/lib/modules/Entity.js
@@ -1,4 +1,4 @@
-var ENTITY_SYSTEM_PROPERTIES=['metadata','created','modified','oldpassword','newpassword','type','activated','uuid'];
+var ENTITY_SYSTEM_PROPERTIES = ['metadata', 'created', 'modified', 'oldpassword', 'newpassword', 'type', 'activated', 'uuid'];
 
 /*
  *  A class to Model a Usergrid Entity.
@@ -8,8 +8,11 @@ var ENTITY_SYSTEM_PROPERTIES=['metadata','created','modified','oldpassword','new
  *  @param {object} options {client:client, data:{'type':'collection_type', uuid:'uuid', 'key':'value'}}
  */
 Usergrid.Entity = function(options) {
+  this._data={};
+  this._client=undefined;
   if (options) {
-    this._data = options.data || {};
+    //this._data = options.data || {};
+    this.set(options.data || {});
     this._client = options.client || {};
   }
 };
@@ -22,9 +25,9 @@ Usergrid.Entity = function(options) {
  *  @params {any} obj - any variable
  *  @return {boolean} Returns true or false
  */
-Usergrid.Entity.isEntity = function(obj){
+Usergrid.Entity.isEntity = function(obj) {
   return (obj && obj instanceof Usergrid.Entity);
-}
+};
 
 /*
  *  method to determine whether or not the passed variable is a Usergrid Entity
@@ -35,9 +38,9 @@ Usergrid.Entity.isEntity = function(obj){
  *  @params {any} obj - any variable
  *  @return {boolean} Returns true or false
  */
-Usergrid.Entity.isPersistedEntity = function(obj){
+Usergrid.Entity.isPersistedEntity = function(obj) {
   return (isEntity(obj) && isUUID(obj.get('uuid')));
-}
+};
 
 /*
  *  returns a serialized version of the entity object
@@ -47,7 +50,7 @@ Usergrid.Entity.isPersistedEntity = function(obj){
  *  @method serialize
  *  @return {string} data
  */
-Usergrid.Entity.prototype.serialize = function () {
+Usergrid.Entity.prototype.serialize = function() {
   return JSON.stringify(this._data);
 };
 
@@ -59,27 +62,29 @@ Usergrid.Entity.prototype.serialize = function () {
  *  @param {string} field
  *  @return {string} || {object} data
  */
-Usergrid.Entity.prototype.get = function (key) {
-    var value;
-    if(arguments.length===0){
-        value=this._data;
-    }else if(arguments.length>1){
-        key=[].slice.call(arguments).reduce(function(p,c,i,a){
-            if(c instanceof Array){
-                p= p.concat(c);
-            }else{
-                p.push(c);
-            }
-            return p;
-        },[]);
-    }
-    if(key instanceof Array){
-        var self=this;
-        value=key.map(function(k){return self.get(k)});
-    }else if("undefined" !== typeof key){
-        value=this._data[key];
-    }
-    return value;
+Usergrid.Entity.prototype.get = function(key) {
+  var value;
+  if (arguments.length === 0) {
+    value = this._data;
+  } else if (arguments.length > 1) {
+    key = [].slice.call(arguments).reduce(function(p, c, i, a) {
+      if (c instanceof Array) {
+        p = p.concat(c);
+      } else {
+        p.push(c);
+      }
+      return p;
+    }, []);
+  }
+  if (key instanceof Array) {
+    var self = this;
+    value = key.map(function(k) {
+      return self.get(k);
+    });
+  } else if ("undefined" !== typeof key) {
+    value = this._data[key];
+  }
+  return value;
 };
 /*
  *  adds a specific key value pair or object to the Entity's data
@@ -91,9 +96,9 @@ Usergrid.Entity.prototype.get = function (key) {
  *  @param {string} value
  *  @return none
  */
-Usergrid.Entity.prototype.set = function (key, value) {
+Usergrid.Entity.prototype.set = function(key, value) {
   if (typeof key === 'object') {
-    for(var field in key) {
+    for (var field in key) {
       this._data[field] = key[field];
     }
   } else if (typeof key === 'string') {
@@ -107,22 +112,21 @@ Usergrid.Entity.prototype.set = function (key, value) {
   }
 };
 
-Usergrid.Entity.prototype.getEndpoint = function () {
-    var type = this.get('type'), name, endpoint;
-    var nameProperties=['uuid', 'name'];
-    if (type === undefined) {
-        throw new UsergridError('cannot fetch entity, no entity type specified', 'no_type_specified');
-    }else if(type==="users"||type==="user"){
-        nameProperties.unshift('username');
-    }
-
-    var names= this.get(nameProperties).filter(function(x){return x != null && "undefined"!==typeof x});
-    if (names.length===0) {
-        return type;
-    }else{
-        name=names.shift();
-    }
-    return [type, name].join('/');
+Usergrid.Entity.prototype.getEndpoint = function() {
+  var type = this.get('type'),
+    nameProperties = ['uuid', 'name'],
+    name;
+  if (type === undefined) {
+    throw new UsergridError('cannot fetch entity, no entity type specified', 'no_type_specified');
+  } else if (/^users?$/.test(type)) {
+    nameProperties.unshift('username');
+  }
+  name = this.get(nameProperties)
+    .filter(function(x) {
+      return (x !== null && "undefined" !== typeof x);
+    })
+    .shift();
+  return (name) ? [type, name].join('/') : type;
 };
 /*
  *  Saves the entity back to the database
@@ -130,94 +134,90 @@ Usergrid.Entity.prototype.getEndpoint = function () {
  *  @method save
  *  @public
  *  @param {function} callback
- *  @return {callback} callback(err, data)
+ *  @return {callback} callback(err, response, self)
  */
 Usergrid.Entity.prototype.save = function(callback) {
   var self = this,
     type = this.get('type'),
     method = 'POST',
     entityId = this.get("uuid"),
-    data = {},
+    changePassword,
     entityData = this.get(),
-    password = this.get('password'),
-    oldpassword = this.get('oldpassword'),
-    newpassword = this.get('newpassword'),
     options = {
       method: method,
       endpoint: type
     };
-
-  //update the entity
+  //update the entity if the UUID is present
   if (entityId) {
     options.method = 'PUT';
     options.endpoint += '/' + entityId;
   }
-
   //remove system-specific properties
-  Object.keys(entityData)
+  options.body = Object.keys(entityData)
     .filter(function(key) {
-      return (ENTITY_SYSTEM_PROPERTIES.indexOf(key) === -1)
+      return (ENTITY_SYSTEM_PROPERTIES.indexOf(key) === -1);
     })
-    .forEach(function(key) {
+    .reduce(function(data, key) {
       data[key] = entityData[key];
-    });
-  options.body = data;
-  //save the entity first
-  this._client.request(options, function(err, response) {
+      return data;
+    }, {});
+  self._client.request(options, function(err, response) {
     var entity = response.getEntity();
     if (entity) {
       self.set(entity);
       self.set('type', (/^\//.test(response.path)) ? response.path.substring(1) : response.path);
     }
-    //      doCallback(callback,[err, self]);
-
-    /*
-        TODO move user logic to its own entity
-       */
-
-
-    //clear out pw info if present
-    self.set('password', null);
-    self.set('oldpassword', null);
-    self.set('newpassword', null);
     if (err && self._client.logging) {
       console.log('could not save entity');
-      doCallback(callback, [err, response, self]);
-    } else if ((/^users?/.test(self.get('type'))) && oldpassword && newpassword) {
-      //if this is a user, update the password if it has been specified;
-      //Note: we have a ticket in to change PUT calls to /users to accept the password change
-      //      once that is done, we will remove this call and merge it all into one
-      var options = {
-        method: 'PUT',
-        endpoint: type + '/' + self.get("uuid") + '/password',
-        body: {
-          uuid: self.get("uuid"),
-          username: self.get("username"),
-          password: password,
-          oldpassword: oldpassword,
-          newpassword: newpassword
-        }
-      }
-      self._client.request(options, function(err, data) {
-        if (err && self._client.logging) {
-          console.log('could not update user');
-        }
-        //remove old and new password fields so they don't end up as part of the entity object
-        self.set({
-          'password': null,
-          'oldpassword': null,
-          'newpassword': null
-        });
-        doCallback(callback, [err, data, self]);
-      });
-    } else {
-      doCallback(callback, [err, response, self]);
     }
-
+    doCallback(callback, [err, response, self], self);
   });
 };
 
 /*
+ *
+ * Updates the user's password
+ */
+Usergrid.Entity.prototype.changePassword = function(oldpassword, password, newpassword, callback) {
+  //Note: we have a ticket in to change PUT calls to /users to accept the password change
+  //      once that is done, we will remove this call and merge it all into one
+  var self = this;
+  if ("function" === typeof oldpassword && callback === undefined) {
+    callback = oldpassword;
+    oldpassword = self.get("oldpassword");
+    password = self.get("password");
+    newpassword = self.get("newpassword");
+  }
+  //clear out pw info if present
+  self.set({
+    'password': null,
+    'oldpassword': null,
+    'newpassword': null
+  });
+  if ((/^users?$/.test(self.get('type'))) && oldpassword && newpassword) {
+    var options = {
+      method: 'PUT',
+      endpoint: 'users/' + self.get("uuid") + '/password',
+      body: {
+        uuid: self.get("uuid"),
+        username: self.get("username"),
+        password: password,
+        oldpassword: oldpassword,
+        newpassword: newpassword
+      }
+    };
+    self._client.request(options, function(err, response) {
+      if (err && self._client.logging) {
+        console.log('could not update user');
+      }
+      //remove old and new password fields so they don't end up as part of the entity object
+      doCallback(callback, [err, response, self], self);
+    });
+  } else {
+    throw new UsergridInvalidArgumentError("Invalid arguments passed to 'changePassword'");
+  }
+};
+/*
  *  refreshes the entity by making a GET call back to the database
  *
  *  @method fetch
@@ -225,20 +225,20 @@ Usergrid.Entity.prototype.save = function(callback) {
  *  @param {function} callback
  *  @return {callback} callback(err, data)
  */
-Usergrid.Entity.prototype.fetch = function (callback) {
-    var endpoint, self = this;
-    endpoint=this.getEndpoint();
-    var options = {
-        method: 'GET',
-        endpoint: endpoint
-    };
-    this._client.request(options, function (err, response) {
-        var entity=response.getEntity();
-        if(entity){
-            self.set(entity);
-        }
-        doCallback(callback,[err, entity, self]);
-    });
+Usergrid.Entity.prototype.fetch = function(callback) {
+  var endpoint, self = this;
+  endpoint = this.getEndpoint();
+  var options = {
+    method: 'GET',
+    endpoint: endpoint
+  };
+  this._client.request(options, function(err, response) {
+    var entity = response.getEntity();
+    if (entity) {
+      self.set(entity);
+    }
+    doCallback(callback, [err, response, self], self);
+  });
 };
 
 /*
@@ -251,19 +251,19 @@ Usergrid.Entity.prototype.fetch = function (callback) {
  *  @return {callback} callback(err, data)
  *
  */
-Usergrid.Entity.prototype.destroy = function (callback) {
+Usergrid.Entity.prototype.destroy = function(callback) {
   var self = this;
   var endpoint = this.getEndpoint();
 
   var options = {
-    method:'DELETE',
-    endpoint:endpoint
+    method: 'DELETE',
+    endpoint: endpoint
   };
-  this._client.request(options, function (err, data) {
+  this._client.request(options, function(err, response) {
     if (!err) {
       self.set(null);
     }
-    doCallback(callback,[err, data]);
+    doCallback(callback, [err, response, self], self);
   });
 };
 
@@ -278,49 +278,65 @@ Usergrid.Entity.prototype.destroy = function (callback) {
  *  @return {callback} callback(err, data)
  *
  */
-Usergrid.Entity.prototype.connect = function (connection, entity, callback) {
+Usergrid.Entity.prototype.connect = function(connection, entity, callback) {
+  this.addOrRemoveConnection("POST", connection, entity, callback);
+};
 
+/*
+ *  disconnects one entity from another
+ *
+ *  @method disconnect
+ *  @public
+ *  @param {string} connection
+ *  @param {object} entity
+ *  @param {function} callback
+ *  @return {callback} callback(err, data)
+ *
+ */
+Usergrid.Entity.prototype.disconnect = function(connection, entity, callback) {
+  this.addOrRemoveConnection("DELETE", connection, entity, callback);
+};
+/*
+ *  adds or removes a connection between two entities
+ *
+ *  @method addOrRemoveConnection
+ *  @public
+ *  @param {string} method
+ *  @param {string} connection
+ *  @param {object} entity
+ *  @param {function} callback
+ *  @return {callback} callback(err, data)
+ *
+ */
+Usergrid.Entity.prototype.addOrRemoveConnection = function(method, connection, entity, callback) {
   var self = this;
-
-  var error;
+  if (['POST', 'DELETE'].indexOf(method.toUpperCase()) == -1) {
+    throw new UsergridInvalidArgumentError("invalid method for connection call. must be 'POST' or 'DELETE'");
+  }
   //connectee info
   var connecteeType = entity.get('type');
   var connectee = this.getEntityId(entity);
   if (!connectee) {
-    if (typeof(callback) === 'function') {
-      error = 'Error trying to delete object - no uuid specified.';
-      if (self._client.logging) {
-        console.log(error);
-      }
-      doCallback(callback, [true, error], self);
-    }
-    return;
+    throw new UsergridInvalidArgumentError("connectee could not be identified");
   }
 
   //connector info
   var connectorType = this.get('type');
   var connector = this.getEntityId(this);
   if (!connector) {
-    if (typeof(callback) === 'function') {
-      error = 'Error in connect - no uuid specified.';
-      if (self._client.logging) {
-        console.log(error);
-      }
-      doCallback(callback, [true, error], self);
-    }
-    return;
+    throw new UsergridInvalidArgumentError("connector could not be identified");
   }
 
-  var endpoint = connectorType + '/' + connector + '/' + connection + '/' + connecteeType + '/' + connectee;
+  var endpoint = [connectorType, connector, connection, connecteeType, connectee].join('/');
   var options = {
-    method:'POST',
-    endpoint:endpoint
+    method: method,
+    endpoint: endpoint
   };
-  this._client.request(options, function (err, data) {
+  this._client.request(options, function(err, response) {
     if (err && self._client.logging) {
-      console.log('entity could not be connected');
+      console.log('There was an error with the connection call');
     }
-    doCallback(callback, [err, data], self);
+    doCallback(callback, [err, response, self], self);
   });
 };
 
@@ -334,7 +350,7 @@ Usergrid.Entity.prototype.connect = function (connection, entity, callback) {
  *  @return {callback} callback(err, data)
  *
  */
-Usergrid.Entity.prototype.getEntityId = function (entity) {
+Usergrid.Entity.prototype.getEntityId = function(entity) {
   var id = false;
   if (isUUID(entity.get('uuid'))) {
     id = entity.get('uuid');
@@ -359,7 +375,7 @@ Usergrid.Entity.prototype.getEntityId = function (entity) {
  *  @return {callback} callback(err, data, connections)
  *
  */
-Usergrid.Entity.prototype.getConnections = function (connection, callback) {
+Usergrid.Entity.prototype.getConnections = function(connection, callback) {
 
   var self = this;
 
@@ -379,22 +395,22 @@ Usergrid.Entity.prototype.getConnections = function (connection, callback) {
 
   var endpoint = connectorType + '/' + connector + '/' + connection + '/';
   var options = {
-    method:'GET',
-    endpoint:endpoint
+    method: 'GET',
+    endpoint: endpoint
   };
-  this._client.request(options, function (err, data) {
+  this._client.request(options, function(err, data) {
     if (err && self._client.logging) {
       console.log('entity could not be connected');
     }
 
     self[connection] = {};
 
-    var length = (data && data.entities)?data.entities.length:0;
+    var length = (data && data.entities) ? data.entities.length : 0;
     for (var i = 0; i < length; i++) {
-      if (data.entities[i].type === 'user'){
+      if (data.entities[i].type === 'user') {
         self[connection][data.entities[i].username] = data.entities[i];
       } else {
-        self[connection][data.entities[i].name] = data.entities[i]
+        self[connection][data.entities[i].name] = data.entities[i];
       }
     }
 
@@ -403,16 +419,16 @@ Usergrid.Entity.prototype.getConnections = function (connection, callback) {
 
 };
 
-Usergrid.Entity.prototype.getGroups = function (callback) {
+Usergrid.Entity.prototype.getGroups = function(callback) {
 
   var self = this;
 
-  var endpoint = 'users' + '/' + this.get('uuid') + '/groups' ;
+  var endpoint = 'users' + '/' + this.get('uuid') + '/groups';
   var options = {
-    method:'GET',
-    endpoint:endpoint
+    method: 'GET',
+    endpoint: endpoint
   };
-  this._client.request(options, function (err, data) {
+  this._client.request(options, function(err, data) {
     if (err && self._client.logging) {
       console.log('entity could not be connected');
     }
@@ -424,16 +440,16 @@ Usergrid.Entity.prototype.getGroups = function (callback) {
 
 };
 
-Usergrid.Entity.prototype.getActivities = function (callback) {
+Usergrid.Entity.prototype.getActivities = function(callback) {
 
   var self = this;
 
-  var endpoint = this.get('type') + '/' + this.get('uuid') + '/activities' ;
+  var endpoint = this.get('type') + '/' + this.get('uuid') + '/activities';
   var options = {
-    method:'GET',
-    endpoint:endpoint
+    method: 'GET',
+    endpoint: endpoint
   };
-  this._client.request(options, function (err, data) {
+  this._client.request(options, function(err, data) {
     if (err && self._client.logging) {
       console.log('entity could not be connected');
     }
@@ -449,16 +465,16 @@ Usergrid.Entity.prototype.getActivities = function (callback) {
 
 };
 
-Usergrid.Entity.prototype.getFollowing = function (callback) {
+Usergrid.Entity.prototype.getFollowing = function(callback) {
 
   var self = this;
 
-  var endpoint = 'users' + '/' + this.get('uuid') + '/following' ;
+  var endpoint = 'users' + '/' + this.get('uuid') + '/following';
   var options = {
-    method:'GET',
-    endpoint:endpoint
+    method: 'GET',
+    endpoint: endpoint
   };
-  this._client.request(options, function (err, data) {
+  this._client.request(options, function(err, data) {
     if (err && self._client.logging) {
       console.log('could not get user following');
     }
@@ -466,7 +482,7 @@ Usergrid.Entity.prototype.getFollowing = function (callback) {
     for (var entity in data.entities) {
       data.entities[entity].createdDate = (new Date(data.entities[entity].created)).toUTCString();
       var image = self._client.getDisplayImage(data.entities[entity].email, data.entities[entity].picture);
-      data.entities[entity]._portal_image_icon =  image;
+      data.entities[entity]._portal_image_icon = image;
     }
 
     self.following = data.entities;
@@ -477,16 +493,16 @@ Usergrid.Entity.prototype.getFollowing = function (callback) {
 };
 
 
-Usergrid.Entity.prototype.getFollowers = function (callback) {
+Usergrid.Entity.prototype.getFollowers = function(callback) {
 
   var self = this;
 
-  var endpoint = 'users' + '/' + this.get('uuid') + '/followers' ;
+  var endpoint = 'users' + '/' + this.get('uuid') + '/followers';
   var options = {
-    method:'GET',
-    endpoint:endpoint
+    method: 'GET',
+    endpoint: endpoint
   };
-  this._client.request(options, function (err, data) {
+  this._client.request(options, function(err, data) {
     if (err && self._client.logging) {
       console.log('could not get user followers');
     }
@@ -494,7 +510,7 @@ Usergrid.Entity.prototype.getFollowers = function (callback) {
     for (var entity in data.entities) {
       data.entities[entity].createdDate = (new Date(data.entities[entity].created)).toUTCString();
       var image = self._client.getDisplayImage(data.entities[entity].email, data.entities[entity].picture);
-      data.entities[entity]._portal_image_icon =  image;
+      data.entities[entity]._portal_image_icon = image;
     }
 
     self.followers = data.entities;
@@ -504,16 +520,16 @@ Usergrid.Entity.prototype.getFollowers = function (callback) {
 
 };
 
-Usergrid.Entity.prototype.getRoles = function (callback) {
+Usergrid.Entity.prototype.getRoles = function(callback) {
 
   var self = this;
 
-  var endpoint = this.get('type') + '/' + this.get('uuid') + '/roles' ;
+  var endpoint = this.get('type') + '/' + this.get('uuid') + '/roles';
   var options = {
-    method:'GET',
-    endpoint:endpoint
+    method: 'GET',
+    endpoint: endpoint
   };
-  this._client.request(options, function (err, data) {
+  this._client.request(options, function(err, data) {
     if (err && self._client.logging) {
       console.log('could not get user roles');
     }
@@ -526,16 +542,16 @@ Usergrid.Entity.prototype.getRoles = function (callback) {
 
 };
 
-Usergrid.Entity.prototype.getPermissions = function (callback) {
+Usergrid.Entity.prototype.getPermissions = function(callback) {
 
   var self = this;
 
-  var endpoint = this.get('type') + '/' + this.get('uuid') + '/permissions' ;
+  var endpoint = this.get('type') + '/' + this.get('uuid') + '/permissions';
   var options = {
-    method:'GET',
-    endpoint:endpoint
+    method: 'GET',
+    endpoint: endpoint
   };
-  this._client.request(options, function (err, data) {
+  this._client.request(options, function(err, data) {
     if (err && self._client.logging) {
       console.log('could not get user permissions');
     }
@@ -557,9 +573,9 @@ Usergrid.Entity.prototype.getPermissions = function (callback) {
           path_part = parts[1];
         }
 
-        ops_part.replace("*", "get,post,put,delete")
+        ops_part=ops_part.replace("*", "get,post,put,delete");
         var ops = ops_part.split(',');
-        var ops_object = {}
+        var ops_object = {};
         ops_object.get = 'no';
         ops_object.post = 'no';
         ops_object.put = 'no';
@@ -582,61 +598,3 @@ Usergrid.Entity.prototype.getPermissions = function (callback) {
   });
 
 };
-
-/*
- *  disconnects one entity from another
- *
- *  @method disconnect
- *  @public
- *  @param {string} connection
- *  @param {object} entity
- *  @param {function} callback
- *  @return {callback} callback(err, data)
- *
- */
-Usergrid.Entity.prototype.disconnect = function (connection, entity, callback) {
-
-  var self = this;
-
-  var error;
-  //connectee info
-  var connecteeType = entity.get('type');
-  var connectee = this.getEntityId(entity);
-  if (!connectee) {
-    if (typeof(callback) === 'function') {
-      error = 'Error trying to delete object - no uuid specified.';
-      if (self._client.logging) {
-        console.log(error);
-      }
-      doCallback(callback, [true, error], self);
-
-    }
-    return;
-  }
-
-  //connector info
-  var connectorType = this.get('type');
-  var connector = this.getEntityId(this);
-  if (!connector) {
-    if (typeof(callback) === 'function') {
-      error = 'Error in connect - no uuid specified.';
-      if (self._client.logging) {
-        console.log(error);
-      }
-      doCallback(callback, [true, error], self);
-    }
-    return;
-  }
-
-  var endpoint = connectorType + '/' + connector + '/' + connection + '/' + connecteeType + '/' + connectee;
-  var options = {
-    method:'DELETE',
-    endpoint:endpoint
-  };
-  this._client.request(options, function (err, data) {
-    if (err && self._client.logging) {
-      console.log('entity could not be disconnected');
-    }
-    doCallback(callback, [err, data], self);
-  });
-};

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/da8ecfff/sdks/html5-javascript/lib/modules/Error.js
----------------------------------------------------------------------
diff --git a/sdks/html5-javascript/lib/modules/Error.js b/sdks/html5-javascript/lib/modules/Error.js
index e2b44b8..2a560d2 100644
--- a/sdks/html5-javascript/lib/modules/Error.js
+++ b/sdks/html5-javascript/lib/modules/Error.js
@@ -3,7 +3,7 @@
 /**
  * Created by ryan bridges on 2014-02-05.
  */
-(function (global) {
+(function(global) {
     //noinspection JSUnusedAssignment
     var name = 'UsergridError',
         short,
@@ -27,14 +27,14 @@
      *  UsergridError(message);
      */
 
-    function UsergridError(message, name, timestamp, duration, exception){
-        this.message=message;
-        this.name=name;
-        this.timestamp=timestamp||Date.now();
-        this.duration=duration||0;
-        this.exception=exception;
+    function UsergridError(message, name, timestamp, duration, exception) {
+        this.message = message;
+        this.name = name;
+        this.timestamp = timestamp || Date.now();
+        this.duration = duration || 0;
+        this.exception = exception;
     }
-    UsergridError.prototype=new Error();
+    UsergridError.prototype = new Error();
     UsergridError.prototype.constructor = UsergridError;
     /*
      *  Creates a UsergridError from the JSON response returned from the backend
@@ -53,65 +53,78 @@
      *  "error_description":"Could not find application for yourorgname/sandboxxxxx from URI: yourorgname/sandboxxxxx"
      *  }
      */
-    UsergridError.fromResponse=function(response){
-        if(response && "undefined"!==typeof response){
+    UsergridError.fromResponse = function(response) {
+        if (response && "undefined" !== typeof response) {
             return new UsergridError(response.error_description, response.error, response.timestamp, response.duration, response.exception);
-        }else{
+        } else {
             return new UsergridError();
         }
     };
-    UsergridError.createSubClass=function(name){
-        if(name in global && global[name])return global[name]
-        global[name]=function(){};
-        global[name].name=name;
-        global[name].prototype=new UsergridError();
+    UsergridError.createSubClass = function(name) {
+        if (name in global && global[name]) return global[name];
+        global[name] = function() {};
+        global[name].name = name;
+        global[name].prototype = new UsergridError();
         return global[name];
     };
 
-    function UsergridHTTPResponseError(message, name, timestamp, duration, exception){
-        this.message=message;
-        this.name=name;
-        this.timestamp=timestamp||Date.now();
-        this.duration=duration||0;
-        this.exception=exception;
+    function UsergridHTTPResponseError(message, name, timestamp, duration, exception) {
+        this.message = message;
+        this.name = name;
+        this.timestamp = timestamp || Date.now();
+        this.duration = duration || 0;
+        this.exception = exception;
     }
-    UsergridHTTPResponseError.prototype=new UsergridError();
-    function UsergridInvalidHTTPMethodError(message, name, timestamp, duration, exception){
-        this.message=message;
-        this.name=name;
-        this.timestamp=timestamp||Date.now();
-        this.duration=duration||0;
-        this.exception=exception;
+    UsergridHTTPResponseError.prototype = new UsergridError();
+
+    function UsergridInvalidHTTPMethodError(message, name, timestamp, duration, exception) {
+        this.message = message;
+        this.name = name || 'invalid_http_method';
+        this.timestamp = timestamp || Date.now();
+        this.duration = duration || 0;
+        this.exception = exception;
+    }
+    UsergridInvalidHTTPMethodError.prototype = new UsergridError();
+
+    function UsergridInvalidURIError(message, name, timestamp, duration, exception) {
+        this.message = message;
+        this.name = name || 'invalid_uri';
+        this.timestamp = timestamp || Date.now();
+        this.duration = duration || 0;
+        this.exception = exception;
     }
-    UsergridInvalidHTTPMethodError.prototype=new UsergridError();
-    function UsergridInvalidURIError(message, name, timestamp, duration, exception){
-        this.message=message;
-        this.name=name;
-        this.timestamp=timestamp||Date.now();
-        this.duration=duration||0;
-        this.exception=exception;
+    UsergridInvalidURIError.prototype = new UsergridError();
+
+    function UsergridInvalidArgumentError(message, name, timestamp, duration, exception) {
+        this.message = message;
+        this.name = name || 'invalid_argument';
+        this.timestamp = timestamp || Date.now();
+        this.duration = duration || 0;
+        this.exception = exception;
     }
-    UsergridInvalidURIError.prototype=new UsergridError();
-    function UsergridKeystoreDatabaseUpgradeNeededError(message, name, timestamp, duration, exception){
-        this.message=message;
-        this.name=name;
-        this.timestamp=timestamp||Date.now();
-        this.duration=duration||0;
-        this.exception=exception;
+    UsergridInvalidArgumentError.prototype = new UsergridError();
+
+    function UsergridKeystoreDatabaseUpgradeNeededError(message, name, timestamp, duration, exception) {
+        this.message = message;
+        this.name = name;
+        this.timestamp = timestamp || Date.now();
+        this.duration = duration || 0;
+        this.exception = exception;
     }
-    UsergridKeystoreDatabaseUpgradeNeededError.prototype=new UsergridError();
+    UsergridKeystoreDatabaseUpgradeNeededError.prototype = new UsergridError();
 
-    global['UsergridHTTPResponseError'] = UsergridHTTPResponseError;
-    global['UsergridInvalidHTTPMethodError'] = UsergridInvalidHTTPMethodError;
-    global['UsergridInvalidURIError'] = UsergridInvalidURIError;
-    global['UsergridKeystoreDatabaseUpgradeNeededError'] = UsergridKeystoreDatabaseUpgradeNeededError;
+    global.UsergridHTTPResponseError = UsergridHTTPResponseError;
+    global.UsergridInvalidHTTPMethodError = UsergridInvalidHTTPMethodError;
+    global.UsergridInvalidURIError = UsergridInvalidURIError;
+    global.UsergridInvalidArgumentError = UsergridInvalidArgumentError;
+    global.UsergridKeystoreDatabaseUpgradeNeededError = UsergridKeystoreDatabaseUpgradeNeededError;
 
     global[name] = UsergridError;
     if (short !== undefined) {
         //noinspection JSUnusedAssignment
         global[short] = UsergridError;
     }
-    global[name].noConflict = function () {
+    global[name].noConflict = function() {
         if (_name) {
             global[name] = _name;
         }
@@ -122,4 +135,3 @@
     };
     return global[name];
 }(this));
-

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/da8ecfff/sdks/html5-javascript/lib/modules/Folder.js
----------------------------------------------------------------------
diff --git a/sdks/html5-javascript/lib/modules/Folder.js b/sdks/html5-javascript/lib/modules/Folder.js
index ef654be..cbba955 100644
--- a/sdks/html5-javascript/lib/modules/Folder.js
+++ b/sdks/html5-javascript/lib/modules/Folder.js
@@ -12,18 +12,20 @@ Usergrid.Folder = function(options, callback) {
 	self._client = options.client;
 	self._data = options.data || {};
 	self._data.type = "folders";
-	var missingData = ["name", "owner", "path"].some(function(required) { return !(required in self._data)});
-	if(missingData){
-		return doCallback(callback, [true, new UsergridError("Invalid asset data: 'name', 'owner', and 'path' are required properties.")], self);
+	var missingData = ["name", "owner", "path"].some(function(required) {
+		return !(required in self._data);
+	});
+	if (missingData) {
+		return doCallback(callback, [new UsergridInvalidArgumentError("Invalid asset data: 'name', 'owner', and 'path' are required properties."), null, self], self);
 	}
-	self.save(function(err, data) {
+	self.save(function(err, response) {
 		if (err) {
-			doCallback(callback, [true, new UsergridError(data)], self);
+			doCallback(callback, [new UsergridError(response), response, self], self);
 		} else {
-			if (data && data.entities && data.entities.length){
-				self.set(data.entities[0]);
+			if (response && response.entities && response.entities.length) {
+				self.set(response.entities[0]);
 			}
-			doCallback(callback, [false, self], self);
+			doCallback(callback, [null, response, self], self);
 		}
 	});
 };
@@ -47,17 +49,17 @@ Usergrid.Folder.prototype.fetch = function(callback) {
 		console.log("self", self.get());
 		console.log("data", data);
 		if (!err) {
-			self.getAssets(function(err, data) {
+			self.getAssets(function(err, response) {
 				if (err) {
-					doCallback(callback, [true, new UsergridError(data)], self);
+					doCallback(callback, [new UsergridError(response), resonse, self], self);
 				} else {
 					doCallback(callback, [null, self], self);
 				}
 			});
 		} else {
-			doCallback(callback, [true, new UsergridError(data)], self)
+			doCallback(callback, [null, data, self], self);
 		}
-	})
+	});
 };
 /*
  *  Add an asset to the folder.
@@ -93,7 +95,7 @@ Usergrid.Folder.prototype.addAsset = function(options, callback) {
 		if (asset && asset instanceof Usergrid.Entity) {
 			asset.fetch(function(err, data) {
 				if (err) {
-					doCallback(callback, [err, new UsergridError(data)], self)
+					doCallback(callback, [new UsergridError(data), data, self], self);
 				} else {
 					var endpoint = ["folders", self.get("uuid"), "assets", asset.get("uuid")].join('/');
 					var options = {
@@ -102,13 +104,11 @@ Usergrid.Folder.prototype.addAsset = function(options, callback) {
 					};
 					self._client.request(options, callback);
 				}
-			})
+			});
 		}
 	} else {
 		//nothing to add
-		doCallback(callback, [true, {
-			error_description: "No asset specified"
-		}], self)
+		doCallback(callback, [new UsergridInvalidArgumentError("No asset specified"), null, self], self);
 	}
 };
 
@@ -145,13 +145,17 @@ Usergrid.Folder.prototype.removeAsset = function(options, callback) {
 			self._client.request({
 				method: 'DELETE',
 				endpoint: endpoint
-			}, callback);
+			}, function(err, response) {
+				if (err) {
+					doCallback(callback, [new UsergridError(response), response, self], self);
+				} else {
+					doCallback(callback, [null, response, self], self);
+				}
+			});
 		}
 	} else {
 		//nothing to add
-		doCallback(callback, [true, {
-			error_description: "No asset specified"
-		}], self)
+		doCallback(callback, [new UsergridInvalidArgumentError("No asset specified"), null, self], self);
 	}
 };
 

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/da8ecfff/sdks/html5-javascript/lib/modules/Group.js
----------------------------------------------------------------------
diff --git a/sdks/html5-javascript/lib/modules/Group.js b/sdks/html5-javascript/lib/modules/Group.js
index cdbef60..ca5dc9c 100644
--- a/sdks/html5-javascript/lib/modules/Group.js
+++ b/sdks/html5-javascript/lib/modules/Group.js
@@ -30,44 +30,46 @@ Usergrid.Group.prototype = new Usergrid.Entity();
  */
 Usergrid.Group.prototype.fetch = function(callback) {
   var self = this;
-  var groupEndpoint = 'groups/'+this._path;
-  var memberEndpoint = 'groups/'+this._path+'/users';
+  var groupEndpoint = 'groups/' + this._path;
+  var memberEndpoint = 'groups/' + this._path + '/users';
 
   var groupOptions = {
-    method:'GET',
-    endpoint:groupEndpoint
-  }
+    method: 'GET',
+    endpoint: groupEndpoint
+  };
 
   var memberOptions = {
-    method:'GET',
-    endpoint:memberEndpoint
-  }
+    method: 'GET',
+    endpoint: memberEndpoint
+  };
 
-  this._client.request(groupOptions, function(err, response){
-    if(err) {
-      if(self._client.logging) {
+  this._client.request(groupOptions, function(err, response) {
+    if (err) {
+      if (self._client.logging) {
         console.log('error getting group');
       }
       doCallback(callback, [err, response], self);
     } else {
       var entities = response.getEntities();
-      if(entities && entities.length) {
+      if (entities && entities.length) {
         var groupresponse = entities.shift();
         //self._response = groupresponse || {};
         self._client.request(memberOptions, function(err, response) {
-          if(err && self._client.logging) {
+          if (err && self._client.logging) {
             console.log('error getting group users');
           } else {
-            self._list = response.getEntities();
-              .filter(function(entity){return isUUID(entity.uuid)})
-              .map(function(entity){
-                  return new Usergrid.Entity({
-                    type: entity.type,
-                    client: self._client,
-                    uuid:entity.uuid,
-                    response:entity //TODO: deprecate this property
-                  });
-              })            
+            self._list = response.getEntities()
+              .filter(function(entity) {
+                return isUUID(entity.uuid);
+              })
+              .map(function(entity) {
+                return new Usergrid.Entity({
+                  type: entity.type,
+                  client: self._client,
+                  uuid: entity.uuid,
+                  response: entity //TODO: deprecate this property
+                });
+              });
           }
           doCallback(callback, [err, response, self], self);
         });
@@ -102,22 +104,22 @@ Usergrid.Group.prototype.members = function(callback) {
  */
 Usergrid.Group.prototype.add = function(options, callback) {
   var self = this;
-  if(options.user){
-    var options = {
-      method:"POST",
-      endpoint:"groups/"+this._path+"/users/"+options.user.get('username')
-    }
-    this._client.request(options, function(error, response){
-      if(error) {
+  if (options.user) {
+    options = {
+      method: "POST",
+      endpoint: "groups/" + this._path + "/users/" + options.user.get('username')
+    };
+    this._client.request(options, function(error, response) {
+      if (error) {
         doCallback(callback, [error, response, self], self);
       } else {
         self.fetch(callback);
       }
     });
-  }else{
-    doCallback(callback, ["no user specified"], this);
+  } else {
+    doCallback(callback, [new UsergridError("no user specified", 'no_user_specified'), null, this], this);
   }
-}
+};
 
 /*
  *  Removes a user from a group, and refreshes the group object.
@@ -132,22 +134,22 @@ Usergrid.Group.prototype.add = function(options, callback) {
  */
 Usergrid.Group.prototype.remove = function(options, callback) {
   var self = this;
-  if(options.user){
-    var options = {
-      method:"DELETE",
-      endpoint:"groups/"+this._path+"/users/"+options.user.get('username')
-    }
-    this._client.request(options, function(error, response){
-      if(error) {
+  if (options.user) {
+    options = {
+      method: "DELETE",
+      endpoint: "groups/" + this._path + "/users/" + options.user.get('username')
+    };
+    this._client.request(options, function(error, response) {
+      if (error) {
         doCallback(callback, [error, response, self], self);
       } else {
         self.fetch(callback);
       }
     });
-  }else{
-    doCallback(callback, ["no user specified"], this);
+  } else {
+    doCallback(callback, [new UsergridError("no user specified", 'no_user_specified'), null, this], this);
   }
-}
+};
 
 /*
  * Gets feed for a group.
@@ -160,17 +162,13 @@ Usergrid.Group.prototype.remove = function(options, callback) {
 Usergrid.Group.prototype.feed = function(callback) {
   var self = this;
   var options = {
-    method:"GET",
-    endpoint:"groups/"+this._path+"/feed"
-  }
-
-  this._client.request(options, function(err, response){
-    if (err && self.logging) {
-      console.log('error trying to log user in');
-    }
+    method: "GET",
+    endpoint: "groups/" + this._path + "/feed"
+  };
+  this._client.request(options, function(err, response) {
     doCallback(callback, [err, response, self], self);
   });
-}
+};
 
 /*
  * Creates activity and posts to group feed.
@@ -183,7 +181,7 @@ Usergrid.Group.prototype.feed = function(callback) {
  * @param {function} callback
  * @returns {callback} callback(err, entity)
  */
-Usergrid.Group.prototype.createGroupActivity = function(options, callback){
+Usergrid.Group.prototype.createGroupActivity = function(options, callback) {
   var self = this;
   var user = options.user;
   var entity = new Usergrid.Entity({

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/da8ecfff/sdks/html5-javascript/lib/modules/util/Ajax.js
----------------------------------------------------------------------
diff --git a/sdks/html5-javascript/lib/modules/util/Ajax.js b/sdks/html5-javascript/lib/modules/util/Ajax.js
index a9cf16c..8fc8d3a 100644
--- a/sdks/html5-javascript/lib/modules/util/Ajax.js
+++ b/sdks/html5-javascript/lib/modules/util/Ajax.js
@@ -5,7 +5,7 @@
     function partial(){
         var args = Array.prototype.slice.call(arguments);
         var fn=args.shift();
-        return fn.bind(this, args)
+        return fn.bind(this, args);
     }
     function Ajax() {
         this.logger=new global.Logger(name);
@@ -29,17 +29,21 @@
             self.logger.time(m + ' ' + u);
             (function(xhr) {
                 xhr.onreadystatechange = function() {
-                    this.readyState ^ 4 || (self.logger.timeEnd(m + ' ' + u), clearTimeout(timeout), p.done(null, this));
+                    if(this.readyState === 4){
+                        self.logger.timeEnd(m + ' ' + u);
+                        clearTimeout(timeout);
+                        p.done(null, this);
+                    }
                 };
                 xhr.onerror=function(response){
                     clearTimeout(timeout);
                     p.done(response, null);
-                }
+                };
                 xhr.oncomplete=function(response){
                     clearTimeout(timeout);
                     self.logger.timeEnd(m + ' ' + u);
                     self.info("%s request to %s returned %s", m, u, this.status );
-                }
+                };
                 xhr.open(m, u);
                 if (d) {
                     if("object"===typeof d){
@@ -50,13 +54,13 @@
                 }
                 timeout = setTimeout(function() {
                     xhr.abort();
-                    p.done("API Call timed out.", null)
+                    p.done("API Call timed out.", null);
                 }, 30000);
                 //TODO stick that timeout in a config variable
                 xhr.send(encode(d));
             }(new XMLHttpRequest()));
             return p;
-        };
+        }
         this.request=request;
         this.get = partial(request,'GET');
         this.post = partial(request,'POST');

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/da8ecfff/sdks/html5-javascript/lib/modules/util/Event.js
----------------------------------------------------------------------
diff --git a/sdks/html5-javascript/lib/modules/util/Event.js b/sdks/html5-javascript/lib/modules/util/Event.js
index 146d03e..d826e04 100644
--- a/sdks/html5-javascript/lib/modules/util/Event.js
+++ b/sdks/html5-javascript/lib/modules/util/Event.js
@@ -1,6 +1,6 @@
 var UsergridEventable	= function(){
-    throw Error("'UsergridEventable' is not intended to be invoked directly")
-}
+    throw Error("'UsergridEventable' is not intended to be invoked directly");
+};
 UsergridEventable.prototype	= {
     bind	: function(event, fn){
         this._events = this._events || {};
@@ -16,7 +16,7 @@ UsergridEventable.prototype	= {
         this._events = this._events || {};
         if( event in this._events === false  )	return;
         for(var i = 0; i < this._events[event].length; i++){
-            this._events[event][i].apply(this, Array.prototype.slice.call(arguments, 1))
+            this._events[event][i].apply(this, Array.prototype.slice.call(arguments, 1));
         }
     }
 };
@@ -30,4 +30,4 @@ UsergridEventable.mixin	= function(destObject){
         }
         destObject.prototype[props[i]]	= UsergridEventable.prototype[props[i]];
     }
-}
+};

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/da8ecfff/sdks/html5-javascript/lib/modules/util/Logger.js
----------------------------------------------------------------------
diff --git a/sdks/html5-javascript/lib/modules/util/Logger.js b/sdks/html5-javascript/lib/modules/util/Logger.js
index f81a0e8..fe357b7 100644
--- a/sdks/html5-javascript/lib/modules/util/Logger.js
+++ b/sdks/html5-javascript/lib/modules/util/Logger.js
@@ -14,12 +14,12 @@
     Logger.prototype.init=function(name, logEnabled){
         this.name=name||"UNKNOWN";
         this.logEnabled=logEnabled||true;
-        var addMethod=function(method){this[method]=this.createLogMethod(method)}.bind(this);
-        Logger.METHODS.forEach(addMethod)
-    }
+        var addMethod=function(method){this[method]=this.createLogMethod(method);}.bind(this);
+        Logger.METHODS.forEach(addMethod);
+    };
     Logger.prototype.createLogMethod=function(method){
         return Logger.prototype.log.bind(this, method);
-    }
+    };
     Logger.prototype.prefix=function(method, args){
         var prepend='['+method.toUpperCase()+']['+name+"]:\t";
         if(['log', 'error', 'warn', 'info'].indexOf(method)!==-1){
@@ -30,7 +30,7 @@
             }
         }
         return args;
-    }
+    };
     Logger.prototype.log=function(){
         var args=[].slice.call(arguments);
         method=args.shift();
@@ -40,10 +40,10 @@
         if(!(this.logEnabled && console && console[method]))return;
         args=this.prefix(method, args);
         console[method].apply(console, args);
-    }
+    };
     Logger.prototype.setLogEnabled=function(logEnabled){
         this.logEnabled=logEnabled||true;
-    }
+    };
 
     Logger.mixin	= function(destObject){
         destObject.__logger=new Logger(destObject.name||"UNKNOWN");
@@ -55,8 +55,8 @@
             }
             destObject.prototype[method]=destObject.__logger.createLogMethod(method);
         };
-        Logger.METHODS.forEach(addMethod)
-    }
+        Logger.METHODS.forEach(addMethod);
+    };
     global[name] =  Logger;
     global[name].noConflict = function() {
         if(overwrittenName){

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/da8ecfff/sdks/html5-javascript/lib/modules/util/Promise.js
----------------------------------------------------------------------
diff --git a/sdks/html5-javascript/lib/modules/util/Promise.js b/sdks/html5-javascript/lib/modules/util/Promise.js
index e2d97a6..43d7ed6 100644
--- a/sdks/html5-javascript/lib/modules/util/Promise.js
+++ b/sdks/html5-javascript/lib/modules/util/Promise.js
@@ -8,12 +8,9 @@
             this.result = null;
             this.callbacks = [];
         }
-        Promise.prototype.create = function() {
-            return new Promise()
-        };
         Promise.prototype.then = function(callback, context) {
             var f = function() {
-                return callback.apply(context, arguments)
+                return callback.apply(context, arguments);
             };
             if (this.complete) {
                 f(this.error, this.result);

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/da8ecfff/sdks/html5-javascript/tests/mocha/test.js
----------------------------------------------------------------------
diff --git a/sdks/html5-javascript/tests/mocha/test.js b/sdks/html5-javascript/tests/mocha/test.js
index ff6fa3e..d27949c 100644
--- a/sdks/html5-javascript/tests/mocha/test.js
+++ b/sdks/html5-javascript/tests/mocha/test.js
@@ -79,11 +79,10 @@ describe('UsergridError', function() {
 describe('Usergrid', function(){
     describe('SDK Version', function(){
         it('should contain a minimum SDK version',function(){
-            assert(Usergrid.VERSION, "expected minimum version '0.10.08'");
-            var parts=Usergrid.VERSION.split(/\.0?/).map(function(bit){return parseInt(bit)});
-            console.log(parts);
-            assert(parts.length===3, "Version number is not in the ##.##.## format");
-            assert(parts.shift()>=0 && parts.shift() >=10 && parts.shift() >=8, "expected minimum version '0.10.08'");
+            var parts=Usergrid.VERSION.split('.').map(function(i){return i.replace(/^0+/,'')}).map(function(i){return parseInt(i)});
+
+            assert(parts[1]>=10, "expected minor version >=10");
+            assert(parts[1]>10||parts[2]>=8, "expected minimum version >=8");
         });
     });
     describe('Usergrid Request/Response', function() {
@@ -92,6 +91,7 @@ describe('Usergrid', function(){
         var dogURI='https://api.usergrid.com/yourorgname/sandbox/dogs'
         it('should POST to a URI',function(done){
             var req=new Usergrid.Request("POST", dogURI, {}, dogData, function(err, response){
+                console.error(err, response);
                 assert(!err, err);
                 assert(response instanceof Usergrid.Response, "Response is not and instance of Usergrid.Response");
                 done();
@@ -205,7 +205,6 @@ describe('Usergrid', function(){
                     method: 'GET',
                     endpoint: 'users'
                 }, function(err, data) {
-                    //console.log(err, data);
                     assert(data.params.test2[0]==='test2', "the default query parameters were not sent to the backend");
                     assert(data.params.test1[0]==='test1', "the default query parameters were not sent to the backend");
                     done();
@@ -222,7 +221,7 @@ describe('Usergrid', function(){
                 }, function(err, data) {
                     usergridTestHarness(err, data, done, [
                         function(err, data) {
-                            assert(true)
+                            assert(!err)
                         }
                     ]);
                 });
@@ -303,7 +302,8 @@ describe('Usergrid', function(){
         describe('Usergrid convenience methods', function(){
             before(function(){ client.logout();});
             it('createEntity',function(done){
-                client.createEntity({type:'dog',name:'createEntityTestDog'}, function(err, dog){
+                client.createEntity({type:'dog',name:'createEntityTestDog'}, function(err, response, dog){
+                    console.warn(err, response, dog);
                     assert(!err, "createEntity returned an error")
                     assert(dog, "createEntity did not return a dog")
                     assert(dog.get("name")==='createEntityTestDog', "The dog's name is not 'createEntityTestDog'")
@@ -311,7 +311,7 @@ describe('Usergrid', function(){
                 })
             })
             it('createEntity - existing entity',function(done){
-                    client.createEntity({type:'dog',name:'createEntityTestDog'}, function(err, dog){
+                    client.createEntity({type:'dog',name:'createEntityTestDog'}, function(err, response, dog){
                         try{
                             assert(err, "createEntity should return an error")
                         }catch(e){
@@ -323,7 +323,7 @@ describe('Usergrid', function(){
             })
             var testGroup;
             it('createGroup',function(done){
-                client.createGroup({path:'dogLovers'},function(err, group){
+                client.createGroup({path:'dogLovers'},function(err, response, group){
                         try{
                             assert(!err, "createGroup returned an error")
                         }catch(e){
@@ -346,7 +346,7 @@ describe('Usergrid', function(){
             })
             var dogEntity;
             it('getEntity',function(done){
-                client.getEntity({type:'dog',name:'createEntityTestDog'}, function(err, dog){
+                client.getEntity({type:'dog',name:'createEntityTestDog'}, function(err, response, dog){
                     assert(!err, "createEntity returned an error")
                     assert(dog, "createEntity returned a dog")
                     assert(dog.get("uuid")!==null, "The dog's UUID was not returned")
@@ -366,7 +366,7 @@ describe('Usergrid', function(){
             })
             var dogCollection;
             it('createCollection',function(done){
-                client.createCollection({type:'dogs'},function(err, dogs){
+                client.createCollection({type:'dogs'},function(err, response, dogs){
                     assert(!err, "createCollection returned an error");
                     assert(dogs, "createCollection did not return a dogs collection");
                     dogCollection=dogs;
@@ -384,8 +384,10 @@ describe('Usergrid', function(){
             })
             var activityUser;
             before(function(done){
-                activityUser=new Usergrid.Entity({client:client,data:{"type":"user",username:"testActivityUser"}});
+                activityUser=new Usergrid.Entity({client:client,data:{"type":"user",'username':"testActivityUser"}});
+                console.warn(activityUser);
                 activityUser.fetch(function(err, data){
+                    console.warn(err, data, activityUser);
                     if(err){
                         activityUser.save(function(err, data){
                             activityUser.set(data);
@@ -646,7 +648,7 @@ describe('Usergrid', function(){
                 } //limit statement set to 50
             }
 
-            client.createCollection(options, function(err, dogs) {
+            client.createCollection(options, function(err, response, dogs) {
                 if (!err) {
                     assert(!err, "could not retrieve list of dogs: " + dogs.error_description);
                     //we got 50 dogs, now display the Entities:
@@ -655,6 +657,7 @@ describe('Usergrid', function(){
                     while (dogs.hasNextEntity()) {
                         //get a reference to the dog
                         var dog = dogs.getNextEntity();
+                        console.warn(dog);
                         //notice('removing dog ' + dogname + ' from database');
                         if(dog === null) continue;
                         dog.destroy(function(err, data) {
@@ -987,8 +990,8 @@ describe('Usergrid', function(){
                     owner: user.get("uuid"),
                     path: folderpath
                 }
-            }, function(err, data) {
-                assert(!err, data.error_description);
+            }, function(err, response, folder) {
+                assert(!err, err);
                 done();
             });
         });
@@ -1000,8 +1003,10 @@ describe('Usergrid', function(){
                     owner: user.get("uuid"),
                     path: filepath
                 }
-            }, function(err, data) {
-                assert(!err, data.error_description);
+            }, function(err, response, asset) {
+                if(err){
+                    assert(false, err);
+                }
                 //console.log(data);
                 done();
             });
@@ -1009,17 +1014,21 @@ describe('Usergrid', function(){
         it('should upload asset data', function(done) {
             this.timeout(15000);
             setTimeout(function() {
-                asset.upload(test_image, function(err, data) {
-                    assert(!err, data.error_description);
+                asset.upload(test_image, function(err, response, asset) {
+                    if(err){
+                        assert(false, err.error_description);
+                    }
                     done();
                 });
             }, 10000);
         });
         it('should retrieve asset data', function(done) {
-            asset.download(function(err, data) {
-                assert(!err, data.error_description);
-                assert(data.type == test_image.type, "MIME types don't match");
-                assert(data.size == test_image.size, "sizes don't match");
+            asset.download(function(err, response, asset) {
+                if(err){
+                    assert(false, err.error_description);
+                }
+                assert(asset.type == test_image.type, "MIME types don't match");
+                assert(asset.size == test_image.size, "sizes don't match");
                 done();
             });
         });
@@ -1027,14 +1036,18 @@ describe('Usergrid', function(){
             folder.addAsset({
                 asset: asset
             }, function(err, data) {
-                assert(!err, data.error_description);
+                if(err){
+                    assert(false, err.error_description);
+                }
                 //console.log(data['entities']);
                 done();
             })
         });
         it('should list the assets from a folder', function(done) {
             folder.getAssets(function(err, assets) {
-                assert(!err, assets.error_description);
+                if(err){
+                    assert(false, err.error_description);
+                }
                 //console.log(folder['assets']);
                 done();
             })
@@ -1043,21 +1056,27 @@ describe('Usergrid', function(){
             folder.removeAsset({
                 asset: asset
             }, function(err, data) {
-                assert(!err, data.error_description);
+                if(err){
+                    assert(false, err.error_description);
+                }
                 //console.log(data['entities']);
                 done();
             })
         });
         it('should DELETE the asset', function(done) {
             asset.destroy(function(err, data) {
-                assert(!err, data.error_description);
+                if(err){
+                    assert(false, err.error_description);
+                }
                 //console.log(data);
                 done();
             })
         });
         it('should DELETE the folder', function(done) {
             folder.destroy(function(err, data) {
-                assert(!err, data.error_description);
+                if(err){
+                    assert(false, err.error_description);
+                }
                 //console.log(data);
                 done();
             })