srsf/vcommandmanager/src/vcxmlparser.cpp
branchRCL_3
changeset 19 e36f3802f733
parent 0 bf1d17376201
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/srsf/vcommandmanager/src/vcxmlparser.cpp	Wed Sep 01 12:29:17 2010 +0100
@@ -0,0 +1,1181 @@
+/*
+* Copyright (c) 2005-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 for Voice Commands XML files
+*
+*/
+
+
+// INCLUDE FILES
+#include <e32math.h>
+#include <featmgr.h>
+#include <parser.h>
+#include <utf.h>
+#include "vcxmlparser.h"
+#include "vcresource.h"
+#include "rubydebug.h"
+
+// CONSTANTS
+// XML Tags
+_LIT8( KXmlDocumentTag, "nssvcommands" );
+_LIT8( KXmlFolderTag, "vcommandfolder" );
+_LIT8( KXmlVCommandTag, "vcommand" );
+_LIT8( KXmlSpokenTag, "spoken" ); 
+_LIT8( KXmlWrittenTag, "written" ); 
+_LIT8( KXmlExecutesTag, "executes" );
+_LIT8( KXmlCmdlineparamsTag, "cmdlineparams" );
+_LIT8( KXmlIconTag, "icon" );
+_LIT8( KXmlTooltipTag, "tooltip" );
+
+// XML attributes
+_LIT8( KXmlVersionAttr, "version" );
+_LIT8( KXmlLocFileAttr, "localizationfile" );
+_LIT8( KXmlLocAttr, "locindex" );
+_LIT8( KXmlFolderTitleLocAttr, "titlelocindex" );
+_LIT8( KXmlFolderIconFileAttr, "iconfile" );
+_LIT8( KXmlFolderIconIndexAttr, "iconindex" );
+_LIT8( KXmlTtsAttr, "tts" );
+_LIT8( KXmlModifiableAttr, "modifiable" );
+_LIT8( KXmlUidAttr, "uid" );
+_LIT8( KXmlExeAttr, "exe" );
+
+// XML attribute values
+_LIT8( KXmlVersionValue, "1.0" );
+_LIT8( KXmlTrueValue, "true" );
+_LIT8( KXmlFalseValue, "false" );
+
+// XML file MIME type
+_LIT8( KMimeType, "text/xml" );
+
+static const TInt KNoTags = 0;
+static const TInt KLastTag = 1;
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+// -----------------------------------------------------------------------------
+// CVcXmlParser::CVcXmlParser
+// C++ default constructor can NOT contain any code, that
+// might leave.
+// -----------------------------------------------------------------------------
+//
+CVcXmlParser::CVcXmlParser( RFs& aRFs, MVcXmlParserObserver& aObserver )
+ : iObserver( aObserver ), iRFs( aRFs )
+    {
+    // Nothing
+    }
+
+// -----------------------------------------------------------------------------
+// CVcXmlParser::ConstructL
+// Symbian 2nd phase constructor can leave.
+// -----------------------------------------------------------------------------
+//
+void CVcXmlParser::ConstructL()
+    {
+    RUBY_DEBUG_BLOCK( "CVcXmlParser::ConstructL" );
+    
+    ResetVCommandFolder();
+    
+    using namespace Xml;
+    
+    iParser = CParser::NewL( KMimeType, *this );
+    }
+
+// -----------------------------------------------------------------------------
+// CVcXmlParser::NewL
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+CVcXmlParser* CVcXmlParser::NewL( RFs& aRFs, MVcXmlParserObserver& aObserver )
+    {
+    CVcXmlParser* self = new( ELeave ) CVcXmlParser( aRFs, aObserver );
+    CleanupStack::PushL( self );
+    self->ConstructL();
+    CleanupStack::Pop( self );
+    return self;
+    }
+
+// -----------------------------------------------------------------------------
+// CVcXmlParser::~CVcXmlParser
+// Destructor.
+// -----------------------------------------------------------------------------
+//
+CVcXmlParser::~CVcXmlParser()
+    {
+    iXmlNesting.Close();
+    ResetVCommandInfo();
+    delete iResource;
+    delete iFolder;
+    delete iFolderTitle;
+    delete iFolderIconFile;
+    delete iAttributeValue;
+    delete iParser;
+    delete iParameters;
+    delete iParameters8;
+    delete iAppName;
+    }
+
+// -----------------------------------------------------------------------------
+// CVcXmlParser::ParseFileL
+// Parses a specific file.
+// -----------------------------------------------------------------------------
+//
+void CVcXmlParser::ParseFileL( const TFileName& aFileName )
+    {
+    RUBY_DEBUG_BLOCK( "CVcXmlParser::ParseFileL" );
+    
+    iParser->ParseBeginL();
+    
+    ParseL( *iParser, iRFs, aFileName );
+    }
+
+// -----------------------------------------------------------------------------
+// CVcXmlParser::OnStartDocumentL
+// Callback from XML parser when beginning of document has been found
+// -----------------------------------------------------------------------------
+//
+void CVcXmlParser::OnStartDocumentL( const Xml::RDocumentParameters& /*aDocParam*/, 
+                                     TInt aErrorCode )
+    {
+    RUBY_DEBUG_BLOCKL( "CVcXmlParser::OnStartDocumentL" );
+    
+    delete iResource;
+    iResource = NULL;
+    
+    if ( ( iXmlNesting.Count() == KNoTags ) && ( aErrorCode == KErrNone ) )
+        {
+        iXmlNesting.Append( EXmlStarted );
+        }
+    else
+        {
+        User::Leave( KErrGeneral );
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CVcXmlParser::OnEndDocumentL
+// Callback from XML parser when end of document has been reached
+// -----------------------------------------------------------------------------
+//
+void CVcXmlParser::OnEndDocumentL( TInt aErrorCode )
+    {
+    RUBY_DEBUG_BLOCKL( "CVcXmlParser::OnEndDocumentL" );
+    
+    if ( ( iXmlNesting.Count() == KLastTag ) && ( aErrorCode == KErrNone ) )
+        {
+        iXmlNesting.Reset();
+        }
+    else
+        {
+        User::Leave( KErrGeneral );
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CVcXmlParser::OnStartElementL
+// Callback from XML parser when new element has been found
+// -----------------------------------------------------------------------------
+//
+void CVcXmlParser::OnStartElementL( const Xml::RTagInfo& aElement, 
+	                                const Xml::RAttributeArray& aAttributes, 
+	                                TInt aErrorCode )
+    {
+    RUBY_DEBUG_BLOCKL( "CVcXmlParser::OnStartElementL" );
+    __ASSERT_ALWAYS( iXmlNesting.Count() > 0, User::Leave( KErrCorrupt ) );    
+    
+    User::LeaveIfError( aErrorCode );
+
+    HBufC8* name = ToLowercaseLC( aElement.LocalName().DesC() );
+
+    // Check what was the previous tag
+    switch ( iXmlNesting[ iXmlNesting.Count() - 1 ] )
+        {
+        case EXmlStarted:
+            {
+            if ( !ResolveDocumentTagL( name->Des(), aAttributes ) )
+                {
+                User::Leave( KErrNotFound );
+                }
+            break;
+            }
+            
+        case EXmlDocument:
+            {
+            if ( !ResolveFolderTagL( name->Des(), aAttributes ) )
+                {
+                if ( !ResolveVCommandTagL( name->Des(), aAttributes ) )
+                    {
+                    RUBY_DEBUG0( "VC XML ERROR: <vcommandfolder> or <vcommand> exptected but not found" );
+                    User::Leave( KErrNotFound );
+                    }
+                }
+            break;
+            }
+        
+        case EXmlFolder:
+            {
+            if ( !ResolveVCommandTagL( name->Des(), aAttributes ) )
+                {
+                RUBY_DEBUG0( "VC XML ERROR: <vcommand> exptected but not found" );
+                User::Leave( KErrNotFound );
+                }
+
+            // New voice command starts
+            ResetVCommandInfo();
+             
+            break;
+            }
+        
+        case EXmlVCommand:
+            {
+            if ( !ResolveSpokenTagL( name->Des(), aAttributes ) )
+                {
+                if ( !ResolveWrittenTagL( name->Des(), aAttributes ) )
+                    {
+                    if ( !ResolveExecutesTagL( name->Des(), aAttributes ) )
+                        {
+                        if ( !ResolveCmdlineparamsTag( name->Des(), aAttributes ) )
+                            {
+                            if ( !ResolveIconTagL( name->Des(), aAttributes ) )
+                                {
+                                if ( !ResolveTooltipTagL( name->Des(), aAttributes ) )
+                                    {
+                                    RUBY_DEBUG0( "VC XML ERROR: <spoken> <written> <executes> or <cmdlineparams> exptected but not found" );   
+                                    User::Leave( KErrNotFound );
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            break;
+            }
+            
+        default:
+            {
+            
+            RUBY_DEBUG0( "VC XML ERROR: Unexpected starting tag found" );
+            User::Leave( KErrNotFound );
+            
+            break;
+            }
+
+        }
+        
+    CleanupStack::PopAndDestroy( name );
+ 
+    }
+
+// -----------------------------------------------------------------------------
+// CVcXmlParser::OnEndElementL
+// Callback from XML parser when ending tag has been found
+// -----------------------------------------------------------------------------
+//
+void CVcXmlParser::OnEndElementL( const Xml::RTagInfo& aElement, 
+                                  TInt aErrorCode )
+    {
+    RUBY_DEBUG_BLOCKL( "CVcXmlParser::OnEndElementL" );
+    __ASSERT_ALWAYS( iXmlNesting.Count() > 0, User::Leave( KErrCorrupt ) );
+    
+    User::LeaveIfError( aErrorCode );
+    
+    HBufC8* name = ToLowercaseLC( aElement.LocalName().DesC() );
+    
+    switch ( iXmlNesting[ iXmlNesting.Count() - 1 ] )
+        {
+        case EXmlDocument:
+            {
+            PopFromStackIfFoundL( name->Des(), KXmlDocumentTag );
+            break;
+            }
+        
+        case EXmlFolder:
+            {
+            PopFromStackIfFoundL( name->Des(), KXmlFolderTag );
+            ResetVCommandFolder();
+            break;
+            }
+        
+        case EXmlVCommand:
+            {
+            PopFromStackIfFoundL( name->Des(), KXmlVCommandTag );
+            CheckVoiceCommmandData();
+            break;
+            }
+            
+         case EXmlSpoken:
+            {
+            PopFromStackIfFoundL( name->Des(), KXmlSpokenTag );
+            break;
+            }
+         
+         case EXmlWritten:
+            {
+            PopFromStackIfFoundL( name->Des(), KXmlWrittenTag );
+            break;
+            }
+        
+         case EXmlExecutes:
+            {
+            PopFromStackIfFoundL( name->Des(), KXmlExecutesTag );
+            break;
+            }
+         
+         case EXmlCmdlineparams:
+            {
+            PopFromStackIfFoundL( name->Des(), KXmlCmdlineparamsTag );   
+                
+            // Convert content of <cmdlineparams> into unicode
+            // First trim out unnecessary white space
+            TPtr8 des8( iParameters8->Des() );
+            des8.Trim();
+                
+            // Delete previous unicode buffer and create new
+            delete iParameters;
+            iParameters = NULL;
+            iParameters = CnvUtfConverter::ConvertToUnicodeFromUtf8L( des8 );
+                
+            break;
+            }
+
+         case EXmlIcon:
+            {
+            PopFromStackIfFoundL( name->Des(), KXmlIconTag );
+            break;
+            }
+
+         case EXmlTooltip:
+            {
+            PopFromStackIfFoundL( name->Des(), KXmlTooltipTag );
+            break;
+            }
+           
+        default:
+            {
+            RUBY_DEBUG0( "VC XML ERROR: Ending tag found when not expected" );
+            User::Leave( KErrGeneral );
+            break;
+            }
+
+        }
+    CleanupStack::PopAndDestroy( name );
+    }
+
+// -----------------------------------------------------------------------------
+// CVcXmlParser::PopFromStackIfFoundL
+// Checks that last item on stack is the expected one
+// -----------------------------------------------------------------------------
+//
+void CVcXmlParser::PopFromStackIfFoundL( const TDesC8& aTagName, const TDesC8& aExpectedTag )
+    {
+    if ( aTagName != aExpectedTag )
+        {
+        RUBY_DEBUG0( "VC XML ERROR: Unexpected ending tag found" );
+        User::Leave( KErrNotFound );
+        }
+        
+    iXmlNesting.Remove( iXmlNesting.Count() - 1 );    
+    }
+
+// -----------------------------------------------------------------------------
+// CVcXmlParser::OnContentL
+// Callback from XML parser when element has some content
+// -----------------------------------------------------------------------------
+//
+void CVcXmlParser::OnContentL( const TDesC8& aBytes, TInt aErrorCode )
+    {
+    RUBY_DEBUG_BLOCKL( "CVcXmlParser::OnContentL" );
+    
+    User::LeaveIfError( aErrorCode );
+    
+    TInt lastTag = iXmlNesting.Count() - 1;
+    
+    if ( iXmlNesting[ lastTag ] == EXmlCmdlineparams )
+        {
+        if ( !iParameters8 )
+            {
+            // Create new buffer
+            iParameters8 = HBufC8::NewL( aBytes.Size() );
+            TPtr8 des( iParameters8->Des() );
+            des.Copy( aBytes );
+            }
+        else
+            {
+            // Append at the end of previous stuff
+            iParameters8 = iParameters8->ReAllocL( iParameters8->Size() + aBytes.Size() );
+            TPtr8 des( iParameters8->Des() );
+            des.Append( aBytes );
+            }
+
+        RUBY_DEBUG0( "<cmdlineparams> content resolved" );
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CVcXmlParser::OnStartPrefixMappingL
+// Callback from XML parser
+// -----------------------------------------------------------------------------
+//
+void CVcXmlParser::OnStartPrefixMappingL( const RString& /*aPrefix*/, 
+	                                      const RString& /*aUri*/, 
+	                                      TInt /*aErrorCode*/ )
+    {
+    // Nothing
+    }
+
+// -----------------------------------------------------------------------------
+// CVcXmlParser::OnEndPrefixMappingL
+// Callback from XML parser
+// -----------------------------------------------------------------------------
+//
+void CVcXmlParser::OnEndPrefixMappingL( const RString& /*aPrefix*/, 
+                                        TInt /*aErrorCode*/ )
+    {
+    // Nothing
+    }
+
+// -----------------------------------------------------------------------------
+// CVcXmlParser::OnIgnorableWhiteSpaceL
+// Callback from XML parser
+// -----------------------------------------------------------------------------
+//
+void CVcXmlParser::OnIgnorableWhiteSpaceL( const TDesC8& /*aBytes*/, 
+                                           TInt /*aErrorCode*/ )
+    {
+    // Nothing
+    }
+
+// -----------------------------------------------------------------------------
+// CVcXmlParser::OnSkippedEntityL
+// Callback from XML parser
+// -----------------------------------------------------------------------------
+//
+void CVcXmlParser::OnSkippedEntityL( const RString& /*aName*/, 
+                                     TInt /*aErrorCode*/ )
+    {
+    // Nothing
+    }
+
+// -----------------------------------------------------------------------------
+// CVcXmlParser::OnProcessingInstructionL
+// Callback from XML parser
+// -----------------------------------------------------------------------------
+//
+void CVcXmlParser::OnProcessingInstructionL( const TDesC8& /*aTarget*/, 
+                                             const TDesC8& /*aData*/, 
+	                                         TInt /*aErrorCode*/ )
+    {
+    // Nothing
+    }
+
+// -----------------------------------------------------------------------------
+// CVcXmlParser::OnError
+// Callback from XML parser when general error has occured
+// -----------------------------------------------------------------------------
+//
+#if defined(_DEBUG) && !defined(__RUBY_DEBUG_DISABLED)
+void CVcXmlParser::OnError( TInt aErrorCode )
+    {
+    RUBY_DEBUG1( "CVcXmlParser::OnError general error: [%d]", aErrorCode );
+    }
+#else
+void CVcXmlParser::OnError( TInt /*aErrorCode*/ )
+    {
+    // Nothing
+    }
+#endif // #if defined(_DEBUG) && !defined(__RUBY_DEBUG_DISABLED)
+    
+// -----------------------------------------------------------------------------
+// CVcXmlParser::GetExtendedInterface
+// Callback from XML parser
+// -----------------------------------------------------------------------------
+//
+TAny* CVcXmlParser::GetExtendedInterface( const TInt32 /*aUid*/ )
+    {
+    return NULL;
+    }
+
+// -----------------------------------------------------------------------------
+// CVcXmlParser::CheckAttributeL
+// Checks the value of certain attribute
+// -----------------------------------------------------------------------------
+//
+TBool CVcXmlParser::CheckAttributeL( const Xml::RAttributeArray& aAttributes,
+                                     const TDesC8& aAttribute, const TDesC8& aValue )
+    {
+    RUBY_DEBUG_BLOCKL( "CVcXmlParser::CheckAttributeL" );
+    
+    TBool resolved( EFalse );
+    
+    // Loop through attribute list
+    for ( TInt iCounter = 0 ; iCounter < aAttributes.Count() ; iCounter++ )
+        {        
+        HBufC8* name = ToLowercaseLC( aAttributes[iCounter].Attribute().LocalName().DesC() );
+       
+        if ( name->Des() == aAttribute )
+            {
+            HBufC8* value = ToLowercaseLC( aAttributes[iCounter].Value().DesC() );
+            
+            // If value is null descriptor, then we just check if attribute exists           
+            if ( aValue == KNullDesC8 || value->Des() == aValue )
+                {                
+                resolved = ETrue;
+                }
+            
+            CleanupStack::PopAndDestroy( value );
+            }
+        CleanupStack::PopAndDestroy( name );
+        }
+        
+    return resolved;
+    }
+    
+// -----------------------------------------------------------------------------
+// CVcXmlParser::ResolveDocumentTagL
+// Resolves the content of <nssvcommands>
+// -----------------------------------------------------------------------------
+//
+TBool CVcXmlParser::ResolveDocumentTagL( const TDesC8& aName, 
+                                        const Xml::RAttributeArray& aAttributes )
+    {
+    RUBY_DEBUG_BLOCKL( "CVcXmlParser::ResolveDocumentTagL" );
+    
+    TBool resolved( EFalse );
+    
+    if ( aName == KXmlDocumentTag )
+        {
+        iXmlNesting.Append( EXmlDocument );
+        resolved = CheckAttributeL( aAttributes, KXmlVersionAttr, KXmlVersionValue );
+        if ( !resolved )
+            {
+            RUBY_DEBUG0( "VC XML ERROR: Version information not found or it does not match" );
+            User::Leave( KErrGeneral );
+            }
+        else
+            {
+            CVcResource* newResource( NULL );
+            TPtrC8 locFileAttr( KXmlLocFileAttr );
+            TRAPD( error, newResource =
+                CVcResource::NewL( iRFs, Find16ValueL( locFileAttr, aAttributes ) ) );
+
+            // Delete old resource object if new was found
+            if ( newResource )
+                {
+                delete iResource;
+                iResource = newResource;
+                }
+        
+            if ( error != KErrNone )
+                {
+                resolved = EFalse;
+                RUBY_DEBUG0( "VC XML ERROR: Resource file load error" );
+                User::Leave( KErrNotFound );
+                }
+            }
+        }
+     else
+        {
+        RUBY_DEBUG0( "VC XML ERROR: <nssvoicecommands> exptected but not found" );
+        User::Leave( KErrNotFound );        
+        }
+               
+    return resolved;
+    }
+
+// -----------------------------------------------------------------------------
+// CVcXmlParser::ResolveFolderTagL
+// Resolves the content of <vcommandfolder>
+// -----------------------------------------------------------------------------
+//
+TBool CVcXmlParser::ResolveFolderTagL( const TDesC8& aName, 
+                                       const Xml::RAttributeArray& aAttributes )
+    {
+    RUBY_DEBUG_BLOCKL( "CVcXmlParser::ResolveFolderTagL" );
+    
+    // Use specific resource file for folder strings if specified
+    CVcResource* mainResource = iResource;
+    
+    CVcResource* newResource( NULL );
+    TPtrC locFile = Find16ValueL( KXmlLocFileAttr, aAttributes );
+    if ( locFile != KNullDesC )
+        {
+        newResource = CVcResource::NewL( iRFs, locFile );
+        }
+                  
+    if ( newResource )
+        {
+        iResource = newResource;
+        CleanupStack::PushL( mainResource );
+        }    
+    
+    // Find folder name
+    TBool resolved = ResolveLocalizedTagL( aName, aAttributes, KXmlFolderTag, 
+                                           EXmlFolder );
+    if ( resolved )
+        {
+        delete iFolder;
+        iFolder = iCurrentLocalizedString;
+        iCurrentLocalizedString = NULL;
+        
+        // Find folder title string
+        TBool titleFound = GetLocalizedStringL( aAttributes, KXmlFolderTitleLocAttr );
+        
+        if ( titleFound )
+            {
+            delete iFolderTitle;
+            iFolderTitle = iCurrentLocalizedString;
+            iCurrentLocalizedString = NULL;
+            }
+            
+        TBool iconFileFound = ResolveFolderIconFileL( aAttributes );
+        RUBY_DEBUG1( "iconFileFound [%d]", iconFileFound );
+        iFolderIconIndex = ResolveFolderIconIndexL( aAttributes );
+       
+        }
+        
+    // Revert back to use the old resource file
+    iResource = mainResource;
+    if ( newResource )
+        {
+        delete newResource;
+        CleanupStack::Pop( mainResource );
+        }
+                
+    return resolved;
+    }
+
+// -----------------------------------------------------------------------------
+// CVcXmlParser::ResolveVCommandTagL
+// Resolves the content of <vcommand>
+// -----------------------------------------------------------------------------
+//
+TBool CVcXmlParser::ResolveVCommandTagL( const TDesC8& aName, 
+                                         const Xml::RAttributeArray& aAttributes )
+    {
+    RUBY_DEBUG_BLOCKL( "CVcXmlParser::ResolveVCommandTagL" );
+    
+    TBool resolved( EFalse );
+    if ( aName == KXmlVCommandTag )
+        {
+        resolved = ETrue;
+        iXmlNesting.Append( EXmlVCommand );
+        }
+    
+    if ( resolved )
+        {
+        // TTS on/off  
+        resolved = CheckAttributeL( aAttributes, KXmlTtsAttr, KXmlTrueValue );
+        if ( resolved )
+            {
+            // By default, tts is on
+            iStartImmediately = ETrue;
+            }
+        
+        // Modifiable on/off
+        resolved = CheckAttributeL( aAttributes, KXmlModifiableAttr, KXmlFalseValue );
+        if ( resolved )
+            {
+            iUserCanModify = EFalse;
+            }
+            
+        resolved = ETrue;
+        }
+
+    return resolved;
+    }
+
+
+// -----------------------------------------------------------------------------
+// CVcXmlParser::ResolveSpokenTagL
+// Resolves the content of <spoken>
+// -----------------------------------------------------------------------------
+//
+TBool CVcXmlParser::ResolveSpokenTagL( const TDesC8& aName, 
+                                       const Xml::RAttributeArray& aAttributes )
+    {
+    RUBY_DEBUG_BLOCKL( "CVcXmlParser::ResolveSpokenTagL" );
+    
+    TBool resolved = ResolveLocalizedTagL( aName, aAttributes, KXmlSpokenTag, 
+                                           EXmlSpoken );
+
+    if ( resolved )
+        {
+        delete iSpokenText;
+        iSpokenText = iCurrentLocalizedString;
+        iCurrentLocalizedString = NULL;
+        }
+    return resolved;
+    }
+
+// -----------------------------------------------------------------------------
+// CVcXmlParser::ResolveWrittenTagL
+// Resolves the content of <written>
+// -----------------------------------------------------------------------------
+//
+TBool CVcXmlParser::ResolveWrittenTagL( const TDesC8& aName,
+                                        const Xml::RAttributeArray& aAttributes )
+    {
+    RUBY_DEBUG_BLOCKL( "CVcXmlParser::ResolveWrittenTagL" );
+    
+    TBool resolved = ResolveLocalizedTagL( aName, aAttributes, KXmlWrittenTag, 
+                                           EXmlWritten );
+    if ( resolved )
+        {
+        delete iWrittenText;
+        iWrittenText = iCurrentLocalizedString;
+        iCurrentLocalizedString = NULL;
+        }
+    return resolved;
+    }
+
+// -----------------------------------------------------------------------------
+// CVcXmlParser::ResolveTooltipTagL
+// Resolves the content of <tooltip>
+// -----------------------------------------------------------------------------
+//
+TBool CVcXmlParser::ResolveTooltipTagL( const TDesC8& aName,
+                                        const Xml::RAttributeArray& aAttributes )
+    {
+    RUBY_DEBUG_BLOCKL( "CVcXmlParser::ResolveTooltipTagL" );
+    
+    TBool resolved = ResolveLocalizedTagL( aName, aAttributes, KXmlTooltipTag, 
+                                           EXmlTooltip );
+    if ( resolved )
+        {
+        delete iTooltipText;
+        iTooltipText = iCurrentLocalizedString;
+        iCurrentLocalizedString = NULL;
+        }
+    return resolved;
+    }
+
+// -----------------------------------------------------------------------------
+// CVcXmlParser::ResolveLocalizedTagL
+// Resolves content of tag which contains localized data
+// -----------------------------------------------------------------------------
+//
+TBool CVcXmlParser::ResolveLocalizedTagL( const TDesC8& aName,
+                                          const Xml::RAttributeArray& aAttributes,
+                                          const TDesC8& aExpectedName,
+                                          TVcXmlTagNesting aTagEnum )
+    {
+    RUBY_DEBUG_BLOCKL( "CVcXmlParser::ResolveLocalizedTagL" );
+    
+    TBool resolved( EFalse );
+    if ( aName == aExpectedName )
+        {
+        resolved = ETrue;
+        iXmlNesting.Append( aTagEnum );
+        
+        resolved = GetLocalizedStringL( aAttributes, KXmlLocAttr );
+        }
+
+    return resolved;
+    }
+
+// -----------------------------------------------------------------------------
+// CVcXmlParser::ResolveExecutesTagL
+// Resolves the content of <executes>
+// -----------------------------------------------------------------------------
+//
+TBool CVcXmlParser::ResolveExecutesTagL( const TDesC8& aName,
+                                         const Xml::RAttributeArray& aAttributes )
+    {
+    RUBY_DEBUG_BLOCKL( "CVcXmlParser::ResolveExecutesTagL" );
+    
+    TBool resolved( EFalse );
+   
+    if ( aName == KXmlExecutesTag )
+        {
+        resolved = ETrue;
+        iXmlNesting.Append( EXmlExecutes );
+
+        iAppId = ResolveUidL( aAttributes );
+        if ( iAppId == KNullUid )
+            {
+            resolved = ResolveExeL( aAttributes );
+            }
+        }
+
+    return resolved;
+    }
+
+// -----------------------------------------------------------------------------
+// CVcXmlParser::ResolveCmdlineparamsTag
+// Resolves the content of <cmdlineparams>
+// -----------------------------------------------------------------------------
+//
+TBool CVcXmlParser::ResolveCmdlineparamsTag( const TDesC8& aName, 
+                                             const Xml::RAttributeArray& /*aAttributes*/ )
+    {
+    TBool resolved( EFalse );
+    
+    if ( aName == KXmlCmdlineparamsTag )
+        {
+        iXmlNesting.Append( EXmlCmdlineparams );
+        delete iParameters;
+        delete iParameters8;
+        iParameters = NULL;
+        iParameters8 = NULL;
+        resolved = ETrue;        
+        }
+        
+    return resolved;
+    }
+
+// -----------------------------------------------------------------------------
+// CVcXmlParser::ResolveIconTagL
+// Resolves the content of <icon>
+// -----------------------------------------------------------------------------
+//
+TBool CVcXmlParser::ResolveIconTagL( const TDesC8& aName,
+                                     const Xml::RAttributeArray& aAttributes )
+    {
+    RUBY_DEBUG_BLOCKL( "CVcXmlParser::ResolveIconTagL" );
+    
+    TBool resolved( EFalse );
+    
+    if ( aName == KXmlIconTag )
+        {
+        resolved = ETrue;
+        iXmlNesting.Append( EXmlIcon );
+
+        iIcon = ResolveUidL( aAttributes );
+        if ( iIcon == KNullUid )
+            {
+            resolved = EFalse;
+            }
+        }
+
+    return resolved;
+    }
+
+// -----------------------------------------------------------------------------
+// CVcXmlParser::Find16ValueL
+// Finds a certain attribute and returns its value as unicode
+// -----------------------------------------------------------------------------
+//
+const TDesC& CVcXmlParser::Find16ValueL( const TDesC8& aName, 
+                                         const Xml::RAttributeArray& aAttributes )
+    {
+    RUBY_DEBUG_BLOCKL( "CVcXmlParser::Find16ValueL" );
+    
+    delete iAttributeValue;
+    iAttributeValue = NULL;
+    
+    iAttributeValue = CnvUtfConverter::ConvertToUnicodeFromUtf8L( Find8ValueL( aName, aAttributes ) );
+       
+    return *iAttributeValue;
+    }
+
+// -----------------------------------------------------------------------------
+// CVcXmlParser::Find8ValueL
+// Finds a certain attribute and returns its value as utf-8
+// -----------------------------------------------------------------------------
+//
+const TDesC8& CVcXmlParser::Find8ValueL( const TDesC8& aName, 
+                                         const Xml::RAttributeArray& aAttributes )
+    {
+    RUBY_DEBUG_BLOCKL( "CVcXmlParser::Find8ValueL" );
+    
+    // Loop through attribute list
+    for ( TInt iCounter = 0 ; iCounter < aAttributes.Count() ; iCounter++ )
+        {
+        HBufC8* name = ToLowercaseLC( aAttributes[iCounter].Attribute().LocalName().DesC() );
+        
+        if ( name->Des() == aName )
+            {
+            CleanupStack::PopAndDestroy( name );
+
+            return aAttributes[iCounter].Value().DesC();
+            }
+        CleanupStack::PopAndDestroy( name );
+        }
+        
+    return KNullDesC8;
+    }
+    
+// -----------------------------------------------------------------------------
+// CVcXmlParser::ResetVCommandFolder
+// Destroys the data of one voice command folder
+// -----------------------------------------------------------------------------
+//
+void CVcXmlParser::ResetVCommandFolder()
+    {
+    delete iFolder;
+    iFolder = HBufC16::New( 0 );
+    
+    delete iFolderTitle;
+    iFolderTitle = HBufC16::New( 0 );
+    
+    delete iFolderIconFile;
+    iFolderIconFile = HBufC16::New( 0 );
+    
+    iFolderIconIndex = -1;
+    
+    ResetVCommandInfo();
+    }
+
+// -----------------------------------------------------------------------------
+// CVcXmlParser::ResetVCommandInfo
+// Destroys the data of one voice command
+// -----------------------------------------------------------------------------
+//
+void CVcXmlParser::ResetVCommandInfo()
+    {
+    delete iWrittenText;
+    iWrittenText = NULL;
+    delete iSpokenText;
+    iSpokenText = NULL;
+    delete iTooltipText;
+    iTooltipText = NULL;
+    delete iParameters;
+    iParameters = NULL;
+    delete iParameters8;
+    iParameters8 = NULL;
+    delete iAppName;
+    iAppName = NULL;
+    
+    iAppId = KNullUid;
+    iIcon = KNullUid;
+    
+    iStartImmediately = EFalse;
+    iUserCanModify = ETrue;
+    }
+
+// -----------------------------------------------------------------------------
+// CVcXmlParser::CheckVoiceCommmandData
+// Checks if all mandatory data for one voice command is available and makes
+// callback based on that
+// -----------------------------------------------------------------------------
+//
+void CVcXmlParser::CheckVoiceCommmandData()
+    {
+    if ( iWrittenText && ( iAppId != KNullUid || iAppName ) )
+        {
+        RUBY_DEBUG0( "CVcXmlParser::CheckVoiceCommmandData(): All required data for voice command found ok" );
+        
+        // folder icon file is optional
+        // if it is not present, reference to KNullDesC should be passed
+        const TDesC* pFolderIconFile =iFolderIconFile;
+        if( !pFolderIconFile )
+            {
+            pFolderIconFile = &KNullDesC;
+            }
+        
+        iObserver.MvcxpoVoiceCommandFound( *iWrittenText, *iSpokenText, 
+                                           *iTooltipText, *iFolder, *iFolderTitle, 
+                                           *iParameters, iIcon,
+                                           iAppId, *iAppName,
+                                           iStartImmediately, iUserCanModify,
+                                           *pFolderIconFile, iFolderIconIndex );
+        }
+    else
+        {
+        RUBY_DEBUG0( "VC XML ERROR: Mandatory data not found for Voice Command" );
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CVcXmlParser::GetLocalizedStringL
+// Reads localized string from resource file
+// -----------------------------------------------------------------------------
+//
+TBool CVcXmlParser::GetLocalizedStringL( const Xml::RAttributeArray& aAttributes,
+                                         const TDesC8& aAttributeName )
+    {
+    RUBY_DEBUG_BLOCKL( "CVcXmlParser::GetLocalizedStringL" );
+    
+    TBool resolved( EFalse );
+    iCurrentLocalizedString = NULL;
+    
+    // Resource file object should have been initialized
+    if ( !iResource )
+        {
+        return resolved;
+        }
+
+    // locIndex is key to the localized resource file
+    TPtrC8 locAttr( aAttributeName );    
+    TPtrC locIndex = Find16ValueL( locAttr, aAttributes );
+    
+    if ( locIndex != KNullDesC )
+        {
+        HBufC* command = NULL;
+        // Find string from loc file based on key
+        TRAPD( error,  command = &iResource->GetCommandL( locIndex ) );
+        if ( error == KErrNone )
+            {
+            // Make a copy of localized string
+            TPtr des = command->Des();
+            delete iCurrentLocalizedString;
+            iCurrentLocalizedString = des.Alloc();
+            resolved = ETrue;
+            }
+        else
+            {
+            resolved = EFalse;
+            iCurrentLocalizedString = NULL;
+            RUBY_DEBUG0( "VC XML ERROR: Cannot resolve localized string" );
+            User::Leave( KErrGeneral );
+            }
+        }
+        
+    return resolved;
+    }
+
+// -----------------------------------------------------------------------------
+// CVcXmlParser::ResolveUidL
+// Resolves the content of uid="0x1234567" attribute
+// -----------------------------------------------------------------------------
+//
+TUid CVcXmlParser::ResolveUidL( const Xml::RAttributeArray& aAttributes )
+    {
+    RUBY_DEBUG_BLOCKL( "CVcXmlParser::ResolveUidL" );
+    
+    _LIT( KHexIdentifierLowercase, "0x" );
+    _LIT( KHexIdentifierUppercase, "0X" );
+    const TInt KHexIndentifierLength = 2;
+    
+    TUid newUid( KNullUid );
+    
+    TPtrC uidDes = Find16ValueL( KXmlUidAttr, aAttributes );
+    
+    if ( uidDes != KNullDesC )
+        {
+        TPtrC ptr( uidDes );
+        // Check if string starts with 0x or 0X
+        if ( ( uidDes.Find( KHexIdentifierLowercase ) == 0 ) ||
+             ( uidDes.Find( KHexIdentifierUppercase ) == 0 ) )
+            {
+            ptr.Set( uidDes.Right( uidDes.Length() - KHexIndentifierLength ) );
+            }
+        
+        // Do conversion from string to number
+        TLex lex( ptr );
+        TInt64 intUid( 0 );
+        TInt error = lex.Val( intUid, EHex );
+        newUid.iUid = intUid;
+        }
+        
+    return newUid;
+    }
+
+// -----------------------------------------------------------------------------
+// CVcXmlParser::ResolveExeL
+// Resolves the content of exe="name.exe" attribute
+// -----------------------------------------------------------------------------
+//
+TBool CVcXmlParser::ResolveExeL( const Xml::RAttributeArray& aAttributes )
+    {
+    RUBY_DEBUG_BLOCKL( "CVcXmlParser::ResolveExeL" );
+    
+    TBool resolved( EFalse );
+    
+    TPtrC nameDes = Find16ValueL( KXmlExeAttr, aAttributes );
+    if ( nameDes != KNullDesC )
+        {
+        delete iAppName;
+        iAppName = NULL;
+        
+        iAppName = HBufC::NewL( nameDes.Length() );
+        TPtr namePtr = iAppName->Des();
+        namePtr.Copy( nameDes );
+        
+        resolved = ETrue;
+        }
+        
+    return resolved;
+    }
+    
+// -----------------------------------------------------------------------------
+// CVcXmlParser::ToLowercaseLC
+// Converts given string to lowercase
+// -----------------------------------------------------------------------------
+//
+HBufC8* CVcXmlParser::ToLowercaseLC( const TDesC8& aString )
+    {
+    // RUBY_DEBUG0( "CVcXmlParser::ToLowercaseLC START" );
+    
+    // Convert string to lowercase    
+    HBufC8* string = HBufC8::NewL( aString.Length() );
+    CleanupStack::PushL( string );
+    TPtr8 des = string->Des();
+    des.Copy( aString );
+    des.LowerCase();
+    
+    //RUBY_DEBUG0( "CVcXmlParser::ToLowercaseLC EXIT" );
+    
+    return string;
+    }
+
+// -----------------------------------------------------------------------------
+// Reads the iconfile attribute and constructs the file name or
+// sets it to NULL
+// 
+// @params aAttributes List of XML attributes
+// @return ETrue if resolved successfully, EFalse otherwise
+// -----------------------------------------------------------------------------
+TBool CVcXmlParser::ResolveFolderIconFileL( const Xml::RAttributeArray& aAttributes )
+	{
+    RUBY_DEBUG_BLOCKL( "CVcXmlParser::ResolveFolderIconFileL" );
+    
+    TBool resolved( EFalse );
+    delete iFolderIconFile;
+    iFolderIconFile = NULL;
+    
+    TPtrC nameDes = Find16ValueL( KXmlFolderIconFileAttr, aAttributes );
+    if ( nameDes != KNullDesC )
+        {
+        iFolderIconFile = HBufC::NewL( nameDes.Length() );
+        TPtr folderIconFilePtr = iFolderIconFile->Des();
+        folderIconFilePtr.Copy( nameDes );
+        
+        resolved = ETrue;
+        }
+        
+    return resolved;
+	
+	}
+
+// -----------------------------------------------------------------------------
+// Reads the iconindex attribute and stores the index or sets it to 0
+// 
+// @params aAttributes List of XML attributes
+// @return ETrue if resolved successfully, EFalse otherwise
+// -----------------------------------------------------------------------------
+TInt CVcXmlParser::ResolveFolderIconIndexL( const Xml::RAttributeArray& aAttributes )
+	{
+	RUBY_DEBUG_BLOCKL( "CVcXmlParser::ResolveFolderIconIndexL" );
+	
+	TInt index = -1;
+    
+    TPtrC indexDes = Find16ValueL( KXmlFolderIconIndexAttr, aAttributes );
+    
+    if ( indexDes != KNullDesC )
+        {
+        TPtrC ptr( indexDes );
+        
+        // Do conversion from string to number
+        TLex lex( ptr );
+        TInt error = lex.Val( index );
+        if( error != KErrNone )
+        	{
+        	RUBY_ERROR1( "Converting icon index from string to int resulted in [%d]", error );
+        	index = -1;
+        	}
+        }
+        
+    return index;	
+	}
+
+// End of File