Wikipedia/preview/script/lib/sapi/Calendar.js
changeset 20 918767a9c8d3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Wikipedia/preview/script/lib/sapi/Calendar.js	Tue Mar 09 10:34:58 2010 +0000
@@ -0,0 +1,410 @@
+/**
+ * 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'
+	};
+		
+
+}) ();
+