Wikipedia/preview/script/lib/sapi/Calendar.js
changeset 20 918767a9c8d3
equal deleted inserted replaced
19:f3521a11d878 20:918767a9c8d3
       
     1 /**
       
     2  * Calendar.js
       
     3  * 
       
     4  * Nokia Web Runtime Service API emulation 
       
     5  * WRT v1.1
       
     6  * 
       
     7  * Copyright 2009 Nokia Corporation. All rights reserved.
       
     8 */
       
     9 
       
    10  
       
    11 (function(){
       
    12 	
       
    13 	var provider = 'Service.Calendar' ,
       
    14 		Interface = 'IDataSource';
       
    15 
       
    16 	/**
       
    17 	 * Calendar service
       
    18 	 */
       
    19 	var CalendarService = function(){
       
    20 		this.GetList 	= __GetList;
       
    21 		this.Add 		= __Add;
       
    22 		this.Delete 	= __Delete;
       
    23 		this.Import 	= __Import;
       
    24 		this.Export 	= __Export;
       
    25 		this.Cancel 	= __Cancel;
       
    26 		this.RequestNotification = __RequestNotification;
       
    27 	}
       
    28 
       
    29 	device.implementation.extend(provider, Interface, new CalendarService() );
       
    30 
       
    31 
       
    32 	/******************************************************/	
       
    33 	/******************************************************/	
       
    34 	/******************************************************/	
       
    35 
       
    36 	var	context = device.implementation.context,
       
    37 		_t = context._t,
       
    38 		method = '',
       
    39 		result = false,
       
    40 		DBase = null,
       
    41 		default_calendar = 'C:Calendar';
       
    42 	
       
    43 	/**
       
    44 	 * Calendar: GetList
       
    45 	 * @param {Object} criteria
       
    46 	 */
       
    47 	function __GetList(criteria){
       
    48 		if ((result = validator.apply('GetList', arguments)) !== false)
       
    49 			return result; 
       
    50 
       
    51 		var returnValue = [], 
       
    52 			match = null,
       
    53 			filter = criteria.Filter || null;
       
    54  
       
    55 		DBase = context.getData(provider);
       
    56 
       
    57 		// Type = Calendar
       
    58 		if (!/CalendarEntry/i.test(criteria.Type)){
       
    59 			var cals = [default_calendar];
       
    60 			if (filter && filter.DefaultCalendar === false)
       
    61 				cals = context.keys(DBase)
       
    62 
       
    63 			returnValue = cals;
       
    64 
       
    65 		} else {
       
    66 		// Type = CalendarEntry
       
    67 			var cal = default_calendar;
       
    68 			if (filter && filter.CalendarName)
       
    69 				cal = filter.CalendarName;
       
    70 			
       
    71 			if (!(cal in DBase))
       
    72 				return error(device.implementation.ERR_INVALID_SERVICE_ARGUMENT, msg.badCalendar);
       
    73 
       
    74 			// filter by id or LocalId
       
    75 			if (filter && (filter.id || filter.LocalId)) {
       
    76 				var which = filter.id ? 'id' : 'LocalId', 
       
    77 					id = filter[which];
       
    78 					
       
    79 				for (var i in DBase[cal]) {
       
    80 					if (id == DBase[cal][i][which]) {
       
    81 						returnValue.push(DBase[cal][i]);
       
    82 					}
       
    83 				}
       
    84 			}
       
    85 			// filter by type 
       
    86 			else if (filter && filter.Type && !/IncludeAll/i.test(filter.Type)) {
       
    87 				for (var i in DBase[cal]) {
       
    88 					// match on type is case insensitive
       
    89 					if (filter.Type.toLowerCase() == DBase[cal][i].Type.toLowerCase()) {
       
    90 						returnValue.push(DBase[cal][i]);
       
    91 					}
       
    92 				}
       
    93 			}
       
    94 			// unsupported filters 
       
    95 			else if (filter 
       
    96 				&& (match = context.keys(filter).join().match(/StartRange|EndRange|SearchText/ig)) ) {
       
    97 				context.notify(_t('%s:: GetList : filter %s not implemented in preview').arg(provider, match.join()));
       
    98 			}
       
    99 			// return everything 
       
   100 			else {
       
   101 				returnValue = DBase[cal];
       
   102 			}
       
   103 		}
       
   104 
       
   105 		return context.Result(context.Iterator(returnValue));
       
   106 	}
       
   107 			
       
   108 	/**
       
   109 	 * Calendar: Add
       
   110 	 * @param {Object} criteria
       
   111 	 */
       
   112 	function __Add(criteria){
       
   113 		if ((result = validator.apply('Add', arguments)) !== false)
       
   114 			return result; 
       
   115 		
       
   116 		var Item = criteria.Item || false; 
       
   117 		
       
   118 		DBase = context.getData(provider);
       
   119 
       
   120 		// Type = Calendar
       
   121 		if (!/CalendarEntry/i.test(criteria.Type)){
       
   122 
       
   123 			if (!Item || !Item.CalendarName)
       
   124 				return error(device.implementation.ERR_INVALID_SERVICE_ARGUMENT, msg.missingCalendar);
       
   125 				
       
   126 			var cal = Item.CalendarName;
       
   127 			if (cal in DBase) {
       
   128 				return error(device.implementation.ERR_ENTRY_EXISTS);
       
   129 			}
       
   130 
       
   131 			// @todo: validate calendar name <drive>:<name>
       
   132 			// return error(device.implementation.ERR_INVALID_SERVICE_ARGUMENT, msg.badCalendar);
       
   133 			
       
   134 			// create new calendar
       
   135 			device.implementation.loadData(provider, cal, []);
       
   136 			return error(device.implementation.ERR_SUCCESS);
       
   137 
       
   138 		} else {
       
   139 		// Type = CalendarEntry
       
   140 
       
   141 			if (!Item)
       
   142 				return error(device.implementation.ERR_INVALID_SERVICE_ARGUMENT, msg.is_missing, 'Item');
       
   143 				
       
   144 			var cal = Item.CalendarName || default_calendar;
       
   145 
       
   146 			// if calendar doesn't exist and it's the default, create it
       
   147 			if (!(cal in DBase) && cal == default_calendar)
       
   148 				device.implementation.loadData(provider, cal, []);
       
   149 			
       
   150 			if (!(cal in DBase))
       
   151 				return error(device.implementation.ERR_NOT_FOUND);
       
   152 
       
   153 			// update existing item?
       
   154 			if ('LocalId' in Item) {
       
   155 				
       
   156 				if (!Item.LocalId && Item.LocalId !== 0)
       
   157 					return error(device.implementation.ERR_INVALID_SERVICE_ARGUMENT, msg.is_invalid, 'LocalId');
       
   158 				
       
   159 				if ('InstanceStartTime' in Item)
       
   160 					context.notify(_t('%s:: Add : InstanceStartTime not implemented in preview.').arg(provider));
       
   161 
       
   162 				// can't update id
       
   163 				delete Item.id;
       
   164 				
       
   165 				//  search for and update item
       
   166 				var found = false;
       
   167 				for (var i in DBase[cal]) {
       
   168 					var entry = DBase[cal][i];
       
   169 					if (entry.LocalId == Item.LocalId) {
       
   170 						context.extend(entry, Item);
       
   171 						Item.id = entry.id;
       
   172 						found = true;
       
   173 						break;
       
   174 					}
       
   175 				}
       
   176 				if (!found)
       
   177 					return error(device.implementation.ERR_INVALID_SERVICE_ARGUMENT, msg.is_invalid, 'LocalId');
       
   178 
       
   179 			} else {
       
   180 			// add new item
       
   181 				// generate new id and localId 
       
   182 				// -- in calendar id's are string!
       
   183 				Item.id = String(context.getUniqueID());
       
   184 				Item.LocalId = String(context.getUniqueID());
       
   185 				DBase[cal].push(Item);
       
   186 			} 
       
   187 		} 
       
   188 		// return success
       
   189 		return context.Result(Item.id, device.implementation.ERR_SUCCESS);
       
   190 	}
       
   191 			
       
   192 
       
   193 	/**
       
   194 	 * Calendar: Delete
       
   195 	 * @param {Object} criteria
       
   196 	 * @param {function} callback function for async call (optional - valid only for CalendarEntry)
       
   197 	 */
       
   198 	function __Delete(criteria, callback){
       
   199 		
       
   200 		if ((result = validator.apply('Delete', arguments)) !== false)
       
   201 			return result; 
       
   202 
       
   203 		var Data = criteria.Data || false; 
       
   204 		if (!Data || typeof Data != 'object')
       
   205 			return error(device.implementation.ERR_INVALID_SERVICE_ARGUMENT, msg.is_invalid, 'Data');
       
   206 		
       
   207 		// only sync call supported for Calendar
       
   208 		if (!/CalendarEntry/i.test(criteria.Type) && typeof callback == 'function')
       
   209 			return error(device.implementation.ERR_SERVICE_NOT_SUPPORTED, msg.noAsync);
       
   210 
       
   211 		DBase = context.getData(provider);
       
   212 		var cal = Data.CalendarName || default_calendar;			
       
   213 		if (!(cal in DBase))
       
   214 			return error(device.implementation.ERR_NOT_FOUND);
       
   215 		
       
   216 		// Type = Calendar
       
   217 		if (!/CalendarEntry/i.test(criteria.Type)) {
       
   218 			// CalendarName is mandatory
       
   219 			if (!Data.CalendarName)
       
   220 				return error(device.implementation.ERR_INVALID_SERVICE_ARGUMENT, msg.is_missing, 'CalendarName');
       
   221 						
       
   222 			DBase[cal] = null;
       
   223 			delete DBase[cal];
       
   224 		}
       
   225 		else {
       
   226 		// Type = CalendarEntry
       
   227 
       
   228 			if (!context.keys(Data).join().match(/IdList|LocalIdList|DeleteAll|StartRange|EndRange/ig))
       
   229 				return error(device.implementation.ERR_INVALID_SERVICE_ARGUMENT, msg.is_missing, 'Data');
       
   230 
       
   231 			if (typeof callback == 'function') {
       
   232 				return context.callAsync(this, arguments.callee, criteria, callback);
       
   233 			}
       
   234 
       
   235 			var which = Data.IdList ? 'IdList' : 'LocalIdList',
       
   236 				idList = Data[which] || false;
       
   237 				
       
   238 			if (idList) {
       
   239 				//  search for and delete items
       
   240 				for (var id in idList) {
       
   241 					id = idList[id];
       
   242 					for (var i in DBase[cal]) {
       
   243 						if (id == DBase[cal][i][which]) {
       
   244 							DBase[cal].splice(i, 1);
       
   245 						}
       
   246 					}
       
   247 				}
       
   248 			}
       
   249 			else if (Data.DeleteAll && Data.DeleteAll === true){
       
   250 				delete DBase[cal];
       
   251 				DBase[cal] = [];
       
   252 			}
       
   253 
       
   254 			if (Data.StartRange || Data.EndRange) {
       
   255 				context.notify(_t('%s:: Delete : StartRange / EndRange not implemented in preview.').arg(provider));
       
   256 			}
       
   257 		}
       
   258 		// return success
       
   259 		return context.ErrorResult(device.implementation.ERR_SUCCESS);				
       
   260 	}
       
   261 			
       
   262 
       
   263 	/**
       
   264 	 * Calendar: Import
       
   265 	 * @param {Object} criteria
       
   266 	 * @param {function} callback function for async call (optional)
       
   267 	 */
       
   268 	function __Import(criteria, callback){
       
   269 
       
   270 		if ((result = validator.apply('Import', arguments)) !== false)
       
   271 			return result; 
       
   272 
       
   273 		var Data = criteria.Data || false; 
       
   274 		if (!Data)
       
   275 			return error(device.implementation.ERR_INVALID_SERVICE_ARGUMENT, msg.is_invalid, 'Data');
       
   276 		
       
   277 		if (!Data.FileName)
       
   278 			return error(device.implementation.ERR_INVALID_SERVICE_ARGUMENT, msg.is_invalid, 'FileName');
       
   279 
       
   280 		if (!Data.Format)
       
   281 			return error(device.implementation.ERR_INVALID_SERVICE_ARGUMENT, msg.is_invalid, 'Format');
       
   282 
       
   283 		if (typeof callback == 'function') {
       
   284 			return context.callAsync(this, arguments.callee, criteria, callback);
       
   285 		}
       
   286 
       
   287 		context.notify(_t('%s:: Import : not implemented in preview.').arg(provider));
       
   288 		var returnValue = context.Iterator([]);
       
   289 		return context.Result(returnValue, device.implementation.ERR_SUCCESS);		
       
   290 	}
       
   291 			
       
   292 
       
   293 	/**
       
   294 	 * Calendar: Export
       
   295 	 * @param {Object} criteria
       
   296 	 * @param {function} callback function for async call (optional)
       
   297 	 */
       
   298 	function __Export(criteria, callback){
       
   299 
       
   300 		if ((result = validator.apply('Export', arguments)) !== false)
       
   301 			return result; 
       
   302 
       
   303 		var Data = criteria.Data || false; 
       
   304 		if (!Data)
       
   305 			return error(device.implementation.ERR_INVALID_SERVICE_ARGUMENT, msg.is_invalid, 'Data');
       
   306 
       
   307 		if (!Data.Format)
       
   308 			return error(device.implementation.ERR_INVALID_SERVICE_ARGUMENT, msg.is_invalid, 'Format');
       
   309 
       
   310 		if (typeof callback == 'function') {
       
   311 			return context.callAsync(this, arguments.callee, criteria, callback);
       
   312 		}
       
   313 		context.notify(_t('%s:: Export : not implemented in preview.').arg(provider));
       
   314 		var returnValue = '';
       
   315 		return context.Result(returnValue, device.implementation.ERR_SUCCESS);		
       
   316 	}
       
   317 			
       
   318 
       
   319 	/**
       
   320 	 * Calendar: RequestNotification
       
   321 	 * @param {Object} criteria
       
   322 	 * @param {function} callback function for async call 
       
   323 	 */
       
   324 	function __RequestNotification(criteria, callback){
       
   325 
       
   326 		if ((result = validator.apply('RequestNotification', arguments)) !== false)
       
   327 			return result; 
       
   328 
       
   329 		if (typeof callback != 'function')
       
   330 			return error(device.implementation.ERR_SERVICE_NOT_SUPPORTED, msg.badAsync);
       
   331 
       
   332 		context.notify(_t('%s:: RequestNotification : not implemented in preview.').arg(provider));
       
   333 		var result = context.ErrorResult(device.implementation.ERR_SUCCESS);
       
   334 		result.TransactionID = 0;
       
   335 		return result;		
       
   336 	}
       
   337 			
       
   338 
       
   339 	/**
       
   340 	 * Calendar: Cancel
       
   341 	 * @param {Object} criteria
       
   342 	 */
       
   343 	function __Cancel(criteria){
       
   344 		method = 'Cancel';
       
   345 		if (!criteria || !criteria.TransactionID)
       
   346 			return error(device.implementation.ERR_INVALID_SERVICE_ARGUMENT, msg.missingTID);
       
   347 		
       
   348 		clearTimeout(criteria.TransactionID);
       
   349 		return context.ErrorResult(device.implementation.ERR_SUCCESS);
       
   350 	}
       
   351 
       
   352 
       
   353 	
       
   354 	/*******************************
       
   355 	 * helper functions
       
   356 	 *******************************/
       
   357 	
       
   358 	function error(code, msg /*, args...*/){
       
   359 
       
   360 		var args = ['Calendar',method].concat([].slice.call(arguments,2));
       
   361 		msg = msg ? _t().arg.apply(msg,args) : undefined;
       
   362 		return context.ErrorResult(code, msg);
       
   363 	}
       
   364 
       
   365 	/**
       
   366 	 * validate common input arguments
       
   367 	 * 'this' is string (object) name of calling function
       
   368 	 * 
       
   369 	 * @param {arguments} arguments of calling function
       
   370 	 * @return {Result} Result object if error, false if no error.
       
   371 	 */
       
   372 	function validator() {
       
   373 		method = ''+this;
       
   374 		var	failed = false,
       
   375 			criteria = arguments[0] || false;
       
   376 			
       
   377 		if (!criteria)
       
   378 			return error(device.implementation.ERR_INVALID_SERVICE_ARGUMENT, msg.badType);
       
   379 			
       
   380 		if (typeof criteria != 'object' || typeof criteria.Type == 'undefined')
       
   381 			return error(device.implementation.ERR_INVALID_SERVICE_ARGUMENT, msg.badType);
       
   382 		
       
   383 		var TypeRE = /Import|Export|RequestNotification/i.test(method)
       
   384 			? /^CalendarEntry$/i
       
   385 			: /^(Calendar|CalendarEntry)$/i;
       
   386 		 
       
   387 		if (!TypeRE.test(criteria.Type)) 
       
   388 			return error(device.implementation.ERR_INVALID_SERVICE_ARGUMENT, msg.badType);
       
   389 		
       
   390 		return failed;
       
   391 	}
       
   392 
       
   393 	/** 
       
   394 	 * error messages
       
   395 	 * order of %s args: Service name, method name, parameter name 
       
   396 	 */
       
   397 	var msg = {
       
   398 		badType			: '%s : %s : Type is invalid',
       
   399 		badCalendar		: '%s : %s : CalendarName is invalid',
       
   400 		missingCalendar	: '%s : %s : CalendarName is missing',
       
   401 		missingTID 		: '%s : %s : TransactionID is missing',
       
   402 		badAsync		: '%s : %s : Invalid async parameters',
       
   403 		noAsync			: '%s : %s : Async not supported',
       
   404 		is_missing		: '%s : %s : %s is missing',
       
   405 		is_invalid		: '%s : %s : %s is invalid'
       
   406 	};
       
   407 		
       
   408 
       
   409 }) ();
       
   410