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