/**
* @copyright 2015 Tridium, Inc. All Rights Reserved.
* @author Gareth Johnson
*/
/**
* Defines `SlotCursor` (not exposed on `baja` namespace).
* @module baja/comp/SlotCursor
*/
define([ "bajaScript/sys",
"bajaScript/baja/sys/structures/FilterCursor" ], function (
baja,
FilterCursor) {
"use strict";
var subclass = baja.subclass,
callSuper = baja.callSuper;
/**
* A `Cursor` used for `Slot` iteration.
*
* @class
* @alias module:baja/comp/SlotCursor
* @extends baja.FilterCursor
*
* @see baja.Complex#getSlots
*/
var SlotCursor = function SlotCursor() {
callSuper(SlotCursor, this, arguments);
};
subclass(SlotCursor, FilterCursor);
/**
* If the `Slot` is a `Property`, return its value (otherwise return null).
*
* @returns a Property value.
*/
SlotCursor.prototype.getValue = function () {
var slot = this.get();
return slot !== null && slot.isProperty() ? this.$context.get(slot) : null;
};
/**
* If the `Slot` is a `Property`, return its display `String` (otherwise return null).
*
* @returns {String} display String.
*/
SlotCursor.prototype.getDisplay = function () {
var slot = this.get();
return slot !== null && slot.isProperty() ? this.$context.getDisplay(slot) : null;
};
/**
* Return the first `Property` value in the cursor (regardless of iterative state).
*
* @returns {baja.Value} first `Property` value found in the Cursor (or null if nothing found).
*/
SlotCursor.prototype.firstValue = function () {
var slot = this.first();
return slot !== null && slot.isProperty() ? this.$context.get(slot) : null;
};
/**
* Return the first `Property` display String in the cursor (regardless of iterative state).
*
* @returns {String} first `Property` display String found in the Cursor (or null if nothing found).
*/
SlotCursor.prototype.firstDisplay = function () {
var slot = this.first();
return slot !== null && slot.isProperty() ? this.$context.getDisplay(slot) : null;
};
/**
* Return the last `Property` value in the cursor (regardless of iterative state).
*
* @returns {baja.Value} first Property value found in the Cursor (or null if nothing found).
*/
SlotCursor.prototype.lastValue = function () {
var slot = this.last();
return slot !== null && slot.isProperty() ? this.$context.get(slot) : null;
};
/**
* Return the last `Property` display `String` in the cursor (regardless of iterative state).
*
* @returns {String} last `Property` display `String` found in the Cursor (or null if nothing found).
*/
SlotCursor.prototype.lastDisplay = function () {
var slot = this.last();
return slot !== null && slot.isProperty() ? this.$context.getDisplay(slot) : null;
};
/**
* Iterate through the Cursor and call 'each' on every `Property` Slot and
* get its value.
*
* When the function is called, 'this' refers to the associated `Complex`
* and the argument is the value of the `Property`.
*
* @param {Function} func function called on every iteration with the
* argument being a `Property`'s value.
*/
SlotCursor.prototype.eachValue = function (func) {
return this.each(function (slot, i) {
if (slot.isProperty()) {
return func.call(this, this.get(slot), i);
}
// Return false so nothing stops iterating
return false;
});
};
/**
* Iterate through the Cursor and call 'each' on every `Property` Slot and
* get its display `String`.
*
* When the function is called, 'this' refers to the associated Complex and the argument
* is the display String.
*
* @param {Function} func function called on every iteration with the argument being a Property's display String
*/
SlotCursor.prototype.eachDisplay = function (func) {
return this.each(function (slot, i) {
if (slot.isProperty()) {
return func.call(this, this.getDisplay(slot), i);
}
// Return false so nothing stops iterating
return false;
});
};
/**
* Return an array of `Property` values (regardless of iterative state).
* This will call `get()` on each slot in the cursor, so please see the
* `get()` documentation for performance notes.
*
* @returns {Array.<baja.Value>}
* @see baja.Complex#get
*/
SlotCursor.prototype.toValueArray = function () {
var slots = this.toArray(),
values = [],
i;
for (i = 0; i < slots.length; ++i) {
if (slots[i].isProperty()) {
values.push(this.$context.get(slots[i]));
}
}
return values;
};
/**
* Return an array of `Property` display `String`s (regardless of iterative state).
*
* @returns {Array.<String>}
*/
SlotCursor.prototype.toDisplayArray = function () {
var slots = this.toArray(),
displays = [],
i;
for (i = 0; i < slots.length; ++i) {
if (slots[i].isProperty()) {
displays.push(this.$context.getDisplay(slots[i]));
}
}
return displays;
};
/**
* Return an Object Map of `Property` names with their corresponding
* values (regardless of iterative state).
*
* @returns {Object}
*/
SlotCursor.prototype.toValueMap = function () {
var slots = this.toArray(),
map = {},
s,
i;
for (i = 0; i < slots.length; ++i) {
s = slots[i];
if (s.isProperty()) {
map[s.getName()] = this.$context.get(s);
}
}
return map;
};
/**
* Return an Object Map of `Property` names with their corresponding display
* `String`s (regardless of iterative state).
*
* @returns {Object}
*/
SlotCursor.prototype.toDisplayMap = function () {
var slots = this.toArray(),
map = {},
s,
i;
for (i = 0; i < slots.length; ++i) {
s = slots[i];
if (s.isProperty()) {
map[s.getName()] = this.$context.getDisplay(s);
}
}
return map;
};
function slotCursorFrozen(slot) {
return slot.isFrozen();
}
/**
* Adds a filter to the Cursor for frozen Slots.
*
* @returns {module:baja/comp/SlotCursor} itself.
*/
SlotCursor.prototype.frozen = function () {
this.filter(slotCursorFrozen);
return this;
};
function slotCursorDynamic(slot) {
return !slot.isFrozen();
}
/**
* Adds a filter to the Cursor for dynamic Slots.
*
* @returns {module:baja/comp/SlotCursor} itself.
*/
SlotCursor.prototype.dynamic = function () {
this.filter(slotCursorDynamic);
return this;
};
function slotCursorProperties(slot) {
return slot.isProperty();
}
/**
* Adds a filter to the Cursor for Properties.
*
* @returns {module:baja/comp/SlotCursor} itself.
*/
SlotCursor.prototype.properties = function () {
this.filter(slotCursorProperties);
return this;
};
function slotCursorActions(slot) {
return slot.isAction();
}
/**
* Adds a filter to the Cursor for Actions.
*
* @returns {module:baja/comp/SlotCursor} itself.
*/
SlotCursor.prototype.actions = function () {
this.filter(slotCursorActions);
return this;
};
function slotCursorTopics(slot) {
return slot.isTopic();
}
/**
* Adds a filter to the Cursor for Topics.
*
* @returns {module:baja/comp/SlotCursor} itself.
*/
SlotCursor.prototype.topics = function () {
this.filter(slotCursorTopics);
return this;
};
/**
* Adds a filter for Property values that match the TypeSpec via {@link Type#is}.
*
* This method can take a variable number of TypeSpecs. If a variable
* number of TypeSpecs are specified then a slot will be filtered through
* if any of the TypeSpecs match (logical OR).
*
* @see Type#is
*
* @param {Type|String} typeSpec the TypeSpec to test against.
*
* @returns {module:baja/comp/SlotCursor} itself.
*/
SlotCursor.prototype.is = function (typeSpec) {
var typeSpecs = Array.prototype.slice.call(arguments);
const that = this;
this.filter(function (slot) {
if (slot.isProperty()) {
var t = slot.getType(),
a = that.$context && that.$context.get(slot),
i;
for (i = 0; i < typeSpecs.length; ++i) {
if (t.is(typeSpecs[i]) || (a && a.getType().is(typeSpecs[i]))) {
return true;
}
}
}
return false;
});
return this;
};
function slotCursorIsValue(slot) {
return slot.isProperty() && slot.getType().isValue();
}
/**
* Adds a filter for Property values that are of Type `baja:Value`
* ({@link Type#isValue}).
*
* @see Type#isValue
*
* @returns {module:baja/comp/SlotCursor} itself.
*/
SlotCursor.prototype.isValue = function () {
this.filter(slotCursorIsValue);
return this;
};
function slotCursorIsSimple(slot) {
return slot.isProperty() && slot.getType().isSimple();
}
/**
* Adds a filter for Property values that are of Type `baja:Simple`
* ({@link Type#isSimple}).
*
* @see Type#isSimple
*
* @returns {module:baja/comp/SlotCursor} itself.
*/
SlotCursor.prototype.isSimple = function () {
this.filter(slotCursorIsSimple);
return this;
};
function slotCursorIsNumber(slot) {
return slot.isProperty() && slot.getType().isNumber();
}
/**
* Adds a filter for Property values that are of Type `baja:Number`
* ({@link Type#isNumber}).
*
* @see Type#isNumber
*
* @returns {module:baja/comp/SlotCursor} itself.
*/
SlotCursor.prototype.isNumber = function () {
this.filter(slotCursorIsNumber);
return this;
};
function slotCursorIsComplex(slot) {
return slot.isProperty() && slot.getType().isComplex();
}
/**
* Adds a filter for Property values that are of Type `baja:Complex`
* ({@link Type#isComplex}).
*
* @see Type#isComplex
*
* @returns {module:baja/comp/SlotCursor} itself.
*/
SlotCursor.prototype.isComplex = function () {
this.filter(slotCursorIsComplex);
return this;
};
function slotCursorIsComponent(slot) {
return slot.isProperty() && slot.getType().isComponent();
}
/**
* Adds a filter for Property values that are of Type `baja:Component`
* ({@link Type#isComponent}).
*
* @see Type#isComponent
*
* @returns {module:baja/comp/SlotCursor} itself.
*/
SlotCursor.prototype.isComponent = function () {
this.filter(slotCursorIsComponent);
return this;
};
function slotCursorIsStruct(slot) {
return slot.isProperty() && slot.getType().isStruct();
}
/**
* Adds a filter for Property values that are of Type `baja:Struct`
* ({@link Type#isStruct}).
*
* @see Type#isStruct
*
* @returns {module:baja/comp/SlotCursor} itself.
*/
SlotCursor.prototype.isStruct = function () {
this.filter(slotCursorIsStruct);
return this;
};
/**
* Adds a filter for Properties whose Type matches via equals.
*
* This method can take a variable number of TypeSpecs. If a variable number
* of TypeSpecs are specified then a slot will be filtered through if any of
* the TypeSpecs match (logical OR).
*
* @param {Type|String|Array} typeSpec the TypeSpec to test against.
*
* @returns {module:baja/comp/SlotCursor} itself.
*/
SlotCursor.prototype.equalType = function (typeSpec) {
var typeSpecs = Array.prototype.slice.call(arguments),
i;
// Ensure we have the Types we're interested in
for (i = 0; i < typeSpecs.length; ++i) {
typeSpec = typeSpecs[i];
typeSpecs[i] = typeof typeSpec === "string" ? baja.lt(typeSpec) : typeSpec;
}
this.filter(function (slot) {
if (slot.isProperty()) {
var t = slot.getType(),
i;
for (i = 0; i < typeSpecs.length; ++i) {
if (t.equals(typeSpecs[i])) {
return true;
}
}
}
return false;
});
return this;
};
/**
* Adds a filter for Property values that match via equals.
*
* This method can take a variable number of values. If a variable number
* of values are specified then a slot will be filtered through if any of
* the values match (logical OR).
*
* @param value the value to be used for equals.
*
* @returns {module:baja/comp/SlotCursor} itself.
*/
SlotCursor.prototype.equalValue = function (value) {
var values = Array.prototype.slice.call(arguments);
this.filter(function (slot) {
if (slot.isProperty()) {
var v = this.get(slot),
i;
for (i = 0; i < values.length; ++i) {
if (v.equals(values[i])) {
return true;
}
}
}
return false;
});
return this;
};
/**
* Adds a filter for Property values that match via equivalent.
*
* This method can take a variable number of values. If a variable number of
* values are specified then a slot will be filtered through if any of the
* values match (logical OR).
*
* @param value the value to be used for equivalent.
*
* @returns {module:baja/comp/SlotCursor} itself.
*/
SlotCursor.prototype.equivalent = function (value) {
var values = Array.prototype.slice.call(arguments);
this.filter(function (slot) {
if (slot.isProperty()) {
var v = this.get(slot),
i;
for (i = 0; i < values.length; ++i) {
if (v.equivalent(values[i])) {
return true;
}
}
}
return false;
});
return this;
};
/**
* Adds a filter for Slots that match the given Slot name.
*
* @param {String|RegExp} slotName a String or Regular Expression for
* matching Slots via name.
*
* @returns {module:baja/comp/SlotCursor} itself.
*/
SlotCursor.prototype.slotName = function (slotName) {
if (typeof slotName === "string") {
// String Comparison
this.filter(function (slot) {
return slot.getName().equals(slotName.toString());
});
} else {
// RegEx test
this.filter(function (slot) {
return slotName.test(slot.getName());
});
}
return this;
};
/**
* Adds a filter for Slots that match the requested Slot Flags.
*
* @see baja.Flags
*
* @param {Number} flags the Slot flags to be tested for.
*
* @returns {module:baja/comp/SlotCursor} itself.
*/
SlotCursor.prototype.flags = function (flags) {
this.filter(function (slot) {
return (this.getFlags(slot) & flags);
});
return this;
};
return SlotCursor;
});