upnpsharing/upnpsharingalgorithm/src/upnpcontainerresolver.cpp
branchIOP_Improvements
changeset 40 08b5eae9f9ff
equal deleted inserted replaced
39:6369bfd1b60d 40:08b5eae9f9ff
       
     1 /*
       
     2 * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  Implementation of the class CUpnpContainerResolver.
       
    15 *
       
    16 */
       
    17 
       
    18 #include "upnpconstantdefs.h"        // upnpobject class types
       
    19 #include <utf.h>                     // for CnvUtfConverter
       
    20 #include <bautils.h>                 // for BaflUtils
       
    21 #include <pathinfo.h>                // for PathInfo
       
    22 #include <upnpitem.h>                // for CUpnpItem
       
    23 #include <upnpelement.h>             // for CUpnpElement
       
    24 #include "upnpitemutility.h"         // for CUpnpItemUtility
       
    25 #include <upnpsharingalgorithm.rsg>
       
    26 #include <mm/mmcleanup.h>            // for array cleanup
       
    27 
       
    28 #include "upnpcontainerresolver.h"
       
    29 #include "upnpsharingalgorithmconstants.h"
       
    30 #include "upnplog.h"
       
    31 #include "upnpcdsliteobject.h"
       
    32 
       
    33 const TInt KDateStringLength = 10;
       
    34 const TInt KMaxDateStringLength = 30;
       
    35 const TInt KMonthAndDayLength = 2;
       
    36 const TInt KMonthAndDayDigitLimit = 10;
       
    37 const TInt KSeparatorLength = 1;
       
    38 const TInt KDateYearLength = 4;
       
    39 const TInt KSecondSeparatorPosition = 7;
       
    40 
       
    41 _LIT( KZero, "0" );
       
    42 
       
    43 // Year, e.g. "2008"
       
    44 _LIT( KDateTimeYear,"%Y%3" );
       
    45 
       
    46 // Month, e.g. "October"
       
    47 _LIT( KDateTimeMonth,"%N%2" );
       
    48 
       
    49 // Day, e.g. "4th Mon"
       
    50 _LIT( KDateTimeDay,"%X%*D%1 %*E" );
       
    51 
       
    52 
       
    53 // --------------------------------------------------------------------------
       
    54 // CUpnpContainerResolver::NewL
       
    55 // --------------------------------------------------------------------------
       
    56 //
       
    57 CUpnpContainerResolver* CUpnpContainerResolver::NewL(
       
    58     CUpnpCdsLiteObjectArray& aCdsLiteObjectArray )
       
    59     {
       
    60     __LOG( "[CUpnpSharingAlgorithm]\t CUpnpContainerResolver::NewL" );
       
    61 
       
    62     CUpnpContainerResolver* self =
       
    63         new ( ELeave ) CUpnpContainerResolver( aCdsLiteObjectArray );
       
    64     CleanupStack::PushL( self );
       
    65     self->ConstructL();
       
    66     CleanupStack::Pop( self );
       
    67 
       
    68     return self;
       
    69     }
       
    70 
       
    71 // --------------------------------------------------------------------------
       
    72 // CUpnpContainerResolver::ResolveContainerStructureL
       
    73 // --------------------------------------------------------------------------
       
    74 //
       
    75 RPointerArray<CUpnpContainer>
       
    76     CUpnpContainerResolver::ResolveContainerStructureL( CUpnpItem& aItem )
       
    77     {
       
    78     __LOG( "[CUpnpSharingAlgorithm]\t CUpnpContainerResolver::\
       
    79 ResolveContainerStructureL" );
       
    80 
       
    81     // List of needed containers
       
    82     RPointerArray<CUpnpContainer> containers;
       
    83     CleanupResetAndDestroyPushL( containers );
       
    84 
       
    85     RPointerArray<HBufC8> containerNames;
       
    86     CleanupResetAndDestroyPushL( containerNames );
       
    87 
       
    88     HBufC8* itemParent = NULL;
       
    89 
       
    90     if ( aItem.ObjectClass() == KClassAudioMusicTrack )
       
    91         {
       
    92         // Fill container name array, containers must be in
       
    93         // hierarchical order staring from root
       
    94         AppendContainerNameToArrayL( containerNames,
       
    95                                      R_UPNP_SHARE_MUSIC_TEXT );
       
    96         AppendContainerNameToArrayL( containerNames,
       
    97                                      R_UPNP_SHARE_ALL_TEXT );
       
    98 
       
    99         // Create non-existing containers
       
   100         itemParent = CreateContainersL( containerNames,
       
   101                                         containers,
       
   102                                         KMusicClassContainer );
       
   103         CleanupStack::PushL( itemParent );
       
   104         }
       
   105     else if ( aItem.ObjectClass() == KClassImage )
       
   106         {
       
   107         AppendContainerNameToArrayL( containerNames,
       
   108                                      R_UPNP_SHARE_IMAGE_TEXT );
       
   109         AppendContainerNameToArrayL( containerNames,
       
   110                                      R_UPNP_SHARE_ALL_TEXT );
       
   111 
       
   112         itemParent = CreateContainersL( containerNames,
       
   113                                         containers,
       
   114                                         KImageClassContainer );
       
   115         CleanupStack::PushL( itemParent );
       
   116         }
       
   117     else if ( aItem.ObjectClass() == KClassVideo )
       
   118         {
       
   119         AppendContainerNameToArrayL( containerNames,
       
   120                                      R_UPNP_SHARE_VIDEO_TEXT );
       
   121         AppendContainerNameToArrayL( containerNames,
       
   122                                      R_UPNP_SHARE_ALL_TEXT );
       
   123 
       
   124         itemParent = CreateContainersL( containerNames,
       
   125                                         containers,
       
   126                                         KVideoClassContainer );
       
   127         CleanupStack::PushL( itemParent );
       
   128         }
       
   129 
       
   130     // If new containers are not needed, set item parent id here,
       
   131     // because caller does not know the item parent container
       
   132     if ( !containers.Count() )
       
   133         {
       
   134         aItem.SetParentIdL( *itemParent );
       
   135         }
       
   136     if ( itemParent )
       
   137         {
       
   138         CleanupStack::PopAndDestroy( itemParent );
       
   139         }
       
   140 
       
   141     // Cleanup
       
   142     CleanupStack::PopAndDestroy( &containerNames );
       
   143     CleanupStack::Pop( &containers );
       
   144 
       
   145     return containers;
       
   146     }
       
   147 
       
   148 // --------------------------------------------------------------------------
       
   149 // CUpnpContainerResolver::ResolveReferenceContainersL
       
   150 // --------------------------------------------------------------------------
       
   151 //
       
   152 RPointerArray<CUpnpContainer>
       
   153     CUpnpContainerResolver::ResolveReferenceContainersL( TInt aType,
       
   154                                                          CUpnpItem& aItem )
       
   155     {
       
   156     __LOG( "[CUpnpSharingAlgorithm]\t CUpnpContainerResolver::\
       
   157 ResolveReferenceContainersL" );
       
   158 
       
   159     // List of needed containers
       
   160     RPointerArray<CUpnpContainer> containers;
       
   161     CleanupResetAndDestroyPushL( containers );
       
   162 
       
   163     RPointerArray<HBufC8> containerNames;
       
   164     CleanupResetAndDestroyPushL( containerNames );
       
   165 
       
   166     HBufC8* itemParent = NULL;
       
   167     TInt error( KErrNone );
       
   168 
       
   169     // Get object elements from where metadata is fetched
       
   170     const RUPnPElementsArray& elements = aItem.GetElements();
       
   171 
       
   172     switch( aType )
       
   173         {
       
   174         case EGenreType :
       
   175             {
       
   176             // Fill container name array, containers must be in
       
   177             // hierarchical order starting from root
       
   178             AppendContainerNameToArrayL( containerNames,
       
   179                                          R_UPNP_SHARE_MUSIC_TEXT );
       
   180             // Append "By Genre" container
       
   181             AppendContainerNameToArrayL( containerNames,
       
   182                                          R_UPNP_SHARE_BY_GENRE_TEXT );
       
   183 
       
   184             // Modify "Genre" element and append it to the array
       
   185             TRAP( error, ModifyAndAppendElementL( containerNames,
       
   186                                                   elements,
       
   187                                                   KElementGenre ));
       
   188 
       
   189             // If metadata is missing, containers are not created
       
   190             if ( error == KErrNone )
       
   191                 {
       
   192                 // Create non-existing containers
       
   193                 itemParent = CreateContainersL( containerNames,
       
   194                                                 containers,
       
   195                                                 KMusicClassContainer );
       
   196                 CleanupStack::PushL( itemParent );
       
   197                 }
       
   198             break;
       
   199             }
       
   200         case EAlbumType :
       
   201             {
       
   202             // Fill container name array, containers must be in
       
   203             // hierarchical order staring from root
       
   204             AppendContainerNameToArrayL( containerNames,
       
   205                                          R_UPNP_SHARE_MUSIC_TEXT );
       
   206             // Append "By Album" container
       
   207             AppendContainerNameToArrayL( containerNames,
       
   208                                          R_UPNP_SHARE_BY_ALBUM_TEXT );
       
   209 
       
   210             // Modify "Album" element and append it to the array
       
   211             TRAP( error, ModifyAndAppendElementL( containerNames,
       
   212                                                   elements,
       
   213                                                   KElementAlbum ));
       
   214 
       
   215             // If metadata is missing, containers are not created
       
   216             if ( error == KErrNone )
       
   217                 {
       
   218                 // Create non-existing containers
       
   219                 itemParent = CreateContainersL( containerNames,
       
   220                                                 containers,
       
   221                                                 KMusicClassContainer );
       
   222                 CleanupStack::PushL( itemParent );
       
   223                 }
       
   224             break;
       
   225             }
       
   226         case EArtistType :
       
   227             {
       
   228             // Fill container name array, containers must be in
       
   229             // hierarchical order staring from root
       
   230             AppendContainerNameToArrayL( containerNames,
       
   231                                          R_UPNP_SHARE_MUSIC_TEXT );
       
   232             // Append "By Artist" container
       
   233             AppendContainerNameToArrayL( containerNames,
       
   234                                          R_UPNP_SHARE_BY_ARTIST_TEXT );
       
   235 
       
   236             // Modify "Artist" element and append it to the array
       
   237             TRAP( error, ModifyAndAppendElementL( containerNames,
       
   238                                                   elements,
       
   239                                                   KElementArtist ));
       
   240 
       
   241             // If metadata is missing, containers are not created
       
   242             if ( error == KErrNone )
       
   243                 {
       
   244                 // Create non-existing containers
       
   245                 itemParent = CreateContainersL( containerNames,
       
   246                                                 containers,
       
   247                                                 KMusicClassContainer );
       
   248                 CleanupStack::PushL( itemParent );
       
   249                 }
       
   250             break;
       
   251             }
       
   252         case EMusicByDateType :
       
   253             {
       
   254             // Fill container name array, containers must be in
       
   255             // hierarchical order staring from root
       
   256             AppendContainerNameToArrayL( containerNames,
       
   257                                          R_UPNP_SHARE_MUSIC_TEXT );
       
   258             // Append "By Date" container
       
   259             AppendContainerNameToArrayL( containerNames,
       
   260                                          R_UPNP_SHARE_BY_DATE_TEXT );
       
   261 
       
   262             TTime time;
       
   263             HBufC8* elementValue = GetElementL( elements, KElementDate );
       
   264             if ( elementValue )
       
   265                 {
       
   266                 CleanupStack::PushL( elementValue );
       
   267                 HBufC8* adjustedDate = AdjustDateL( *elementValue );
       
   268                 CleanupStack::PopAndDestroy( elementValue );
       
   269                 CleanupStack::PushL( adjustedDate );
       
   270 
       
   271                 error = UPnPItemUtility::UPnPDateAsTTime( *adjustedDate,
       
   272                                                           time );
       
   273 
       
   274                 CleanupStack::PopAndDestroy( adjustedDate );
       
   275 
       
   276                 if ( error == KErrNone &&
       
   277                      adjustedDate->Length() > 0 )
       
   278                     {
       
   279                     TBuf<KMaxDateStringLength> finalTime;
       
   280 
       
   281                     // Append Year container
       
   282                     time.FormatL( finalTime, KDateTimeYear );
       
   283                     HBufC8* timeStr =
       
   284                         CnvUtfConverter::ConvertFromUnicodeToUtf8L(
       
   285                         finalTime );
       
   286                     CleanupStack::PushL( timeStr );
       
   287                     containerNames.Append( timeStr );
       
   288                     CleanupStack::Pop( timeStr );
       
   289 
       
   290                     // Create non-existing containers
       
   291                     itemParent = CreateContainersL( containerNames,
       
   292                                                     containers,
       
   293                                                     KMusicClassContainer );
       
   294                     CleanupStack::PushL( itemParent );
       
   295                     }
       
   296                 }
       
   297             else
       
   298                 {
       
   299                 error = KErrNotFound;
       
   300                 }
       
   301 
       
   302             break;
       
   303             }
       
   304         case EImageByDateType :
       
   305             {
       
   306             // Fill container name array, containers must be in
       
   307             // hierarchical order staring from root
       
   308             AppendContainerNameToArrayL( containerNames,
       
   309                                          R_UPNP_SHARE_IMAGE_TEXT );
       
   310 
       
   311             error = AddByDateContainersL( containerNames, elements );
       
   312 
       
   313             // If metadata is missing, containers are not created
       
   314             if ( error == KErrNone )
       
   315                 {
       
   316                 // Create non-existing containers
       
   317                 itemParent = CreateContainersL( containerNames,
       
   318                                                 containers,
       
   319                                                 KImageClassContainer );
       
   320                 CleanupStack::PushL( itemParent );
       
   321                 }
       
   322             break;
       
   323             }
       
   324         case EVideoByDateType :
       
   325             {
       
   326             // Fill container name array, containers must be in
       
   327             // hierarchical order staring from root
       
   328             AppendContainerNameToArrayL( containerNames,
       
   329                                          R_UPNP_SHARE_VIDEO_TEXT );
       
   330 
       
   331             error = AddByDateContainersL( containerNames, elements );
       
   332 
       
   333             // If metadata is missing, containers are not created
       
   334             if ( error == KErrNone )
       
   335                 {
       
   336                 // Create non-existing containers
       
   337                 itemParent = CreateContainersL( containerNames,
       
   338                                                 containers,
       
   339                                                 KVideoClassContainer );
       
   340                 CleanupStack::PushL( itemParent );
       
   341                 }
       
   342             break;
       
   343             }
       
   344         default:
       
   345             {
       
   346             User::Leave( KErrNotSupported );
       
   347             break;
       
   348             }
       
   349         }
       
   350 
       
   351     // If new containers are not needed, set item parent id here,
       
   352     // because caller does not know the item parent container.
       
   353     // If metadata is not found, item is left untouched.
       
   354     if ( !containers.Count() &&
       
   355          error == KErrNone )
       
   356         {
       
   357         aItem.SetParentIdL( *itemParent );
       
   358         }
       
   359 
       
   360     if ( itemParent )
       
   361         {
       
   362         CleanupStack::PopAndDestroy( itemParent );
       
   363         }
       
   364 
       
   365     // Cleanup
       
   366     CleanupStack::PopAndDestroy( &containerNames );
       
   367     CleanupStack::Pop( &containers );
       
   368 
       
   369     return containers;
       
   370     }
       
   371 
       
   372 // --------------------------------------------------------------------------
       
   373 // CUpnpContainerResolver::ResolveEmptyContainersL
       
   374 // --------------------------------------------------------------------------
       
   375 //
       
   376 RPointerArray<CUpnpCdsLiteObject>
       
   377     CUpnpContainerResolver::ResolveEmptyContainersL( TDesC8& aContainerId )
       
   378     {
       
   379     __LOG( "[CUpnpSharingAlgorithm]\t CUpnpContainerResolver::\
       
   380 ResolveEmptyContainersL" );
       
   381 
       
   382     RPointerArray<CUpnpCdsLiteObject> emptyContainers;
       
   383     TBool empty( ETrue );
       
   384     const TDesC8* parentId = &aContainerId;
       
   385 
       
   386     // Search empty containers from the array
       
   387     while ( empty &&
       
   388             parentId->Match( KRootContainer ) == KErrNotFound )
       
   389         {
       
   390         TInt count = iCdsLiteObjectArray.ChildCount( aContainerId );
       
   391         if ( iCdsLiteObjectArray.ChildCount( *parentId ) > 1 )
       
   392             {
       
   393             // There is more than one item inside container
       
   394             // Current container must not be removed, exit loop
       
   395             empty = EFalse;
       
   396             }
       
   397         else
       
   398             {
       
   399             // Get object index from CDS object array
       
   400             TInt objectIndex =
       
   401                 iCdsLiteObjectArray.FindByObjectId( *parentId );
       
   402 
       
   403             // Append correct container from CDS object array
       
   404             emptyContainers.Append(
       
   405                 &iCdsLiteObjectArray.ObjectAtL( objectIndex ) );
       
   406 
       
   407             // Get parent container id of the current container
       
   408             parentId =
       
   409                 &iCdsLiteObjectArray.ObjectAtL( objectIndex ).ParentId();
       
   410             }
       
   411         }
       
   412     return emptyContainers;
       
   413     }
       
   414 
       
   415 // --------------------------------------------------------------------------
       
   416 // CUpnpContainerResolver::ConstructL
       
   417 // --------------------------------------------------------------------------
       
   418 //
       
   419 void CUpnpContainerResolver::ConstructL()
       
   420     {
       
   421     __LOG( "[CUpnpSharingAlgorithm]\t CUpnpContainerResolver::\
       
   422 ConstructL" );
       
   423 
       
   424     // Open file server session
       
   425     User::LeaveIfError( iFs.Connect() );
       
   426 
       
   427     TFileName resourceFileName( KSharingAlgorithmRscFile );
       
   428 
       
   429     // Get the exact filename of the resource file
       
   430     BaflUtils::NearestLanguageFile( iFs, resourceFileName );
       
   431 
       
   432     TInt err( KErrNone );
       
   433     // Open resource file
       
   434     TRAP( err, iResourceFile.OpenL( iFs, resourceFileName ) );
       
   435 
       
   436     if ( err != KErrNone )
       
   437         {
       
   438         // If not found, try to read resource file from memory card
       
   439         resourceFileName.Copy( PathInfo::MemoryCardRootPath() );
       
   440         resourceFileName.Delete( 2, 2 ); // remove //
       
   441         resourceFileName.Append( KSharingAlgorithmRscFile );
       
   442         iResourceFile.OpenL( iFs, resourceFileName );
       
   443         }
       
   444     }
       
   445 
       
   446 // --------------------------------------------------------------------------
       
   447 // CCUpnpContainerResolver::~CUpnpContainerResolver
       
   448 // --------------------------------------------------------------------------
       
   449 //
       
   450 CUpnpContainerResolver::~CUpnpContainerResolver()
       
   451     {
       
   452     __LOG( "[CUpnpSharingAlgorithm]\t CUpnpContainerResolver::\
       
   453 ~CUpnpContainerResolver" );
       
   454 
       
   455     // Close resource file
       
   456     iResourceFile.Close();
       
   457 
       
   458     // Close file server session
       
   459     iFs.Close();
       
   460     }
       
   461 
       
   462 // --------------------------------------------------------------------------
       
   463 // CCUpnpContainerResolver::CreateContainerL
       
   464 // --------------------------------------------------------------------------
       
   465 //
       
   466 CUpnpContainer* CUpnpContainerResolver::CreateContainerL(
       
   467     const TDesC8& aTitle,
       
   468     const TDesC8& aClass )
       
   469     {
       
   470     __LOG( "[CUpnpSharingAlgorithm]\t CUpnpContainerResolver::\
       
   471 CreateContainerL" );
       
   472 
       
   473     CUpnpContainer* container = CUpnpContainer::NewL();
       
   474     CleanupStack::PushL( container );
       
   475 
       
   476     // Set container info
       
   477     container->SetTitleL( aTitle );
       
   478     container->SetObjectClassL( aClass );
       
   479 
       
   480     CleanupStack::Pop( container );
       
   481 
       
   482     return container;
       
   483     }
       
   484 
       
   485 // --------------------------------------------------------------------------
       
   486 // CCUpnpContainerResolver::CreateContainersL
       
   487 // --------------------------------------------------------------------------
       
   488 //
       
   489 HBufC8* CUpnpContainerResolver::CreateContainersL(
       
   490         RPointerArray<HBufC8>& aContainerNames,
       
   491         RPointerArray<CUpnpContainer>& aContainers,
       
   492         const TDesC8& aMediaClass )
       
   493     {
       
   494     __LOG( "[CUpnpSharingAlgorithm]\t CUpnpContainerResolver::\
       
   495 CreateContainersL" );
       
   496 
       
   497     HBufC8* parentId = NULL;
       
   498     TInt index( 1 );
       
   499 
       
   500     // Find first media container, e.g. "Music"
       
   501     TInt objectIndex ( iCdsLiteObjectArray.FindByMediaClassAndParentId(
       
   502         aMediaClass, KRootContainer ) );
       
   503 
       
   504     if ( objectIndex == KErrNotFound )
       
   505         {
       
   506         // Create media root container and append it to the container array.
       
   507         // Parent container is root container ("0")
       
   508         if ( aContainerNames.Count() )
       
   509             {
       
   510             CUpnpContainer* container = CreateContainerL(
       
   511                                           *aContainerNames[0], aMediaClass );
       
   512             CleanupStack::PushL( container );
       
   513             aContainers.Append( container );
       
   514             CleanupStack::Pop( container );
       
   515             }
       
   516         parentId = KRootContainer().AllocL();
       
   517         }
       
   518     else
       
   519         {
       
   520         // Remember media root container id
       
   521         parentId = iCdsLiteObjectArray.ObjectAtL(
       
   522                             objectIndex ).ObjectId().AllocL();
       
   523         }
       
   524 
       
   525     // Find the first container that does not exist
       
   526     for ( ; index < aContainerNames.Count(); index++ )
       
   527         {
       
   528         // Container is found by container name and parent id.
       
   529         // If search cannot find the container, it needs to be created.
       
   530         objectIndex = iCdsLiteObjectArray.FindByNameAndParentId(
       
   531             *aContainerNames[index], *parentId );
       
   532 
       
   533         if ( objectIndex == KErrNotFound )
       
   534             {
       
   535             break;
       
   536             }
       
   537         else
       
   538             {
       
   539             // Remember last found container id
       
   540             parentId = iCdsLiteObjectArray.ObjectAtL(
       
   541                                     objectIndex ).ObjectId().AllocL();
       
   542             }
       
   543         }
       
   544 
       
   545     // Create needed containers
       
   546     for ( TInt index2( index ); index2 < aContainerNames.Count(); index2++ )
       
   547         {
       
   548         CUpnpContainer* container = CreateContainerL(
       
   549                                      *aContainerNames[index2], aMediaClass );
       
   550         CleanupStack::PushL( container );
       
   551         aContainers.Append( container );
       
   552         CleanupStack::Pop( container );
       
   553         }
       
   554 
       
   555     // Use the last found object id as parent id of the first new container
       
   556     if ( aContainers.Count() )
       
   557         {
       
   558         aContainers[0]->SetParentIdL( *parentId );
       
   559         }
       
   560 
       
   561     return parentId;
       
   562     }
       
   563 
       
   564 // --------------------------------------------------------------------------
       
   565 // CUpnpContainerResolver::ReadResourceTextL
       
   566 // --------------------------------------------------------------------------
       
   567 //
       
   568 HBufC8* CUpnpContainerResolver::ReadResourceTextL( TInt aResourceId )
       
   569     {
       
   570     __LOG( "[CUpnpSharingAlgorithm]\t CUpnpContainerResolver::\
       
   571 ReadResourceTextL" );
       
   572 
       
   573     // Load resource text
       
   574     HBufC8* resourceString8 = iResourceFile.AllocReadLC( aResourceId );
       
   575 
       
   576     TResourceReader theReader;
       
   577     theReader.SetBuffer( resourceString8 );
       
   578     HBufC16* resourceString16 = theReader.ReadHBufC16L();
       
   579     CleanupStack::PushL( resourceString16 );
       
   580 
       
   581     HBufC8* returnString8 = CnvUtfConverter::ConvertFromUnicodeToUtf8L(
       
   582         resourceString16->Des() );
       
   583 
       
   584     CleanupStack::PopAndDestroy( resourceString16 );
       
   585     CleanupStack::PopAndDestroy( resourceString8 );
       
   586 
       
   587     return returnString8;
       
   588     }
       
   589 
       
   590 // --------------------------------------------------------------------------
       
   591 // CUpnpContainerResolver::GetElementL
       
   592 // --------------------------------------------------------------------------
       
   593 //
       
   594 HBufC8* CUpnpContainerResolver::GetElementL(
       
   595         const RUPnPElementsArray& aElements,
       
   596         const TDesC8& aElement )
       
   597     {
       
   598     __LOG( "[CUpnpSharingAlgorithm]\t CUpnpContainerResolver::\
       
   599 GetElementL" );
       
   600 
       
   601     HBufC8* elementValue = NULL;
       
   602 
       
   603     // Find the element
       
   604     for( TInt index = 0; index < aElements.Count(); index++ )
       
   605         {
       
   606         if( aElements[index]->Name().Match( aElement ) == KErrNone )
       
   607             {
       
   608             elementValue = aElements[index]->Value().AllocL();
       
   609             index = aElements.Count();
       
   610             }
       
   611         }
       
   612 
       
   613     return elementValue;
       
   614     }
       
   615 
       
   616 // --------------------------------------------------------------------------
       
   617 // CUpnpContainerResolver::AdjustDateL
       
   618 // --------------------------------------------------------------------------
       
   619 //
       
   620 HBufC8* CUpnpContainerResolver::AdjustDateL( const TDesC8& aDate )
       
   621     {
       
   622     __LOG( "[CUpnpSharingAlgorithm]\t CUpnpContainerResolver::\
       
   623 AdjustDateL" );
       
   624 
       
   625     HBufC* date = CnvUtfConverter::ConvertToUnicodeFromUtf8L( aDate );
       
   626     CleanupStack::PushL( date );
       
   627     TBuf<KMaxDateStringLength> modifiedDate;
       
   628 
       
   629     TBuf<KMonthAndDayLength> month;
       
   630     TBuf<KMonthAndDayLength> day;
       
   631 
       
   632     if( aDate.Length() >= KDateStringLength )
       
   633         {
       
   634         // Month and day are decreased by 1, because
       
   635         // both are started from zero in TTime::Set()
       
   636         // Formats date e.g. 2008-10-30 --> 2008-09-29
       
   637 
       
   638         // Add year and separator e.g. "2008-"
       
   639         modifiedDate.Copy( date->Des().Left(
       
   640             ( KDateYearLength + KSeparatorLength ) ) );
       
   641 
       
   642         // Adjust month "10" --> "9"
       
   643         month.Append( date->Des().Mid(
       
   644             ( KDateYearLength + KSeparatorLength ),
       
   645             KMonthAndDayLength) );
       
   646         TLex monthLex( month );
       
   647         TInt monthInt( 0 );
       
   648         monthLex.Val( monthInt );
       
   649         monthInt--;
       
   650         TBuf<KMonthAndDayLength> adjustedMonth;
       
   651         adjustedMonth.Num( monthInt );
       
   652 
       
   653         // Month and day values need to contain
       
   654         // two digits. Append extra zero, if needed,
       
   655         // e.g. "9" --> "09"
       
   656         if ( monthInt < KMonthAndDayDigitLimit )
       
   657             {
       
   658             modifiedDate.Append( KZero );
       
   659             }
       
   660 
       
   661         // Add modified month string
       
   662         modifiedDate.Append( adjustedMonth );
       
   663 
       
   664         // Add separator "-" that is between month and day
       
   665         modifiedDate.Append( date->Des().Mid(
       
   666             KSecondSeparatorPosition,
       
   667             KSeparatorLength ) );
       
   668 
       
   669         // Adjust day e.g. "30" --> "29"
       
   670         day.Append( date->Des().Mid(
       
   671             ( KSecondSeparatorPosition + KSeparatorLength ),
       
   672             KMonthAndDayLength) );
       
   673         TLex dayLex( day );
       
   674         TInt dayInt( 0 );
       
   675         dayLex.Val( dayInt );
       
   676         dayInt--;
       
   677         TBuf<KMonthAndDayLength> adjustedDay;
       
   678         adjustedDay.Num( dayInt );
       
   679 
       
   680         if ( dayInt < KMonthAndDayDigitLimit )
       
   681             {
       
   682             modifiedDate.Append( KZero );
       
   683             }
       
   684 
       
   685         // Add modified day string
       
   686         modifiedDate.Append( adjustedDay );
       
   687         }
       
   688 
       
   689     CleanupStack::PopAndDestroy( date );
       
   690 
       
   691     HBufC8* adjustedDate =
       
   692         CnvUtfConverter::ConvertFromUnicodeToUtf8L( modifiedDate );
       
   693 
       
   694     return adjustedDate;
       
   695     }
       
   696 
       
   697 // --------------------------------------------------------------------------
       
   698 // CUpnpContainerResolver::AddByDateContainersL
       
   699 // --------------------------------------------------------------------------
       
   700 //
       
   701 TInt CUpnpContainerResolver::AddByDateContainersL(
       
   702                                 RPointerArray<HBufC8>& aContainerNames,
       
   703                                 const RUPnPElementsArray& aElements )
       
   704     {
       
   705     __LOG( "[CUpnpSharingAlgorithm]\t CUpnpContainerResolver::\
       
   706 AddByDateContainersL" );
       
   707 
       
   708     TInt metadataError( KErrNone );
       
   709     TTime time;
       
   710 
       
   711     // Append "By Date" container
       
   712     aContainerNames.AppendL(
       
   713         ReadResourceTextL( R_UPNP_SHARE_BY_DATE_TEXT ) );
       
   714 
       
   715     HBufC8* elementValue = GetElementL( aElements, KElementDate );
       
   716     if ( elementValue )
       
   717         {
       
   718         CleanupStack::PushL( elementValue );
       
   719         // Get date element and adjust it to match TTime::Set() time
       
   720         HBufC8* adjustedDate = AdjustDateL( *elementValue );
       
   721         CleanupStack::PopAndDestroy( elementValue );
       
   722         CleanupStack::PushL( adjustedDate );
       
   723 
       
   724         if ( adjustedDate->Length() <= 0 )
       
   725             {
       
   726             metadataError = KErrNotFound;
       
   727             }
       
   728 
       
   729         // Convert date to TTime
       
   730         TInt adjustError ( UPnPItemUtility::UPnPDateAsTTime(
       
   731             *adjustedDate, time ) );
       
   732 
       
   733         CleanupStack::PopAndDestroy( adjustedDate );
       
   734 
       
   735         if ( adjustError == KErrNone &&
       
   736              metadataError == KErrNone )
       
   737             {
       
   738             TBuf<KMaxDateStringLength> finalTime;
       
   739 
       
   740             // Append Year container
       
   741             time.FormatL( finalTime, KDateTimeYear );
       
   742             aContainerNames.Append(
       
   743                 CnvUtfConverter::ConvertFromUnicodeToUtf8L(
       
   744                     finalTime ) );
       
   745 
       
   746             // Append Month container
       
   747             time.FormatL( finalTime, KDateTimeMonth );
       
   748             aContainerNames.Append(
       
   749                 CnvUtfConverter::ConvertFromUnicodeToUtf8L(
       
   750                     finalTime ) );
       
   751 
       
   752             // Append Day container
       
   753             time.FormatL( finalTime, KDateTimeDay );
       
   754             aContainerNames.Append(
       
   755                 CnvUtfConverter::ConvertFromUnicodeToUtf8L(
       
   756                     finalTime ) );
       
   757             }
       
   758         }
       
   759     else
       
   760         {
       
   761         metadataError = KErrNotFound;
       
   762         }
       
   763 
       
   764     return metadataError;
       
   765     }
       
   766 
       
   767 // --------------------------------------------------------------------------
       
   768 // CUpnpContainerResolver::ModifyAndAppendElementL
       
   769 // --------------------------------------------------------------------------
       
   770 //
       
   771 void CUpnpContainerResolver::ModifyAndAppendElementL(
       
   772                                 RPointerArray<HBufC8>& aContainerNames,
       
   773                                 const RUPnPElementsArray& aElements,
       
   774                                 const TDesC8& aElementType )
       
   775     {
       
   776     __LOG( "[CUpnpSharingAlgorithm]\t CUpnpContainerResolver::\
       
   777 ModifyAndAppendElementL" );
       
   778 
       
   779     // Find correct element
       
   780     HBufC8* elementValue = GetElementL( aElements, aElementType );
       
   781     CleanupStack::PushL( elementValue );
       
   782     if ( !elementValue ||
       
   783          elementValue->Length() <= 0 )
       
   784         {
       
   785         User::Leave( KErrNotFound );
       
   786         }
       
   787 
       
   788     // Set all letters to lower case
       
   789     elementValue->Des().LowerCase();
       
   790 
       
   791     // Capitalize the first letter of the string
       
   792     elementValue->Des().Capitalize();
       
   793 
       
   794     // Append modified element value to container names array.
       
   795     // aContainerNames array is responsible for deleteting objects in it.
       
   796     // Transfer ownership.
       
   797     aContainerNames.AppendL( elementValue );
       
   798 
       
   799     CleanupStack::Pop( elementValue );
       
   800     }
       
   801 
       
   802 // --------------------------------------------------------------------------
       
   803 // CUpnpContainerResolver::AppendContainerNameToArrayL
       
   804 // --------------------------------------------------------------------------
       
   805 //
       
   806 void CUpnpContainerResolver::AppendContainerNameToArrayL(
       
   807                                             RPointerArray<HBufC8>& aArray,
       
   808                                             TInt aResourceTextId )
       
   809     {
       
   810     __LOG( "[CUpnpSharingAlgorithm]\t CUpnpContainerResolver::\
       
   811 AppendContainerNameToArrayL" );
       
   812 
       
   813     HBufC8* name = ReadResourceTextL( aResourceTextId );
       
   814     CleanupStack::PushL( name );
       
   815     aArray.AppendL( name );
       
   816     CleanupStack::Pop( name );
       
   817     }
       
   818 
       
   819 // End of file