/**
* Calendar.js
*
* Nokia Web Runtime Service API emulation
* WRT v1.1
*
* Copyright 2009 Nokia Corporation. All rights reserved.
*/
(function(){
var provider = 'Service.Calendar' ,
Interface = 'IDataSource';
/**
* Calendar service
*/
var CalendarService = function(){
this.GetList = __GetList;
this.Add = __Add;
this.Delete = __Delete;
this.Import = __Import;
this.Export = __Export;
this.Cancel = __Cancel;
this.RequestNotification = __RequestNotification;
}
device.implementation.extend(provider, Interface, new CalendarService() );
/******************************************************/
/******************************************************/
/******************************************************/
var context = device.implementation.context,
_t = context._t,
method = '',
result = false,
DBase = null,
default_calendar = 'C:Calendar';
/**
* Calendar: GetList
* @param {Object} criteria
*/
function __GetList(criteria){
if ((result = validator.apply('GetList', arguments)) !== false)
return result;
var returnValue = [],
match = null,
filter = criteria.Filter || null;
DBase = context.getData(provider);
// Type = Calendar
if (!/CalendarEntry/i.test(criteria.Type)){
var cals = [default_calendar];
if (filter && filter.DefaultCalendar === false)
cals = context.keys(DBase)
returnValue = cals;
} else {
// Type = CalendarEntry
var cal = default_calendar;
if (filter && filter.CalendarName)
cal = filter.CalendarName;
if (!(cal in DBase))
return error(device.implementation.ERR_INVALID_SERVICE_ARGUMENT, msg.badCalendar);
// filter by id or LocalId
if (filter && (filter.id || filter.LocalId)) {
var which = filter.id ? 'id' : 'LocalId',
id = filter[which];
for (var i in DBase[cal]) {
if (id == DBase[cal][i][which]) {
returnValue.push(DBase[cal][i]);
}
}
}
// filter by type
else if (filter && filter.Type && !/IncludeAll/i.test(filter.Type)) {
for (var i in DBase[cal]) {
// match on type is case insensitive
if (filter.Type.toLowerCase() == DBase[cal][i].Type.toLowerCase()) {
returnValue.push(DBase[cal][i]);
}
}
}
// unsupported filters
else if (filter
&& (match = context.keys(filter).join().match(/StartRange|EndRange|SearchText/ig)) ) {
context.notify(_t('%s:: GetList : filter %s not implemented in preview').arg(provider, match.join()));
}
// return everything
else {
returnValue = DBase[cal];
}
}
return context.Result(context.Iterator(returnValue));
}
/**
* Calendar: Add
* @param {Object} criteria
*/
function __Add(criteria){
if ((result = validator.apply('Add', arguments)) !== false)
return result;
var Item = criteria.Item || false;
DBase = context.getData(provider);
// Type = Calendar
if (!/CalendarEntry/i.test(criteria.Type)){
if (!Item || !Item.CalendarName)
return error(device.implementation.ERR_INVALID_SERVICE_ARGUMENT, msg.missingCalendar);
var cal = Item.CalendarName;
if (cal in DBase) {
return error(device.implementation.ERR_ENTRY_EXISTS);
}
// @todo: validate calendar name <drive>:<name>
// return error(device.implementation.ERR_INVALID_SERVICE_ARGUMENT, msg.badCalendar);
// create new calendar
device.implementation.loadData(provider, cal, []);
return error(device.implementation.ERR_SUCCESS);
} else {
// Type = CalendarEntry
if (!Item)
return error(device.implementation.ERR_INVALID_SERVICE_ARGUMENT, msg.is_missing, 'Item');
var cal = Item.CalendarName || default_calendar;
// if calendar doesn't exist and it's the default, create it
if (!(cal in DBase) && cal == default_calendar)
device.implementation.loadData(provider, cal, []);
if (!(cal in DBase))
return error(device.implementation.ERR_NOT_FOUND);
// update existing item?
if ('LocalId' in Item) {
if (!Item.LocalId && Item.LocalId !== 0)
return error(device.implementation.ERR_INVALID_SERVICE_ARGUMENT, msg.is_invalid, 'LocalId');
if ('InstanceStartTime' in Item)
context.notify(_t('%s:: Add : InstanceStartTime not implemented in preview.').arg(provider));
// can't update id
delete Item.id;
// search for and update item
var found = false;
for (var i in DBase[cal]) {
var entry = DBase[cal][i];
if (entry.LocalId == Item.LocalId) {
context.extend(entry, Item);
Item.id = entry.id;
found = true;
break;
}
}
if (!found)
return error(device.implementation.ERR_INVALID_SERVICE_ARGUMENT, msg.is_invalid, 'LocalId');
} else {
// add new item
// generate new id and localId
// -- in calendar id's are string!
Item.id = String(context.getUniqueID());
Item.LocalId = String(context.getUniqueID());
DBase[cal].push(Item);
}
}
// return success
return context.Result(Item.id, device.implementation.ERR_SUCCESS);
}
/**
* Calendar: Delete
* @param {Object} criteria
* @param {function} callback function for async call (optional - valid only for CalendarEntry)
*/
function __Delete(criteria, callback){
if ((result = validator.apply('Delete', arguments)) !== false)
return result;
var Data = criteria.Data || false;
if (!Data || typeof Data != 'object')
return error(device.implementation.ERR_INVALID_SERVICE_ARGUMENT, msg.is_invalid, 'Data');
// only sync call supported for Calendar
if (!/CalendarEntry/i.test(criteria.Type) && typeof callback == 'function')
return error(device.implementation.ERR_SERVICE_NOT_SUPPORTED, msg.noAsync);
DBase = context.getData(provider);
var cal = Data.CalendarName || default_calendar;
if (!(cal in DBase))
return error(device.implementation.ERR_NOT_FOUND);
// Type = Calendar
if (!/CalendarEntry/i.test(criteria.Type)) {
// CalendarName is mandatory
if (!Data.CalendarName)
return error(device.implementation.ERR_INVALID_SERVICE_ARGUMENT, msg.is_missing, 'CalendarName');
DBase[cal] = null;
delete DBase[cal];
}
else {
// Type = CalendarEntry
if (!context.keys(Data).join().match(/IdList|LocalIdList|DeleteAll|StartRange|EndRange/ig))
return error(device.implementation.ERR_INVALID_SERVICE_ARGUMENT, msg.is_missing, 'Data');
if (typeof callback == 'function') {
return context.callAsync(this, arguments.callee, criteria, callback);
}
var which = Data.IdList ? 'IdList' : 'LocalIdList',
idList = Data[which] || false;
if (idList) {
// search for and delete items
for (var id in idList) {
id = idList[id];
for (var i in DBase[cal]) {
if (id == DBase[cal][i][which]) {
DBase[cal].splice(i, 1);
}
}
}
}
else if (Data.DeleteAll && Data.DeleteAll === true){
delete DBase[cal];
DBase[cal] = [];
}
if (Data.StartRange || Data.EndRange) {
context.notify(_t('%s:: Delete : StartRange / EndRange not implemented in preview.').arg(provider));
}
}
// return success
return context.ErrorResult(device.implementation.ERR_SUCCESS);
}
/**
* Calendar: Import
* @param {Object} criteria
* @param {function} callback function for async call (optional)
*/
function __Import(criteria, callback){
if ((result = validator.apply('Import', arguments)) !== false)
return result;
var Data = criteria.Data || false;
if (!Data)
return error(device.implementation.ERR_INVALID_SERVICE_ARGUMENT, msg.is_invalid, 'Data');
if (!Data.FileName)
return error(device.implementation.ERR_INVALID_SERVICE_ARGUMENT, msg.is_invalid, 'FileName');
if (!Data.Format)
return error(device.implementation.ERR_INVALID_SERVICE_ARGUMENT, msg.is_invalid, 'Format');
if (typeof callback == 'function') {
return context.callAsync(this, arguments.callee, criteria, callback);
}
context.notify(_t('%s:: Import : not implemented in preview.').arg(provider));
var returnValue = context.Iterator([]);
return context.Result(returnValue, device.implementation.ERR_SUCCESS);
}
/**
* Calendar: Export
* @param {Object} criteria
* @param {function} callback function for async call (optional)
*/
function __Export(criteria, callback){
if ((result = validator.apply('Export', arguments)) !== false)
return result;
var Data = criteria.Data || false;
if (!Data)
return error(device.implementation.ERR_INVALID_SERVICE_ARGUMENT, msg.is_invalid, 'Data');
if (!Data.Format)
return error(device.implementation.ERR_INVALID_SERVICE_ARGUMENT, msg.is_invalid, 'Format');
if (typeof callback == 'function') {
return context.callAsync(this, arguments.callee, criteria, callback);
}
context.notify(_t('%s:: Export : not implemented in preview.').arg(provider));
var returnValue = '';
return context.Result(returnValue, device.implementation.ERR_SUCCESS);
}
/**
* Calendar: RequestNotification
* @param {Object} criteria
* @param {function} callback function for async call
*/
function __RequestNotification(criteria, callback){
if ((result = validator.apply('RequestNotification', arguments)) !== false)
return result;
if (typeof callback != 'function')
return error(device.implementation.ERR_SERVICE_NOT_SUPPORTED, msg.badAsync);
context.notify(_t('%s:: RequestNotification : not implemented in preview.').arg(provider));
var result = context.ErrorResult(device.implementation.ERR_SUCCESS);
result.TransactionID = 0;
return result;
}
/**
* Calendar: Cancel
* @param {Object} criteria
*/
function __Cancel(criteria){
method = 'Cancel';
if (!criteria || !criteria.TransactionID)
return error(device.implementation.ERR_INVALID_SERVICE_ARGUMENT, msg.missingTID);
clearTimeout(criteria.TransactionID);
return context.ErrorResult(device.implementation.ERR_SUCCESS);
}
/*******************************
* helper functions
*******************************/
function error(code, msg /*, args...*/){
var args = ['Calendar',method].concat([].slice.call(arguments,2));
msg = msg ? _t().arg.apply(msg,args) : undefined;
return context.ErrorResult(code, msg);
}
/**
* validate common input arguments
* 'this' is string (object) name of calling function
*
* @param {arguments} arguments of calling function
* @return {Result} Result object if error, false if no error.
*/
function validator() {
method = ''+this;
var failed = false,
criteria = arguments[0] || false;
if (!criteria)
return error(device.implementation.ERR_INVALID_SERVICE_ARGUMENT, msg.badType);
if (typeof criteria != 'object' || typeof criteria.Type == 'undefined')
return error(device.implementation.ERR_INVALID_SERVICE_ARGUMENT, msg.badType);
var TypeRE = /Import|Export|RequestNotification/i.test(method)
? /^CalendarEntry$/i
: /^(Calendar|CalendarEntry)$/i;
if (!TypeRE.test(criteria.Type))
return error(device.implementation.ERR_INVALID_SERVICE_ARGUMENT, msg.badType);
return failed;
}
/**
* error messages
* order of %s args: Service name, method name, parameter name
*/
var msg = {
badType : '%s : %s : Type is invalid',
badCalendar : '%s : %s : CalendarName is invalid',
missingCalendar : '%s : %s : CalendarName is missing',
missingTID : '%s : %s : TransactionID is missing',
badAsync : '%s : %s : Invalid async parameters',
noAsync : '%s : %s : Async not supported',
is_missing : '%s : %s : %s is missing',
is_invalid : '%s : %s : %s is invalid'
};
}) ();