/**
* @copyright 2015 Tridium, Inc. All Rights Reserved.
* @author Gareth Johnson
*/
/**
* Defines {@link baja.coll.tableMixIn}.
* @module baja/coll/tableMixIn
*/
define([ "bajaScript/bson",
"bajaScript/baja/obj/Simple",
"bajaScript/baja/obj/Facets",
"bajaScript/baja/coll/TableCursor",
"bajaScript/baja/coll/collUtil",
"bajaScript/baja/comm/Callback",
"bajaPromises" ],
function (
baja,
Simple,
Facets,
TableCursor,
collUtil,
Callback,
bajaPromises) {
"use strict";
const { objectify, strictArg } = baja;
/**
* A Mix-In for objects that are tables.
*
* @mixin
* @alias baja.coll.tableMixIn
*/
var tableMixIn = {
/**
* Returns an array of Table Columns.
*
* @see baja.coll.Table#getCol
*
* @returns {Array.<module:baja/coll/Table.TableColumn>} an array of columns
*/
getColumns: function () {
var columns = [],
cols = this.$tableData.cols,
i;
for (i = 0; i < cols.length; ++i) {
columns.push(this.getCol(cols[i].n));
}
return columns;
},
/**
* Returns a column object for the given column name.
*
* @param {String|Number} column the column name or index.
* @returns {module:baja/coll/Table.TableColumn} the table column or null
* if the column can't be found.
*/
getCol: function (column) {
strictArg(column);
var to = typeof column,
cols = this.$tableData.cols,
data,
i;
if (to === "number") {
data = cols[column];
} else if (to === "string") {
for (i = 0; i < cols.length; ++i) {
if (cols[i].n === column) {
data = cols[i];
break;
}
}
}
// If there's no data then return null at this point
if (!data) {
return null;
}
/**
* Table Column.
* @class module:baja/coll/Table.TableColumn
* @see baja.coll.Table
*/
return /** @lends module:baja/coll/Table.TableColumn.prototype */ {
/**
* Return the column name.
*
* @returns {String}
*/
getName: function getName() {
return data.n;
},
/**
* Return the column display name.
*
* @returns {String}
*/
getDisplayName: function getDisplayName() {
return data.dn;
},
/**
* Return the column Type.
*
* @returns {Type}
*/
getType: function getType() {
return baja.lt(data.t);
},
/**
* Return the column flags.
*
* @returns {Number}
*/
getFlags: function getFlags() {
return data.f;
},
/**
* the column facets
*
* @returns {baja.Facets}
*/
getFacets: function getFacets() {
return Facets.DEFAULT.decodeFromString(data.x, baja.Simple.$unsafeDecode);
}
};
},
/**
* Returns a promise that's used to access a Component that contains all the
* table's configuration data. In the case of a History, the Component will
* be a 'history:HistoryConfig' Component. For other types of query, this
* may change in the future.
*
* @param {Object} [obj] optional object literal parameters.
* @param {Function} [obj.ok] (Deprecated: use Promise) the ok callback.
* This function is called once the parameters have been resolved.
* @param {Function} [obj.fail] (Deprecated: use Promise) the fail callback.
* This function is called once the parameters have failed to resolve.
* @returns {Promise.<baja.Component>} promise that resolves to a config
* Component.
*/
toConfig: function (obj) {
obj = obj || {};
var that = this,
cb = new Callback(obj.ok, obj.fail);
if (!that.$config) {
if (that.$tableData.config) {
baja.bson.importUnknownTypes(that.$tableData.config,
function ok() {
that.$config = baja.bson.decodeValue(that.$tableData.config,
baja.$serverDecodeContext);
cb.ok(that.$config);
},
function fail(err) {
cb.fail(err);
}
);
} else {
that.$config = new baja.Component();
cb.ok(that.$config);
}
} else {
cb.ok(that.$config);
}
return cb.promise();
},
/**
* Return true if the table has a configuration component.
*
* @returns {Boolean} true if a config component is available.
*/
hasConfig: function () {
return !!this.$tableData.config;
},
/**
* Iterate through a Table.
*
* Please note, this may retrieve data asynchronously.
*
* A callback function is passed in to retrieve the Cursor.
*
* @see module:baja/coll/TableCursor
*
* @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
* myTable.cursor({
* each: function () {
* // Called for each item 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
* });
*/
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) {
function createCursor(cursorValues) {
const cursor = new TableCursor(that, cursorValues);
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 cursor;
}
bajaPromises.all(resp.map((bson) => baja.bson.decodeAsync(bson, baja.$serverDecodeContext)))
.then((cursorValues) => ok(createCursor(cursorValues)), fail);
});
obj.limit = obj.limit || 10;
obj.offset = obj.offset || 0;
// $cursorBsonArray might get stashed away by resolving a cursor-based ORD, in Ord.js. this
// allows the ORD resolution to return the table data in the same network call, rather than
// doing the resolution and cursor in two separate calls.
if (obj.$cursorBsonArray) {
cb.ok(obj.$cursorBsonArray);
} else {
// Make a network call for the Cursor data
baja.comm.cursor(this.$tableData.req, cb, obj);
}
return cb.promise();
}
};
/**
* Mix-in the table methods onto the given Object.
*
* @private
*
* @param obj
*/
return function mixin(obj) {
obj.getColumns = tableMixIn.getColumns;
obj.getCol = tableMixIn.getCol;
obj.toConfig = tableMixIn.toConfig;
obj.hasConfig = tableMixIn.hasConfig;
obj.cursor = tableMixIn.cursor;
};
});