landmarks/locationlandmarks/converter/src/EPos_CPosLmLmxEncoder.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Tue, 02 Feb 2010 01:06:48 +0200
changeset 0 667063e416a2
permissions -rw-r--r--
Revision: 201003 Kit: 201005

/*
* Copyright (c) 2007 Nokia Corporation and/or its subsidiary(-ies). 
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of "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: Implementation of CPosLmXmlEncoder for LMX format.
*
*
*/


#include    <e32base.h>
#include    <e32math.h>
#include    <lbsposition.h>
#include    <EPos_LandmarksErrors.h>
#include    "EPos_CPosLmLmxEncoder.h"
#include    "EPos_PosLmConverterUtils.h"

const TInt KPosFieldsGranularity = 8;

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

// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
//
CPosLmLmxEncoder::CPosLmLmxEncoder()
    {
    }

// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
//
CPosLmLmxEncoder* CPosLmLmxEncoder::NewL()
    {
    return new (ELeave) CPosLmLmxEncoder;
    }

// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
//
CPosLmLmxEncoder::~CPosLmLmxEncoder()
    {
    }

// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
//
void CPosLmLmxEncoder::WriteStartTagsL()
    {
    // Root
    HBufC* rootAttributes = HBufC::NewLC( KPosLongStringLength );
    rootAttributes->Des().Append( KPosXmlLmNSAttName );
    rootAttributes->Des().Append( KPosXmlEq );
    rootAttributes->Des().Append( KPosXmlQuotationMark );
    rootAttributes->Des().Append( KPosXmlSchemaLocationAttValue );
    rootAttributes->Des().Append( KPosXmlVersionAttValue );
    rootAttributes->Des().Append( KPosXmlQuotationMark );

    rootAttributes->Des().Append( KPosXmlSpace );
    rootAttributes->Des().Append( KPosXmlXsiNSAttName );
    rootAttributes->Des().Append( KPosXmlEq );
    rootAttributes->Des().Append( KPosXmlQuotationMark );
    rootAttributes->Des().Append( KPosXmlXsiNSAttValue );
    rootAttributes->Des().Append( KPosXmlQuotationMark );

    rootAttributes->Des().Append( KPosXmlSpace );
    rootAttributes->Des().Append( KPosXmlSchemaLocationAttName );
    rootAttributes->Des().Append( KPosXmlEq );
    rootAttributes->Des().Append( KPosXmlQuotationMark );
    rootAttributes->Des().Append( KPosXmlSchemaLocationAttValue );
    rootAttributes->Des().Append( KPosXmlVersionAttValue );
    rootAttributes->Des().Append( KPosXmlSlash );
    rootAttributes->Des().Append( KPosXmlSpace );
    rootAttributes->Des().Append( KPosXmlSchemaAttValue );
    rootAttributes->Des().Append( KPosXmlQuotationMark );

    WriteSTagL( EPosXmlRoot, *rootAttributes );
    CleanupStack::PopAndDestroy( rootAttributes );

    // Start with collection right away
    WriteSTagL( EPosXmlLmCollection, KNullDesC );
    }

// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
//
void CPosLmLmxEncoder::WriteFinalTagsL()
    {
    WriteETagL( EPosXmlLmCollection );
    WriteETagL( EPosXmlRoot );
    }

// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
//
void CPosLmLmxEncoder::WriteCollectionDataL( 
    const HBufC* aCollectionName,
    const HBufC* aCollectionDescription )
    {
    if ( aCollectionName )
        {
        WriteStringWithTagsL( *aCollectionName, EPosXmlLmCollName );
        }

    if ( aCollectionDescription )
        {
        WriteStringWithTagsL( *aCollectionDescription, EPosXmlLmCollDescription );
        }
    }

// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
//
void CPosLmLmxEncoder::WriteLandmarkL( 
    const CPosLandmark& aLandmark,
    const RPointerArray<const CPosLandmarkCategory>& aCategories )
    {
    TPtrC textField;

    WriteSTagL( EPosXmlLandmark, KNullDesC );
 
    // Write lm name
    if (aLandmark.GetLandmarkName(textField) == KErrNone)
        {
        WriteStringWithTagsL(textField, EPosXmlLmName);
        }

    // Write lm description
    if (aLandmark.GetLandmarkDescription(textField) == KErrNone)
        {
        WriteStringWithTagsL(textField, EPosXmlLmDescription);
        }

    // Write lm coordinates
    TLocality position;
    TInt status = aLandmark.GetPosition(position);
    if (status == KErrNone)
        {
        WriteLmCoordinatesL(position);
        }

    // Write lm coverage radius
    TReal32 coverageRadius;
    if (aLandmark.GetCoverageRadius(coverageRadius) == KErrNone)
        {
        WriteTRealWithTagsL(coverageRadius, EPosXmlLmCoverageRadius);
        }

    // Write address info and media link
    WriteLmPositionFieldsL(aLandmark);

    for ( TInt i = 0; i < aCategories.Count(); ++i )
        {
        WriteCategoryL( *(aCategories[i]) );
        }
    
    WriteETagL( EPosXmlLandmark );
    }

// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
//
void CPosLmLmxEncoder::WriteLmCoordinatesL( const TLocality& aLocality )
    {
    WriteSTagL( EPosXmlLmCoordinates, KNullDesC );

    // Write latitude, mandatory tag
    WriteTRealWithTagsL(aLocality.Latitude(), EPosXmlCoordLatitude);

    // Write longitude, mandatory tag
    WriteTRealWithTagsL(aLocality.Longitude(), EPosXmlCoordLongitude);

    // Write altitude
    if (!Math::IsNaN(aLocality.Altitude()))
        {
        WriteTRealWithTagsL(aLocality.Altitude(), EPosXmlCoordAltitude);
        }

    // Write horizontalAccuracy
    if (!Math::IsNaN(aLocality.HorizontalAccuracy()))
        {
        WriteTRealWithTagsL(aLocality.HorizontalAccuracy(),
                            EPosXmlCoordHorizontalAcc);
        }

    // Write verticalAccuracy
    if (!Math::IsNaN(aLocality.VerticalAccuracy()))
        {
        WriteTRealWithTagsL(aLocality.VerticalAccuracy(),
                            EPosXmlCoordVerticalAcc);
        }

    WriteETagL(EPosXmlLmCoordinates);
    }

// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
//
void CPosLmLmxEncoder::WriteLmPositionFieldsL( const CPosLandmark& aLandmark )
    {
    RArray<TPosXmlTagType> addressTags;
    CleanupClosePushL(addressTags);

    CDesCArray* addressStrings =
        new (ELeave) CDesCArrayFlat(KPosFieldsGranularity);
    CleanupStack::PushL(addressStrings);

    CDesCArray* mediaLinkStrings =
        new (ELeave) CDesCArrayFlat(KPosFieldsGranularity);
    CleanupStack::PushL(mediaLinkStrings);

    // Sort out address info and media link from position fields.
    TPositionFieldId id = aLandmark.FirstPositionFieldId();
    while (id != EPositionFieldNone)
        {
        TPtrC textField;
        if (aLandmark.GetPositionField(id, textField) == KErrNone)
            {
            if ((id > EPositionFieldAddressCapabilitiesBegin &&
                id < EPositionFieldNMEACapabilitiesBegin)|| id == EPositionFieldProprietaryFieldsBegin)
                {
                TPosXmlTagType tag = XmlTagForPositionField( id );
                TBool validToExport = (tag != EPosXmlNothing);

                if (id == EPositionFieldCountryCode)
                    {
                    // Check that this is a valid token
                    validToExport = PosLmConverterUtils::IsTokenL(
                        textField, KPosCountryCodeLength);
                    }

                if (validToExport)
                    {
                    User::LeaveIfError(addressTags.Append(tag));
                    addressStrings->AppendL(textField);
                    }
                }
            else if (id > EPositionFieldMediaLinks &&
                id < EPositionFieldProprietaryFieldsBegin)
                {
                mediaLinkStrings->AppendL(textField);
                }
            }

        id = aLandmark.NextPositionFieldId(id);
        }

    // Write lm address info
    if (addressTags.Count() != 0)
        {
        WriteSTagL( EPosXmlLmAddressInfo, KNullDesC );

        for (TInt i = 0; i < addressTags.Count(); i++)
            {
            WriteStringWithTagsL((*addressStrings)[i], addressTags[i]);
            }

        WriteETagL(EPosXmlLmAddressInfo);
        }

    // Write media links
    for (TInt i = 0; i < mediaLinkStrings->Count(); i++)
        {
        TInt maxLength = (*mediaLinkStrings)[i].Length();
        HBufC* mime = HBufC::NewLC(maxLength);
        HBufC* url = HBufC::NewLC(maxLength);

        TInt status = PosLmConverterUtils::SeparateMediaLink(
            (*mediaLinkStrings)[i], mime, url);

        if (status == KErrNone)
            {
            if (PosLmConverterUtils::IsAnyUri(*url))
                {
                WriteSTagL( EPosXmlLmMediaLink, KNullDesC );

                // Write mime
                if (mime->Length() != 0)
                    {
                    WriteStringWithTagsL(*mime, EPosXmlMediaLinkMime);
                    }

                // Write url, mandatory tag
                WriteStringWithTagsL(*url, EPosXmlMediaLinkUrl);

                WriteETagL(EPosXmlLmMediaLink);
                }
            }

        CleanupStack::PopAndDestroy(2, mime); // url
        }

    CleanupStack::PopAndDestroy(3, &addressTags); // addressStrings
                                                  // mediaLinkStrings
    }

// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
//
void CPosLmLmxEncoder::WriteCategoryL( const CPosLandmarkCategory& aCategory )
    {
    WriteSTagL( EPosXmlLmCategory, KNullDesC );

    // Write global id
    TPosLmGlobalCategory id = aCategory.GlobalCategory();
    if ( id != KPosLmNullGlobalCategory )
        {
        const TInt KMaxDecimalStringLen = 10;
        TBuf<KMaxDecimalStringLen> idStr;
        idStr.AppendNum( id );
        WriteStringWithTagsL( idStr, EPosXmlCategoryId );
        }

    // Write category name
    WriteSTagL( EPosXmlCategoryName, KNullDesC ); // mandatory tag
    TPtrC categoryName;
    if (aCategory.GetCategoryName(categoryName) == KErrNone)
        {
        WriteEscapedStringL(categoryName);
        }
    WriteETagL( EPosXmlCategoryName ); // mandatory tag

    WriteETagL( EPosXmlLmCategory );
    }

// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
//
TPosXmlTagType CPosLmLmxEncoder::XmlTagForPositionField( TPositionFieldId aPosFieldId )
    {
    TPosXmlTagType xmlType = EPosXmlNothing;

    switch (aPosFieldId)
        {
        case EPositionFieldBuildingFloor:
            xmlType = EPosXmlAddrBuildingFloor;
            break;
        case EPositionFieldBuildingName:
            xmlType = EPosXmlAddrBuildingName;
            break;
        case EPositionFieldBuildingRoom:
            xmlType = EPosXmlAddrBuildingRoom;
            break;
        case EPositionFieldBuildingZone:
            xmlType = EPosXmlAddrBuildingZone;
            break;
        case EPositionFieldCity:
            xmlType = EPosXmlAddrCity;
            break;
        case EPositionFieldCountry:
            xmlType = EPosXmlAddrCountry;
            break;
        case EPositionFieldCountryCode:
            xmlType = EPosXmlAddrCountryCode;
            break;
        case EPositionFieldCounty:
            xmlType = EPosXmlAddrCounty;
            break;
        case EPositionFieldCrossing1:
            xmlType = EPosXmlAddrCrossing1;
            break;
        case EPositionFieldCrossing2:
            xmlType = EPosXmlAddrCrossing2;
            break;
        case EPositionFieldDistrict:
            xmlType = EPosXmlAddrDistrict;
            break;
        case EPositionFieldStreetExtension:
            xmlType = EPosXmlAddrExtension;
            break;
        case EPositionFieldBuildingTelephone:
            xmlType = EPosXmlAddrPhoneNumber;
            break;
        case EPositionFieldPostalCode:
            xmlType = EPosXmlAddrPostalCode;
            break;
        case EPositionFieldState:
            xmlType = EPosXmlAddrState;
            break;
        case EPositionFieldStreet:
            xmlType = EPosXmlAddrStreet;
            break;
        case EPositionFieldProprietaryFieldsBegin:
            xmlType = EPosXmlAddrPlaceId;
            break;
        default:
            break;
        }

    return xmlType;
    }

// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
//
TPtrC CPosLmLmxEncoder::TagNameL( TPosXmlTagType aTagType )
    {
    switch (aTagType)
        {
        case EPosXmlRoot:
            return KPosXmlLmxRoot();
        case EPosXmlLmCollection:
            return KPosXmlLmCollection();
        case EPosXmlLandmark:
            return KPosXmlLm();
        case EPosXmlLmCoordinates:
            return KPosXmlLmCoordinates();
        case EPosXmlLmAddressInfo:
            return KPosXmlLmAddressInfo();
        case EPosXmlLmMediaLink:
            return KPosXmlLmMediaLink();
        case EPosXmlLmCategory:
            return KPosXmlLmCategory();
        case EPosXmlLmCollName:
            return KPosXmlLmCollName();
        case EPosXmlLmCollDescription:
            return KPosXmlLmCollDescription();
        case EPosXmlLmName:
            return KPosXmlLmName();
        case EPosXmlLmDescription:
            return KPosXmlLmDescription();
        case EPosXmlLmCoverageRadius:
            return KPosXmlLmCoverageRadius();
        case EPosXmlCoordLatitude:
            return KPosXmlCoordLatitude();
        case EPosXmlCoordLongitude:
            return KPosXmlCoordLongitude();
        case EPosXmlCoordAltitude:
            return KPosXmlCoordAltitude();
        case EPosXmlCoordHorizontalAcc:
            return KPosXmlCoordHorizontalAcc();
        case EPosXmlCoordVerticalAcc:
            return KPosXmlCoordVerticalAcc();
        case EPosXmlAddrCountry:
            return KPosXmlAddrCountry();
        case EPosXmlAddrCountryCode:
            return KPosXmlAddrCountryCode();
        case EPosXmlAddrState:
            return KPosXmlAddrState();
        case EPosXmlAddrCounty:
            return KPosXmlAddrCounty();
        case EPosXmlAddrCity:
            return KPosXmlAddrCity();
        case EPosXmlAddrDistrict:
            return KPosXmlAddrDistrict();
        case EPosXmlAddrPostalCode:
            return KPosXmlAddrPostalCode();
        case EPosXmlAddrCrossing1:
            return KPosXmlAddrCrossing1();
        case EPosXmlAddrCrossing2:
            return KPosXmlAddrCrossing2();
        case EPosXmlAddrStreet:
            return KPosXmlAddrStreet();
        case EPosXmlAddrBuildingName:
            return KPosXmlAddrBuildingName();
        case EPosXmlAddrBuildingZone:
            return KPosXmlAddrBuildingZone();
        case EPosXmlAddrBuildingFloor:
            return KPosXmlAddrBuildingFloor();
        case EPosXmlAddrBuildingRoom:
            return KPosXmlAddrBuildingRoom();
        case EPosXmlAddrExtension:
            return KPosXmlAddrExtension();
        case EPosXmlAddrPhoneNumber:
            return KPosXmlAddrPhoneNumber();
        case EPosXmlMediaLinkMime:
            return KPosXmlMediaLinkMime();
        case EPosXmlMediaLinkUrl:
            return KPosXmlMediaLinkUrl();
        case EPosXmlCategoryId:
            return KPosXmlCategoryId();
        case EPosXmlCategoryName:
            return KPosXmlCategoryName();
        case EPosXmlAddrPlaceId:
            return KPosXmlAddrPlaceID();
        default:
            User::Leave(KErrNotSupported);
            return KNullDesC();
        }
    }