/**
* @copyright 2015 Tridium, Inc. All Rights Reserved.
* @author Gareth Johnson
*/
/**
* Defines {@link baja.coll.QueryResult}.
* @module baja/coll/QueryResult
*/
define([ "bajaScript/bson",
"bajaScript/baja/obj/Simple",
"bajaScript/baja/coll/collUtil",
"bajaScript/baja/coll/QueryCursor",
"bajaScript/baja/comm/Callback",
"bajaScript/baja/tag/entityDecoder",
"bajaPromises" ],
function (
baja,
Simple,
collUtil,
QueryCursor,
Callback,
entityDecoder,
bajaPromises) {
"use strict";
var subclass = baja.subclass,
callSuper = baja.callSuper,
objectify = baja.objectify,
isObjEmpty = collUtil.isObjEmpty;
/**
* Represents a `baja:QueryResult` in BajaScript.
*
* A QueryResult can be resolved from a NEQL query.
*
* @class
* @alias baja.coll.QueryResult
*/
var QueryResult = function QueryResult(queryData) {
callSuper(QueryResult, this, arguments);
this.$queryData = queryData;
};
subclass(QueryResult, Simple);
/**
* Default `QueryResult` instance.
* @type {baja.coll.QueryResult}
*/
QueryResult.DEFAULT = new QueryResult({});
/**
* Make a `QueryResult`.
*
* @private
*
* @param {Object} queryData
* @returns {baja.coll.QueryResult} the QueryResult.
*/
QueryResult.make = function (queryData) {
return isObjEmpty(queryData) ? QueryResult.DEFAULT : new QueryResult(queryData);
};
/**
* Make a `QueryResult`.
*
* @private
*
* @param {Object} queryData
* @returns {baja.coll.QueryResult} the QueryResult
*/
QueryResult.prototype.make = function (queryData) {
return QueryResult.make(queryData);
};
/**
* Decode a `QueryResult` from a `String`.
*
* @private
*
* @param {String} str
* @returns {baja.coll.QueryResult}
*/
QueryResult.prototype.decodeFromString = function (str) {
return QueryResult.make(JSON.parse(str));
};
/**
* Encode the `QueryResult` to a `String`.
*
* @private
*
* @returns {String}
*/
QueryResult.prototype.encodeToString = function () {
return JSON.stringify(this.$queryData);
};
/**
* Return the Query string for the result.
*
* @returns {String} The Query.
*/
QueryResult.prototype.getQuery = function () {
return this.$queryData.query;
};
/**
* Return the Scope ORD for the result.
*
* @returns {baja.Ord} The Scope ORD.
*/
QueryResult.prototype.getScopeOrd = function () {
return baja.Ord.make(this.$queryData.scope);
};
/**
* Iterate through a QueryResult's Entities.
*
* Please note, this may retrieve data asynchronously.
*
* A callback function is passed in to retrieve the Cursor.
*
* @see module:baja/coll/QueryCursor
*
* @param {Object|Function} obj the object literal that specifies the method's
* arguments.
* @param {Function} [obj.ok] (Deprecated: use Promise) called when the
* cursor has been created with the cursor as an argument.
* @param {Function} [obj.fail] (Deprecated: use Promise) called if the cursor
* fails to be retrieved. An error is passed in as the first argument.
* @param {baja.comm.Batch} [obj.batch] if specified, the operation will be
* batched into this object.
* @param {Function} [obj.before] called just before the Cursor is about to be
* iterated through.
* @param {Function} [obj.after] called just after the Cursor has finished
* iterating.
* @param {Number} [obj.offset=0] Specifies the row number to start encoding
* the result-set from.
* @param {Number} [obj.limit=10] Specifies the maximum number of rows that
* can be encoded.
* @returns {Promise} a promise that will be resolved once the cursor has been
* retrieved.
*
* @example
* myQueryResult.cursor({
* each: function () {
* // Called for each Entity in the Cursor...
* var dataFromCursor = this.get();
* }
* })
* .then(function (cursor) {
* // Called once we have the Cursor
* })
* .catch(function (err) {
* // Called if any errors in getting data
* });
*/
QueryResult.prototype.cursor = function (obj) {
obj = objectify(obj, "each");
var cb = new Callback(obj.ok, obj.fail, obj.batch),
that = this;
// Add an intermediate callback to create the Cursor Object and pass it back
cb.addOk(function (ok, fail, resp) {
var i,
cursor;
// Decode Entities
var promises = [];
for (i = 0; i < resp.length; ++i) {
promises[i] = entityDecoder.decodeEntity(resp[i]);
}
return bajaPromises.all(promises)
.then(function (entities) {
// Create a Cursor Object and pass it into the Handler
cursor = new QueryCursor(that, entities);
if (typeof obj.before === "function") {
cursor.before(obj.before);
}
if (typeof obj.after === "function") {
cursor.after(obj.after);
}
// Please note, if defined, this will trigger an iteration
if (typeof obj.each === "function") {
cursor.each(obj.each);
}
return ok(cursor);
});
});
obj.limit = obj.limit || 10;
obj.offset = obj.offset || 0;
// If '$data' is specified then use this for the first Cursor iteration. This is an optimization made
// by BajaScript's ORD architecture. This enables an ORD to be queried and then iterated through at the same time.
if (obj.$data) {
cb.ok(obj.$data);
} else {
// Make a a network call for the Cursor data
baja.comm.cursor(this.$queryData.req, cb, obj);
}
return cb.promise();
};
return QueryResult;
});