blob: 75affaac70046c900dba1c3a5d5cb9e509518e24 [file] [log] [blame]
/*
* 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)
*/
Usergrid.Collection = function(options, callback) {
if (options) {
this._client = options.client;
this._type = options.type;
this.qs = options.qs || {};
//iteration
this._list = options.list || [];
this._iterator = options.iterator || -1; //first thing we do is increment, so set to -1
//paging
this._previous = options.previous || [];
this._next = options.next || null;
this._cursor = options.cursor || null;
//restore entities if available
if (options.list) {
var count = options.list.length;
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) {
//populate the collection
this.fetch(callback);
}
};
/*
* method to determine whether or not the passed variable is a Usergrid Collection
*
* @method isCollection
* @public
* @params {any} obj - any variable
* @return {boolean} Returns true or false
*/
Usergrid.isCollection = function(obj){
return (obj && obj instanceof Usergrid.Collection);
}
/*
* gets the data from the collection object for serialization
*
* @method serialize
* @return {object} data
*/
Usergrid.Collection.prototype.serialize = function () {
//pull out the state from this object and return it
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;
data.list = [];
while(this.hasNextEntity()) {
var entity = this.getNextEntity();
data.list[i] = entity.serialize();
i++;
}
data = JSON.stringify(data);
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);
}
});
};
/*
* Populates the collection from the server
*
* @method fetch
* @param {function} callback
* @return {callback} callback(err, data)
*/
Usergrid.Collection.prototype.fetch = function (callback) {
var self = this;
var qs = this.qs;
//add in the cursor if one is available
if (this._cursor) {
qs.cursor = this._cursor;
} else {
delete qs.cursor;
}
var options = {
method:'GET',
endpoint:this._type,
qs:this.qs
};
this._client.request(options, function (err, data) {
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;
}
}
}
}
doCallback(callback, [err, data], self);
});
};
/*
* Adds a new Entity to the collection (saves, then adds to the local object)
*
* @method addNewEntity
* @param {object} entity
* @param {function} callback
* @return {callback} callback(err, data, entity)
*/
Usergrid.Collection.prototype.addEntity = function (options, callback) {
var self = this;
options.type = this._type;
//create the new entity
this._client.createEntity(options, function (err, entity) {
if (!err) {
//then add the entity to the list
var count = self._list.length;
self._list[count] = entity;
}
doCallback(callback, [err, entity], self);
});
};
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;
};
/*
* Removes the Entity from the collection, then destroys the object on the server
*
* @method destroyEntity
* @param {object} entity
* @param {function} callback
* @return {callback} callback(err, data)
*/
Usergrid.Collection.prototype.destroyEntity = function (entity, callback) {
var self = this;
entity.destroy(function(err, data) {
if (err) {
if (self._client.logging) {
console.log('could not destroy entity');
}
doCallback(callback, [err, data], self);
} else {
//destroy was good, so repopulate the collection
self.fetch(callback);
}
});
//remove entity from the local store
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 false;
};
/*
* Looks up an Entity by UUID
*
* @method getEntityByUUID
* @param {string} UUID
* @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
}
var entity = new Usergrid.Entity(options);
entity.fetch(callback);
};
/*
* Returns the first Entity of the Entity list - does not affect the iterator
*
* @method getFirstEntity
* @return {object} returns an entity object
*/
Usergrid.Collection.prototype.getFirstEntity = function () {
var count = this._list.length;
if (count > 0) {
return this._list[0];
}
return null;
};
/*
* Returns the last Entity of the Entity list - does not affect the iterator
*
* @method getLastEntity
* @return {object} returns an entity object
*/
Usergrid.Collection.prototype.getLastEntity = function () {
var count = this._list.length;
if (count > 0) {
return this._list[count-1];
}
return null;
};
/*
* Entity iteration -Checks to see if there is a "next" entity
* in the list. The first time this method is called on an entity
* list, or after the resetEntityPointer method is called, it will
* return true referencing the first entity in the list
*
* @method hasNextEntity
* @return {boolean} true if there is a next entity, false if not
*/
Usergrid.Collection.prototype.hasNextEntity = function () {
var next = this._iterator + 1;
var hasNextElement = (next >=0 && next < this._list.length);
if(hasNextElement) {
return true;
}
return false;
};
/*
* Entity iteration - Gets the "next" entity in the list. The first
* time this method is called on an entity list, or after the method
* resetEntityPointer is called, it will return the,
* first entity in the list
*
* @method hasNextEntity
* @return {object} entity
*/
Usergrid.Collection.prototype.getNextEntity = function () {
this._iterator++;
var hasNextElement = (this._iterator >= 0 && this._iterator <= this._list.length);
if(hasNextElement) {
return this._list[this._iterator];
}
return false;
};
/*
* Entity iteration - Checks to see if there is a "previous"
* entity in the list.
*
* @method hasPrevEntity
* @return {boolean} true if there is a previous entity, false if not
*/
Usergrid.Collection.prototype.hasPrevEntity = function () {
var previous = this._iterator - 1;
var hasPreviousElement = (previous >=0 && previous < this._list.length);
if(hasPreviousElement) {
return true;
}
return false;
};
/*
* Entity iteration - Gets the "previous" entity in the list.
*
* @method getPrevEntity
* @return {object} entity
*/
Usergrid.Collection.prototype.getPrevEntity = function () {
this._iterator--;
var hasPreviousElement = (this._iterator >= 0 && this._iterator <= this._list.length);
if(hasPreviousElement) {
return this._list[this._iterator];
}
return false;
};
/*
* Entity iteration - Resets the iterator back to the beginning
* of the list
*
* @method resetEntityPointer
* @return none
*/
Usergrid.Collection.prototype.resetEntityPointer = function () {
this._iterator = -1;
};
/*
* Method to save off the cursor just returned by the last API call
*
* @public
* @method saveCursor
* @return none
*/
Usergrid.Collection.prototype.saveCursor = function(cursor) {
//if current cursor is different, grab it for next cursor
if (this._next !== cursor) {
this._next = cursor;
}
};
/*
* Resets the paging pointer (back to original page)
*
* @public
* @method resetPaging
* @return none
*/
Usergrid.Collection.prototype.resetPaging = function() {
this._previous = [];
this._next = null;
this._cursor = null;
};
/*
* Paging - checks to see if there is a next page od data
*
* @method hasNextPage
* @return {boolean} returns true if there is a next page of data, false otherwise
*/
Usergrid.Collection.prototype.hasNextPage = function () {
return (this._next);
};
/*
* Paging - advances the cursor and gets the next
* page of data from the API. Stores returned entities
* in the Entity list.
*
* @method getNextPage
* @param {function} callback
* @return {callback} callback(err, data)
*/
Usergrid.Collection.prototype.getNextPage = function (callback) {
if (this.hasNextPage()) {
//set the cursor to the next page of data
this._previous.push(this._cursor);
this._cursor = this._next;
//empty the list
this._list = [];
this.fetch(callback);
}
}
/*
* Paging - checks to see if there is a previous page od data
*
* @method hasPreviousPage
* @return {boolean} returns true if there is a previous page of data, false otherwise
*/
Usergrid.Collection.prototype.hasPreviousPage = function () {
return (this._previous.length > 0);
};
/*
* Paging - reverts the cursor and gets the previous
* page of data from the API. Stores returned entities
* in the Entity list.
*
* @method getPreviousPage
* @param {function} callback
* @return {callback} callback(err, data)
*/
Usergrid.Collection.prototype.getPreviousPage = function (callback) {
if (this.hasPreviousPage()) {
this._next=null; //clear out next so the comparison will find the next item
this._cursor = this._previous.pop();
//empty the list
this._list = [];
this.fetch(callback);
}
};