phonebookengines/VirtualPhonebook/VPbkCntModel/src/CContact.cpp
changeset 0 e686773b3f54
equal deleted inserted replaced
-1:000000000000 0:e686773b3f54
       
     1 /*
       
     2 * Copyright (c) 2002-2007 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:  The virtual phonebook contact
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 
       
    20 #include "CContact.h"
       
    21 #include <cntitem.h>
       
    22 #include <babitflags.h>
       
    23 
       
    24 #include <VPbkError.h>
       
    25 #include <MVPbkContactObserver.h>
       
    26 #include <TVPbkFieldTypeMapping.h>
       
    27 #include <MVPbkFieldType.h>
       
    28 #include <MVPbkContactStoreProperties.h>
       
    29 #include <CVPbkContactLinkArray.h>
       
    30 #include <CVPbkContactFieldCollection.h>
       
    31 #include <MVPbkStoreContactProperties.h>
       
    32 
       
    33 #include "CContactStore.h"
       
    34 #include "CFieldTypeMap.h"
       
    35 #include "TNewContactField.h"
       
    36 #include "CViewContact.h"
       
    37 #include "CContactLink.h"
       
    38 
       
    39 namespace VPbkCntModel {
       
    40 
       
    41 // ======== LOCAL CLASSES ========
       
    42 
       
    43 /**
       
    44  * Internal store contact properties class,
       
    45  * use CContactItem to implement MVPbkStoreContactProperties methods
       
    46  *
       
    47  */
       
    48 class CVPbkStoreContactProperties :
       
    49     public CBase,
       
    50     public MVPbkStoreContactProperties
       
    51     {
       
    52     public:
       
    53         static CVPbkStoreContactProperties* NewL(
       
    54         		CContactItem& aContactItem, 
       
    55         		CContactDatabase& aContactDb );
       
    56         
       
    57         ~CVPbkStoreContactProperties();
       
    58     protected: // MVPbkStoreContactProperties
       
    59         TTime LastModifiedL() const;
       
    60         TPtrC GuidL() const;
       
    61     private:
       
    62         CVPbkStoreContactProperties(
       
    63         		CContactItem& aContactItem,
       
    64         		CContactDatabase& aContactDb );
       
    65 
       
    66     private:
       
    67         CContactItem& iContactItem;  
       
    68         CContactDatabase& iContactDb;
       
    69     };
       
    70     
       
    71 CVPbkStoreContactProperties* CVPbkStoreContactProperties::NewL(
       
    72     CContactItem& aContactItem,
       
    73     CContactDatabase& aContactDb )
       
    74     {
       
    75     CVPbkStoreContactProperties* self = new(ELeave) CVPbkStoreContactProperties(
       
    76     		aContactItem,
       
    77     		aContactDb );
       
    78     return self;
       
    79     }
       
    80     
       
    81 CVPbkStoreContactProperties::CVPbkStoreContactProperties(
       
    82     CContactItem& aContactItem, 
       
    83 	CContactDatabase& aContactDb ) :
       
    84     iContactItem( aContactItem ),
       
    85     iContactDb( aContactDb )
       
    86     {
       
    87     }
       
    88     
       
    89 CVPbkStoreContactProperties::~CVPbkStoreContactProperties()
       
    90     {
       
    91     }
       
    92     
       
    93 TTime CVPbkStoreContactProperties::LastModifiedL() const
       
    94     {
       
    95     return iContactItem.LastModified();
       
    96     }
       
    97 
       
    98 TPtrC CVPbkStoreContactProperties::GuidL() const
       
    99     {
       
   100     return iContactItem.UidStringL(iContactDb.MachineId());
       
   101     }
       
   102 // ======== LOCAL FUNCTIONS ========
       
   103 
       
   104 TInt FindMatchingField( const MVPbkBaseContactFieldCollection& aFields, 
       
   105                        const MVPbkFieldType* aFieldType,
       
   106                        const MVPbkFieldTypeList& aMasterFieldTypeList )
       
   107     {
       
   108     TInt result = KErrNotFound;
       
   109     
       
   110     const TInt fieldCount = aFields.FieldCount();
       
   111     const TInt maxMatchPriority = aMasterFieldTypeList.MaxMatchPriority();
       
   112     for ( TInt matchPriority = 0; matchPriority <= maxMatchPriority; 
       
   113                     ++matchPriority )
       
   114         {
       
   115         for ( TInt i = 0; i < fieldCount; ++i )
       
   116             {
       
   117             const MVPbkFieldType* fieldType =
       
   118                 aFields.FieldAt( i ).MatchFieldType( matchPriority );
       
   119             if ( fieldType && fieldType->IsSame(*aFieldType) )
       
   120                 { 
       
   121                 result = i;
       
   122                 break;
       
   123                 }
       
   124             }
       
   125         }
       
   126         
       
   127     return result;
       
   128     }
       
   129 
       
   130 // ======== MEMBER FUNCTIONS ========
       
   131 
       
   132 inline CContact::CContact(
       
   133         CContactStore& aParentStore, 
       
   134         CContactItem& aContactItem,
       
   135         TBool aIsNewContact ) :
       
   136     iIsNewContact( aIsNewContact ),
       
   137     iFields( *this, aContactItem.CardFields() ),
       
   138     iParentStore( aParentStore ),
       
   139     iLastUpdatedGroupContactId( KNullContactId )
       
   140     {
       
   141     }
       
   142 
       
   143 inline void CContact::ConstructL()
       
   144     {
       
   145     }
       
   146 
       
   147 CContact* CContact::NewL(
       
   148         CContactStore& aParentStore, 
       
   149         CContactItem* aContactItem,
       
   150         TBool aIsNewContact /* = EFalse */)
       
   151     {
       
   152     CContact* self = new(ELeave) CContact( aParentStore, *aContactItem, 
       
   153                                             aIsNewContact );
       
   154     CleanupStack::PushL( self );
       
   155     self->ConstructL();
       
   156     CleanupStack::Pop( self );
       
   157     // Potentially leaving initialisation is done; take parameter ownership now
       
   158     self->iContactItem = aContactItem;
       
   159     return self;
       
   160     }
       
   161 
       
   162 CContact::~CContact()
       
   163     { 
       
   164     // Incase there was a problem when updating the time stamps of contacts
       
   165     // belonging to a group we need to make sure the contact is unlocked by
       
   166     // closing it. Symbian documentation says that despite the trailing L 
       
   167     // in the function's name, CloseContactL cannot leave. Also specifying 
       
   168     // a contact item that is not open, or cannot be found, is harmless.  
       
   169    if ( iLastUpdatedGroupContactId != KNullContactId )
       
   170        {
       
   171        iParentStore.NativeDatabase().CloseContactL( iLastUpdatedGroupContactId );  
       
   172        }
       
   173           
       
   174     iParentStore.ContactDestroyed( iContactItem, iModified );
       
   175     delete iContactItem;
       
   176     delete iAddedContacts;    
       
   177     }
       
   178 
       
   179 void CContact::SetContact( CContactItem* aContactItem )
       
   180     {
       
   181     if ( aContactItem && aContactItem != iContactItem )
       
   182         {
       
   183         delete iContactItem;
       
   184         iContactItem = aContactItem;
       
   185         iFields.SetContact( *this, iContactItem->CardFields() );
       
   186         }
       
   187     }
       
   188 
       
   189 const CFieldTypeMap& CContact::FieldTypeMap() const
       
   190     {
       
   191     return iParentStore.FieldTypeMap();
       
   192     }
       
   193 
       
   194 MVPbkObjectHierarchy& CContact::ParentObject() const
       
   195     {
       
   196     return iParentStore;
       
   197     }
       
   198 
       
   199 const MVPbkStoreContactFieldCollection& CContact::Fields() const
       
   200     {
       
   201     return iFields;
       
   202     }
       
   203 
       
   204 TBool CContact::IsSame( const MVPbkStoreContact& aOtherContact ) const
       
   205     {
       
   206     if ( &iParentStore == &aOtherContact.ContactStore() )
       
   207         {
       
   208         return ( iContactItem->Id() == 
       
   209             static_cast<const CContact&>(aOtherContact).iContactItem->Id() );
       
   210         }
       
   211     return EFalse;
       
   212     }
       
   213 
       
   214 TBool CContact::IsSame( const MVPbkViewContact& aOtherContact ) const
       
   215     {
       
   216     return aOtherContact.IsSame( *this, &ContactStore() );
       
   217     }
       
   218 
       
   219 MVPbkContactLink* CContact::CreateLinkLC() const
       
   220     {
       
   221     return iParentStore.CreateLinkLC( iContactItem->Id() );
       
   222     }
       
   223 
       
   224 void CContact::LockL(MVPbkContactObserver& aObserver) const
       
   225     {
       
   226     iParentStore.LockContactL( *this, aObserver );
       
   227     }
       
   228 
       
   229 void CContact::DeleteL(MVPbkContactObserver& aObserver) const
       
   230     {
       
   231     iParentStore.NativeDatabase().CloseContactL( iContactItem->Id() );
       
   232     iParentStore.DeleteContactL( iContactItem->Id(), aObserver );
       
   233     }
       
   234 
       
   235 TBool CContact::MatchContactStore(const TDesC& aContactStoreUri) const
       
   236     {
       
   237     return iParentStore.MatchContactStore( aContactStoreUri );
       
   238     }
       
   239     
       
   240 TBool CContact::MatchContactStoreDomain( const TDesC& aContactStoreDomain ) const
       
   241     {
       
   242     return iParentStore.MatchContactStoreDomain( aContactStoreDomain );
       
   243     }
       
   244 
       
   245 MVPbkContactBookmark* CContact::CreateBookmarkLC() const
       
   246     {
       
   247     return iParentStore.CreateBookmarkLC( iContactItem->Id() );
       
   248     }
       
   249     
       
   250 MVPbkContactStore& CContact::ParentStore() const
       
   251     {
       
   252     return iParentStore;
       
   253     }
       
   254 
       
   255 MVPbkStoreContactFieldCollection& CContact::Fields()
       
   256     {
       
   257     return iFields;
       
   258     }
       
   259 
       
   260 MVPbkStoreContactField* CContact::CreateFieldLC( const MVPbkFieldType& 
       
   261                                                     aFieldType ) const
       
   262     {
       
   263     // Match the field type to the Contact Db's system template
       
   264     CContactItemField* newField = iParentStore.CreateFieldLC( aFieldType );
       
   265     if ( !newField )
       
   266         {
       
   267         User::Leave( KErrNotSupported );
       
   268         }
       
   269 
       
   270     // Create a wrapper for the newly created field
       
   271     TNewContactField* fieldWrapper = 
       
   272         new(ELeave) TNewContactField( const_cast<CContact&>(*this), newField );
       
   273     CleanupStack::Pop( newField );
       
   274     CleanupDeletePushL( fieldWrapper );
       
   275 
       
   276     // Return the wrapper
       
   277     return fieldWrapper;
       
   278     }
       
   279 
       
   280 TInt CContact::AddFieldL( MVPbkStoreContactField* aField )
       
   281     {
       
   282     __ASSERT_ALWAYS( aField, VPbkError::Panic( VPbkError::ENullContactField ) );
       
   283     __ASSERT_ALWAYS( &aField->ParentContact() == this, 
       
   284         VPbkError::Panic(VPbkError::EInvalidContactField) );
       
   285     // Test that the client doesn't pass an existing field of this contact as 
       
   286     // a new one
       
   287     __ASSERT_ALWAYS( aField != iFields.FieldPointer(), 
       
   288         VPbkError::Panic(VPbkError::EInvalidContactField) );
       
   289 
       
   290     // After all the checks the field can be cast back to the wrapper that was
       
   291     // created in CreateFieldLC
       
   292     TNewContactField* fieldWrapper = static_cast<TNewContactField*>( aField );
       
   293     
       
   294     // Add the Contact Model field to the contact item
       
   295     iContactItem->AddFieldL( *fieldWrapper->NativeField() );
       
   296     // Field added succesfully, release wrapper's ownership
       
   297     fieldWrapper->ReleaseNativeField();
       
   298 
       
   299     // Delete fieldWrapper. This function must not leave after deletion
       
   300     // of fieldWrapper because CreateFieldLC has put fieldWrapper 
       
   301     // into the cleanup stack and client pops it after this function
       
   302     delete fieldWrapper;
       
   303     // The field is appended to the contact -> return the last field index
       
   304     return iContactItem->CardFields().Count() - 1;
       
   305     }
       
   306 
       
   307 void CContact::RemoveField(TInt aIndex)
       
   308     {
       
   309     __ASSERT_ALWAYS( aIndex >= 0 && aIndex < iFields.FieldCount(), 
       
   310         VPbkError::Panic(VPbkError::EInvalidFieldIndex) );
       
   311     __ASSERT_ALWAYS( !iParentStore.StoreProperties().ReadOnly(),
       
   312         VPbkError::Panic(VPbkError::EInvalidAccessToReadOnlyContact ) );
       
   313 
       
   314     iContactItem->RemoveField( aIndex );
       
   315     } 
       
   316 
       
   317 void CContact::RemoveAllFields()
       
   318     {
       
   319     __ASSERT_ALWAYS( !iParentStore.StoreProperties().ReadOnly(),
       
   320         VPbkError::Panic(VPbkError::EInvalidAccessToReadOnlyContact ) );
       
   321 
       
   322     iContactItem->CardFields().Reset();
       
   323     }
       
   324 
       
   325 void CContact::CommitL( MVPbkContactObserver& aObserver ) const
       
   326     {
       
   327     iParentStore.CommitContactL( *this, aObserver );
       
   328     }
       
   329     
       
   330 MVPbkContactLinkArray* CContact::GroupsJoinedLC() const
       
   331     {
       
   332     CVPbkContactLinkArray* result = CVPbkContactLinkArray::NewLC();
       
   333     
       
   334     if ( iContactItem->Type() == KUidContactCard )
       
   335         {
       
   336         CContactCard* contactCard = static_cast<CContactCard*>( iContactItem );
       
   337         CContactIdArray* groups = contactCard->GroupsJoinedLC();
       
   338         const TInt count = groups->Count();
       
   339         for ( TInt i = 0; i < count; ++i )
       
   340             {
       
   341             MVPbkContactLink* link = iParentStore.CreateLinkLC( (*groups)[i] );
       
   342             result->AppendL( link );
       
   343             CleanupStack::Pop(); // link
       
   344             }
       
   345         CleanupStack::PopAndDestroy( groups );
       
   346         }
       
   347     
       
   348     return result;
       
   349     }
       
   350 
       
   351 TInt CContact::MaxNumberOfFieldL( const MVPbkFieldType& aType ) const
       
   352     {
       
   353     if ( iParentStore.StoreProperties().SupportedFields().ContainsSame(aType) )
       
   354         {
       
   355         return KVPbkStoreContactUnlimitedNumber;
       
   356         }
       
   357     return 0;
       
   358     }
       
   359         
       
   360 MVPbkContactGroup* CContact::Group()
       
   361     {
       
   362     MVPbkContactGroup* result = NULL;
       
   363     
       
   364     if ( iContactItem->Type() == KUidContactGroup )
       
   365         {
       
   366         result = this;
       
   367         }
       
   368         
       
   369     return result;
       
   370     }
       
   371 
       
   372 void CContact::SetGroupLabelL( const TDesC& aLabel )
       
   373     {
       
   374     TVPbkFieldTypeMapping typeMapping;
       
   375     typeMapping.SetNonVersitType( EVPbkNonVersitTypeGenericLabel );
       
   376     const MVPbkFieldType* labelType = 
       
   377             typeMapping.FindMatch( iParentStore.MasterFieldTypeList() );
       
   378     
       
   379     TInt labelFieldIndex = FindMatchingField( Fields(), 
       
   380                                              labelType, 
       
   381                                              iParentStore.MasterFieldTypeList() );
       
   382 
       
   383     // Update the timestamp of the all contacts that belong to the group. 
       
   384     // This is needed for synch service as it checks the timestamps of contacts 
       
   385     // and get's the group information from the vCard of a contact. 
       
   386     UpdateTimeStampOfAllContactsInGroupL();
       
   387        
       
   388     if ( labelFieldIndex != KErrNotFound )
       
   389         {
       
   390         // field already exists
       
   391         MVPbkStoreContactField& labelField = Fields().FieldAt( labelFieldIndex );
       
   392         MVPbkContactFieldTextData::Cast( labelField.FieldData()).SetTextL(aLabel );
       
   393         }
       
   394     else
       
   395         {
       
   396         // field does not exist => add it
       
   397         MVPbkStoreContactField* labelField = CreateFieldLC( *labelType );
       
   398         MVPbkContactFieldTextData::Cast( labelField->FieldData() ).SetTextL( aLabel );
       
   399         AddFieldL( labelField );
       
   400         CleanupStack::Pop(); // labelField
       
   401         }
       
   402     }
       
   403     
       
   404 TPtrC CContact::GroupLabel() const
       
   405     {
       
   406     TVPbkFieldTypeMapping typeMapping;
       
   407     typeMapping.SetNonVersitType( EVPbkNonVersitTypeGenericLabel );
       
   408     const MVPbkFieldType* labelType = 
       
   409             typeMapping.FindMatch( iParentStore.MasterFieldTypeList() );
       
   410     
       
   411     TInt labelFieldIndex = FindMatchingField( Fields(), 
       
   412                                              labelType, 
       
   413                                              iParentStore.MasterFieldTypeList() );
       
   414     
       
   415     if ( labelFieldIndex != KErrNotFound )
       
   416         {
       
   417         const MVPbkBaseContactField& labelField = Fields().FieldAt( labelFieldIndex );
       
   418         return MVPbkContactFieldTextData::Cast(labelField.FieldData()).Text();
       
   419         }
       
   420     else
       
   421         {
       
   422         return KNullDesC();        
       
   423         }
       
   424     }
       
   425 
       
   426 // --------------------------------------------------------------------------
       
   427 // CContact::UpdateTimeStampOfAllContactsInGroupL
       
   428 // --------------------------------------------------------------------------
       
   429 //
       
   430 void CContact::UpdateTimeStampOfAllContactsInGroupL( )
       
   431     {
       
   432     MVPbkContactLinkArray* contactsInGroup = ItemsContainedLC();
       
   433     
       
   434     // Loop through all contacts in the group and update time stamps
       
   435     for (TInt i=0; i < contactsInGroup->Count(); i++ )
       
   436         {
       
   437         UpdateTimeStampOfContactInGroupL( contactsInGroup->At(i) );
       
   438         }
       
   439     
       
   440     CleanupStack::PopAndDestroy(); // contactsInGroup
       
   441     }
       
   442 
       
   443 // --------------------------------------------------------------------------
       
   444 // CContact::UpdateTimeStampOfContactInGroupL
       
   445 // --------------------------------------------------------------------------
       
   446 //
       
   447 void CContact::UpdateTimeStampOfContactInGroupL(const MVPbkContactLink& aContactLink )
       
   448     {
       
   449     const CContactLink& link = static_cast<const CContactLink&>( aContactLink );
       
   450     
       
   451     // Store the id of currently processed contact in the group
       
   452     iLastUpdatedGroupContactId = link.ContactId();
       
   453     
       
   454     // Try to open the contact for editing and then commit.
       
   455     // This will update the timestamp of the contact.
       
   456     // In case of a leave, we will make sure in the destructor that the
       
   457     // contact is unlocked (see CContact::~CContact).
       
   458     CContactItem* contact = 
       
   459           iParentStore.NativeDatabase().OpenContactL( link.ContactId() );  
       
   460     CleanupStack::PushL(contact);     
       
   461     
       
   462     iParentStore.NativeDatabase().CommitContactL(*contact);
       
   463     CleanupStack::PopAndDestroy(contact);
       
   464     
       
   465     // No need to store the id anymore.
       
   466     iLastUpdatedGroupContactId = KNullContactId;
       
   467     }
       
   468 
       
   469 void CContact::AddContactL( const MVPbkContactLink& aContactLink )
       
   470     {        
       
   471     // We have to maintain iAddedContacts ID array here because
       
   472     // the AddContactToGroup(id, id) method does not update
       
   473     // the native contact group we have in hand. It updates the
       
   474     // database only. So, in the ItemsContainedLC function
       
   475     // we have to know both the group members in the database
       
   476     // and the group members that have been added after this group
       
   477     // has been read from database
       
   478     const CContactLink& link = static_cast<const CContactLink&>( aContactLink );
       
   479     
       
   480     // Read the contact so that 
       
   481     // AddContactToGroupL(CContactItem &aItem, CContactItem &aGroup)
       
   482     // can be used.
       
   483     CContactItem* contact = 
       
   484         iParentStore.NativeDatabase().ReadContactLC( link.ContactId() );
       
   485         
       
   486     if ( !iAddedContacts )
       
   487         {
       
   488         iAddedContacts = CContactIdArray::NewL();
       
   489         }        
       
   490     if ( iAddedContacts->Find( link.ContactId() ) == KErrNotFound )
       
   491         {
       
   492         iAddedContacts->AddL( link.ContactId() );
       
   493         }
       
   494     
       
   495     // Use AddContactToGroupL(CContactItem &aItem, CContactItem &aGroup)
       
   496     // instead of 
       
   497     // AddContactToGroupL(TContactItemId aItemId, TContactItemId aGroupId)
       
   498     // because otherwise the member iContactItem won't be updated and commiting
       
   499     // it would loose the information about added contact
       
   500     TRAPD( err1, iParentStore.NativeDatabase().AddContactToGroupL(
       
   501                *contact, *iContactItem ) );
       
   502     if ( err1 != KErrNone )
       
   503         {
       
   504         iAddedContacts->Remove( iAddedContacts->Count() - 1 );
       
   505         User::Leave( err1 );
       
   506         } 
       
   507     
       
   508     // Update the timestamp of the added contact. This is needed for 
       
   509     // synch service as it checks the timestamps of contacts and get's the group
       
   510     // information from the vCard of a contact.    
       
   511     TRAPD( err2, UpdateTimeStampOfContactInGroupL( aContactLink ) );
       
   512     if ( err2 != KErrNone )
       
   513         {
       
   514         iAddedContacts->Remove( iAddedContacts->Count() - 1 );
       
   515         iParentStore.NativeDatabase().RemoveContactFromGroupL(
       
   516                 *contact, *iContactItem );
       
   517         User::Leave( err2 );
       
   518         } 
       
   519     CleanupStack::PopAndDestroy( contact );
       
   520     }
       
   521     
       
   522 void CContact::RemoveContactL( const MVPbkContactLink& aContactLink )
       
   523     {    
       
   524     const CContactLink& link = static_cast<const CContactLink&>( aContactLink );
       
   525     
       
   526     // Read the contact so that 
       
   527     // RemoveContactFromGroupL(CContactItem &aItem, CContactItem &aGroup)
       
   528     // can be used.
       
   529     CContactItem* contact = 
       
   530         iParentStore.NativeDatabase().ReadContactLC( link.ContactId() );
       
   531     
       
   532     // First update the timestamp of the removed contact. This is needed for 
       
   533     // synch service as it checks the timestamps of contacts and get's the group
       
   534     // information from the vCard of a contact. If updating fails this function 
       
   535     // will leave and contact won't be removed from the group.
       
   536     UpdateTimeStampOfContactInGroupL(aContactLink);
       
   537     
       
   538     TInt index = KErrNotFound;
       
   539     if ( iAddedContacts )
       
   540     	{
       
   541     	index = iAddedContacts->Find( link.ContactId() );
       
   542     	}
       
   543     
       
   544     // Use RemoveContactFromGroupL(CContactItem &aItem, CContactItem &aGroup)
       
   545     // instead of 
       
   546     // RemoveContactFromGroupL(TContactItemId aItemId, TContactItemId aGroupId)
       
   547     // because otherwise the member iContactItem won't be updated and commiting
       
   548     // it would loose the information about removed contact
       
   549     iParentStore.NativeDatabase().RemoveContactFromGroupL(
       
   550             *contact, *iContactItem );
       
   551     if ( index != KErrNotFound )
       
   552         {
       
   553         iAddedContacts->Remove( index );
       
   554         }
       
   555     CleanupStack::PopAndDestroy( contact );
       
   556     }
       
   557 
       
   558 MVPbkContactLinkArray* CContact::ItemsContainedLC() const
       
   559     {
       
   560     CVPbkContactLinkArray* result = CVPbkContactLinkArray::NewLC();
       
   561     TInt i;
       
   562 
       
   563     const CContactGroup* thisGroup = static_cast<const CContactGroup*>( iContactItem );
       
   564     // 1. append the IDs found in the group
       
   565     const CContactIdArray* contacts = thisGroup->ItemsContained();
       
   566     const TInt count = ( contacts ? contacts->Count() : 0 );
       
   567     for ( i = 0; i < count; ++i )
       
   568         {
       
   569         MVPbkContactLink* link = iParentStore.CreateLinkLC( (*contacts)[i] );
       
   570         result->AppendL( link );
       
   571         CleanupStack::Pop(); // link
       
   572         }
       
   573     // 2. append the IDs in iAddedContacts
       
   574     const TInt addedCount = ( iAddedContacts ? iAddedContacts->Count() : 0 );
       
   575     for ( i = 0; i < addedCount; ++i )
       
   576         {
       
   577         // add the contact if the iAddedContact[i] was not in contacts already
       
   578         if ( !contacts ||
       
   579             contacts->Find( (*iAddedContacts)[i]) == KErrNotFound )
       
   580             {
       
   581             MVPbkContactLink* link = iParentStore.CreateLinkLC( (*iAddedContacts)[i] );
       
   582             result->AppendL( link );
       
   583             CleanupStack::Pop(); // link
       
   584             }
       
   585         }
       
   586     return result;
       
   587     }
       
   588 
       
   589 TAny* CContact::StoreContactExtension(TUid aExtensionUid) 
       
   590 {
       
   591     if( aExtensionUid == KMVPbkStoreContactExtension2Uid )
       
   592 		return static_cast<MVPbkStoreContact2*>( this );
       
   593     return NULL;
       
   594 }
       
   595     
       
   596 MVPbkStoreContactProperties* CContact::PropertiesL() const
       
   597     {
       
   598     return CVPbkStoreContactProperties::NewL( *iContactItem, iParentStore.NativeDatabase() );
       
   599     }
       
   600 
       
   601 void CContact::SetAsOwnL(MVPbkContactObserver& aObserver) const
       
   602 	{
       
   603 	iParentStore.SetAsOwnL( *this, aObserver );
       
   604 	}
       
   605 
       
   606 TAny* CContact::BaseContactExtension( TUid aExtensionUid )
       
   607     {
       
   608     if( aExtensionUid == KVPbkBaseContactExtension2Uid )
       
   609         return static_cast<MVPbkBaseContact2*>( this );
       
   610     return NULL;
       
   611     }
       
   612 
       
   613 TBool CContact::IsOwnContact( TInt& aError ) const
       
   614     {
       
   615     aError = KErrNone;
       
   616     return ( iContactItem->Type() == KUidContactOwnCard );
       
   617     }
       
   618 
       
   619 
       
   620 } // namespace VPbkCntModel
       
   621 
       
   622 // end of file