phonebookengines/VirtualPhonebook/VPbkVCardEng/src/CVPbkVCardCompactBCardImporter.cpp
changeset 0 e686773b3f54
child 21 9da50d567e3c
equal deleted inserted replaced
-1:000000000000 0:e686773b3f54
       
     1 /*
       
     2 * Copyright (c) 2006-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:  Virtual Phonebook VCard compact BCard importer
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 
       
    20 // System includes
       
    21 #include <versit.h>
       
    22 
       
    23 #include "CVPbkVCardData.h"
       
    24 #include "CVPbkVCardCompactBCardImporter.h"
       
    25 #include "VPbkVCardEngError.h"
       
    26 #include "CVPbkVCardFieldTypeProperty.h"
       
    27 #include <VPbkEng.rsg>
       
    28 
       
    29 // From Virtual Phonebook engine
       
    30 #include <MVPbkContactFieldTextData.h>
       
    31 #include <MVPbkFieldType.h>
       
    32 #include <MVPbkSingleContactOperationObserver.h>
       
    33 #include <MVPbkStoreContactField.h>
       
    34 #include <MVPbkStoreContact.h>
       
    35 #include <MVPbkContactStore.h>
       
    36 #include <MVPbkContactStoreProperties.h>
       
    37 #include <MVPbkContactCopyPolicy.h>
       
    38 #include <MVPbkContactOperationBase.h>
       
    39 
       
    40 
       
    41 #ifdef _DEBUG
       
    42 using namespace VPbkVCardEngError;
       
    43 #endif // _DEBUG
       
    44 
       
    45 namespace 
       
    46     {
       
    47     enum TVPbkBCardImporterState
       
    48         {
       
    49         EGetLine,
       
    50         EStartTitleCopy,
       
    51         EAddAddress,
       
    52         EStop
       
    53         };
       
    54     
       
    55     _LIT(KBusinessCardText, "Business Card");   // Business card signature
       
    56     _LIT(KCloseParenthesis, ")");
       
    57     _LIT(KTelText, "tel ");
       
    58     _LIT(KFaxText, "fax ");
       
    59     _LIT(KSeparatorText, ", ");
       
    60     const TText KOpenParenthesis = '(';
       
    61     // Assume compact business card is corrupted if single field length
       
    62     // exceeds 200 bytes. This value is not officially specified anywhere.
       
    63     const TInt KBufferSize = 200;
       
    64     const TInt KStartPosition = 4;
       
    65     const TInt KLabelStartPosition = 5;
       
    66     const TInt KLabelValueDelimiterLength = 2;
       
    67     const TInt KGranularity( 2 );
       
    68 
       
    69     // Comapct business card fixed field line numbers.
       
    70     enum TVPbkCBCFieldLines
       
    71         {
       
    72         ECBCSignatureLine = 1,
       
    73         ECBCNameLine,
       
    74         ECBCCompanyLine,
       
    75         ECBCTitleLine
       
    76         };
       
    77     } // namespace
       
    78 
       
    79 CVPbkVCardCompactBCardImporter::CVPbkVCardCompactBCardImporter(
       
    80     RPointerArray<MVPbkStoreContact>& aImportedContacts,
       
    81     MVPbkContactStore& aTargetStore,
       
    82     RReadStream &aSourceStream,
       
    83     CVPbkVCardData& aData )
       
    84     :   CActive( EPriorityStandard ),
       
    85         iImportedContacts( aImportedContacts ),
       
    86         iTargetStore(aTargetStore),
       
    87         iData( aData ),
       
    88         iSource( aSourceStream )
       
    89     {
       
    90     }
       
    91 
       
    92 CVPbkVCardCompactBCardImporter* CVPbkVCardCompactBCardImporter::NewL(
       
    93     RPointerArray<MVPbkStoreContact>& aImportedContacts,
       
    94     MVPbkContactStore& aTargetStore, 
       
    95     RReadStream &aSourceStream,
       
    96     CVPbkVCardData& aData )
       
    97 	{
       
    98     CVPbkVCardCompactBCardImporter* self = new (ELeave)
       
    99         CVPbkVCardCompactBCardImporter(
       
   100             aImportedContacts,
       
   101             aTargetStore,
       
   102             aSourceStream,
       
   103             aData );
       
   104     CleanupStack::PushL( self );
       
   105     self->ConstructL();
       
   106     CleanupStack::Pop( self );
       
   107     return self;
       
   108 	}
       
   109 
       
   110 void CVPbkVCardCompactBCardImporter::ConstructL()
       
   111     {
       
   112     CActiveScheduler::Add(this);
       
   113     iAddressArray = new( ELeave ) CDesCArrayFlat( KGranularity );
       
   114     iCopyPolicy = &iData.CopyPolicyL( iTargetStore.StoreProperties().Uri() );
       
   115     }
       
   116 
       
   117 CVPbkVCardCompactBCardImporter::~CVPbkVCardCompactBCardImporter()
       
   118     {
       
   119     Cancel();
       
   120     delete iAddToFieldOperation;
       
   121     delete iCurContact;
       
   122     delete iAddressArray;
       
   123     delete iValue;
       
   124     delete iLabel;
       
   125     delete iLine;
       
   126     }
       
   127 
       
   128 void CVPbkVCardCompactBCardImporter::StartL()
       
   129     {
       
   130     iCurContact = iTargetStore.CreateNewContactLC();
       
   131     CleanupStack::Pop();
       
   132     iState = EGetLine;
       
   133     IssueRequest();
       
   134     }
       
   135 
       
   136 void CVPbkVCardCompactBCardImporter::SetObserver( 
       
   137         MVPbkImportOperationObserver& aObserver )
       
   138     {
       
   139     iObserver = &aObserver;
       
   140     }
       
   141     
       
   142 void CVPbkVCardCompactBCardImporter::RunL()
       
   143     {
       
   144     switch (iState)
       
   145         {
       
   146         case EGetLine:
       
   147             {
       
   148             if (GetLineL())
       
   149                 {
       
   150                 ParseLineL();
       
   151                 }
       
   152             break;
       
   153             }
       
   154         case EAddAddress:
       
   155 	        {
       
   156 	    	AddAddressL();
       
   157 	    	break;
       
   158 	        }
       
   159         case EStartTitleCopy:
       
   160             {
       
   161             StartTitleCopyL();
       
   162             break;
       
   163             }
       
   164         case EStop:
       
   165         	{
       
   166         	iObserver->ContactsImportingCompleted();
       
   167         	break;	
       
   168         	}
       
   169         default:
       
   170             {
       
   171             // Do nothing
       
   172             break;
       
   173             }
       
   174         }
       
   175     }
       
   176     
       
   177 void CVPbkVCardCompactBCardImporter::DoCancel()
       
   178     {
       
   179     delete iAddToFieldOperation;
       
   180     iAddToFieldOperation = NULL;
       
   181     }
       
   182     
       
   183 TInt CVPbkVCardCompactBCardImporter::RunError(TInt aError)
       
   184     {
       
   185     iObserver->ContactImportingFailed( aError );
       
   186     return KErrNone;
       
   187     }
       
   188 
       
   189 void CVPbkVCardCompactBCardImporter::FieldAddedToContact(
       
   190         MVPbkContactOperationBase& aOperation)
       
   191     {
       
   192     if ( &aOperation == iAddToFieldOperation )
       
   193         {
       
   194         delete iAddToFieldOperation;
       
   195         iAddToFieldOperation = NULL;
       
   196         IssueRequest();
       
   197         }
       
   198     }
       
   199 
       
   200 void CVPbkVCardCompactBCardImporter::FieldAddingFailed(
       
   201         MVPbkContactOperationBase& aOperation, TInt aError)
       
   202     {
       
   203     if ( &aOperation == iAddToFieldOperation )
       
   204         {
       
   205         delete iAddToFieldOperation;
       
   206         iAddToFieldOperation = NULL;
       
   207         if (aError == KErrNotSupported )
       
   208             {
       
   209             // Target contact didn't support field -> continue
       
   210             IssueRequest();
       
   211             }
       
   212         else if ( aError == KErrOverflow )
       
   213             {
       
   214             // Target contact is full of that field
       
   215             TRAPD( res, HandleContactSwitchL() );
       
   216             HandleError( res );
       
   217             }
       
   218         else
       
   219             {
       
   220             iObserver->ContactImportingFailed( aError );
       
   221             }
       
   222         }
       
   223     }
       
   224 
       
   225 void CVPbkVCardCompactBCardImporter::FieldsCopiedToContact(
       
   226         MVPbkContactOperationBase& /*aOperation*/)
       
   227     {
       
   228     ++iTargetContactIndex;
       
   229     if ( iTargetContactIndex >= iImportedContacts.Count() )
       
   230         {
       
   231         iObserver->ContactsImported();
       
   232         }
       
   233     else
       
   234         {
       
   235         TRAPD( res, CopyTitleL() );
       
   236         HandleError( res );    
       
   237         }
       
   238     }
       
   239 
       
   240 void CVPbkVCardCompactBCardImporter::FieldsCopyFailed(
       
   241         MVPbkContactOperationBase& /*aOperation*/, 
       
   242         TInt aError)
       
   243     {
       
   244     HandleError( aError );
       
   245     }
       
   246             
       
   247 void CVPbkVCardCompactBCardImporter::IssueRequest()
       
   248     {
       
   249     TRequestStatus* status = &iStatus;
       
   250     User::RequestComplete(status, KErrNone);
       
   251     SetActive();
       
   252     }
       
   253     
       
   254 TBool CVPbkVCardCompactBCardImporter::GetLineL()
       
   255     {
       
   256     delete iLine; 
       
   257     iLine = NULL;
       
   258     iLine = HBufC::NewL( KBufferSize );
       
   259     TPtr line = iLine->Des();
       
   260     
       
   261     TBool result = EFalse;
       
   262     TInt retVal( GetLineFromStreamL( line, iSource ) );
       
   263     if ( retVal == KErrNone || retVal == KErrEof  )
       
   264 		{
       
   265 		if(line.Length() > 0)
       
   266 		    {
       
   267 		    ++iLineCount;
       
   268 		    result = ETrue;	
       
   269 		    }
       
   270 	    else
       
   271 		    {
       
   272 		    iState = EStop;
       
   273 		    IssueRequest(); 	
       
   274 		    }
       
   275 
       
   276 		 }
       
   277 	if(retVal == KErrEof && line.Length() > 0 )
       
   278 		{
       
   279 		iState = EAddAddress;
       
   280 		}
       
   281     
       
   282     return result;
       
   283     }
       
   284 
       
   285 void CVPbkVCardCompactBCardImporter::ParseLineL()
       
   286     {
       
   287     TPtr line = iLine->Des();
       
   288     TInt resId( ResolveFieldTypeResIdL( line ) );
       
   289     
       
   290     if ( resId == KErrNotFound )
       
   291         {
       
   292         IssueRequest();
       
   293         }
       
   294     else if ( resId == R_VPBK_FIELD_TYPE_LANDPHONEGEN || 
       
   295               resId == R_VPBK_FIELD_TYPE_FAXNUMBERGEN )
       
   296         {
       
   297         // Asynchronous
       
   298         ValueAndLabelToBufL( line, resId );
       
   299         }
       
   300     else if ( resId == R_VPBK_FIELD_TYPE_ADDRLABELGEN )
       
   301         {
       
   302         // Synchronous
       
   303         ValueToArrayL( line );
       
   304         IssueRequest();
       
   305         }
       
   306     else
       
   307         {
       
   308         // Asynchronous
       
   309         ValueToBufL( line, resId );
       
   310         }
       
   311     }
       
   312 
       
   313 void CVPbkVCardCompactBCardImporter::ValueToBufL( 
       
   314     const TDesC& aBuffer, TInt aResId )
       
   315     {
       
   316     const MVPbkFieldType* fieldType = FindFieldTypeL( aResId );
       
   317     __ASSERT_DEBUG( fieldType, 
       
   318         VPbkVCardEngError::Panic( VPbkVCardEngError::ENullFieldType ) );
       
   319 
       
   320     AddFieldWithValueL( *fieldType, aBuffer, NULL );
       
   321     }
       
   322 
       
   323 void CVPbkVCardCompactBCardImporter::ValueToArrayL( const TDesC& aBuffer )
       
   324     {
       
   325     // Address is saved after all other fields have been saved
       
   326     iAddressArray->AppendL( aBuffer );
       
   327 
       
   328     if( iValueLength )
       
   329         {
       
   330         iValueLength += KSeparatorText().Length();
       
   331         }
       
   332 
       
   333     iValueLength += aBuffer.Length();
       
   334     }
       
   335 
       
   336 void CVPbkVCardCompactBCardImporter::ValueAndLabelToBufL( 
       
   337     const TDesC& aBuffer, TInt aResId )
       
   338     {
       
   339     const MVPbkFieldType* fieldType = FindFieldTypeL( aResId );
       
   340     __ASSERT_DEBUG( fieldType, 
       
   341         VPbkVCardEngError::Panic( VPbkVCardEngError::ENullFieldType ) );
       
   342 
       
   343 	// Read tel num label
       
   344 	TInt position( KStartPosition );
       
   345 
       
   346     delete iLabel;
       
   347     iLabel = NULL;
       
   348     if( aBuffer[KStartPosition] == KOpenParenthesis )
       
   349         {
       
   350         position = aBuffer.Find( KCloseParenthesis );
       
   351         if( position == KErrNotFound )
       
   352             {
       
   353             return;
       
   354             }
       
   355         iLabel = HBufC::NewL( position - KStartPosition );
       
   356     	TPtr writebuf = iLabel->Des();
       
   357 	    writebuf = KNullDesC;
       
   358         for( TInt i = KLabelStartPosition; i<position; i++ )
       
   359             {
       
   360             writebuf.Append( aBuffer[i] );
       
   361             }
       
   362 		// Jump few characters
       
   363         position += KLabelValueDelimiterLength;
       
   364         }
       
   365 
       
   366 	// Read value
       
   367     delete iValue;
       
   368     iValue = NULL;
       
   369     iValue = HBufC::NewL( aBuffer.Length() - position );
       
   370    	TPtr writebuf = iValue->Des();
       
   371     writebuf = KNullDesC;
       
   372     for( TInt i = position; i < aBuffer.Length(); i++ )
       
   373         {
       
   374         writebuf.Append( aBuffer[i] );
       
   375         }
       
   376 
       
   377     AddFieldWithValueL( *fieldType, *iValue, iLabel );
       
   378     }
       
   379 
       
   380 void CVPbkVCardCompactBCardImporter::AddAddressL()
       
   381     {
       
   382     if ( iAddressArray->Count() > 0 )
       
   383         {
       
   384         // Then concatenate them with commas into one string
       
   385         // and use that as field value.
       
   386         HBufC* fielddata = HBufC::NewLC( iValueLength );
       
   387         TPtr writebuf = fielddata->Des();
       
   388         writebuf = KNullDesC;
       
   389         TInt count = iAddressArray->Count();
       
   390         for( TInt i = 0; i < count; ++i )
       
   391             {
       
   392             if( i )
       
   393                 {
       
   394                 writebuf.Append( KSeparatorText );
       
   395                 }
       
   396             writebuf.Append( iAddressArray->MdcaPoint( i ) );
       
   397             }
       
   398 
       
   399         const MVPbkFieldType* fieldType = FindFieldTypeL( R_VPBK_FIELD_TYPE_ADDRLABELGEN );
       
   400         __ASSERT_DEBUG( fieldType, 
       
   401             VPbkVCardEngError::Panic( VPbkVCardEngError::ENullFieldType ) );
       
   402 
       
   403         AddFieldWithValueL( *fieldType, *fielddata, NULL );
       
   404         CleanupStack::PopAndDestroy( fielddata );
       
   405         }
       
   406     else
       
   407         {
       
   408         IssueRequest();
       
   409         }
       
   410         
       
   411     // Address is the last field so continue with titles after address
       
   412     // has been added, or not added
       
   413     iState = EStartTitleCopy;
       
   414     }
       
   415     
       
   416 TInt CVPbkVCardCompactBCardImporter::ResolveFieldTypeResIdL( const TDesC& aBuffer )
       
   417     {
       
   418     TInt resId( KErrNotFound );
       
   419     switch ( iLineCount )
       
   420         {
       
   421         case ECBCSignatureLine:
       
   422             {
       
   423             if ( aBuffer.Match( KBusinessCardText() ) == KErrNotFound )
       
   424                 {
       
   425                 User::Leave( KErrNotSupported );
       
   426                 }
       
   427             return resId;
       
   428             }
       
   429 
       
   430         case ECBCNameLine: // Name
       
   431             {
       
   432             resId = R_VPBK_FIELD_TYPE_LASTNAME;
       
   433             break;
       
   434             }
       
   435 
       
   436         case ECBCCompanyLine: // Company name
       
   437             {
       
   438             resId = R_VPBK_FIELD_TYPE_COMPANYNAME;
       
   439             break;
       
   440             }
       
   441 
       
   442         case ECBCTitleLine: // Title
       
   443             {
       
   444             resId = R_VPBK_FIELD_TYPE_JOBTITLE;
       
   445             break;
       
   446             }
       
   447         }
       
   448 
       
   449     if ( resId == KErrNotFound ) // Tel numbers
       
   450         {
       
   451         if ( aBuffer.Find( KTelText ) >= 0 )
       
   452             {
       
   453             resId = R_VPBK_FIELD_TYPE_LANDPHONEGEN;
       
   454             }
       
   455 
       
   456         else if ( aBuffer.Find( KFaxText ) >= 0 )
       
   457             {
       
   458             resId = R_VPBK_FIELD_TYPE_FAXNUMBERGEN;
       
   459             }
       
   460         }
       
   461     if ( !iEMailFetchedFlag && resId == KErrNotFound )
       
   462         {
       
   463         resId = R_VPBK_FIELD_TYPE_EMAILGEN; // Email address
       
   464         iEMailFetchedFlag = ETrue;
       
   465         }
       
   466 
       
   467     if ( resId == KErrNotFound )// Postal address
       
   468         {
       
   469         resId = R_VPBK_FIELD_TYPE_ADDRLABELGEN;
       
   470         }
       
   471 
       
   472     return resId;    
       
   473     }
       
   474 
       
   475 void CVPbkVCardCompactBCardImporter::AddFieldWithValueL( 
       
   476     const MVPbkFieldType& aFieldType, const TDesC& aValue, HBufC* aLabel )
       
   477     {
       
   478     __ASSERT_DEBUG( !iAddToFieldOperation, 
       
   479         VPbkVCardEngError::Panic( 
       
   480         VPbkVCardEngError::EAddToFieldOperationAlreadyExists ) );
       
   481     
       
   482     iAddToFieldOperation = iCopyPolicy->AddFieldToContactL(
       
   483         *iCurContact, aFieldType, aValue, aLabel, NULL, *this);
       
   484     }
       
   485 
       
   486 void CVPbkVCardCompactBCardImporter::StartTitleCopyL()
       
   487     {
       
   488     MoveCurrentContactToImportsL();
       
   489     
       
   490     // If vcard was split to multiple contacts then copy
       
   491     // title fields from the first imported contact to the other contacts.
       
   492     const TInt oneContactImported = 1;
       
   493     if ( iImportedContacts.Count() <= oneContactImported )
       
   494         {
       
   495         iObserver->ContactsImported();
       
   496         }
       
   497     else
       
   498         {
       
   499         iTargetContactIndex = oneContactImported;
       
   500         CopyTitleL();    
       
   501         }
       
   502     }
       
   503         
       
   504 const MVPbkFieldType* CVPbkVCardCompactBCardImporter::FindFieldTypeL( 
       
   505         TInt aFieldIndex )
       
   506     {
       
   507     return iData.SupportedFieldTypes().Find( aFieldIndex );
       
   508     }
       
   509 
       
   510 TInt CVPbkVCardCompactBCardImporter::GetByteFromStream(
       
   511     TInt8& aByte, RReadStream& aSourceStream)
       
   512     {
       
   513     TRAPD(err, aByte = aSourceStream.ReadInt8L());
       
   514     return err;
       
   515     }
       
   516 
       
   517 TInt CVPbkVCardCompactBCardImporter::GetLineFromStreamL(
       
   518     TDes& aBuf, RReadStream& aSourceStream)
       
   519     {
       
   520     aBuf.SetLength(0);
       
   521     TInt8 byte=0;
       
   522     TInt retVal( KErrNone );
       
   523     while( ( retVal = GetByteFromStream(byte, aSourceStream) ) == KErrNone)
       
   524         {
       
   525         if(byte == EKeyLineFeed)
       
   526             {
       
   527             break;
       
   528             }
       
   529         if(byte != EKeyEnter)
       
   530             {
       
   531             if (aBuf.Length() < aBuf.MaxLength())
       
   532                 {
       
   533                 aBuf.Append(byte);
       
   534                 }
       
   535             else
       
   536                 {
       
   537                 User::Leave(KErrCorrupt);
       
   538                 }
       
   539             }
       
   540         }
       
   541 
       
   542     return retVal;
       
   543     }
       
   544 
       
   545 void CVPbkVCardCompactBCardImporter::HandleContactSwitchL()
       
   546     {
       
   547     // Current contact is full -> Create a new contact and
       
   548     // add the same line to that one.
       
   549     MoveCurrentContactToImportsL();
       
   550     iCurContact = iTargetStore.CreateNewContactLC();
       
   551     CleanupStack::Pop();
       
   552     if ( iLine && iLine->Length() > 0 )
       
   553         {
       
   554         // Parse same line again
       
   555         ParseLineL();
       
   556         }
       
   557     else
       
   558         {
       
   559         // End of file -> continue with address
       
   560         AddAddressL();
       
   561         }
       
   562     }
       
   563 
       
   564 void CVPbkVCardCompactBCardImporter::CopyTitleL()
       
   565     {
       
   566     delete iAddToFieldOperation;
       
   567     iAddToFieldOperation = NULL;
       
   568     iAddToFieldOperation = iCopyPolicy->CopyTitleFieldsL(
       
   569         *iImportedContacts[0],
       
   570         *iImportedContacts[iTargetContactIndex],
       
   571         *this );
       
   572     }
       
   573     
       
   574 void CVPbkVCardCompactBCardImporter::MoveCurrentContactToImportsL()
       
   575     {
       
   576     iImportedContacts.AppendL( iCurContact );
       
   577     iCurContact = NULL;
       
   578     }
       
   579     
       
   580 void CVPbkVCardCompactBCardImporter::HandleError( TInt aError )
       
   581     {
       
   582     if ( aError != KErrNone )
       
   583         {
       
   584         iObserver->ContactImportingFailed( aError );
       
   585         }
       
   586     }
       
   587     TBool CVPbkVCardCompactBCardImporter::IsOwncard()
       
   588     {
       
   589     	return EFalse;
       
   590     }
       
   591 
       
   592 // End of file