upnpsharing/upnpsharingalgorithm/src/upnpcontainerresolver.cpp
author Sampo Huttunen <sampo.huttunen@nokia.com>
Wed, 24 Nov 2010 09:39:46 +0200
branchIOP_Improvements
changeset 45 a6c41ca11adf
parent 40 08b5eae9f9ff
permissions -rw-r--r--
Updated the SIS package, there was some BC issue with the earlier version. Also updated the platform UID to S^3 version.

/*
* Copyright (c) 2009 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 the class CUpnpContainerResolver.
*
*/

#include "upnpconstantdefs.h"        // upnpobject class types
#include <utf.h>                     // for CnvUtfConverter
#include <bautils.h>                 // for BaflUtils
#include <pathinfo.h>                // for PathInfo
#include <upnpitem.h>                // for CUpnpItem
#include <upnpelement.h>             // for CUpnpElement
#include "upnpitemutility.h"         // for CUpnpItemUtility
#include <upnpsharingalgorithm.rsg>
#include <mm/mmcleanup.h>            // for array cleanup

#include "upnpcontainerresolver.h"
#include "upnpsharingalgorithmconstants.h"
#include "upnplog.h"
#include "upnpcdsliteobject.h"

const TInt KDateStringLength = 10;
const TInt KMaxDateStringLength = 30;
const TInt KMonthAndDayLength = 2;
const TInt KMonthAndDayDigitLimit = 10;
const TInt KSeparatorLength = 1;
const TInt KDateYearLength = 4;
const TInt KSecondSeparatorPosition = 7;

_LIT( KZero, "0" );

// Year, e.g. "2008"
_LIT( KDateTimeYear,"%Y%3" );

// Month, e.g. "October"
_LIT( KDateTimeMonth,"%N%2" );

// Day, e.g. "4th Mon"
_LIT( KDateTimeDay,"%X%*D%1 %*E" );


// --------------------------------------------------------------------------
// CUpnpContainerResolver::NewL
// --------------------------------------------------------------------------
//
CUpnpContainerResolver* CUpnpContainerResolver::NewL(
    CUpnpCdsLiteObjectArray& aCdsLiteObjectArray )
    {
    __LOG( "[CUpnpSharingAlgorithm]\t CUpnpContainerResolver::NewL" );

    CUpnpContainerResolver* self =
        new ( ELeave ) CUpnpContainerResolver( aCdsLiteObjectArray );
    CleanupStack::PushL( self );
    self->ConstructL();
    CleanupStack::Pop( self );

    return self;
    }

// --------------------------------------------------------------------------
// CUpnpContainerResolver::ResolveContainerStructureL
// --------------------------------------------------------------------------
//
RPointerArray<CUpnpContainer>
    CUpnpContainerResolver::ResolveContainerStructureL( CUpnpItem& aItem )
    {
    __LOG( "[CUpnpSharingAlgorithm]\t CUpnpContainerResolver::\
ResolveContainerStructureL" );

    // List of needed containers
    RPointerArray<CUpnpContainer> containers;
    CleanupResetAndDestroyPushL( containers );

    RPointerArray<HBufC8> containerNames;
    CleanupResetAndDestroyPushL( containerNames );

    HBufC8* itemParent = NULL;

    if ( aItem.ObjectClass() == KClassAudioMusicTrack )
        {
        // Fill container name array, containers must be in
        // hierarchical order staring from root
        AppendContainerNameToArrayL( containerNames,
                                     R_UPNP_SHARE_MUSIC_TEXT );
        AppendContainerNameToArrayL( containerNames,
                                     R_UPNP_SHARE_ALL_TEXT );

        // Create non-existing containers
        itemParent = CreateContainersL( containerNames,
                                        containers,
                                        KMusicClassContainer );
        CleanupStack::PushL( itemParent );
        }
    else if ( aItem.ObjectClass() == KClassImage )
        {
        AppendContainerNameToArrayL( containerNames,
                                     R_UPNP_SHARE_IMAGE_TEXT );
        AppendContainerNameToArrayL( containerNames,
                                     R_UPNP_SHARE_ALL_TEXT );

        itemParent = CreateContainersL( containerNames,
                                        containers,
                                        KImageClassContainer );
        CleanupStack::PushL( itemParent );
        }
    else if ( aItem.ObjectClass() == KClassVideo )
        {
        AppendContainerNameToArrayL( containerNames,
                                     R_UPNP_SHARE_VIDEO_TEXT );
        AppendContainerNameToArrayL( containerNames,
                                     R_UPNP_SHARE_ALL_TEXT );

        itemParent = CreateContainersL( containerNames,
                                        containers,
                                        KVideoClassContainer );
        CleanupStack::PushL( itemParent );
        }

    // If new containers are not needed, set item parent id here,
    // because caller does not know the item parent container
    if ( !containers.Count() )
        {
        aItem.SetParentIdL( *itemParent );
        }
    if ( itemParent )
        {
        CleanupStack::PopAndDestroy( itemParent );
        }

    // Cleanup
    CleanupStack::PopAndDestroy( &containerNames );
    CleanupStack::Pop( &containers );

    return containers;
    }

// --------------------------------------------------------------------------
// CUpnpContainerResolver::ResolveReferenceContainersL
// --------------------------------------------------------------------------
//
RPointerArray<CUpnpContainer>
    CUpnpContainerResolver::ResolveReferenceContainersL( TInt aType,
                                                         CUpnpItem& aItem )
    {
    __LOG( "[CUpnpSharingAlgorithm]\t CUpnpContainerResolver::\
ResolveReferenceContainersL" );

    // List of needed containers
    RPointerArray<CUpnpContainer> containers;
    CleanupResetAndDestroyPushL( containers );

    RPointerArray<HBufC8> containerNames;
    CleanupResetAndDestroyPushL( containerNames );

    HBufC8* itemParent = NULL;
    TInt error( KErrNone );

    // Get object elements from where metadata is fetched
    const RUPnPElementsArray& elements = aItem.GetElements();

    switch( aType )
        {
        case EGenreType :
            {
            // Fill container name array, containers must be in
            // hierarchical order starting from root
            AppendContainerNameToArrayL( containerNames,
                                         R_UPNP_SHARE_MUSIC_TEXT );
            // Append "By Genre" container
            AppendContainerNameToArrayL( containerNames,
                                         R_UPNP_SHARE_BY_GENRE_TEXT );

            // Modify "Genre" element and append it to the array
            TRAP( error, ModifyAndAppendElementL( containerNames,
                                                  elements,
                                                  KElementGenre ));

            // If metadata is missing, containers are not created
            if ( error == KErrNone )
                {
                // Create non-existing containers
                itemParent = CreateContainersL( containerNames,
                                                containers,
                                                KMusicClassContainer );
                CleanupStack::PushL( itemParent );
                }
            break;
            }
        case EAlbumType :
            {
            // Fill container name array, containers must be in
            // hierarchical order staring from root
            AppendContainerNameToArrayL( containerNames,
                                         R_UPNP_SHARE_MUSIC_TEXT );
            // Append "By Album" container
            AppendContainerNameToArrayL( containerNames,
                                         R_UPNP_SHARE_BY_ALBUM_TEXT );

            // Modify "Album" element and append it to the array
            TRAP( error, ModifyAndAppendElementL( containerNames,
                                                  elements,
                                                  KElementAlbum ));

            // If metadata is missing, containers are not created
            if ( error == KErrNone )
                {
                // Create non-existing containers
                itemParent = CreateContainersL( containerNames,
                                                containers,
                                                KMusicClassContainer );
                CleanupStack::PushL( itemParent );
                }
            break;
            }
        case EArtistType :
            {
            // Fill container name array, containers must be in
            // hierarchical order staring from root
            AppendContainerNameToArrayL( containerNames,
                                         R_UPNP_SHARE_MUSIC_TEXT );
            // Append "By Artist" container
            AppendContainerNameToArrayL( containerNames,
                                         R_UPNP_SHARE_BY_ARTIST_TEXT );

            // Modify "Artist" element and append it to the array
            TRAP( error, ModifyAndAppendElementL( containerNames,
                                                  elements,
                                                  KElementArtist ));

            // If metadata is missing, containers are not created
            if ( error == KErrNone )
                {
                // Create non-existing containers
                itemParent = CreateContainersL( containerNames,
                                                containers,
                                                KMusicClassContainer );
                CleanupStack::PushL( itemParent );
                }
            break;
            }
        case EMusicByDateType :
            {
            // Fill container name array, containers must be in
            // hierarchical order staring from root
            AppendContainerNameToArrayL( containerNames,
                                         R_UPNP_SHARE_MUSIC_TEXT );
            // Append "By Date" container
            AppendContainerNameToArrayL( containerNames,
                                         R_UPNP_SHARE_BY_DATE_TEXT );

            TTime time;
            HBufC8* elementValue = GetElementL( elements, KElementDate );
            if ( elementValue )
                {
                CleanupStack::PushL( elementValue );
                HBufC8* adjustedDate = AdjustDateL( *elementValue );
                CleanupStack::PopAndDestroy( elementValue );
                CleanupStack::PushL( adjustedDate );

                error = UPnPItemUtility::UPnPDateAsTTime( *adjustedDate,
                                                          time );

                CleanupStack::PopAndDestroy( adjustedDate );

                if ( error == KErrNone &&
                     adjustedDate->Length() > 0 )
                    {
                    TBuf<KMaxDateStringLength> finalTime;

                    // Append Year container
                    time.FormatL( finalTime, KDateTimeYear );
                    HBufC8* timeStr =
                        CnvUtfConverter::ConvertFromUnicodeToUtf8L(
                        finalTime );
                    CleanupStack::PushL( timeStr );
                    containerNames.Append( timeStr );
                    CleanupStack::Pop( timeStr );

                    // Create non-existing containers
                    itemParent = CreateContainersL( containerNames,
                                                    containers,
                                                    KMusicClassContainer );
                    CleanupStack::PushL( itemParent );
                    }
                }
            else
                {
                error = KErrNotFound;
                }

            break;
            }
        case EImageByDateType :
            {
            // Fill container name array, containers must be in
            // hierarchical order staring from root
            AppendContainerNameToArrayL( containerNames,
                                         R_UPNP_SHARE_IMAGE_TEXT );

            error = AddByDateContainersL( containerNames, elements );

            // If metadata is missing, containers are not created
            if ( error == KErrNone )
                {
                // Create non-existing containers
                itemParent = CreateContainersL( containerNames,
                                                containers,
                                                KImageClassContainer );
                CleanupStack::PushL( itemParent );
                }
            break;
            }
        case EVideoByDateType :
            {
            // Fill container name array, containers must be in
            // hierarchical order staring from root
            AppendContainerNameToArrayL( containerNames,
                                         R_UPNP_SHARE_VIDEO_TEXT );

            error = AddByDateContainersL( containerNames, elements );

            // If metadata is missing, containers are not created
            if ( error == KErrNone )
                {
                // Create non-existing containers
                itemParent = CreateContainersL( containerNames,
                                                containers,
                                                KVideoClassContainer );
                CleanupStack::PushL( itemParent );
                }
            break;
            }
        default:
            {
            User::Leave( KErrNotSupported );
            break;
            }
        }

    // If new containers are not needed, set item parent id here,
    // because caller does not know the item parent container.
    // If metadata is not found, item is left untouched.
    if ( !containers.Count() &&
         error == KErrNone )
        {
        aItem.SetParentIdL( *itemParent );
        }

    if ( itemParent )
        {
        CleanupStack::PopAndDestroy( itemParent );
        }

    // Cleanup
    CleanupStack::PopAndDestroy( &containerNames );
    CleanupStack::Pop( &containers );

    return containers;
    }

// --------------------------------------------------------------------------
// CUpnpContainerResolver::ResolveEmptyContainersL
// --------------------------------------------------------------------------
//
RPointerArray<CUpnpCdsLiteObject>
    CUpnpContainerResolver::ResolveEmptyContainersL( TDesC8& aContainerId )
    {
    __LOG( "[CUpnpSharingAlgorithm]\t CUpnpContainerResolver::\
ResolveEmptyContainersL" );

    RPointerArray<CUpnpCdsLiteObject> emptyContainers;
    TBool empty( ETrue );
    const TDesC8* parentId = &aContainerId;

    // Search empty containers from the array
    while ( empty &&
            parentId->Match( KRootContainer ) == KErrNotFound )
        {
        TInt count = iCdsLiteObjectArray.ChildCount( aContainerId );
        if ( iCdsLiteObjectArray.ChildCount( *parentId ) > 1 )
            {
            // There is more than one item inside container
            // Current container must not be removed, exit loop
            empty = EFalse;
            }
        else
            {
            // Get object index from CDS object array
            TInt objectIndex =
                iCdsLiteObjectArray.FindByObjectId( *parentId );

            // Append correct container from CDS object array
            emptyContainers.Append(
                &iCdsLiteObjectArray.ObjectAtL( objectIndex ) );

            // Get parent container id of the current container
            parentId =
                &iCdsLiteObjectArray.ObjectAtL( objectIndex ).ParentId();
            }
        }
    return emptyContainers;
    }

// --------------------------------------------------------------------------
// CUpnpContainerResolver::ConstructL
// --------------------------------------------------------------------------
//
void CUpnpContainerResolver::ConstructL()
    {
    __LOG( "[CUpnpSharingAlgorithm]\t CUpnpContainerResolver::\
ConstructL" );

    // Open file server session
    User::LeaveIfError( iFs.Connect() );

    TFileName resourceFileName( KSharingAlgorithmRscFile );

    // Get the exact filename of the resource file
    BaflUtils::NearestLanguageFile( iFs, resourceFileName );

    TInt err( KErrNone );
    // Open resource file
    TRAP( err, iResourceFile.OpenL( iFs, resourceFileName ) );

    if ( err != KErrNone )
        {
        // If not found, try to read resource file from memory card
        resourceFileName.Copy( PathInfo::MemoryCardRootPath() );
        resourceFileName.Delete( 2, 2 ); // remove //
        resourceFileName.Append( KSharingAlgorithmRscFile );
        iResourceFile.OpenL( iFs, resourceFileName );
        }
    }

// --------------------------------------------------------------------------
// CCUpnpContainerResolver::~CUpnpContainerResolver
// --------------------------------------------------------------------------
//
CUpnpContainerResolver::~CUpnpContainerResolver()
    {
    __LOG( "[CUpnpSharingAlgorithm]\t CUpnpContainerResolver::\
~CUpnpContainerResolver" );

    // Close resource file
    iResourceFile.Close();

    // Close file server session
    iFs.Close();
    }

// --------------------------------------------------------------------------
// CCUpnpContainerResolver::CreateContainerL
// --------------------------------------------------------------------------
//
CUpnpContainer* CUpnpContainerResolver::CreateContainerL(
    const TDesC8& aTitle,
    const TDesC8& aClass )
    {
    __LOG( "[CUpnpSharingAlgorithm]\t CUpnpContainerResolver::\
CreateContainerL" );

    CUpnpContainer* container = CUpnpContainer::NewL();
    CleanupStack::PushL( container );

    // Set container info
    container->SetTitleL( aTitle );
    container->SetObjectClassL( aClass );

    CleanupStack::Pop( container );

    return container;
    }

// --------------------------------------------------------------------------
// CCUpnpContainerResolver::CreateContainersL
// --------------------------------------------------------------------------
//
HBufC8* CUpnpContainerResolver::CreateContainersL(
        RPointerArray<HBufC8>& aContainerNames,
        RPointerArray<CUpnpContainer>& aContainers,
        const TDesC8& aMediaClass )
    {
    __LOG( "[CUpnpSharingAlgorithm]\t CUpnpContainerResolver::\
CreateContainersL" );

    HBufC8* parentId = NULL;
    TInt index( 1 );

    // Find first media container, e.g. "Music"
    TInt objectIndex ( iCdsLiteObjectArray.FindByMediaClassAndParentId(
        aMediaClass, KRootContainer ) );

    if ( objectIndex == KErrNotFound )
        {
        // Create media root container and append it to the container array.
        // Parent container is root container ("0")
        if ( aContainerNames.Count() )
            {
            CUpnpContainer* container = CreateContainerL(
                                          *aContainerNames[0], aMediaClass );
            CleanupStack::PushL( container );
            aContainers.Append( container );
            CleanupStack::Pop( container );
            }
        parentId = KRootContainer().AllocL();
        }
    else
        {
        // Remember media root container id
        parentId = iCdsLiteObjectArray.ObjectAtL(
                            objectIndex ).ObjectId().AllocL();
        }

    // Find the first container that does not exist
    for ( ; index < aContainerNames.Count(); index++ )
        {
        // Container is found by container name and parent id.
        // If search cannot find the container, it needs to be created.
        objectIndex = iCdsLiteObjectArray.FindByNameAndParentId(
            *aContainerNames[index], *parentId );

        if ( objectIndex == KErrNotFound )
            {
            break;
            }
        else
            {
            // Remember last found container id
            parentId = iCdsLiteObjectArray.ObjectAtL(
                                    objectIndex ).ObjectId().AllocL();
            }
        }

    // Create needed containers
    for ( TInt index2( index ); index2 < aContainerNames.Count(); index2++ )
        {
        CUpnpContainer* container = CreateContainerL(
                                     *aContainerNames[index2], aMediaClass );
        CleanupStack::PushL( container );
        aContainers.Append( container );
        CleanupStack::Pop( container );
        }

    // Use the last found object id as parent id of the first new container
    if ( aContainers.Count() )
        {
        aContainers[0]->SetParentIdL( *parentId );
        }

    return parentId;
    }

// --------------------------------------------------------------------------
// CUpnpContainerResolver::ReadResourceTextL
// --------------------------------------------------------------------------
//
HBufC8* CUpnpContainerResolver::ReadResourceTextL( TInt aResourceId )
    {
    __LOG( "[CUpnpSharingAlgorithm]\t CUpnpContainerResolver::\
ReadResourceTextL" );

    // Load resource text
    HBufC8* resourceString8 = iResourceFile.AllocReadLC( aResourceId );

    TResourceReader theReader;
    theReader.SetBuffer( resourceString8 );
    HBufC16* resourceString16 = theReader.ReadHBufC16L();
    CleanupStack::PushL( resourceString16 );

    HBufC8* returnString8 = CnvUtfConverter::ConvertFromUnicodeToUtf8L(
        resourceString16->Des() );

    CleanupStack::PopAndDestroy( resourceString16 );
    CleanupStack::PopAndDestroy( resourceString8 );

    return returnString8;
    }

// --------------------------------------------------------------------------
// CUpnpContainerResolver::GetElementL
// --------------------------------------------------------------------------
//
HBufC8* CUpnpContainerResolver::GetElementL(
        const RUPnPElementsArray& aElements,
        const TDesC8& aElement )
    {
    __LOG( "[CUpnpSharingAlgorithm]\t CUpnpContainerResolver::\
GetElementL" );

    HBufC8* elementValue = NULL;

    // Find the element
    for( TInt index = 0; index < aElements.Count(); index++ )
        {
        if( aElements[index]->Name().Match( aElement ) == KErrNone )
            {
            elementValue = aElements[index]->Value().AllocL();
            index = aElements.Count();
            }
        }

    return elementValue;
    }

// --------------------------------------------------------------------------
// CUpnpContainerResolver::AdjustDateL
// --------------------------------------------------------------------------
//
HBufC8* CUpnpContainerResolver::AdjustDateL( const TDesC8& aDate )
    {
    __LOG( "[CUpnpSharingAlgorithm]\t CUpnpContainerResolver::\
AdjustDateL" );

    HBufC* date = CnvUtfConverter::ConvertToUnicodeFromUtf8L( aDate );
    CleanupStack::PushL( date );
    TBuf<KMaxDateStringLength> modifiedDate;

    TBuf<KMonthAndDayLength> month;
    TBuf<KMonthAndDayLength> day;

    if( aDate.Length() >= KDateStringLength )
        {
        // Month and day are decreased by 1, because
        // both are started from zero in TTime::Set()
        // Formats date e.g. 2008-10-30 --> 2008-09-29

        // Add year and separator e.g. "2008-"
        modifiedDate.Copy( date->Des().Left(
            ( KDateYearLength + KSeparatorLength ) ) );

        // Adjust month "10" --> "9"
        month.Append( date->Des().Mid(
            ( KDateYearLength + KSeparatorLength ),
            KMonthAndDayLength) );
        TLex monthLex( month );
        TInt monthInt( 0 );
        monthLex.Val( monthInt );
        monthInt--;
        TBuf<KMonthAndDayLength> adjustedMonth;
        adjustedMonth.Num( monthInt );

        // Month and day values need to contain
        // two digits. Append extra zero, if needed,
        // e.g. "9" --> "09"
        if ( monthInt < KMonthAndDayDigitLimit )
            {
            modifiedDate.Append( KZero );
            }

        // Add modified month string
        modifiedDate.Append( adjustedMonth );

        // Add separator "-" that is between month and day
        modifiedDate.Append( date->Des().Mid(
            KSecondSeparatorPosition,
            KSeparatorLength ) );

        // Adjust day e.g. "30" --> "29"
        day.Append( date->Des().Mid(
            ( KSecondSeparatorPosition + KSeparatorLength ),
            KMonthAndDayLength) );
        TLex dayLex( day );
        TInt dayInt( 0 );
        dayLex.Val( dayInt );
        dayInt--;
        TBuf<KMonthAndDayLength> adjustedDay;
        adjustedDay.Num( dayInt );

        if ( dayInt < KMonthAndDayDigitLimit )
            {
            modifiedDate.Append( KZero );
            }

        // Add modified day string
        modifiedDate.Append( adjustedDay );
        }

    CleanupStack::PopAndDestroy( date );

    HBufC8* adjustedDate =
        CnvUtfConverter::ConvertFromUnicodeToUtf8L( modifiedDate );

    return adjustedDate;
    }

// --------------------------------------------------------------------------
// CUpnpContainerResolver::AddByDateContainersL
// --------------------------------------------------------------------------
//
TInt CUpnpContainerResolver::AddByDateContainersL(
                                RPointerArray<HBufC8>& aContainerNames,
                                const RUPnPElementsArray& aElements )
    {
    __LOG( "[CUpnpSharingAlgorithm]\t CUpnpContainerResolver::\
AddByDateContainersL" );

    TInt metadataError( KErrNone );
    TTime time;

    // Append "By Date" container
    aContainerNames.AppendL(
        ReadResourceTextL( R_UPNP_SHARE_BY_DATE_TEXT ) );

    HBufC8* elementValue = GetElementL( aElements, KElementDate );
    if ( elementValue )
        {
        CleanupStack::PushL( elementValue );
        // Get date element and adjust it to match TTime::Set() time
        HBufC8* adjustedDate = AdjustDateL( *elementValue );
        CleanupStack::PopAndDestroy( elementValue );
        CleanupStack::PushL( adjustedDate );

        if ( adjustedDate->Length() <= 0 )
            {
            metadataError = KErrNotFound;
            }

        // Convert date to TTime
        TInt adjustError ( UPnPItemUtility::UPnPDateAsTTime(
            *adjustedDate, time ) );

        CleanupStack::PopAndDestroy( adjustedDate );

        if ( adjustError == KErrNone &&
             metadataError == KErrNone )
            {
            TBuf<KMaxDateStringLength> finalTime;

            // Append Year container
            time.FormatL( finalTime, KDateTimeYear );
            aContainerNames.Append(
                CnvUtfConverter::ConvertFromUnicodeToUtf8L(
                    finalTime ) );

            // Append Month container
            time.FormatL( finalTime, KDateTimeMonth );
            aContainerNames.Append(
                CnvUtfConverter::ConvertFromUnicodeToUtf8L(
                    finalTime ) );

            // Append Day container
            time.FormatL( finalTime, KDateTimeDay );
            aContainerNames.Append(
                CnvUtfConverter::ConvertFromUnicodeToUtf8L(
                    finalTime ) );
            }
        }
    else
        {
        metadataError = KErrNotFound;
        }

    return metadataError;
    }

// --------------------------------------------------------------------------
// CUpnpContainerResolver::ModifyAndAppendElementL
// --------------------------------------------------------------------------
//
void CUpnpContainerResolver::ModifyAndAppendElementL(
                                RPointerArray<HBufC8>& aContainerNames,
                                const RUPnPElementsArray& aElements,
                                const TDesC8& aElementType )
    {
    __LOG( "[CUpnpSharingAlgorithm]\t CUpnpContainerResolver::\
ModifyAndAppendElementL" );

    // Find correct element
    HBufC8* elementValue = GetElementL( aElements, aElementType );
    CleanupStack::PushL( elementValue );
    if ( !elementValue ||
         elementValue->Length() <= 0 )
        {
        User::Leave( KErrNotFound );
        }

    // Set all letters to lower case
    elementValue->Des().LowerCase();

    // Capitalize the first letter of the string
    elementValue->Des().Capitalize();

    // Append modified element value to container names array.
    // aContainerNames array is responsible for deleteting objects in it.
    // Transfer ownership.
    aContainerNames.AppendL( elementValue );

    CleanupStack::Pop( elementValue );
    }

// --------------------------------------------------------------------------
// CUpnpContainerResolver::AppendContainerNameToArrayL
// --------------------------------------------------------------------------
//
void CUpnpContainerResolver::AppendContainerNameToArrayL(
                                            RPointerArray<HBufC8>& aArray,
                                            TInt aResourceTextId )
    {
    __LOG( "[CUpnpSharingAlgorithm]\t CUpnpContainerResolver::\
AppendContainerNameToArrayL" );

    HBufC8* name = ReadResourceTextL( aResourceTextId );
    CleanupStack::PushL( name );
    aArray.AppendL( name );
    CleanupStack::Pop( name );
    }

// End of file