Purpose

The purpose of Landmarks Search API is to extend Landmarks API to enable searching for landmarks or landmark categories that match certain criteria. For instance, a client can search for all the landmarks under the category "Restaurants" in a landmark database. Landmarks Search API is used mainly by end-user applications.

Constraints

Landmarks Search API is available from S60 3rd Edition onwards.

API Description

Landmarks Search API is mainly targeted for end-user applications. It lets clients search for landmarks and landmark categories in landmark databases.

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

Use cases

  • Searching landmarks

  • Searching categories

  • Searching multiple databases

API class structure

The following sections describe the Landmarks Search API class structure. UML diagrams are used to present the classes and their dependencies.

Note: The UML diagrams do not show all the available functions, and some or all function parameters may be left out.

Main classes

The Landmarks Search API allows searching in a single database or in multiple databases by means of CPosLandmarkSearch and CPosLmMultiDbSearch respectively.

CPosLandmarkSearch is mainly used to start searches and to obtain the search matches. The client has to specify the landmark database to search when CPosLandmarkSearch is instantiated. CPosLandmarkSearch returns a CPosLmOperation instance, which is used to execute the search operation incrementally or all at once (see Incremental execution in Landmarks API specification). If the operation is run incrementally, the client can check the operation progress between the incremental steps. CPosLmItemIterator with the IDs of the search matches can be obtained from CPosLandmarkSearch .

CPosLmMultiDbSearch is used to search for landmarks and landmark categories in several landmark databases. The client specifies the URIs of the landmark databases to be searched. CPosLmMultiDbSearch returns a CPosLmOperation instance, which is used to execute the search operation incrementally or all at once. If the operation is run incrementally, the client can check the operation progress between the incremental steps. CPosLmItemIterator with the IDs of the search matches can be obtained from CPosLmMultiDbSearch .

CPosLandmarkDatabase , CPosLmItemIterator and CPosLmOperation are parts of Landmarks API and they are described further in Landmarks API specification.

Landmarks API classes


Landmarks API classes

Related APIs
  • CPosLandmarkDatabase
  • CPosLandmarkSearch
  • CPosLmItemIterator
  • CPosLmMultiDbSearch
  • CPosLmOperation

Criterion classes

CPosLmSearchCriteria is a base class for search criterion classes in Landmarks Search API. Criterion classes are used to specify what criteria a landmark must fulfill in order to be a search match. There are several search criterion classes in Landmarks Search API.

Search criterion classes


Search criterion classes

Used for searching landmarks, which contain a certain category, or landmarks, which do not contain any categories.

CPosLmTextCriteria

Used for searching landmarks, which contain a certain text.

CPosLmAreaCriteria

Used for searching landmarks, which reside in a certain area.

CPosLmNearestCriteria

Used for finding landmarks, which are closest to a certain coordinate.

CPosLmCompositeCriteria

Used for searching landmarks by combining multiple search criteria.

CPosLmIdListCriteria

Used if the client only wants to search a subset of the landmarks in a database.

CPosLmCatNameCriteria

Used for searching landmark categories with a certain name.

Related APIs
  • CPosLmAreaCriteria
  • CPosLmCatNameCriteria
  • CPosLmCompositeCriteria
  • CPosLmIdListCriteria
  • CPosLmNearestCriteria
  • CPosLmSearchCriteria
  • CPosLmTextCriteria

Result classes

When using the landmark item iterator to retrieve search matches, the matches will not be sorted until the search operation has completed. If the client needs a sorted list of the matches before the search has completed, e.g. it wants to show matches in a sorted list as they are found to the application user, the display data feature should be used instead.

Before a search is started, the client specifies CPosLmDisplayData to be used in the search. When the search is executing, the matching categories or landmarks are read from the database and added to CPosLmDisplayData . CPosLmDisplayItem holds the matching CPosLandmark or CPosLandmarkCategory together with the index of the database where the match was found. The database index is only used when searching in several databases.

Result classes


Result classes

Related APIs
  • CPosLandmark
  • CPosLandmarkCategory
  • CPosLmDisplayData
  • CPosLmDisplayItem

Using the Landmarks Search API

Searching landmarks

The client uses CPosLandmarkSearch to search landmarks in a landmarks database. To create a CPosLandmarkSearch instance, the client must specify a database to search in. A handle to an open database ( CPosLandmarkDatabase instance) is passed to CPosLandmarkSearch::NewL() .

Configuring search

CPosLandmarkSearch can be configured by setting certain parameters described below.

Maximum number of matches

The client can set a maximum number of matches by calling CPosLandmarkSearch::SetMaxNumOfMatches() . The search operation stops if the maximum number of matches is reached.

If the client does not set a maximum, the search returns all the matches in the database. The client can also set this explicitly by passing KPosLmMaxNumOfMatchesUnlimited to CPosLandmarkSearch::SetMaxNumOfMatches() .

Search previous matches only

If the CPosLandmarkSearch instance has just finished a search, the client can specify that only these matches should be considered in the next search. This is specified by passing a boolean value to CPosLandmarkSearch::StartLandmarkSearchL() when the search is started. In that way, the client can refine its search, for instance, if there are too many matches.

Searching previous matches is useful if there are too many matches and the application user wants to narrow down the search before listing all matches.

It is also possible to use CPosLmIdListCriteria to search previous matches that are not immediate previous matches (see Search criteria ).

Sort preference

The client can specify that the matching landmarks or landmark categories should be sorted.

One of CPosLandmarkSearch::StartLandmarkSearchL() method overloads takes TPosLmSortPref as parameter. In TPosLmSortPref, the client can specify whether the landmarks should be sorted by name in ascending or descending order.

Related APIs
  • CPosLandmarkSearch
  • CPosLandmarkSearch::SetMaxNumOfMatches()
  • CPosLandmarkSearch::StartLandmarkSearchL()
  • CPosLmIdListCriteria
  • KPosLmMaxNumOfMatchesUnlimited
  • TPosLmSortPref

Specifying search criteria

In order to specify what landmarks to search for the client uses criterion classes. The criteria are passed to CPosLandmarkSearch::StartLandmarkSearchL() when the search is started. In this section, each criterion class is explained.

Landmarks by category

CPosLmCategoryCriteria is used to search for landmarks, which belong to a certain category. The category is specified in one of the following ways:

  • By category ID: A category in a landmark database is identified by an ID, which is unique within the database.

  • By global category: There is a globally defined list of categories, which can be used in multiple databases. The client can specify one of these by global ID.

  • By category name: The client can specify the name of the category. The name search is case sensitive. Wild card patterns are not supported.

If no category is specified, the search operation retrieves uncategorized landmarks.

The predefined global landmark categories are listed in Landmarks API Specification.

Matching text pattern

CPosLmTextCriteria is used to search for landmarks, which contain a certain text. The criterion is defined by providing a text to search for and the position fields and text attributes to search in each landmark. For example, the user can search for “Chinese” in the landmark description and landmark name attributes.

The search is case insensitive.

If no position fields or landmark attributes to search are specified, all the position fields and landmark attributes are searched in each landmark.

Wild card characters are supported in the search string: "?" matches any single character and "*" matches zero or more consecutive characters.

Landmarks within an area

CPosLmAreaCriteria is used to search for landmarks, which reside in a certain area. The search area is defined by providing two latitude and two longitude values that specify the borders of the area.

Note: This search does not consider landmark coverage radius (coverage radius is defined in Landmarks API ).

The area borders must fulfill the following rules:

  • -90 ≤ South Latitude ≤ North Latitude ≤ +90

  • -180 ≤ West Longitude < +180

  • -180 ≤ East Longitude ≤ +180

The east border longitude can be less than the west border longitude. This defines an area, which crosses the 180 meridian.

If the east and west border longitudes are equal, only landmarks that lie on the specified longitude are returned. Similarly, if the north and south border latitudes are equal, only landmarks that lie on the specified latitude are returned.

If west longitude is set to -180 and east longitude is set to +180, all longitudes are included in the search.

Nearest landmarks

CPosLmNearestCriteria is used to find the landmarks, which are closest to a certain coordinate. By default, the matches returned in the search are sorted in an ascending distance order.

Since this operation returns all the landmarks in the database by default, it is recommended to combine the nearest criteria with a limit on the number of matches. The match limit is set by calling CPosLandmarkSearch::SetMaxNumOfMatches() .

It is often a good idea to specify a maximum distance to narrow down the search. This is done by calling CPosLmNearestCriteria::SetMaxDistance() .

By default, the coverage radius of the landmarks is not considered in the search; that is, the distance to the landmark center point is used. The client can change this behavior by calling CPosLmNearestCriteria::SetUseCoverageRadius() . If ETrue is passed to this function, coverage radius is considered; that is, the effective distance is the distance to the landmark center point minus the coverage radius. If the search coordinate lies within a landmark’s coverage area, the effective distance is zero.

Composite criterion

CPosLmCompositeCriteria is used to search for landmarks by combining multiple search criteria. For instance, to search for all restaurants in the area, this class can be used to combine CPosLmAreaCriteria and CPosLmCategoryCriteria

The client combines the criteria by passing each criterion instance to CPosLmCompositeCriteria::AddArgument() .

If CPosLmNearestCriteria is used and no sort preference is specified, the result will be sorted by distance. If more than one CPosLmNearestCriteria are combined using CPosLmCompositeCriteria , the sort order will be undefined unless a sort preference is specified.

Note:

  • It is not allowed to use nested composite criterion.

  • ECompositionOR - is supported only when all the contained criteria are CPosLmTextCriteria. it is not supported for other criteria

ID list

CPosLmIdListCriteria is used if the client only wants to search a subset of the landmarks in a database. The client passes a list of landmark IDs to specify which landmarks to include in the search.

This criterion must be combined with other search criteria using CPosLmCompositeCriteria (see Composite criterion above).

For example, if this criterion is combined with CPosLmTextCriteria , the search operation searches the landmarks specified in the ID list criterion and returns those that match the given text string.

Note: Only one ID list criterion is allowed in a composite criterion.

Related APIs
  • CPosLandmarkSearch::SetMaxNumOfMatches()
  • CPosLandmarkSearch::StartLandmarkSearchL()
  • CPosLmAreaCriteria
  • CPosLmCategoryCriteria
  • CPosLmCompositeCriteria
  • CPosLmCompositeCriteria::AddArgument()
  • CPosLmIdListCriteria
  • CPosLmNearestCriteria
  • CPosLmNearestCriteria::SetMaxDistance()
  • CPosLmNearestCriteria::SetUseCoverageRadius()
  • CPosLmTextCriteria

Executing search

A search for landmarks is started by calling CPosLandmarkSearch::StartLandmarkSearchL() .

This function returns a CPosLmOperation instance, which is used to execute the search operation. The operation can either be executed all at once or in incremental steps. An active object can be used to incrementally run the search in the background. CPosLmOperation::ExecuteL() runs the operation all at once and CPosLmOperation::NextStep() runs the operation incrementally. When the search is complete, the client must delete the CPosLmOperation object.

Instead of calling CPosLmOperation::ExecuteL() , the client can call the global function ExecuteAndDeleteLD() which also deletes the operation object. For example:

               
                ExecuteAndDeleteLD( search->StartLandmarkSearchL( criteria ) );
               
              

If the search is run incrementally, the client is informed of the search progress. The client passes a TReal32 variable to CPosLmOperation::NextStep() which contains the progress when NextStep() completes.

Progress is a floating point number in the interval [0.0, 1.0]. 0.0 indicates that the operation has not started and 1.0 indicates that the operation has completed.

The client also passes TRequestStatus to CPosLmOperation::NextStep() . The request status is set to KPosLmOperationNotComplete if the step has completed, but more steps are needed before the operation is complete. The request status is KErrNone if the operation has finished successfully. The status is set to an error code if the operation has failed.

The IDs of the matches from the search can be retrieved by calling CPosLandmarkSearch::MatchIteratorL() . It is possible to call it also during a search to retrieve any matches encountered so far, but it is not guaranteed that the matches are sorted. However, the matches in the iterator are always sorted, also during a search, if a display data is set to CPosLandmarkSearch before the search is started.

The sequence diagram below shows how client searches landmarks by text criterion and reads matches from database.

Search landmarks sequence diagram


Search landmarks sequence diagram

The following code example shows how to perform a search synchronously (not incrementally) in a landmark database.

              
               // Create a search object and provide the CPosLandmarkDatabase object.
               
CPosLandmarkSearch* search = CPosLandmarkSearch::NewL( *database );
CleanupStack::PushL( search );

// Create the search criterion
_LIT( KSearchString, "flowers" );
CPosLmTextCriteria* crit = CPosLmTextCriteria::NewLC();
crit->SetTextL( KSearchString );

// Start the search and execute it at once.
ExecuteAndDeleteLD( search->StartLandmarkSearchL( *crit ) );

CleanupStack::PopAndDestroy( crit );

// Retrieve an iterator to access the matching landmarks.
CPosLmItemIterator* iter = search->MatchIteratorL();
CleanupStack::PushL( iter );

// Iterate the search matches.
TPosLmItemId lmID;
while ( ( lmID = iter->NextL() ) != KPosLmNullItemId )
    {
    CPosLandmark* lm = database->ReadLandmarkLC( lmID );

    // Do something with the landmark information

    CleanupStack::PopAndDestroy( lm );
    }

CleanupStack::PopAndDestroy( iter );
CleanupStack::PopAndDestroy( search );

The following example shows how to use composite criterion to search for restaurants, which contain the text “thai”.

              
               // Create the composite criterion
               
CPosLmCompositeCriteria* compCrit = CPosLmCompositeCriteria::NewLC(
    CPosLmCompositeCriteria::ECompositionAND );

// Create the category search criterion and add it to composite
_LIT( KCategoryName, "restaurant" );
CPosLmCategoryCriteria* catCrit = CPosLmCategoryCriteria::NewLC();
catCrit->SetCategoryNameL( KCategoryName );

User::LeaveIfError( compCrit->AddArgument( catCrit ) );
// Ownership of the category criterion has been passed to the composite
CleanupStack::Pop( catCrit );

// Create the text search criterion and add it to composite
_LIT( KSearchString, "thai" );
CPosLmTextCriteria* textCrit = CPosLmTextCriteria::NewLC();
textCrit->SetTextL( KSearchString );

User::LeaveIfError( compCrit->AddArgument( textCrit ) );
// Ownership of the text criterion has been passed to the composite
CleanupStack::Pop( textCrit );

// Start the search
ExecuteAndDeleteLD( search->StartLandmarkSearchL( *compCrit ) );
CleanupStack::PopAndDestroy( compCrit );

// Retrieve matches

The following example shows how to use composite criterion to search for landmark which start from latter "A" or " A" (space + A)”, Example result for this type of search can be 'Apple' & ' My Apple' both.

              
               // Create the composite criterion
               
CPosLmCompositeCriteria* compCrit = CPosLmCompositeCriteria::NewLC(
    CPosLmCompositeCriteria::ECompositionOR );

// Create the Text criterion and add it to composite
_LIT( KFirstTextPattern, "A" );
CPosLmTextCriteria* criteria1 = CPosLmTextCriteria::NewLC();
criteria1->SetTextL(KFirstTextPattern);
criteria1->SetAttributesToSearch(CPosLandmark::ELandmarkName);
User::LeaveIfError( compCrit->AddArgument( criteria1 ) );

// Ownership of the text criterion has been passed to the composite
CleanupStack::Pop(criteria1);

// Create the text search criterion and add it to composite
_LIT( KSecondTextPattern, " A" );
CPosLmTextCriteria* textCrit = CPosLmTextCriteria::NewLC();
textCrit->SetTextL( KSecondTextPattern );
textCrit->SetAttributesToSearch(CPosLandmark::ELandmarkName);
User::LeaveIfError( compCrit->AddArgument( textCrit ) );
// Ownership of the text criterion has been passed to the composite
CleanupStack::Pop( textCrit );

// Start the search
ExecuteAndDeleteLD( search->StartLandmarkSearchL( *compCrit ) );
CleanupStack::PopAndDestroy( compCrit );

// Retrieve matches
Related APIs
  • CPosLandmarkSearch
  • CPosLandmarkSearch::MatchIteratorL()
  • CPosLandmarkSearch::StartLandmarkSearchL()
  • CPosLmOperation
  • CPosLmOperation::ExecuteL()
  • CPosLmOperation::NextStep()
  • ExecuteAndDeleteLD()
  • KErrNone
  • KPosLmOperationNotComplete
  • TRequestStatus

Retrieving displayable results

The client can specify a displayable data collection that will be populated with the matching landmarks or landmark categories during the search. This is done by creating a CPosLmDisplayData instance and passing it to CPosLandmarkSearch::SetDisplayData() . The display data object will be reset each time a new search is started.

The client can specify that only partial landmark data will be read from the database by calling CPosLmDisplayData::SetPartialReadParametersL() . If the client does not set partial read parameters, full landmark data will be read. The client can also set this explicitly by calling CPosLmDisplayData::UnsetPartialReadParametersL() .

When searching for categories, full category data is always read from the database.

The client can unset a previously set display data by calling CPosLandmarkSearch::UnsetDisplayData() .

If display data has been set before the search is started, all matches from the search can be retrieved by calling CPosLmDisplayData::DisplayItem() for all the indexes in the interval [0, CPosLmDisplayData::Count() - 1]. By calling CPosLmDisplayItem::Landmark() or CPosLmDisplayItem::Category() , the client gets access to the match.

During a search, CPosLmDisplayData::NewItemIndex() can be called repeatedly to get the index of each new match found and CPosLmDisplayData::DisplayItem() can be called for each new index. The matches in the display data are always sorted, even during a search.

The following sequence diagram shows how to perform a search synchronously (not incrementally) in a landmark database using display data.

Using display data sequence diagram


Using display data sequence diagram

The following example shows how to search a landmark database incrementally. The client also requests to sort the matches. The implementation is encapsulated in active object class CSearchHandler .

              
               class CSearchHandler : public CActive
               
    {
    public: // constructor and destructor

        static CSearchHandler* NewL(CPosLandmarkDatabase* aDb);
        virtual ~CSearchHandler();

    public:
 
        void StartLandmarkSearchL(CPosLmSearchCriteria* aCriteria);
        void StartCategorySearchL(CPosLmSearchCriteria* aCriteria);

        void NextSearchStep();
        void CleanupSearch();

    public: // from CActive

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

    private:

        CSearchHandler(CPosLandmarkDatabase* aDb);
        void ConstructL();

    private:
        CPosLandmarkDatabase* iDb;
        CPosLandmarkSearch* iSearch;
        CPosLmDisplayData* iDisplayData;
        CPosLmOperation* iSearchOperation;
        TReal32 iProgress;
        TBool iIsSearchingForLandmarks;
    };

CSearchHandler::CSearchHandler( CPosLandmarkDatabase* aDb )
: CActive( EPriorityNormal ), iDb( aDb )
    {
    }

void CSearchHandler::ConstructL()
    {
    iSearch = CPosLandmarkSearch::NewL( *iDb );

    iDisplayData = CPosLmDisplayData::NewL();
    iSearch->SetDisplayData( *iDisplayData );
    }

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

CSearchHandler::~CSearchHandler()
    {
    Cancel();
    iSearch->UnsetDisplayData();
    delete iDisplayData;
    delete iSearch;
    }

void CSearchHandler::StartLandmarkSearchL( CPosLmSearchCriteria* aCriteria )
    {
    TPosLmSortPref sp( CPosLandmark::ELandmarkName, TPosLmSortPref::EAscending );
    iSearchOperation = iSearch->StartLandmarkSearchL( *aCriteria, sp );
    iIsSearchingForLandmarks = ETrue;

    // Perform the first step in the incremental search operation.
    NextSearchStep();
    }

void CSearchHandler::StartCategorySearchL( CPosLmSearchCriteria* aCriteria )
    {
    iSearch->StartCategorySearchL( *aCriteria,
    CPosLmCategoryManager::ECategorySortOrderNameAscending );
    iIsSearchingForLandmarks = EFalse;

    // Perform the first step in the incremental search operation.
    NextSearchStep();
    }

void CSearchHandler::NextSearchStep()
    {
    iSearchOperation->NextStep( iStatus, iProgress );
    SetActive();
    }

void CSearchHandler::CleanupSearch()
    {
    // Delete the search operation. This will cancel the operation if it is not
    // already complete.
    delete iSearchOperation;
    iSearchOperation = NULL;
    }

void CSearchHandler::RunL()
    {
    // Get all new matches since last step.
    TInt newItemIndex = iDisplayData->NewItemIndex();
    while ( newItemIndex != KPosLmNoNewItems )
        {
        CPosLmDisplayItem& item = iDisplayData->DisplayItem( newItemIndex );
        if (iIsSearchingForLandmarks)
            {
            const CPosLandmark& lm = item.Landmark();
            // Do something with the landmark information
            }
        else
            {
            const CPosLandmarkCategory& category = item.Category();
            // Do something with the landmark category information
            }
 
        newItemIndex = iDisplayData->NewItemIndex();
        }

    if ( iStatus == KPosLmOperationNotComplete )
        { 
        // The search operation has not completed.
        // Use value iProgress to show progress bar to the application user.

        // Perform the next search step
        NextSearchStep();
        }
    else
        { // The search operation has completed.
        User::LeaveIfError( iStatus.Int() );

        CleanupSearch();
        }
    }

void CSearchHandler::DoCancel()
    {
    CleanupSearch();
    }

TInt CSearchHandler::RunError( TInt /*aError*/ )
    {
    // Notify application user of error and cleanup.
    CleanupSearch();
    return KErrNone;
    }
Related APIs
  • CPosLandmarkSearch::SetDisplayData()
  • CPosLandmarkSearch::UnsetDisplayData()
  • CPosLmDisplayData
  • CPosLmDisplayData::Count()
  • CPosLmDisplayData::DisplayItem()
  • CPosLmDisplayData::NewItemIndex()
  • CPosLmDisplayData::SetPartialReadParametersL()
  • CPosLmDisplayData::UnsetPartialReadParametersL()
  • CPosLmDisplayItem::Category()
  • CPosLmDisplayItem::Landmark()
  • CSearchHandler
Related APIs
  • CPosLandmarkDatabase
  • CPosLandmarkSearch
  • CPosLandmarkSearch::NewL()

Searching categories

A search for landmark categories is started by calling CPosLandmarkSearch::StartCategorySearchL() . All the other steps are similar to those for searching landmarks with a few exceptions.

Searching for categories supports only one search criterion, CPosLmCatNameCriteria : search for landmark categories with a certain name. Wild card characters in the search string are supported: "?" matches any single character and "*" matches zero or more consecutive characters. The search is case insensitive.

CPosLandmarkSearch::StartCategorySearchL() takes CPosLandmarkCategory::TCategorySortPref as parameter. It can be set to no sorting, ascending by category name or descending by category name.

Similarly to searching landmarks searching categories also supports limiting maximum amount of results and searching within previous results only.

Following code example shows how a client can search for categories, which contain word "food" (in order to find categories such as "Food and beverages", "Chinese food", etc.).

             
              // Create a search object and provide the CPosLandmarkDatabase object.
              
CPosCategorySearch* search = CPosCategorySearch::NewL( *database );
CleanupStack::PushL( search );

// Create the search criterion
_LIT( KSearchString, "*food*" ); // using wildcards
CPosLmCatNameCriteria* crit = CPosLmCatNameCriteria::NewLC();
crit->SetTextL( KSearchString );

// Start the search and execute it at once.
ExecuteAndDeleteLD( search->StartLandmarkSearchL( *crit ) );

CleanupStack::PopAndDestroy( crit );

// Retrieve an iterator to access the matching landmarks.
CPosLmItemIterator* iter = search->MatchIteratorL();
CleanupStack::PushL( iter );

// Iterate the search matches.
TPosLmItemId categoryID;
while ( ( categoryID = iter->NextL() ) != KPosLmNullItemId )
    {
    CPosLandmarkCategory* category = database->ReadCategoryLC( categoryID );

    // Do something with the category information

    CleanupStack::PopAndDestroy( category );
    }

CleanupStack::PopAndDestroy( iter );
CleanupStack::PopAndDestroy( search );
Related APIs
  • CPosLandmarkCategory::TCategorySortPref
  • CPosLandmarkSearch::StartCategorySearchL()
  • CPosLmCatNameCriteria

Search multiple databases

Searching for landmarks or landmark categories in multiple landmark databases is rather similar to searching in one database.

The client creates a CPosLmMultiDbSearch instance by passing an array containing the URIs of the landmark databases to search to CPosLmMultiDbSearch::NewL() . The client can also change which databases to search by calling CPosLmMultiDbSearch::SetDatabasesToSearchL() .

However, there are some restrictions on the criterion classes and some extra functionality needed to handle several databases:

  • Configuring search

    • Setting a maximum number of matches limits the number of matches per database.

    • If the client specifies to search only the previous matches and has changed which databases to search, new databases that were not a part of the previous search will generate no matches.

  • Search criteria

    • Search by category ID in CPosLmCategoryCriteria is not allowed since an ID is only valid in one landmark database.

    • Search with CPosLmIdListCriteria is not allowed since an ID is only valid in one landmark database.

  • Error checking:

    • If an error occurs when executing a search operation the search in the database where the error occurred will be terminated and the search will then continue in the remaining databases. This means that CPosLmOperation::ExecuteL() will never leave and CPosLmOperation::NextStep() will not complete with an error code (the only exception is when the client has an outstanding request when canceling the search, in which case the complete code will be KErrCancel ). Instead, CPosLmMultiDbSearch must be checked for any errors encountered during the search.

    • The client can check the number of errors encountered during the search by calling CPosLmMultiDbSearch::NumOfSearchErrors() . Each error can be fetched by calling CPosLmMultiDbSearch::GetSearchError() and passing the index of the error.

  • Retrieving results

    • IDs of the matches from the search can be retrieved per database so the client must specify the index of the database.

    • The display data contains matches from all databases. Each display item contains the index of the database where the match was found.

  • Releasing resources

    • The Landmarks subsystem uses ECom plug-ins, which 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 thing in the client’s destructor. If this is not done, the client may receive an ALLOC panic.

This example shows how to perform a search synchronously (not incrementally) in multiple landmark databases.

             
              void SearchInDatabasesL( const CDesCArray& aDatabaseURIs )
              
{
// Create a multi search object and provide a list of database URIs.
CPosLmMultiDbSearch* search = CPosLmMultiDbSearch::NewL( aDatabaseURIs );
CleanupStack::PushL( search );

// Create a display data object.
CPosLmDisplayData* displayData = CPosLmDisplayData::NewL();
CleanupStack::PushL( displayData );

// Set the display data to the search object.
search->SetDisplayData( *displayData );

// Create the search criterion
_LIT( KSearchString, "flowers" );
CPosLmTextCriteria* crit = CPosLmTextCriteria::NewLC();
crit->SetTextL( KSearchString );

// Start the search and execute it all at once.
ExecuteAndDeleteLD( search->StartLandmarkSearchL( *crit ) );
CleanupStack::PopAndDestroy( crit );

// Check if any errors have occured.
TUint numOfErrors = search->NumOfSearchErrors();
for ( TUint i = 0; i < numOfErrors; i++ )
    {
    CPosLmMultiDbSearch::TSearchError searchError;
    search->GetSearchError( i, searchError );
    // Do something with error
    }

// Iterate the search matches.
for ( TInt i = 0; i < displayData->Count(); i++ )
    {
    const CPosLandmark& lm = displayData->DisplayItem( i ).Landmark();
    // Do something with the landmark information
    }

// Unset display data collection so that it is not reset by next search
search->UnsetDisplayData();

CleanupStack::PopAndDestroy( displayData );
CleanupStack::PopAndDestroy( search );
Related APIs
  • CPosLmCategoryCriteria
  • CPosLmIdListCriteria
  • CPosLmMultiDbSearch
  • CPosLmMultiDbSearch::GetSearchError()
  • CPosLmMultiDbSearch::NewL()
  • CPosLmMultiDbSearch::NumOfSearchErrors()
  • CPosLmMultiDbSearch::SetDatabasesToSearchL()
  • CPosLmOperation::ExecuteL()
  • CPosLmOperation::NextStep()
  • KErrCancel
  • REComSession::FinalClose()
  • ReleaseLandmarkResources(
  • ReleaseLandmarkResources()

Error handling

Landmarks Search API uses the standard Symbian error reporting mechanism. In case of a serious error, panics are used. Otherwise, errors are reported through return codes or leaves.

Landmarks Search API uses the same panic code category as Landmarks API. The panic codes are documented in Landmarks API specification.

Memory overhead

If there are several matches (more than 1000) in a search, a large amount of memory is needed to store the matches. It might therefore be a good idea to set a maximum number of matches before starting the search. Note, however, that it is the first found matches that are retrieved. For example, if the maximum number of matches is set when searching in sorted order, the result can be without a match although its name is in the beginning of the sort order.

Extensions to the API

There are no extensions defined to Landmarks Search API.

Security issues

Landmarks are considered as important user data and this applies some access limitations to client applications. For example, in order to be able to read landmarks from landmark database client must have ReadUserData capability. The NetworkServices is required to access network-based databases. Whenever special capabilities are needed to utilize a class or method, they are listed in appropriate class and method descriptions.

Related APIs
  • NetworkServices
  • ReadUserData

Glossary

Abbreviations

Abbreviations

None

Definitions

Definitions

Landmark A landmark is a named object that contains a location. The location can be defined by various attributes, for example WGS84 coordinates or a textual address.

Landmark attribute

An attribute of a landmark, for example landmark name, position, landmark description, coverage area. For more details, see reference Landmarks API specification.

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.

Position fields

Generic position fields defined in Location Acquisition API (see Location Acquisition API ), for example street name, country, building name.

References

None