From afc9069b107dd2724d1c394823b0df68e0866504 Mon Sep 17 00:00:00 2001 From: Pawel Kaczmarek Date: Tue, 23 Dec 2014 12:27:39 +0100 Subject: [PATCH] [Calenda][Tizen] Filter - JS implementation [Verification] Below TCT should pass: Calendar_find_with_filter Change-Id: Ic60fc5ab4e81ed16f9a75676f6c266519379e521 Signed-off-by: Pawel Kaczmarek --- src/calendar/js/tizen.calendar.Calendar.js | 62 ++++++++---- src/tizen/tizen_api.js | 148 ++++++++++++++++++++++++++++- 2 files changed, 189 insertions(+), 21 deletions(-) diff --git a/src/calendar/js/tizen.calendar.Calendar.js b/src/calendar/js/tizen.calendar.Calendar.js index 3e2adcf..5255495 100644 --- a/src/calendar/js/tizen.calendar.Calendar.js +++ b/src/calendar/js/tizen.calendar.Calendar.js @@ -247,14 +247,11 @@ Calendar.prototype.addBatch = function() { tmp.push(tmpItem); } - var result = native_.call('Calendar_addBatch', { + native_.call('Calendar_addBatch', { type: this.type, items: tmp }, callback); - if (native_.isFailure(result)) { - throw native_.getErrorObject(result); - } }; Calendar.prototype.update = function() { @@ -355,7 +352,7 @@ Calendar.prototype.updateBatch = function() { tmp.push(tmpItem); } - var result = native_.call('Calendar_updateBatch', { + native_.call('Calendar_updateBatch', { type: this.type, items: tmp, updateAllInstances: (args.has.updateAllInstances) @@ -363,9 +360,6 @@ Calendar.prototype.updateBatch = function() { : true }, callback); - if (native_.isFailure(result)) { - throw native_.getErrorObject(result); - } }; Calendar.prototype.remove = function(id) { @@ -426,14 +420,11 @@ Calendar.prototype.removeBatch = function() { } }; - var result = native_.call('Calendar_removeBatch', { + native_.call('Calendar_removeBatch', { type: this.type, ids: args.ids }, callback); - if (native_.isFailure(result)) { - throw native_.getErrorObject(result); - } }; Calendar.prototype.find = function(successCallback, errorCallback, filter, sortMode) { @@ -463,6 +454,46 @@ Calendar.prototype.find = function(successCallback, errorCallback, filter, sortM nullable: true } ]); + //TODO: Move sorting and filtering to native code + var C = {}; + C.sort = function (arr, sortMode) { + var _getSortProperty = function (obj, props) { + for (var i = 0; i < props.length; ++i) { + if (!obj.hasOwnProperty(props[i])) { + return null; + } + obj = obj[props[i]]; + } + return obj; + }; + + if (sortMode instanceof tizen.SortMode) { + var props = sortMode.attributeName.split('.'); + arr.sort(function (a, b) { + var aValue = _getSortProperty(a, props); + var bValue = _getSortProperty(b, props); + + if (sortMode.order === 'DESC') { + return aValue < bValue; + } + return bValue < aValue; + }); + } + return arr; + }; + + C.filter = function (arr, filter) { + if (T.isNullOrUndefined(arr)) + return arr; + if (filter instanceof tizen.AttributeFilter || + filter instanceof tizen.AttributeRangeFilter || + filter instanceof tizen.CompositeFilter) { + arr = arr.filter(function (element) { + return filter._filter(element); + }); + } + return arr; + }; var calendarType = this.type; @@ -488,17 +519,12 @@ Calendar.prototype.find = function(successCallback, errorCallback, filter, sortM } }; - - var result = native_.call('Calendar_find', { + native_.call('Calendar_find', { calendarId: this.id, filter: args.filter, sortMode: args.sortMode }, callback); - if (native_.isFailure(result)) { - throw native_.getErrorObject(result); - } - }; var _listeners = {}; diff --git a/src/tizen/tizen_api.js b/src/tizen/tizen_api.js index 94dc559..f7f195d 100644 --- a/src/tizen/tizen_api.js +++ b/src/tizen/tizen_api.js @@ -217,6 +217,30 @@ function is_tizen_filter(f) { (f instanceof tizen.CompositeFilter); } +//Extract property by string +function _extractProperty(obj, attributeName) { + var props = attributeName.split('.'); + for (var i = 0; i < props.length; ++i) { + if (obj instanceof Array) { + var ret = []; + for (var j = 0; j < obj.length; ++j) + { + ret.push(_extractProperty(obj[j], props.slice(i).join('.'))); + } + return ret; + } + if (!obj.hasOwnProperty(props[i])) { + if (i === props.length - 1) { + throw new tizen.WebAPIException('InvalidValuesError', 'Property "' + attributeName + + '" is not valid'); + } + return null; + } + obj = obj[props[i]]; + } + return obj; +} + /** * This is a common interface used by different types of object filters. */ @@ -226,7 +250,7 @@ exports.AbstractFilter = function() {}; * Represents a set of filters. */ exports.AttributeFilter = function(attrName, matchFlag, matchValue) { - if (this && this.constructor == exports.AttributeFilter && + if (this && this.constructor === exports.AttributeFilter && (typeof(attrName) === 'string' || attrname instanceof String) && matchFlag && matchFlag in FilterMatchFlag) { Object.defineProperties(this, { @@ -247,6 +271,49 @@ exports.AttributeFilter = function(attrName, matchFlag, matchValue) { } }; exports.AttributeFilter.prototype = new exports.AbstractFilter(); + +//TODO: Move filtering to native code +exports.AttributeFilter.prototype._filter = function (element) { + var elemValue = _extractProperty(element, this.attributeName); + + if (!(elemValue instanceof Array)) { + elemValue = [elemValue]; + } + + var ret = false; + for (var i = 0; i < elemValue.length; ++i) { + var elemValueStr = String(elemValue[i]); + var elemValueStrU = elemValueStr.toUpperCase(); + var matchValueStr = String(this.matchValue); + var matchValueStrU = matchValueStr.toUpperCase(); + + switch (this.matchFlag) { + case "EXACTLY": + ret = elemValue[i] === this.matchValue; + break; + case "FULLSTRING": + ret = elemValueStrU === matchValueStrU; + break; + case "CONTAINS": + ret = elemValueStrU.indexOf(matchValueStrU) > -1; + break; + case "STARTSWITH": + ret = elemValueStrU.indexOf(matchValueStrU) === 0; + break; + case "ENDSWITH": + ret = elemValueStrU.lastIndexOf(matchValueStrU) + + matchValueStrU.length === elemValueStrU.length; + break; + case "EXISTS": + ret = elemValue[i] !== undefined; + break; + } + if (ret) { + return ret; + } + } + return ret; +}; exports.AttributeFilter.prototype.constructor = exports.AttributeFilter; /** @@ -254,7 +321,7 @@ exports.AttributeFilter.prototype.constructor = exports.AttributeFilter; * within a particular range. */ exports.AttributeRangeFilter = function(attrName, start, end) { - if (!this || this.constructor != exports.AttributeRangeFilter || + if (!this || this.constructor !== exports.AttributeRangeFilter || !(typeof(attrName) === 'string' || attrname instanceof String)) { throw new exports.WebAPIException(exports.WebAPIException.TYPE_MISMATCH_ERR); } @@ -268,14 +335,65 @@ exports.AttributeRangeFilter = function(attrName, start, end) { 'endValue': { writable: true, enumerable: true, value: end === undefined ? null : end } }); }; + exports.AttributeRangeFilter.prototype = new exports.AbstractFilter(); + +//TODO: Move filtering to native code +exports.AttributeRangeFilter.prototype._filter = function (element) { + var elemValue = _extractProperty(element, this.attributeName); + + if (!(elemValue instanceof Array)) { + elemValue = [elemValue]; + } + + for (var i = 0; i < elemValue.length; ++i) { + var value = elemValue[i]; + + if ((this.initialValue !== undefined && this.initialValue !== null) && + (this.endValue !== undefined && this.endValue !== null)) { + if (value instanceof tizen.TZDate) { + if (this.initialValue.earlierThan(value) && this.endValue.laterThan(value)) { + return true; + } + } else { + if (this.initialValue <= value && this.endValue > value) { + return true; + } + } + } else if ((this.initialValue !== undefined && this.initialValue !== null) && + (this.endValue === undefined || this.endValue === null)) { + if (value instanceof tizen.TZDate) { + if (this.initialValue.earlierThan(value)) { + return true; + } + } else { + if (this.initialValue <= value) { + return true; + } + } + } else if ((this.initialValue === undefined || this.initialValue === null) && + (this.endValue !== undefined && this.endValue !== null)) { + if (value instanceof tizen.TZDate) { + if (this.endValue.laterThan(value)) { + return true; + } + } else { + if (this.endValue > value) { + return true; + } + } + } + } + return false; +}; + exports.AttributeRangeFilter.prototype.constructor = exports.AttributeRangeFilter; /** * Represents a set of filters. */ exports.CompositeFilter = function(type, filters) { - if (!this || this.constructor != exports.CompositeFilter || + if (!this || this.constructor !== exports.CompositeFilter || !(type in CompositeFilterType) || filters && !(filters instanceof Array)) { throw new exports.WebAPIException(exports.WebAPIException.TYPE_MISMATCH_ERR); @@ -290,7 +408,31 @@ exports.CompositeFilter = function(type, filters) { } }); }; + exports.CompositeFilter.prototype = new exports.AbstractFilter(); + +//TODO: Move filtering to native code +exports.CompositeFilter.prototype._filter = function (element) { + var filters = this.filters; + if (this.type === "UNION") { + for (var i = 0; i < filters.length; ++i) { + if (filters[i]._filter(element)) { + return true; + } + } + return false; + } else if (this.type === "INTERSECTION") { + if (filters.length === 0) + return false; + for (var i = 0; i < filters.length; ++i) { + if (!filters[i]._filter(element)) { + return false; + } + } + return true; + } +}; + exports.CompositeFilter.prototype.constructor = exports.CompositeFilter; /** -- 2.7.4