meetingrequest/mrurlparserplugin/src/cesmrurlparserpluginimpl.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Thu, 17 Dec 2009 08:39:21 +0200
changeset 0 8466d47a6819
child 16 4ce476e64c59
permissions -rw-r--r--
Revision: 200949 Kit: 200951

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



#include "emailtrace.h"
#include <EPos_CPosLandmark.h>
#include <ecom/implementationproxy.h>
#include <barsread.h>
#include <esmrurlparserplugindata.rsg>
#include <data_caging_path_literals.hrh>
#include <barsc.h>
#include <f32file.h>
#include <lbsposition.h>

#include "cesmrurlparserpluginimpl.h"
#include "esmrinternaluid.h"


_LIT( KResourceName, "esmrurlparserplugindata.rsc" );
_LIT( KResourceFileLocFormat, "r%02d" );
_LIT( KResourceFormat, "rsc" );

const TInt KCoordinateMaxLength = 10;
const TInt KNumberOfDecimals = 4;
const TUint KDecimalSeparator = '.';



// ======== MEMBER FUNCTIONS ========



// ---------------------------------------------------------------------------
// Non-leaving constructor
// ---------------------------------------------------------------------------
//
CESMRUrlParserPluginImpl::CESMRUrlParserPluginImpl()
:   iIsInitialized(EFalse)
    {
    FUNC_LOG;

    }


// ---------------------------------------------------------------------------
// ConstructL for leaving construction
// ---------------------------------------------------------------------------
//
void CESMRUrlParserPluginImpl::ConstructL()// codescanner::LFunctionCantLeave
    {
    FUNC_LOG;

    }


// ---------------------------------------------------------------------------
// Symbian style NewL constructor
// ---------------------------------------------------------------------------
//
CESMRUrlParserPluginImpl* CESMRUrlParserPluginImpl::NewL()
    {
    FUNC_LOG;
    CESMRUrlParserPluginImpl* self = CESMRUrlParserPluginImpl::NewLC();
    CleanupStack::Pop( self );
    return self;
    }


// ---------------------------------------------------------------------------
// Symbian style NewLC constructor
// ---------------------------------------------------------------------------
//
CESMRUrlParserPluginImpl* CESMRUrlParserPluginImpl::NewLC()
    {
    FUNC_LOG;
    CESMRUrlParserPluginImpl* self = new( ELeave ) CESMRUrlParserPluginImpl;
    CleanupStack::PushL( self );
    self->ConstructL();
    return self;
    }


// ---------------------------------------------------------------------------
// Destructor
// ---------------------------------------------------------------------------
//
CESMRUrlParserPluginImpl::~CESMRUrlParserPluginImpl()
    {
    FUNC_LOG;
    iFile.Close();
    iFs.Close();
    }

// ---------------------------------------------------------------------------
// Finds location URL from given text input
// ---------------------------------------------------------------------------
//
TInt CESMRUrlParserPluginImpl::FindLocationUrl( const TDesC& aText, 
                                                      TPtrC& aUrl )

    {
    FUNC_LOG;
    TInt pos(0);
    TRAPD( error, pos = DoFindLocationUrlL( aText, aUrl ) );
    if ( error != KErrNone )
        {
        return error;
        }
    else
        {
        return pos;
        }
    }

// ---------------------------------------------------------------------------
// Finds location URL from given text input
// ---------------------------------------------------------------------------
//
TInt CESMRUrlParserPluginImpl::DoFindLocationUrlL( // codescanner::intleaves
                                       const TDesC& aText, 
                                       TPtrC& aUrl )
    {
    FUNC_LOG;
    //If this parserplugin instance is not yet initialized
    //init it now
    if( !iIsInitialized )
        {
        InitializeL();
        }

    //Read basestring from resource file
    HBufC* baseString = ReadResourceStringLC(R_QTN_LOCATION_URL);
    
    //Seach if base string is found from aText
    TInt urlLocation = aText.Find(*baseString);
    CleanupStack::PopAndDestroy(baseString);
    if( urlLocation < KErrNone )
        {
        User::Leave(KErrNotFound);
        }
    
    //Take out unnecessary part before URL and search if endmark (whitespace)
    //is found. If endmark is not found, 
    //then all the rest of descriptor is part of URL
    HBufC* urlAndAfterBuf = aText.Mid( urlLocation ).AllocLC();
    TInt urlAndAfterBufLength = urlAndAfterBuf->Length();
    TInt urlEndmarkLocation = KErrNotFound; 
    
    for( TInt i = 0; i < urlAndAfterBufLength; i++)
        {
        if( TChar( (*urlAndAfterBuf)[i] ).IsSpace() )
            {
            urlEndmarkLocation = i;
            break;
            }
        }
     
    if( urlEndmarkLocation == KErrNotFound )
        {
        urlEndmarkLocation = urlAndAfterBufLength;
        }
    
    //Take out part from beginning of URL to endmark
    HBufC* urlToEndMark = urlAndAfterBuf->Left( urlEndmarkLocation ).AllocLC();
        
    //Now we should have only URL left, check with "sieve" that it is about in 
    //right format
    HBufC* sieve = ReadResourceStringLC(R_QTN_LOCATION_SIEVE_URL);
    TInt sievedStartPoint = urlToEndMark->Match( *sieve );
    
    CleanupStack::PopAndDestroy(sieve);
    CleanupStack::PopAndDestroy(urlToEndMark);
    CleanupStack::PopAndDestroy(urlAndAfterBuf);
    
    if( sievedStartPoint == KErrNotFound )
        {
        User::Leave(KErrNotFound);
        }
    
    //Check that parameters are in right format
    TPtrC latValue;
    TPtrC lonValue;
    
    GetCoordinateParamValuesL( aText.Mid(urlLocation,urlEndmarkLocation),
                               latValue, lonValue );
    CheckCoordinateParamL( latValue );
    CheckCoordinateParamL( lonValue );
    
    //Set aURL to correspond URL part of aText and return with url position
    aUrl.Set( aText.Mid(urlLocation,urlEndmarkLocation));
    return urlLocation;
    }


// ---------------------------------------------------------------------------
// Creates location URL from landmark object
// ---------------------------------------------------------------------------
//
HBufC* CESMRUrlParserPluginImpl::CreateUrlFromLandmarkL( 
                                               const CPosLandmark& aLandmark )
    {
    FUNC_LOG;
    //If this parserplugin instance is not yet initialized
    //init it now
    if( !iIsInitialized )
        {
        InitializeL();
        }
    
    //Take longitude and latitude out of landmark
    TLocality position;
    User::LeaveIfError( aLandmark.GetPosition( position ) );
    TReal64 latitude = position.Latitude();
    TReal64 longitude = position.Longitude();
   
    //Define TReal format type
    TRealFormat format( KCoordinateMaxLength );
    format.iType = KRealFormatFixed;
    format.iPlaces = KNumberOfDecimals;
    format.iPoint = TChar(KDecimalSeparator);

    //Read strings from resourcefile
    HBufC* baseUrl = ReadResourceStringLC( R_QTN_LOCATION_URL );                        
    HBufC* lat = ReadResourceStringLC( R_QTN_LOCATION_URL_LATITUDE );               
    HBufC* separator = ReadResourceStringLC( R_QTN_LOCATION_URL_PARAM_SEPARATOR );        
    HBufC* lon = ReadResourceStringLC( R_QTN_LOCATION_URL_LONGITUDE );
    
    //Concatenate all strings and coordinates
    HBufC* url = HBufC::NewL( baseUrl->Length() + lat->Length() + separator->Length() 
                         + lon->Length() + format.iWidth + format.iWidth );
    TPtr pointer = url->Des();
    pointer.Append( *baseUrl );
    pointer.Append( *lat );
    pointer.AppendNum( latitude, format );
    pointer.Append( *separator );
    pointer.Append( *lon );
    pointer.AppendNum( longitude, format );
    
    CleanupStack::PopAndDestroy( lon );
    CleanupStack::PopAndDestroy( separator );
    CleanupStack::PopAndDestroy( lat  );
    CleanupStack::PopAndDestroy( baseUrl );
    
    //Transfer ownership of url
    return url;
    }


// ---------------------------------------------------------------------------
// Creates landmark object from location URL
// ---------------------------------------------------------------------------
//
CPosLandmark* CESMRUrlParserPluginImpl::CreateLandmarkFromUrlL( 
                                                           const TDesC& aUrl )
    {
    FUNC_LOG;
    //If this parserplugin instance is not yet initialized
    //init it now
    if( !iIsInitialized )
        {
        InitializeL();
        }
    
    //Read sieve from resourcefile and check if URL matches the sieveformat
    HBufC* sieve = ReadResourceStringLC( R_QTN_LOCATION_SIEVE_URL );
    TInt matchPos = User::LeaveIfError( aUrl.Match( *sieve ) );
    CleanupStack::PopAndDestroy( sieve );
    if( matchPos != 0 )
        {
        //URL was found but is not int the beginning of desc
        User::Leave( KErrArgument );
        }

    //Parse actual coordinate values out of url
    TPtrC latValue;
    TPtrC lonValue;
    GetCoordinateParamValuesL( aUrl, latValue, lonValue );
    
    //Check that parameters are in right format
    CheckCoordinateParamL( latValue );
    CheckCoordinateParamL( lonValue );

    //Convert parameters to TReal values
    TLex lexConverter( latValue );
    TReal64 realLatitude;
    lexConverter.Val( realLatitude );
     
    lexConverter.Assign( lonValue );
    TReal64 realLongitude;
    lexConverter.Val( realLongitude );
    
    //Create landmark with coordinatevalues
    CPosLandmark* landmark = CPosLandmark::NewLC();
    TLocality position;
    position.SetCoordinate( realLatitude, realLongitude );
    landmark->SetPositionL( position );
    CleanupStack::Pop( landmark );
    //transfer ownership
    return landmark;
    }

// ----------------------------------------------------------------------------
// CESMRUrlParserPluginImpl::LocateResourceFile
//
// For locating resource file    
// ----------------------------------------------------------------------------
// 
TInt CESMRUrlParserPluginImpl::LocateResourceFile( 
        const TDesC& aResource,
        const TDesC& aPath,
        TFileName &aResourceFile,
        RFs* aFs )
    {
    FUNC_LOG;
    TFindFile resourceFile( *aFs );
    TInt err = resourceFile.FindByDir(
            aResource,
            aPath );
    
    if ( KErrNone == err )
        {
        aResourceFile.Copy( resourceFile.File() );
        }
    else
        {
        const TChar KFileFormatDelim( '.' );
        TFileName locResourceFile;
        
        TInt pos = aResource.LocateReverse( KFileFormatDelim );
        if ( pos != KErrNotFound )
            {       
            locResourceFile.Copy( aResource.Mid(0, pos + 1) );
            
            TInt language( User::Language() );
            locResourceFile.AppendFormat( KResourceFileLocFormat, language );
            
            TFindFile resourceFile( *aFs );
            err = resourceFile.FindByDir(
                    locResourceFile,
                    aPath );            
            
            if ( KErrNone == err )
                {
                aResourceFile.Copy( resourceFile.File() );
                aResourceFile.Replace(
                        aResourceFile.Length() - KResourceFormat().Length(),
                        KResourceFormat().Length(),
                        KResourceFormat() );
                }
            }
        }
    

    return err; 
    }

// ----------------------------------------------------------------------------
// CESMRUrlParserPluginImpl::InitializeL
//
// Initializes resources
// ----------------------------------------------------------------------------
// 
void CESMRUrlParserPluginImpl::InitializeL()
    {
    FUNC_LOG;
    if( iIsInitialized )
        {
        return;
        }
    //Connect to RFs session
    User::LeaveIfError( iFs.Connect( KFileServerDefaultMessageSlots ) );
    
    //Find and open resource file containing URL strings
    TFileName fileName;
    User::LeaveIfError( LocateResourceFile( KResourceName,
                                            KDC_RESOURCE_FILES_DIR,
                                            fileName,
                                            &iFs ) );
    iFile.OpenL( iFs, fileName );
    iFile.ConfirmSignatureL();
    iIsInitialized = ETrue;
    }

// ----------------------------------------------------------------------------
// CESMRUrlParserPluginImpl::ReadResourceStringLC 
// Reads resource string from specified id
// ----------------------------------------------------------------------------
// 
HBufC* CESMRUrlParserPluginImpl::ReadResourceStringLC( TInt aResourceId )
    {
    FUNC_LOG;
    HBufC8* string = iFile.AllocReadLC(aResourceId);
    iReader.SetBuffer(string);
    HBufC* stringBuffer = iReader.ReadTPtrC().AllocL();
    CleanupStack::PopAndDestroy( string );
    CleanupStack::PushL( stringBuffer );
    //stringBuffer ownership is transfered
    return stringBuffer; 
    }

// ----------------------------------------------------------------------------
// CESMRUrlParserPluginImpl::CheckCoordinateParam 
//
// Checks if coordinate parameter (lon or lat) is in correct format
// Leaves if not
// Correct form is:
// -minus sign allowed only in first position
// -only one decimalseparator sign allowed
// -only digits allowed
// -aParam length not allowed to be zero    
// ----------------------------------------------------------------------------
// 
void CESMRUrlParserPluginImpl::CheckCoordinateParamL( const TDesC& aParam )
    {
    FUNC_LOG;
    if( aParam.Length() == 0 )
        {
        User::Leave( KErrArgument );
        }
    
    //check that aParam contains only digits and only one decimalseparator
    //and minus sign is first, if it exists
    TChar character;
    TBool decimalSeparatorFound = EFalse;
    TLex lex;
    lex.Assign( aParam );
    const TUint KMinusSign = '-';
    
    for( TInt i = 0; i < aParam.Length(); i++)
        {
        character = lex.Get();
        //checks if first character is minus sign and continues if it is
        if( i == 0 && (TUint)character == KMinusSign)
            {
            continue;
            }
        //check that only one decimalseparator exists
        if( (TUint)character == KDecimalSeparator )
            {
            if( decimalSeparatorFound )
                {
                User::Leave( KErrArgument );
                }
            else
                {
                decimalSeparatorFound = ETrue;
                }
            }
        //check that character is either digit or decimalseparator
        if( !( character.IsDigit() ) && (TUint)character != KDecimalSeparator )
            {
            User::Leave( KErrArgument );
            }
        }
    }

// ----------------------------------------------------------------------------
// CESMRUrlParserPluginImpl::GetCoordinateParamValuesL 
// Returns longitude and latitude if found correctly
// ----------------------------------------------------------------------------
// 
void CESMRUrlParserPluginImpl::GetCoordinateParamValuesL( const TDesC& aUrl,
                                                          TPtrC& aLatitude,
                                                          TPtrC& aLongitude )
    {
    FUNC_LOG;
    //Read latitude and longitude strings from resourcefile
    HBufC* lat = ReadResourceStringLC( R_QTN_LOCATION_URL_LATITUDE );
    HBufC* lon = ReadResourceStringLC( R_QTN_LOCATION_URL_LONGITUDE );
    HBufC* separator = ReadResourceStringLC( R_QTN_LOCATION_URL_PARAM_SEPARATOR );
    
    //Find out if lat and lon params and separator exists in aUrl
    TInt latPos = aUrl.Find( *lat );
    TInt lonPos = aUrl.Find( *lon );
    TInt separatorPos = aUrl.Find( *separator );
    if( latPos == KErrNotFound || lonPos == KErrNotFound 
         || separatorPos == KErrNotFound )
        {
        User::Leave( KErrNotFound );
        }
    
    //takes from aUrl parts with actual coordinate data
    aLatitude.Set( aUrl.Mid( latPos + lat->Length(), separatorPos - latPos - lat->Length() ) );
    aLongitude.Set( aUrl.Right( aUrl.Length() - separatorPos - 1 - lon->Length() ) );

    CleanupStack::PopAndDestroy( separator );
    CleanupStack::PopAndDestroy( lon );
    CleanupStack::PopAndDestroy( lat );
    }
//EOF