/*
* Copyright (c) 2007 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of the License "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description:  Defination of class CCalendarInterface
*
*/

// Namepace: com.nokia.device.service

var __device_landmarks_service_entry = {
    "name": null,
    "version": null,
    "proto": __device_landmarks,
    "descriptor": __device_landmarks_descriptor,
    "providers": [{
        "descriptor": __sp_landmarks_descriptor,
        "instance": __sp_landmarks_instance
    }]
};

// Private location prototype: called from service factory
function __device_landmarks(provider){
    //Private properties
    this.provider = provider;
    //Read-only properties
    this.interfaceName = provider.descriptor.interfaceName;
    this.version = provider.descriptor.version;
    //Core methods
    this.startEditor = __device_landmarks_startEditor;
    //Extended methods
    this.getCategories = __device_landmarks_getCategories;
    this.getLandmarks = __device_landmarks_getLandmarks;
    this.addCategory = __device_landmarks_add_category;
    this.updateCategory = __device_landmarks_update_category;
    this.updateLandmark = __device_landmarks_update_landmark;
    this.addLandmark = __device_landmarks_add_landmark;
    this.deleteCategory = __device_landmarks_delete_category;
    this.deleteLandmark = __device_landmarks_delete_landmark;
    this.importLandmarks = __device_landmarks_import_landmarks;
    this.exportLandmarks = __device_landmarks_export_landmarks;
    this.organizeLandmarks = __device_landmarks_organize_landmarks;
    ;
    this.cancel = __device_landmarks_cancel;
}

function __device_landmarks_descriptor(provider){
    this.interfaceName = provider.interfaceName;
    this.version = provider.version;
}

function __device_landmarks_startEditor(callback, entry){
    this.provider.startEditor(callback, entry);
}

function __device_landmarks_getCategories(callback, name, errorcb){
    return this.provider.getCategories(callback, name, errorcb);
}


function __device_landmarks_getLandmarks(callback, match, errcb){
    return this.provider.getLandmarks(callback, match, errcb);
}

function __device_landmarks_add_category(callback, categoryItem, ErrorCallback){
    return this.provider.addCategory(callback, categoryItem, ErrorCallback);
}


function __device_landmarks_add_landmark(callback, landmarkItem, ErrorCallback){
    return this.provider.addLandmark(callback, landmarkItem, ErrorCallback);
}

function __device_landmarks_delete_category(callback, categoryId, ErrorCallback){
    return this.provider.deleteCategory(callback, categoryId, ErrorCallback);
}

function __device_landmarks_delete_landmark(callback, landmarkId, ErrorCallback){
    return this.provider.deleteLandmark(callback, landmarkId, ErrorCallback);
}

function __device_landmarks_update_landmark(callback, landmarkItem, ErrorCallback){
    return this.provider.updateLandmark(callback, landmarkItem, ErrorCallback);
}

function __device_landmarks_update_category(callback, categoryItem, ErrorCallback){
    return this.provider.updateCategory(callback, categoryItem, ErrorCallback);
}

function __device_landmarks_import_landmarks(callback, sourceFileUri, mimetype, ErrorCallback){
    return this.provider.importLandmarks(callback, sourceFileUri, mimetype, ErrorCallback);
}

function __device_landmarks_export_landmarks(callback, landmarkIdList, destFileUri, mimetype, ErrorCallback){
    return this.provider.exportLandmarks(callback, landmarkIdList, destFileUri, mimetype, ErrorCallback);
}

function __device_landmarks_organize_landmarks(callback, landmarkIdList, categoryId, associate, ErrorCallback){
    return this.provider.organizeLandmarks(callback, landmarkIdList, categoryId, associate, ErrorCallback);
}

function __device_landmarks_cancel(transactionId){
    return this.provider.cancel(transactionId);
}




/*
 Copyright � 2009 Nokia. All rights reserved.
 Code licensed under the BSD License:
 Software License Agreement (BSD License) Copyright � 2009 Nokia.
 All rights reserved.
 Redistribution and use of this software in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
 Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
 Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
 Neither the name of Nokia Corporation. nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission of Nokia Corporation.
 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 version: 1.0
 */
//utillity function for converting error code from PS to CJSE codes
//this gets used in communicating errors via error callback
var err_missing_argument = 1003;
var err_bad_argument = 1002;
var err_ServiceNotSupported = 1004;
var err_InvalidService_Argument = 1000;
function convertFromPS2JS(PSCode){
    var JSCodeValue = new DeviceAPIError(0, "dummy");
    var JsErrCode;
    switch (PSCode) {
        case 1016:
            JsErrCode = JSCodeValue.TIMEOUT_ERR;
            break;
        case 1012:
            JsErrCode = JSCodeValue.DATA_NOT_FOUND_ERR;
            break;
        case 1010:
            JsErrCode = JSCodeValue.DATA_ALREADY_EXISTS_ERR;
            break;
        case 1009:
            JsErrCode = JSCodeValue.SERVICE_BUSY_ERR;
            break;
        case 1005:
            JsErrCode = JSCodeValue.SERVICE_IN_USE_ERR;
            break;
        default:
            JsErrCode = 1001;
    }
    return JsErrCode;
}

// S60 sp-based landmarks provider

function __sp_landmarks_descriptor(){
    //Read-only properties
    this.interfaceName = "landmarks";
    if (window.__Service_Interface_Ver) 
        this.version = __Service_Interface_Ver;
    else 
        this.version = 1.0;
    //Class-static properties 
}

function __sp_landmarks_instance(){
    //Descriptor
    this.descriptor = new __sp_landmarks_descriptor();
    //Core methods
    this.startEditor = __sp_landmarks_startEditor;
    //Extended methods
    this.getCategories = __sp_landmarks_category_getList;
    this.getCategoriesCb = __sp_landmarks_category_getList_cb;
    
    this.addCategory = __sp_landmarks_category_add;
    this.addCategoryCb = __sp_landmarks_category_add_cb;
    
    this.updateCategory = __sp_landmarks_category_update;
    this.updateCategoryCb = __sp_landmarks_category_update_cb;
    
    this.deleteCategory = __sp_landmarks_category_delete;
    this.deleteCategoryCb = __sp_landmarks_category_delete_cb;
    
    this.getLandmarks = __sp_landmarks_getList;
    this.getLandmarksCb = __sp_landmarks_getList_cb;
    
    this.addLandmark = __sp_landmarks_add;
    this.addLandmarkCb = __sp_landmarks_add_cb;
    
    this.updateLandmark = __sp_landmarks_update;
    this.updateLandmarkCb = __sp_landmarks_update_cb;
    
    this.deleteLandmark = __sp_landmarks_delete;
    this.deleteLandmarkCb = __sp_landmarks_delete_cb;
    
    this.importLandmarks = __sp_landmarks_import;
    this.importLandmarksCb = __sp_landmarks_import_cb;
    
    this.exportLandmarks = __sp_landmarks_export;
    this.exportLandmarksCb = __sp_landmarks_export_cb;
    
    this.organizeLandmarks = __sp_landmarks_organize;
    this.organizeLandmarksCb = __sp_landmarks_organize_cb;
    
    this.temporarySCb = null;
    this.temporaryECb = null;
    
    this.cancel = __sp_landmarks_cancel;
    //Private data 
    try {
        this.so = device.getServiceObject("Service.Landmarks", "IDataSource");
    } 
    catch (e) {
        __device_handle_exception(e, "Landmarks service not available");
    }
}

// TBD: We MUST get rid of this when underlying sp supports category names directly
// For one thing this is not localized!

var __SP_CATEGORY_MIN_LOCAL_ID = 16;

var __sp_category_list = [{
    id: 1,
    globalId: 3000,
    name: "Accommodation"
}, {
    id: 2,
    globalId: 6000,
    name: "Businesses"
}, {
    id: 3,
    globalId: 9000,
    name: "Telecommunications"
}, {
    id: 4,
    globalId: 12000,
    name: "Education"
}, {
    id: 5,
    globalId: 15000,
    name: "Entertainment"
}, {
    id: 6,
    globalId: 18000,
    name: "Food and drink"
}, {
    id: 7,
    globalId: 21000,
    name: "Geographical locations"
}, {
    id: 8,
    globalId: 24000,
    name: "Outdoor activities"
}, {
    id: 9,
    globalId: 27000,
    name: "People"
}, {
    id: 10,
    globalId: 30000,
    name: "Public services"
}, {
    id: 11,
    globalId: 33000,
    name: "Places of worship"
}, {
    id: 12,
    globalId: 36000,
    name: "Shopping"
}, {
    id: 13,
    globalId: 39000,
    name: "Sightseeing"
}, {
    id: 14,
    globalId: 42000,
    name: "Sports"
}, {
    id: 15,
    globalId: 45000,
    name: "Transport"
}];

/* ------ Wrap sp iterators ------- */

function __sp_landmarks_category_iterator(js_iterator){
    this.iter = js_iterator;
    this.next = __sp_landmarks_category_iterator_get_next;
    this.hasNext = __sp_landmarks_category_iterator_has_next;
    
    //indicate whether iterator has been populated atleast once
    this.hasElement = false;
    //refers to the current category item
    this.catItem = null;
    this.close = __sp_landmarks_category_close;
}

function __sp_landmarks_category_close(){
    this.iter.close();
}

function __sp_landmarks_category_iterator_has_next(){
    if (this.hasElement) {
        if (this.catItem !== null) {
            return true;
        }
        else {
            return false;
        }
        
    }
    else {
        this.catItem = this.iter.getNext();
        this.hasElement = true;
        if (typeof this.catItem == "undefined") {
            this.catItem = null;
            return false;
        }
        else {
            return true;
        }
    }
}

function __sp_landmarks_category_iterator_get_next(){
    if (this.hasElement) {
        var tempitem = new Object();
        tempitem = this.catItem;
        //update
        this.catItem = this.iter.getNext();
        if (typeof(this.catItem) == "undefined") {
            this.catItem = null;
        }
        return new __sp_device_category_obj(tempitem);
    }
    else {
        this.catItem = this.iter.getNext();
        if (typeof this.catItem == "undefined") {
            this.hasElement = true;
            this.catItem = null;
            return null;
            
        }
        else {
            this.hasElement = true;
            var tempObject = new Object();
            tempObject = this.lmItem;
            //update 
            
            this.catItem = this.iter.getNext();
            if (typeof(this.catItem) == "undefined") {
                this.catItem = null;
            }
            return new __sp_device_category_obj(tempObject);
        }
    }
}

//landmark iterator
function __sp_landmarks_iterator(js_iterator){
    this.iter = js_iterator;
    this.next = __sp_landmarks_iterator_get_next;
    this.hasNext = __sp_landmarks_iterator_has_next;
    
    //indicate whether iterator has been populated atleast once
    this.hasElement = false;
    //refers to the current landmark item
    this.lmItem = null;
    this.close = __sp_landmarks_landmarkitem_close;
}

function __sp_landmarks_landmarkitem_close(){
    this.iter.close();
}

// Parameter objects
//converts from LIW position to JS wrapper positionfield object
function __sp_device_landmark_location_obj(sp_location){
    this.longitude = (sp_location.Longitude == undefined) ? null : sp_location.Longitude;
    this.latitude = (sp_location.Latitude == undefined) ? null : sp_location.Latitude;
    if (sp_location.Altitude) 
        this.altitude = sp_location.Altitude;
    if (sp_location.HAccuracy) 
        this.hAccuracy = sp_location.HAccuracy;
    if (sp_location.VAccuracy) 
        this.vAccuracy = sp_location.VAccuracy;
}

//this is being used for converting position field in criteria for getLandmarks.
function __sp_landmark_position_obj(location){
    if ((location.longitude !== undefined) &&
    (location.longitude !== null) &&
    (location.longitude !== "")) {
        this.Longitude = location.longitude;
    }
    if ((location.latitude !== undefined) &&
    (location.latitude !== null) &&
    (location.latitude !== "")) {
        this.Latitude = location.latitude;
    }
    
    
    /*if(location.altitude) 
    
     this.Altitude = location.altitude;
    
     if(location.hAccuracy)
    
     this.HAccuracy = location.hAccuracy;
    
     if(location.vAccuracy)
    
     this.VAccuracy = location.vAccuracy;*/
    
}

//use this to convert from positon filed of landmarkitem to convert it to position field 
//in LIW of landmark item
function __sp_landmark_position_obj_fromJS_2LIW(location){
	var error = new DeviceAPIError(0, "dummy");
	if (typeof(location) != "object"){
		throw new DeviceAPIError(error.INVALID_ARG_ERR, 'position must be of type object');	
	}
	var loFound = false;
	var laFound = false;
	if ((location.longitude !== undefined)
	     && (location.longitude !== null)
		 && (location.longitude !== "")){
		this.Longitude = location.longitude;
		loFound = true;	 
	}
	if ((location.latitude !== undefined)
	     && (location.latitude !== null)
		 && (location.latitude !== "")){
		this.Latitude = location.latitude;
		laFound = true;	 
	}
    if (!(loFound && laFound)) {
		throw new DeviceAPIError(error.MISSING_ARG_ERR, 'missing position field');
	}
    if (location.altitude) 
        this.Altitude = location.altitude;
    if (location.hAccuracy) 
        this.HAccuracy = location.hAccuracy;
    if (location.vAccuracy) 
        this.VAccuracy = location.vAccuracy;
}

function __sp_landmark_bounded_area_obj(area){

    var error = new DeviceAPIError(0, "dummy");
    var c1Found = false;
    var c2Found = false;
    if ((area.coordinate1 !== undefined) &&
    (area.coordinate1 !== null) &&
    (area.coordinate1 !== "")) {
        if (typeof(area.coordinate1) != "object") {
            throw new DeviceAPIError(error.INVALID_ARG_ERR, 'coordinate1 must be an object');
        }
        else {
            var latFound = false;
            var longFound = false;
            if ((area.coordinate1.latitude !== undefined) &&
            (area.coordinate1.latitude !== null) &&
            (area.coordinate1.latitude !== "")) {
                this.NorthLatitude = area.coordinate1.latitude;
                latFound = true;
            }
            
            
            if ((area.coordinate1.longitude !== undefined) &&
            (area.coordinate1.longitude !== null) &&
            (area.coordinate1.longitude !== "")) {
                this.EastLongitude = area.coordinate1.longitude;
                longFound = true;
            }
            if (!(latFound && longFound)) {
                throw new DeviceAPIError(error.MISSING_ARG_ERR, 'missing position field');
            }
            c1Found = true;
            
        }
        
        
    }
    if ((area.coordinate2 !== undefined) &&
    (area.coordinate2 !== null) &&
    (area.coordinate2 !== "")) {
        if (typeof(area.coordinate2) != "object") {
            throw new DeviceAPIError(error.INVALID_ARG_ERR, 'coordinate2 must be an object');
        }
        else {
            var latFound = false;
            var longFound = false;
            if ((area.coordinate2.latitude !== undefined) &&
            (area.coordinate2.latitude !== null) &&
            (area.coordinate2.latitude !== "")) {
                this.SouthLatitude = area.coordinate2.latitude;
                latFound = true;
            }
            
            
            if ((area.coordinate2.longitude !== undefined) &&
            (area.coordinate2.longitude !== null) &&
            (area.coordinate2.longitude !== "")) {
                this.WestLongitude = area.coordinate2.longitude;
                longFound = true;
            }
            if (!(latFound && longFound)) {
                throw new DeviceAPIError(error.MISSING_ARG_ERR, 'missing position field');
            }
            c2Found = true;
            
        }
        
        
    }
    if (!(c1Found && c2Found)) {
        throw new DeviceAPIError(error.MISSING_ARG_ERR, 'missing position field');
    }
    
}


//converts from LIW address to JS wrapper AddressDetails

function __sp_device_landmark_address_obj(sp_address){
    if (sp_address.Street) 
        this.street = sp_address.Street;
    if (sp_address.City) 
        this.city = sp_address.City;
    if (sp_address.state) 
        this.state = sp_address.state;
    if (sp_address.AreaCode) 
        this.postalCode = sp_address.AreaCode;
    if (sp_address.Country) 
        this.country = sp_address.Country;
    if (sp_address.BuildingName) 
        this.building = sp_address.BuildingName;
    if (sp_address.Telephone) 
        this.phone = sp_address.Telephone;
}

// sp problem: no way to specify state/province?

function __sp_landmark_address_obj(address){
	var error = new DeviceAPIError(0, "dummy");
	if (typeof(address) != "object"){
		throw new DeviceAPIError(error.MISSING_ARG_ERR, 'address must be of type object');	
	}
	
    if (address.street !== undefined){
		if (address.street === null){
			this.Street = "";	
		}
		else {
			this.Street = address.street;	
		}
			
	} 
	if (address.city !== undefined){
		if (address.city === null){
			this.City = "";	
		}
		else {
			this.City = address.city;	
		}
			
	} 
	if (address.state !== undefined){
		if (address.state === null){
			this.state = "";	
		}
		else {
			this.state = address.state;	
		}
			
	} 
	if (address.postalCode !== undefined){
		if (address.postalCode === null){
			this.AreaCode = "";	
		}
		else {
			this.AreaCode = address.postalCode;	
		}
			
	} 
	if (address.country !== undefined){
		if (address.country === null){
			this.Country = "";	
		}
		else {
			this.Country = address.country;	
		}
			
	} 
	if (address.building !== undefined){
		if (address.building === null){
			this.BuildingName = "";	
		}
		else {
			this.BuildingName = address.building;	
		}
			
	} 
	if (address.phone !== undefined){
		if (address.phone === null){
			this.Telephone = "";	
		}
		else {
			this.Telephone = address.phone;	
		}
			
	} 
    
}

function __sp_add_category_ids_for_names(names){
    var errObj = new DeviceAPIError(0, "dummy");
    var retval = new Array();
    
    for (var i in names) {
        if ((names[i] !== undefined) &&
        (names[i] !== "") &&
        (names[i] !== null)) {
            if (typeof(names[i]) != "string") {
                throw new DeviceAPIError(errObj.INVALID_ARG_ERR, 'category should be of type string');
            }
            else {
                retval.push(names[i].toString());
            }
            
            
        }
        
    }
    return retval;
}

function __sp_get_category_ids_for_names(names){
    var errObj = new DeviceAPIError(0, "dummy");
    var retval = new Array();
    var isCatGlobal = 0;// to check if the category passed is a global category
    for (var i in names) {
        if (typeof(names[i]) != "string") {
            throw new DeviceAPIError(errObj.INVALID_ARG_ERR, 'category should be of type string');
        }
        for (var ii in __sp_category_list) {
            //__device_debug(names[i] + " ==? " + __sp_category_list[ii].name);
            
            if (__sp_category_list[ii].name.toLowerCase() == names[i].toLowerCase()) {
                retval.push(__sp_category_list[ii].id.toString());
                isCatGlobal = 1;
            }
        }
        if (isCatGlobal == 0) {
            return null;
        }
        isCatGlobal = 0;// set the flag to 0
    }
    return retval;
}

//converts from LIW to JS wrapper paramater
function __sp_device_landmark_obj(sp_landmark){
    this.landmarkId = sp_landmark.id;
    if (sp_landmark.LandmarkName) {
        this.name = sp_landmark.LandmarkName;
    }
    if (sp_landmark.LandmarkDesc) {
        this.description = sp_landmark.LandmarkDesc;
    }
    if (sp_landmark.CoverageRadius) {
        this.coverageRadius = sp_landmark.CoverageRadius;
    }
    if (sp_landmark.LandmarkPosition) {
        this.position = new __sp_device_landmark_location_obj(sp_landmark.LandmarkPosition);
    }
    if (sp_landmark.CategoryInfo) {
        this.categoryIds = sp_landmark.CategoryInfo;
    }
    
    if (sp_landmark.LandmarkFields) {
        this.address = new __sp_device_landmark_address_obj(sp_landmark.LandmarkFields);
    }
}

function __sp_landmarks_addLocality(add){
    var errLoc = new DeviceAPIError(0, "dummy");
    if (typeof(add) != "object") {
        throw new DeviceAPIError(errLoc.INVALID_ARG_ERR, 'address should be of type object');
    }
    if ((add.street !== undefined) &&
    (add.street !== null) &&
    (add.street !== "")) {
    
        this.Street = add.street;
        
    }
    if ((add.city !== undefined) &&
    (add.city !== null) &&
    (add.city !== "")) {
    
        this.City = add.city;
        
    }
    if ((add.state !== undefined) &&
    (add.state !== null) &&
    (add.state !== "")) {
    
        this.state = add.state;
        
    }
    if ((add.postalCode !== undefined) &&
    (add.postalCode !== null) &&
    (add.postalCode !== "")) {
    
        this.AreaCode = add.postalCode;
        
    }
    if ((add.country !== undefined) &&
    (add.country !== null) &&
    (add.country !== "")) {
    
        this.Country = add.country;
        
    }
    if ((add.building !== undefined) &&
    (add.building !== null) &&
    (add.building !== "")) {
    
        this.BuildingName = add.building;
        
    }
    if ((add.phone !== undefined) &&
    (add.phone !== null) &&
    (add.phone !== "")) {
    
        this.Telephone = add.phone;
        
    }
}

function __sp_landmarks_addPosition(pos){
    var errPos = new DeviceAPIError(0, "dummy");
    if (typeof(pos) != "object") {
        throw new DeviceAPIError(errPos.INVALID_ARG_ERR, 'position should be of type object');
    }
    
    if ((pos.longitude !== undefined) &&
    (pos.longitude !== null) &&
    (pos.longitude !== "")) {
    
        this.Longitude = pos.longitude;
        //alert("longitude found");
    
    }
    if ((pos.latitude !== undefined) &&
    (pos.latitude !== null) &&
    (pos.latitude !== "")) {
    
        this.Latitude = pos.latitude;
        //alert("latitude found");
    
    }
    if ((pos.altitude !== undefined) &&
    (pos.altitude !== null) &&
    (pos.altitude !== "")) {
    
        this.Altitude = pos.altitude;
        
    }
    if ((pos.hAccuracy !== undefined) &&
    (pos.hAccuracy !== null) &&
    (pos.hAccuracy !== "")) {
    
        this.HAccuracy = pos.hAccuracy;
        
    }
    if ((pos.vAccuracy !== undefined) &&
    (pos.vAccuracy !== null) &&
    (pos.vAccuracy !== "")) {
    
        this.VAccuracy = pos.vAccuracy;
        
    }
}

function __sp_landmarks_addLmObject(lm){
    var posSet = false;
    var errObj = new DeviceAPIError(0, "dummy");
    if ((lm.name !== undefined) &&
    (lm.name !== null) &&
    (lm.name !== "")) {
    
        this.LandmarkName = lm.name;
        
    }
    if ((lm.description !== undefined) &&
    (lm.description !== null) &&
    (lm.description !== "")) {
    
        this.LandmarkDesc = lm.description;
        
    }
    if ((lm.position !== undefined) &&
    (lm.position !== null) &&
    (lm.position !== "")) {
        //alert("adding position");
        this.LandmarkPosition = new __sp_landmarks_addPosition(lm.position);
        posSet = true;
        //alert("pos="+this.position); 
    
    }
    if ((lm.coverageRadius !== undefined) &&
    (lm.coverageRadius !== null) &&
    (lm.coverageRadius !== "")) {
    
        if (posSet) {
            this.CoverageRadius = lm.coverageRadius;
        }
        else {
            throw new DeviceAPIError(errObj.MISSING_ARG_ERR, 'missing position');
        }
        
        
    }
    
    if ((lm.categoryIds !== undefined) &&
    (lm.categoryIds !== null) &&
    (lm.categoryIds !== "")) {
        if (typeof(lm.categoryIds) != 'object') {
            throw new DeviceAPIError(errObj.INVALID_ARG_ERR, 'categoryids should be of type object');
        }
        
        this.CategoryInfo = __sp_add_category_ids_for_names(lm.categoryIds);
        if (!this.CategoryInfo) {
            throw new DeviceAPIError(errObj.MISSING_ARG_ERR, 'invalid category');
            
        }
        
    }
    if ((lm.address !== undefined) &&
    (lm.address !== null) &&
    (lm.address !== "")) {
    
        this.LandmarkFields = new __sp_landmarks_addLocality(lm.address);
        
    }
    //dummy object
    this.dummyField = "dummyfield";
    
}

//this converts from JS landmarkitem to LIW landmark item
//being used by updateLandmark API
function __sp_landmark_obj(landmark, str){
	var error = new DeviceAPIError(0, "dummy");
    if (landmark.name !== undefined){
		if (landmark.name === null){
			this.LandmarkName = "";	
		}
		else {
			this.LandmarkName = landmark.name;	
		}
		
	} 
        
    if ((landmark.landmarkId === undefined)
	     || (landmark.landmarkId === null)
		 || (landmark.landmarkId === "")) 
		 throw new DeviceAPIError(error.MISSING_ARG_ERR, 'for updating; id must be supplied');
	else 
        this.id = landmark.landmarkId;
    if (landmark.description !== undefined){
		if (landmark.description === null){
			this.LandmarkDesc = "";	
		}
		else {
			this.LandmarkDesc = landmark.description;	
		}
		
	} 
        
    if (landmark.position) 
        this.LandmarkPosition = new __sp_landmark_position_obj_fromJS_2LIW(landmark.position);
    if (landmark.coverageRadius) 
        this.CoverageRadius = landmark.coverageRadius;
    if (landmark.categories) {
        this.CategoryInfo = __sp_get_category_ids_for_names(landmark.categories);
        if (!this.CategoryInfo) {
            throw new DeviceError("Landmarks: " + str + "Category is invalid", err_bad_argument);
        }
    }
    if (landmark.address) 
        this.LandmarkFields = new __sp_landmark_address_obj(landmark.address);
    
	this.temp = "dummy";
}

function __sp_landmarks_iterator_has_next(){
    if (this.hasElement) {
        if (this.lmItem !== null) {
            return true;
        }
        else {
            return false;
        }
        
    }
    else {
        this.lmItem = this.iter.getNext();
        this.hasElement = true;
        if (typeof this.lmItem == "undefined") {
            this.lmItem = null;
            return false;
        }
        else {
            return true;
        }
    }
}

function __sp_landmarks_iterator_get_next(){
    if (this.hasElement) {
        var tempitem = new Object();
        tempitem = this.lmItem;
        //update
        this.lmItem = this.iter.getNext();
        if (typeof(this.lmItem) == "undefined") {
            this.lmItem = null;
        }
        return new __sp_device_landmark_obj(tempitem);
    }
    else {
        this.lmItem = this.iter.getNext();
        if (typeof this.lmItem == "undefined") {
            this.hasElement = true;
            this.lmItem = null;
            return null;
            
        }
        else {
            this.hasElement = true;
            var tempObject = new Object();
            tempObject = this.lmItem;
            //update 
            
            this.lmItem = this.iter.getNext();
            if (typeof(this.lmItem) == "undefined") {
                this.lmItem = null;
            }
            return new __sp_device_landmark_obj(tempObject);
        }
    }
    
}

function __sp_category_obj(category){
    if (category.name) 
        this.CategoryName = category.name;
    if (category.categoryId) 
        this.id = category.categoryId;
}

function __sp_device_category_obj(sp_category){
    this.categoryId = sp_category.id;
    this.name = sp_category.CategoryName;
}

/* --------- Public methods ---------- */


var LANDMARKS_APP_ID = 0x101F85A2;

// Apps should take care that this is not reinvoked
// while the editor is already running. 

function __sp_landmarks_startEditor(__success_cb, landmark_item, _error_cb){
    // internal variable used in this library implementation
    // This will made local variable when seperate module js files gets integrated in this file.
    error = new DeviceAPIError(0, "dummy");
    if ((__success_cb === undefined) ||
    (__success_cb === null) ||
    (__success_cb === "")) 
        throw new DeviceAPIError(error.MISSING_ARG_ERR, 'StartEditor:Missing Success Callback');
    
    if ((typeof __success_cb) != "function") 
        throw new DeviceAPIError(error.INVALID_ARG_ERR, 'StartEditor:Success Callback must be of type function');
    
    if (landmark_item !== undefined) {
        if ((landmark_item !== null) &&
        (landmark_item !== "")) {
        
            throw new DeviceAPIError(error.NOT_SUPPORTED_ERR, 'startEditor:landmark item is not supported');
            
        }
    }
    
    if ((_error_cb !== undefined) &&
    (_error_cb !== null) &&
    (_error_cb !== "")) {
        if ((typeof _error_cb) != "function") 
            throw new DeviceAPIError(error.INVALID_ARG_ERR, 'StartEditor:error callback must be of type function');
    }
    
    var LANDMARKS_APP_ID = 0x101F85A2;
    
    
    var __s60_start_and_wait_cb;
    
    function __s60_on_app_exit(){
        window.xwidget.onshow = null;
        if (__s60_start_and_wait_cb) {
            __s60_start_and_wait_cb();
        }
    }
    
    var finished = function(arg1, arg2, arg3){
        __success_cb(arg1, arg2, arg3);
    };
    __s60_start_and_wait(LANDMARKS_APP_ID, '', finished);
    
}

//oriiginal signature category_cb, name

function __sp_landmarks_category_getList_cb(arg1, arg2, arg3){
    var CbObj;
    var category_cb;
    var ErrorCallback;
    if (this.temporarySCb) {
        category_cb = this.temporarySCb;
        ErrorCallback = this.temporaryECb;
        this.temporarySCb = null;
        this.temporaryECb = null;
    }
    else {
        CbObj = glob_obj.getFromArray(arg1);
        if (CbObj) {
            category_cb = CbObj.success_cb;
            ErrorCallback = CbObj.error_cb;
        }
        
        else {
            alert("Landmarks: __sp_landmarks_category_getList_cb: Callback not found ");
            return;
        }
    }
    
    
    var iter = null;
    //if there is an error invoke user supplied error callback
    if (arg3.ErrorCode || (arg2 == 4)) { //indicates an error
        var scbErrCode = convertFromPS2JS(arg3.ErrorCode);
        var erroObject = new DeviceAPIError(scbErrCode, arg3.ErrorMessage);
        if (ErrorCallback) {
            ErrorCallback(erroObject);
        }
    }
    else {
        if (arg3.ReturnValue) {
            iter = new __sp_landmarks_category_iterator(arg3.ReturnValue);
            category_cb(iter);
        }
    }
    glob_obj.removeFromArray(arg1);
}

function __sp_landmarks_category_getList(category_cb, name, ErrorCallback){
    try {
        //alert("calling getlist");
        var error = new DeviceAPIError(0, "dummy");
        //succes callback must be defined and should be of the type function
        if ((category_cb === undefined) ||
        (category_cb === "") ||
        (category_cb === null)) {
            throw new DeviceAPIError(error.MISSING_ARG_ERR, 'callback is missing');
        }
        if (typeof(category_cb) != "function") {
            throw new DeviceAPIError(error.INVALID_ARG_ERR, 'invalid callback argument');
        }
        //check if errorcallback has been supplied and valid
        var errcbFound = false;
        if ((ErrorCallback !== undefined) &&
        (ErrorCallback !== null) &&
        (ErrorCallback !== "")) {
            if (typeof(ErrorCallback) != "function") {
                throw new DeviceAPIError(error.INVALID_ARG_ERR, 'invalid error callback argument');
            }
            else {
                errcbFound = true;
            }
        }
        //to check from here
        var criteria = new Object();
        modifyObjectBaseProp(criteria);
        criteria.Type = "Category";
        //if name has been supplied it must be of type string
        if ((name !== undefined) &&
        (name !== null) &&
        (name !== "")) {
        
            if (typeof(name) != "string") {
                throw new DeviceAPIError(error.INVALID_ARG_ERR, 'name must be a string');
            }
            
        }
        
        if (name) {
            criteria.Filter = new Object();
            modifyObjectBaseProp(criteria.Filter);
            criteria.Filter.CategoryName = name;
            criteria.Filter.PreviousMatchesOnly = false;
        }
        
        this.temporarySCb = category_cb;
        this.temporaryECb = ErrorCallback;
        
        var rval = this.so.IDataSource.GetList(criteria, this.getCategoriesCb);
        
        if (rval.TransactionID) {
            glob_obj.addToGlobalArray(rval.TransactionID, category_cb, ErrorCallback);
        }
        
        if (rval.ErrorCode != 0) {
            switch (rval.ErrorCode) {
                case 1003:
                    throw new DeviceAPIError(error.MISSING_ARG_ERR, rval.ErrorMessage);
                    break;
                case 1002:
                    throw new DeviceAPIError(error.INVALID_ARG_ERR, rval.ErrorMessage);
                    break;
                case 1004:
                    throw new DeviceAPIError(error.NOT_SUPPORTED_ERR, rval.ErrorMessage);
                    break;
                case 1000:
                    throw new DeviceAPIError(error.INVALID_ARG_ERR, rval.ErrorMessage);
                    break;
                default:
                    throw new DeviceAPIError(-101, "unknown error message");
                    
            }
            
        }
        return rval.TransactionID;
        
        
    } 
    catch (e) {
        //alert("exception from here");
        throw e;
    }
}

function __sp_landmarks_category_add_cb(arg1, arg2, arg3){
    var CbObj;
    var callback;
    var ErrorCallback;
    if (this.temporarySCb) {
        category_cb = this.temporarySCb;
        ErrorCallback = this.temporaryECb;
        this.temporarySCb = null;
        this.temporaryECb = null;
    }
    else {
        CbObj = glob_obj.getFromArray(arg1);
        if (CbObj) {
            callback = CbObj.success_cb;
            ErrorCallback = CbObj.error_cb;
        }
        
        else {
            alert("Landmarks: __sp_landmarks_category_add_cb: Callback not found ");
            return;
        }
    }
    
    
    var id = null;
    //if there is an error invoke user supplied error callback
    if (arg2 == 4 || arg3.ErrorCode) { //indicates an error
        var scbErrCode = convertFromPS2JS(arg3.ErrorCode);
        var erroObject = new DeviceAPIError(scbErrCode, arg3.ErrorMessage);
        if (ErrorCallback) {
            ErrorCallback(erroObject);
        }
    }
    else {
        if (arg3.ReturnValue) {
            id = arg3.ReturnValue;
        }
        //in case of success invoke user supplied scb
        callback(id);
    }
    glob_obj.removeFromArray(arg1);
}

//original signature : __sp_landmarks_category_add(cat)
function __sp_landmarks_category_add(callback, categoryItem, ErrorCallback){
    try {
        var error = new DeviceAPIError(0, "dummy");
        var isErrCB = true;//indicates a valid errocalback has been supplied
        if (callback === undefined) {
            throw new DeviceAPIError(error.MISSING_ARG_ERR, 'AddSucessCallback is missing');
        }
        else {
            if (((callback === null) ||
            (callback === "")) &&
            (typeof(callback) != "number")) {
                throw new DeviceAPIError(error.MISSING_ARG_ERR, 'AddSucessCallback is missing');
            }
            else 
                if (typeof(callback) != 'function') {
                    throw new DeviceAPIError(error.INVALID_ARG_ERR, 'invalid AddSucessCallback argument');
                }
        }
        if (categoryItem === undefined || categoryItem === null) {
            throw new DeviceAPIError(error.MISSING_ARG_ERR, 'CategoryItem is missing');
        }
        else 
            if (typeof(categoryItem) !== "object") {
                throw new DeviceAPIError(error.INVALID_ARG_ERR, 'invalid CategoryItem argument');
            }
        
        if ((ErrorCallback != undefined)) {
            if ((!ErrorCallback) &&
            (typeof(ErrorCallback) != "number")) {
                isErrCB = false;
            }
            else 
                if ((typeof(ErrorCallback) != 'function')) {
                    throw new DeviceAPIError(error.INVALID_ARG_ERR, 'invalid ErrorCallback callback');
                }
            
        }
        else {
            isErrCB = false;
        }
        
        var criteria = new Object();
        modifyObjectBaseProp(criteria);
        criteria.Type = "Category";
        criteria.Data = new __sp_category_obj(categoryItem);
		
		this.temporarySCb = callback;
        this.temporaryECb = ErrorCallback;
		
        var rval = this.so.IDataSource.Add(criteria, this.addCategoryCb);
        
        if (rval.TransactionID) {
            glob_obj.addToGlobalArray(rval.TransactionID, callback, ErrorCallback);
        }
        if (rval.ErrorCode != 0) {
            switch (rval.ErrorCode) {
                case err_missing_argument:
                    throw new DeviceAPIError(error.MISSING_ARG_ERR, rval.ErrorMessage);
                    break;
                case err_bad_argument:
                    throw new DeviceAPIError(error.INVALID_ARG_ERR, rval.ErrorMessage);
                    break;
                case err_ServiceNotSupported:
                    throw new DeviceAPIError(error.NOT_SUPPORTED_ERR, rval.ErrorMessage);
                    break;
                case err_InvalidService_Argument:
                    throw new DeviceAPIError(error.INVALID_ARG_ERR, rval.ErrorMessage);
                    break;
                default:
                    throw new DeviceAPIError(-101, "unknown error message");
            }
        }
        return rval.TransactionID;
    } 
    catch (e) {
        throw e;
    }
}

function __sp_landmarks_add_cb(arg1, arg2, arg3){
    var id = null;
    var CbObj;
    var callback;
    var ErrorCallback;
	if (this.temporarySCb) {
        category_cb = this.temporarySCb;
        ErrorCallback = this.temporaryECb;
        this.temporarySCb = null;
        this.temporaryECb = null;
    }
    else {
        CbObj = glob_obj.getFromArray(arg1);
        if (CbObj) {
            callback = CbObj.success_cb;
            ErrorCallback = CbObj.error_cb;
        }
        
        else {
            alert("Landmarks: __sp_landmarks_add_cb: Callback not found ");
            return;
        }
    }
    
    //if there is an error invoke user supplied error callback
    if (arg2 == 4 || arg3.ErrorCode) { //indicates an error
        var scbErrCode = convertFromPS2JS(arg3.ErrorCode);
        var erroObject = new DeviceAPIError(scbErrCode, arg3.ErrorMessage);
        if (ErrorCallback) {
            ErrorCallback(erroObject);
        }
    }
    else {
        if (arg3.ReturnValue) {
            id = arg3.ReturnValue;
        }
        //in case of success invoke user supplied scb
        callback(id);
    }
    glob_obj.removeFromArray(arg1);
}

//original signature : __sp_landmarks_add(landmark)
function __sp_landmarks_add(callback, landmarkItem, ErrorCallback){
    try {
        var error = new DeviceAPIError(0, "dummy");
        var isErrCB = true;//indicates a valid errocalback has been supplied
        if (callback === undefined) {
            throw new DeviceAPIError(error.MISSING_ARG_ERR, 'AddSucessCallback is missing');
        }
        else {
            if (((callback === null) ||
            (callback === "")) &&
            (typeof(callback) != "number")) {
                throw new DeviceAPIError(error.MISSING_ARG_ERR, 'AddSucessCallback is missing');
            }
            else 
                if (typeof(callback) != 'function') {
                    throw new DeviceAPIError(error.INVALID_ARG_ERR, 'invalid AddSucessCallback argument');
                }
        }
        if ((landmarkItem === undefined) ||
        (landmarkItem === null) ||
        (landmarkItem === "")) {
            throw new DeviceAPIError(error.MISSING_ARG_ERR, 'LandmarkItem is missing');
        }
        else 
            if (typeof(landmarkItem) !== "object") {
                throw new DeviceAPIError(error.INVALID_ARG_ERR, 'invalid LandmarkItem argument');
            }
        
        if ((ErrorCallback != undefined)) {
            if ((!ErrorCallback) &&
            (typeof(ErrorCallback) != "number")) {
                isErrCB = false;
            }
            else 
                if ((typeof(ErrorCallback) != 'function')) {
                    throw new DeviceAPIError(error.INVALID_ARG_ERR, 'invalid ErrorCallback callback');
                }
            
        }
        else {
            isErrCB = false;
        }
        
        
        var str = "addLandmark: ";
        var criteria = new Object();
        modifyObjectBaseProp(criteria);
        criteria.Type = "Landmark";
        //criteria.Data = new __sp_landmark_obj(landmarkItem, str);
        criteria.Data = new __sp_landmarks_addLmObject(landmarkItem);
        //alert("calling PS add");
		this.temporarySCb = callback;
        this.temporaryECb = ErrorCallback;
        var rval = this.so.IDataSource.Add(criteria, this.addLandmarkCb);
        //alert("rval.tid="+rval.TransactionID);
        //alert("rval.error="+rval.ErrorCode);
        if (rval.TransactionID) {
            glob_obj.addToGlobalArray(rval.TransactionID, callback, ErrorCallback);
        }
        
        if (rval.ErrorCode != 0) {
            switch (rval.ErrorCode) {
                case err_missing_argument:
                    throw new DeviceAPIError(error.MISSING_ARG_ERR, rval.ErrorMessage);
                    break;
                case err_bad_argument:
                    throw new DeviceAPIError(error.INVALID_ARG_ERR, rval.ErrorMessage);
                    break;
                case err_ServiceNotSupported:
                    throw new DeviceAPIError(error.NOT_SUPPORTED_ERR, rval.ErrorMessage);
                    break;
                case err_InvalidService_Argument:
                    throw new DeviceAPIError(error.INVALID_ARG_ERR, rval.ErrorMessage);
                    break;
                default:
                    throw new DeviceAPIError(-101, "unknown error message");
            }
        }
        return rval.TransactionID;
    } 
    catch (e) {
        throw e;
    }
}

function __sp_landmarks_delete_cb(arg1, arg2, arg3){
    var callback;
    var ErrorCallback;
    var CbObj;
	if (this.temporarySCb) {
        category_cb = this.temporarySCb;
        ErrorCallback = this.temporaryECb;
        this.temporarySCb = null;
        this.temporaryECb = null;
    }
    else {
        CbObj = glob_obj.getFromArray(arg1);
        if (CbObj) {
            callback = CbObj.success_cb;
            ErrorCallback = CbObj.error_cb;
        }
        
        else {
            alert("Landmarks: __sp_landmarks_delete_cb: Callback not found ");
            return;
        }
    }
    
    //if there is an error invoke user supplied error callback
    if (arg2 == 4 || arg3.ErrorCode) { //indicates an error
        var scbErrCode = convertFromPS2JS(arg3.ErrorCode);
        var erroObject = new DeviceAPIError(scbErrCode, arg3.ErrorMessage);
        if (ErrorCallback) {
            ErrorCallback(erroObject);
        }
    }
    else {
        //in case of success invoke user supplied scb
        callback();
    }
    glob_obj.removeFromArray(arg1);
}

//original signature : __sp_landmarks_delete(id)
function __sp_landmarks_delete(callback, landmarkId, ErrorCallback){
    try {
        var error = new DeviceAPIError(0, "dummy");
        var isErrCB = true;//indicates a valid errocalback has been supplied
        if (callback === undefined) {
            throw new DeviceAPIError(error.MISSING_ARG_ERR, 'SucessCallback is missing');
        }
        else {
            if (((callback === null) ||
            (callback === "")) &&
            (typeof(callback) != "number")) {
                throw new DeviceAPIError(error.MISSING_ARG_ERR, 'SucessCallback is missing');
            }
            else 
                if (typeof(callback) != 'function') {
                    throw new DeviceAPIError(error.INVALID_ARG_ERR, 'invalid SucessCallback argument');
                }
        }
        if (landmarkId === undefined || landmarkId === null) {
            throw new DeviceAPIError(error.MISSING_ARG_ERR, 'landmarkId is missing');
        }
        else 
            if (typeof(landmarkId) !== "string") {
                throw new DeviceAPIError(error.INVALID_ARG_ERR, 'invalid landmarkId argument');
            }
        
        if ((ErrorCallback != undefined)) {
            if ((!ErrorCallback) &&
            (typeof(ErrorCallback) != "number")) {
                isErrCB = false;
            }
            else 
                if ((typeof(ErrorCallback) != 'function')) {
                    throw new DeviceAPIError(error.INVALID_ARG_ERR, 'invalid ErrorCallback callback');
                }
            
        }
        else {
            isErrCB = false;
        }
        
        
        var criteria = new Object();
        modifyObjectBaseProp(criteria);
        criteria.Type = "Landmark";
        criteria.Data = new Object();
        modifyObjectBaseProp(criteria.Data);
        criteria.Data.id = landmarkId;
		
		this.temporarySCb = callback;
        this.temporaryECb = ErrorCallback;
		
        var rval = this.so.IDataSource.Delete(criteria, this.deleteLandmarkCb);
        if (rval.TransactionID) {
            glob_obj.addToGlobalArray(rval.TransactionID, callback, ErrorCallback);
        }
        if (rval.ErrorCode != 0) {
            switch (rval.ErrorCode) {
                case err_missing_argument:
                    throw new DeviceAPIError(error.MISSING_ARG_ERR, rval.ErrorMessage);
                    break;
                case err_bad_argument:
                    throw new DeviceAPIError(error.INVALID_ARG_ERR, rval.ErrorMessage);
                    break;
                case err_ServiceNotSupported:
                    throw new DeviceAPIError(error.NOT_SUPPORTED_ERR, rval.ErrorMessage);
                    break;
                case err_InvalidService_Argument:
                    throw new DeviceAPIError(error.INVALID_ARG_ERR, rval.ErrorMessage);
                    break;
                default:
                    throw new DeviceAPIError(-101, "unknown error message");
            }
        }
        return rval.TransactionID;
    } 
    catch (e) {
        throw e;
    }
}

function __sp_landmarks_update_cb(arg1, arg2, arg3){

    var callback;
    var ErrorCallback;
    var CbObj;
		if (this.temporarySCb) {
        category_cb = this.temporarySCb;
        ErrorCallback = this.temporaryECb;
        this.temporarySCb = null;
        this.temporaryECb = null;
    }
    else {
        CbObj = glob_obj.getFromArray(arg1);
        if (CbObj) {
            callback = CbObj.success_cb;
            ErrorCallback = CbObj.error_cb;
        }
        
        else {
            alert("Landmarks: __sp_landmarks_update_cb: Callback not found ");
            return;
        }
    }
    
    //if there is an error invoke user supplied error callback
    if (arg2 == 4 || arg3.ErrorCode) { //indicates an error
        var scbErrCode = convertFromPS2JS(arg3.ErrorCode);
        var erroObject = new DeviceAPIError(scbErrCode, arg3.ErrorMessage);
        if (ErrorCallback) {
            ErrorCallback(erroObject);
        }
    }
    else {
        //in case of success invoke user supplied scb
        callback();
    }
    glob_obj.removeFromArray(arg1);
}

//original signature : __sp_landmarks_update(landmark)
function __sp_landmarks_update(callback, landmarkItem, ErrorCallback){
    try {
        var error = new DeviceAPIError(0, "dummy");
        var isErrCB = true;//indicates a valid errocalback has been supplied
        if (callback === undefined) {
            throw new DeviceAPIError(error.MISSING_ARG_ERR, 'SuccessCallback is missing');
        }
        else {
            if (((callback === null) ||
            (callback === "")) &&
            (typeof(callback) != "number")) {
                throw new DeviceAPIError(error.MISSING_ARG_ERR, 'SuccessCallback is missing');
            }
            else 
                if (typeof(callback) != 'function') {
                    throw new DeviceAPIError(error.INVALID_ARG_ERR, 'invalid SuccessCallback argument');
                }
        }
        if (landmarkItem === undefined || landmarkItem === null || landmarkItem === "") {
            throw new DeviceAPIError(error.MISSING_ARG_ERR, 'LandmarkItem is missing');
        }
        else 
            if (typeof(landmarkItem) !== "object") {
                throw new DeviceAPIError(error.INVALID_ARG_ERR, 'invalid LandmarkItem argument');
            }
        
        if ((ErrorCallback != undefined)) {
            if ((!ErrorCallback) &&
            (typeof(ErrorCallback) != "number")) {
                isErrCB = false;
            }
            else 
                if ((typeof(ErrorCallback) != 'function')) {
                    throw new DeviceAPIError(error.INVALID_ARG_ERR, 'invalid ErrorCallback callback');
                }
            
        }
        else {
            isErrCB = false;
        }
        
        
        var str = "updateLandmark: ";
        var criteria = new Object();
        modifyObjectBaseProp(criteria);
        criteria.Type = "Landmark";
        criteria.Data = new __sp_landmark_obj(landmarkItem, str);
		
		this.temporarySCb = callback;
        this.temporaryECb = ErrorCallback;
        var rval = this.so.IDataSource.Add(criteria, this.updateLandmarkCb);
        if (rval.TransactionID) {
            glob_obj.addToGlobalArray(rval.TransactionID, callback, ErrorCallback);
        }
        
        if (rval.ErrorCode != 0) {
            switch (rval.ErrorCode) {
                case err_missing_argument:
                    throw new DeviceAPIError(error.MISSING_ARG_ERR, rval.ErrorMessage);
                    break;
                case err_bad_argument:
                    throw new DeviceAPIError(error.INVALID_ARG_ERR, rval.ErrorMessage);
                    break;
                case err_ServiceNotSupported:
                    throw new DeviceAPIError(error.NOT_SUPPORTED_ERR, rval.ErrorMessage);
                    break;
                case err_InvalidService_Argument:
                    throw new DeviceAPIError(error.INVALID_ARG_ERR, rval.ErrorMessage);
                    break;
                default:
                    throw new DeviceAPIError(-101, "unknown error message");
            }
        }
        return rval.TransactionID;
    } 
    catch (e) {
        throw e;
    }
}

function __sp_landmarks_category_update_cb(arg1, arg2, arg3){
    var callback;
    var ErrorCallback;
    var CbObj;
	if (this.temporarySCb) {
        category_cb = this.temporarySCb;
        ErrorCallback = this.temporaryECb;
        this.temporarySCb = null;
        this.temporaryECb = null;
    }
    else {
        CbObj = glob_obj.getFromArray(arg1);
        if (CbObj) {
            callback = CbObj.success_cb;
            ErrorCallback = CbObj.error_cb;
        }
        
        else {
            alert("Landmarks: __sp_landmarks_category_update_cb: Callback not found ");
            return;
        }
    }
    
    //if there is an error invoke user supplied error callback
    if (arg2 == 4 || arg3.ErrorCode) { //indicates an error
        var scbErrCode = convertFromPS2JS(arg3.ErrorCode);
        var erroObject = new DeviceAPIError(scbErrCode, arg3.ErrorMessage);
        if (ErrorCallback) {
            ErrorCallback(erroObject);
        }
    }
    else {
        //in case of success invoke user supplied scb
        callback();
    }
    glob_obj.removeFromArray(arg1);
}

function __sp_landmarks_category_update(callback, categoryItem, ErrorCallback){
    try {
        var error = new DeviceAPIError(0, "dummy");
        var isErrCB = true;//indicates a valid errocalback has been supplied
        if (callback === undefined) {
            throw new DeviceAPIError(error.MISSING_ARG_ERR, 'SucessCallback is missing');
        }
        else {
            if (((callback === null) ||
            (callback === "")) &&
            (typeof(callback) != "number")) {
                throw new DeviceAPIError(error.MISSING_ARG_ERR, 'SucessCallback is missing');
            }
            else 
                if (typeof(callback) != 'function') {
                    throw new DeviceAPIError(error.INVALID_ARG_ERR, 'invalid SucessCallback argument');
                }
        }
        if (categoryItem === undefined || categoryItem === null || categoryItem === "") {
            throw new DeviceAPIError(error.MISSING_ARG_ERR, 'CategoryItem is missing');
        }
        else 
            if (typeof(categoryItem) !== "object") {
                throw new DeviceAPIError(error.INVALID_ARG_ERR, 'invalid CategoryItem argument');
            }
        if ((categoryItem.categoryId === undefined)
		     || (categoryItem.categoryId === null)
			 || (categoryItem.categoryId === "")){
			 throw new DeviceAPIError(error.MISSING_ARG_ERR, 'categoryId is missing');	
		}
		if (typeof (categoryItem.categoryId) != "string") {
			throw new DeviceAPIError(error.INVALID_ARG_ERR, 'category Id must be a string');
		}
        if ((ErrorCallback != undefined)) {
            if ((!ErrorCallback) &&
            (typeof(ErrorCallback) != "number")) {
                isErrCB = false;
            }
            else 
                if ((typeof(ErrorCallback) != 'function')) {
                    throw new DeviceAPIError(error.INVALID_ARG_ERR, 'invalid ErrorCallback callback');
                }
        }
        else {
            isErrCB = false;
        }
        
        
        var criteria = new Object();
        modifyObjectBaseProp(criteria);
        criteria.Type = "Category";
        criteria.Data = new __sp_category_obj(categoryItem);
		
		this.temporarySCb = callback;
        this.temporaryECb = ErrorCallback;
		
        var rval = this.so.IDataSource.Add(criteria, this.updateCategoryCb);
        
        if (rval.TransactionID) {
            glob_obj.addToGlobalArray(rval.TransactionID, callback, ErrorCallback);
        }
        
        if (rval.ErrorCode != 0) {
            switch (rval.ErrorCode) {
                case err_missing_argument:
                    throw new DeviceAPIError(error.MISSING_ARG_ERR, rval.ErrorMessage);
                    break;
                case err_bad_argument:
                    throw new DeviceAPIError(error.INVALID_ARG_ERR, rval.ErrorMessage);
                    break;
                case err_ServiceNotSupported:
                    throw new DeviceAPIError(error.NOT_SUPPORTED_ERR, rval.ErrorMessage);
                    break;
                case err_InvalidService_Argument:
                    throw new DeviceAPIError(error.INVALID_ARG_ERR, rval.ErrorMessage);
                    break;
                default:
                    throw new DeviceAPIError(-101, "unknown error message");
            }
        }
        return rval.TransactionID;
    } 
    catch (e) {
        throw e;
    }
}

function __sp_landmarks_category_delete_cb(arg1, arg2, arg3){
    var callback;
    var ErrorCallback;
    var CbObj;
    if (this.temporarySCb) {
        category_cb = this.temporarySCb;
        ErrorCallback = this.temporaryECb;
        this.temporarySCb = null;
        this.temporaryECb = null;
    }
    else {
        CbObj = glob_obj.getFromArray(arg1);
        if (CbObj) {
            callback = CbObj.success_cb;
            ErrorCallback = CbObj.error_cb;
        }
        
        else {
            alert("Landmarks: __sp_landmarks_category_delete_cb: Callback not found ");
            return;
        }
    }
    
    //if there is an error invoke user supplied error callback
    if (arg2 == 4 || arg3.ErrorCode) { //indicates an error
        var scbErrCode = convertFromPS2JS(arg3.ErrorCode);
        var erroObject = new DeviceAPIError(scbErrCode, arg3.ErrorMessage);
        if (ErrorCallback) {
            ErrorCallback(erroObject);
        }
    }
    else {
        //in case of success invoke user supplied scb
        callback();
    }
    glob_obj.removeFromArray(arg1);
}

function __sp_landmarks_category_delete(callback, categoryId, ErrorCallback){
    try {
        var error = new DeviceAPIError(0, "dummy");
        var isErrCB = true;//indicates a valid errocalback has been supplied
        if (callback === undefined) {
            throw new DeviceAPIError(error.MISSING_ARG_ERR, 'SucessCallback is missing');
        }
        else {
            if (((callback === null) ||
            (callback === "")) &&
            (typeof(callback) != "number")) {
                throw new DeviceAPIError(error.MISSING_ARG_ERR, 'SucessCallback is missing');
            }
            else 
                if (typeof(callback) != 'function') {
                    throw new DeviceAPIError(error.INVALID_ARG_ERR, 'invalid SucessCallback argument');
                }
        }
        if (categoryId === undefined || categoryId === null) {
            throw new DeviceAPIError(error.MISSING_ARG_ERR, 'categoryId is missing');
        }
        else 
            if (typeof(categoryId) !== "string") {
                throw new DeviceAPIError(error.INVALID_ARG_ERR, 'invalid categoryId argument');
            }
        
        if ((ErrorCallback != undefined)) {
            if ((!ErrorCallback) &&
            (typeof(ErrorCallback) != "number")) {
                isErrCB = false;
            }
            else 
                if ((typeof(ErrorCallback) != 'function')) {
                    throw new DeviceAPIError(error.INVALID_ARG_ERR, 'invalid ErrorCallback callback');
                }
            
        }
        else {
            isErrCB = false;
        }
        
        
        var criteria = new Object();
        modifyObjectBaseProp(criteria);
        criteria.Type = "Category";
        criteria.Data = new Object();
        modifyObjectBaseProp(criteria.Data);
        criteria.Data.id = categoryId;
		
		this.temporarySCb = callback;
        this.temporaryECb = ErrorCallback;
		
        var rval = this.so.IDataSource.Delete(criteria, this.deleteCategoryCb);
        if (rval.TransactionID) {
            glob_obj.addToGlobalArray(rval.TransactionID, callback, ErrorCallback);
        }
        
        if (rval.ErrorCode != 0) {
            switch (rval.ErrorCode) {
                case err_missing_argument:
                    throw new DeviceAPIError(error.MISSING_ARG_ERR, rval.ErrorMessage);
                    break;
                case err_bad_argument:
                    throw new DeviceAPIError(error.INVALID_ARG_ERR, rval.ErrorMessage);
                    break;
                case err_ServiceNotSupported:
                    throw new DeviceAPIError(error.NOT_SUPPORTED_ERR, rval.ErrorMessage);
                    break;
                case err_InvalidService_Argument:
                    throw new DeviceAPIError(error.INVALID_ARG_ERR, rval.ErrorMessage);
                    break;
                default:
                    throw new DeviceAPIError(-101, "unknown error message");
            }
        }
        return rval.TransactionID;
    } 
    catch (e) {
        throw e;
    }
}

function __sp_landmarks_getList_cb(arg1, arg2, arg3){
    var iter = null;
    var callback;
    var ErrorCallback;
    var CbObj;
    if (this.temporarySCb) {
        category_cb = this.temporarySCb;
        ErrorCallback = this.temporaryECb;
        this.temporarySCb = null;
        this.temporaryECb = null;
    }
    else {
        CbObj = glob_obj.getFromArray(arg1);
        if (CbObj) {
            callback = CbObj.success_cb;
            ErrorCallback = CbObj.error_cb;
        }
        
        else {
            alert("Landmarks: __sp_landmarks_getList_cb: Callback not found ");
            return;
        }
    }
    
    //if there is an error invoke user supplied error callback
    if (arg3.ErrorCode || (arg2 == 4)) { //indicates an error
        var scbErrCode = convertFromPS2JS(arg3.ErrorCode);
        var erroObject = new DeviceAPIError(scbErrCode, arg3.ErrorMessage);
        if (ErrorCallback) {
            ErrorCallback(erroObject);
        }
    }
    else {
        if (arg3.ReturnValue) {
            iter = new __sp_landmarks_iterator(arg3.ReturnValue);
        }
        //in case of success invoke user supplied scb
        callback(iter);
    }
    glob_obj.removeFromArray(arg1);
}

function __sp_landmarks_getList(callback, matchObject, ErrorCallback){
    try {
        var error = new DeviceAPIError(0, "dummy");
        //test variable
        var isErrCB = false;//indicates a valid errocalback has not been supplied
        var isNameSearch = false;
        var isDefaultvalue = false;
        
        if ((callback === undefined) ||
        (callback === null) ||
        (callback === "")) {
        
            throw new DeviceAPIError(error.MISSING_ARG_ERR, 'SucessCallback is missing');
        }
        if (typeof(callback) != 'function') {
            throw new DeviceAPIError(error.INVALID_ARG_ERR, 'invalid SucessCallback argument');
        }
        if ((ErrorCallback !== undefined) &&
        (ErrorCallback !== "") &&
        (ErrorCallback !== null)) {
        
            if ((typeof(ErrorCallback) != 'function')) {
                throw new DeviceAPIError(error.INVALID_ARG_ERR, 'invalid error callback');
            }
            else {
                isErrCB = true;
            }
            
        }
        var criteria = new Object();
        modifyObjectBaseProp(criteria);
        criteria.Type = "Landmark";
        criteria.Filter = new Object();
        if ((matchObject === undefined) ||
        (matchObject === null) ||
        (matchObject === "")) {
        
            criteria.Filter.dummy = "dummy";
        }
        else 
            if (typeof(matchObject) == "string") {
            
                criteria.Filter.LandmarkName = matchObject;
            }
            else 
                if (typeof(matchObject) != "object") {
                    throw new DeviceAPIError(error.INVALID_ARG_ERR, 'invalid match criteria');
                }
                else {
                    if ((matchObject.name !== undefined) &&
                    (matchObject.name !== null) &&
                    (matchObject.name !== "")) 
                        criteria.Filter.LandmarkName = matchObject.name;
                    if ((matchObject.description !== undefined) &&
                    (matchObject.description !== null) &&
                    (matchObject.description !== "")) 
                        criteria.Filter.LandmarkDesc = matchObject.description;
                    
                    if ((matchObject.categoryId !== undefined) &&
                    (matchObject.categoryId !== null) &&
                    (matchObject.categoryId !== "")) 
                        criteria.Filter.categoryId = matchObject.categoryId;
                    
                    if ((matchObject.position !== undefined) &&
                    (matchObject.position !== null) &&
                    (matchObject.position !== "")) {
                        if (typeof(matchObject.position) != "object") 
                            throw new DeviceAPIError(error.INVALID_ARG_ERR, 'position must be an object');
                        else {
                            criteria.Filter.LandmarkPosition = new __sp_landmark_position_obj(matchObject.position);
                        }
                    }
                    if ((matchObject.coverageRadiusUsed !== undefined) &&
                    (matchObject.coverageRadiusUsed !== null) &&
                    (matchObject.coverageRadiusUsed !== "")) {
                        if (typeof(matchObject.coverageRadiusUsed) != "number") 
                            throw new DeviceAPIError(error.INVALID_ARG_ERR, "coverageRadiusUsed should be number");
                        else 
                            criteria.Filter.CoverageRadiusOption = matchObject.coverageRadiusUsed;
                    }
                    
                    if ((matchObject.searchRadius !== undefined) &&
                    (matchObject.searchRadius !== null) &&
                    (matchObject.searchRadius !== "")) {
                        if (typeof(matchObject.searchRadius) != "number") 
                            throw new DeviceAPIError(error.INVALID_ARG_ERR, "searchRadius should be number");
                        else 
                            criteria.Filter.MaximumDistance = matchObject.searchRadius;
                        
                    }
                    
                    if ((matchObject.area !== undefined) &&
                    (matchObject.area !== null) &&
                    (matchObject.area !== "")) {
                        if (typeof(matchObject.area) != 'object') 
                            throw new DeviceAPIError(error.INVALID_ARG_ERR, 'area must be an object');
                        else {
                            criteria.Filter.BoundedArea = new __sp_landmark_bounded_area_obj(matchObject.area);
                        }
                    }
                }
        //alert("calling getlist");        
		
		this.temporarySCb = callback;
        this.temporaryECb = ErrorCallback;
		   
        var rval = this.so.IDataSource.GetList(criteria, this.getLandmarksCb);
        if (rval.TransactionID) {
            glob_obj.addToGlobalArray(rval.TransactionID, callback, ErrorCallback);
        }
        
        if (rval.ErrorCode != 0) {
            switch (rval.ErrorCode) {
                case 1003:
                    throw new DeviceAPIError(error.MISSING_ARG_ERR, rval.ErrorMessage);
                    break;
                case 1002:
                    throw new DeviceAPIError(error.INVALID_ARG_ERR, rval.ErrorMessage);
                    break;
                case 1004:
                    throw new DeviceAPIError(error.NOT_SUPPORTED_ERR, rval.ErrorMessage);
                    break;
                case 1000:
                    throw new DeviceAPIError(error.INVALID_ARG_ERR, rval.ErrorMessage);
                    break;
                default:
                    throw new DeviceAPIError(-101, "unknown error message");
                    
            }
            
        }
        return rval.TransactionID;
        
        
    } 
    catch (e) {
        //alert("exception from here");
        throw e;
    }
}

function __sp_landmarks_import_cb(arg1, arg2, arg3){
    //if there is an error invoke user supplied error callback
    var iter = null;
    var callback;
    var ErrorCallback;
    var CbObj;
    if (this.temporarySCb) {
        category_cb = this.temporarySCb;
        ErrorCallback = this.temporaryECb;
        this.temporarySCb = null;
        this.temporaryECb = null;
    }
    else {
        CbObj = glob_obj.getFromArray(arg1);
        if (CbObj) {
            callback = CbObj.success_cb;
            ErrorCallback = CbObj.error_cb;
        }
        
        else {
            alert("Landmarks: __sp_landmarks_import_cb: Callback not found ");
            return;
        }
    }
    
    //if there is an error invoke user supplied error callback
    if (arg2 == 4 || arg3.ErrorCode) { //indicates an error
        var scbErrCode = convertFromPS2JS(arg3.ErrorCode);
        var erroObject = new DeviceAPIError(scbErrCode, arg3.ErrorMessage);
        if (ErrorCallback) {
            ErrorCallback(erroObject);
        }
    }
    else {
        if (arg3.ReturnValue) {
            iter = new __sp_landmarks_iterator(arg3.ReturnValue);
        }
        
        //in case of success invoke user supplied scb
        callback(iter);
    }
    glob_obj.removeFromArray(arg1);
}

function __sp_landmarks_import(callback, sourceFileUri, mimetype, ErrorCallback){
    try {
        var error = new DeviceAPIError(0, "dummy");
        var isErrCB = true;//indicates a valid errocalback has been supplied
        if (callback === undefined) {
            throw new DeviceAPIError(error.MISSING_ARG_ERR, 'LandmarksItrCallback is missing');
        }
        else {
            if (((callback === null) ||
            (callback === "")) &&
            (typeof(callback) != "number")) {
                throw new DeviceAPIError(error.MISSING_ARG_ERR, 'LandmarksItrCallback is missing');
            }
            else 
                if (typeof(callback) != 'function') {
                    throw new DeviceAPIError(error.INVALID_ARG_ERR, 'invalid LandmarksItrCallback argument');
                }
        }
        
        if (sourceFileUri === undefined || sourceFileUri === null) {
            throw new DeviceAPIError(error.MISSING_ARG_ERR, 'sourceFileUri is missing');
        }
        else 
            if (typeof(sourceFileUri) !== "string") {
                throw new DeviceAPIError(error.INVALID_ARG_ERR, 'invalid sourceFileUri argument');
            }
        
        if (mimetype === undefined || mimetype === null) {
            throw new DeviceAPIError(error.MISSING_ARG_ERR, 'mimetype is missing');
        }
        else 
            if (typeof(mimetype) !== "string") {
                throw new DeviceAPIError(error.INVALID_ARG_ERR, 'invalid mimetype argument');
            }
        
        if ((ErrorCallback != undefined)) {
            if ((!ErrorCallback) &&
            (typeof(ErrorCallback) != "number")) {
                isErrCB = false;
            }
            else 
                if ((typeof(ErrorCallback) != 'function')) {
                    throw new DeviceAPIError(error.INVALID_ARG_ERR, 'invalid ErrorCallback callback');
                }
            
        }
        else {
            isErrCB = false;
        }
        
        
        
        var criteria = new Object();
        modifyObjectBaseProp(criteria);
        criteria.Type = "Landmark";
        criteria.Data = new Object();
        modifyObjectBaseProp(criteria.Data);
        //replace all '/' to '\' and remove file:// or file:///
        if (sourceFileUri.slice(0, 7) == "file://") {
            sourceFileUri = sourceFileUri.slice(7);
        }
        else 
            if (sourceFileUri.slice(0, 8) == "file:///") {
                sourceFileUri = sourceFileUri.slice(8);
            }
            else {
                throw new DeviceAPIError(error.INVALID_ARG_ERR, "sourceFileUri is not in URI format");
            }
        while (sourceFileUri.search("/") != -1) {
            sourceFileUri = sourceFileUri.replace("/", "\\");
        }
        criteria.Data.SourceFile = sourceFileUri;
        criteria.Data.MimeType = mimetype;
		
		this.temporarySCb = callback;
        this.temporaryECb = ErrorCallback;
		
        var rval = this.so.IDataSource.Import(criteria, this.importLandmarksCb);
        if (rval.TransactionID) {
            glob_obj.addToGlobalArray(rval.TransactionID, callback, ErrorCallback);
        }
        
        if (rval.ErrorCode != 0) {
            switch (rval.ErrorCode) {
                case err_missing_argument:
                    throw new DeviceAPIError(error.MISSING_ARG_ERR, rval.ErrorMessage);
                    break;
                case err_bad_argument:
                    throw new DeviceAPIError(error.INVALID_ARG_ERR, rval.ErrorMessage);
                    break;
                case err_ServiceNotSupported:
                    throw new DeviceAPIError(error.NOT_SUPPORTED_ERR, rval.ErrorMessage);
                    break;
                case err_InvalidService_Argument:
                    throw new DeviceAPIError(error.INVALID_ARG_ERR, rval.ErrorMessage);
                    break;
                default:
                    throw new DeviceAPIError(-101, "unknown error message");
            }
        }
        return rval.TransactionID;
    } 
    catch (e) {
        throw e;
    }
}

function __sp_landmarks_export_cb(arg1, arg2, arg3){
    var callback;
    var ErrorCallback;
    var CbObj;
    if (this.temporarySCb) {
        category_cb = this.temporarySCb;
        ErrorCallback = this.temporaryECb;
        this.temporarySCb = null;
        this.temporaryECb = null;
    }
    else {
        CbObj = glob_obj.getFromArray(arg1);
        if (CbObj) {
            callback = CbObj.success_cb;
            ErrorCallback = CbObj.error_cb;
        }
        
        else {
            alert("Landmarks: __sp_landmarks_export_cb: Callback not found ");
            return;
        }
    }
    
    //if there is an error invoke user supplied error callback
    //if there is an error invoke user supplied error callback
    if (arg2 == 4 || arg3.ErrorCode) { //indicates an error
        var scbErrCode = convertFromPS2JS(arg3.ErrorCode);
        var erroObject = new DeviceAPIError(scbErrCode, arg3.ErrorMessage);
        if (ErrorCallback) {
            ErrorCallback(erroObject);
        }
    }
    else {
        //in case of success invoke user supplied scb
        callback();
    }
    
    glob_obj.removeFromArray(arg1);
}

function __sp_landmarks_export(callback, landmarkIdList, destFileUri, mimetype, ErrorCallback){
    try {
        var error = new DeviceAPIError(0, "dummy");
        var isErrCB = true;//indicates a valid errocalback has been supplied
        if (callback === undefined) {
            throw new DeviceAPIError(error.MISSING_ARG_ERR, 'SuccessCallback is missing');
        }
        else {
            if (((callback === null) ||
            (callback === "")) &&
            (typeof(callback) != "number")) {
                throw new DeviceAPIError(error.MISSING_ARG_ERR, 'SuccessCallback is missing');
            }
            else 
                if (typeof(callback) != 'function') {
                    throw new DeviceAPIError(error.INVALID_ARG_ERR, 'invalid SuccessCallback argument');
                }
        }
        
        if (landmarkIdList === undefined || landmarkIdList === null) {
            throw new DeviceAPIError(error.MISSING_ARG_ERR, 'landmarkIdList is missing');
        }
        else 
            if (typeof(landmarkIdList) !== "object") {
                throw new DeviceAPIError(error.INVALID_ARG_ERR, 'invalid landmarkIdList argument');
            }
        
        if (destFileUri === undefined || destFileUri === null) {
            throw new DeviceAPIError(error.MISSING_ARG_ERR, 'destFileUri is missing');
        }
        else 
            if (typeof(destFileUri) !== "string") {
                throw new DeviceAPIError(error.INVALID_ARG_ERR, 'invalid destFileUri argument');
            }
        
        if (mimetype === undefined || mimetype === null) {
            throw new DeviceAPIError(error.MISSING_ARG_ERR, 'mimetype is missing');
        }
        else 
            if (typeof(mimetype) !== "string") {
                throw new DeviceAPIError(error.INVALID_ARG_ERR, 'invalid mimetype argument');
            }
        
        if ((ErrorCallback != undefined)) {
            if ((!ErrorCallback) &&
            (typeof(ErrorCallback) != "number")) {
                isErrCB = false;
            }
            else 
                if ((typeof(ErrorCallback) != 'function')) {
                    throw new DeviceAPIError(error.INVALID_ARG_ERR, 'invalid ErrorCallback callback');
                }
            
        }
        else {
            isErrCB = false;
        }
        
        
        var criteria = new Object();
        modifyObjectBaseProp(criteria);
        criteria.Type = "Landmark";
        criteria.Data = new Object();
        modifyObjectBaseProp(criteria.Data);
        //replace all '/' to '\' and remove file:// or file:///
        if (destFileUri.slice(0, 7) == "file://") {
            destFileUri = destFileUri.slice(7);
        }
        else 
            if (destFileUri.slice(0, 8) == "file:///") {
                destFileUri = destFileUri.slice(8);
            }
            else {
                throw new DeviceAPIError(error.INVALID_ARG_ERR, "destFileUri is not in URI format");
            }
        while (destFileUri.search("/") != -1) {
            destFileUri = destFileUri.replace("/", "\\");
        }
        criteria.Data.DestinationFile = destFileUri;
        criteria.Data.IdList = landmarkIdList;
        criteria.Data.MimeType = mimetype;
		
		this.temporarySCb = callback;
        this.temporaryECb = ErrorCallback;
		
        var rval = this.so.IDataSource.Export(criteria, this.exportLandmarksCb);
        if (rval.TransactionID) {
            glob_obj.addToGlobalArray(rval.TransactionID, callback, ErrorCallback);
        }
        if (rval.ErrorCode != 0) {
            switch (rval.ErrorCode) {
                case err_missing_argument:
                    throw new DeviceAPIError(error.MISSING_ARG_ERR, rval.ErrorMessage);
                    break;
                case err_bad_argument:
                    throw new DeviceAPIError(error.INVALID_ARG_ERR, rval.ErrorMessage);
                    break;
                case err_ServiceNotSupported:
                    throw new DeviceAPIError(error.NOT_SUPPORTED_ERR, rval.ErrorMessage);
                    break;
                case err_InvalidService_Argument:
                    throw new DeviceAPIError(error.INVALID_ARG_ERR, rval.ErrorMessage);
                    break;
                default:
                    throw new DeviceAPIError(-101, "unknown error message");
            }
        }
        return rval.TransactionID;
    } 
    catch (e) {
        throw e;
    }
}

function __sp_landmarks_organize_cb(arg1, arg2, arg3){
    var callback;
    var ErrorCallback;
	if (this.temporarySCb) {
        category_cb = this.temporarySCb;
        ErrorCallback = this.temporaryECb;
        this.temporarySCb = null;
        this.temporaryECb = null;
    }
    else {
        CbObj = glob_obj.getFromArray(arg1);
        if (CbObj) {
            callback = CbObj.success_cb;
            ErrorCallback = CbObj.error_cb;
        }
        
        else {
            alert("Landmarks: __sp_landmarks_organize_cb: Callback not found ");
            return;
        }
    }
    
    //if there is an error invoke user supplied error callback
    if (arg2 == 4 || arg3.ErrorCode) { //indicates an error
        var scbErrCode = convertFromPS2JS(arg3.ErrorCode);
        var erroObject = new DeviceAPIError(scbErrCode, arg3.ErrorMessage);
        if (ErrorCallback) {
            ErrorCallback(erroObject);
        }
    }
    else {
        //in case of success invoke user supplied scb
        callback();
    }
    glob_obj.removeFromArray(arg1);
}

function __sp_landmarks_organize(callback, landmarkIdList, categoryId, associate, ErrorCallback){
    try {
        var error = new DeviceAPIError(0, "dummy");
        var isErrCB = true;//indicates a valid errocalback has been supplied
        if (callback === undefined) {
            throw new DeviceAPIError(error.MISSING_ARG_ERR, 'SuccessCallback is missing');
        }
        else {
            if (((callback === null) ||
            (callback === "")) &&
            (typeof(callback) != "number")) {
                throw new DeviceAPIError(error.MISSING_ARG_ERR, 'SuccessCallback is missing');
            }
            else 
                if (typeof(callback) != 'function') {
                    throw new DeviceAPIError(error.INVALID_ARG_ERR, 'invalid SuccessCallback argument');
                }
        }
        
        if (landmarkIdList === undefined || landmarkIdList === null) {
            throw new DeviceAPIError(error.MISSING_ARG_ERR, 'landmarkIdList is missing');
        }
        else 
            if (typeof(landmarkIdList) !== "object") {
                throw new DeviceAPIError(error.INVALID_ARG_ERR, 'invalid LandmarkItem argument');
            }
        
        if (categoryId === undefined || categoryId === null) {
            throw new DeviceAPIError(error.MISSING_ARG_ERR, 'categoryId is missing');
        }
        else 
            if (typeof(categoryId) !== "string") {
                throw new DeviceAPIError(error.INVALID_ARG_ERR, 'invalid categoryId argument');
            }
        
        if (associate === undefined || associate === null) {
            associate = true;
        }
        else 
            if (typeof(associate) !== "boolean") {
                throw new DeviceAPIError(error.INVALID_ARG_ERR, 'invalid associate argument');
            }
        
        if ((ErrorCallback != undefined)) {
            if ((!ErrorCallback) &&
            (typeof(ErrorCallback) != "number")) {
                isErrCB = false;
            }
            else 
                if ((typeof(ErrorCallback) != 'function')) {
                    throw new DeviceAPIError(error.INVALID_ARG_ERR, 'invalid ErrorCallback callback');
                }
            
        }
        else {
            isErrCB = false;
        }
        
        
        
        var criteria = new Object();
        modifyObjectBaseProp(criteria);
        criteria.Type = "Landmark";
        criteria.Data = new Object();
        modifyObjectBaseProp(criteria.Data);
        criteria.Data.id = categoryId;
        criteria.Data.IdList = landmarkIdList;
        if (associate) 
            criteria.OperationType = "Associate";
        else 
            criteria.OperationType = "Disassociate";
		
		this.temporarySCb = callback;
        this.temporaryECb = ErrorCallback;
		
        var rval = this.so.IDataSource.Organise(criteria, this.organizeLandmarksCb);
        if (rval.TransactionID) {
            glob_obj.addToGlobalArray(rval.TransactionID, callback, ErrorCallback);
        }
        
        if (rval.ErrorCode != 0) {
            switch (rval.ErrorCode) {
                case err_missing_argument:
                    throw new DeviceAPIError(error.MISSING_ARG_ERR, rval.ErrorMessage);
                    break;
                case err_bad_argument:
                    throw new DeviceAPIError(error.INVALID_ARG_ERR, rval.ErrorMessage);
                    break;
                case err_ServiceNotSupported:
                    throw new DeviceAPIError(error.NOT_SUPPORTED_ERR, rval.ErrorMessage);
                    break;
                case err_InvalidService_Argument:
                    throw new DeviceAPIError(error.INVALID_ARG_ERR, rval.ErrorMessage);
                    break;
                default:
                    throw new DeviceAPIError(-101, "unknown error message");
            }
        }
        return rval.TransactionID;
    } 
    catch (e) {
        throw e;
    }
}

function __sp_landmarks_cancel(transactionId){
    try {
        var error = new DeviceAPIError(0, "dummy");
        if ((transactionId === undefined) ||
        (transactionId === null) ||
        (transactionId === "")) {
            throw new DeviceAPIError(error.MISSING_ARG_ERR, 'transactionId is missing');
        }
        
        if (typeof(transactionId) != "number") {
            throw new DeviceAPIError(error.INVALID_ARG_ERR, 'invalid transactionId argument');
        }
        if (transactionId < 0) {
            throw new DeviceAPIError(error.DATA_NOT_FOUND_ERR, 'non-existent transactionId');
        }
        
        var criteria = new Object();
        modifyObjectBaseProp(criteria);
        criteria.TransactionID = transactionId;
        var rval = this.so.IDataSource.Cancel(criteria);
        if (rval.ErrorCode != 0) {
            switch (rval.ErrorCode) {
                case err_missing_argument:
                    throw new DeviceAPIError(error.MISSING_ARG_ERR, rval.ErrorMessage);
                    break;
                case err_bad_argument:
                    throw new DeviceAPIError(error.INVALID_ARG_ERR, rval.ErrorMessage);
                    break;
                case err_ServiceNotSupported:
                    throw new DeviceAPIError(error.NOT_SUPPORTED_ERR, rval.ErrorMessage);
                    break;
                case err_InvalidService_Argument:
                    throw new DeviceAPIError(error.INVALID_ARG_ERR, rval.ErrorMessage);
                    break;
                default:
                    throw new DeviceAPIError(-101, "unknown error message");
            }
        }
    } 
    catch (e) {
        throw e;
    }
}
