Landmarks API Specification

Contents

1 Overview

The Landmarks API enables client applications to manage landmarks in a consistent way. For example, if a landmark is received in an email and the user chooses to store the landmark, the landmark is instantly available for a map application.


API categorypublic
API typec++
API librarieseposlandmarks.lib
Location/sf/mw/locationsrv/locsrv_pub/landmarks_api
Buildfiles/sf/mw/locationsrv/locsrv_pub/landmarks_api/group/bld.inf


1.1 Description

The Landmarks API does not provide search functionality. Search is provided by Landmarks Search API.

Landmarks API is mainly targeted for end-user applications. It allows clients to access landmark databases and read and edit their content.

This API uses position classes and generic position field IDs from Location Acquisition API to define the location of a landmark.

The Landmarks API enables defining landmark categories. Landmark categories are labels, which can be assigned to a landmark to define the type of the landmark. For instance, a landmark of some restaurant could be a assigned with category "Restaurants".

The Landmarks API provides an interface for listening to database events. Clients can be notified when a landmark database is edited.

The Landmarks API also offers methods for exporting landmark data to and importing from exchange format, which enables exchanging landmarks between terminals.

As a part of the exchange format support,it provides encoding of a landmark object into a URL and parsing of a URL and decoding it into a landmark object.

The logical type of the API is Library API. Technically it is method-call interface. Landmarks API loads the implementation at run time but the implementation consists only of local objects.

1.2 Changes

The Landmarks API is introduced in Symbian OS, S60 3.0.

Support for importing GPX content is introduced in Symbian OS, S60 5.0.

Support for importing KML/KMZ content is introduced in Symbian OS, S60 5.0.

Support for URL encoding and decoding is introduced in Symbian OS, S60 5.2.

Support for m.ovi.me format for URL encoding and decoding is introduced in Symbian OS, S60 5.3

1.3 Use Cases

The following are the main use cases of the Landmarks API:

1.4 Class Structure

Summary of API classes and header files
ClassesFiles
CPosLandmark /epoc32/include/mw/EPos_CPosLandmark.h CPosLandmarkCategory /epoc32/include/mw/EPos_CPosLandmarkCategory.h CPosLandmarkDatabase /epoc32/include/mw/EPos_CPosLandmarkDatabase.h CPosLandmarkDatabaseExtended /epoc32/include/mw/epos_cposlandmarkdatabaseextended.h CPosLandmarkEncoder /epoc32/include/mw/EPos_CPosLandmarkEncoder.h CPosLandmarkParser /epoc32/include/mw/EPos_CPosLandmarkParser.h CPosLmCategoryManager /epoc32/include/mw/EPos_CPosLmCategoryManager.h CPosLmItemIterator /epoc32/include/mw/EPos_CPosLmItemIterator.h CPosLmOperation /epoc32/include/mw/EPos_CPosLmOperation.h CPosLmPartialReadParameters /epoc32/include/mw/EPos_CPosLmPartialReadParameters.h PosLandmarkSerialization /epoc32/include/mw/epos_poslandmarkserialization.h PosLmCategorySerialization /epoc32/include/mw/epos_poslmcategoryserialization.h TMapImageAttributes /epoc32/include/mw/EPos_TMapImageAttributes.h TPosLmSortPref /epoc32/include/mw/EPos_TPosLmSortPref.h No classes/epoc32/include/mw/EPos_CPosLmOperation.inl, /epoc32/include/mw/EPos_Landmarks.h

The following subchapters describe the Landmarks API class structure. UML diagrams are used to present the classes and their dependencies. Note: The UML diagrams do not show all the available methods, and some of or all of the method parameters may be left out.

1.4.1 Database access

Landmarks are stored in databases. A client accesses landmark databases through the CPosLandmarkDatabase class. Each instance of CPosLandmarkDatabase is a handle to exactly one landmark database. All operations upon a landmark database are performed through instances of CPosLandmarkDatabase .

CPosLandmark represents the content of a landmark, for example the landmark name and landmark position. This class is used in CPosLandmarkDatabase methods to let the client read or edit a landmark in the database.

A landmark stored in a database is referenced by an ID ( TPosLmItemId ), which is unique within the database. To access a landmark through CPosLandmarkDatabase, the client must specify the ID of the landmark.

It is common that a client needs to retrieve a set of landmarks, for instance when listing the content of a landmark database. In Landmarks API, a landmark set is accessed by using an iterator object. CPosLmItemIterator lets the client retrieve the IDs of the iterated landmarks. The client can iterate all the landmarks in a database by retrieving a CPosLmItemIterator instance from CPosLandmarkDatabase .

Clients may require retrieving landmarks in a certain sort order. In Landmarks API, the client specifies sort preference by using a TPosLmSortPref object.

If a client is not interested in full landmark information, it can perform a partial read. For instance, the client may only be interested in the name of the landmark. By using a CPosLmPartialReadParameters object, the client can specify which landmark information is of interest.

Landmark database access classes
Landmark database access classes

1.4.2 Category management

A landmark database can contain landmark categories. To access categories in the database, the client must create a CPosLmCategoryManager object connected to the database. Through this object, the client can retrieve information about the categories in the database or edit the category content.

CPosLandmarkCategory represents information about a landmark category. It is used in the CPosLmCategoryManager interface to pass category information from/to the client.

A landmark category stored in a database is referenced by an ID ( TPosLmItemId ), which is unique within the database. To refer to a landmark category, the client specifies the ID of the category. Note: The same type, TPosLmItemId , is used to refer to landmarks and categories. It is possible that a landmark and a category have the same ID.

Categories can be iterated, just like landmarks. CPosLmItemIterator is used for iterating both landmark and category sets. Note: The iterator is never used to iterate a mixed set of landmarks and categories.

Landmark category management classes
Landmark category management classes

1.4.3 Database events

A client can listen to events from landmark databases. To listen to the next event, the client calls CPosLandmarkDatabase::NotifyDatabaseEvent() . The client passes a TRequestStatus, which will be completed when an event is detected. When an event has been retrieved, the client must renew the NotifyDatabaseEvent() request to listen to further events.

Classes for listening to landmark database events
Classes for listening to landmark database events

1.4.4 Exchange operations

A client can exchange landmark data with another party by using the import and export functionality. If a client has received a file or buffer containing landmark data and the client is connected to a landmark database, the client can use the Landmarks API to import landmarks to the landmark database. To import landmarks, the client must create an instance of the CPosLandmarkParser class.

The client can also use the Landmarks API to export landmarks from the landmark database. This will result in a file or buffer containing the landmark data. To export landmarks, the client must create an instance of the CPosLandmarkEncoder class.

The exchange of landmarks is also supported via a URL.The client can encode a landmark object into a URL containing all the location inforamtion. To encode a landmark to a URL, the client must create an instance of the CPosLandmarkEncoder class.

Also the client can parse a given URL to decode the location information present in the URL and create a landmark object. To parse a URL, the client must create an instance of the CPosLandmarkParser class.

Classes for handling exchange of landmark content
Classes for handling exchange of landmark content

1.4.5 Incremental operations

Some operations in the Landmarks API can potentially take a long time. These operations can therefore be run incrementally. The client retrieves a CPosLmOperation object, which can either be run incrementally or all at once.

If the operation is run incrementally, the client can read the operation progress between incremental steps.

Classes for handling incremental operations in Landmarks API
Classes for handling incremental operations in Landmarks API

1.4.6 Serialization support

A client can pack a landmark or a landmark category object into a buffer for further serialization. This can be used e.g. for sending data over process boundaries. On the receiving side packed objects can be unpacked from buffer. The PosLandmarkSerialization class contains static methods PackL() and UnpackL() for packing and unpacking CPosLandmark instances. PosLmCategorySerialization class contains appropriate methods for packing and unpacking CPosLandmarkCategory instances.

This feature is added in Symbian OS, S60 3.1.

Classes for packing landmark and categories into buffer and unpacking back
Classes for packing landmark and categories into buffer and unpacking back

1.5 Landmarks

A landmark is a location with a name and it may also contain other data, such as description, icon and address details. Landmarks are organized in landmark databases, which reside on terminal or may be remote. Client can read landmarks from a database, add new, modify and remove existing landmarks.

1.5.1 Landmark attributes

A landmark can contain the following attributes:

Landmark attributes
Landmark attribute Description
Item ID This ID is a reference to the landmark in a landmark database. It is locally unique within one database.
Landmark name The name of the landmark can contain a maximum of 255 characters. The landmark name does not have to be unique in a database.
Position The WGS84 coordinate for the landmark.
Coverage radius Coverage radius is set if the landmark is big, for example, a city. It defines the size of the area, which the landmark represents. The coverage area is specified in meters.
Category info The categories related to the landmark, such as restaurants, gas stations and grocery stores.
Icon A reference to an icon in an icon file which can be used to symbolize the landmark in a UI. An icon mask can also be specified from the same icon file.
Description A textual description of the landmark, for example, "Chinese restaurant. Nice atmosphere and the service is superb". The description has a maximum length of 4095 characters.
Position fields Generic position fields as defined by Location Acquisition API . A position field can, for instance, be the street address of the landmark or the name of the city where the landmark is found. Landmarks API only supports

text position fields. If the client wants to store a non-text field, the value must first be converted to a textual representation. A landmark can contain any number of position fields.

Place ID The unique id specified by the client for any location.
TimeStamp The time associated with a landmark.The format that is used for timestamp is YYYYMMDD:HHMMSS.MMMMMM wherein the date field is mandatory.Validations for this field are the same as in TTime object.

1.6 Landmark categories

A landmark may be assigned to one or many categories (or none at all). Categories help to classify landmarks, group them, enable finer search criteria etc. Landmark categories are also stored in landmark databases.

1.6.1 Local and global landmark categories

Landmark categories may be local or global. Local categories are defined by the user. They are stored in a database and cannot be reused by multiple databases unless the user creates the same category in several databases.

Global categories are predefined in the terminal and may be reused in multiple databases and multiple phones and on different platforms. The Global Category ID uniquely specifies a global category, which makes global categories localizable. The names and icons of global categories are predefined in a resource file and the category name is automatically changed in the database when it is open if the terminal language changes since the last usage of the database. Note: The global category name will not be changed to the newly selected language if the user has previously renamed this category.

The predefined global landmark categories are listed in the following table:

Predefined global landmark categories
ID Name Purpose (examples of landmarks)
3000 Accommodation Hotel, Camping site
6000 Business Bank, Factory, Office
9000 Communication Internet Access Point, Public Telephone, Wireless LAN Hot Spot
12000 Educational institute School, College
15000 Entertainment Amusement park, Cinema, Concert hall, Night club
18000 Food & Beverage Fast food, Restaurant, Café, Bar
21000 Geographical area City, City center, Town
24000 Outdoor activities Camping site, Fishing place, Hunting, National park, Playground
27000 People My home, My friend's home, Father's summer cottage, Child's school
30000 Public service Tourist information office, Government office, Library, Post office,

Hospital, Police

33000 Religious places Church, Mosque
36000 Shopping Market Place, Pharmacy, Shop, Shopping Center
39000 Sightseeing Monument, Mountain top, Museum
42000 Sports Bowling, Golf course, Ice hockey hall, Stadium
45000 Transport Airport, Bus stop, Harbour, Railway Station, Rest area

Other IDs are reserved for future use. Names are given only for reference purposes, localized names are defined for all languages supported by the platform.

1.6.2 Category attributes

A landmark category contains the following attributes:

Landmark category attributes
Category attribute Description
Item ID This ID is a reference to the category in a landmark database. It is

locally unique within one database.

Category name The name of the category can contain a maximum of 124 characters. The

category name must be unique in a database. If the client tries to change the name of a category and that name is already occupied by another category, the update fails.

Global category ID This ID refers to a category in a globally defined category set.
Icon A reference to an icon in an icon file, which can be used to symbolize

the category in a UI. An icon mask can also be specified from the same icon file.

1.7 Landmark URL format specification

The URL that is required to be encoded or parsed should be specified according to the following format.

1.7.1 Notations Used

* - 0 or more occurences

1* - 1 or more occurrences

() - optional contents

' ' - literals

X*Y - between X & Y occurences ( For Eg : 2*5 - between 2 & 5 occurences )

1.7.2 Grammar Definition

url -> ( protocol '://' ) hostname '/?' location *( '??' location )

protocol -> 'http' | 'https'

hostname -> ('www.') 'maps.ovi.com'

location -> locationparams *( '&' locationparams )

locationparams -> placeid | latitude | longitude | name | street | housenumber | postalcode | city | state | country | telephone | web | category | description | positionaccuracy | altitude | altitudeaccuracy | speed | heading | timestamp

placeid -> 'pid =' placeidvalue

placeidvalue -> 0*255 ( alphanum | escaped )

alphanum -> alpha | digit

alpha -> lowalpha | upalpha

lowalpha -> 'a' | 'b' | 'c' | 'd' | 'e' | 'f' | 'g' | 'h' | 'i' | 'j' | 'k' | 'l' | 'm' | 'n' | 'o' | 'p' | 'q' | 'r' | 's' | 't' | 'u' | 'v' | 'w' | 'x' | 'y' | 'z'

upalpha -> 'A' | 'B' | 'C' | 'D' | 'E' | 'F' | 'G' | 'H' | 'I' | 'J' | 'K' | 'L' | 'M' | 'N' | 'O' | 'P' | 'Q' | 'R' | 'S' | 'T' | 'U' | 'V' | 'W' | 'X' | 'Y' | 'Z'

digit -> '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9'

escaped -> '%' hex hex

hex -> digit | 'a' | 'b' | 'c' | 'd' | 'e' | 'f' | 'A' | 'B' | 'C' | 'D' | 'E' | 'F'

latitude -> 'la =' latitudevalue

latitudevalue -> (sign) 1*2 digit ( '.'0 *6 digit )

sign -> '+' | '-'

longitude -> 'lo =' longitudevalue

longitudevalue -> (sign) 1*3 digit ( '.'0 *6 digit )

name -> 'n =' namevalue

namevalue -> 0*255 ( alphanum | escaped )

street -> 's =' streetvalue

streetvalue -> 0*255 ( alphanum | escaped )

housenumber -> 'sn =' housenumbervalue

housenumbervalue -> 0*255 ( alphanum | escaped )

postalcode -> 'pz =' postalcodevalue

postalcodevalue -> 0*255 ( alphanum | escaped )

city -> 'c =' cityvalue

cityvalue -> 0*255 ( alphanum | escaped )

state -> 'sp =' statevalue

statevalue -> 0*255 ( alphanum | escaped )

country -> 'cr =' countryvalue

countryvalue -> 0*255 ( alphanum | escaped )

telephone -> 't =' telephonevalue

telephonevalue -> 0*255 ( alphanum | escaped )

web -> 'w =' webvalue

webvalue ->0 *255 ( alphanum | escaped )

category -> 'cat =' categoryvalue

categoryvalue -> 0*124 ( alphanum | escaped )

description -> 'd =' descriptionvalue

descriptionvalue -> 0*4095 ( alphanum | escaped )

positionaccuracy -> 'pa =' positionaccuracyvalue

positionaccuracyvalue -> 1* digit ( '.' 0*2digit )

altitude -> 'a=' altitudevalue

altitudevalue -> (sign) 1* digit ( '.' 0*2 digit )

altitudeaccuracy -> 'aa =' altitudeaccuracyvalue

altitudeaccuracyvalue -> 1* digit ( '.'0 *2 digit )

speed -> 'v =' speedvalue

speedvalue -> 1* digit ( '.'0 *2 digit )

heading -> 'h =' headingvalue

headingvalue -> 1* digit ( '.'0 *2 digit )

timestamp -> 'ts =' timestampvalue

timestampvalue -> full-date ':' ( full-time )

full-date -> date-fullyear date-month date-mday

full-time -> time-hour time-minute time-second ('.'time-microseconds)

time-microseconds -> 0*6digit

time-second -> 2digit

time-minute -> 2digit

time-hour -> 2digit

date-mday -> 2digit

date-month -> 2digit

date-fullyear -> 4digit

1.7.3 Restrictions

locationparams Latitude & longitude params are mandatory.Except the category param

( cat ),if there is repetition of any other params then only the value of the first occurrence is considered.The category param is allowed to be repeated in order to support multiple categories to be associated with a single landmark.

latitudevalue Value ranges between -90 and +90,where negative values indicate southern

hemisphere & positive values indicate northern hemisphere.The decimal number is rounded upto 6 decimal digits.

longitudevalue Value ranges between -180 and +180,where negative values indicate western

hemisphere & positive values indicate eastern hemisphere.The decimal number is rounded upto 6 decimal digits.

escaped Only special characters whose Ascii value ( provided in hex ) ranges

between these are to be escaped : 20 - 2F , 3A - 40 , 5B - 60 , 7B - 7E.

positionaccuracyvalue Max value is that of max value of TReal32 .The metric considered here

is metres.The decimal number is rounded upto 2 decimal digits.

altitudevalue Max value is that of max value of TReal32 .The metric considered here

is metres.The decimal number is rounded upto 2 decimal digits.

altitudeaccuracyvalue Max value is that of max value of TReal32 The metric considered here

is metres.The decimal number is rounded upto 2 decimal digits.

speedvalue Max value is that of max value of TReal32 .The metric considered here

is metres/second.The decimal number is rounded upto 2 decimal digits.

headingvalue Max value is that of max value of TReal32 .The metric considered here

is degrees.The decimal number is rounded upto 2 decimal digits.

timestampvalue The full date is mandatory for this field to be encoded/parsed whereas

if the full time is not specified then the default value assumed for time will be 0.

1.7.4 Example URL

The following example URL contains the location information and follows the grammar as defined previously.

"http://www.maps.ovi.com/?la=23.134&lo=120.22&pid=12&n=Placemark&s=HighStreet&sn=1234&pz=123457&c=Bangalore&sp=Karnataka&cr=India&t=9812434125&w=www.weburl.com&cat=MyLandmarks&cat=MyFavouritePlaces&d=Placemark%20from%20Bangalore&pa=12.22&a=43215&v=0&h=0&ts=20090304:121209.123456"

1.8 Landmarks URL Format Specification for m.ovi.me domain

The URL that is required to be encoded or parsed should be specified according to the following format.

1.8.1 Grammar Definition

url -> ( 'http://m.ovi.me/' )location

location -> (encodedlocation | plaintextlocation) *( '&' locationparams )

plaintextlocation -> '?latitude&longitude'

latitude -> 'la=' latitudevalue

latitudevalue -> (sign) 1*2 digit ( '.'0 *6 digit )

sign -> '+' | '-'

longitude -> 'lo=' longitudevalue

longitudevalue -> (sign) 1*3 digit ( '.'0 *6 digit )

encodedlocation -> base64encodedvalue

base64encodedvalue -> alphanum | '-' | '_'

alphanum -> alpha | digit

alpha -> lowalpha | upalpha

lowalpha -> 'a' | 'b' | 'c' | 'd' | 'e' | 'f' | 'g' | 'h' | 'i' | 'j' | 'k' | 'l' | 'm' | 'n' | 'o' | 'p' | 'q' | 'r' | 's' | 't' | 'u' | 'v' | 'w' | 'x' | 'y' | 'z'

upalpha -> 'A' | 'B' | 'C' | 'D' | 'E' | 'F' | 'G' | 'H' | 'I' | 'J' | 'K' | 'L' | 'M' | 'N' | 'O' | 'P' | 'Q' | 'R' | 'S' | 'T' | 'U' | 'V' | 'W' | 'X' | 'Y' | 'Z'

digit -> '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9'

locationparams -> street | housenumber | postalcode | city | state | country | zoomValue | imageHeight | imageWidth | imageFormat | imageQuality | mapScheme | mapRadius | locationUncertainty

street -> 's=' streetvalue

streetvalue -> 0*255 ( alphanum | escaped )

housenumber -> 'n=' housenumbervalue

housenumbervalue -> 0*255 ( alphanum | escaped )

postalcode -> 'zi=' postalcodevalue

postalcodevalue -> 0*255 ( alphanum | escaped )

city -> 'ci=' cityvalue

cityvalue -> 0*255 ( alphanum | escaped )

country -> 'co=' countryvalue

countryvalue -> 0*255 ( alphanum | escaped )

zoomValue -> 'z=' 0*2 (digit)

imageHeight -> 'h=' 0*4 (digit)

imageWidth -> 'w=' 0*4 (digit)

imageFormat -> 'f=' 0*1 (digit)

imageQuality -> 'q=' 0*3 (digit)

mapScheme -> 't=' 0*1 (digit)

mapRadius -> 'r=' 0*2 digit ( '.'0 *6 digit )

locationUncertainty -> 'u=' 0*2 digit ( '.'0 *6 digit )

escaped -> '%' hex hex

hex -> digit | 'a' | 'b' | 'c' | 'd' | 'e' | 'f' | 'A' | 'B' | 'C' | 'D' | 'E' | 'F'

1.8.2 Restrictions

encodedParams Latitude & longitude params are mandatory.
plainTextParams Latitude & longitude params are mandatory.
latitudevalue Value ranges between -90 and +90,where negative values indicate southern

hemisphere & positive values indicate northern hemisphere.The decimal number is rounded upto 6 decimal digits.

longitudevalue Value ranges between -180 and +180,where negative values indicate western

hemisphere & positive values indicate eastern hemisphere.The decimal number is rounded upto 6 decimal digits.

escaped Only special characters whose Ascii value ( provided in hex ) ranges

between these are to be escaped : 20 - 2F , 3A - 40 , 5B - 60 , 7B - 7E.

zoomValue Ranges from 0 to 17
imageHeight Ranges from 0 to 2048 (works only when imageWidth is also specified)
imageWidth Ranges from 0 to 2048 (works only when imageHeight is also specified)
imageFormat Ranges from 0 to 3. 0-PNG, 1-JPEG, 2-GIF, 3-BMP
mapScheme Ranges from 0 to 2. 0-normal.day, 1-hybrid.day, 2-terrain.day
imageQuality Ranges from 0 to 100. Applicable only for JPEG images

1.8.3 Example URL

The following example URLs contains the location information and follows the grammar as defined previously.

Example of Plaintext URL:

http://m.ovi.me/?lo=2.29464&la=48.8580&u=10d&z=10&w=111&h=121&f=2&t=2&co=France&ci=Paris&s=Champ%20de%20Mars&zi=1234567&n=123

Example of Encoded URL:

http://m.ovi.me/BE_Uh_TozbGo&s=E%20Huamen%20Ave%2087&ci=Beijing&co=China

2 Using The API

2.1 Using a landmarks database

To start accessing landmarks in a landmark database, the client only must create an instance of the CPosLandmarkDatabase class. This is accomplished by calling one of the CPosLandmarkDatabase::OpenL() overloads. The default landmark database is opened by calling the overload with no parameters. (If the client wants to open any other landmark database, a URI is used to specify which database to open.

When the client has opened a landmark database, the database may have to be initialized. There is a method CPosLandmarkDatabase::IsInitializingNeeded() for checking if the database must be initialized and a method CPosLandmarkDatabase::InitializeL() for performing initialization. If the database is not initialized, the client will not be able to access the database. The client may also be required to call InitializeL() in the case when the database needs recovery (which may happen if a modifying transaction has failed).

When the client has a CPosLandmarkDatabase object, it can start reading or editing the database content. Note: It is not possible to edit the database content if the database is read-only.

The database handle is closed by destroying the CPosLandmarkDatabase object. Closing the handle is not allowed while there are still operations running on it. Doing so will result in a panic.

When the client is done using Landmarks API, it must call the global method ReleaseLandmarkResources(). If this method is not called, the client may get a memory leak.

Using database sequence diagram
Using database sequence diagram

It is recommended to execute initialization operation incrementally-asynchronously.

2.1.1 Database URI

CPosLandmarkDatabase contains a method OpenL(), which takes a database URI as input. The URI consists of a scheme and the database location-<scheme>://<location>. If the scheme is left out, it is understood that the database is local on the terminal and is accessed through the file system. The URI c:landmarks.LDB is therefore the same thing as file://c:landmarks.ldb.

The location part of a landmark database URI for a database residing in the terminal is specified by a drive letter, a database name and the LDB extension. The format is <drive>:<database name>.ldb, e.g. c:landmarks.ldb. Note: A path cannot be specified. If the URI does not specify the drive letter, for example landmarks.ldb, the default landmark database drive will be assumed.

CPosLandmarkDatabase provides also method DatabaseUriLC(), which retrieves the URI of the open database.

2.1.2 Compacting database

When modifying a landmark database, the database size increases. Some of this memory is not really used. The client should therefore supervise the database usage using the CPosLandmarkDatabase::SizeL() method and compact the database if there is too much unused space. CPosLandmarkDatabase::CompactL() is used to perform compacting and it can be run incrementally.

Compaction is done internally in Landmarks as fallback in case the client does not do it. This will lock the database and clients will not be able to access the database until the compaction is complete. This is unexpected behavior from the user's point of view and it is therefore recommended that the client performs the compaction itself.

It is recommended to perform compaction when the usage level drops below 70%.

2.1.3 Releasing resources

The Landmarks subsystem uses ECom plug-ins that provide the implementation for accessing landmark databases. ECom allocates resources that are not released when the plug-in is unloaded. These must be explicitly released by the client at shutdown. This is done by calling the global method ReleaseLandmarkResources(), which has the same effect as REComSession::FinalClose().

The most common way to release landmark resources is to call ReleaseLandmarkResources() last in the client's destructor.

2.2 Managing landmarks

Landmark properties are maintained by CPosLandmark class. A client uses this class to get and set landmark data.

The following example shows how to open database and read landmarks.

// Open a handle to the default landmark database.
CPosLandmarkDatabase* db = CPosLandmarkDatabase::OpenL();
CleanupStack::PushL( db );

// Perform initialization.
// If initialization is not needed, this method will not do anything.
ExecuteAndDeleteLD( db->InitializeL() );

// Create an iterator for iterating the landmarks in the database
CPosLmItemIterator* iter = db->LandmarkIteratorL();
CleanupStack::PushL( iter );

// Read each landmark in the database and do something.
TPosLmItemId lmID = KPosLmNullItemId;
while ( ( lmID = iter->NextL() ) != KPosLmNullItemId )
    {
    CPosLandmark* lm = db->ReadLandmarkLC( lmID );
    // Do something with the landmark information
    CleanupStack::PopAndDestroy( lm );
    }
// Close the iterator and the database handle.
CleanupStack::PopAndDestroy( iter );
CleanupStack::PopAndDestroy( db );

The client can also edit the attributes of a landmark in the database. In order to save changes permanently in database the CPosLandmarkDatabase::UpdateLandmarkL method needs to be used.

The following example shows how to change the name of a landmark ( aDatabase is an open CPosLandmarkDatabase handle).

void RenameLandmarkL(
    CPosLandmarkDatabase& aDatabase,
    TPosLmItemId aLandmarkId,
    const TDesC& aNewName )
{
// Read the landmark from the database.
CPosLandmark* lm = aDatabase.ReadLandmarkLC( aLandmarkId );

// Set the new name and update the database
lm->SetLandmarkNameL( aNewName );
aDatabase.UpdateLandmarkL( *lm );

CleanupStack::PopAndDestroy( lm );
}

The following example shows how a landmark is added to a landmark database ( aDatabase is an open CPosLandmarkDatabase pointer).

_LIT( KName, "My Thai" );
_LIT( KDescription, "Best Thai restaurant ever. Spicy food." );

TLocality pos;
pos.SetCoordinate( 61.1120, 23.4231 );

// Create the landmark object and set available information.
CPosLandmark* lm = CPosLandmark::NewLC();
lm->SetLandmarkNameL( KName );
lm->SetLandmarkDescriptionL( KDescription );
lm->SetPositionL( pos );

// Add the landmark to the database.
aDatabase->AddLandmarkL(*lm);

CleanupStack::PopAndDestroy(lm);

2.2.1 Reading partial landmarks

Landmark data can be spread among different tables in the landmark database. When landmark is read from database, all those tables need to be accessed. However, in many cases when many landmarks are read (e.g. for landmark list) applications need only partial information for every landmark. In this case amount of tables accessed and data transferred during reading can be reduced (thus improving performance) by using "partial read" mechanism of Landmarks API. Following diagram shows basic steps of partial read.

Partial read sequence diagram
Partial read sequence diagram

The following example shows how the client can efficiently read just the names of all the landmarks using partial read. aDatabase is an open CPosLandmarkDatabase handle. For simplicity the incremental operation is executed in one batch in this example.

CArrayPtr<CPosLandmark>* ReadLandmarkNamesOnlyLC( CPosLandmarkDatabase& aDatabase )
{
// Retrieve IDs for all landmarks in the database.
RArray<TPosLmItemId> landmarkIds;
CleanupClosePushL( landmarkIds );
CPosLmItemIterator* iter = aDatabase->LandmarkIteratorL();
CleanupStack::PushL( iter );
iter->GetItemIdsL( landmarkIds, 0, iter->NumOfItemsL() );
CleanupStack::PopAndDestroy(iter);

// Set partial parameters so that only the landmark name will be retrieved.
CPosLmPartialReadParameters* part = CPosLmPartialReadParameters::NewLC();
part->SetRequestedAttributes( CPosLandmark::ELandmarkName );
aDatabase->SetPartialReadParametersL( *part );
CleanupStack::PopAndDestroy( part );

// Start collecting the partial landmark data. Note that
// this will be quicker than reading full landmarks.
CPosLmOperation* op = aDatabase->PreparePartialLandmarksL( landmarkIds );
CleanupStack::PushL( op );
op->ExecuteL();

// The landmark objects can be retrieved from the operation object. These
// landmark objects now contain only the names of the landmarks so
// the heap is used efficiently.
CArrayPtr<CPosLandmark>* lmData = aDatabase->TakePreparedPartialLandmarksL( op );
CleanupStack::PopAndDestroy(op);
CleanupStack::PopAndDestroy( &landmarkIds );

CleanupStack::PushL( lmData ); // there is a slot for it freed by previous Pop
return lmData;
}

2.3 Managing categories

To access categories in a landmark database, the client must first have a handle to a landmark database ( CPosLandmarkDatabase ). This handle is passed to CPosLmCategoryManager::NewL() to create a category manager. After this, the client can read and edit category content in the database. Category properties are maintained by CPosLandmarkCategory class.

The following example shows how to read all landmark categories in a database and retrieve their names. aDb is an open database handle.

void ReadAllCategoriesInDatabase( CPosLandmarkDatabase& aDb )
{
// Create the category manager
CPosLmCategoryManager* categoryManager = CPosLmCategoryManager::NewL( aDb );
CleanupStack::PushL( categoryManager );

// Create an iterator for iterating the landmarks in the database
CPosLmItemIterator* iter = categoryManager->CategoryIteratorL();
CleanupStack::PushL( iter );

// Read each category in the database and do something.
TPosLmItemId catID;
while ( ( catID = iter->NextL() ) != KPosLmNullItemId )
    {
    CPosLandmarkCategory* cat = categoryManager->ReadCategoryLC( catID );

    // do something with the category information
    TPtrC catName;
    cat->GetCategoryName( catName );

    // if any changes made, following code saves them to database
    // categoryManager->UpdateCategoryL( *cat );

    CleanupStack::PopAndDestroy( cat );
    }

// Close the iterator and the category manager.
CleanupStack::PopAndDestroy( iter );
CleanupStack::PopAndDestroy( categoryManager );
}

2.3.1 Creating a local category

The following example shows how the client can create a new category and add it to the database.

// Create a local category object
CPosLandmarkCategory* category = CPosLandmarkCategory::NewLC();
_LIT( KRestaurant, "Restaurant" );
category->SetCategoryNameL( KRestaurant );

// Add it to the database
TPosLmItemId categoryId = aCategoryManager->AddCategoryL( *category );
CleanupStack::PopAndDestroy( category );

2.4 Assigning categories to landmarks

There is a "many-to-many" relationship between landmarks and landmarks categories: landmark can be assigned to zero or more categories and one category may be assigned to zero or more landmarks.

The following example shows how the client can add a category to a landmark.

void AddCategoryToLandmarkL(
    CPosLandmarkDatabase& aDatabase,
    TPosLmItemId aLandmarkId,
    TPosLmItemId aCategoryId )
{
// Find landmark in database
CPosLandmark* landmark = aDatabase.ReadLandmarkLC( aLandmarkId );
// Add category. If it is already added, nothing happens
landmark->AddCategoryL( aCategoryId );
// Save to database
aDatabase.UpdateLandmarkL( *landmark );
// Cleanup
CleanupStack::PopAndDestroy( landmark );
}

The following code example shows how the client can add a category to multiple landmarks. A global category is assigned to a set of landmarks in this example.

void AddLandmarksToGlobalCategoryL(
    CPosLandmarkDatabase& aDatabase,
    RPointerArray<TPosLmItemId>& aLandmarkIds,
    TPosLmGlobalCategory aGlobalCategoryID )
{
CPosLmCategoryManager* categoryManager = CPosLmCategoryManager::NewL( aDatabase );
CleanupStack::PushL( categoryManager );

// Find ID of the given global category in given database
TPosLmItemId categoryId = categoryManager->GetGlobalCategory( aGlobalCategoryID );

// Add given landmarks to this category
ExecuteAndDeleteLD(
 categoryManager->AddCategoryToLandmarksL( categoryId, aLandmarkIds ) );

CleanupStack::PopAndDestroy( categoryManager );
}

2.5 Listening to database events

The following sequence shows how a client can listen to database events.

the ID of a newly added landmark).

The following table lists defined events:

Landmark database events
Event type Description Item Id
EPosLmEventUnknownChanges Unknown change event. Something has been changed in the database but no further details are given. All content, which is of interest for the client, should be read again from the database. This event may be received if there are big changes in the database.
EPosLmEventNewDefaultDatabaseLocation This event is received if the default landmark database location is

changed. The client has to open a new CPosLandmarkDatabase handle to access the default database from the new location.||

EPosLmEventMediaRemoved This event is received if the media where the database is stored is removed. After this, the database cannot be accessed. If the media is inserted again, the database must still be reopened by the client.
EPosLmEventLandmarkUnknownChanges Unknown change event concerns only landmarks. This is analogous to EPosLmEventUnknownChanges but it is known that only landmark data has been modified.
EPosLmEventLandmarkCreated A new landmark has been created in the database. The ID of the new landmark.
EPosLmEventLandmarkDeleted A landmark has been deleted from the database. The ID of the deleted landmark.
EPosLmEventLandmarkUpdated A landmark in the database has been updated. The ID of the updated landmark.
EPosLmEventCategoryUnknownChanges Unknown change event concerning only landmark categories. This is analogous

to EPosLmEventUnknownChanges but it is known that only landmark category data has been modified.||

EPosLmEventCategoryCreated A new landmark category has been created in the database. The ID of the new landmark category.
EPosLmEventCategoryDeleted A landmark category has been deleted from the database. Note: No events relating to landmarks are sent even if the deleted category was assigned to some landmarks. The ID of the deleted landmark category.
EPosLmEventCategoryUpdated A landmark category in the database has been updated. The ID of the updated landmark category.

The following code example shows how to implement a class, which listens to changes in a landmark database. The following code section shows how the class is defined. class CLandmarkEventListener : public CActive

    {
    public: // constructor and destructor

        static CLandmarkEventListener* NewL( CPosLandmarkDatabase* aDatabase );
        virtual ~CLandmarkEventListener();

    public: // From CActive

        void RunL();
        void DoCancel();
        TInt RunError( TInt aError );

    private:
        CLandmarkEventListener( CPosLandmarkDatabase* aDatabase );
        void ConstructL();

    private:
        CPosLandmarkDatabase* iDatabase;
        TPosLmEvent iEvent;
    };

The following example code shows the source code for CLandmarkEventListener .

CLandmarkEventListener::CLandmarkEventListener( CPosLandmarkDatabase* aDatabase )
: CActive( EPriorityStandard ), iDatabase( aDatabase )
    {
    }

void CLandmarkEventListener::ConstructL()
    {
    // Start listening for events.
    iDatabase->NotifyDatabaseEvent( iEvent, iStatus );
    SetActive();
    }

CLandmarkEventListener* CLandmarkEventListener::NewL(
    CPosLandmarkDatabase* aDatabase)
    {
    CLandmarkEventListener* self =
        new (ELeave) CLandmarkEventListener( aDatabase );
    CleanupStack::PushL( self );
    self->ConstructL();
    CleanupStack::Pop( self );
    return self;
    }

CLandmarkEventListener::~CLandmarkEventListener()
    {
    // Cancel any outstanding event request.
    Cancel();
    }

void CLandmarkEventListener::RunL()
    {
    if ( iStatus != KErrNone )
        {
        // Unexpected error. This should be handled in some way, such as
        // shut down application, try to listen again, notify user.
        }
    switch ( iEvent.iEventType )
        {
        case EPosLmEventLandmarkCreated :
            {
            TPosLmItemId newLandmarkId = iEvent.iLandmarkItemId;
            // Read new landmark from database and add it to UI.
            }
            break;
        case EPosLmEventLandmarkDeleted :
            {
            TPosLmItemId deletedLandmarkId = iEvent.iLandmarkItemId;
            // Remove the landmark from the UI.
            }
            break;
        }
    // Resume event listening
    iDatabase->NotifyDatabaseEvent( iEvent, iStatus );
    SetActive();
    }

void CLandmarkEventListener::DoCancel()
    {
    iDatabase->CancelNotifyDatabaseEvent();
    }

TInt CLandmarkEventListener::RunError( TInt /*aError*/ )
    {
    // process leaves from RunL, if any
    return KErrNone;
    }

2.6 Exchanging landmarks

A client can exchange landmark data with another party by using the import and export functionality. Two classes, CPosLandmarkEncoder and CPosLandmarkParser are used to convert landmark data to exchange format and from. The exchange format is defined by specifying its MIME type. The recommended format is "application/vnd.nokia.landmarkcollection+xml". Since S60 5.0 also GPX format parsing supported. GPX format is identified by MIME "application/gps+xml".

since S60 5.1 KML/KMZ format parsing supported. KML format is identified by MIME "application/vnd.google-earth.kml+xml " and KMZ formate is identified by MIME "application/vnd.google-earth.kmz "

Since S60 5.2, Encoding and Parsing of a URL is also supported.The mime type to be specified here ,while creating an instance of the CPosLandmarkEncoder and CPosLandmarkParser class is the hostname of the URL to be parsed. For example, if the URL to be parsed is "http://www.maps.ovi.com/? la = 23.45 & lo = 45.65 ", the mime type to be passed will be " maps.ovi.com". Currently there is support only for this hostname.

2.6.1 Exporting landmarks

To export a set of landmarks, the client must first create a CPosLandmarkEncoder object for the landmark content format in which the landmarks should be encoded. The client can add some information of the landmark collection in the encoder as well.

The client must also provide a list of the landmarks to be exported. If some of the landmarks are not found in the database, the export operation fails with the error code KErrNotFound. The client does not have to add any landmarks to the encoder object. The export operation will add the ones specified in the ID array. The method returns an operation object, which can be run in incremental mode. If it is run incrementally, the client can supervise the progress of the operation.

If the CPosLmOperation object is deleted before the operation is complete, it is possible that only a subset of the landmarks is exported. The client takes ownership of the returned operation object. When all the landmarks have been exported, the client must finalize the encoding by calling CPosLandmarkEncoder::FinalizeEncodingL() .

The sequence diagram below describes basic steps a client does to export landmarks from a database to a file.

Exporting landmarks sequence diagram
Exporting landmarks sequence diagram

The following example shows how the client can export landmarks to a file using the CPosLandmarkDatabase::ExportLandmarksL() method. aDatabase is an open CPosLandmarkDatabase handle. In this example incremental operations are executed synchronously.

void ExportSelectedLandmarksL(
    CPosLandmarkDatabase& aDatabase,
    RArray<TPosLmItemId>& aSelectedLandmarks)
{
_LIT( KExportFilePath, "c:\\eposLmExport.lmx" );
// Mime type of landmarks exchange format
_LIT8( KPosMimeTypeLandmarkCollectionXml,
 "application/vnd.nokia.landmarkcollection+xml" );

// Create the encoder to be used for exporting landmarks
CPosLandmarkEncoder* encoder =
	  CPosLandmarkEncoder::NewL( KPosMimeTypeLandmarkCollectionXml );
CleanupStack::PushL( encoder );

// Point out the file to export landmark data to
encoder->SetOutputFileL( KExportFilePath );

// Execute the operation in one batch
// Note: There must be landmarks for specified IDs in the database,
// otherwise operation will fail with KErrNotFound leave code
ExecuteAndDeleteLD( aDatabase->ExportLandmarksL(
 *encoder, aSelectedLandmarks, CPosLandmarkDatabase::EIncludeCategories ) );

// Finalize encoding to complete export
ExecuteAndDeleteLD( encoder->FinalizeEncodingL() );
CleanupStack::PopAndDestroy( encoder );
}

2.6.2 Importing landmarks

To import landmark content, the client must first create a parser object of class CPosLandmarkParser , which can parse the landmark content. The client does not have to call CPosLandmarkParser::ParseContentL() first. If the content is not already parsed, this will be handled by the import operation.

There are two different CPosLandmarkDatabase::ImportLandmarksL() overloads defined that can be used to import landmark data. In one of them, the client can pass an array defining a subset of the landmarks in the parser object. This way the client can select to import only a part of the landmark content. The other method does not take any parameters and imports all landmarks. Both the import methods return an operation object, which can be run in incremental mode. If it is run incrementally, the client can supervise the progress of the operation.

If the CPosLmOperation object is deleted before the operation is complete, it is possible that only a subset of the landmarks is imported. The client takes ownership of the returned operation object. After completion, CPosLandmarkDatabase::ImportedLandmarksIteratorL() can be called to retrieve the IDs of the added landmarks. If the database is read-only, this operation will complete with the error code KErrAccessDenied. If the client specifies invalid transfer option values, this operation will panic.

Note: The CPosLmOperation::NextStep() method cannot be executed synchronously using User::WaitForRequest() for the import operations. Doing so may cause the operation to hang. CPosLmOperation::NextStep() must be executed using an active object.

The diagram below describes general steps, which client does when imports landmarks from a file.

Importing landmarks sequence diagram
Importing landmarks sequence diagram

The following example shows how the client can import landmarks from file using the CPosLandmarkDatabase::ImportLandmarksL() method. aDatabase is an open CPosLandmarkDatabase handle.

void ImportLandmarksL(
    CPosLandmarkDatabase& aDatabase,
    const TDesC& aImportFilePath )
{
// Mime type of landmarks exchange format
_LIT8( KPosMimeTypeLandmarkCollectionXml,
    "application/vnd.nokia.landmarkcollection+xml");

// Create the parser to be used for importing landmarks
CPosLandmarkParser* parser =
    CPosLandmarkParser::NewL( KPosMimeTypeLandmarkCollectionXml );
CleanupStack::PushL( parser );

// Point out the file to import landmark data from
parser->SetInputFileL( aImportFilePath );
CPosLmOperation* op = aDatabase->ImportLandmarksL(
    *parser, CPosLandmarkDatabase::EDefaultOptions );
CleanupStack::PushL( op );
// Execute the operation in one batch
op->ExecuteL();

// Fetch the landmark iterator of imported landmark IDs
CPosLmItemIterator* iter = aDatabase->ImportedLandmarksIteratorL( op );
CleanupStack::PushL( iter );

// Fetch imported landmark data using this iterator

// Cleanup
CleanupStack::PopAndDestroy( iter );
CleanupStack::PopAndDestroy( op );
CleanupStack::PopAndDestroy( parser );
}

2.6.3 Encoding of Landmarks to a URL

To encode a landmark to a URL ,the client has to first create an instance of CPosLandmarkEncoder class with the URL hostname as the MIME type.( which can either be 'maps.ovi.com' or 'm.ovi.me').The output buffer into which the encoded URL is written can be set using the CPosLandmarkEncoder::SetUseOutputBufferL.The output can also be encoded into a file by setting the output file using CPosLandmarkEncoder::SetUseOutputFileL.

The client can specify the landmark to be encoded by using CPosLandmarkEncoder::AddLandmarkL() method.When the landmark has been encoded, the client must finalize the encoding by calling CPosLandmarkEncoder::FinalizeEncodingL().

The sequence diagram below describes basic steps a client does to encode landmark to a URL.Currently encoding of only a single landmark is supported.Therefore if AddLandmarkL() method is called more than once during the encoding process KErrNotSupported is returned.

The following example shows how the client can encode landmark to a URL using CPosLandmarkEncoder class.

void EncodeLandmarktoUrl ( CPosLandmark& aLandmark )
{
//Mime type used for encoding URL
_LIT8( KUrlMimeType , "maps.ovi.com" );

// Mime type used for encoding a URL for m.ovi.me domain
// _LIT8( KUrlMimeType , "m.ovi.me" );

// Create the encoder to be used for encoding landmark to URL
CPosLandmarkEncoder* encoder =
	  CPosLandmarkEncoder::NewL( KUrlMimeType );
CleanupStack::PushL( encoder );

// Set output buffer into which the encoded URL will be written
CBufBase* outputBuffer = encoder->SetUseOutputBufferL();

// Add the landmark to be encoded
encoder->AddLandmarkL( aLandmark );

// Perform required operation on the outputBuffer
// Delete the buffer
delete outputBuffer;

// Finalize encoding
ExecuteAndDeleteLD( encoder->FinalizeEncodingL() );
CleanupStack::PopAndDestroy( encoder );

}

2.6.4 Parsing a URL to obtain a landmark

The client can parse a URL and decode the landmark information present in the URL by using the CPosLandmarkParser class.In order to do this,the client has to first create an instance of the CPosLandmarkParser with the MIME type as the hostname of the URL( which can either be 'maps.ovi.com' or 'm.ovi.me').

The URL can be provided as an input buffer or input file by using the CPosLandmarkParser::SetInputBuffer method and CPosLandmarkParser::SetInputFileL or CPosLandmarkParser::SetInputFileHandleL methods respectively.

The URL can then be parsed by calling the CPosLandmarkParser::ParseContentL method.This method returns a pointer to the CPosLmOperation class , which is then used to call the CPosLmOperation::ExecuteL method to complete the parsing operation.

The parsed landmark can then be retrieved using the CPosLandmarkParser::LandmarkLC method.

The sequence diagram below describes basic steps a client does to parse a URL and decode it to a landmark Currently decoding of only a single landmark is supported.

The following example shows how the client can parse a URL using CPosLandmarkParser class.

void ParseURLtoLandmark ( TDesC& aUrl )
{
//Mime type used for encoding URL
_LIT8( KUrlMimeType , "maps.ovi.com" );

// Mime type used for decoding a URL for m.ovi.me domain
// _LIT8( KUrlMimeType , "m.ovi.me" );

// Create the parser to be used for parsing the URL
CPosLandmarkParser* parser =
	  CPosLandmarkParser::NewL( KUrlMimeType );
CleanupStack::PushL( parser );

// Set the input buffer that contains the URL to be parsed
parser->SetInputBuffer( aUrl );

// Parse the URL
CPosLmOperation* op  = parser->ParseContentL();
CleanupStack::PushL( op );
// Execute the operation in one batch
op -> ExecuteL();

// Retrieve the parsed landmark
CPosLandmark* parsedLandmark = parser->LandmarkLC();

// Client can perform required operation on the parsedLandmark

CleanupStack::PopAndDestroy( parsedLandmark );
CleanupStack::PopAndDestroy( op );
CleanupStack::PopAndDestroy( parser );

}

2.7 Incremental operations

Some operations in the Landmarks API can take a long time to complete. It is recommended to run them incrementally. The client can use an active object to run the incremental operations in the background so that other tasks can be handled in the meantime, in particular handling UI events.

The following sequence shows a typical usage of an incremental operation.

The operation can be cancelled by deleting the operation object before the operation is complete. Note: Changes that were already done before the operation was cancelled are not rolled back. These changes will be a part of the database.

Note: It is still possible to run the operation all at once. This is done by calling CPosLmOperation::ExecuteL() instead of CPosLmOperation::NextStep() . If there is some error, ExecuteL() will leave. There is a utility method, ExecuteAndDeleteLD() , which first calls ExecuteL() and then deletes the operation object. The utility method leaves if the operation fails. This utility method is useful when the client does not need to use the operation object after it has completed.

ExecuteAndDeleteLD( database->InitializeL() );

Note: The usage of ExecuteL() and NextStep() cannot be mixed. For instance, if NextStep() has been called, any call to ExecuteL() will panic.

The next example shows how to handle the compaction of a landmark database using incremental execution of operations. CCompactHandler is responsible for the compact operation, and to be able to handle incremental execution asynchronously, it inherits from CActive .

The CCompactHandler class is defined as follows:

class CCompactHandler : public CActive
    {
    public:
       CCompactHandler( CPosLandmarkDatabase* aDatabase );
       virtual ~CCompactHandler();

       void CompactIfNeededL();

    public: // from CActive
       void RunL();
       void DoCancel();

    private:
       CPosLandmarkDatabase* iDatabase;
       CPosLmOperation* iCompactOperation;
       TReal32 iProgress;
 };

The following code section shows implementation of CCompactHandler .

CCompactHandler::CCompactHandler( CPosLandmarkDatabase* aDatabase )
: CActive( EPriorityIdle ), iDatabase( aDatabase )
    {
    }

CCompactHandler::~CCompactHandler()
    {
    Cancel();
    delete iCompactOperation;
    }

void CCompactHandler::CompactIfNeededL()
    {
    // Only compact if not started yet.
    if ( !iCompactOperation )
        {
        CPosLandmarkDatabase::TSize size = iDatabase->SizeL();
        // When to compact is up to the client.
        // In this example we compact when
        // less than 70% of the database is used.
        const TReal32 KPercentage = 0.70f;
        if ( size.iUsage < KPercentage )
            {
            iCompactOperation = iDatabase->CompactL();
            }
        iCompactOperation->NextStep( iStatus, iProgress );
        SetActive();
        }
    }

void CCompactHandler::RunL()
    {
    if ( iStatus == KPosLmOperationNotComplete )
        { // The compact operation has not completed.

        // Use the value iProgress to show progress bar to the phone user.
        // Perform the next compact step
        iCompactOperation->NextStep( iStatus, iProgress );
        SetActive();
        }
    else
        { // The compact operation has completed.
        if ( iStatus != KErrNone )
            {
            // Notify user of error
            }
        delete iCompactOperation;
        iCompactOperation = NULL;
        }
    }

void CCompactHandler::DoCancel()
    {
    // Cancel is done by deleting the operation object.
    delete iCompactOperation;
    iCompactOperation = NULL;
    }

2.8 Error handling

The Landmarks API uses the standard Symbian error reporting mechanism. In case of an irrecoverable error, panics are used, otherwise, errors are reported through return codes or leaves.

CPosLmOperation::NextStep() returns a status, which indicates if there is an error.

The following table lists the panic codes defined by the Landmarks API and other Landmarks APIs (such as Landmarks Search API and Landmarks Database Management API). The panic category is "Landmarks Client".

Landmarks panic codes
Panic code Panic name Description
0 EPosInvalidPositionFieldId A client has specified a position field ID that is invalid for the

landmark.

1 EPosNoneOrMultipleLandmarkAttributeSet A client has specified none or multiple landmark attributes.
2 EPosSpecifiedIntervalLiesOutsideIteratedSet A client has specified an interval that lies partially outside the

iterated set.

3 EPosNaNCoordinate A client has specified a coordinate with latitude and/or longitude

set to NaN.

4 EPosInvalidLandmarkAttribute A client has specified a landmark attribute that is invalid.
5 EPosInvalidValueSpecifiedInResourceFile An invalid value has been detected in an internal resource file. Configuration

problem.

6 EPosInvalidPartialReadParameters The client has specified invalid partial read parameters in CPosLmPartialReadParameters .
7 EPosInvalidRequestedPositionFields The client has specified invalid requested position fields in CPosLmPartialReadParameters .
8 EPosNegativeValue The client specified a negative value where a negative value was not

allowed.

9 EPosInvalidOperationMode Invalid operation mode. Caused by mixed calls to NextStep and ExecuteL for

a CPosLmOperation object or subsequent calls to NextStep.

10 EPosInvalidEnumValue Invalid enumeration value.
11 EPosLmProtocolBreak The protocol of CPosLandmarkEncoder or CPosLandmarkParser is

not followed.

12 EPosLmInvalidArgument A client has passed an invalid argument.
14 EPosInvalidIndex A client has specified an invalid index.
15 EPosInvalidItemType A client has specified an invalid item type.
16 EPosSearchOperationInUse A client has tried to set/unset display data during an ongoing search.

2.9 Memory and Performance Considerations

When using the Landmarks API, the memory overhead depends on the amount of classes instantiated by the client. However, there are some cases where extra memory usage can be involved and cannot be controlled by the client.

CPosLmItemIterator objects may use a caching scheme to enable fast access to landmarks that have already been read. This means that the iterator can use memory that the client cannot control. This memory will be released when the iterator is destroyed.

CPosLandmarkDatabase::PreparePartialLandmarksL() allocates a lot of information on the heap if many landmarks are read, especially if partial read parameters are set to include a lot of landmark attributes. These landmark objects are stored inside the CPosLmOperation object until retrieved by the client.

Clients take ownership of the CPosLmOperation objects and must delete them immediately after they are not needed to release unused heap memory.

2.10 Extensions to the API

This API does not allow extensions.

2.11 Security issues

Landmarks are considered as important user data and this applies some access limitations to client applications. For example, to be able to read landmarks from landmark database, clients must have ReadUserData capability and WriteUserData to modify it. Whenever special capabilities are needed to work with landmarks database, they are listed in appropriate class and method descriptions.

3 Glossary

3.1 Abbreviations

WGS 84 World Geodetic System 1984
GPX GPS Exchange (format)

3.2 Definitions

Landmark A landmark is a named object that contains a location. The location can be defined by various attributes such as WGS 84 coordinates or a textual address.
Landmark category A landmark can be categorized by assigning a landmark category to it. A typical landmark category is "Restaurant".
Landmark database Persistent storage of a collection of landmarks and landmark categories.

4 References

GPX
http://www.topografix.com/GPX KML http://code.google.com/apis/kml/documentation/kmlreference.html URL http://www.rfc-editor.org/rfc/rfc2396.txt http://www.rfc-editor.org/rfc/rfc1738.txt ASCII table http://www.asciitable.com/