/*jslint indent: 2, maxlen: 80, sloppy: true, nomen: true */ /*global Query: true, inherits: true, query_class_dict: true, _export: true, convertStringToRegExp, RSVP */ var checkKeySchema = function (key_schema) { var prop; if (key_schema !== undefined) { if (typeof key_schema !== 'object') { throw new TypeError("SimpleQuery().create(): " + "key_schema is not of type 'object'"); } // key_set is mandatory if (key_schema.key_set === undefined) { throw new TypeError("SimpleQuery().create(): " + "key_schema has no 'key_set' property"); } for (prop in key_schema) { if (key_schema.hasOwnProperty(prop)) { switch (prop) { case 'key_set': case 'cast_lookup': case 'match_lookup': break; default: throw new TypeError("SimpleQuery().create(): " + "key_schema has unknown property '" + prop + "'"); } } } } }; /** * The SimpleQuery inherits from Query, and compares one metadata value * * @class SimpleQuery * @extends Query * @param {Object} [spec={}] The specifications * @param {String} [spec.operator="="] The compare method to use * @param {String} spec.key The metadata key * @param {String} spec.value The value of the metadata to compare */ function SimpleQuery(spec, key_schema) { Query.call(this); checkKeySchema(key_schema); this._key_schema = key_schema || {}; /** * Operator to use to compare object values * * @attribute operator * @type String * @default "=" * @optional */ this.operator = spec.operator || "="; /** * Key of the object which refers to the value to compare * * @attribute key * @type String */ this.key = spec.key; /** * Value is used to do the comparison with the object value * * @attribute value * @type String */ this.value = spec.value; } inherits(SimpleQuery, Query); var checkKey = function (key) { var prop; if (key.read_from === undefined) { throw new TypeError("Custom key is missing the read_from property"); } for (prop in key) { if (key.hasOwnProperty(prop)) { switch (prop) { case 'read_from': case 'cast_to': case 'equal_match': break; default: throw new TypeError("Custom key has unknown property '" + prop + "'"); } } } }; /** * #crossLink "Query/match:method" */ SimpleQuery.prototype.match = function (item, wildcard_character) { var object_value = null, equal_match = null, cast_to = null, matchMethod = null, value = null, key = this.key; matchMethod = this[this.operator]; if (this._key_schema.key_set && this._key_schema.key_set[key] !== undefined) { key = this._key_schema.key_set[key]; } if (typeof key === 'object') { checkKey(key); object_value = item[key.read_from]; equal_match = key.equal_match; // equal_match can be a string if (typeof equal_match === 'string') { // XXX raise error if equal_match not in match_lookup equal_match = this._key_schema.match_lookup[equal_match]; } // equal_match overrides the default '=' operator if (equal_match !== undefined) { matchMethod = (this.operator === '=') ? equal_match : matchMethod; } value = this.value; cast_to = key.cast_to; if (cast_to) { // cast_to can be a string if (typeof cast_to === 'string') { // XXX raise error if cast_to not in cast_lookup cast_to = this._key_schema.cast_lookup[cast_to]; } value = cast_to(value); object_value = cast_to(object_value); } } else { object_value = item[key]; value = this.value; } if (object_value === undefined || value === undefined) { return RSVP.resolve(false); } return matchMethod(object_value, value, wildcard_character); }; /** * #crossLink "Query/toString:method" */ SimpleQuery.prototype.toString = function () { return (this.key ? this.key + ": " : "") + (this.operator || "=") + ' "' + this.value + '"'; }; /** * #crossLink "Query/serialized:method" */ SimpleQuery.prototype.serialized = function () { return { "type": "simple", "operator": this.operator, "key": this.key, "value": this.value }; }; /** * Comparison operator, test if this query value matches the item value * * @method = * @param {String} object_value The value to compare * @param {String} comparison_value The comparison value * @param {String} wildcard_character The wildcard_character * @return {Boolean} true if match, false otherwise */ SimpleQuery.prototype["="] = function (object_value, comparison_value, wildcard_character) { var value, i; if (!Array.isArray(object_value)) { object_value = [object_value]; } for (i = 0; i < object_value.length; i += 1) { value = object_value[i]; if (typeof value === 'object' && value.hasOwnProperty('content')) { value = value.content; } if (value.cmp !== undefined) { return RSVP.resolve(value.cmp(comparison_value, wildcard_character) === 0); } if ( convertStringToRegExp( comparison_value.toString(), wildcard_character ).test(value.toString()) ) { return RSVP.resolve(true); } } return RSVP.resolve(false); }; /** * Comparison operator, test if this query value does not match the item value * * @method != * @param {String} object_value The value to compare * @param {String} comparison_value The comparison value * @param {String} wildcard_character The wildcard_character * @return {Boolean} true if not match, false otherwise */ SimpleQuery.prototype["!="] = function (object_value, comparison_value, wildcard_character) { var value, i; if (!Array.isArray(object_value)) { object_value = [object_value]; } for (i = 0; i < object_value.length; i += 1) { value = object_value[i]; if (typeof value === 'object' && value.hasOwnProperty('content')) { value = value.content; } if (value.cmp !== undefined) { return RSVP.resolve(value.cmp(comparison_value, wildcard_character) !== 0); } if ( convertStringToRegExp( comparison_value.toString(), wildcard_character ).test(value.toString()) ) { return RSVP.resolve(false); } } return RSVP.resolve(true); }; /** * Comparison operator, test if this query value is lower than the item value * * @method < * @param {Number, String} object_value The value to compare * @param {Number, String} comparison_value The comparison value * @return {Boolean} true if lower, false otherwise */ SimpleQuery.prototype["<"] = function (object_value, comparison_value) { var value; if (!Array.isArray(object_value)) { object_value = [object_value]; } value = object_value[0]; if (typeof value === 'object' && value.hasOwnProperty('content')) { value = value.content; } if (value.cmp !== undefined) { return RSVP.resolve(value.cmp(comparison_value) < 0); } return RSVP.resolve(value < comparison_value); }; /** * Comparison operator, test if this query value is equal or lower than the * item value * * @method <= * @param {Number, String} object_value The value to compare * @param {Number, String} comparison_value The comparison value * @return {Boolean} true if equal or lower, false otherwise */ SimpleQuery.prototype["<="] = function (object_value, comparison_value) { var value; if (!Array.isArray(object_value)) { object_value = [object_value]; } value = object_value[0]; if (typeof value === 'object' && value.hasOwnProperty('content')) { value = value.content; } if (value.cmp !== undefined) { return RSVP.resolve(value.cmp(comparison_value) <= 0); } return RSVP.resolve(value <= comparison_value); }; /** * Comparison operator, test if this query value is greater than the item * value * * @method > * @param {Number, String} object_value The value to compare * @param {Number, String} comparison_value The comparison value * @return {Boolean} true if greater, false otherwise */ SimpleQuery.prototype[">"] = function (object_value, comparison_value) { var value; if (!Array.isArray(object_value)) { object_value = [object_value]; } value = object_value[0]; if (typeof value === 'object' && value.hasOwnProperty('content')) { value = value.content; } if (value.cmp !== undefined) { return RSVP.resolve(value.cmp(comparison_value) > 0); } return RSVP.resolve(value > comparison_value); }; /** * Comparison operator, test if this query value is equal or greater than the * item value * * @method >= * @param {Number, String} object_value The value to compare * @param {Number, String} comparison_value The comparison value * @return {Boolean} true if equal or greater, false otherwise */ SimpleQuery.prototype[">="] = function (object_value, comparison_value) { var value; if (!Array.isArray(object_value)) { object_value = [object_value]; } value = object_value[0]; if (typeof value === 'object' && value.hasOwnProperty('content')) { value = value.content; } if (value.cmp !== undefined) { return RSVP.resolve(value.cmp(comparison_value) >= 0); } return RSVP.resolve(value >= comparison_value); }; query_class_dict.simple = SimpleQuery; _export("SimpleQuery", SimpleQuery);