plugin/poi/geonames/provider/src/Loader.cpp
author David Caabeiro <david.caabeiro@seqpoint.com>
Fri, 25 Jun 2010 12:50:05 +0200
changeset 0 c316ab048e9d
permissions -rw-r--r--
First public commit

/*
 * Name        : Loader.cpp
 * Description : 
 * Project     : This file is part of OpenMAR, an Open Mobile Augmented Reality browser
 * Website     : http://OpenMAR.org
 *
 * Copyright (c) 2010 David Caabeiro
 *
 * All rights reserved. This program and the accompanying materials are made available 
 * under the terms of the Eclipse Public License v1.0 which accompanies this 
 * distribution, and is available at http://www.eclipse.org/legal/epl-v10.html
 *
 */

#include "Loader.h"

#include "HttpClient.h"
#include "Entry.h"

#include <AknUtils.h>
#include <LbsPositionInfo.h>
#include <Http/mhttpdatasupplier.h>
#include <HttpErr.h>

#include <EPos_CPosLandmark.h>
#include <utf.h>

#include "Logger.h"

CLoader* CLoader::NewL(MLandmarkLoaderObserver& aObserver)
{
    CLoader* self = new(ELeave) CLoader(aObserver);
    CleanupStack::PushL(self);
    self->ConstructL();
    CleanupStack::Pop(self);

    return self;
}

CLoader::~CLoader()
{
    delete iEntry;
    delete iParser;
    delete iClient;
}

CLoader::CLoader(MLandmarkLoaderObserver& aObserver)
    : iObserver(aObserver)
{
}

void CLoader::ConstructL()
{
    LOGTXT("[GEONAMES] Creating POI loader");

    iClient = CHttpClient::NewL(*this);

    _LIT8(KXmlMimeType, "text/xml");
    iParser = Xml::CParser::NewL(KXmlMimeType, *this);

    iEntry = CEntry::NewL();
}

void CLoader::RequestL(const TCoordinate& aPosition, TReal32 aRadius)
{
    // Regardless of system locale, always use point as decimal separator character
    // Also use a maximum of 6 chars to represent each float
    TRealFormat realFormat;
    realFormat.iPoint  = TChar('.');
    realFormat.iWidth  = 8;
    realFormat.iPlaces = 5;

    TBuf8<KDefaultRealWidth> latitude;
    latitude.Num(aPosition.Latitude(), realFormat);

    TBuf8<KDefaultRealWidth> longitude;
    longitude.Num(aPosition.Longitude(), realFormat);

    // Convert to kilometers
    const TInt radius = static_cast<TInt>(aRadius / 1000);

    TBuf8<2> langCode;

    // Use device's language to retrieve entries
    HBufC* tag = AknLangUtils::DisplayLanguageTagL();
    langCode.Copy(tag->Left(2));
    delete tag;

    // Set a limit to entries retrieved
    const TInt maxRows = 20;

    TBuf8<256> uri;
    _LIT8(KUri, "http://ws.geonames.org/findNearbyWikipedia?lat=%S&lng=%S&radius=%d&lang=%S&maxRows=%d");
    uri.Format(KUri, &latitude, &longitude, radius, &langCode, maxRows);

    iClient->GetL(uri);
}

void CLoader::MHFRunL(RHTTPTransaction aTransaction, const THTTPEvent& aEvent)
{
    switch (aEvent.iStatus)
    {
        case THTTPEvent::EGotResponseHeaders:
        {
            RHTTPResponse resp = aTransaction.Response();
            TInt status = resp.StatusCode();

            // Treat any 2xx HTTP code as successful request
            TInt error = HTTPStatus::IsSuccessful(status)? KErrNone : KErrGeneral;

            if (error == KErrNone)
                iParser->ParseBeginL();

            iObserver.LandmarkLoaderOpenedL(error);

            break;
        }

        case THTTPEvent::EGotResponseBodyData:
        {
            MHTTPDataSupplier* body = aTransaction.Response().Body();

            TPtrC8 dataChunk;
            body->GetNextDataPart(dataChunk);
            iParser->ParseL(dataChunk);
            body->ReleaseData();

            break;
        }

        case THTTPEvent::EResponseComplete:
            LOGTXT("[GEONAMES] HTTP response complete");

            iParser->ParseEndL();
            break ;

        case THTTPEvent::ESucceeded:
        case THTTPEvent::EFailed:
        {
            RHTTPResponse resp = aTransaction.Response();
            TInt status = resp.StatusCode();

            LOGARG("[GEONAMES] HTTP response status code %d", status);

            aTransaction.Close();

            break;
        }

        default:
            LOGARG("[GEONAMES] HTTP unknown event %d", aEvent.iStatus);

            iObserver.LandmarkLoaderOpenedL(KErrUnknown);

            aTransaction.Close();
            break;
    }
}

TInt CLoader::MHFRunError(TInt aError, RHTTPTransaction aTransaction, const THTTPEvent& aEvent)
{
    return KErrNone;
}

void CLoader::OnStartDocumentL(const Xml::RDocumentParameters& aDocParam, TInt aErrorCode)
{}

void CLoader::OnEndDocumentL(TInt aErrorCode)
{}

void CLoader::OnStartElementL(const Xml::RTagInfo& aElement, const Xml::RAttributeArray& aAttributes, TInt aErrorCode)
{
    _LIT8(KEntryTag, "entry");
    if (aElement.LocalName().DesC() == KEntryTag)
        iState = EValid;
    else if (iState == EValid)
        iEntry->EnterState(aElement.LocalName().DesC());
}

void CLoader::OnEndElementL(const Xml::RTagInfo& aElement, TInt aErrorCode)
{
    _LIT8(KEntryTag, "entry");
    if (aElement.LocalName().DesC() == KEntryTag)
    {
        NotifyPOIEntryL();

        iEntry->Reset();
        iState = EInvalid;
    }
    else
        iEntry->ExitState();
}

void CLoader::OnContentL(const TDesC8& aBytes, TInt aErrorCode)
{
    iEntry->FeedState(aBytes);
}

void CLoader::OnStartPrefixMappingL(const RString& /*aPrefix*/, const RString& /*aUri*/, TInt /*aErrorCode*/)
{}

void CLoader::OnEndPrefixMappingL(const RString& /*aPrefix*/, TInt /*aErrorCode*/)
{}

void CLoader::OnIgnorableWhiteSpaceL(const TDesC8& /*aBytes*/, TInt /*aErrorCode*/)
{}

void CLoader::OnSkippedEntityL(const RString& /*aName*/, TInt /*aErrorCode*/)
{}

void CLoader::OnProcessingInstructionL(const TDesC8& /*aTarget*/, const TDesC8& /*aData*/, TInt /*aErrorCode*/)
{}

void CLoader::OnError(TInt /*aErrorCode*/)
{}

TAny* CLoader::GetExtendedInterface(const TInt32 /*aUid*/)
{
    return 0;
}

/*
 * Notify observer of new XML entry
 */
void CLoader::NotifyPOIEntryL()
{
    CPosLandmark* landmark = CPosLandmark::NewLC();

    HBufC* title = CnvUtfConverter::ConvertToUnicodeFromUtf8L(iEntry->iTitle);
    CleanupStack::PushL(title);
    landmark->SetLandmarkNameL(*title);
    CleanupStack::PopAndDestroy(title);

    HBufC* description = CnvUtfConverter::ConvertToUnicodeFromUtf8L(iEntry->iSummary);
    CleanupStack::PushL(description);
    landmark->SetLandmarkDescriptionL(*description);
    CleanupStack::PopAndDestroy(description);

    TLex8 lex;

    lex.Assign(iEntry->iLat);
    TReal32 lat = 0;
    lex.Val(lat);

    lex.Assign(iEntry->iLng);
    TReal32 lng = 0;
    lex.Val(lng);

    lex.Assign(iEntry->iElevation);
    TReal32 elevation = 0;
    lex.Val(elevation);

    TCoordinate coordinate(lat, lng, elevation);
    landmark->SetPositionL(TLocality(coordinate, 0, 0));

    HBufC* url = HBufC::NewLC(iEntry->iWikipediaUrl.Length());
    url->Des().Copy(iEntry->iWikipediaUrl);
    landmark->SetPositionFieldL(EPositionFieldMediaLinksStart, url->Left(KPosLmMaxTextFieldLength));
    CleanupStack::PopAndDestroy(url);

    iObserver.LandmarkLoaderItemCreatedL(*landmark);

    CleanupStack::PopAndDestroy(landmark);
}