landmarks/locationlandmarks/converter/src/EPos_CPosLmXmlParser.cpp
author hgs
Wed, 13 Oct 2010 17:19:10 +0530
changeset 52 4d26d2f138a3
parent 0 667063e416a2
permissions -rw-r--r--
201041

/*
* Copyright (c) 2002-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: Parser that uses Symbian XML Framework to parse XML files with
*  Landmark Content Format.
 *
 *
*/


#include <utf.h>
#include <xml/xmlparsererrors.h>
#include <lbs.h>
#include <EPos_PosLmImplExtension.h>
#include <EPos_LandmarksErrors.h>
#include "EPos_CPosLmXmlParser.h"
#include "EPos_CPosLmXmlParserOperation.h"
#include "EPos_CPosLmCollectionData.h"
#include "EPos_CPosLmParsedLmBuffer.h"
#include "EPos_PosLmConverterUtils.h"
#include "EPos_LmConverter.h"

const TInt KPosLmParserBytesAtATime = 100;

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

// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
//
CPosLmXmlParser::CPosLmXmlParser()
    {
     
    }

// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
//
CPosLmXmlParser::~CPosLmXmlParser()
    {
    // Notify operation that parser is deleted
    DisconnectOperation();
    ResetParser();

    iCollectionData.Close();

    iCategories.Close();
    iParsedLmBuffer.Close();
    
    }

// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
//
TInt CPosLmXmlParser::ParseNextPartL( TReal32& aProgress )
    {
    __ASSERT_ALWAYS(( iParserStatus & EStateInitialized ) &&( iParserStatus & EStateOperationConstructed ), Panic(
            KPosLandmarksClientPanic, EPosLmProtocolBreak ) );
    TInt status = KPosLmOperationNotComplete;

    // Check if there are a parsed landmark before in lm parsed buffer
    TBool lmBeforeParsing = EFalse;
    if ( iParsedLmBuffer.Count()> 0 )
        {
        lmBeforeParsing = ETrue;
        }

    // We need to parse file/buffer since we don't have any landmark
    // in parsed buffer and
    // also to check that there are some more landmarks coming
    if ( iParsedLmBuffer.Count()<= 1 )
        {
        TInt nrOfLmBeforeParsing = iParsedLmBuffer.Count();
        TInt bytesBeforeParsing = iNumberOfBytesRead;

        iParserStatus |= EStateParsingStarted;
        iParserStatus &= ~EStateParsedLandmark;
        iParserStatus &= ~EStateParsingForNextLm;
        iParserStatus &= ~EStateParsingPartReady;
        iParserError = KErrNone;
        ReadNextPartL();
        iParserStatus |= EStateParsing;

        // Check if we have read a landmark
        while(!ParsedPart() && BufferLength()> 0 )
            {
            iXmlParser->ParseL(*iBuffer );
            User::LeaveIfError( iParserError );

            // Check if we are ready parsing
            /*if (( iParserStatus & EStateParsedLandmark ) &&( iParserStatus & EStateParsingForNextLm ) )
                {
                iParserStatus |= EStateParsingPartReady;
                }
            else
                if ( iParserStatus & EStateParsedLandmark )
                    {
                    iParserStatus |= EStateParsingForNextLm;
                    }*/

            if (!ParsedPart() )
                {
                ReadNextPartL();
                }
            }

        // Evaluate read bytes per read lm, used for progress
        if ( nrOfLmBeforeParsing < iParsedLmBuffer.Count() )
            {
            iIncrBytesPerLm = TReal32( iNumberOfBytesRead -TReal32( bytesBeforeParsing ) )/( iParsedLmBuffer.Count() - nrOfLmBeforeParsing );
            }

        // Finished parsing
        iParserStatus &= ~EStateParsing;
        }

    // Remove latest landmark if there where any parsed
    if ( lmBeforeParsing && iParserStatus)// & EStateParsedLandmark)
        {
        
        	delete iParsedLmBuffer[0];
        	iParsedLmBuffer.Remove( 0 );
                
        }

	if ( iParsedLmBuffer.Count()> 0 && iParsedLmBuffer[0]->Landmark())
        {
        	iNumOfParsedLandmarks++;
        }
    	else
        {
        	User::Leave( KErrPosLmUnknownFormat );
        }	
	    	
	    


		
	
    // Set progress / Linear progress
    aProgress = TReal32( iNumberOfBytesRead -iIncrBytesPerLm *( iParsedLmBuffer.Count() - 1 ) )/TReal32( iContentSize );

    // Check status if parsing is completed
    if ( IsParsingComplete() )
        {
        User::LeaveIfError( CompleteParsing());
        status = KErrNone;
        }
    
 
    return status;
    }

// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
//
void CPosLmXmlParser::ResetParserOnError()
    {
    CompleteParsing();

    iParserStatus &= ~EStateParsingStarted;
    iParserStatus &= ~EStateParsing;
    iParserStatus &= ~EStateParsingReady;
    iReadTags.Reset();
    iTrees.Reset();
    iLastElementState = EXmlParserOnEndElement;
    
    iNumberOfBytesRead = 0;
    iIncrBytesPerLm = 0;

    iParserError = KErrNone;
    ResetParserPartState();
    }

// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
//
void CPosLmXmlParser::SetInputBuffer( const TDesC8& aBuffer )
    {
    __ASSERT_ALWAYS(!( iParserStatus & EStateParsing ), Panic( KPosLandmarksClientPanic,
            EPosLmProtocolBreak ) );

    ResetParser();

    iInputBuffer.Set( aBuffer );

    // Set size
    iContentSize = iInputBuffer.Length();

    iParserStatus |= EStateInitialized;
    }

// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
//
void CPosLmXmlParser::SetInputFileL( const TDesC& aFile )
{
	SetInputFileInternalL( NULL, aFile );
}

// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
//
void CPosLmXmlParser::SetInputFileHandleL( RFile& aFileHandle )
{
	SetInputFileInternalL(&aFileHandle );
}

// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
//
CPosLmOperation* CPosLmXmlParser::ParseContentL( TBool aBuildIndex )
    {
    __ASSERT_ALWAYS( iParserStatus & EStateInitialized, Panic(
            KPosLandmarksClientPanic, EPosLmProtocolBreak ) );

    // Check if we support buildindex
    if ( aBuildIndex )
        {
        User::Leave( KErrNotSupported );
        }

     // Reset parsers content
    ResetContentL();

    DisconnectOperation();

    iParserOp = CPosLmXmlParserOperation::NewL(*this );
    return iParserOp; // ownership is transferred to client
    }

// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
//
TUint32 CPosLmXmlParser::NumOfParsedLandmarks() const
    {
    return iNumOfParsedLandmarks;
    }

// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
//
TPosLmCollectionDataId CPosLmXmlParser::FirstCollectionDataId() const
    {
    if ( iCollectionData.Count()== 0 )
        {
        return EPosLmCollDataNone;
        }
    return iCollectionData[0]->CollectionDataId();
    }

// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
//
TPosLmCollectionDataId CPosLmXmlParser::NextCollectionDataId(
        TPosLmCollectionDataId aCollectionDataId ) const
    {
    for( TInt i = 0; i < iCollectionData.Count(); i++ )
        {
        if ( iCollectionData[i]->CollectionDataId()== aCollectionDataId &&i+1 < iCollectionData.Count() )
            {
            return iCollectionData[i+1]->CollectionDataId();
            }
        }

    return EPosLmCollDataNone;
    }

// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
//
TPtrC CPosLmXmlParser::CollectionData( TPosLmCollectionDataId aDataId ) const
    {
    TPtrC collectionData;
    TBool found = EFalse;
    for( TInt i = 0; !found && i < iCollectionData.Count(); i++ )
        {
        if ( iCollectionData[i]->CollectionDataId()== aDataId )
            {
            iCollectionData[i]->GetCollectionData( collectionData );
            found = ETrue;
            }
        }

    return collectionData;
    }

// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
//
CPosLandmark* CPosLmXmlParser::LandmarkLC( TUint aLandmarkIndex ) const
    {
    __ASSERT_ALWAYS(
            aLandmarkIndex < iNumOfParsedLandmarks ||aLandmarkIndex == KPosLastParsedLandmark,
            Panic( KPosLandmarksClientPanic, EPosInvalidIndex ) );

    // Need to check things here
    if ( aLandmarkIndex != KPosLastParsedLandmark ||iParsedLmBuffer.Count()== 0 )
        {
        //User::Leave( KErrPosLmUnknownFormat);//KErrNotFound );
        User::Leave( KErrNotFound );
        }
	//if(!isAlreadyCreated)
		
    	return CPosLandmark::NewLC(*iParsedLmBuffer[0]->Landmark() );
    	
    //else
    	//return NULL;		
	
	
    }

// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
//
CPosLandmarkCategory* CPosLmXmlParser::LandmarkCategoryLC(
        TPosLmItemId aCategoryId ) const
    {
    TInt found = KErrNotFound;
    if ( iParsedLmBuffer.Count()== 0 )
        {
        User::Leave( found );
        }

    for( TInt i=0; found == KErrNotFound &&i<iParsedLmBuffer[0]->Categories().Count(); i++ )
        {
        TPosLmItemId itemid = iParsedLmBuffer[0]->Categories()[i]->CategoryId();
        if ( itemid != KPosLmNullItemId && itemid == aCategoryId )
            {
            found = i;
            }
        }

    User::LeaveIfError( found );
    return CPosLandmarkCategory::NewLC(*iParsedLmBuffer[0]->Categories()[found] );
    }

// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
//
void CPosLmXmlParser::OnStartDocumentL(
        const Xml::RDocumentParameters& /*aDocParam*/, TInt /*aErrorCode*/)
    {
    }

// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
//
void CPosLmXmlParser::OnEndDocumentL( TInt /*aErrorCode*/)
    {
    iParserStatus |= EStateParsingReady;
    }

// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
//
void CPosLmXmlParser::OnStartElementL( 
    const Xml::RTagInfo& aElement,
    const Xml::RAttributeArray& aAttributes, 
    TInt /*aErrorCode*/)
    {
    delete iReadContent;
    iReadContent = NULL;
    
    if ( iLastElementState == EXmlParserOnStartElement )
        {
        // new element started, but last one has not been yet closed 
        // => last element is a tree tag
        StartNewTreeL();
        }
    else
        {
        iLastElementState = EXmlParserOnStartElement;
        }

    TPosXmlTagType startTag = TagTypeL( aElement );
    
    // Save namespace of root tag
    if ( startTag == EPosXmlRoot && !iRootNs )
    	{
    	iRootNs = aElement.Uri().DesC().AllocL();
    	}

    if ( startTag != EPosXmlUnknown )
        {
        CheckSequenceOrderL( startTag );
        OnAttributesL( startTag, aAttributes );
        }

    iReadTags.AppendL( startTag );
    SetParserStateL( startTag );
    }


// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
//
void CPosLmXmlParser::CheckSequenceOrderL( TPosXmlTagType aTag )
    {
    RArray<TPosXmlTagType> allowedChildTags;
    CleanupClosePushL( allowedChildTags );
    GetNextAllowedTagsL( allowedChildTags );
    
    PosLmConverterUtils::AssertL( allowedChildTags.Find( aTag ) >= 0 );
    
    CleanupStack::PopAndDestroy( &allowedChildTags );
    }

// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
//
void CPosLmXmlParser::OnEndElementL( const Xml::RTagInfo& aElement, TInt /*aErrorCode*/)
    {
    if ( iLastElementState == EXmlParserOnEndElement )
        {
        // some tree is closed
        CheckMandatoryTagsL( CurrentTree() );
        CloseCurrentTree();
        }
    else
        {
        // here checking is done for the case when
        // closing tag looks like a leaf,
        // but is expected to be a tree and is missing all child tags
        // cases like <latitide>/<longitude> fields not included in <landmark> in LMX
        CheckMandatoryTagsL( CurrentTag() );
        iLastElementState = EXmlParserOnEndElement;
        }

    TPosXmlTagType tagType = TagTypeL( aElement );

    SaveContentL( tagType );
    
    if ( tagType == EPosXmlRoot ) 
        {
        HandleRootTag();
        }
    }

// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
//
void CPosLmXmlParser::SaveContentL( TPosXmlTagType aTag )
    {
    // Read property/content for end element
    if ( iReadContent )
        {
        // Convert property/content
        HBufC* content = PosLmConverterUtils::Utf8ToUnicodeLC( *iReadContent );

        // Set content on Landmark related objects and parser status
        SetContentL( aTag, *content );

        // Reset/delete read/converted content
        CleanupStack::PopAndDestroy( content );

        delete iReadContent;
        iReadContent = NULL;
        }
    else
        {
        SetContentL( aTag, KNullDesC );
        }
    }

// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
//
void CPosLmXmlParser::OnContentL( const TDesC8& aBytes, TInt /*aErrorCode*/)
    {
    TPosXmlTagType currentTag = EPosXmlNothing;
    if ( iLastElementState == EXmlParserOnStartElement )
        {
        currentTag = CurrentTag();
        }
    else
        {
        currentTag = CurrentTree();
        }
    
    if ( currentTag != EPosXmlUnknown && 
         currentTag != EPosXmlNothing )
        {
        // Only leaf tags should contain data
        if ( !PosLmConverterUtils::OnlyWhiteSpaces( aBytes ) )
            {
            PosLmConverterUtils::AssertL( !IsTreeTag( currentTag ) );
            }
        
        // If there is a content from a previous parsing
        // then we need to concatenate data/strings.
        if ( iReadContent )
            {
            HBufC8* prevContent = iReadContent;
            CleanupStack::PushL( prevContent );
            iReadContent = NULL;
    
            iReadContent = HBufC8::NewL( prevContent->Length()+ aBytes.Length() );
            iReadContent->Des().Append( *prevContent );
            iReadContent->Des().Append( aBytes );
    
            CleanupStack::PopAndDestroy( prevContent );
            }
        else
            {
            iReadContent = aBytes.AllocL();
            }
        }
    }

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

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

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

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

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

// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
//
void CPosLmXmlParser::OnOutOfData()
    {
    }

// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
//
void CPosLmXmlParser::OnError( TInt aErrorCode )
    {
    iParserError = aErrorCode;
    }

// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
//
TAny* CPosLmXmlParser::GetExtendedInterface( const TInt32 /*aUid*/)
    {
    return NULL;
    }

// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
//
void CPosLmXmlParser::SetInputFileInternalL( RFile* aFileHandle,
        const TDesC& aFile )
    {
    __ASSERT_ALWAYS(!( iParserStatus & EStateParsing ), Panic( KPosLandmarksClientPanic,
            EPosLmProtocolBreak ) );

    ResetParser();

    if (!aFileHandle )
        {
        User::LeaveIfError( iFs.Connect() );
        User::LeaveIfError( iFile.Open( iFs, aFile,
                EFileShareReadersOnly | EFileRead ) );
        iFileHandle = &iFile;
        }
    else
        {
        iFileHandle = aFileHandle;
        }

    // Set size
    User::LeaveIfError( iFileHandle->Size( iContentSize ) );

    iParserStatus |= EStateInitialized;
    }

// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
//
TBool CPosLmXmlParser::IsParsingComplete()
    {
    return(( iParserStatus & EStateParsingReady || !( BufferLength() > 0 )) &&
            (iParsedLmBuffer.Count() == 1  || iParsedLmBuffer.Count() == 0));
    }

// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
//
TInt CPosLmXmlParser::CompleteParsing()
    {
    TInt err = KErrNone;
    if ( iXmlParser &&( iParserStatus & EStateParsingStarted ) )
        {
        TRAP( err, iXmlParser->ParseEndL() );
        }
    return err;
    }

// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
//
void CPosLmXmlParser::AddCollectionDataL( 
    TPosLmCollectionDataId aCollId,
    const TDesC& aContent )
    {
    CPosLmCollectionData* colldata = CPosLmCollectionData::NewLC( aContent,  aCollId );
    User::LeaveIfError( iCollectionData.Append( colldata ) );
    CleanupStack::Pop( colldata );
    }

// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
//
void CPosLmXmlParser::ResetParser()
    {
    iInputBuffer.Set( NULL, 0 );

	CloseCurrentFileHandle();

	iFs.Close();
    iParserStatus &= ~EStateInitialized;
    iParserStatus &= ~EStateOperationConstructed;
    ResetParserState();
    }

// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
//
void CPosLmXmlParser::ResetParserState()
    {
    ResetParserOnError();

    iNumOfParsedLandmarks = 0;

    delete iXmlParser;
    iXmlParser = NULL;

    delete iBuffer;
    iBuffer = NULL;
    delete iReadContent;
    iReadContent = NULL;

    delete iWorkingLandmark;
    iWorkingLandmark = NULL;
    delete iWorkingCategory;
    iWorkingCategory = NULL;
    iCategories.ResetAndDestroy();
    iParsedLmBuffer.ResetAndDestroy();

    iCollectionData.ResetAndDestroy();
    
    iLastElementState = EXmlParserOnEndElement;
    
    iReadTags.Close();
    iTrees.Close();
    delete iRootNs;
    iRootNs = NULL;
    }

// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
//
void CPosLmXmlParser::ResetParserPartState()
    {
    delete iReadMimeType;
    iReadMimeType = NULL;
    delete iReadUrl;
    iReadUrl = NULL;

    PosLmConverterUtils::SetNaN( iParsedLatitude );
    PosLmConverterUtils::SetNaN( iParsedLongitude );
    PosLmConverterUtils::SetNaN( iParsedAltitude );
    PosLmConverterUtils::SetNaN( iParsedHorAcc );
    PosLmConverterUtils::SetNaN( iParsedVertAcc );
    }

// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
//
TInt CPosLmXmlParser::BufferLength() const
    {
    return iBuffer->Length();
    }

// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
//
TBool CPosLmXmlParser::ParsedPart()
    {
    return( iParserStatus & EStateParsingForNextLm /*EStateParsingPartReady*/ ) ;
    }

// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
//
void CPosLmXmlParser::ReadNextPartL()
    {
    // Read next chunk from file/buffer
    TPtr8 ptr = iBuffer->Des();
    if ( iInputBuffer.Ptr() )
        {
        TInt length = KPosLmParserBytesAtATime;
        if ( iNumberOfBytesRead + length > iInputBuffer.Length() )
            {
            length = iInputBuffer.Length()- iNumberOfBytesRead;
            }
        ptr = iInputBuffer.Mid( iNumberOfBytesRead, length );
        iNumberOfBytesRead += length;
        }
    else
        {
        User::LeaveIfError( iFileHandle->Read( ptr ) );
        iNumberOfBytesRead += BufferLength();
        }
    }

// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
//
void CPosLmXmlParser::SetParserStateL( TPosXmlTagType aTag )
    {
    // Check status of landmark parsing
    if ( IsLandmarkStarted( aTag  ) )
        {
        // If we have found an earlier landmark then
        // we know we are ready parsing a part for this time.
        if ( iParserStatus & EStateParsedLandmark )
            {
            iParserStatus |= EStateParsingForNextLm; //EStateParsingPartReady;
            }

        iWorkingLandmark = CPosLandmark::NewL();
        iCategories.Reset();
        iWorkingItemId = 1;
        iNoOfMediaLinks = 0;
        }
    else
        {
        if ( IsCategoryStarted ( aTag ) )
            {
            iWorkingCategory = CPosLandmarkCategory::NewL();
            }
        }
    }

// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
//
void CPosLmXmlParser::DisconnectOperation()
    {
    if ( iParserOp )
        {
        iParserOp->DisconnectParser();
        iParserOp = NULL;
        }
    }

// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
//
void CPosLmXmlParser::OperationDestroyed()
    {
    iParserOp = NULL;
    }

// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
//
TBool CPosLmXmlParser::EqualsTagL( const TDesC8& aTag, const TDesC& aDefinedTag )
    {
    HBufC* tag = HBufC::NewLC( aTag.Length() );
    TPtr16 tagptr = tag->Des();

    PosLmConverterUtils::Utf8ToUnicodeL( aTag, tagptr );

    TBool answer = ( tag->CompareF( aDefinedTag ) == 0 );
    CleanupStack::PopAndDestroy( tag );

    return answer;
    }

// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
//
TBool CPosLmXmlParser::MatchesRootNamespace( const Xml::RTagInfo& aElement )
    {
    if ( iRootNs )
        {
        return ( iRootNs->Compare( aElement.Uri().DesC() ) == 0 );
        }
    else
        {
        return EFalse;
        }
    }

// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
//
void CPosLmXmlParser::HandleLandmarkParsedL()
    {
    // Set parser tag/states
    iParserStatus |= EStateParsedLandmark;
    
    // Set last sucessfully parsed landmark/categories for later use
    CPosLmParsedLmBuffer* buf = CPosLmParsedLmBuffer::NewLC( *iWorkingLandmark, iCategories );

    // Reset current landmark/category
    delete iWorkingLandmark;
    iWorkingLandmark = NULL;
    iCategories.Reset();
    
    User::LeaveIfError( iParsedLmBuffer.Append( buf ) );
    CleanupStack::Pop( buf );
    
    ResetParserPartState();
    }

// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
//
void CPosLmXmlParser::HandleRootTag()
    {
    // Unset parser tag/states
    iParserStatus |= EStateParsingReady;
    }

// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
// 
void CPosLmXmlParser::StartNewTreeL()
    {
    __ASSERT_DEBUG( iReadTags.Count(), Panic( KPosLmConverterPanic, KErrGeneral ) );
    iTrees.AppendL( iReadTags.Count() - 1 );
    }

// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
// 
void CPosLmXmlParser::CloseCurrentTree()
    {
    __ASSERT_DEBUG( iTrees.Count(), Panic( KPosLmConverterPanic, KErrGeneral ) );
    RemoveChildTags();
    iTrees.Remove( iTrees.Count() - 1 );
    }

// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
//
void CPosLmXmlParser::RemoveChildTags()
    {
    TInt treeIndex = CurrentTreeTagIndex();
    // treeIndex item itself should remain in the list!
    for ( TInt i = iReadTags.Count() - 1; i > treeIndex; --i )
        {
        iReadTags.Remove( i );
        }
    }

// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
//
TBool CPosLmXmlParser::ChildTagFound( TPosXmlTagType aTag )
    {
    for ( TInt i = CurrentTreeTagIndex() + 1; i < iReadTags.Count(); i++ ) 
        {
        if ( iReadTags[i] == aTag )
            {
            return ETrue;
            }
        }
    return EFalse;
    }

// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
// 
TPosXmlTagType CPosLmXmlParser::CurrentTree()
    {
    TInt currentTreeTagIndex = CurrentTreeTagIndex();
    if ( currentTreeTagIndex >= 0 )
        {
        __ASSERT_DEBUG( iReadTags.Count() > currentTreeTagIndex, Panic( KPosLmConverterPanic, KErrGeneral ) );
        return iReadTags[ currentTreeTagIndex ];
        }
    else
        {
        return EPosXmlNothing;
        }
    }

// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
// 
TInt CPosLmXmlParser::CurrentTreeTagIndex()
    {
    if ( iTrees.Count() )
        {
        return iTrees[ iTrees.Count() - 1 ]; // last element in iTrees
        }
    else
        {
        return -1;
        }
    }

// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
// 
TPosXmlTagType CPosLmXmlParser::CurrentTag()
    {
    if ( iReadTags.Count() ) 
        {
        return iReadTags[iReadTags.Count() - 1];
        }
    return EPosXmlNothing;
    }

// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
// 
TPosXmlTagType CPosLmXmlParser::LastKnownChildTag()
    {
    TInt treeIndex = CurrentTreeTagIndex();
    for ( TInt i = iReadTags.Count() - 1; i > treeIndex; i-- )
        {
        if ( iReadTags[i] != EPosXmlUnknown ) 
            {
            return iReadTags[i];
            }
        }
    return EPosXmlNothing;
    }

// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
// 
void CPosLmXmlParser::GenValidSequenceL( 
    const TPosXmlTagType* aChildTags,
    TInt aChildTagsCount,
    RArray<TPosXmlTagType>& aSequence )
    {
    TInt i = 0;
    TPosXmlTagType lastChildTag = LastKnownChildTag();

    if ( lastChildTag != EPosXmlNothing )
        {
        // find last child tag, already parsed
        for ( ; i < aChildTagsCount; i++ )
            {
            if ( *( aChildTags + i ) == lastChildTag )
                {
                i++;
                break;
                }
            }
        }
    
    // add the rest of child tags as allowed for this sequence
    for ( ; i < aChildTagsCount; i++ )
        {
        aSequence.AppendL( *( aChildTags + i ) );
        }
    }

// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
// 
void CPosLmXmlParser::GenValidSetL( 
    const TPosXmlTagType* aChildTags,
    TInt aChildTagsCount,
    RArray<TPosXmlTagType>& aSet )
    {
    // valid set contains all tags, not yet parsed
    for ( TInt i = 0 ; i < aChildTagsCount; i++ ) 
        {
        TPosXmlTagType tag = *( aChildTags + i );
        if ( !ChildTagFound( tag ) )
            {
            aSet.AppendL( tag );
            }
        }
    }

//--------------------------------------------------------------------------------
//----------------------------------------------------------------------------------
//

void CPosLmXmlParser::ResetContentL()
{
	// Reset parsers state
    ResetParserState();
    // Set file pointer
    if ( iFileHandle )
        {
        TInt filepos = 0;
        User::LeaveIfError( iFileHandle->Seek( ESeekStart, filepos ) );
        }

    iBuffer = HBufC8::NewL( KPosLmParserBytesAtATime );

    // Create Symbian XML parser
    _LIT8( KXmlMimeType, "text/xml" );
    iXmlParser = Xml::CParser::NewL( KXmlMimeType, *this );
    iXmlParser->ParseBeginL();
    iParserStatus |= EStateOperationConstructed;
}

//------------------------------------------------------------------------------
//-----------------------------------------------------------------------------
//
void CPosLmXmlParser::CloseCurrentFileHandle()
{
	if(iFileHandle)
	{
		iFileHandle = NULL;
    	iFile.Close();
	}
}